Автомат диф: Что такое дифавтомат и для чего его применяют?

Содержание

Что такое дифавтомат и для чего его применяют?

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

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

Устройство и принцип действия

Для начала приведем обозначение на схеме по ГОСТ, по которому наглядно видно, из чего состоит дифавтомат:


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

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

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

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

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

На корпусе указывается порог срабатывания дифференциального трансформатора — ток утечки в мА, номинальный ток теплового расцепителя (при котором работает неограниченное время) в А. Пример маркировки на корпусе — С16 А / 30 мА. В данном случае маркировка “С” перед значением номинала показывает кратность срабатывания электромагнитного расцепителя (класс аппарата). Буква “С” указывает, что электромагнитный расцепитель сработает при превышении номинала 16А в 5-10 раз.

Область применения

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

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

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

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

Источник: сайт Сам электрик.

Автоматический выключатель, дифференциальный автомат и УЗО: в чем отличие?

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

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

От чего защищают.

Неисправности в электрической цепи чаще всего вызваны тремя основными факторами:

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

2. Токи утечек. Возникают, когда нарушена изоляция. При случайном возникновении цепей на земле.

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

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

Отличие по назначению.

Автоматические выключатели.

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

Электромагнитная катушка – она отключает токи напряжения и способствует гашению электрической дуги.

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

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

УЗО (устройство защитного отключения).

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

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

Но нюанс в том, что само защитное устройство не застраховано от перегрузов и коротких замыканий. Поэтому его устанавливают в комплексе с автоматическим выключателем.

Дифференциальный автомат.

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

Внешние отличия.

Габариты.

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

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

Маркировка.

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

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

Дополнительные сведения.

Монтаж.

Легко монтируется как один модуль, так и два. Отличие только в том, что установка двух аппаратов займет больше времени. Основные трудности возникают при подключении проводов. УЗО и «дифференциалки» подключаются только к нулю и фазе. А вот автоматический выключатель требует дополнительного объема работы: придется прокладывать перемычки.

Долговечность.

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

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

Вывод.

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

Как отличить Дифференциальный автомат от УЗО?

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

Как работает дифференциальный автоматический выключатель (диф. автомат)?

Теперь поговорим о диф.автомате (дифференциальной защите тока и общей защите). Прибор предназначен для защиты цепи от утечки тока (аналогично работе Узо), но преимущество диф. автомата заключается в том, что в него встроен автоматический выключатель, который выполняет функцию защиты цепи от коротких замыканий и перегрузок. Два в одном: УЗО+ Автоматический выключатель= Дифференциальный автомат. Получился своего рода технический симбиоз.

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

Если под обычным Узо устанавливают 3 или 4 группы отдельных автоматических выключателей, то диф.автомат обеспечивает отдельную группу для защиты электрической цепи. Под диф.автоматом не устанавливают автоматические выключатели, он несет самостоятельную ответственность за короткое замыкание (КЗ), перегрузку электрической цепи и утечку тока в землю. Можно конечно и поставить автоматические выключатели под диф. автоматом, но это расточительно.

Читайте следующие статьи про УЗО:

Где устанавливают дифференциальные автоматические выключатели?

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

Диф.автомат-надежная заЩИТа!

Что нужно учесть устанавливая дифференциальный автоматический выключатель?

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

Обязательно прочитайте следующую статью про установку реле «Почему нужно устанавливать реле контроля напряжения?»

Оцените качество статьи:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Итоги

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

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

Что нужно сделать, чтобы проверить дифференциальный автомат и УЗО

Что нужно сделать, чтобы проверить дифференциальный автомат и УЗО

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

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

Принцип действия УЗО и дифавтомата и их отличия

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

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

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

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

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

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

Способы проверки

Как вы уже догадались — методика проверки срабатывания УЗО и дифавтомата на утечку аналогична. На лицевой панели и одного и другого прибора есть флажок включения/выключения и кнопка «ТЕСТ». Согласно ПТЭЭП прил. 3, табл. 28, п.28.7 нужно проверять срабатывание с помощью этой кнопки не реже чем раз в квартал (3 месяца).

Важно:

Кнопка «ТЕСТ» проверяет только срабатывание прибора по дифференциальному току или току утечки, но не проверяет срабатывание по превышению номинального тока у дифавтомата.

Есть 5 основных способов проверки:

— с помощью кнопки «ТЕСТ»;

— с помощью батарейки;

— с помощью магнита;

— резистором

— специализированным прибором.

Проверка с помощью кнопки «ТЕСТ»

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

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

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

Проверка с помощью батарейки и магнита

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

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

Примечание: УЗО типа «А» срабатывает при любой полярности, а типа «AC» — только при определенной полярности – переворачивайте батарейку!

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

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

ВАЖНО:

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

Проверка с помощью резистора или лампочки

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

Для начала рассчитайте номинал резистора под величину дифференциального тока срабатывания. Например, очень распространены УЗО с током срабатывания в 30 мА, значит условно представим, что в сети 220 вольт (реальные значение измеряйте непосредственно на объекте где будет установлен прибор). Значит нужно взять резистор на:

220/0.030=7333.33 Ом

Мощность на резисторе выделится кратковременно (порядка 6 Ватт), но тем не менее будет лучше если вы выберете как можно более мощный резистор.

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

Таким же образом и работает кнопка «ТЕСТ».

ВАЖНО:

При такой проверке УЗО должно быть подключено к сети.

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

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

Заключение

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

— Sonel MRP-200;

— ПЗО-500;

— ПЗО-500 Про.

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

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

Нормы: Согласно ПТЭЭП проверка выключателей дифференциального тока должна осуществляться в соответствии с рекомендациями завода изготовителя. В среднем они включают в себя проверку перемещения флажка «ВКЛ/ВЫКЛ». Он должен четко переключаться из одного положения в другое, а также 1 раз в указанный период проходить проверку нажатием кнопки «ТЕСТ» (но не реже 1 раза в квартал, согласно ПТЭЭП). Ток срабатывания должен быть не менее чем 0.5In (для УЗО на 30 мА — это 15 мА), другие допустимые величины описаны в ГОСТ Р50571.16-99.

Ранее ЭлектроВести писали, почему бьет током одежда, мебель, машина и окружающие предметы.

По материалам: electrik.info.

Дифференциальный автомат — это… Что такое Дифференциальный автомат?

Двухполюсное УЗО с номинальным током 100 А

