Автомат диф: Автомат дифференциальный Abb 2 полюса 16 А

Содержание

Что такое дифавтомат, для чего применяют, схемы, как подключить

Из статьи вы узнаете, что такое дифавтомат и для чего применяют, какие бывают, устройство и принцип действия устройства, принципиальная схема, расшифровка обозначений на корпусе, как подключить.

Безопасность – это важно

При проектировании и прокладке низковольтной электрической сети одной из главных задач для специалистов является защита от коротких замыканий и обеспечение максимального уровня безопасности.

Для ее решения применяются специальные устройства, одним из которых является дифференциальный автомат (дифавтомат).

Ниже рассмотрим следующие вопросы:

  • Что это за изделие?
  • Для чего применяют, и какие виды дифавтоматов бывают?
  • Из каких элементов он состоит, и как работает?
  • Как расшифровать обозначения и подключить дифавтомат?
  • В чем причины срабатывания?

Определение дифавтомата

Дифференциальный автомат — защитное устройство, которое устанавливается в низковольтной сети для обеспечения ее комплексной защиты.

В одном аппарате объединяется две функции — автоматического выключателя (отсечки) и УЗО.

Благодаря расширенным возможностям, изделие пользуется широким спросом в быту и на производстве.

Сфера применения

Дифавтомат применяется для решения следующих задач:

  • Защиты определенного участка сети от протекания повышенных токов, возникающих в случае КЗ или перегрузки.
  • Предотвращения пожара или попадания людей под действие напряжения из-за появления утечки, возникающей по причине некачественной изоляции проводов или выхода из строя бытовых приборов.

В первом случае дифференциальный автомат работает как автоматический выключатель, а во втором — как УЗО (устройство защитного отключения).

Какие виды бывают?

Дифференциальный автомат — универсальный аппарат, который может с легкостью применяться в одно-, так и трехфазных сетях.

В первом случае используются изделия с двумя полюсами, а во втором — с четырьмя.

Читайте также:

Конструктивные особенности, принцип действия и схема дифавтомата

Рассматривая обозначение устройства по ГОСТ, несложно выделить конструктивные элементы защитного аппарата.

К основным стоит отнести:

  • Дифференциальный трансформатор;
  • Группа расцепителей (тепловой и электромагнитный).

Каждый из элементов выполняет определенные задачи. Рассмотрим их подробнее.

Дифтрансформатор — устройство с несколькими обмотками, число которых напрямую зависит от количества полюсов.

В его задачу входит сравнение нагрузочных токов в каждом из проводников. В случае расхождения показателей появляется ток утечки, который направляется в пусковой орган.

Если параметр выше определенного уровня устройство отключает электрическую цепь посредством разделения силовых контактов дифавтомата.

Для проверки работоспособности предусмотрена специальная кнопка, чаще всего подписываемая, как «TEST». Она подключена через сопротивление, которое подключается двумя способами:

  • Параллельно одной из существующих обмоток;
  • Отдельной обмоткой на трансформатор.

После срабатывания кнопки пользователь искусственно формирует ток небаланса. Если дифавтомат исправен, он должен отключить цепь. В противном случае делаются выводы о неисправности аппарата.

Следующий элемент дифавтомата — электрический расцепитель. Конструктивно он имеет вид электрического магнита с сердечником.

Назначением элемента является воздействие на отключающий механизм. Срабатывание электромагнита происходит при увеличении нагрузочного тока выше установленного уровня.

Чаще всего это бывает при появлении КЗ в низковольтной сети. Особенность расцепителя заключается в срабатывании без выдержки времени. На отключение питания уходят доли секунды.

В отличие от электромагнитного, тепловой расцепитель защищает не от КЗ в цепи, а от перегрузок. В основе узла лежит биметаллическая пластинка, через которую протекает нагрузочный ток.

Если он выше допустимого значения (номинального тока дифавтомата), происходит постепенная деформация этого элемента. В определенный момент пластина из биметалла постепенно изгибается.

В определенный момент она воздействует на отключающий орган защитного устройства. Задержка времени теплового расцепителя зависит от тока и температуры в месте установки. Как правило, эта зависимость имеет прямо пропорциональный характер.

На кожухе дифавтомата прописывается нижний предел (указывается в мА). Кроме тока утечки, указывается и номинальный ток расцепителя. Более подробно о маркировке аппарата поговорим ниже.

Как расшифровать обозначения на корпусе?

Выше уже отмечалось, что на корпусе дифференциального автомата можно найти всю необходимую информацию.

Изучив основные параметры, легче принимать решение — подходит ли прибор под решения конкретных задач.

К наиболее важным обозначениям стоит отнести:

  • АВДТ — аббревиатура, сокращенный вариант полного названия («автоматический выключатель дифференциального тока»).
  • С25 — номинальный параметр тока. Здесь C — характеристика зависимости времени и тока, а 25 — предельный ток дифавтомата, превышение которого недопустимо.
  • 230 В — номинальное напряжение, при котором допускается применение аппарата (для бытовой сети).
  • In 30mA — параметр тока утечки. При достижении 30 мА работает УЗО.
  • Специальный знак, который подтверждает наличие функции УЗО и тип АВДТ. По наличию обозначения делается вывод о способности дифференциального автомата реагировать на постоянный или переменный пульсирующий ток.

Также на корпусе защитного изделия нанесена принципиальная схема. Обычному обывателю она может ничего не рассказать, поэтому на нее не обязательно обращать внимание.

Также на внешней части устройства предусмотрена кнопка «ТЕСТ», необходимая для периодического контроля исправности устройства в части УЗО. Об особенностях проверки с помощью этого элемента мы уже говорили выше.

Как подключить устройство?

Перед тем как подключить дифавтомат, стоит разобраться с типом электрической проводки.

Здесь возможны следующие варианты:

  • Тип сети — однофазная или трехфазная. В первом случае номинальное напряжение составит 220 Вольт, а во втором — 380.
  • Наличие заземления — существуют сети с заземлением или без него.
  • Место для монтажа. Чаще всего АВДТ устанавливается в квартире, но возможен монтаж на каждую отдельную группу проводников.

С учетом рассмотренных условий необходимо определиться, как подключать защитный аппарат. Стоит помнить, что дифавтомат может иметь ряд конструктивных отличий.

Рассмотрим основные способы подключения в щитке:

  1. Простейший вариант. Популярный способ — установка одного дифференциального автомата, который защищает всю цепочку. При выборе такого варианта желательно покупать дифавтомат с большим номинальным током, чтобы учесть нагрузку всех потребителей в квартире. Главный минус схемы заключается в сложности поиска места повреждения при срабатывании защиты. По сути, проблема может скрываться на любом из участков проводки.В приведенной схеме видно, что «земля» идет отдельно и объединяется с шиной заземления. К ней же подключаются все проводники (PE) от электрических приборов. Ключевое значение имеет подключение «нуля», который выведен из дифавтомата. Его объединение с другими «нулями» электрической сети запрещено. Это объясняется разницей величин токов, проходящих по каждому из нулевых проводников, из-за чего дифференциальный автомат может срабатывать.
  2. Надежная защита. Это улучшенный вариант подключения защитного аппарата, благодаря применению которого удается повысить надежность сети и упростить задачу поиска повреждения. Особенность заключается в монтаже отдельного дифавтомата на каждую группу проводов. Следовательно, защитный аппарат будет работать только в той ситуации, когда проблема возникнет на контролируемом участке цепи. Другие участки продолжат работать в обычном режиме. В отличие от прошлой схемы, найти неисправность в случае КЗ, появления утечки или перегрузки в сети много проще. Но имеется и недостаток — большие финансовые затраты, связанные с необходимостью покупки нескольких дифавтоматов.
  3. Схема без заземления. Рассмотренные выше варианты подключения дифавтомата подразумевают наличие защитной «земли». Но в некоторых домах или на дачном участке контур заземления отсутствует вовсе. В таких сетях применяется однофазная сеть, где присутствует только фаза и «ноль». В этой ситуации защитный аппарат (АВДП) подключается по другому принципу. Если у вас в низковольтной сети также нет «земли», перед установкой дифавтомата желательно полностью поменять проводку в доме. В противном случае в сети может быть ток утечки, из-за которого будет срабатывать УЗО.
  4. Схема для 3-х фазной сети. В случаях, когда требуется монтаж дифференциального аппарата в цепи тремя фазами (например, в современной квартире, в доме или в гараже), требуется соответствующий АВДП. Принципа построения здесь такой же, как и в прошлом случае. Разница в том, что на входе и на выходе нужно подключать четыре жилы.

По каким причинам может сработать дифавтомат?

В процессе эксплуатации защитного устройства важно понимать, в каких случаях оно может сработать.

С учетом этих нюансов стоит принимать решение о причине проблемы (короткое замыкание, ток утечки и прочие).

Рассмотрим каждый из вариантов более подробно:

Срабатывание без нагрузки.

В старых домах с плохой проводкой имеют место серьезные проблемы с изоляцией.

Последняя изношена и высок риск появления токов утечки, величина которых может меняться с учетом многих параметров — наличия рядом животных уровня влажности и так далее.

В такой ситуации АВДП может срабатывать ложно.

Причиной проблемы может быть:

  • Поврежденная изоляция;
  • Наличие скруток;
  • Просчеты в расположении распредкоробок;
  • Электрофурнитура.

Для выявления причины требуется ревизия проводки. Начинать необходимо с диагностики места повреждения.

Например, если дифавтомат выбивает при включении лампочки, проблему необходимо искать в осветительной цепи.

Если АВДП срабатывает после подключения какого-то либо устройства в розетку, стоит убедиться, что это устройство исправно.

При замыкании «нуля» и «земли».

Если по какой-либо причине провода N и PE касаются друг друга, высок риск срабатывания дифференциального автомата. Распространенные места замыканий — в распредкоробке или в коробе под розетку.

Читайте по теме — эффективные способы защиты электроприборов с помощью специальных устройств.

Логика срабатывания построена на принципе действия устройства. Если «ноль» и «земля» объединены, ток разделяется между двумя проводниками. Соответственно, в дифтрансформаторе нет равенства токов, и он воспринимает этот факт, как утечку.

С проблемой часто сталкиваются начинающие мастера, которые не имеют должного опыта в вопросе обслуживания дифавтомата.

  1. В момент включения нагрузки. Если АВДП работает при подключении нагрузки, проблему необходимо искать в изоляции. Использовать проводку при такой неисправности небезопасно, поэтому рекомендуется вызвать специалиста и разобраться с проблемой. Если же ее игнорировать, высок риск попадания под напряжение кого-либо из членов семьи или возникновения пожара.
  2. При скачках напряжения. Логика дифавтомата построена таким образом, что отключение может происходить в случае повышения напряжения. Правда, такой опцией обладают не все устройства, а только имеющие электронную схему. Кроме того, защита может работать при КЗ внутри потребителя, ведь дифавтомат умеет отключаться при таком виде аварии.

Читайте по теме — как действует электрический ток на организм человека.

Итоги

Дифференциальный автомат — полезное устройство, способное защитить от КЗ и токов утечки в низковольтной сети.

Для его правильного применения важно знать правила подключения и эксплуатации, а также особенности диагностики неисправности в случае срабатывания аппарата. Полезно почитать — как выполнять монтаж электропроводки в деревянном доме.

Диф.автомат АД14 4Р 32А 300мА TDM SQ0204-0038

Описание

Диф.автомат АД14 4Р 32А 300мА TDM SQ0204-0038

Маркировка

  • Номинальный ток – значение тока в амперах (А), который дифференциальный автомат способен пропускать бесконечно долго без отключения цепи.
  • Номинальное напряжение – напряжение переменного тока (знак ~), при котором дифференциальный автомат работает в нормальных условиях.
  • Кривая отключения – отражает порог срабатывания при защите от короткого замыкания.
    • Кривая B– автомат срабатывает при появлении вцепи тока в 3-5 раз больше номинального (т.е. автомат на 16А отключит цепь при токе 48-80А). Используется вбытовых сетях сзамоноличенной алюминиевой проводкой.
    • Кривая С– ток вцепи в 5-10 раз больше номинального (т.е. автомат на16А отключит цепь при токе 80-160А). Используют в современном жилом строительстве ивофисных сетях.
  • Номинальная отключающая способность – максимальный ток короткого замыкания, который данный дифференциальный автомат способен отключить и остаться в работоспособном состоянии.
  • Дифференциальный ток – ток в миллиамперах (мА), протекающий по телу человека, прикоснувшегося к токоведущей части и стоящего на токопроводящем полу. Для защиты от поражения используют аппараты с уставками 10, 30 и 100мА. Аппараты с уставкой 300 мА используют для защиты от пожаров или как двухступенчатую селективную защиту.
  • Класс АС – дифференциальные автоматы класса АС защищают от синусоидальных дифференциальных токов.
  • Устройство способно работать при температуре −25°С.

Назначение

  • Проведение тока в нормальном режиме.
  • Отключение тока при коротких замыканиях или перегрузке.
  • Отключение тока при прикосновении человека к токоведущим частям электроустановок или протекании дифференциального (утечки) тока на землю.

Применение

  • Строительные объекты.
  • Жилищно-коммунальное хозяйство и офисы.
  • Промышленные здания.
  • Электрифицированные рекламные конструкции.

Материалы

  • Корпус и детали выполнены из пластика, не поддерживающего горение.
  • Маркировка выполнена в соответствии с требованиями ГОСТ и не подвержена стиранию в пределах срока эксплуатации.

Конструкция

  • Защита от сверхтоков в каждом из полюсов (2Р или 4Р)
  • В блоке дифференциальной защиты предусмотрена кнопка возврат, которая, в случае срабатывания аппарата по дифференциальному току, выходит из корпуса и препятствует повторному включению аппарата без возврата ее в корпус.
  • Насечки на контактных зажимах предотвращают перегрев и оплавление проводов за счет более плотного и большего по площади контакта.
  • На лицевой панели каждого полюса дифференциального автомата АД реализован механический индикатор положения контактов (включено/отключено).

Преимущества

  • Цена гораздо ниже, чем при покупке УЗО и автоматического выключателя, за счёт совмещения функций в одном изделии.
  • Подробная инструкция по монтажу и эксплуатации позволяет легко монтировать автомат начинающему монтажнику.
  • Клеммные зажимы автомата промаркированы, что позволяет избежать ошибок при монтаже.
  • Защелка на DIN-рейку с фиксацией упрощает монтаж и демонтаж аппарата.
  • Наличие двойного одновременного подключения шины и проводника значительно расширяет диапазон возможных схемных решений.
  • Аппараты АД12 и АД14 сочетает в себе функции автоматического выключателя и выключателя дифференциального тока.

Простой рецепт подбора дифавтомата для вашего дома



Дифференциальный автомат – подключается для обеспечения защиты от поражения электрическим током, одновременно с защитой электросети от перегрузок и короткого замыкания.

Где устанавливается

Диф-автомат устанавливается только на DIN-рейку в распределительном щитке квартиры или дома. К автомату подключаются блоки розеток или отдельные мощные электроприборы – стиральная машина, электропечь, электродуховка или водонагреватель.

Стиральная машина, морозильная камера, насос – эти приборы имеют в своей конструкции электродвигатель, поэтому их пусковая потребляемая мощность может превышать заявленную фирмой – производителем в несколько раз. Приводим таблицу с указанием коэффициентов возрастания токов в начале работы прибора:

Время действия пусковых токов в бытовых приборах

Таким образом, стиральная машина при включении может потреблять 12,5 кВт в течении первых 4х секунд, а если дифавтомат для нее не рассчитан на такую мощность – каждый раз при включении он будет выбивать. Но это не означает, что нужно выбирать дифференциальный автомат, мощностью 12,5 кВт!

Условные обозначения



Дифавтоматы поставляются обычно с паспортами, в которых указываются все данные, но многие из них дублируются на корпусе устройства. Здесь вы можете прочитать информацию о номинальном напряжении, частоте и мощности, дифференциальном токе отключения, температурный диапазон использования автомата. В отличие от инструкции, обозначения на корпусе со временем не потеряются и при открытии распределительного щитка вы всегда будете знать, на какой автомат можно добавить нагрузку, а на какой нет.

Условные обозначения на дифавтомате

Какой дифавтомат выбрать

Дифференциальный автомат соединяет в себе одновременно три функции, защита проводки от короткого замыкания, защита проводки от перенапряжения и защиты человека от удара электрическим током или утечки электричества. При планировании проводки в квартире или доме можно рассчитать количество потребителей тока, которые планируется подключать к сети, подсчитать время их работы и что будет включаться одновременно, а что нет. И ошибиться 🙂

Дифавтомат ABB на 10А тип С
Дифавтомат ABB на 16А тип С
Дифавтомат ABB на 25А тип С

Дифференциальный автомат устанавливается для тех мест, где возможно поражение электрическим током. В квартире под дифавтоматы подключают розетки и выключатели в ванной комнате и кухне. Именно в этих местах наиболее вероятно поражение током, т.к. имеется избыточная влажность и опасность протекания от соседей сверху. Если в вашем случае есть места, где также есть опасность контакта электрики с водой, например сауна, бассейн или холл с фонтаном, то такие комнаты следует также запитать через диф-автомат.