Устройство защитного отключения (УЗО; более точное название: Устройство защитного отключения, управляемое дифференциальным (остаточным) током, сокр. УЗО−Д) — механический коммутационный аппарат или совокупность элементов, которые при достижении (превышении) дифференциальным током заданного значения при определённых условиях эксплуатации должны вызвать размыкание контактов. Может состоять из различных отдельных элементов, предназначенных для обнаружения, измерения (сравнения с заданной величиной) дифференциального тока и замыкания и размыкания электрической цепи (разъединителя)[1].

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

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

Назначение

УЗО предназначены для

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

Цели и принцип работы

схема УЗО и принцип работы

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

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

В США, в соответствии с National Electrical Code, устройства защитного отключения (ground fault circuit interrupter — GFCI), предназначенные для защиты людей, должны размыкать цепь при утечке тока 4-6 мА (точное значение выбирается производителем устройства и обычно составляет 5 мА) за время не более 25 мс. Для устройств GFCI, защищающих оборудование (то есть не для защиты людей), отключающий дифференциальный ток может составлять до 30 мА. В Европе используются УЗО с отключающим дифференциальным током 10-500 мА.

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

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

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

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

Пример

Внутреннее устройство УЗО, подключаемого в разрыв шнура питания

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

  • УЗО со вспомогательным источником питания
  • выполняющим автоматическое отключение при отказе вспомогательного источника

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

Фазный и нулевой проводники от источника питания подключаются к контактам (1), нагрузка УЗО подключается к контактам (2). Проводник защитного заземления (PE-проводник) к УЗО никак не подключается.

При нажатии кнопки (3) контакты (4) (а также еще один контакт, скрытый за узлом (5)) замыкаются, и УЗО пропускает ток. Соленоид (5) удерживает контакты в замкнутом состоянии после того, как кнопка отпущена.

Катушка (6) на тороидальном сердечнике является вторичной обмоткой дифференциального трансформатора тока, который окружает фазный и нулевой проводники. Проводники проходят сквозь тор, но не имеют электрического контакта с катушкой[2]. В нормальном состоянии ток, текущий по фазному проводнику, точно равен току, текущему по нулевому проводнику, однако эти токи противоположны по направлению. Таким образом, токи взаимно компенсируют друг друга и в катушке дифференциального трансформатора тока ЭДС отсутствует.

Любая утечка тока из защищаемой цепи на заземленные проводники (например, прикосновение человека, стоящего на мокром полу, к фазному проводнику) приводит к нарушению баланса в трансформаторе тока: через фазный проводник «втекает больше тока», чем возвращается по нулевому (часть тока утекает через тело человека, то есть помимо трансформатора). Несбалансированный ток в первичной обмотке трансформатора тока приводит к появлению ЭДС во вторичной обмотке. Эта ЭДС сразу же регистрируется следящим устройством (7), которое отключает питание соленоида (5). Отключенный соленоид больше не удерживает контакты (4) в замкнутом состоянии, и они размыкаются под действием силы пружины, обесточивая неисправную нагрузку.

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

Кнопка проверки (8) позволяет проверить работоспособность устройства путем пропускания небольшого тока через оранжевый тестовый провод (9). Тестовый провод проходит через сердечник трансформатора тока, поэтому ток в тестовом проводе эквивалентен нарушению баланса токонесущих проводников, то есть УЗО должно отключиться при нажатии на кнопку проверки. Если УЗО не отключилось, значит оно неисправно и должно быть заменено.

Применение

В России применение УЗО стало обязательным с принятием 7-го издания Правил устройства электроустановок (ПУЭ). Выдержки из документов, регламентирующих применение УЗО, собраны здесь. Как правило, в случае бытовой электропроводки одно или несколько УЗО устанавливаются на DIN-рейку в электрощите.

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

Проверка

Рекомендуется ежемесячно проверять работоспособность УЗО. Наиболее простой способ проверки — нажатие кнопки «тест», которая обычно расположена на корпусе УЗО (как правило, на кнопке «тест» нанесено изображение большой буквы «Т»). Тест кнопкой может производиться пользователем, то есть квалифицированный персонал для этого не требуется. Если УЗО исправно и подключено к электрической сети, то оно при нажатии кнопки «тест» должно сразу же сработать (то есть отключить нагрузку). Если после нажатия кнопки нагрузка осталась под напряжением, то УЗО неисправно и должно быть заменено.

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

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

Ограничения

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

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

История

В начале 1970-х годов большинство УЗО выпускались[3] в корпусах типа автоматических выключателей. С начала 1980-х годов большинство бытовых УЗО были уже встроенными в розетки. В России используются преимущественно УЗО для монтажа в электрощите на DIN-рейку, а встроенные УЗО пока широкого распространения не получили.

Классификация УЗО

По способу действия

  • УЗО−Д без вспомогательного источника питания
  • УЗО−Д со вспомогательным источником питания:
    • выполняющие автоматическое отключение при отказе вспомогательного источника с выдержкой времени и без нее:
      • производящие автоматическое повторное включение при восстановлении работы вспомогательного источника
      • не производящие автоматическое повторное включение при восстановлении работы вспомогательного источника
    • не производящие автоматическое отключение при отказе вспомогательного источника:
      • способные произвести отключение при возникновении опасной ситуации после отказа вспомогательного источника
      • не способные произвести отключение при возникновении опасной ситуации после отказа вспомогательного источника

По способу установки

  • стационарные с монтажом стационарной электропроводкой
  • переносные с монтажом гибкими проводами с удлинителями

По числу полюсов

  • однополюсные двухпроводные
  • двухполюсные
  • двухполюсные трехпроводные
  • трехполюсные
  • трехполюсные четырехпроводные
  • четырехполюсные

По виду защиты от сверхтоков и перегрузок по току

  • без встроенной защиты от сверхтоков
  • со встроенной защитой от сверхтоков
  • со встроенной защитой от перегрузки
  • со встроенной защитой от коротких замыканий

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

На стадии рассмотрения

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

  • нерегулируемые
  • регулируемые:
    • с дискретным регулированием
    • с плавным регулированием

По стойкости при импульсном напряжении

  • допускающие возможность отключения при импульсном напряжении
  • стойкие при импульсном напряжении

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

  • УЗО−Д типа АС
  • УЗО−Д типа А
  • УЗО−Д типа В

Характеристики УЗО