Каждая такая комната запитывается двумя контурами, каждый из которых подключается через отдельный автоматический дифференциальный автомат. Это контуры освещения и розеток:

  • Розетки – автомат на 16А, тип С;
  • Освещение – автомат на 10А, тип С;

Под отдельный диф-автомат подключаются:

  • Проточный водонагреватель;
  • Накопительный водонагреватель;
  • Электроварочная панель;
  • Электродуховой шкаф;
  • Кондиционер.

Проточный водонагреватель, электроварочная панель и электродуховка подключаются под диф-автоматы на 25А, тип С. Кондиционер и накопительный водонагреватель под автоматы на 16А тип С.

Важно. Если варочная панель и духовка – это два разных прибора, то они должны подключаться под разные диф-автоматы.

Не стоит подбирать отдельный дифавтомат для стиральной машины, микроволновки или пылесоса. Все эти приборы рассчитаны на включение в обычную электросеть, а значит отдельно беспокоиться об их безопасности не стоит.

Видео о технических характеристиках дифавтоматов

Ролик подробно описывает технические характеристики дифференционных автоматических выключателей. Видео будет полезно тем, кто ищет более углубленную информацию по теме и решает специфические вопросы по электрообеспечению офиса, производственного участка или иного коммерческого помещения.



Сфера применения 3-х полюсных автоматических выключателей Розетка с дистанционным управлением – незаменимая помощь дома Несколько простых правил выбора розеток и выключателей Схема подключения двухклавишного проходного выключателя – особенности, а также последовательность осуществления работ

отличия, что лучше выбрать, и как установить

Для многих людей слова дифавтомат и УЗО ни о чем не говорят. Но приходит время замены электропроводки в доме или начинается строительство дачи и специалисты постоянно упоминают о них, о необходимости защиты от поражения электрическим током, и предлагают разные варианты. Вот тут владельцу дома нужно сделать выбор, причем правильный.

Ему хочется получить надежную защиту от электрического тока за приемлемые деньги, без переплаты и излишнего оборудования. Для этого надо немного разобраться с приборами, их назначением, отличиями, достоинствами и недостатками. Понять, в чем разница между дифавтоматами УЗО, будет полезно любому начинающему электрику.

Назначение устройств защитного отключения

УЗО обеспечивает защиту изоляции электропроводки и предотвращает возникновение пожара. А человека оно предохраняет от воздействия электрического тока при прикосновении к частям устройств, на которых имеется фазное напряжение.

УЗО срабатывает на дисбаланс токов в фазном и нулевом проводах защищаемой электросети. Это бывает, когда происходит пробой изоляции и появляется дополнительная утечка.

Протекание тока через не предназначенные для этого материалы может привести к возгоранию. В зданиях с ветхой электропроводкой пожары от повреждения изоляции случаются довольно часто.

Другой опасный случай – это прикосновение к токоведущим частям приборов, которые в нормальном состоянии не должны быть под напряжением. Ток начинает протекать на землю через человека, минуя нулевой провод.

Автоматический выключатель в таком случае не сработает, так как для отключения ему необходимы токи как минимум в десятки ампер. Для жизни человека опасны токи, начиная с 30 мА и выше. Способность устройства защитного отключения реагировать на 10-30 мА является надежной защитой от воздействия электричества.

Следует знать, что УЗО, не обеспечивает защиту от сверхтоков, это основное отличие УЗО от дифавтомата. В ситуации, когда стоит только УЗО и происходит короткое замыкание, устройство не среагирует, при этом может еще и само сгореть. Отдельно, без автоматического выключателя, оно не используется.

Если стоит вопрос, что выбирать – УЗО или дифавтомат, – надо понимать, что вместе с УЗО в цепь обязательно придется устанавливать автоматический выключатель.

Назначение дифференциального автомата

Дифавтомат используется для предохранения электрической сети от перегрузки, короткого замыкания и утечек. В дополнение к возможностям УЗО он выполняет функции автоматического выключателя.

Бывает так, что человек присоединяет к одной розетке удлинитель с пятью, шестью дополнительными розетками, а через них подключает несколько мощных приборов. В таких обстоятельствах перегрев проводников неизбежен.

Или, допустим, при включении электродвигателя заклинило вал, обмотка начинает греться, через какое-то время происходит пробой, с последующим коротким замыканием проводов.

Чтобы это избежать, устанавливается дифавтомат. Если превышение тока значительное, то дифавтомат в течение нескольких секунд, не дожидаясь пока расплавится изоляция, отключит линию, тем самым предотвратив пожар.

Быстрота отключения дифавтомата зависит от того, во сколько раз протекающий ток превышает номинальный для данной линии. При многократном превышении вплоть до короткого замыкания мгновенно срабатывает электромагнитный расцепитель.

Если протекающий по линии ток превышает номинальный более чем на 25%, то примерно через час устройство отключит линию, сработает тепловой расцепитель.

Если превышение будет больше, то отключение произойдет гораздо раньше. Время срабатывания можно определить по время-токовым характеристикам, дающимся на каждый прибор.

Внешний вид

Всеобщая унификация привела к тому, что по форме и размерам корпуса очень сложно уловить разницу между дифавтоматом и УЗО.

Для однофазной сети корпуса этих приборов имеют размер равный двум корпусам однополюсного автоматического выключателя. Каждый из них имеет тестовую кнопку, они двухполюсные. Установка УЗО на DIN-рейку ничем не отличается от монтажа дифавтомата.

Внешне дифференциальные автоматы отличаются от УЗО:

  • по надписям на лицевой панели;
  • маркировке;
  • функциональной схеме.

Обычно в верхней части прибора ниже названия фирмы производителя идет название прибора. К примеру, ВД и несколько цифр. ВД означает выключатель дифференциальный, то есть это УЗО.

Если присутствует аббревиатура АВДТ (сокращение от выражения: автоматический выключатель дифференциального тока), то это дифавтомат. На случай повреждения надписи на лицевой панели производитель предусмотрительно выдавил название устройства на боковой стороне прибора.

Правда, для определения типа устройства придется снимать его с DIN-рейки. Но этот способ касается в основном отечественных производителей.

Зарубежные поставщики на этот счет не заморачиваются. Поэтому приходится ориентироваться по маркировке и схеме.

Обозначение номинального тока

Разница наблюдается в обозначении номинального тока. В УЗО его записывают в виде цифры, например 16 А, которая означает, что прибор будет нормально работать при токах не превышающих 16 ампер. Главная характеристика для него – это значение тока отключения.

Для дифавтомата, кроме тока отключения по утечке, важной является время-токовая характеристика. От нее зависит, при каких токах перегрузки и насколько быстро отключится устройство.

Поэтому перед значением номинального тока стоит буква, обозначающая предел превышения номинала, при котором произойдет мгновенное срабатывание прибора. Если на передней панели стоит надпись, например, «С16», значит, перед вами дифавтомат.

Электромагнитный расцепитель данного дифавтомата мгновенно отключит линию при превышении номинального тока в 5-10 раз.

Функциональная схема

На схеме УЗО на передней панели, можно видеть изображение магнитопровода дифференциального трансформатора, тестового резистора, трех ключей и управляющей обмотки.

Два ключа отключают фазовый и нулевой провода в случае токов утечки, превышающих уставку. Третий ключ нужен для протекания ограниченного резистором тока, минуя трансформатор. Таким образом, создается дисбаланс между токами, протекающими через фазу и ноль.

На схеме дифавтомата, в дополнение к схеме УЗО, изображается ключ, подсоединенный к фазовому проводу на выходе трансформатора. Или может быть другое изображение.

Вместо дополнительного ключа показывают квадрат с фигурой внутри положительной синусоиды и прямоугольного импульса. Синусоида означает электромагнитный расцепитель, а прямоугольный импульс – тепловой расцепитель.

Другие различия

Уже из назначения приборов становится понятным, в чем между ними разница. Дифавтомат более универсален, он включает в себя функции УЗО. Но, помимо функций и внешнего вида, есть и другие различия.

Стоимость

Немаловажная разница состоит в цене. Дифференциальный автоматический выключатель значительно выше в цене, чем УЗО. Даже, если функционально УЗО уравнять с дифавтоматом, подсоединив дополнительный автоматический выключатель, все равно стоимость дифавтомата будет выше.

Размеры и ремонтопригодность

Занимаемый объем такой конструкции за счет добавочного автомата будет в полтора раза больше, чем место для дифавтомата. Это имеет значение при небольших электрических щитках.

Зато ремонтопригодность приборов при равном функционале лучше в системе УЗО+ автомат, чем просто дифавтомат. Кроме этого сразу становится ясна причина отключения – токи утечки или перегрузка в сети.

Подключение

Но при монтаже дифференциального выключателя не надо думать, как ставить УЗО, подключить до или после автомата. Вообще-то, большинство специалистов рекомендуют устанавливать сначала автоматический выключатель, затем дифференциальный.

Что касается УЗО, то здесь возможно два варианта. Если УЗО ставят на несколько групп потребителей, то оно идет первым, а за ним уже автоматические выключатели на каждую группу.

Если одну линию защищает одно УЗО и один автомат, то автомат идет первым.

Еще один момент, который нужно учитывать при выборе между дифференциальным автоматом и УЗО+ автомат. Это надежность устройств. Как известно, чем проще устройство, тем оно надежнее. В этом отношении дифавтомат проигрывает.

Итак, основная разница между дифавтоматом и УЗО состоит в их функциях, маркировке, стоимости, способе подключения и занимаемом месте в щитке.

Что использовать лучше, решает каждый собственник самостоятельно. Главное, правильно подключить все приборы и обеспечить надежную защиту от пожара или удара током.

виды, конструкция, применение в электрике . Как выбрать дифавтомат и какие бывают

В электротехнике есть масса терминов, которые неизвестны непрофессионалам. Но иногда необходимо немного углубиться в изучения определенных устройств, чтобы правильно сделать их выбор при покупке. Каждый дифференциальный автомат представляет собой компактное изделие, сочетающее в себе функции выключателя и защитного аппарата УЗО. Главная цель применения этого оборудования состоит в полном предохранении пользователей от удара током при соприкосновении с каким-то прибором или в результате короткого замыкания. Важной функцией аппаратуры является отключение электрического тока, если есть риск получить повреждение. Надежный дифференциальный автомат выключатель защитит от перегрузок в сети на производстве или в бытовом использовании. Это универсальный аппарат, без которого сложно обойтись, если вы используете сразу несколько мощных электроприборов.

Особенности конструкции: за счет чего функционирует дифференциальный автомат?

Это техника, которая состоит из защитной и рабочей частей. Функциональная, то есть рабочая часть агрегата — выключатель, который срабатываетавтоматически. Он обязательно включает механизм для независимого расцепления через активное механическое воздействие. В разных автоматах могут устанавливаться выключатели двух- или четырехполюсного типа.

В конструкции дифференциального прибора предусмотрено наличие двух расцепителей — теплового и электромагнитного. Примечательно, что первый срабатывает при перегрузке конкретной группы электрических приборов, а второй обеспечивает полную защиту при коротком замыкании оборудования.

Модульная или защитная часть дифференциального автомата позволяет своевременно выявить ток утечки и провести преобразование электрического тока в механическое воздействие, которое полностью безопасно. Модуль защиты и автоматический выключатель подключаются к питанию последовательно друг с другом для обеспечения функциональности и длительной работы. В защитной части автомата присутствует дополнительный элемент — трансформатор для обнаружения остаточного электрического тока. Также в конструкции предусмотрено наличие электронного усилителя с электромагнитной катушкой. Каждый автомат дифференциальный 16а имеет кнопку для предварительного тестирования на корпусе, которая поможет проверить устройство.

Виды дифференциальных автоматов

Для обозначения аппаратов разного типа используются буквы латинского алфавита. Рассмотрим основные вариации электротехнических изделий:

  • A – применяются для защиты полупроводниковых устройств;
  • B – подходят для осветительных сетей общего назначения;
  • C – обладают высокой перегрузочной способностью, используются в оборудовании с умеренными пусковыми электрическими токами;
  • D – защищают электротехнические устройства с тяжелым запуском;
  • Z – для разнообразной электронной техники;
  • K – дифференциальные автоматы для индуктивной нагрузки (для решения других задач не приспособлены).

Надежный дифференциальный автомат abb станет предпочтительным вариантом для многих потребителей. Это продукция известного шведско-швейцарского бренда, которая отличается высоким уровнем износостойкости и длительными сроками эксплуатации. Подобный дифференциальный автомат купить можно в нашем интернет-магазине, предварительно выбрав оборудование, подходящее для ваших конкретных целей. Электротехническая аппаратура от известной марки предоставляется с гарантией качества и соответствующими сертификационными документами.

Дифференциальный автомат: назначение, устройство, схема подключения

Дифференциальный автомат – уникальный аппарат, сочетающий в едином корпусе функции сразу двух защитных устройств – это одновременно УЗО и автоматический выключатель. Профессионалы рекомендуют использовать дифференциальные автоматические выключатели в обязательном порядке при устройстве или реконструкции проводки.

Каково назначение дифференциальных автоматов, по каким параметрам выбирается и какова его схема подключения – ответы на эти вопросы постараемся дать ниже.

Для чего нужны дифференциальные автоматы?

Прямым предназначением дифференциального автомата является защита человека от поражения электрическим током при прямом контакте. Устройство одновременно отслеживает как возникновение короткого замыкания, так и проявление признаков утечки электричества через повреждённые токопроводящие компоненты сети.

Дифференциальный автомат обесточит контролируемую линию при возникновении:

  • короткого замыкания;
  • перегрева электрической проводки из-за превышения уставки номинального тока дифавтомата;
  • утечки на землю больше, чем соответствующая уставка.

Так, простое устройство вполне способно обезопасить квартиру или частный дом, предотвращая возникновение чрезвычайных ситуаций, вызванных проблемами с электричеством.

Преимуществом использования дифференциального автомата является отсутствие необходимости подбора УЗО, ведь он уже содержится в составе компонентов дифференциального автомата. Одно устройство, совмещающее в себе функции двух (УЗО и автоматического выключателя), занимает меньше места в электрическом щитке на размер однополюсного автомат – его ширина 17,5 мм.

Среди недостатков можно выделить вероятность выхода из строя одного из двух компонентов дифавтомата – замена отдельной части невозможна, что вынудит приобрести новый дифференциальный автомат.

Техническое устройство

Конструктивно дифавтоматы выполняются из диэлектрического материала. Задняя часть имеет специальное крепление для установки на DIN-рейку. Внутри они состоят из двухполюсного или четырёх полюсного выключателя и включенного последовательно с ним модуля дифзащиты. Данный модуль представляет собой дифференциальный трансформатор тока, через который проходят ноль и фаза, образуя тем самым первичную обмотку и обмотку управления — вторичную обмотку.

Как работает дифференциальный автомат

В основе принципа работы дифавтомата лежит использование специального трансформатора, функционирование которого строится на изменениях дифференциального тока в проводниках электричества.

При появлении токов утечки баланс нарушается, так как часть тока не возвращается. Фазный и нулевой провода начинают наводить разные магнитные потоки и в сердечнике трансформатора тока возникает дифференциальный магнитный поток. В результате этого в обмотках управления возникает ток и срабатывает расцепитель.

При перегреве в модуле автоматического выключателя срабатывает биметаллическая пластина и размыкает автомат.

Основные параметры

Любой дифференциальный автомат располагает 8-ю клеммами для трёхфазной сети и 4-мя для однофазной. Само устройство является модульным и состоит из:

  • Корпуса, изготовленного из негорючего тугоплавкого материала;
  • Клемм с маркировкой, предназначенных для подключения проводников;
  • Рычага включения-выключения. Количество зависит от модели конкретного устройства;
  • Кнопки тестирования, позволяющей вручную проверить работоспособность дифференциального автомата;
  • Сигнального огонька, информирующего о выбранном типе срабатывания (утечка или перегрузка).

При выборе дифференциального автомата со всей интересующей информацией можно ознакомиться непосредственно на самом корпусе устройства.

Выбор дифавтомата нужно производить исходя из множества параметров:

  1. Номинальный ток – показывает, на какую нагрузку рассчитан дифавтомат. Эти значения стандартизированы и могут принимать следующие значения: 6, 10, 16, 20, 25, 32, 40, 50, 63А.
  2. Время-токовая характеристика – значения могут быть равны B, C и D. Для простой сети с маломощным оборудованием (используется редко) подойдёт тип В, в городской квартире – С, на мощных производственных предприятиях – D. Например, при запуске двигателя ток резко возрастает на доли секунд, ведь необходимы определённые усилия для его раскрутки. Данный пусковой ток может в несколько раз превышать номинальный ток. После запуска потребляемый ток становится в несколько раз меньше. Для этого и нужен этот параметр. Характеристика B означает кратковременное превышение такого пускового тока в 3-5 раз, C – 5-10 раз, D – 10-20 раз.
  3. Дифференциальный ток утечки – 10 или 30 мА. Первый тип подойдёт для линии с 1-2 потребителями, второй – с несколькими.
  4. Класс дифференциальной защиты – определяет, на какие утечки будет реагировать дифавтомат. При выборе устройства для квартиры подойдут классы АС или А.
  5. Отключающая способность – значение зависит от номинала автомата и должно быть выше 3 кА для автоматов до 25 А, 6 кА для автоматических выключателей на ток до 63 А и 10 кА для автоматических выключателей на ток до 125 А.
  6. Класс токоограничения – показывает, как быстро будет отключена линия при возникновении критических токов. Существует 3 класса дифавтоматов с самого «медленного» — 1 к самому «быстрому» — 3 по срабатыванию соответственно. Чем выше класс, тем выше цена.
  7. Условия использования – определяются исходя из потребностей.