Характеристики, общие для всех УЗО−Д

  • Способ установки
  • Число полюсов и число токоведущих проводников
  • Номинальный ток In — указанное изготовителем значение тока, которое УЗО−Д может пропускать в продолжительном режиме работы
  • Номинальный отключающий дифференциальный ток IΔn — указанное изготовителем значение дифференциального тока, которое вызывает отключение УЗО−Д при заданных условиях эксплуатации
  • Номинальный неотключающий дифференциальный ток, если он отличается от предпочтительного значения IΔn0 — указанное изготовителем значение дифференциального тока, которое не вызывает отключения УЗО−Д при заданных условиях эксплуатации
  • Тип УЗО−Д по характеристикам наличия постоянной составляющей дифференциального тока
  • Номинальное напряжение Un — указанное изготовителем действующее значение напряжения, при котором обеспечивается работоспособность УЗО−Д (в частности при коротких замыканиях)
  • Номинальная частота — значение частоты, на которое рассчитано УЗО−Д и при котором оно работоспособно при заданных условиях эксплуатации
  • Тип вспомогательного источника (если он имеется) и реакция УЗО−Д на его отказ
  • Номинальное напряжение вспомогательного источника (если он имеется) Usn — напряжение вспомогательного источника, на которое рассчитано УЗО−Д и при котором обеспечивается его работоспособность при заданных условиях эксплуатации
  • Номинальная включающая и отключающая способность Im — действующее значение ожидаемого тока, который УЗО−Д способно включить, пропускать в течение своего времени и отключить при заданных условиях эксплуатации без нарушения его работоспособности
  • Номинальная способность включения и отключения дифференциального тока IΔm — действующее значение ожидаемого дифференциального тока, который УЗО−Д способно включить, пропускать в течение своего времени отключения и отключить при заданных условиях эксплуатации без нарушения его работоспособности
  • Выдержка времени (если она имеется)
  • Селективность (если она имеется)
  • Координация изоляции, включая воздушные зазоры и пути утечки тока
  • Степень защиты (по ГОСТ 14254)

Только для УЗО−Д без встроенной защиты от коротких замыканий

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

Смотри также

Примечания

  1. Определение согласно ГОСТ Р 50807-95 (2003)
  2. То есть катушка гальванически развязана от токонесущих проводников УЗО
  3. За рубежом. В России УЗО начали применяться гораздо позже — примерно с 1994—1995 годов

Ссылки

Wikimedia Foundation. 2010.

Дифференциальный автомат. Виды и работа. Устройство

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

Дифференциальный автомат

Разделение дифавтоматов на виды осуществляется по их характеристикам.

Тип электрической сети

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

Параметры тока

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

В быту популярными стали дифавтоматы С16. Остальные виды используются реже. Ток утечки обозначается символом Δ, а справа от этого символа указывается ток в миллиамперах. В цепях освещения чаще всего используются дифавтоматы с номинальным значением тока утечки 10-30 мА. Из них для одиночных сетей применяют автоматы на 10 мА, а в групповых сетях на 30 мА. Защита с номинальным током утечки 100-300 мА применяется для входных дифавтоматов.

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

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

По параметру тока, при котором срабатывает защита при запуске мощных потребителей, дифференциальные автоматы делятся на типы:
  • В – выдерживает перегрузку от 3 до 5 раз.
  • С – перегрузка от 5 до 10 раз.
  • D – отключение питания происходит при возрастании тока от 10 до 20 раз.

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

Класс защиты

Этот параметр означает, на какие виды токов реагирует дифференциальный автомат.

AC — Для синусоидального переменного тока
A  — Для синусоидального переменного и пульсирующего постоянного
B  — Для переменного, импульсного, постоянного и сглаженного постоянного
S  — Выдержка времени отключения 200-300 мс
G  — Выдержка времени отключения 60-80 мс

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

Класс ограничения тока и отключающей способности

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

Класс токоограничения имеет цифровое обозначение:
  • 1 – медленный.
  • 2 – средний.
  • 3 – быстрый.

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

Условия эксплуатации

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

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

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

Внутреннее устройство

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

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

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

Устройство и принцип работы

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

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

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

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

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

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

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

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

Похожие темы:

Автоматическое дифференцирование и двойное число в прямом режиме | Роберт Ланге

Автоматическая дифференциация (AD) — одна из движущих сил истории успеха глубокого обучения. Это позволяет нам эффективно вычислять оценки градиента для наших любимых составных функций. TensorFlow, PyTorch и все предшественники используют AD. Наряду с методами стохастической аппроксимации, такими как SGD (и все его варианты), эти градиенты уточняют параметры наших любимых сетевых архитектур.

Многие люди (до недавнего времени включая меня) считают, что обратное распространение, правило цепочки и автоматическое дифференцирование являются синонимами. Но это не так. Чтобы стать настоящими мастерами своего дела, мы должны понять, почему. 🔥

TL; DR : Мы обсуждаем различные способы дифференциации компьютерных программ. В частности, мы сравниваем автоматическое дифференцирование в прямом и обратном (обратном) режимах. В конечном итоге мы реализуем AD прямого режима с двойными числами для решения простой задачи логистической регрессии.Обычный цифровой код можно найти здесь .

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

Аналитическое выражение можно легко преобразовать в некоторый код Python:

Функция вычисляет числовое значение на основе фиксированные истинные метки ( y_true ) и предсказанные / подогнанные вероятности меток ( y_pred ).В нашем случае y_pred составляет выходной сигнал со сжатием сигмовидной формы, который снова является функцией β. Чтобы найти наиболее подходящие коэффициенты, нам нужно следовать направлению наискорейшего спуска (также известного как градиент), которое минимизирует функцию потерь. Для этого у нас есть доступ к набору методов дифференциации:

  1. Ручная дифференциация (🙌): Как уже можно заметить, ручная дифференциация требует, чтобы производная была определена на листе бумаги. Впоследствии эту производную можно реализовать в коде.Это чревато «математическими» ошибками и (по крайней мере, для меня) отнимает довольно много времени. Удачи в попытках разобраться в глубокой сети.
  2. Числовое дифференцирование (💻): Вместо того, чтобы запачкать руки правилами цепочки и частного, можно просто попытаться аппроксимировать градиент, используя два бесконечно малых разных входа. Тем самым мы приближаем формальное определение производной. Это имеет два основных недостатка: требует многократных оценок функций (по крайней мере, дважды для каждого входного измерения) и подвержен ошибкам округления, а также ошибкам усечения (входные данные никогда не бывают одинаковыми).С другой стороны, это очень легко реализовать.
  3. Символьное дифференцирование (🈂): Символьные методы применяют преобразования, которые соответствуют правилам дифференцирования, чтобы получить выражение для производной. Это реализовано в программном обеспечении, таком как Mathematica, и требует серьезных алгебраических манипуляций. Составление функций рискует привести к чрезмерно сложным символическим представлениям производной. Это обычно называют «вздутие живота».В конечном итоге это может привести к произвольно дорогостоящим оценкам градиента.
  4. Автоматическое дифференцирование (🔁): вместо увеличения до бесконечности AD упрощает выражение производной в любой возможный момент времени. Например после каждой операции! Всю математику можно рассматривать как композицию конечного набора основных операций (сложение, умножение, возведение в степень и т. Д.). И для таких операций мы уже знаем функциональную форму производной. Благодаря красоте правила цепочки мы можем объединить эти элементарные производные и уменьшить сложность выражения за счет хранения в памяти.