Выбор дифавтомата по мощности

Для того чтобы выбрать дифавтомат по мощности необходимо учитывать состояние проводки. При условии, что проводка качественная, надёжная и отвечающая всем требованиям, для расчёта номинала можно применить следующую формулу – I=P/U, где P – это суммарная мощность используемых на линии дифференциального автомата электрических приборов. Выбираем дифавтомат ближайший по номиналу. Ниже приведена таблица зависимости номинала дифавтомата от мощности нагрузки для сети 220 В.

Внимание! Электрические провода должны быть правильно подобраны, исходя из мощности нагрузки.

Все характеристики дифавтоматов указываются непосредственно на самом корпусе устройства, что облегчит подбор подходящего дифференциального автомата и поможет определиться с тем, какой дифавтомат для квартиры подойдёт лучше всего.

На данный момент в продаже имеются дифавтоматы с двумя типами расцепителя:

  • Электронный – имеет электронную схему с усилителем сигнала, которая питается от подключённой фазы, что делает устройство уязвимым при отсутствии питания. При пропаже нуля такой он не сработает.
  • Электромеханический — не потребует для работы внешних источников питания, что делает его автономным.

Подключение

Подключение дифавтомата – весьма несложный процесс. Верхняя часть дифференциального автомата содержит контактные пластины и зажимные винты, предназначенные для подключения нуля N и фазы L от счётчика. Нижняя часть располагает контактами, к которым и подключается линия с потребителями.

Подключение дифавтомата можно представить следующим образом:

  1. Зачистка концов проводников от изоляционного материала примерно на 1 сантиметр.
  2. Ослабление зажимного винта на несколько оборотов.
  3. Подключение проводника.
  4. Затягивание винта.
  5. Проверка качества крепления простейшим физическим усилием.

Выбор между конфигурацией УЗО + автомат и обычным дифавтоматом должен обуславливаться наличием места в щитке и ценой самих устройств. В первом варианте сложность монтажа слегка возрастёт.

В случае с однофазной сетью в 220 В, используемой в большинстве квартир и домов, необходимо использовать двухполюсное устройство. Монтаж дифференциального автомата в данном случае можно провести двумя способами:

  1. На входе после электросчётчика для всей квартирной проводки. При использовании данной схемы питающие провода подключаются к верхним клеммам. К нижним же подаётся нагрузка от различных электрических групп, разделённых автоматическими выключателями. Существенным минусом данного варианта является сложность поиска причины выхода из строя в случае срабатывания автоматики и полное отключение всех групп при неполадках.
  2. На каждую группу потребителей по отдельности. Этот метод применяют для защиты в помещениях, где отмечается повышенный уровень влажности воздуха – ванные, кухни. Актуален метод и для мест, где электробезопасность должна быть на высшем уровне – например, для детской. Понадобится несколько дифференциальных автоматов – несмотря на большие затраты, данный способ является наиболее надёжным и гарантирующим бесперебойное электроснабжение, а срабатывание любого из дифавтоматов не заставит сработать остальные.

При наличии трёхфазной сети в 380 В нужно применять четырёхполюсный дифавтомат. Вариант используется в новых домах или коттеджах, где устройству необходимо выдерживать высокие нагрузки от электроприборов. Использовать такое подключение дифавтоматов можно и в гаражах в связи с возможным использованием мощного электрооборудования.

Можно сделать вывод, что схема подключения дифференциальных автоматов мало чем отличается от аналогичных схем для УЗО. На выходе устройства должны быть подключены фаза и ноль от защищаемого участка сети. Безопасность именно этой группы и будет контролироваться.

Дифференциальные автоматы успешно применяются и в однофазных, и в трёхфазных сетях переменного тока. Установка такого устройства значительно повышает уровень безопасности при эксплуатации электроприборов. Кроме того, дифференциальный автомат может поспособствовать предотвращению пожара, связанного с возгоранием изоляционного материала.

устройство и принцип работы, монтаж, схемы и способы подключения в распределительном щите

Электричество — это, безусловно, благо. Однако, обращаться с ним нужно осторожно, ведь из-за короткого замыкания или перепадов напряжения в электросети могут пострадать бытовые приборы. А для человека, случайно соприкоснувшегося с электропроводкой под напряжением, может все кончится летальным исходом. Защитить имущество и окружающих можно с помощью специального прибора, о нем и пойдет речь ниже.

Дифференциальный автомат: общие сведения

Дифференциальный автомат (дифавтомат) — является электромеханическим устройством, которое имеет два основных предназначения:

  • защитить электрическую цепь от утечки токов на землю;
  • защитить цепь от перегрузки в сети и короткого замыкания.

Дифференциальный автомат соединяет в себе функции УЗО и автоматического выключателя. Как УЗО, дифавтомат полностью защищает человеческий организм от поражения электричеством при соприкосновении с токонесущей частью электрооборудования.

Кроме этого, дифференциальный автомат отлично защищает сеть от короткого замыкания и перегрузок, то есть ведет себя, как автоматический выключатель.

Конструкция дифавтомата отличается от аналогичных ему устройств. В малом с виду корпусе удачно сочетаются и действуют два защитных прибора: УЗО и автоматический выключатель. Благодаря этому, дифференциальный автомат может быстро произвести защитное отключение. Соответственно это может произойти в случае утечки тока, перегрузки сети или короткого замыкания.

Принципы работы дифавтомата

Встроенный в дифавтомат автоматический выключатель обеспечивает защиту от перегрузок в сети и короткого замыкания. В этот защитный модуль входит устройство расцепления контактов. Оно сработает если в электрической сети возникнет перегрузка или короткое замыкание. Также автомат имеет рейку сброса. Она приводится в действие благодаря внешнему механическому воздействию.

Для защиты человека от воздействия электричества в дифавтомате встроен модуль дифференциальной защиты, в который входит дифференциальный трансформатор. Это устройство проводит постоянное сравнение текущих через него токов на входе и на выходе. Если обнаружится разница, которая несет угрозу, защитный модуль с помощью усилителя и электромагнитной катушки преобразует электрический ток в механическое действие, что и обесточит цепь.

Монтаж и схема подключения дифференциального автомата

При подключении дифавтомата нужно руководствоваться следующим правилом: в дифференциальный автомат подсоединяются ноль и фаза той цепи, которую будет защищать дифавтомат. Ни в коем случае нельзя объединять нулевой провод, приходящий с автомата с другим нулевым проводом. Это приведет к отключению дифавтомата.

Монтаж дифавтомата: схема подключения №1

Первая схема подключения защищает все электрические группы при помощи одного дифференциального автомата. Устройство устанавливают на входе цепи.

Во второй схеме дифавтомат, подключенный в цепь, защищает определенную электрическую группу. Этот вариант применяется для разработки надежной электробезопасности в помещении, где находится электрическая группа.

Если дифавтомат подключается по первому варианту, то к верхним клеммам прибора подводятся провода с питающим напряжением, а к нижним — подключают нагрузку от каждой группы в отдельности. При этом группы предварительно разделены электрическими выключателями.

Главный минус такого варианта подключения является то, что в случае аварийного срабатывания автомата полностью отключатся все электрические группы.

Чтобы избежать ложного срабатывания вводного дифавтомата, рекомендуется применять автомат с током утечки 30 мА.

Монтаж дифференциального автомата: схема подключения №2

Этот вариант защиты электрической сети дифавтоматом считается наиболее надежной и удобной. Часто эта схема применяется в помещениях с повышенными требованиями по электробезопасности или во влажных помещениях — кухня или ванная комната. Особенностью второй схемы подключения дифавтомата является то, что аварийное отключение одного дифавтомата не повлечет за собой отключение остальных. Безусловно, это положительный момент такой схемы подключения дифференциального автомата для защиты необходимых групповых линий. Впрочем, эта схема стоит дороже по сравнению с первой.

Монтаж дифавтомата: подключение по селективной схеме

Разобраться, чем отличается селективная схема подключения от неселективной, можно на примере двух схем, приведенных ниже.

Для простоты понимания опишем эти схемы, как схемы условной электрической разводки на лестничной площадке дома. Вводный дифавтомат размещается в распределительном щите на площадке, а остальные дифавтоматы пусть будут установлены в трех квартирах.

Схема с селективным подключением дифавтомата.

Принцип работы такой: если из-за повреждения происходит аварийное отключение автомата в одной из квартир, то автоматы в остальных квартирах и дифавтомат в распределительном щите будут продолжать работать. В селективной схеме дифавтомат имеет обозначение «S» — селективный.

Схема без селективного подключения дифавтомата.

При срабатывании на отключение автомата в квартире, происходит отключение дифавтомата и в распределительном щите. Кроме поврежденной линии обесточиваются и две рабочие. Это происходит потому что дифавтомат в распределительном щите рассчитан на ток утечки 100 мА, а отводные автоматы рассчитанны на 30 мА. Очень важно правильно подобрать автомат по току утечки.

В зависимости от вида дифавтомата, схема подключения будет либо селективной либо неселективной.

Правила монтажа дифавтомата в распределительном щите

Подключая дифавтомат в распределительном щите, нужно следовать определенным правилам.

  1. Подсоединять фазу следует на вход дифавтомата, то есть туда, где на верхней части устройства имеются обозначения «1» или «L».
  2. Рядом с ними будет стоять буква «N» — это вход нуля на дифавтомат.
  3. Выход фазы с устройства находится в нижней части и обозначен «2» или «L».
  4. Выход нуля с прибора тут же и имеет обозначение «N».

Дифавтомат подключается, следуя приложенной к прибору инструкции.

Мастер, производящий подключение, должен четко осознавать какой из проводов и куда нужно подключать. Определить фазу можно с помощью отвертки-индикатора.

Дифавтоматы подключаются как к однофазной сети, так и к трехфазной сети переменного тока.

Подключение дифференциального автомата проводится с соблюдением всех мер электробезопасности.

Если недостаточно средств или не хватает места в распределительном щите, то стоит выбрать схему №1. Но нужно учесть, что если сработает водный дифавтомат — вся квартира будет обесточена. Также в этой схеме очень сложно искать неисправности.

Если есть время и желание повозится с более сложной схемой, хватает финансов на покупку дифавтоматов, а также имеется много места в распределительном щите, то можно смело выбирать схему №2. Она обеспечит надежность и безопасность. Ведь в случае аварии отключится лишь одна линия, а, значит, искать неисправность в такой схеме будет гораздо легче.

Что касается селективной и неселективной схем, то они, независимо от выбора дифавтомата, считаются очень надежными и вполне могут защитить людей, бытовые приборы и сеть.

Введение в градиенты и автоматическое распознавание

Автоматическая дифференциация и градиенты

Автоматическая дифференциация полезен для реализации алгоритмов машинного обучения, таких как обратное распространение для обучения нейронные сети.

В этом руководстве вы изучите способы вычисления градиентов с помощью TensorFlow, особенно при активном выполнении.

Настройка

  импортировать numpy как np
импортировать matplotlib.pyplot как plt

импортировать тензорный поток как tf
  

Вычислительные градиенты

Чтобы различать автоматически, TensorFlow должен запоминать, какие операции в каком порядке выполняются во время прохода вперед и .Затем во время обратного прохода TensorFlow просматривает этот список операций в обратном порядке для вычисления градиентов.

Градиентные ленты

TensorFlow предоставляет tf.GradientTape API для автоматического распознавания; то есть вычисление градиента вычисления относительно некоторых входных данных, обычно tf. Переменная s. TensorFlow «записывает» соответствующие операции, выполняемые в контексте tf.GradientTape , на «ленту». Затем TensorFlow использует эту ленту для вычисления градиентов «записанного» вычисления с использованием обратного дифференцирования.

Вот простой пример:

  x = tf. Переменная (3,0)

с tf.GradientTape () в качестве ленты:
  у = х ** 2
  

После записи некоторых операций используйте GradientTape.gradient (target, sources) для вычисления градиента некоторой цели (часто потери) относительно некоторого источника (часто переменных модели):

  # dy = 2x * dx
dy_dx = tape.gradient (y, x)
dy_dx.numpy ()
  
6.0
 

В приведенном выше примере используются скаляры, но tf.GradientTape так же легко работает на любом тензоре:

  w = tf.Variable (tf.random.normal ((3, 2)), name = 'w')
b = tf.Variable (tf.zeros (2, dtype = tf.float32), name = 'b')
x = [[1., 2., 3.]]

с tf.GradientTape (persistent = True) в качестве ленты:
  у = х @ ш + Ь
  потеря = tf.reduce_mean (y ** 2)
  

Чтобы получить градиент потери по обеим переменным, вы можете передать оба в качестве источников в метод gradient . Лента гибкая в отношении того, как передаются источники, и принимает любую вложенную комбинацию списков или словарей и возвращает градиент, структурированный таким же образом (см. tf.гнездо ).

  [dl_dw, dl_db] = tape.gradient (потеря, [w, b])
  

Градиент по отношению к каждому источнику имеет форму источника:

  печать (в форме)
печать (dl_dw.shape)
  
(3, 2)
(3, 2)
 

Вот снова расчет градиента, на этот раз передающий словарь переменных:

  my_vars = {
    'ш': ш,
    'b': b
}

grad = tape.gradient (потеря, my_vars)
град ['b']
  

 

Градиенты относительно модели

Обычно tf.Variables собирают в tf.Module или в один из его подклассов (слои .Layer , keras.Model ) для создания контрольных точек и экспорта.

В большинстве случаев вам может потребоваться вычислить градиенты относительно обучаемых переменных модели. Поскольку все подклассы tf.Module агрегируют свои переменные в модуле .trainable_variables , вы можете вычислить эти градиенты в нескольких строках кода:

  слой = tf.keras.layers.Dense (2, активация = 'relu')
x = tf.constant ([[1., 2., 3.]])

с tf.GradientTape () в качестве ленты:
  # Передний пас
  y = слой (x)
  потеря = tf.reduce_mean (y ** 2)

# Рассчитываем градиенты по каждой обучаемой переменной
grad = tape.gradient (потеря, layer.trainable_variables)
  
  для var, g в zip (layer.trainable_variables, grad):
  print (f '{var.name}, shape: {g.shape} ')
  
плотный / ядро ​​& двоеточие; 0, форма & двоеточие; (3, 2)
плотный / смещение & двоеточие; 0, форма & двоеточие; (2,)
 

Контроль за тем, что смотрит магнитофон

По умолчанию записываются все операции после доступа к обучаемой tf.Variable . Причины этого:

  • Ленте необходимо знать, какие операции записывать при прямом проходе, чтобы вычислить градиенты при обратном проходе.
  • Лента содержит ссылки на промежуточные выходы, поэтому вы не хотите записывать ненужные операции.
  • Наиболее распространенный вариант использования включает вычисление градиента потерь по всем обучаемым переменным модели.

Например, следующее не может вычислить градиент, потому что tf.Tensor не «отслеживается» по умолчанию, а tf.Variable не обучается:

  # Обучаемая переменная
x0 = tf.Variable (3.0, имя = 'x0')
# Не обучается
x1 = tf.Variable (3.0, name = 'x1', trainable = False)
# Не переменная: переменная + тензор возвращает тензор.x2 = tf.Variable (2.0, name = 'x2') + 1.0
# Не переменная
x3 = tf.constant (3.0, имя = 'x3')

с tf.GradientTape () в качестве ленты:
  у = (х0 ** 2) + (х1 ** 2) + (х2 ** 2)

grad = tape.gradient (y, [x0, x1, x2, x3])

для g в град:
  печать (г)
  
tf.Tensor (6.0, shape = (), dtype = float32)
Никто
Никто
Никто
 

Вы можете перечислить переменные, за которыми следит лента, используя метод GradientTape.watched_variables :

  [имя переменной для переменной в tape.watched_variables ()]
  
['x0 & двоеточие; 0']
 

тс.GradientTape предоставляет хуки, которые дают пользователю возможность контролировать, что смотрит, а что нет.

Чтобы записать градиенты относительно tf.Tensor , вам необходимо вызвать GradientTape.watch (x) :

  x = tf.постоянная (3,0)
с tf.GradientTape () в качестве ленты:
  tape.watch (x)
  у = х ** 2

# dy = 2x * dx
dy_dx = tape.gradient (y, x)
печать (dy_dx.numpy ())
  
6.0
 

И наоборот, чтобы отключить поведение по умолчанию при просмотре всех tf.Переменные , установите watch_accessed_variables = False при создании градиентной ленты. Этот расчет использует две переменные, но связывает градиент только для одной из переменных:

  x0 = tf. Переменная (0,0)
x1 = tf. переменная (10.0)

с tf.GradientTape (watch_accessed_variables = False) в качестве ленты:
  лента. часы (x1)
  y0 = tf.math.sin (x0)
  y1 = tf.nn.softplus (x1)
  у = у0 + у1
  ys = tf.reduce_sum (y)
  