По своей сути AD объединяет в себе лучшее, что есть как в числовом, так и в символическом мире. Он вычисляет значение производной с помощью набора элементарных правил от символического дифференцирования. Чтобы преодолеть опухоль, символическое выражение упрощается на каждом этапе. Просто численно оценивая результаты предыдущих вычислений (или просто входные данные). Следовательно, он не дает аналитического выражения для самой производной. Вместо этого он итеративно оценивает данные градиента.Проще говоря: f ’(2) ≠ f’ (x).

Давайте посмотрим, как это применимо к нашей задаче логистической регрессии, и определим пошаговые результаты как a (h) = σ (h) и h (X, β) = X β. Затем мы можем переписать интересующий градиент как:

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

  1. Предварительные активации h (X, β) и их градиент ∇h (X, β) относительно параметров β .
  2. Активации a (h) и их градиент ∇a (h) относительно предварительных активаций h.
  3. Журнал вероятностей класса log a (h) и диагональная матрица градиента ∇log a (h) относительно активаций a.

Для каждого из частных оценок h (X, β), a (h), log a (h) мы можем легко вычислить чувствительность к их соответствующим входным данным β, h, a и получить их производные. В конечном итоге истинный вектор вероятности p обеспечивает сигнал ошибки, который масштабирует градиент.

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

  1. Накопительный режим в прямом направлении (⏩): Режим простого выдвижения применяет правило цепочки Лейбница к каждой базовой операции в прямом первичном преобразовании . трассировка .Таким образом, получается производная трасса . На каждом этапе мы оцениваем оператора, а также его градиент «синхронно»!
  • Первичный след: h (X, β) → a (h) → log a (h)
  • Производный след: ∇h (X, β) → ∇a (h) → ∇log a (h)
  • Оценка Lockstep + производная:

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

  1. Обратный накопительный режим (⏪): Обратный режим, с другой стороны, не вычисляет производные одновременно, а требует двух отдельных фаз.Во время прямой фазы все промежуточные переменные оцениваются и их значения сохраняются в памяти. В следующей обратной фазе мы затем распространяем обратно производные / сопряженные с помощью снова цепного правила. Обратный режим AD — это то, что мы обычно называем обратным распространением (Rumelhart et al., 1988) в глубоком обучении.
  • Прямая фаза: h (X, β) → a (h) → log a (h)
  • Обратная фаза: ∇log a (h) → ∇a (h) → ∇h (X, β). Итак, как мы узнаем, как отправить градиент? Нам нужна схема бухгалтерского учета, которая обеспечивается заранее заданным вычислительным графом , который определяет поток операций.

При сравнении режимов работы необходимо учитывать два основных момента:

  1. Хранение в памяти и время вычисления : в прямом режиме мы должны хранить производные, в то время как в обратном режиме AD требуется только сохранение активаций. В то время как в прямом режиме AD вычисляет производную одновременно с оценкой переменной, обратное распространение делает это в отдельной обратной фазе.
  2. Размерность входа и выхода : Учитывая функцию f, мы можем различать два режима в зависимости от размеров, которые будут обрабатываться:
  • n << m: Размер входа меньше, чем выходной.Применяемые операции расширяют размерность с набора нескольких единиц. → Прямой режим в вычислительном отношении дешевле, чем обратный режим.
  • n >> m: входной размер больше выходного. Это классическая установка глубокого обучения. Мы получаем скалярную оценку потерь от прямого прохода и возвращаемся к входу довольно большой размерности. → Обратный режим вычислительно дешевле, чем прямой режим.

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

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

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

с вещественными числами v, v̇, ≠ 0 и ϵ² = 0. На основе этого простого определения получаются следующие основные арифметические свойства:

Кроме того, одно можно алгебраически вывести следующее:

Вау! Оценивая f (x) в двойственной форме и устанавливая v̇ = 1, мы можем восстановить как значение функции f (v), так и ее вычисленную производную f ’(v) в виде коэффициента перед! Наконец, цепное правило плавно переводится в двойную настройку:

Это означает, что мы можем легко распространять градиенты по уровням вычислений, просто умножая производные друг на друга.Для реализации двойных чисел нам просто нужна отдельная система хранения, которая отслеживает x = (v, coeff-in-front-of-v̇) и применяет соответствующие вычисления производной к двойственной части x. Потрясающая алгебра!

Для многомерных функций все становится немного сложнее. Представьте себе два входа:

Частная производная по x вычисляется путем задания v = 1 и u = 0. Для y мы должны перевернуть оба бита. Чтобы сделать это параллельно и предотвратить несколько прямых проходов, мы можем векторизовать вещи и сохранить диагональную матрицу:

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

Так что осталось обсудить, как думать о ϵ? Две интуиции, которые я позаимствовал из этого сообщения в блоге, следующие:

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

Вычисление ϵ x ϵ затем дает требуемую нулевую матрицу.Ограничивая мнимые числа i² = -1, помогите нам в вычислении вращения. С другой стороны, двойные числа ограничивают ϵ² = 0 и позволяют проводить эффективную и точную оценку производной. Давайте посмотрим, как мы можем преобразовать это в код для нашего примера логистической регрессии.

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

Давайте сгенерируем данные!

Теперь давайте определим «двойное мясо» вещей. Нам нужно убедиться, что все наши элементарные операции (сложение, умножение, активация сигмоида, а также логарифм, необходимый для градиента) действуют как на действительную, так и на двойную часть двойного представления вектора (для которого требуется градиент ). Следовательно, нам нужна двойная оболочка и перегрузка / переопределение операторов.

Давайте настроим несколько операций с двойными числами.

Двойная версия сигмоидной функции применяет стандарт σ к действительной части и изменяет числовое значение двойной матрицы размерности n x d на ее вычисленную производную. Поскольку σ ’(h) = σ (h), (1 — σ) применяется к каждому элементу вектора h. Следовательно, общее изменение двойственной части дается формулой:

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

Простой проход «вперед» и оценка функции двойных потерь

Наконец, давайте положим все вместе в последнем цикле обучения.Мы генерируем двоичные данные и инициализируем некоторые списки заполнителей для хранения наших промежуточных результатов. После этого мы вычисляем коэффициенты решения Sklearn, чтобы измерить, как далеко мы находимся. Затем мы можем просто перебрать отдельные партии. Мы инициализируем коэффициенты как двойной тензор, образцы пакетов, устанавливаем коэффициенты градиента / диагональную матрицу обратно в их инициализацию частной производной. Получаем прогнозы и проигрыш. Двойная оценка потерь соответствует интересующему градиенту ∇ L .Затем обновления SGD просто берут дуал и делают шаг в направлении наискорейшего спуска.

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

Запустите цикл обучения!

И какой сюрприз получается, что теория. Потери уменьшаются с увеличением количества обработанных пакетов. Коэффициенты сходятся к решению Sklearn и точности обучения небесным ракетам. Ганнибал из A-Team сказал: «Мне нравится, когда план слагается».

Мы уже обсуждали, почему обратное распространение и обратный режим AD более эффективны для стандартных приложений глубокого обучения.Одна из причин, по которой AD в прямом режиме все еще может пригодиться, — это его полезность при вычислении произведений вектора Гессе, Hv. Мы можем использовать конфигурацию назад-вперед-вперед , чтобы объединить как прямой, так и обратный режим для вычисления гессиана 2-го порядка. Более конкретно, учитывая функцию f со входом x, мы можем просто использовать оба режима вместе:

  1. Прямой режим: вычислить произведение вектора градиента ∇ fv , установив ẋ = v.
  2. Обратный режим: возьмите результат и примените обратное распространение к нему: ∇²fv = Hv

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

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

В целом, я нашел чрезвычайно приятным и очень полезным реализовывать что-то с нуля. Я совершенно по-другому думаю о текущих библиотеках DL, а также об их проблемах (например, статические и динамические вычислительные графы, хранение и вычисления). Я рекомендую заинтересованному читателю внимательнее ознакомиться с отличным обзором Baydin et al. (2018). Этот документ был моей отправной точкой и дает очень читаемый обзор! Также вы можете найти весь код здесь.

  1. Байдин А.Г., Б.А. Перлмуттер, А.А. Радул и Дж. М. Сискинд. (2018): «Автоматическая дифференциация в машинном обучении: обзор», Журнал исследований в области машинного обучения , 18.
  2. Рамелхарт, Д. Э., Г. Э. Хинтон, Р. Дж. Уильямс и другие. (1988): «Изучение представлений путем обратного распространения ошибок», Когнитивное моделирование , 5, 1.

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

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

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