Поскольку GradientTape.watch не вызывается на x0 , градиент не вычисляется относительно него:

  # dys / dx1 = exp (x1) / (1 + exp (x1)) = сигмовидная (x1)
град = лента.градиент (ys, {'x0': x0, 'x1': x1})

print ('dy / dx0:', grad ['x0'])
print ('dy / dx1:', grad ['x1']. numpy ())
  
dy / dx0 & двоеточие; Никто
dy / dx1 & двоеточие; 0,9999546
 

Вы также можете запросить градиенты вывода относительно промежуточных значений, вычисленных в контексте tf.GradientTape .

  x = tf.постоянная (3,0)

с tf.GradientTape () в качестве ленты:
  tape.watch (x)
  у = х * х
  г = у * у

# Используйте ленту, чтобы вычислить градиент z относительно
# промежуточное значение y.# dz_dy = 2 * y и y = x ** 2 = 9
печать (лента.градиент (z, y) .numpy ())
  
18.0
 

По умолчанию ресурсы, удерживаемые GradientTape , освобождаются, как только вызывается метод GradientTape.gradient . Чтобы вычислить несколько градиентов за одно вычисление, создайте градиентную ленту с persistent = True . Это позволяет многократно вызывать метод gradient по мере высвобождения ресурсов при сборке мусора для объекта ленты.Например:

  x = tf.constant ([1, 3.0])
с tf.GradientTape (persistent = True) в качестве ленты:
  tape.watch (x)
  у = х * х
  г = у * у

print (tape.gradient (z, x) .numpy ()) # [4.0, 108.0] (4 * x ** 3 при x = [1.0, 3.0])
print (tape.gradient (y, x) .numpy ()) # [2.0, 6.0] (2 * x при x = [1.0, 3.0])
  
[4. 108.]
[2. 6.]
 
  del tape # Сбросьте ссылку на ленту
  

Примечания к исполнению

  • Есть крошечные накладные расходы, связанные с выполнением операций внутри контекста градиентной ленты.Для наиболее энергичного выполнения это не будет заметной ценой, но вы все равно должны использовать ленточный контекст вокруг областей только там, где это необходимо.

  • Градиентные ленты используют память для хранения промежуточных результатов, включая входные и выходные данные, для использования во время обратного прохода.

    Для повышения эффективности некоторым операциям (например, ReLU ) не нужно сохранять свои промежуточные результаты, и они удаляются во время прямого прохода. Однако, если вы используете persistent = True на своей ленте, ничего не отбрасывается, и ваше пиковое использование памяти будет выше.

Градиенты нескалярных целей

Градиент — это, по сути, операция над скаляром.

  x = tf. Переменная (2.0)
с tf.GradientTape (persistent = True) в качестве ленты:
  у0 = х ** 2
  у1 = 1 / х

печать (лента.градиент (y0, x) .numpy ())
печать (лента.градиент (y1, x) .numpy ())
  
4.0
-0,25
 

Таким образом, если вы запросите градиент нескольких целей, результат для каждого источника будет:

  • Градиент суммы целей, или эквивалентно
  • Сумма градиентов каждой цели.
  x = tf. Переменная (2.0)
с tf.GradientTape () в качестве ленты:
  у0 = х ** 2
  у1 = 1 / х

print (tape.gradient ({'y0': y0, 'y1': y1}, x) .numpy ())
  
3,75
 

Аналогично, если цель (и) не скалярная, вычисляется градиент суммы:

  x = tf. Переменная (2.)

с tf.GradientTape () в качестве ленты:
  y = x * [3., 4.]

печать (лента.градиент (у, х) .numpy ())
  
7.0
 

Это упрощает получение градиента суммы совокупных потерь или градиента суммы поэлементного расчета потерь.

Если вам нужен отдельный градиент для каждого элемента, обратитесь к якобианам.

В некоторых случаях якобиан можно пропустить. Для поэлементного расчета градиент суммы дает производную каждого элемента по отношению к его входному элементу, поскольку каждый элемент независим:

  x = tf.linspace (-10.0, 10.0, 200 + 1)

с tf.GradientTape () в качестве ленты:
  tape.watch (x)
  у = tf.nn.sigmoid (х)

dy_dx = tape.gradient (y, x)
  
  plt.plot (x, y, label = 'y')
plt.сюжет (x, dy_dx, label = 'dy / dx')
plt.legend ()
_ = plt.xlabel ('x')
  

Управляющий поток

Поскольку градиентная лента записывает операции по мере их выполнения, поток управления Python обрабатывается естественным образом (например, , если операторы и , а операторы ).

Здесь разные переменные используются в каждой ветви , если . Градиент связан только с используемой переменной:

  x = tf.постоянная (1.0)

v0 = tf. переменная (2.0)
v1 = tf. переменная (2.0)

с tf.GradientTape (persistent = True) в качестве ленты:
  tape.watch (x)
  если x> 0,0:
    результат = v0
  еще:
    результат = v1 ** 2

dv0, dv1 = tape.gradient (результат, [v0, v1])

печать (dv0)
печать (dv1)
  
tf.Tensor (1.0, shape = (), dtype = float32)
Никто
 

Просто помните, что управляющие операторы сами по себе не дифференцируемы, поэтому они невидимы для оптимизаторов на основе градиентов.

В зависимости от значения x в приведенном выше примере на ленту записывается либо result = v0 , либо result = v1 ** 2 .Градиент относительно x всегда равен Нет .

  dx = tape.gradient (результат, x)

печать (dx)
  
Никто
 

Получение градиента

Нет

Когда цель не подключена к источнику, вы получите градиент Нет .

  x = tf. Переменная (2.)
y = tf. переменная (3.)

с tf.GradientTape () в качестве ленты:
  г = у * у
печать (лента.градиент (z, x))
  
Никто
 

Здесь z , очевидно, не связан с x , но есть несколько менее очевидных способов отключения градиента.

1. Заменил переменную на тензор

В разделе «Контроль за тем, что смотрит лента» вы видели, что лента автоматически отслеживает tf.Variable , но не tf.Tensor .

Одна из распространенных ошибок — непреднамеренная замена tf.Variable на tf.Tensor вместо использования Variable.assign для обновления tf.Variable . Вот пример:

  x = tf. Переменная (2.0)

для эпохи в диапазоне (2):
  с тф.GradientTape () как лента:
    у = х + 1

  print (type (x) .__ name__, ":", tape.gradient (y, x))
  x = x + 1 # Это должно быть `x.assign_add (1)`
  
ResourceVariable & двоеточие; tf.Tensor (1.0, shape = (), dtype = float32)
EagerTensor & двоеточие; Никто
 

2. Выполнял вычисления вне TensorFlow

Лента не может записать путь градиента, если вычисление выходит из TensorFlow. Например:

  x = tf.Variable ([[1.0, 2.0],
                 [3.0, 4.0]], dtype = tf.float32)

с tf.GradientTape () в качестве ленты:
  х2 = х ** 2

  # Этот шаг рассчитывается с помощью NumPy
  y = np.mean (x2, ось = 0)

  # Как и большинство операций, reduce_mean преобразует массив NumPy в постоянный тензор
  # используя `tf.convert_to_tensor`.
  y = tf.reduce_mean (y, ось = 0)

печать (лента.градиент (у, х))
  
Никто
 

3. Взял градиенты через целое число или строку

Целые числа и строки не дифференцируются. Если расчетный путь использует эти типы данных, градиент не будет.

Никто не ожидает, что строки будут дифференцируемыми, но легко случайно создать константу или переменную int , если вы не укажете dtype .

  x = tf.постоянная (10)

с tf.GradientTape () как g:
  g.watch (x)
  у = х * х

печать (g.gradient (y, x))
  
ПРЕДУПРЕЖДЕНИЕ & Colon; Tenorflow & Colon; Тип dtype наблюдаемого тензора должен быть плавающим (например, tf.float32), получено tf.int32
ПРЕДУПРЕЖДЕНИЕ & Colon; tensorflow & Colon; Тип d целевого тензора должен быть плавающим (например,грамм. tf.float32) при вызове GradientTape.gradient получил tf.int32
ПРЕДУПРЕЖДЕНИЕ & Colon; tensorflow & Colon; dtype исходного тензора должен быть плавающим (например, tf.float32) при вызове GradientTape.gradient, получен tf.int32
Никто
 

TensorFlow не выполняет автоматическое преобразование типов между типами, поэтому на практике вы часто получаете ошибку типа вместо отсутствующего градиента.

4. Получение градиентов через объект с сохранением состояния

Состояние остановки градиентов. Когда вы читаете из объекта с состоянием, лента может наблюдать только текущее состояние, а не историю, которая к нему ведет.

A tf.Tensor неизменяемый. Вы не можете изменить тензор после его создания. Он имеет значение , но не имеет состояния . Все операции, которые обсуждались до сих пор, также не имеют состояния: вывод tf.matmul зависит только от его входных данных.

A tf. Переменная имеет внутреннее состояние — свое значение. Когда вы используете переменную, считывается состояние. Вычисление градиента относительно переменной является нормальным явлением, но состояние переменной препятствует дальнейшему возврату вычислений градиента.Например:

  x0 = tf. Переменная (3,0)
x1 = tf. переменная (0,0)

с tf.GradientTape () в качестве ленты:
  # Обновить x1 = x1 + x0.
  x1.assign_add (x0)
  # Лента начинает запись с x1.
  у = х1 ** 2 # у = (х1 + х0) ** 2

# Это не работает.
print (tape.gradient (y, x0)) # dy / dx0 = 2 * (x1 + x0)
  
Никто
 

Точно так же итераторы tf.data.Dataset и tf.queue сохраняют состояние и останавливают все градиенты на тензорах, которые проходят через них.

Градиент не зарегистрирован

Некоторые tf.Operation s зарегистрированы как недифференцируемые и вернут Нет . У других градиент не зарегистрирован .

Страница tf.raw_ops показывает, какие низкоуровневые операции имеют зарегистрированные градиенты.

Если вы попытаетесь взять градиент через операцию с плавающей точкой, для которой не зарегистрирован градиент, лента выдаст ошибку вместо того, чтобы молча вернуть Нет .Таким образом, вы узнаете, что что-то пошло не так.

Например, функция tf.image.adjust_contrast оборачивает raw_ops.AdjustContrastv2 , которые могут иметь градиент, но градиент не реализован:

  image = tf.Variable ([[[0.5, 0.0, 0.0]]])
дельта = tf. переменная (0,1)

с tf.GradientTape () в качестве ленты:
  new_image = tf.image.adjust_contrast (изображение, дельта)

пытаться:
  print (tape.gradient (new_image, [изображение, дельта]))
  assert False # Этого не должно происходить.кроме LookupError как e:
  print (f '{type (e) .__ name__}: {e}')
  
LookupError & двоеточие; В реестре градиента нет записи для & col; AdjustContrastv2
 

Если вам нужно различать с помощью этой операции, вам нужно либо реализовать градиент и зарегистрировать его (используя tf.RegisterGradient ), либо повторно реализовать функцию, используя другие операции.

нулей вместо отсутствия

В некоторых случаях было бы удобно получить 0 вместо Нет для несвязанных градиентов.Вы можете решить, что возвращать, когда у вас есть несвязанные градиенты, используя аргумент unconnected_gradients :

  x = tf.Variable ([2., 2.])
y = tf. переменная (3.)

с tf.GradientTape () в качестве ленты:
  г = у ** 2
print (tape.gradient (z, x, unconnected_gradients = tf.UnconnectedGradients.ZERO))
  
tf.Tensor ([0. 0.], shape = (2,), dtype = float32)
 
Оптимизация

— Пошаговый пример автоматического дифференцирования в обратном режиме

Допустим, у нас есть выражение $ z = x_1x_2 + \ sin (x_1) $ и мы хотим найти производные $ \ frac {dz} {dx_1} $ и $ \ frac {dz} {dx_2} $.AD в обратном режиме разделяет эту задачу на 2 части, а именно, прямой и обратный проходы.

Передний пас

Сначала мы разлагаем наше сложное выражение на набор примитивных выражений, то есть выражений, состоящих не более чем из одного вызова функции. Обратите внимание, что я также переименовал входные и выходные переменные для единообразия, хотя в этом нет необходимости:

$$ w_1 = x_1 $$ $$ w_2 = x_2 $$ $$ w_3 = w_1w_2 $$ $$ w_4 = \ sin (w_1) $$ $$ w_5 = w_3 + w_4 $$ $$ z = w_5 $$

Преимущество этого представления в том, что правила дифференциации для каждого отдельного выражения уже известны.Например, мы знаем, что производная от $ \ sin $ равна $ \ cos $, и поэтому $ \ frac {dw_4} {dw_1} = \ cos (w_1) $. Мы воспользуемся этим фактом в обратном порядке ниже.

По сути, прямой проход состоит из оценки каждого из этих выражений и сохранения результатов. Скажем, наши входные данные: $ x_1 = 2 $ и $ x_2 = 3 $. Тогда имеем:

$$ w_1 = x_1 = 2 $$ $$ w_2 = x_2 = 3 $$ $$ w_3 = w_1w_2 = 6 $$ $$ w_4 = \ sin (w_1) ~ = 0.9 $$ $$ w_5 = w_3 + w_4 = 6.9 $$ $$ z = w_5 = 6.9 $$

Обратный проход

Это было начало магии, и оно начинается с правила цепочки .В своей основной форме цепное правило гласит, что если у вас есть переменная $ t (u (v)) $, которая зависит от $ u $, который, в свою очередь, зависит от $ v $, то:

$$ \ frac {dt} {dv} = \ frac {dt} {du} \ frac {du} {dv} $$

или, если $ t $ зависит от $ v $ через несколько путей / переменных $ u_i $, например:

$$ u_1 = f (v) $$ $$ u_2 = g (v) $$ $$ t = h (u_1, u_2) $$

тогда (см. Доказательство здесь):

$$ \ frac {dt} {dv} = \ sum_i \ frac {dt} {du_i} \ frac {du_i} {dv} $$

В терминах графа выражений, если у нас есть конечный узел $ z $ и входные узлы $ w_i $, а путь от $ z $ до $ w_i $ проходит через промежуточные узлы $ w_p $ (i.е. $ z = g (w_p) $, где $ w_p = f (w_i) $), мы можем найти производную $ \ frac {dz} {dw_i} $ как

$$ \ frac {dz} {dw_i} = \ sum_ {p \ in parent (i)} \ frac {dz} {dw_p} \ frac {dw_p} {dw_i} $$

Другими словами, чтобы вычислить производную выходной переменной $ z $ w.r.t. любая промежуточная или входная переменная $ w_i $, нам нужно знать только производные ее родителей и формулу для вычисления производной примитивного выражения $ w_p = f (w_i) $.

Обратный проход начинается в конце (т.е. $ \ frac {dz} {dz} $) и распространяется в обратном направлении на все зависимости.Здесь мы имеем (выражение для «семя»):

$$ \ frac {dz} {dz} = 1 $$

Это можно прочитать как «изменение $ z $ приводит к точно такому же изменению $ z $», что совершенно очевидно.

Тогда мы знаем, что $ z = w_5 $ и так:

$$ \ frac {dz} {dw_5} = 1 $$

$ w_5 $ линейно зависит от $ w_3 $ и $ w_4 $, поэтому $ \ frac {dw_5} {dw_3} = 1 $ и $ \ frac {dw_5} {dw_4} = 1 $. Используя цепное правило, находим:

$$ \ frac {dz} {dw_3} = \ frac {dz} {dw_5} \ frac {dw_5} {dw_3} = 1 \ times 1 = 1 $$ $$ \ frac {dz} {dw_4} = \ frac {dz} {dw_5} \ frac {dw_5} {dw_4} = 1 \ times 1 = 1 $$

Из определения $ w_3 = w_1w_2 $ и правил частных производных находим, что $ \ frac {dw_3} {dw_2} = w_1 $.Таким образом:

$$ \ frac {dz} {dw_2} = \ frac {dz} {dw_3} \ frac {dw_3} {dw_2} = 1 \ times w_1 = w_1 $$

Что, как мы уже знаем из прохода вперед, это:

$$ \ frac {dz} {dw_2} = w_1 = 2 $$

Наконец, $ w_1 $ вносит вклад в $ z $ через $ w_3 $ и $ w_4 $. Еще раз, из правил частных производных мы знаем, что $ \ frac {dw_3} {dw_1} = w_2 $ и $ \ frac {dw_4} {dw_1} = \ cos (w_1) $. Таким образом:

$$ \ frac {dz} {dw_1} = \ frac {dz} {dw_3} \ frac {dw_3} {dw_1} + \ frac {dz} {dw_4} \ frac {dw_4} {dw_1} = w_2 + \ cos (w_1) $$

И снова, учитывая известные входные данные, мы можем вычислить это:

$$ \ frac {dz} {dw_1} = w_2 + \ cos (w_1) = 3 + \ cos (2) ~ = 2.58 $$

Поскольку $ w_1 $ и $ w_2 $ — это просто псевдонимы для $ x_1 $ и $ x_2 $, мы получаем ответ:

$$ \ frac {dz} {dx_1} = 2,58 $$ $$ \ frac {dz} {dx_2} = 2 $$