В этом руководстве вы изучите способы вычисления градиентов с помощью 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.Переменная (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 . Чтобы вычислить несколько градиентов за одно вычисление, создайте градиентную ленту с постоянным значением = True . Это позволяет многократно вызывать метод gradient по мере высвобождения ресурсов при сборке мусора для объекта ленты.Например:

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

print (tape.gradient (z, x) .numpy ()) # 108.0 (4 * x ** 3 при x = 3)
print (tape.gradient (y, x) .numpy ()) # 6.0 (2 * x)
  
[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.constant (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)

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

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

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

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

  x = tf.constant (10)

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

печать (g.gradient (y, x))
  
ПРЕДУПРЕЖДЕНИЕ & columbus; tensorflow & col; тип 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 зарегистрированы как как недифференцируемые и вернут None . У других градиент не зарегистрирован .

Страница 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 (изображение, дельта)

пытаться:
  печать (tape.gradient (новое_изображение, [изображение, дельта]))
  assert False # Этого не должно происходить.кроме LookupError как e:
  print (f '{type (e) .__ name__}: {e}')
  
LookupError & двоеточие; В реестре градиентов нет записи для & coli; 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)
 

Расширенная автоматическая дифференциация | TensorFlow Core

Руководство «Введение в градиенты и автоматическое различение» включает все необходимое для расчета градиентов в TensorFlow.В этом руководстве основное внимание уделяется более глубоким и менее распространенным функциям API tf.GradientTape .

Настройка

Примечание: Для этого учебника требуется только пакет tf-nightly для документирования изменений пользовательского градиента SavedModel, доступных в TensorFlow 2.6.
  pip удалить tenorflow keras -y 
  pip install tf-nightly 
 
  импортировать тензорный поток как tf

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

mpl.rcParams ['рисунок.figsize '] = (8, 6)
  

Управление записью градиента

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

На ленте также есть способы манипулировать записью.

Остановить запись

Если вы хотите остановить запись градиентов, вы можете использовать tf.GradientTape.stop_recording , чтобы временно приостановить запись.

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

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

с tf.GradientTape () как t:
  x_sq = х * х
  с t.stop_recording ():
    y_sq = y * y
  z = x_sq + y_sq

grad = t.gradient (z, {'x': x, 'y': y})

print ('dz / dx:', grad ['x']) # 2 * x => 4
print ('dz / dy:', grad ['y'])
  
dz / dx & двоеточие; tf.Tensor (4.0, shape = (), dtype = float32)
дз / ди и двоеточие; Никто
 

Сброс / начало записи с нуля

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

  x = tf. Переменная (2.0)
y = tf. переменная (3,0)
reset = True

с tf.GradientTape () как t:
  y_sq = y * y
  если сбросить:
    # Выбросьте всю записанную кассету.
    t.reset ()
  г = х * х + y_sq

grad = t.gradient (z, {'x': x, 'y': y})

print ('dz / dx:', grad ['x']) # 2 * x => 4
print ('dz / dy:', grad ['y'])
  
dz / dx & двоеточие; tf.Тензор (4.0, shape = (), dtype = float32)
дз / ди и двоеточие; Никто
 

Прецизионная остановка градиентного потока

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

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

с tf.GradientTape () как t:
  y_sq = y ** 2
  z = x ** 2 + tf.stop_gradient (y_sq)

град = т.градиент (z, {'x': x, 'y': y})

print ('dz / dx:', grad ['x']) # 2 * x => 4
print ('dz / dy:', grad ['y'])
  
dz / dx & двоеточие; tf.Tensor (4.0, shape = (), dtype = float32)
дз / ди и двоеточие; Никто
 

Пользовательские градиенты

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

  1. Нет определенного градиента для новой операции, которую вы пишете.
  2. Расчеты по умолчанию численно нестабильны.
  3. Вы хотите кэшировать дорогостоящие вычисления из прямого прохода.
  4. Вы хотите изменить значение (например, используя tf.clip_by_value или tf.math.round ) без изменения градиента.

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

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

Вот пример, который применяет tf.clip_by_norm к промежуточному градиенту:

  # Установить операцию идентификации, но обрезать во время градиентного прохода.
@ tf.custom_gradient
def clip_gradients (y):
  def назад (dy):
    вернуть tf.clip_by_norm (dy, 0.5)
  вернуть y, назад

v = tf. переменная (2.0)
с tf.GradientTape () как t:
  output = clip_gradients (v * v)
print (t.gradient (output, v)) # вызывает "назад", что обрезает 4 до 2
  
tf.Тензор (2.0, shape = (), dtype = float32)
 

Дополнительные сведения см. В документации API декоратора tf.custom_gradient .

Пользовательские градиенты в SavedModel

Примечание. Эта функция будет доступна в TensorFlow 2.6.

Пользовательские градиенты можно сохранить в SavedModel с помощью параметра tf.saved_model.SaveOptions (экспериментальный_custom_gradients = True) .

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

  класс MyModule (tf.Module):

  @ tf.function (input_signature = [tf.TensorSpec (None)])
  def call_custom_grad (self, x):
    вернуть clip_gradients (x)

модель = MyModule ()
  
  tf.saved_model.save (
    модель,
    'сохраненная_модель',
    options = tf.saved_model.SaveOptions (экспериментальный_custom_gradients = True))

# Загруженные градиенты будут такими же, как в приведенном выше примере.
v = tf. переменная (2.0)
загружен = tf.saved_model.load ('сохраненная_модель')
с tf.GradientTape () как t:
  вывод = загружен.call_custom_grad (v * v)
print (t.gradient (вывод, v))
  
ИНФОРМАЦИЯ & двоеточие; тензорный поток & двоеточие; Ресурсы, записанные в & двоеточие; сохраненная_модель / активы
tf.Tensor (2.0, shape = (), dtype = float32)
 

Примечание о приведенном выше примере: если вы попытаетесь заменить приведенный выше код на tf.saved_model.SaveOptions (экспериментальный_custom_gradients = False) , градиент по-прежнему будет давать тот же результат при загрузке. Причина в том, что реестр градиентов все еще содержит настраиваемый градиент, используемый в функции call_custom_op .Однако, если вы перезапустите среду выполнения после сохранения без настраиваемых градиентов, запуск загруженной модели под tf.GradientTape выдаст ошибку: LookupError: не определен градиент для операции IdentityN (тип операции: IdentityN) .

Несколько лент

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

Например, здесь каждая лента наблюдает за своим набором тензоров:

  x0 = tf.постоянная (0,0)
x1 = tf.constant (0,0)

с tf.GradientTape () как tape0, tf.GradientTape () как tape1:
  tape0.watch (x0)
  tape1.watch (x1)

  y0 = tf.math.sin (x0)
  y1 = tf.nn.sigmoid (x1)

  у = у0 + у1

  ys = tf.reduce_sum (y)
  
  tape0.gradient (ys, x0) .numpy () # cos (x) => 1.0
  
1.0
 
  tape1.gradient (ys, x1) .numpy () # сигмоид (x1) * (1-сигмоид (x1)) => 0,25
  
0,25
 

Градиенты высшего порядка

Операции внутри контекстного менеджера tf.GradientTape записываются для автоматического различения.Если градиенты вычисляются в этом контексте, то вычисление градиента также записывается. В результате тот же API работает и для градиентов более высокого порядка.

Например:

  x = tf.Variable (1.0) # Создать переменную Tensorflow, инициализированную значением 1.0

с tf.GradientTape () как t2:
  с tf.GradientTape () как t1:
    у = х * х * х

  # Вычисляем градиент во внешнем диспетчере контекста `t2`
  # что означает, что вычисление градиента также является дифференцируемым.dy_dx = t1.gradient (y, x)
d2y_dx2 = t2.градиент (dy_dx, x)

print ('dy_dx:', dy_dx.numpy ()) # 3 * x ** 2 => 3.0
print ('d2y_dx2:', d2y_dx2.numpy ()) # 6 * x => 6.0
  
dy_dx & двоеточие; 3.0
d2y_dx2 & двоеточие; 6.0
 

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

«Вложенные вызовы к tf.GradientTape.gradient » — хороший шаблон, когда вы вычисляете скаляр из градиента, а затем полученный скаляр действует как источник для вычисления второго градиента, как в следующем примере.

Пример: регуляризация входного градиента

Многие модели подвержены «состязательным примерам». Этот набор методов изменяет входные данные модели, чтобы запутать выходные данные модели. В простейшей реализации — например, в примере Adversarial с использованием атаки метода Fast Gradient Signed Method — делается один шаг по градиенту выходных данных по отношению к входным; «входной градиент».

Одним из методов повышения устойчивости к состязательным примерам является регуляризация входного градиента (Finlay & Oberman, 2019), которая пытается минимизировать величину входного градиента. Если входной градиент небольшой, то изменение на выходе тоже должно быть небольшим.

Ниже представлена ​​простая реализация регуляризации входного градиента. Реализация:

  1. Рассчитайте градиент выхода по отношению к входу, используя внутреннюю ленту.
  2. Рассчитайте величину этого входного градиента.
  3. Рассчитайте градиент этой величины по отношению к модели.
  x = tf.random.normal ([7, 5])

layer = tf.keras.layers.Dense (10, активация = tf.nn.relu)
  
  с tf.GradientTape () как t2:
  # Внутренняя лента принимает только градиент относительно входа,
  # не переменные.
  с tf.GradientTape (watch_accessed_variables = False) как t1:
    t1.watch (x)
    y = слой (x)
    out = tf.reduce_sum (слой (x) ** 2)
  # 1. Рассчитайте входной градиент.g1 = t1.gradient (out, x)
  # 2. Рассчитайте величину входного градиента.
  g1_mag = tf.norm (g1)

# 3. Рассчитайте градиент величины по отношению к модели.
dg1_mag = t2.gradient (g1_mag, layer.trainable_variables)
  
  [var.shape для var в dg1_mag]
  
[TensorShape ([5, 10]), TensorShape ([10])]
 

Якобиане

Во всех предыдущих примерах использовались градиенты скалярной цели относительно некоторого исходного тензора (ов).

Матрица Якоби представляет собой градиенты векторной функции. Каждая строка содержит градиент одного из элементов вектора.

Метод tf.GradientTape.jacobian позволяет эффективно вычислять матрицу Якоби.

Обратите внимание:

  • Как gradient : Аргумент sources может быть тензором или контейнером тензоров.
  • В отличие от градиента : целевой тензор должен быть одним тензором.

Скалярный источник

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

  x = tf.linspace (-10.0, 10.0, 200 + 1)
дельта = tf. переменная (0,0)

с tf.GradientTape () в качестве ленты:
  y = tf.nn.sigmoid (x + дельта)

dy_dx = tape.jacobian (y, дельта)
  

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

  принт (г.форма)
печать (dy_dx.shape)
  
(201,)
(201,)
 
  plt.plot (x.numpy (), y, label = 'y')
plt.plot (x.numpy (), dy_dx, label = 'dy / dx')
plt.legend ()
_ = plt.xlabel ('x')
  

Источник тензор

Независимо от того, является ли вход скалярным или тензорным, tf.GradientTape.jacobian эффективно вычисляет градиент каждого элемента источника по отношению к каждому элементу цели (целей).

Например, результат этого слоя имеет форму (10, 7) :

  x = tf.random.normal ([7, 5])
layer = tf.keras.layers.Dense (10, активация = tf.nn.relu)

с tf.GradientTape (persistent = True) в качестве ленты:
  y = слой (x)

y.shape
  
TensorShape ([7, 10])
 

А форма ядра слоя - (5, 10) :

  layer.kernel.shape
  
TensorShape ([5, 10])
 

Форма якобиана выходных данных по отношению к ядру - это эти две формы, сцепленные вместе:

  j = лента.якобиан (y, layer.kernel)
j.shape
  
TensorShape ([7, 10, 5, 10])
 

Если вы суммируете размеры цели, у вас останется градиент суммы, которая была бы вычислена с помощью tf.GradientTape.gradient :

  г = лента.градиент (y, слой.ядро)
print ('g.shape:', g.shape)

j_sum = tf.reduce_sum (j, axis = [0, 1])
дельта = tf.reduce_max (абс (г - j_sum)). numpy ()
утверждать дельту <1e-3
print ('дельта:', дельта)
  
g.shape & двоеточие; (5, 10)
дельта и двоеточие; 2.3841858e-07
 
Пример: Гессен

Хотя tf.GradientTape не дает явного метода для построения матрицы Гессе, ее можно построить, используя метод tf.GradientTape.jacobian .

Примечание: Матрица Гессе содержит N ** 2 параметров. По этой и другим причинам это непрактично для большинства моделей. Этот пример включен больше как демонстрация того, как использовать метод tf.GradientTape.jacobian , и не является одобрением прямой оптимизации на основе Гессе.Произведение вектора Гессе можно эффективно вычислить с помощью вложенных лент, и это гораздо более эффективный подход к оптимизации второго порядка.
  x = tf.random.normal ([7, 5])
layer1 = tf.keras.layers.Dense (8, активация = tf.nn.relu)
layer2 = tf.keras.layers.Dense (6, активация = tf.nn.relu)

с tf.GradientTape () как t2:
  с tf.GradientTape () как t1:
    x = слой1 (x)
    x = слой2 (x)
    потеря = tf.reduce_mean (x ** 2)

  g = t1.gradient (потеря, layer1.kernel)

h = t2.jacobian (g, layer1.kernel)
  
  печать (f'layer.kernel.shape: {layer1.kernel.shape} ')
печать (f'h.shape: {h.shape} ')
  
layer.kernel.shape и двоеточие; (5, 8)
h.shape & двоеточие; (5, 8, 5, 8)
 

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

  n_params = tf.reduce_prod (layer1.kernel.shape)

g_vec = tf.reshape (g, [n_params, 1])
h_mat = tf.reshape (h, [n_params, n_params])
  

Матрица Гессе должна быть симметричной:

  def imshow_zero_center (изображение, ** kwargs):
  lim = tf.-1 @ ∇f (X (k))
# h_mat = ∇²f (X (k))
# g_vec = ∇f (X (k))
update = tf.linalg.solve (h_mat + eye_eps, g_vec)

# Измените форму обновления и примените его к переменной.
_ = layer1.kernel.assign_sub (tf.reshape (update, layer1.kernel.shape))
  

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

Пакетный Якобиан

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

Например, здесь вход x имеет форму (партия, входы) , а выход y имеет форму (партия, выходы) :

  x = tf.random.normal ([7, 5])

layer1 = tf.keras.layers.Dense (8, активация = tf.nn.elu)
layer2 = tf.keras.layers.Dense (6, активация = tf.nn.elu)

с tf.GradientTape (persistent = True, watch_accessed_variables = False) в качестве ленты:
  tape.watch (x)
  y = слой1 (x)
  y = слой2 (y)

y.shape
  
TensorShape ([7, 6])
 

Полный якобиан y относительно x имеет форму (партия, входы, партия, выходы) , даже если вам нужен только (партия, входы, выходы) :

  j = лента.якобиан (y, x)
j.shape
  
TensorShape ([7, 6, 7, 5])
 

Если градиенты каждого элемента в стеке независимы, то каждый (пакет, пакет) срез этого тензора является диагональной матрицей:

  imshow_zero_center (j [:, 0,:, 0])
_ = plt.title ('Срез (партия, партия)')
  

  def plot_as_patches (j):
  # Измените порядок осей так, чтобы каждая диагональ образовывала непрерывный участок.
  j = tf.transpose (j, [1, 0, 3, 2])
  # Прокладывайте между каждым патчем.lim = tf.reduce_max (абс (j))
  j = tf.pad (j, [[0, 0], [1, 1], [0, 0], [1, 1]],
             constant_values ​​= -lim)
  # Измените форму, чтобы сформировать единое изображение.
  s = j.shape
  j = tf.reshape (j, [s [0] * s [1], s [2] * s [3]])
  imshow_zero_center (j, протяженность = [- 0,5, с [2] -0,5, с [0] -0,5, -0,5])

plot_as_patches (j)
_ = plt.title ('Все (партия, партия) срезы диагональны')
  

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

  j_sum = tf.reduce_sum (j, ось = 2)
печать (j_sum.shape)
j_select = tf.einsum ('bxby-> bxy', j)
печать (j_select.shape)
  
(7, 6, 5)
(7, 6, 5)
 

Было бы гораздо эффективнее провести расчет без дополнительного измерения. Метод tf.GradientTape.batch_jacobian делает именно это:

  jb = tape.batch_jacobian (y, x)
jb.shape
  
ВНИМАНИЕ! & Colon; TenorFlow & Colon; 5 из последних 5 вызовов <функции pfor. .f at 0x7f173c6be0e0> запускает повторную трассировку tf.функции. Трассировка стоит дорого, и чрезмерное количество трассировок может быть связано с (1) многократным созданием функции @ tf. в цикле, (2) передачей тензоров с разными формами, (3) передачей объектов Python вместо тензоров. Для (1) определите функцию @ tf. вне цикла. Для (2) у @ tf.function есть опция экспериментальной_relax_shapes = True, которая ослабляет формы аргументов, чтобы избежать ненужного повторения. Для (3), пожалуйста, обратитесь к https & col; // www.tensorflow.org/guide/function#controlling_retracing и https & col; // www.tensorflow.org/api_docs/python/tf/function для получения дополнительных сведений.
TensorShape ([7, 6, 5])
 
  ошибка = tf.reduce_max (abs (jb - j_sum))
утверждать ошибку <1e-3
печать (error.numpy ())
  
0,0
 
Внимание: tf.GradientTape.batch_jacobian проверяет только соответствие первого измерения исходного и целевого. Он не проверяет, действительно ли градиенты независимы.Вам решать, использовать ли batch_jacobian только там, где это имеет смысл. Например, добавление tf.keras.layers.BatchNormalization разрушает независимость, поскольку она нормализуется по измерению
пакета :
  x = tf.random.normal ([7, 5])

layer1 = tf.keras.layers.Dense (8, активация = tf.nn.elu)
bn = tf.keras.layers.BatchNormalization ()
layer2 = tf.keras.layers.Dense (6, активация = tf.nn.elu)

с tf.GradientTape (persistent = True, watch_accessed_variables = False) в качестве ленты:
  Лента.смотреть (х)
  y = слой1 (x)
  y = bn (y, обучение = True)
  y = слой2 (y)

j = лента. якобиан (y, x)
печать (f'j.shape: {j.shape} ')
  
ПРЕДУПРЕЖДЕНИЕ & Colon; Tenorflow & Colon; 6 из последних 6 вызовов  .f по адресу 0x7f16685c5440> привели к повторному отслеживанию tf.функции. Трассировка стоит дорого, и чрезмерное количество трассировок может быть связано с (1) многократным созданием функции @ tf. в цикле, (2) передачей тензоров с разными формами, (3) передачей объектов Python вместо тензоров.Для (1) определите функцию @ tf. вне цикла. Для (2) у @ tf.function есть опция экспериментальной_relax_shapes = True, которая ослабляет формы аргументов, чтобы избежать ненужного повторения. Для (3), пожалуйста, обратитесь к https & col; // www.tensorflow.org/guide/function#controlling_retracing и https & col; // www.tensorflow.org/api_docs/python/tf/function для получения дополнительных сведений.
j. форма и двоеточие; (7, 6, 7, 5)
 
  plot_as_patches (j)

_ = plt.title ('Эти срезы не диагональные')
_ = plt.xlabel ("Не используйте` batch_jacobian` ")
  

В этом случае batch_jacobian все еще выполняется и возвращает что-то с ожидаемой формой, но его содержимое имеет неясное значение:

  jb = tape.batch_jacobian (y, x)
печать (f'jb.shape: {jb.shape} ')
  
jb.shape & двоеточие; (7, 6, 5)
 

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

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

Градиенты

Начиная с

град

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

 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.сумма (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,4

5] W_grad [-0,16965576 -0,8774648 -1,4

5] b_grad -0.2922724 W_grad [-0,16965576 -0,8774648 -1,4

5] b_grad -0.2922724

API grad имеет прямое соответствие превосходной нотации в классическом исчислении Спивака на многообразиях (1965), также используемом в Структура и интерпретация классической механики (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,4

5], 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))
 
 стоимость убытка 3.0519395