И все!


Это описание касается только скалярных входных данных, то есть чисел, но фактически оно также может применяться к многомерным массивам, таким как векторы и матрицы. При различении выражений с такими объектами следует иметь в виду две вещи:

  1. Производные инструменты могут иметь гораздо более высокую размерность, чем входные или выходные данные, например.грамм. производная вектора по вектор — это матрица и производная от матрицы по отношению к матрица — это 4-мерный массив (иногда называемый тензором). Во многих случаях таких производных очень мало.
  2. Каждый компонент в выходном массиве является независимой функцией 1 или более компонентов входного массива (ов). Например. если $ y = f (x) $ и оба $ x $ и $ y $ являются векторами, $ y_i $ никогда не зависит от $ y_j $, а только от подмножества $ x_k $. В частности, это означает, что поиск производной $ \ frac {dy_i} {dx_j} $ сводится к отслеживанию того, как $ y_i $ зависит от $ x_j $.

Сила автоматического дифференцирования заключается в том, что оно может иметь дело со сложными структурами языков программирования, такими как условия и циклы. Однако, если все, что вам нужно, это алгебраические выражения и у вас достаточно хорошая структура для работы с символьными представлениями, можно создавать полностью символьные выражения. Фактически, в этом примере мы могли бы создать выражение $ \ frac {dz} {dw_1} = w_2 + \ cos (w_1) = x_2 + \ cos (x_1) $ и вычислить эту производную для любых входных данных, которые нам нужны.

Поваренная книга Autodiff — JAX-документация

JAX имеет довольно общую систему автоматической дифференциации. В этой записной книжке мы рассмотрим целую кучу изящных идей автодифференцирования, которые вы сможете выбрать для своей работы, начиная с основ.

Градиенты

Начиная с

град

Вы можете дифференцировать функцию с помощью град :

 grad_tanh = град (jnp.tanh)
печать (grad_tanh (2.0))
 

grad принимает функцию и возвращает функцию.Если у вас есть функция Python f , которая оценивает математическую функцию \ (f \), тогда grad (f) — это функция Python, которая оценивает математическую функцию \ (\ nabla f \). Это означает, что grad (f) (x) представляет значение \ (\ nabla f (x) \).

Поскольку grad работает с функциями, вы можете применить его к его собственному выводу, чтобы различать столько раз, сколько захотите:

 печать (град (град (jnp.tanh)) (2.0))
печать (град (град (град (jnp.tanh))) (2.0))
 

Давайте посмотрим на вычисление градиентов с градиентами в модели линейной логистической регрессии.Во-первых, установка:

 сигмоида def (x):
    return 0.5 * (jnp.tanh (x / 2) + 1)

# Выводит вероятность того, что метка верна.
def прогноз (W, b, входы):
    вернуть сигмоид (jnp.dot (входы, W) + b)

# Создайте набор данных об игрушках.
входы = jnp.array ([[0.52, 1.12, 0.77],
                   [0,88, -1,08, 0,15],
                   [0,52, 0,06, -1,30],
                   [0,74, -2,49, 1,39]])
target = jnp.array ([Верно, Верно, Ложно, Верно])

# Потеря обучения - это отрицательная логарифмическая вероятность примеров обучения.def потеря (W, b):
    preds = предсказать (W, b, входные данные)
    label_probs = прогнозы * цели + (1 - прогнозы) * (1 - цели)
    вернуть -jnp.sum (jnp.log (label_probs))

# Инициализировать случайные коэффициенты модели
ключ, W_key, b_key = random.split (ключ, 3)
W = случайный.нормальный (W_key, (3,))
b = случайный.нормальный (b_key, ())
 

Используйте функцию grad с ее аргументом argnums , чтобы дифференцировать функцию по позиционным аргументам.

 # Дифференцировать `проигрыш` относительно первого позиционного аргумента:
W_grad = grad (потери, argnums = 0) (W, b)
print ('W_grad', W_grad)

# Поскольку по умолчанию argnums = 0, это делает то же самое:
W_grad = град (потеря) (Вт, б)
print ('W_grad', W_grad)

# Но мы также можем выбрать другие значения и опустить ключевое слово:
b_grad = grad (убыток, 1) (W, b)
print ('b_grad', b_grad)

# Включая значения кортежа
W_grad, b_grad = grad (потеря, (0, 1)) (W, b)
print ('W_grad', W_grad)
print ('b_grad', b_grad)
 
 Вт_град [-0.16965576 -0,8774648 -1,45]
W_grad [-0,16965576 -0,8774648 -1,45]
b_grad -0.2922724
W_grad [-0,16965576 -0,8774648 -1,45]
b_grad -0.2922724
 

Этот API grad имеет прямое соответствие превосходной нотации в классическом исчислении Спивака на многообразиях (1965), также используемом в книге Sussman and Wisdom Структура и интерпретация классической механики (2015) и их функционально-дифференциальной геометрии . (2013). Обе книги находятся в открытом доступе.См., В частности, раздел «Пролог» функционально-дифференциальной геометрии для защиты этой нотации.

По сути, при использовании аргумента argnums , если f является функцией Python для оценки математической функции \ (f \), тогда выражение Python grad (f, i) оценивается как функция Python для оценки \ (\ partial_i f \).

Дифференциация по вложенным спискам, кортежам и диктовкам

Дифференциация по отношению к стандартным контейнерам Python просто работает, поэтому используйте кортежи, списки и словари (и произвольное вложение), как вам нравится.

 def loss2 (params_dict):
    preds = preds (params_dict ['W'], params_dict ['b'], входные данные)
    label_probs = прогнозы * цели + (1 - прогнозы) * (1 - цели)
    вернуть -jnp.sum (jnp.log (label_probs))

print (grad (loss2) ({'W': W, 'b': b}))
 
 {'W': DeviceArray ([- 0,16965576, -0,8774648, -1,45], dtype = float32), 'b': DeviceArray (-0,2922724, dtype = float32)}
 

Вы можете зарегистрировать свои собственные типы контейнеров для работы не только с grad , но и со всеми преобразованиями JAX ( jit , vmap и т. Д.).

Вычислить функцию и ее градиент, используя значение

value_and_grad

Еще одна удобная функция — value_and_grad для эффективного вычисления как значения функции, так и значения ее градиента:

 из jax import value_and_grad
loss_value, Wb_grad = value_and_grad (потеря, (0, 1)) (W, b)
print ('значение потери', loss_value)
print ('значение убытка', убыток (W, b))
 

Проверка числовых различий

В производных финансовых инструментах замечательно то, что их легко проверить с помощью конечных разностей:

 # Установить размер шага для расчетов конечных разностей
eps = 1e-4

# Проверяем b_grad с помощью скалярных конечных разностей
b_grad_numerical = (убыток (W, b + eps / 2.) - убыток (W, b - eps / 2.)) / eps
print ('b_grad_numerical', b_grad_numerical)
print ('b_grad_autodiff', grad (потеря, 1) (W, b))

# Проверяем W_grad с конечными разностями в случайном направлении
ключ, подключ = random.split (ключ)
vec = random.normal (подключ, W.shape)
unitvec = vec / jnp.sqrt (jnp.vdot (vec, vec))
W_grad_numerical = (loss (W + eps / 2. * unitvec, b) - убыток (W - eps / 2. * unitvec, b)) / eps
print ('W_dirderiv_numerical', W_grad_numerical)
print ('W_dirderiv_autodiff', jnp.vdot (grad (потеря) (W, b), unitvec))
 
 b_grad_numerical -0.29325485
b_grad_autodiff -0.2922724
 
 W_dirderiv_numerical -0.19788742
W_dirderiv_autodiff -0.199
 

JAX предоставляет простую удобную функцию, которая, по сути, делает то же самое, но проверяет любой порядок дифференциации, который вам нравится:

 из jax.test_util import check_grads
check_grads (loss, (W, b), order = 2) # проверка производных до 2-го порядка
 

векторных произведений Гессе с

град -оф- град

Одна вещь, которую мы можем сделать с помощью более высокого порядка grad , — это построить функцию произведения вектора Гессе.2 f (x) v = \ partial [x \ mapsto \ partial f (x) \ cdot v] = \ partial g (x) \),

, где \ (g (x) = \ partial f (x) \ cdot v \) — новая скалярная функция, которая ставит точки градиента \ (f \) в \ (x \) с вектором \ (v \ ). Обратите внимание, что мы дифференцируем только скалярные функции от векторных аргументов, и именно здесь мы знаем, что grad эффективен.

В коде JAX мы можем просто написать это:

 def hvp (f, x, v):
    вернуть град (лямбда x: jnp.vdot (grad (f) (x), v)) (x)
 

Этот пример показывает, что вы можете свободно использовать лексическое замыкание, и JAX никогда не будет нарушен или запутан.

Мы проверим эту реализацию на несколько ячеек, как только увидим, как вычислять плотные матрицы Гессе. Мы также напишем еще лучшую версию, в которой используются как прямой, так и обратный режимы.

Якобианы и Гессе с использованием

jacfwd и jacrev

Вы можете вычислить полные матрицы Якоби, используя функции jacfwd и jacrev :

 из jax import jacfwd, jacrev

# Изолируйте функцию от весовой матрицы до прогнозов
f = лямбда W: прогнозировать (W, b, входные данные)

J = jacfwd (f) (Вт)
print ("результат jacfwd, с формой", Дж.форма)
печать (J)

J = jacrev (f) (Вт)
print ("jacrev result, with shape", J.shape)
печать (J)
 
 результат jacfwd, с формой (4, 3)
[[0,05981752 0,1283775 0,08857594]
 [0,04015911 -0,04928619 0,0068453]
 [0,12188288 0,01406341 -0,3047072]
 [0,00140426 -0,00472516 0,00263774]]
результат jacrev, с формой (4, 3)
[[0,05981752 0,1283773 0,08857594]
 [0,04015911 -0,04928619 0,0068453]
 [0,12188289 0,01406341 -0,3047072]
 [0,00140426 -0,00472516 0,00263774]]
 

Эти две функции вычисляют одни и те же значения (вплоть до машинных чисел), но отличаются своей реализацией: jacfwd использует автоматическое дифференцирование в прямом режиме, что более эффективно для «высоких» якобианских матриц, а jacrev использует обратный режим. , что более эффективно для «широких» якобиевых матриц.Для матриц, которые почти квадратны, jacfwd , вероятно, имеет преимущество над jacrev .

Вы также можете использовать jacfwd и jacrev с типами контейнеров:

 def прогноз_dict (параметры, входы):
    вернуть прогноз (params ['W'], params ['b'], input)

J_dict = jacrev (pred_dict) ({'W': W, 'b': b}, входные данные)
для k, v в J_dict.items ():
    print ("Якобиан от {} до логитов" .format (k))
    печать (v)
 
 Якобиан от W до логитов равен
[[0.05981752 0,1283773 0,08857594]
 [0,04015911 -0,04928619 0,0068453]
 [0,12188289 0,01406341 -0,3047072]
 [0,00140426 -0,00472516 0,00263774]]
Якобиан от b до логитов равен
[0,11503369 0,04563536 0,23439017 0,00189765]
 

Подробнее о прямом и обратном режимах, а также о том, как максимально эффективно реализовать jacfwd и jacrev , читайте дальше!

Использование композиции двух из этих функций дает нам способ вычислить плотные матрицы Гессе:

 def hessian (f):
    вернуть jacfwd (jacrev (f))

H = гессиан (f) (W)
print ("гессиан, с формой", H.форма)
печать (H)
 
 гессиан, с формой (4, 3, 3)
[[[0,02285464 0,04922539 0,03384245]
  [0,04922538 0,10602392 0,07289144]
  [0,03384245 0,07289144 0,05011286]]

 [[-0,03195212 0,03921397 -0,00544638]
  [0,03921397 -0,04812624 0,0066842]
  [-0,00544638 0,0066842 -0,00092836]]

 [[-0,01583708 -0,00182736 0,0395927]
  [-0,00182736 -0,00021085 0,00456839]
  [0,0395927 0,00456839 -0,09898175]]

 [[-0,0010352 0,00348332 -0,0019445]
  [0,00348332 -0,01172091 0,006543]
  [-0. {m \ times n} \).м \). Мы называем это отображение от пар \ ((x, v) \) до выходных касательных векторов произведением векторов Якоби   и записываем его как 

\ (\ qquad (x, v) \ mapsto \ partial f (x) v \)

JVP в коде JAX

Вернувшись в код Python, функция JAX jvp моделирует это преобразование. Учитывая функцию Python, которая вычисляет \ (f \), JAX jvp - это способ получить функцию Python для вычисления \ ((x, v) \ mapsto (f (x), \ partial f (x) v) \ ).

 из jax import jvp

# Изолируйте функцию от весовой матрицы до прогнозов
f = лямбда W: прогнозировать (W, b, входные данные)

ключ, подключ = случайный.разделить (ключ)
v = random.normal (подключ, W.shape)

# Сдвинуть вперед вектор `v` вдоль` f`, вычисленного в `W`
y, u = jvp (f, (W,), (v,))
 

В терминах сигнатур типов, подобных Haskell, мы могли бы написать

 jvp :: (a -> b) -> a -> T a -> (b, T b)
 

, где мы используем T a для обозначения типа касательного пространства для a . Проще говоря, jvp принимает в качестве аргументов функцию типа a -> b , значение типа a и значение касательного вектора типа T a .Он возвращает пару, состоящую из значения типа b и выходного касательного вектора типа T b .

Функция jvp, преобразованная в , оценивается во многом так же, как и исходная функция, но в паре с каждым первичным значением типа a она проталкивает по касательным значениям типа T a . Для каждой примитивной числовой операции, которую применила бы исходная функция, преобразованная функция jvp выполняет «правило JVP» для этого примитива, которое одновременно оценивает примитив на примитиве и применяет JVP примитива к этим примитивным значениям.

Эта стратегия оценки имеет некоторые непосредственные последствия для вычислительной сложности: поскольку мы оцениваем JVP по ходу работы, нам не нужно ничего хранить на будущее, и поэтому стоимость памяти не зависит от глубины вычислений. Кроме того, стоимость FLOP для функции, преобразованной в jvp , примерно в 3 раза выше стоимости простой оценки функции (одна единица работы для оценки исходной функции, например sin (x) ; одна единица для линеаризации, например cos (x) ; и один блок для применения линеаризованной функции к вектору, например cos_x * v ).Другими словами, для фиксированной начальной точки \ (x \) мы можем оценить \ (v \ mapsto \ partial f (x) \ cdot v \) примерно с той же предельной стоимостью, что и оценка \ (f \).

Эта сложность памяти звучит довольно убедительно! Так почему же в машинном обучении мы не часто видим форвард-режим?

Чтобы ответить на этот вопрос, сначала подумайте, как с помощью JVP построить полную матрицу Якоби. Если мы применим JVP к вектору с одним горячим касательным, он обнаружит один столбец матрицы Якоби, соответствующий ненулевой записи, которую мы ввели.п \). Построение этой матрицы по одному столбцу за раз, при каждом вызове с одинаковым количеством FLOP для оценки исходной функции, конечно, кажется неэффективным! В частности, для обучения нейронных сетей, где \ (f \) - функция потерь при обучении, а \ (n \) может быть в миллионах или миллиардах, этот подход просто не будет масштабироваться.

Чтобы добиться большего успеха в подобных функциях, нам просто нужно использовать реверсивный режим.

Векторно-якобианские произведения (VJP, также известные как автодифференцирование в обратном режиме)

Если прямой режим возвращает нам функцию для вычисления векторно-якобианских произведений, которую мы затем можем использовать для построения якобианских матриц по одному столбцу за раз, обратный режим - это способ вернуть функцию для оценки векторно-якобианских произведений ( эквивалентно якобиан-транспонированные векторные произведения), которые мы можем использовать для построения якобианских матриц по одной строке за раз.п \).

Соответствующее отображение котангенсных пространств часто называют откатом. из \ (f \) в \ (x \). Ключевым моментом для наших целей является то, что он идет от чего-то, похожего на вывод \ (f \), к чему-то, что выглядит как ввод \ (f \), как мы могли бы ожидать от транспонированной линейной функции.

VJP в коде JAX

При переключении с математики обратно на Python функция JAX vjp может принимать функцию Python для вычисления \ (f \) и возвращать нам функцию Python для оценки VJP \ ((x, v) \ mapsto (f (x ), v ^ \ mathsf {T} \ partial f (x)) \).

 из jax import vjp

# Изолируйте функцию от весовой матрицы до прогнозов
f = лямбда W: прогнозировать (W, b, входные данные)

у, vjp_fun = vjp (f, W)

ключ, подключ = random.split (ключ)
u = random.normal (подключ, y.shape)

# Оттяните ковектор `u` вдоль` f`, вычисленный в `W`
v = vjp_fun (u)
 

В терминах сигнатур типов, подобных Haskell, мы могли бы написать

 vjp :: (a -> b) -> a -> (b, CT b -> CT a)
 

, где мы используем CT a для обозначения типа пространства котангенса для a .n \ to \ mathbb {R} \), мы можем сделать это всего за один вызов. Вот почему grad эффективен для оптимизации на основе градиента, даже для таких целей, как функции потерь при обучении нейронной сети для миллионов или миллиардов параметров.

Однако есть цена: хотя FLOP дружественны, память масштабируется в зависимости от глубины вычислений. Кроме того, реализация традиционно более сложна, чем в прямом режиме, хотя у JAX есть некоторые хитрости в рукаве (это история для будущих ноутбуков!).

Подробнее о том, как работает обратный режим, см. В этом обучающем видео Летней школы глубокого обучения в 2017 году.

Векторные градиенты с VJP

Если вы хотите использовать векторные градиенты (например, tf.gradients ):

 из jax import vjp

def vgrad (f, x):
  у, vjp_fn = vjp (f, x)
  return vjp_fn (jnp.ones (y.shape)) [0]

print (vgrad (лямбда x: 3 * x ** 2, jnp.ones ((2, 2))))
 

Произведения вектора Гессе с использованием как прямого, так и обратного режима

В предыдущем разделе мы реализовали функцию произведения вектора Гессе, просто используя обратный режим (предполагая непрерывные вторые производные):

 def hvp (f, x, v):
    вернуть град (лямбда x: jnp.2 е (х) v \). 

Мы можем перевести это почти прямо в код:

 из jax import jvp, grad

# вперед-назад-назад
def hvp (f, прямые, касательные):
  вернуть jvp (grad (f), прямые, касательные) [1]
 

Еще лучше, поскольку нам не нужно было напрямую вызывать jnp.dot , эта функция hvp работает с массивами любой формы и с произвольными типами контейнеров (например, с векторами, хранящимися как вложенные списки / словари / кортежи), и не работает. Нет даже зависимости от jax.Яковлевский .

Вот пример того, как его использовать:

 def f (X):
  вернуть jnp.sum (jnp.tanh (X) ** 2)

ключ, подключ1, подключ2 = random.split (ключ, 3)
X = случайный.нормальный (подключ1, (30, 40))
V = random.normal (подключ2, (30, 40))

ans1 = hvp (f, (X,), (V,))
ans2 = jnp.tensordot (гессиан (f) (X), V, 2)

печать (jnp.allclose (ans1, ans2, 1e-4, 1e-4))
 

Другой способ, которым вы могли бы подумать о написании этого, - это использовать обратный переход вперед:

 # назад-вперед-вперед
def hvp_revfwd (f, прямые, касательные):
  g = прямые лямбда: jvp (f, прямые, касательные) [1]
  вернуть град (г) (первичные)
 

Это не так хорошо, однако, потому что прямой режим имеет меньше накладных расходов, чем обратный режим, и поскольку здесь оператор внешнего дифференцирования должен различать более крупные вычисления, чем внутренний, сохранение прямого режима снаружи работает лучше всего:

 # reverse-over-reverse, работает только для одиночных аргументов
def hvp_revrev (f, прямые, касательные):
  x, = основные
  v = касательные
  вернуть град (лямбда x: jnp.vdot (grad (f) (x), v)) (x)


print ("Вперед назад")
% timeit -n10 -r3 hvp (f, (X,), (V,))
print ("Назад вперед")
% timeit -n10 -r3 hvp_revfwd (f, (X,), (V,))
print ("Обратный через обратный")
% timeit -n10 -r3 hvp_revrev (f, (X,), (V,))

print («Наивная полная гессенская материализация»)
% timeit -n10 -r3 jnp.tensordot (гессиан (f) (X), V, 2)
 
 Вперед назад
3,77 мс ± 119 мкс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)
Назад вперед
 
 Самый медленный пробег занял 4.В 12 раз длиннее самого быстрого. Это может означать, что промежуточный результат кэшируется.
9,79 мс ± 7,04 мс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)
Обратный обратный
 
 Самый медленный пробег занял в 4,34 раза больше времени, чем самый быстрый. Это может означать, что промежуточный результат кэшируется.
13,9 мс ± 10,3 мс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)
Наивная полная гессенская материализация
 
 64,1 мс ± 368 мкс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)
 

Создание VJP, JVP и

vmap

Якобиан-матрица и матрица-якобиан произведения

Теперь, когда у нас есть преобразования jvp и vjp , которые дают нам функции для перемещения вперед или назад отдельных векторов за раз, мы можем использовать преобразование JAX vmap для одновременного нажатия и извлечения целых баз.В частности, мы можем использовать это для записи быстрых матрично-якобианских и якобиан-матричных произведений.

 # Изолировать функцию от весовой матрицы до прогнозов
f = лямбда W: прогнозировать (W, b, входные данные)

# Оттягиваем ковекторы `m_i` вдоль` f`, вычисленные как `W`, для всех` i`.
# Во-первых, воспользуйтесь списком, чтобы перебрать строки в матрице M.
def loop_mjp (f, x, M):
    у, vjp_fun = vjp (f, x)
    вернуть jnp.vstack ([vjp_fun (mi) для mi в M])

# Теперь используйте vmap для построения вычисления, которое выполняет одну быструю матрицу-матрицу
# умножение, а не внешний цикл векторно-матричного умножения.def vmap_mjp (f, x, M):
    у, vjp_fun = vjp (f, x)
    выходы, = vmap (vjp_fun) (M)
    возвратные выходы

ключ = random.PRNGKey (0)
num_covecs = 128
U = random.normal (ключ, (num_covecs,) + y.shape)

loop_vs = loop_mjp (f, W, M = U)
print ('Матрично-якобиево произведение без vmapped')
% timeit -n10 -r3 loop_mjp (f, W, M = U)

print ('\ nVmapped матрично-якобиево произведение')
vmap_vs = vmap_mjp (f, W, M = U)
% timeit -n10 -r3 vmap_mjp (f, W, M = U)

assert jnp.allclose (loop_vs, vmap_vs), 'Vmap и матрично-якобианские продукты без vmapped должны быть идентичны'
 
 Матрично-якобиево произведение без vmapped
 
 95.6 мс ± 412 мкс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)

Отображенное матрично-якобиево произведение
4,23 мс ± 106 мкс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)
 
 def loop_jmp (f, W, M):
    # jvp немедленно возвращает прямое и касательное значения в виде кортежа,
    # поэтому мы вычислим и выберем касательные в понимании списка
    return jnp.vstack ([jvp (f, (W,), (mi,)) [1] для mi в M])

def vmap_jmp (f, W, M):
    _jvp = лямбда s: jvp (f, (W,), (s,)) [1]
    вернуть vmap (_jvp) (M)

num_vecs = 128
S = случайный.нормальный (ключ, (num_vecs,) + W.shape)

loop_vs = loop_jmp (f, W, M = S)
print ('Якобиан-матричное произведение без отображения v')
% timeit -n10 -r3 loop_jmp (f, W, M = S)
vmap_vs = vmap_jmp (f, W, M = S)
print ('\ nVmapped якобиан-матричное произведение')
% timeit -n10 -r3 vmap_jmp (f, W, M = S)

assert jnp.allclose (loop_vs, vmap_vs), 'Продукты Vmap и не-vmapped Jacobian-Matrix должны быть идентичны'
 
 Якобиан-матричное произведение без v-отображения
 
 208 мс ± 836 мкс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)

Отображенное матричное произведение Якоби
2.38 мс ± 86,4 мкс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)
 

Реализация

jacfwd и jacrev

Теперь, когда мы увидели быстрые произведения на матрицу Якоби и матрицу Якоби, нетрудно догадаться, как записать jacfwd и jacrev . Мы просто используем ту же технику для одновременного продвижения или возврата всего стандартного базиса (изоморфного единичной матрице).

 из jax import jacrev как builtin_jacrev

def our_jacrev (f):
    def jacfun (x):
        у, vjp_fun = vjp (f, x)
        # Используйте vmap для создания матрично-якобиевого произведения.# Здесь матрица является евклидовым базисом, поэтому мы получаем все
        Сразу # записи в якобиане.
        J, = vmap (vjp_fun, in_axes = 0) (jnp.eye (len (y)))
        вернуть J
    вернуть jacfun

assert jnp.allclose (builtin_jacrev (f) (W), our_jacrev (f) (W)), 'Неверные результаты якобиана обратного режима!'
 
 из jax import jacfwd как builtin_jacfwd

def our_jacfwd (f):
    def jacfun (x):
        _jvp = лямбда s: jvp (f, (x,), (s,)) [1]
        Jt = vmap (_jvp, in_axes = 1) (jnp.eye (len (x)))
        вернуть jnp.транспонировать (Jt)
    вернуть jacfun

assert jnp.allclose (builtin_jacfwd (f) (W), our_jacfwd (f) (W)), 'Неверные результаты якобиана прямого режима!'
 

Интересно, что «Автоград» не смог этого сделать. Наша реализация якобиана в обратном режиме в Autograd должна была откатывать по одному вектору за раз с помощью карты внешнего цикла . Пропуск одного вектора через вычисление намного менее эффективен, чем пакетирование всего этого вектора вместе с vmap .

Еще одна вещь, которую Autograd не смог сделать, - это jit .Интересно, что независимо от того, насколько динамизм Python вы используете в своей функции для дифференциации, мы всегда можем использовать jit в линейной части вычислений. Например:

 def f (x):
    пытаться:
        если x <3:
            возврат 2 * x ** 3
        еще:
            поднять ValueError
    кроме ValueError:
        вернуть jnp.pi * x

y, f_vjp = vjp (f, 4.)
печать (jit (f_vjp) (1.))
 
 (DeviceArray (3,1415927, dtype = float32, weak_type = True),)
 

Комплексные числа и дифференцирование

JAX отлично подходит для комплексных чисел и дифференцирования.2 \), а именно

\ (\ begin {bmatrix} \ partial_0 u (x, y) & \ partial_1 u (x, y) \\ \ partial_0 v (x, y) & \ partial_1 v (x, y) \ end {bmatrix} \ begin {bmatrix} c \\ d \ end {bmatrix} \).

Чтобы получить JVP для исходной функции \ (f \), примененной к касательному вектору \ (c + di \ in \ mathbb {C} \), мы просто используем то же определение и идентифицируем результат как другое комплексное число,

\ (\ частичное е (х + у я) (с + д я) = \ begin {matrix} \ begin {bmatrix} 1 & i \ end {bmatrix} \\ ~ \ end {matrix} \ begin {bmatrix} \ partial_0 u (x, y) & \ partial_1 u (x, y) \\ \ partial_0 v (x, y) & \ partial_1 v (x, y) \ end {bmatrix} \ begin {bmatrix} c \\ d \ end {bmatrix} \).

Это наше определение JVP функции \ (\ mathbb {C} \ to \ mathbb {C} \)! Обратите внимание, не имеет значения, является ли \ (f \) голоморфным: JVP однозначно.

Вот чек:

Проверка
 def (seed):
  key = random.PRNGKey (начальное число)

  # случайные коэффициенты для u и v
  ключ, подключ = random.split (ключ)
  a, b, c, d = random.uniform (подключ, (4,))

  def fun (z):
    х, у = jnp.real (z), jnp.imag (z)
    вернуть u (x, y) + v (x, y) * 1j

  def u (x, y):
    вернуть a * x + b * y

  def v (x, y):
    вернуть c * x + d * y

  # основная точка
  ключ, подключ = случайный.разделить (ключ)
  x, y = random.uniform (подключ, (2,))
  г = х + у * 1j

  # касательный вектор
  ключ, подключ = random.split (ключ)
  c, d = random.uniform (подключ, (2,))
  z_dot = c + d * 1j

  # проверить jvp
  _, ans = jvp (веселье, (z,), (z_dot,))
  ожидаемый = (grad (u, 0) (x, y) * c +
              град (и, 1) (х, у) * д +
              град (v, 0) (x, y) * c * 1j +
              град (v, 1) (x, y) * d * 1j)
  print (jnp. * \; \ частичное е (х + у я) =
\ begin {matrix} \ begin {bmatrix} c & -d \ end {bmatrix} \\ ~ \ end {matrix}
\ begin {bmatrix} \ partial_0 u (x, y) & \ partial_1 u (x, y) \\ \ partial_0 v (x, y) & \ partial_1 v (x, y) \ end {bmatrix}
\ begin {bmatrix} 1 \\ -i \ end {bmatrix} \).

Что с негативами? Они просто позаботятся о сложном спряжении и о том, что мы работаем с ковекторами.

Вот проверка правил VJP:

Проверка
 def (seed):
  key = random.PRNGKey (начальное число)

  # случайные коэффициенты для u и v
  ключ, подключ = random.split (ключ)
  a, b, c, d = random.uniform (подключ, (4,))

  def fun (z):
    х, у = jnp.real (z), jnp.imag (z)
    вернуть u (x, y) + v (x, y) * 1j

  def u (x, y):
    вернуть a * x + b * y

  def v (x, y):
    вернуть c * x + d * y

  # основная точка
  ключ, подключ = случайный.разделить (ключ)
  x, y = random.uniform (подключ, (2,))
  г = х + у * 1j

  # котангенс вектор
  ключ, подключ = random.split (ключ)
  c, d = random.uniform (подключ, (2,))
  z_bar = jnp.array (c + d * 1j) # для управления dtype

  # проверить vjp
  _, fun_vjp = vjp (веселье, z)
  ans, = fun_vjp (z_bar)
  ожидаемый = (grad (u, 0) (x, y) * c +
              град (v, 0) (x, y) * (-d) +
              град (и, 1) (х, у) * с * (-1j) +
              град (v, 1) (x, y) * (-d) * (-1j))
  assert jnp.allclose (ans, ожидаемый, atol = 1e-5, rtol = 1e-5)
 
 чек (0)
в клетку (1)
в клетку (2)
 

А как насчет удобных оберток, таких как grad , jacfwd и jacrev ?

Напомним, что для функций \ (\ mathbb {R} \ to \ mathbb {R} \) мы определили grad (f) (x) как vjp (f, x) [1] (1.0) , который работает, потому что применение VJP к значению 1.0 показывает градиент (то есть якобиан или производную). Мы можем сделать то же самое для функций \ (\ mathbb {C} \ to \ mathbb {R} \): мы все еще можем использовать 1.0 в качестве котангенса вектора, и мы просто получаем результат комплексного числа, суммирующий полный якобиан :

 def f (z):
  х, у = jnp.real (z), jnp.imag (z)
  возврат x ** 2 + y ** 2

z = 3. + 4j
град (е) (г)
 
 DeviceArray (6.-8.j, dtype = complex64)
 

Для общих функций \ (\ mathbb {C} \ to \ mathbb {C} \) якобиан имеет 4 действительные степени свободы (как в матрицах Якоби 2x2 выше), поэтому мы не можем надеяться представить все из них в комплексном числе.Но мы можем для голоморфных функций! Голоморфная функция - это в точности функция \ (\ mathbb {C} \ to \ mathbb {C} \) со специальным свойством, что ее производная может быть представлена ​​как одно комплексное число. (Уравнения Коши-Римана гарантируют, что указанные выше якобианы 2x2 имеют особую форму матрицы масштабирования и поворота в комплексной плоскости, то есть действие одного комплексного числа при умножении.) И мы можем выявить это одно комплексное число, используя один звонок на vjp с ковектором 1.0 .

Поскольку это работает только для голоморфных функций, чтобы использовать этот трюк, нам нужно пообещать JAX, что наша функция голоморфна; в противном случае JAX вызовет ошибку, если grad используется для функции комплексного вывода:

 def f (z):
  вернуть jnp.sin (z)

z = 3. + 4j
grad (f, голоморфный = True) (z)
 
 DeviceArray (-27.034946-3.8511534j, dtype = complex64)
 

Все, что делает обещание holomorphic = True , - это отключает ошибку, когда вывод является комплексным.Мы все еще можем записать holomorphic = True , когда функция не голоморфна, но полученный нами ответ не будет представлять полный якобиан. Вместо этого это будет якобиан функции, в которой мы просто отбрасываем мнимую часть вывода:

 def f (z):
  вернуть jnp.conjugate (z)

z = 3. + 4j
grad (f, holomorphic = True) (z) # f на самом деле не голоморфен!
 
 DeviceArray (1.-0.j, dtype = complex64)
 

Вот несколько полезных апшотов о том, как работает grad :

  1. Мы можем использовать grad для голоморфных \ (\ mathbb {C} \ to \ mathbb {C} \) функций.

  2. Мы можем использовать grad для оптимизации функций \ (f: \ mathbb {C} \ to \ mathbb {R} \), таких как вещественные функции потерь комплексных параметров x , предпринимая шаги в направлении конъюгат grad (f) (x) .

  3. Если у нас есть функция \ (\ mathbb {R} \ to \ mathbb {R} \), которая просто использует некоторые комплексные операции внутри (некоторые из которых должны быть неголоморфными, например, БПФ, используемые в свертках) тогда grad все еще работает, и мы получаем тот же результат, который дала бы реализация, использующая только реальные значения.

В любом случае, JVP и VJP всегда однозначны. И если мы хотим вычислить полную матрицу Якоби неголоморфной функции \ (\ mathbb {C} \ to \ mathbb {C} \), мы можем сделать это с помощью JVP или VJP!

Вы должны ожидать, что комплексные числа будут работать везде в JAX. Вот дифференциация сложной матрицы с помощью разложения Холецкого:

 A = jnp.array ([[5., 2. + 3j, 5j],
              [2.-3j, 7., 1. + 7j],
              [-5j, 1.-7j, 12.]])