стоимость убытка 3.0519395
 

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

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

 # Установить размер шага для расчетов конечных разностей
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.n \)), и именно здесь форвард-режим побеждает. 

Как это сделано: две основные функции автодифференцирования

Продукты Якобиана-Вектора (JVP, также известные как autodiff прямого режима)

JAX включает эффективные и общие реализации автоматического дифференцирования как в прямом, так и в обратном режиме. Знакомая функция grad построена на обратном режиме, но чтобы объяснить разницу между двумя режимами, и когда каждый из них может быть полезен, нам понадобится немного математических знаний. {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,7 мс ± 161 мкс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)
Назад вперед
 
 7,21 мс ± 3,62 мс на цикл (среднее ± ст.разработчик из 3 сбн по 10 петель)
Обратный обратный
 
 12,2 мс ± 7,37 мс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)
Наивная полная гессенская материализация
 
 53,7 мс ± 764 мкс на цикл (среднее ± стандартное отклонение из 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 ('Матрично-якобиево произведение без отображения v')
% 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
 
 118 мс ± 581 мкс на цикл (среднее ± ст.разработчик из 3 сбн по 10 петель)

Отображенное матрично-якобиево произведение
4,41 мс ± 48,7 мкс на цикл (среднее ± стандартное отклонение из 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
 
 227 мс ± 175 мкс на цикл (среднее ± стандартное отклонение из 3 прогонов, по 10 циклов в каждом)

Отображенное матричное произведение Якоби
2.31 мс ± 58 мкс на цикл (среднее ± стандартное отклонение из 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)
  • Оптимизация

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

    Допустим, у нас есть выражение $ 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) $ и вычислить эту производную для любых входных данных, которые нам нужны.

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

    Переключение режимов 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 .

    Новый фреймворк с открытым исходным кодом для автоматического дифференцирования с помощью графиков

    Об исследовании:

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

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

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

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

    На этой диаграмме показан простой WFST, встроенный в GTN, который преобразует разложения слова «the» в само слово.

    Как это работает:

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

     
    import gtn
    g1 = gtn.Graph ()
    g2 = gtn.Graph ()
    # ... добавить несколько узлов и дуг к графу ...
    # Вычислить функцию графиков:
    Intersection = gtn.intersect (g1, g2)
    score = gtn.forward_score (пересечение)
    # Вычислить градиенты:
    gtn.backward (score)

    Стиль программирования GTN кажется таким же знакомым для использования в таких популярных фреймворках, как PyTorch. Императивный стиль, API автограда и реализация автограда основаны на схожих принципах проектирования.Основное отличие состоит в том, что мы заменили тензоры на WFST и соответствующие им операции. Как и любой фреймворк, GTN прост в использовании без ущерба для производительности.

    В нашей исследовательской статье мы показываем примеры реализации алгоритмов с помощью GTN. В одном примере GTN используется для дополнения любой функции потерь на уровне последовательности с возможностью маргинализации при разложении фраз на части слов. Модель может свободно выбирать, как разложить такое слово, как «the», на части.Например, модель может выбрать использование «th» и «e» или «t», «h» и «e». Части слова часто используются в машинном переводе и распознавании речи, но декомпозиции выбираются из моделей, не зависящих от задачи. Наш новый подход позволяет модели изучить оптимальное разложение слова или фразы для данной задачи.

    Почему это важно:

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

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

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

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