def f (X):
    L = jnp.linalg.cholesky (X)
    вернуть jnp.sum ((L - jnp.sin (L)) ** 2)

grad (f, голоморфный = True) (A)
 
 DeviceArray ([[- 0.7534186 + 0.j, -3.0509028 -10.940545j,
               5,9896846 + 3,542303j],
             [-3.0509028 + 10.940545j, -8.

1 + 0.j, -5.1351523 -6.559373j], [5.9896846 -3.542303j, -5.1351523 + 6.559373j, 0,01320427 + 0.j]], dtype = complex64)

Секретный соус, который делает фреймворки глубокого обучения такими мощными

В большинстве доступных фреймворков глубокого обучения лежит мощный метод, называемый автоматическим дифференцированием.Если вы когда-нибудь встречали эти слова, но не знаете, что они означают или как работает эта процедура, этот пост для вас.

В предыдущем посте мы увидели, как создать фреймворк глубокого обучения с помощью NumPy. В этом посте я упомянул, что мы можем реализовать вычисления на рабочем уровне и отслеживать градиенты. Это то, что мы назвали автоматическим дифференцированием .

Введение

Автоматическое дифференцирование - это числовой метод для автоматической оценки производных на основе набора операций.Как вы, возможно, помните из предыдущего поста, производные - это инструмент, который мы используем для вычисления градиента функции потерь, и мы используем этот градиент для обновления параметров нашей модели.

Независимо от того, насколько сложна модель глубокого обучения, ее можно резюмировать как набор элементарных операций, из которых получаются градиенты.

Под капотом самые популярные библиотеки глубокого обучения - это просто фреймворки автоматического дифференцирования . Давайте посмотрим на пример с PyTorch:

импортный фонарик


# обратите внимание, как мы заставляем PyTorch отслеживать градиенты
а = фонарик.one (1, requires_grad = True)
b = torch.zeros (1, requires_grad = True)

# проход вперед
с = а * б

# обратный проход
назад = c.backward ()

print (f "градиент: {a.grad} | b gradient: {b.grad}")
 

Приведенный выше код выводит следующую строку:

градиент: тензор ([0.]) | b градиент: тензор ([1.])
 

Правильно ли сделал PyTorch? Конечно, но давайте докажем:

Пусть c будет
$$
c (a, b) = a \ cdot b
$$

Тогда частные производные c по отношению к a и b равны:
$$
\ dfrac {\ partial c} {\ partial a} = b, \ quad \ dfrac {\ partial c} {\ partial b} = a
$$

Следовательно, вычисления, выполненные PyTorch, верны (меньшего мы не ожидали: P).

Теория

Как мы уже говорили, автоматическое дифференцирование преобразует программу в последовательность примитивных операций, называемую вычислительным графом или списками Венгерта , в которых указаны процедуры для вычисления соответствующих производных [Роджер Гросс].

Давайте посмотрим на более сложную функцию:

$$
d (a, b, c) = a \ cdot (b + c)
$$

Предположим, что $$ s (b, c) = (b + c) $$

Мы собираемся нарисовать вычислительный граф d ; то есть мы берем наше математическое выражение и записываем его в виде графика, где каждый узел соответствует определенной операции .

Расчетный график функции d.

Помните, что для каждой операции в прямом направлении. у нас есть обратная сторона. Обратный проход содержит производную операции, которую реализует узел, умноженную на градиент из следующих операций. Вы видите, что происходит? Каждый раз, когда мы оцениваем операцию в обратном режиме, мы применяем цепное правило! Если подумать об обратном распространении ошибки, это значительно облегчит понимание всего процесса.

PyTorch отслеживает операции и вычисляет производные каждой из них, применяя цепное правило для вычисления градиентов.

Обратное дифференцирование функции d .

Числовой пример с использованием PyTorch

Используя ту же функцию d , которую мы определили ранее, мы устанавливаем значение для переменных.

из torch.autograd импортная переменная


a = переменная (torch.Tensor ([2.2]), requires_grad = True)
b = переменная (torch.Tensor ([- 1.8]), requires_grad = True)
c = переменная (torch.Tensor ([0.1]), requires_grad = True)

# проход вперед
г = а * (Ь + с)

# обратный проход
назад = d.назад ()

print (f "градиент: {a.grad} | b gradient: {b.grad} | c gradient: {c.grad}")
 

Результирующие градиенты:

градиент: тензор ([- 1.7000]) | b градиент: тензор ([2.2000]) | c градиент: тензор ([2.2000])
 

Прямой проход на графике выглядит так:

Прямой проход функции d .

Обратный проход на графике выглядит так:

Обратный проход функции d .

Здесь нет ничего удивительного: наши теоретические расчеты совпадают с результатами PyTorch.

Строим с нуля

Чтобы закончить этот пост, мы пойдем еще глубже и создадим нашу собственную систему автодифференцирования.

Этот раздел содержит реализации 2 операций, отслеживающих градиент. Они предназначены для скалярных значений, хотя могут обрабатывать массивы NumPy поэлементно.

Мы начинаем определять базовый класс, который операции могут расширять.

класс _Operation:
    "" "Операция абстрактный класс.
    Операция принимает два операнда и вычисляет результат в "вперед"
    метод и градиент в «обратном» методе.Атрибуты
    ----------
    а: объект
        Первый операнд операции.
    b: объект
        Второй операнд операции.
    a_grad: объект
        Градиент первого операнда.
    b_grad: объект
        Градиент второго операнда
    
    "" "
    def __init __ (сам):
        # операнд
        self.a = Нет
        self.b = Нет
        
        # градиент операндов
        self.a_grad = Нет
        self.b_grad = Нет

    def __call __ (self, * args):
        вернуть себя.вперед (* аргументы)
    
    def вперед (self):
        проходить
 

Обратите внимание, что мы разрешаем только два операнда. Следующий шаг - для определения операций . Передний пас довольно прост. Обратный проход - это просто производная операции, умноженная на входящий градиент (если есть).

класс Добавить (_Operation):
    "" "Добавляет.
    
    Реализует операцию a + b и вычисляет ее градиент.
    
    "" "
    def __init __ (сам):
        super (Добавить, сам) .__ init __ ()
    
    def вперед (self, a, b):
        себя.а = а
        self.b = b
        
        вернуть np.add (a, b)
    
    def назад (self, incoming_grad = 1):
        self.a_grad = входящий_град * 1
        self.b_grad = входящий_град * 1
        
        вернуть self.a_grad, self.b_grad


класс Multiply (_Operation):
    "" "Умножается.
    
    Реализует операцию a * b и вычисляет ее градиент.
    
    "" "
    def __init __ (сам):
        super (Умножение, сам) .__ init __ ()
    
    def вперед (self, a, b):
        self.a = a
        self.b = b
        
        вернуть нп.умножить (а, б)
    
    def назад (self, incoming_grad = 1):
        self.a_grad = входящий_град * self.b
        self.b_grad = входящий_град * self.a
        
        вернуть self.a_grad, self.b_grad
 

Как видите, это действительно простая реализация. Следующие строки содержат пример:

а = 2,2
б = -1,8
с = 0,1

s = Добавить ()
d = Умножить ()

# проход вперед
res = d (a, s (b, c))

# градиент
dd_da, dd_ds = d.backward (incoming_grad = 1)
ds_db, ds_dc = s.backward (incoming_grad = dd_ds)

print (f "градиент: {dd_da} | b град: {ds_db} | c град: {ds_dc}")
 

Приведенный выше код выводит следующую строку:

град: -1.7 | б град: 2,2 | c град: 2.2
 

Мы сделали это! Теперь мы можем расширить эту структуру и построить другие операции, чтобы сделать ее более полной. Здесь вы можете найти чуть более полную библиотеку с большим количеством вариантов вычислений.

Выводы

В этом посте мы увидели, что такое автоматическая дифференциация и как ее используют фреймворки глубокого обучения. Мы даже создали нашу собственную базовую и многословную, но все еще работающую структуру autodiff.

Более продвинутые библиотеки для выполнения этих задач можно найти в разделе «Ссылки», а также в других ресурсах.Я рекомендую вам проверить эти ссылки и попробовать разные библиотеки, чтобы понять, какие инструменты вы можете найти на рынке.

Как различать с компьютером

Автоматическая дифференциация использовалась как минимум 40 лет, а затем с тех пор была заново открыта и применена в различных формах. Однако, похоже, это не так хорошо известно, как следовало бы. ...

Введение

Хотя это может показаться удивительным и даже загадочным, мы все знаем, что математические идеи, берущие начало в нашем человеческом воображении, могут помочь нам решить проблемы, которые мы видим в окружающем нас мире.Реже признается, что заставить математическую идею эффективно работать может быть непросто.

Метод Ньютона представляет собой знакомый пример.

Предположим, у нас есть функция $ f (x) $, и мы хотим найти точку $ r $, где $ f (r) = 0 $, как показано на рисунке.

Мы делаем первоначальное предположение $ x_0 $ относительно местонахождения $ r $.

Затем мы строим линеаризацию $ y = L (x) $ для функции $ y = f (x) $ в точке, соответствующей $ x_0 $.Решение уравнения $ f (x) = 0 $ может быть трудным, но решить линейное уравнение $ L (x) = 0 $ просто.

Нетрудно увидеть, что решение уравнения $ L (x) = 0 $ есть $$ x_1 = x_0 - \ frac {f (x_0)} {f '(x_0)}. $$ Затем мы повторяем этот процесс, линеаризуя в $ x_1 $ и снова решая, чтобы найти $$ x_2 = x_1 - \ frac {f (x_1)} {f '(x_1)}.

$

Если мы сделали разумное первоначальное предположение $ x_0 $ и продолжаем таким же образом, мы создадим последовательность $ \ {x_n \} $, где $$ x_ {n + 1} = x_n - \ frac {f ( x_n)} {f '(x_n)}, $$, сходящаяся к корню $ r $; то есть $ x_n \ to r $.Таким образом, мы можем найти корень $ r $ с любой желаемой степенью точности.

Предположим теперь, что мы хотим автоматизировать этот процесс, создав программу, которая эффективно реализует метод Ньютона для функции $ f $, предоставленной пользователем. Наша программа должна вычислить значения как функции $ f $, так и ее производной $ f '$ в точках $ x_n $.

У нас есть несколько вариантов вычисления производной $ f '$. Во-первых, мы могли бы попросить систему компьютерной алгебры, такую ​​как Mathematica, Matlab или Sage, вычислить производную $ f '$ символически, а затем вычислить $ f' $ в точках $ x_n $.Однако у этого подхода есть несколько недостатков. Во-первых, нахождение производной символически, а затем вычисление результирующего выражения может быть дорогостоящим в вычислительном отношении. Это особенно верно, если у нас есть приложение, требующее более высокой производной. Во-вторых, нам нужно иметь возможность написать символическое выражение для функции. Если значения функции появляются в результате вычислительного алгоритма, может быть трудно или даже невозможно выразить $ f $ символически.

Второй подход состоит в том, чтобы оценить производную численно, используя, скажем, центральную разность $$ f '(x_j) \ приблизительно \ frac {f (x_j + h) -f (x_j-h)} {2h} $$ для небольшое значение $ h $.x $ и аппроксимируем $ f '(0) = 1 $, используя центральную разность, находим:

$ h $ $ \ displaystyle \ frac {f (h) -f (-h)} {2h} $
1e-12 1.00000008274
1e-13 1.00003338943
1e-14 0,999755833675
1e-15 0,999200722163
1e-16 1.05471187339

Мы бы предпочли метод, который оценивает производную в точке за тот же промежуток времени и с той же точностью, с которой мы оцениваем функцию в точке. Тема этого столбца, известная как автоматическое или алгоритмическое дифференцирование , предоставляет именно такой метод.

Автоматическая дифференциация использовалась не менее 40 лет, а затем была открыта заново и с тех пор применялась в различных формах.2 = -1 $. Так же, как кольцо комплексных чисел может быть представлено кольцом $ 2 \ times2 $ матриц, имеющих вид $ \ left [\ begin {array} {cc} a & -b \\ b & a \\ \ end {array} \ right], $ мы можем представить кольцо двойственных чисел, используя матрицы $ 2 \ times2 $ вида $ \ left [\ begin {array} {cc} a & 0 \\ b & a \\ \ end {array} \ справа] $. 2} \ epsilon.{п-1} б \ эпсилон.

$

Это предполагает, что мы расширим определение вещественной функции $ f (x) $ до двойственных чисел $ a + b \ epsilon $, где $ f $ дифференцируемо в $ a $, как $$ f (a + b \ epsilon ) = f (a) + f '(a) b \ epsilon.

$

Многие известные свойства производных совместимы с этим определением.

  • Правило продукта: Если $ f (x) = g (x) h (x) $, то $$ \ begin {align} f (a + b \ epsilon) & {} = {} g (a + b \ epsilon) h (a + b \ epsilon) \\ & {} = {} \ left (g (a) + g '(a) b \ epsilon \ right) \ left (h (a) + h' (a ) b \ epsilon \ right) \\ & {} = {} g (a) h (a) + \ left (g '(a) h (a) + g (a) h' (a) \ right) b \ epsilon, \\ \ end {align} $$, что дает нам правило произведения: $ f '(a) = g' (a) h (a) + g (a) h '(a) $.

  • Цепное правило: Аналогично, если у нас есть составная функция $ f (x) = g (h (x)) $, то $$ \ begin {align} f (a + b \ epsilon) & {} = { } g \ left (h (a + b \ epsilon) \ right) \\ & {} = {} g \ left (h (a) + h '(a) b \ epsilon \ right) \\ & {} = {} g (h (a)) + g '(h (a)) h' (a) b \ epsilon, \\ \ end {align} $$, что приводит к правилу цепочки: $ f '(a) = g '(h (a)) h' (a) $.

2,44.3343365935839], [44.3343365935839,14.7781121978613]], [[44.3343365935839,14.7781121978613], [14.7781121978613,7.38

9893065]]]

Обратите внимание на избыточные значения, вызванные различной симметрией тензоров.Библиотека и старается вычислить каждая отдельная производная только один раз, лениво и для того, чтобы поделиться полученным вычислением.

Обзор

Модули

  • Numeric.AD выполняет вычисления с использованием любого режима или их комбинации, подходящей для каждого отдельного комбинатора. Этот режим используется по умолчанию, повторно экспортируется с помощью Numeric.AD
  • Numeric.AD.Mode.Forward обеспечивает базовый AD прямого режима. Это хорошо для вычисления простых производных.
  • Numeric.AD.Mode.Sparse вычисляет разреженную башню AD прямого режима. Это хорошо для более высоких производных или большого количества выходов.
  • Numeric.AD.Mode.Kahn выполняет вычисления с AD в обратном режиме. Это хорошо для вычисления нескольких выходов при большом количестве входов.
  • Numeric.AD.Mode.Reverse выполняет вычисления с AD в обратном режиме. Это хорошо для вычисления нескольких выходов при большом количестве входов, когда не используется много искр.
  • Numeric.AD.Mode.Tower вычисляет плотную прямую AD-башню, полезную для высших производных функций с одним входом.
  • Numeric.AD.Newton предоставляет ряд комбинаторов для поиска корня с использованием метода Ньютона с квадратичной сходимостью.
  • Numeric.AD.Halley предоставляет ряд комбинаторов для поиска корней с использованием метода Галлея с кубической сходимостью.
  • Numeric.AD.Rank1. * предоставляет комбинаторы для AD, которые имеют строго ранг 1.Это упрощает их переворачивание и искажение с помощью функций более высокого порядка за счет безопасности типов, когда дело доходит до бесконечно малой путаницы.

Комбинаторы

Хотя не каждый режим может обеспечить все операции, поддерживаются следующие основные операции, измененные соответствующим образом с помощью суффиксов, приведенных ниже:

  • grad вычисляет градиент (вектор частных производных в заданной точке) функции.
  • якобиан вычисляет матрицу Якоби функции в точке.
  • diff вычисляет производную функции в точке.
  • du вычисляет производную функции в точке по направлению.
  • hessian вычисляет матрицу Гессе (матрицу вторых частных производных) функции в точке.

Комбинатор Суффиксы

Следующие суффиксы изменяют значение вышеперечисленных функций следующим образом:

  • ' также вернуть ответ
  • With позволяет пользователю указать функцию для смешивания ввода с выводом
  • F - это версия базовой функции, поднятая для возврата результата Traversable (или Functor ).
  • s означает, что функция возвращает все производные более высокого порядка в списке или с f-ветвлением Stream
  • T означает, что результат переносится относительно традиционной формулировки (обычно, чтобы не платить за перенос обратно)
  • 0 означает, что результирующий список производных дополнен нулями в конце.
  • NoEq означает, что возвращается бесконечный список сходящихся значений, а не усечение списка, когда они становятся постоянными.

Сообщения и отчеты об ошибках приветствуются!

Свяжитесь со мной через github или IRC-канал #haskell на irc.freenode.net.

- Эдвард Кметт

Автоматическая дифференциация

Переключение режимов AD

Turing поддерживает четыре пакета автоматического дифференцирования (AD) в бэкенде во время выборки.Бэкэнд AD по умолчанию - ForwardDiff для AD прямого режима. Также поддерживаются три серверных модуля AD обратного режима, а именно Tracker, Zygote и ReverseDiff. Zygote и ReverseDiff поддерживаются дополнительно, если явно загружены пользователем с с использованием Zygote или с использованием ReverseDiff рядом с с использованием Turing .

Для переключения между различными бэкэндами AD можно вызвать функцию Turing.setadbackend (backend_sym) , где backend_sym может быть : forwarddiff ( ForwardDiff ), : трекер ( Tracker ), : zygote ( Zygote ) или : reversediff ( ReverseDiff.jl ). При использовании ReverseDiff , чтобы скомпилировать ленту только один раз и кэшировать ее для дальнейшего использования, пользователю необходимо сначала загрузить Memoization.jl с , используя Memoization , затем вызвать Turing.setrdcache (true) . Однако обратите внимание, что использование кеширования в определенных типах моделей может привести к неверным результатам и / или ошибкам. Модели, для которых скомпилированная лента может быть безопасно кэширована, - это модели с циклами фиксированного размера и без выполняемых операторов if. Операторы if во время компиляции в порядке.Чтобы очистить кеш, вы можете вызвать Turing.emptyrdcache () .

Композиционная выборка с разными режимами AD

Turing поддерживает смешанные методы автоматического дифференцирования для различных пространств переменных. В приведенном ниже фрагменте показано использование ForwardDiff для выборки среднего параметра ( м ) и использование автодиффа TrackerAD на основе трекера для параметра дисперсии ( с ):

  с использованием Тьюринга

# Определить простую нормальную модель с неизвестным средним значением и дисперсией.@model функция gdemo (x, y)
    s² ~ InverseGamma (2, 3)
    м ~ Нормальный (0, sqrt (s²))
    x ~ Нормальный (м, кв (с²))
    y ~ Нормальный (м, кв (с²))
конец

# Пример с использованием Гиббса и различных бэкендов autodiff.
c = образец (
gdemo (1.5, 2),
  Гиббс (
    HMC {Turing.ForwardDiffAD {1}} (0,1, 5,: m),
        HMC {Turing.TrackerAD} (0,1, 5,: s)
    ),
    1000,
)
  

Как правило, TrackerAD работает быстрее при выборке из переменных высокой размерности (больше 20), а ForwardDiffAD более эффективен для переменных меньшей размерности.Эта функция позволяет тем, кто чувствителен к производительности, настроить автоматическую дифференциацию для своих конкретных моделей.

Если метод дифференцирования не указан таким образом, Тьюринг по умолчанию будет использовать любой глобальный бэкэнд AD. В настоящее время по умолчанию используется значение ForwardDiff .

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Теперь мы можем использовать это.2 + 2 \ cdot 3 \ epsilon \\ & {} = {} 9 + 6 \ epsilon. \ end {align} $$ Тогда $$ \ begin {align} v & {} = {} \ sin (u) \\ & {} = {} \ sin (9 + 6 \ epsilon) \\ & {} = {} \ sin (9) + 6 \ cos (9) \ epsilon, \ end {align} $$ и, наконец, $$ \ begin {align} w & {} = {} x \ sin (v) \\ & { } = {} (3+ \ epsilon) (\ sin (9) +6 \ cos (9) \ epsilon) \\ & {} = {} 3 \ sin (9) + (\ sin (9) + 18 \ соз (9)) \ эпсилон. \ end {align} $$ Таким образом, мы вычислили как $ f (3) = 3 \ sin (9) $, так и $ f '(3) = \ sin (9) + 18 \ cos (9) $ с помощью одного вычисление.2) $, а затем все еще необходимо вычислить $ f '(3) $. Двойные числа обеспечивают тот же результат с той же точностью, минуя символическое вычисление $ f '(x) $.

Более того, эту технику легко реализовать во многих объектно-ориентированных языках программирования, используя оператор , перегрузивший . Сначала мы определяем тип данных, моделирующий двойные числа, а затем расширяем определение простых операторов, таких как + , * , sin , exp , log и т. Д., Чтобы принимать двойные числа.Поскольку любую функцию можно написать, объединив эти операторы, тогда можно написать простой код, например

   
    x = 3 + Эпсилон
    напечатать x * sin (x ** 2)
   
 

Поскольку этот процесс проходит по графику функции в том же порядке, в котором мы оцениваем функцию, мы называем это прямым режимом автоматического дифференцирования. Позже мы познакомимся с обратным режимом.

Еще одно простое расширение позволяет нам вычислять градиенты функций с несколькими переменными.Рассмотрим, например, функцию $ f (x, y, z) = xy \ sin (yz) $, градиент которой мы хотим вычислить как $ (x, y, z) = (3, -1,2) $. Мы устанавливаем $$ \ begin {align} x & {} = {} 3 + \ epsilon [1,0,0] \\ y & {} = {} -1 + \ epsilon [0,1,0] \\ z & {} = {} 2 + \ epsilon [0,0,1]. \\ \ end {align} $$

Это приводит к $$ \ begin {align} t {} = {} & \ left (3+ \ epsilon [1,0,0] \ right) \ left (-1+ \ epsilon [0,1,0] \ right) = -3 + \ epsilon [-1,3,0] \\ \\ u {} = {} & \ left (-1+ \ epsilon [0,1,0] \ right) \ left (2 + \ epsilon [0,0,1] \ right) = -2 + \ epsilon [0,2, -1] \\ \\ v {} = {} & \ sin \ left (-2+ \ epsilon [0 , 2, -1] \ right) = \ sin (-2) + \ epsilon \ cos (-2) [0,2, -1] \\ \\ w {} = {} & \ left (-3+ \ epsilon [-1,3,0] \ right) \ left (\ sin (-2) + \ epsilon \ cos (-2) [0,2, -1] \ right) \\ {} = {} & -3 \ sin (-2) + \\ & \ epsilon [- \ sin (-2), 3 \ sin (-2) -6 \ cos (-2), 3 \ cos (-2)].\\ \ end {align} $$

Таким образом, мы видим, что $$ \ begin {align} f (3, -1,2) & {} = {} -3 \ sin (-2) \\ \ nabla f (3, -1,2) & { } = {} [- \ sin (-2), 3 \ sin (-2) -6 \ cos (-2), 3 \ cos (-2)]. \\ \ end {align} $$

Как и раньше, это также легко реализуется во многих ваших любимых языках программирования с помощью перегрузки операторов. Если $ f $ является функцией $ n $ переменных, объем вычислений, требуемых здесь, примерно в $ n + 1 $ умножен на сумму, необходимую для простой оценки функции.

Комментарии ?

Высшие производные

Что, если мы хотим найти высшие производные функции $ f (x) $? Мы можем расширить эти идеи, рассуждая в терминах полиномов Тейлора.2) $ и $ g '(x) $.

Обратный режим автодифференцирования

Ранее мы продемонстрировали, как найти градиент многомерной функции, используя прямой режим автоматического дифференцирования. Если есть $ n $ переменных, то объем вычислений примерно в $ n + 1 $ умножается на объем работы, необходимой для оценки самой функции. Обратный режим автоматического дифференцирования обеспечивает более эффективный способ нахождения частных производных.

Давайте посмотрим на наш предыдущий пример функции $ f (x, y, z) = xy \ sin (yz) $ и найдем частные производные в точке $ (3, -1,2) $.

Сначала мы просматриваем график в прямом направлении, чтобы оценить вспомогательные переменные.

Теперь мы вводим так называемые сопряженные переменные для записи частных производных верхнего узла по отношению к другим узлам. Например, $$ \ begin {align} \ bar {x} & {} = {} \ frac {\ partial w} {\ partial x} \\ \ bar {u} & {} = {} \ frac {\ partial w} {\ partial u} \\ \ end {выровнено} $$ Теперь мы спустимся вниз по графику, начиная с $ \ bar {w} = \ frac {\ partial w} {\ partial w} = 1 $.Затем $$ \ begin {align} \ bar {v} & {} = {} \ frac {\ partial w} {\ partial v} = t = -3 \\ \ bar {t} & {} = {} \ frac {\ partial w} {\ partial t} = v = \ sin (-2) \\ \ bar {u} & {} = {} \ frac {\ partial w} {\ partial v} \ frac {\ partial v} {\ partial u} = \ bar {v} \ cos (u) = - 3 \ cos (-2) \\ \ bar {x} & {} = {} \ frac {\ partial w} {\ partial t} \ frac {\ partial t} {\ partial x} = \ bar {t} y = - \ sin (-2) \\ \ end {align} $$, поэтому мы находим, что $ \ frac {\ partial w} {\ partial x} = - \ sin (-2) $. Таким же образом $$ \ begin {align} \ bar {y} & {} = {} \ frac {\ partial w} {\ partial t} \ frac {\ partial t} {\ partial y} + \ frac {\ partial w} {\ partial u} \ frac {\ partial u} {\ partial y} \\ & {} = {} \ bar {t} x + \ bar {u} z \\ & {} = { } 3 \ sin (-2) -6 \ cos (-2) \\ \ end {align} $$ и, наконец, $$ \ bar {z} = \ frac {\ partial w} {\ partial u} \ frac { \ partial u} {\ partial z} = \ bar {u} y = 3 \ cos (-2).

$

Хотя есть несколько способов реализовать обратный режим, мы просто опишем здесь один. Мы можем сформировать систему линейных уравнений, по одному для каждой сопряженной переменной, перемещаясь по графику функции. Предполагая, что мы находим частные производные в $ (x, y, z) = (3, -1,2) $, мы имеем $$ \ begin {align} \ bar {x} & {} = {} - \ бар {t} \\ \ bar {y} & {} = {} 3 \ bar {t} + 2 \ bar {u} \\ \ bar {z} & {} = {} - \ bar {u} \ \ \ bar {t} & {} = {} v \ bar {w} \\ \ bar {u} & {} = {} \ cos (u) \ bar {v} \\ \ bar {v} & { } = {} 3 \ bar {w} \\ \ bar {w} & {} = {} 1. T.$ Поскольку $ A $ является верхнетреугольной матрицей, эту проблему легко решить обратной подстановкой. Фактически, $ A $ обычно является разреженной матрицей, что означает, что уравнение может быть легко решено для $ {\ mathbf x} $.

Проделав некоторую работу, можно показать, что усилия, необходимые для выполнения вычислений в обратном режиме, всегда меньше, чем в четыре раза усилий, необходимых для оценки функции. Когда функция имеет много переменных, это дает значительную экономию по сравнению с прямым режимом.

Комментарии ?

Сводка

Это было очень краткое введение в теорию автоматического дифференцирования. В частности, мы не коснулись многих вопросов, связанных с реализацией этих идей в вычислительной среде. Это довольно активная область исследований, которую можно изучить в приведенных ниже ссылках.

Мы также не описали многочисленные и разнообразные применения автоматического дифференцирования, хотя не должно удивлять то, что метод для эффективного и точного вычисления производных будет исключительно полезен.Использование включает оптимизацию, градиентный спуск и анализ чувствительности. Действительно, Ник Трефетен включает автоматическое дифференцирование в свой список из 29 великих числовых алгоритмов.

Математики справедливо описывают свою дисциплину как теоретические инструменты для решения важных реальных проблем. Однако разрыв между теорией и ее использованием не всегда незначителен. В этой статье мы надеемся осветить пример того, что требуется, чтобы восполнить этот пробел.

Список литературы

  • Андреас Греванк и Андреа Вальтер. Оценка производных: принципы и методы алгоритмической дифференциации , второе издание, SIAM, Филадельфия. 2008.

  • Ричард Д. Нейдингер. Введение в автоматическое дифференцирование и объектно-ориентированное программирование MATLAB. Обзор SIAM , Vol. 52, No. 3, 545-563. 2010.

    Этот обзор предмета включает идеи по введению автоматического дифференцирования в класс численного анализа бакалавриата.

  • Луи Б. Ралл. Перспективы автоматической дифференциации: прошлое, настоящее и будущее? в Автоматическая дифференциация: приложения, теория и реализации , Bücker et al (редакторы), 1-14. Спрингер, Берлин. 2006.

  • Шон Форт, Пол Ховланд, Эрик Фиппс, Жан Утке и Андреа Вальтер (редакторы) Последние достижения в области алгоритмической дифференциации. Springer, Берлин, 2012 г.

  • Андреас Гриванк. Кто изобрел обратный способ дифференциации? Documenta Math , дополнительный том ISMP, 389-400. 2012.

  • Ник Трефетен. Кто изобрел величайшие числовые алгоритмы? 2005.

  • Портал сообщества для автоматического различения.

    Широкий выбор ресурсов для тех, кто хочет узнать больше об автоматическом различении, его использовании и реализациях.

Комментарии ?

объявлений: автоматическое дифференцирование

Пакет, который предоставляет интуитивно понятный API для автоматической дифференциации (AD) в Haskell. Автоматическое дифференцирование позволяет вычислять производные функции при ее оценке. В отличие от численных методов, основанных на запуске программы с несколькими входами или символических подходах, автоматическое дифференцирование обычно снижает производительность только на небольшой множитель.

AD использует тот факт, что любая программа y = F (x) , которая вычисляет одно или несколько значений, делает это путем составления нескольких примитивных операций. Если (частные) производные каждой из этих операций известны, то их можно составить, чтобы получить ответ для производной всей программы в точке.

Эта библиотека содержит в своей основе единственную реализацию, которая описывает, как вычислять частные производные широкого набора примитивных операций. Затем он предоставляет API, который позволяет пользователю безопасно комбинировать их с использованием стандартных функций высшего порядка, как и с любым другим числовым типом Haskell.

Есть несколько способов составить эти отдельные матрицы Якоби. Мы скрываем выбор, используемый API, за явным типом-классом «Mode» и универсальной количественной оценкой. Это не позволяет пользователям сбивать с толку бесконечно малые величины. Если вы хотите рискнуть бесконечно малой путаницей, чтобы получить большую гибкость в том, как вы карри, переворачиваете и обычно комбинируете дифференциальные операторы, то модули Rank1. * , вероятно, вам подойдут.

Характеристики

  • Предоставляет комбинаторы AD прямого и обратного режимов с общим API.
  • Дополнительный "брендинг" на уровне типа доступен, чтобы конечный пользователь не сбивал с толку бесконечно малые числа.
  • Каждый режим имеет отдельный модуль, полный комбинаторов, с одинаковым внешним видом.

Примеры

Вы можете вычислять производные функций

  Prelude Numeric.AD> diff sin 0 {- cos 0 -}
1.0
  

Или и ответ, и производная функции:

  Prelude Numeric.AD> diff '(exp.журнал) 2
(2.0,1.0)
  

Вы можете вычислить производную функции с постоянным параметром, используя auto :

  Prelude Numeric.AD> let t = 2.0 :: Double
Prelude Numeric.AD> diff (\ x -> auto t * sin x) 0
2.0
  

Для получения символьных производных можно использовать символьный числовой тип, например, из простого отражения :

  Prelude Debug.SimpleReflect Numeric.AD> diff atanh x
получатель (1 - х * х) * 1
  

Вы можете вычислять градиенты для функций, которые принимают нескалярные значения в форме Traversable функтора, полного переменных AD.

  Prelude Numeric.AD Debug.SimpleReflect> grad (\ [x, y, z] -> x * sin (x + log y)) [x, y, z]
[0 + (0 + sin (x + log y) * 1 + 1 * (0 + cos (x + log y) * (0 + x * 1)))
, 0 + (0 + получатель y * (0 + 1 * (0 + cos (x + log y) * (0 + x * 1))))
, 0
]
  

, который можно упростить до:

  [sin (x + log y) + cos (x + log y) * x, получатель y * cos (x + log y) * x, 0]
  

Если вам нужно несколько производных, вы можете рассчитать их с помощью различий :

  Prelude Numeric.AD> возьмите 10 $ diffs sin 1
[0,8414709848078965,0,5403023058681398, -0,8414709848078965, -0,5403023058681398,0,8414709848078965,0,5403023058681398, -0,8414709848078965, -0,540652305868139848078965]
  

, или если ваша функция принимает несколько входных данных, вы можете использовать grads, который возвращает «f-ветвящийся поток» производных, который вы можете лениво осматривать. Несколько более интуитивно понятные ответы можно получить, преобразовав поток в полиморфно рекурсивный Тип данных Jet .Таким образом, мы можем рассматривать только один «слой» ответа за раз:

Ответ:

  Prelude Numeric.AD> headJet $ jet $ grads (\ [x, y] -> exp (x * y)) [1,2]
7,38

9893065

Градиент:

  Prelude Numeric.AD> headJet $ tailJet $ jet $ grads (\ [x, y] -> exp (x * y)) [1,2]
[14.7781121978613,7.38

9893065]

Гессиан (матрица 2-х производных n * n)

  Prelude Numeric.AD> headJet $ tailJet $ tailJet $ jet $ grads (\ [x, y] -> exp (x * y)) [1,2]
[[29.5562243957226,22.16716829679195], [22.16716829679195,7.38

9893065]]

Или даже тензоры производных более высокого порядка в виде струи.

  Prelude Numeric.AD> headJet $ tailJet $ tailJet $ tailJet $ jet $ grads (\ [x, y] -> exp (x * y)) [1,2]
[[[59.1124487