Что называют трансформатором: на каком законе основан, классификация, назначение устройства

Содержание

ГОСТ 16110-82 Трансформаторы силовые. Термины и определения

Power transformers. Terms and definitions

1. РАЗРАБОТАН Министерством электротехнической промышленности

РАЗРАБОТЧИКИ

2. ВНЕСЕН Министерством электротехнической промышленности

3. УТВЕРЖДЕН И ВВЕДЕН В ДЕЙСТВИЕ Постановлением Государственного комитета СССР по стандартам от 04.03.82 N 940

5. ПЕРЕИЗДАНИЕ


Настоящий стандарт устанавливает применяемые в науке, технике и производстве термины и определения основных понятий в области силовых трансформаторов. Стандарт распространяется на силовые трансформаторы — трехфазные и многофазные мощностью 6,3 кВ·А и более и однофазные мощностью 5 кВ·А и более.

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

Для каждого понятия установлен один стандартизованный термин. Применение терминов — синонимов стандартизованного термина запрещается.

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

Термины, помеченные знаком «*», не распространяются на автотрансформаторы.

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

В стандарте имеется приложение, содержащее эскизы, поясняющие некоторые термины.

Стандартизованные термины набраны полужирным шрифтом, их краткая форма — светлым.

Термин

Определение

1. ОБЩИЕ ПОНЯТИЯ

1.1. Трансформатор

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

1.2. Силовой трансформатор

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

Примечание. К силовым относятся трансформаторы трехфазные и многофазные мощностью 6,3 кВ·А и более, однофазные мощностью 5 кВ·А и более

1.3. Силовой трансформаторный агрегат

Устройство, в котором конструктивно объединены два или более силовых трансформаторов

1.4. Многофазная трансформаторная группа

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

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

1.5. Магнитное поле трансформатора

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

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

1.6. Магнитное поле рассеяния обмоток

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

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

1.7. Магнитное поле токов нулевой последовательности

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

1.8. Основное магнитное поле

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

1.9. Сторона высшего (среднего, низшего) напряжения трансформатора

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

1.10. Схема соединения трансформатора

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

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

2. ВИДЫ ТРАНСФОРМАТОРОВ

2.1. Трансформатор общего назначения

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

2.2. Специальный трансформатор

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

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

2.3. Повышающий трансформатор

Трансформатор, у которого первичной обмоткой является обмотка низшего напряжения

2.4. Понижающий трансформатор

Трансформатор, у которого первичной обмоткой является обмотка высшего напряжения

2.5. Однофазный трансформатор

Трансформатор, в магнитной системе которого создается однофазное магнитное поле

2.6. Трехфазный трансформатор

Трансформатор, в магнитной системе которого создается трехфазное магнитное поле

2.7. Многофазный трансформатор

Трансформатор, в магнитной системе которого создается магнитное поле с числом фаз более трех

2.8. Двухобмоточный трансформатор*

Трансформатор, имеющий две основные гальванически не связанные обмотки (черт.4)

2.9. Трехобмоточный трансформатор*

Трансформатор, имеющий три основные гальванически не связанные обмотки (черт.5)

2.10. Многообмоточный трансформатор*

Трансформатор, имеющий более трех основных гальванически не связанных обмоток

2.11. Трансформатор с жидким диэлектриком

Трансформатор, в котором основной изолирующей средой и теплоносителем служит жидкий диэлектрик

2.12. Масляный трансформатор

Трансформатор с жидким диэлектриком, в котором основной изолирующей средой и теплоносителем служит трансформаторное масло

2.13. Трансформатор с негорючим жидким диэлектриком

Трансформатор с жидким диэлектриком, в котором основной изолирующей средой и теплоносителем служит негорючий жидкий диэлектрик

2.14. Сухой трансформатор

Трансформатор, в котором основной изолирующей средой служит атмосферный воздух или другой газ или твердый диэлектрик, а охлаждающей средой — атмосферный воздух

2.15. Воздушный трансформатор

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

2.16. Газонаполненный трансформатор

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

2.17. Трансформатор с литой изоляцией

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

2.18. Кварценаполненный трансформатор

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

2.19. Регулируемый трансформатор

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

2.20. Трансформатор, регулируемый под нагрузкой

Трансформатор РПН

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

особенности, принцип работы и применение

      Рубрики

    • Автомобили
    • Бизнес
    • Дом и семья
    • Домашний уют
    • Духовное развитие
    • Еда и напитки
    • Закон
    • Здоровье
    • Интернет
    • Искусство и развлечения
    • Карьера
    • Компьютеры
    • Красота
    • Маркетинг
    • Мода
    • Новости и общество
    • Образование
    • Отношения
    • Публикации и написание статей
    • Путешествия
    • Реклама
    • Самосовершенствование
    • Спорт и Фитнес
    • Технологии
    • Финансы
    • Хобби
    • О проекте
    • Реклама на сайте
    • Условия
    • Конфиденциальность
    • Вопросы и ответы

    FB

    Войти

    Что такое трансформатор? | Электрознайка. Домашний Электромастер.


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

    Переменный электрический ток (ток, который изменяется по величине и по направлению) наводит в первичной катушке переменное магнитное поле. Это переменное магнитное поле, наводит переменное напряжение во вторичной обмотке. Величина напряжения ЭДС зависит от числа витков  в катушке и от скорости изменения магнитного поля.

    Отношение числа витков первичной и вторичной обмоток определяет коэффициент трансформации:
       k = w1 / w2;   где:
    w1 — число витков в первичной обмотке;
    w2 — число витков во вторичной обмотке.
    Если число витков в первичной обмотке больше чем во вторичной — это понижающий трансформатор.
    Если число витков в первичной обмотке меньше, чем во вторичной — это повышающий трансформатор.

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

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

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

    Особое место трансформаторы со стальным (набор из стальных листов) сердечником занимают в электротехнике.

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

    Силовой трансформатор – что же это?

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

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

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

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

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

    Коэффициент полезного действия трансформатора довольно велик, от 0,9 до 0,98 и зависит от потерь в магнитопроводе и от магнитных полей рассеяния.


    От величины электрической мощности Р зависит площадь поперечного сечения магнитопровода S.
    По значению площади S определяется, при расчетах трансформатора, количество витков w на 1 вольт:

    w = 50 / S.

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

    При расчете трансформатора с определенной степенью точности можно считать, что мощность нагрузки во вторичной обмотке Pн = Uн * Iн и мощность потребляемая из сети в первичной обмотке Pc = Uc * Ic приблизительно равны. Если  потерями в сердечнике  пренебречь, то получается равенство:

    k = Uс / Uн = Iн / Iс.

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

    Трансформатор Википедия

    Эле́ктротрансформа́тор, в разговорной речи чаще просто трансформа́тор (от лат. transformare — «превращать, преобразовывать») — статическое электромагнитное устройство, имеющее две или более индуктивно связанные обмотки на каком-либо магнитопроводе и предназначенное для преобразования посредством электромагнитной индукции одной или нескольких систем (напряжений) переменного тока в одну или несколько других систем (напряжений), без изменения частоты[1][2].

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

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

    Трансформатор силовой ОСМ 0,16 — Однофазный Сухой Многоцелевого назначения мощностью 0,16 кВА

    История

    Для создания трансформаторов необходимо было изучение свойств материалов: неметаллических, металлических и магнитных, создания их теории[3].

    В 1831 году английским физиком Майклом Фарадеем было открыто явление электромагнитной индукции, лежащее в основе действия электрического трансформатора, при проведении им основополагающих исследований в области электричества. 29 августа 1831 года Фарадей описал в своём дневнике опыт, в ходе которого он намотал на железное кольцо диаметром 15 см и толщиной 2 см два медных провода длиной 15 и 18 см. При подключении к зажимам одной обмотки батареи гальванических элементов начинал отклоняться гальванометр на зажимах другой обмотки. Так как Фарадей работал с постоянным током, при достижении в первичной обмотке его максимального значения, ток во вторичной обмотке исчезал, и для возобновления эффекта трансформации требовалось отключить и снова подключить батарею к первичной обмотке.

    Схематичное изображение будущего трансформатора впервые появилось в 1831 году в работах М. Фарадея и Д. Генри. Однако ни тот, ни другой не отмечали в своём приборе такого свойства трансформатора, как изменение напряжений и токов, то есть трансформирование переменного тока[4].

    В 1848 году немецкий механик Г. Румкорф изобрёл индукционную катушку особой конструкции. Она явилась прообразом трансформатора[3].

    Александр Григорьевич Столетов (профессор Московского университета) сделал первые шаги в этом направлении. Он обнаружил петлю гистерезиса и доменную структуру ферромагнетика (1872 год).

    30 ноября 1876 года, дата получения патента Павлом Николаевичем Яблочковым[5], считается датой рождения первого трансформатора переменного тока. Это был трансформатор с разомкнутым сердечником, представлявшим собой стержень, на который наматывались обмотки.

    Первые трансформаторы с замкнутыми сердечниками были созданы в Англии в 1884 году братьями Джоном и Эдуардом Гопкинсон[4].

    В 1885 г. венгерские инженеры фирмы «Ганц и К°» Отто Блати, Карой Циперновский и Микша Дери изобрели трансформатор с замкнутым магнитопроводом, который сыграл важную роль в дальнейшем развитии конструкций трансформаторов.

    Братья Гопкинсон разработали теорию электромагнитных цепей[3]. В 1886 году они нау

    Что такое автотрансформатор? — Работа, преимущества, недостатки и применение

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

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

    Содержание :

    Пояснения к автомобильной схеме трансформатора

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

    Рисунок A: Обычный двухобмоточный трансформатор

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

    Рисунок B: Авто — трансформатор

    Первичная обмотка AB, от которой происходит ответвление в точке C, так что CB действует как вторичная обмотка.Напряжение питания подается на AB, а нагрузка подключается к CB. Отвод может быть фиксированным или переменным. Когда переменное напряжение V 1 приложено к AB, в сердечнике создается переменный магнитный поток, в результате чего в обмотке AB индуцируется ЭДС E 1 . Часть этой наведенной ЭДС отбирается во вторичной цепи.

    Лет,

    • В 1 — первичное приложенное напряжение
    • В 2 — вторичное напряжение на нагрузке
    • I 1 — первичный ток
    • I 2 — ток нагрузки
    • N 1 — количество витков между A и B
    • N 2 — количество витков между C и B

    Без учета тока холостого хода, реактивного сопротивления утечки и потерь,

    V 1 = E 1 и V 2 = E 2

    Следовательно, коэффициент трансформации:

    Поскольку вторичные ампер-витки противоположны первичным ампер-виткам, ток I 2 находится в противофазе с I 1 .Вторичное напряжение меньше первичного. Следовательно, ток I 2 больше тока I 1 . Следовательно, результирующий ток, протекающий через участок BC, равен (I 2 — I 1 ).

    Ампер-витки из-за участка BC = ток x витков.
    Уравнение (1) и (2) показывает, что ампер-витки из-за участка BC и переменного тока уравновешивают друг друга, что характерно для работы трансформатора.

    Экономия меди в автотрансформаторе по сравнению с обычным двухобмоточным трансформатором

    Вес меди пропорционален длине и площади поперечного сечения проводника.

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

    Теперь, исходя из приведенного выше рисунка (B) автотрансформатора, вес меди, необходимой для автотрансформатора, составляет

    W a = вес меди в секции AC + вес меди в секции CB

    Следовательно

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

    Вт 0 = масса меди на первичной обмотке + масса меди на вторичной обмотке

    Следовательно,

    Теперь отношение веса меди в автотрансформаторе к весу меди в обычном трансформаторе равно

    Экономия меди, связанная с использованием автотрансформатора = вес меди, необходимый для обычного трансформатора — вес меди, необходимый для автотрансформатора

    Следовательно,

    Экономия меди = K x вес меди, необходимой для двух обмоток трансформатора

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

    Преимущества автотрансформатора

    • Менее затратно
    • Лучшее регулирование
    • Низкие потери по сравнению с обычным двухобмоточным трансформатором того же номинала.

    Недостатки автотрансформатора

    У автотрансформатора есть различные преимущества, но есть еще один серьезный недостаток, почему автотрансформатор не используется широко, заключается в том, что

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

    Применение автотрансформатора

    • Используется как пускатель для подачи до от 50 до 60% полного напряжения на статор асинхронного двигателя с короткозамкнутым ротором во время пуска.
    • Используется для небольшого повышения напряжения в распределительном кабеле, чтобы исправить падение напряжения.
    • Также используется как регулятор напряжения
    • Используется в системах передачи и распределения электроэнергии, а также в аудиосистемах и на железных дорогах.

    Простая английская Википедия, бесплатная энциклопедия

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

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

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

    Трансформаторы в вашем районе, на электрических столбах или трансформаторы, подключенные к подземным проводам, обычно преобразуют высокое напряжение 7200 вольт в 220–240 вольт электричества для питания освещения и таких приборов, как холодильники в домах и на предприятиях. [4] В некоторых странах, например в Америке, в домах используется другое напряжение, например 120 вольт. Трансформаторы не могут увеличивать мощность, поэтому при повышении напряжения пропорционально снижается ток. Если напряжение понижается, пропорционально увеличивается ток. [5]

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

    Существует несколько основных типов трансформаторов:

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

    Что такое трансформатор? | Вондрополис

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

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

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

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

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

    Например, линия электропередачи электростанции может передавать электричество напряжением от 400 000 до 750 000 вольт. Электричество отправляется с таким высоким напряжением, потому что ему часто приходится преодолевать большие расстояния. Использование более высоких напряжений помогает минимизировать потери энергии при перемещении.

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

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

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

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

    Например, если первичная обмотка имеет 10 витков, а вторичная обмотка — один виток, то трансформатор снизит первичное напряжение в 10 раз.Таким образом, ток, входящий в трансформатор при 1000 вольт, покидает трансформатор при 100 вольт.

    Электрический трансформатор

    | authorSTREAM

    PowerPoint Presentation:

    www.dawateislami.net www.madnichannel.net

    Transformer:

    Transformer Что такое трансформатор? Структура и принцип работы? Строительство трансформатора? Потери в трансформаторе? Типы трансформаторов? Идеальный VS Практический трансформатор? Использование и применение трансформатора? Муддасир Арайн (11ES112) Аяз Мари (11ES97) Шехбаз Ага (11ES136) Зишан Анвар (11ES138) Джума Хан (11ES143) Саддам Догар (11ES111) Бурхан Арайн GL (11ES104) (Сердце системы переменного тока).

    Введение ::

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

    Что такое трансформатор ?:

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

    d:

    d

    Структура трансформатора ::

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

    PowerPoint Presentation:

    Первичная и вторичная обмотки, намотанные на ферромагнитный металлический сердечник. Функция сердечника заключается в передаче изменяющегося магнитного потока от первичной катушки к вторичной катушке.Первичная обмотка имеет N 1 ​​числа витков, а вторичная — N 2 числа витков. Повороты играют важную роль в работе трансформатора.

    Принцип работы ::

    Трансформатор работает по принципу взаимной индукции. Когда в первичной катушке протекает переменный ток, вокруг первичной катушки создается изменяющийся магнитный поток. «Принцип взаимной индукции гласит, что когда две катушки индуктивно связаны и если ток в катушке изменяется равномерно, то e.m.f, индуцированная в другой катушке. Эта ЭДС может управлять током, когда к нему подводится замкнутый путь ». Принцип работы:

    PowerPoint Presentation:

    Изменяющийся магнитный поток передается на вторичную катушку через железный сердечник. Изменяющийся магнитный поток отсекается вторичной обмоткой, поэтому индуцирует э.д.с. во вторичной обмотке. Теперь, если нагрузка подключена ко вторичной обмотке, эта ЭДС пропускает через нее ток. Величиной выходного напряжения можно управлять с помощью соотношения количества первичной и вторичной катушек.«Частота взаимно индуцированной ЭДС соответствует частоте переменного источника, который подает энергию на первичную обмотку. B

    Конструкция трансформатора ::

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

    PowerPoint Presentation:

    Сердечник сделан из пластин. Благодаря конструкции с ламинированным сердечником потери на вихревые токи минимальны. Обычно используются листы кремнистой стали высокого качества (от 0,3 до 0,5 мм). Эти ламинаты изолированы друг от друга с помощью такой изоляции, как лак или толстая бумага.

    PowerPoint Presentation:

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

    PowerPoint Presentation:

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

    PowerPoint Presentation:

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

    Потери в трансформаторе ::

    Потери в трансформаторе: В трансформаторе существует два типа потерь. Основные потери. Медные потери.Потери меди: У него также есть два типа потерь. Потеря гистерезиса. Во время намагничивания и размагничивания из-за эффекта гистерезиса в сердечнике возникают потери энергии, называемые гистерезисными потерями. Потери на вихревые токи: магнитный поток утечки генерирует ЭДС в сердечнике, производящий ток, который называется E ddy Current Loss.

    PowerPoint Presentation:

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

    Типы трансформатора ::

    Типы трансформатора: Как правило, трансформаторы классифицируются соответственно коэффициентами трансформации: 1.Повышающий трансформатор: 2. Понижающий трансформатор 1. Повышающий трансформатор: трансформатор, в котором Ns> Np, называется повышающим трансформатором. Повышающий трансформатор — это трансформатор, который преобразует низкое переменное напряжение в высокое переменное напряжение. 2. Понижающий трансформатор: трансформатор, в котором Np> Ns, называется понижающим трансформатором. Понижающий трансформатор — это трансформатор, который преобразует высокое переменное напряжение в низкое переменное напряжение.

    Ideal V / S Практический трансформатор ::

    Ideal V / S Практический трансформатор: трансформатор считается идеальным, если он удовлетворяет следующим свойствам, но ни один трансформатор не является идеальным на практике.У него нет потерь. Сопротивление обмоток нулевое. Нет утечки флюса. Для создания магнитного поля требуется небольшой ток. Практический трансформатор имеет сопротивление обмоток, некоторый поток рассеяния и небольшие потери.

    Может ли трансформатор повышать или понижать постоянный ток или напряжение ?:

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

    Применение и использование ;:

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

    Ссылки:

    Ссылки: Электротехника UA Bakshi. Вводный анализ схем Роберта Т. Бойластеда. Принцип электрической машины В.К. Мехта. Электрические машины РК Раджпут. Электрические машины Мухаммада Хариса Латифа. www.allaboutcircuit.com www.iiee.com

    СПАСИБО ВСЕМ:

    СПАСИБО ВСЕМ


    Аннотированный трансформатор

      из IPython.отобразить импорт изображения
    Изображение (filename = 'images / aiayn.png')  

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

    В этом посте я представляю «аннотированную» версию статьи в виде Построчная реализация.Я переупорядочил и удалил некоторые разделы из оригинальная статья и добавленные комментарии повсюду. Сам этот документ является рабочим notebook и должна быть полностью пригодной для использования реализацией. Всего есть 400 строк библиотечного кода, который может обрабатывать 27000 токенов в секунду на 4 графических процессорах.

    Чтобы продолжить, вам сначала необходимо установить PyTorch. Полный блокнот также доступен на github или на Google Colab с бесплатными графическими процессорами.

    Обратите внимание, что это просто отправная точка для исследователей и заинтересованных разработчиков.Код здесь в значительной степени основан на наших пакетах OpenNMT. (Если полезно, не стесняйтесь цитировать.) Для другого полного сервиса реализации модели check-out Tensor2Tensor (тензорный поток) и Sockeye (mxnet).

    • Александр Раш (@harvardnlp или [email protected]) с помощью Винсента Нгуена и Гийома Кляйна
      #! Pip install http://download.pytorch.org/whl/cu80/torch-0.3.0.post4-cp36-cp36m-linux_x86_64.whl numpy matplotlib spacy torchtext seaborn  
      import numpy as np
    импортный фонарик
    импортная горелка.nn как nn
    импортировать torch.nn.functional как F
    импорт математики, копии, времени
    из torch.autograd import Variable
    импортировать matplotlib.pyplot как plt
    импортные морские перевозки
    seaborn.set_context (context = "talk")
    % matplotlib inline  

    Содержание

    Мои комментарии цитируются. Основной текст взят из самой бумаги.

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

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

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

    Большинство конкурирующих моделей трансдукции нейронных последовательностей имеют кодер-декодер структура (цитировать). Здесь кодировщик отображает входная последовательность представлений символов $ (x_1,…, x_n) $ в последовательность непрерывные представления $ \ mathbf {z} = (z_1,…, z_n) $.Учитывая $ \ mathbf {z} $, затем декодер генерирует выходную последовательность $ (y_1,…, y_m) $ символов один элемент за раз. На каждом этапе модель является авторегрессивной. (цитировать), потребляя ранее сгенерированные символы в качестве дополнительных входных данных при генерации следующего.

      класс EncoderDecoder (nn.Module):
        "" "
        Стандартная архитектура кодировщика-декодера. База для этого и многих
        другие модели.
        "" "
        def __init __ (сам, кодировщик, декодер, src_embed, tgt_embed, генератор):
            супер (EncoderDecoder, сам).__в этом__()
            self.encoder = кодировщик
            self.decoder = декодер
            self.src_embed = src_embed
            self.tgt_embed = tgt_embed
            self.generator = генератор
            
        def forward (self, src, tgt, src_mask, tgt_mask):
            «Принимать и обрабатывать замаскированные src и целевые последовательности».
            вернуть self.decode (self.encode (src, src_mask), src_mask,
                                tgt, tgt_mask)
        
        def encode (self, src, src_mask):
            вернуть self.encoder (self.src_embed (src), src_mask)
        
        def decode (self, memory, src_mask, tgt, tgt_mask):
            вернуть себя.декодер (self.tgt_embed (tgt), memory, src_mask, tgt_mask)  
      Генератор классов (nn.Module):
        «Определите стандартный шаг генерации linear + softmax».
        def __init __ (я, d_model, словарь):
            super (Генератор, сам) .__ init __ ()
            self.proj = nn.Linear (d_model, словарь)
    
        def вперед (self, x):
            return F.log_softmax (self.proj (x), dim = -1)  

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

      Изображение (filename = 'images / ModalNet-21.png')  

    Стеки кодировщика и декодера

    Кодировщик

    Кодер состоит из стека из $ N = 6 $ идентичных слоев.

      деф клонов (модуль, N):
        «Изготовить N одинаковых слоев».
        return nn.ModuleList ([copy.deepcopy (module) for _ in range (N)])  
      class Encoder (nn.Module):
        «Основной кодировщик - это стек из N слоев»
        def __init __ (self, layer, N):
            супер (кодировщик, сам).__в этом__()
            self.layers = clones (слой, N)
            self.norm = LayerNorm (размер слоя)
            
        def forward (self, x, mask):
            «Пропустите ввод (и маску) через каждый слой по очереди».
            для слоя в self.layers:
                x = слой (x, маска)
            return self.norm (x)  

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

      класс LayerNorm (nn.Module):
        "Создайте модуль layernorm (подробности см. В ссылке)."
        def __init __ (self, features, eps = 1e-6):
            super (LayerNorm, сам) .__ init __ ()
            self.a_2 = nn.Parameter (torch.ones (функции))
            self.b_2 = nn.Parameter (torch.zeros (функции))
            self.eps = eps
    
        def вперед (self, x):
            среднее = x.mean (-1, keepdim = True)
            std = x.std (-1, keepdim = True)
            return self.a_2 * (x - среднее значение) / (std + self.eps) + self.b_2  

    То есть вывод каждого подслоя равен $ \ mathrm {LayerNorm} (x + \ mathrm {Sublayer} (x)) $, где $ \ mathrm {Sublayer} (x) $ — реализованная функция самим подслоем.Применяем отсев (цитировать) к выходу каждого подуровня, прежде чем он будет добавлен на вход подуровня и нормализован.

    Чтобы облегчить эти остаточные соединения, все подслои модели, а также в качестве встраиваемых слоев производят выходные данные размерности $ d _ {\ text {model}} = 512 $.

      класс SublayerConnection (nn.Module):
        "" "
        Остаточное соединение, за которым следует норма слоя.
        Обратите внимание, для простоты кода норма - первая, а не последняя.
        "" "
        def __init __ (self, size, dropout):
            super (SublayerConnection, сам).__в этом__()
            self.norm = LayerNorm (размер)
            self.dropout = nn.Dropout (выпадение)
    
        def forward (self, x, sublayer):
            «Примените остаточное соединение к любому подслою того же размера».
            return x + self.dropout (sublayer (self.norm (x)))  

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

      класс EncoderLayer (nn.Module):
        «Кодировщик состоит из самооценки и упреждения (определение ниже)»
        def __init __ (self, size, self_attn, feed_forward, dropout):
            super (EncoderLayer, сам).__в этом__()
            self.self_attn = self_attn
            self.feed_forward = feed_forward
            self.sublayer = clones (SublayerConnection (размер, выпадение), 2)
            self.size = размер
    
        def forward (self, x, mask):
            «Соединения см. На Рисунке 1 (слева)».
            x = self.sublayer [0] (x, лямбда x: self.self_attn (x, x, x, маска))
            return self.sublayer [1] (x, self.feed_forward)  

    Декодер

    Декодер также состоит из пакета из $ N = 6 $ одинаковых слоев.

      класс Decoder (nn.Модуль):
        «Универсальный декодер N-слоя с маскированием».
        def __init __ (self, layer, N):
            super (Декодер, сам) .__ init __ ()
            self.layers = clones (слой, N)
            self.norm = LayerNorm (размер слоя)
            
        def forward (self, x, memory, src_mask, tgt_mask):
            для слоя в self.layers:
                x = слой (x, память, src_mask, tgt_mask)
            return self.norm (x)  

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

      класс DecoderLayer (nn.Module):
        "Декодер состоит из self-attn, src-attn и прямого распространения (определено ниже)"
        def __init __ (self, size, self_attn, src_attn, feed_forward, dropout):
            super (DecoderLayer, self) .__ init __ ()
            self.size = размер
            self.self_attn = self_attn
            self.src_attn = src_attn
            self.feed_forward = feed_forward
            я.sublayer = clones (SublayerConnection (размер, выпадение), 3)
     
        def forward (self, x, memory, src_mask, tgt_mask):
            «Соединения показаны на Рисунке 1 (справа)».
            m = память
            x = self.sublayer [0] (x, лямбда x: self.self_attn (x, x, x, tgt_mask))
            x = self.sublayer [1] (x, лямбда x: self.src_attn (x, m, m, src_mask))
            return self.sublayer [2] (x, self.feed_forward)  

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

      def secondary_mask (размер):
        «Замаскируйте последующие позиции».
        attn_shape = (1, размер, размер)
        последующая_маска = np.triu (np.ones (attn_shape), k = 1) .astype ('uint8')
        вернуть torch.from_numpy (following_mask) == 0  

    Под маской внимания показано положение, в котором каждое слово (строка) tgt может занимать посмотрите на (столбец).Слова заблокированы для обращения к будущим словам во время тренировка.

      plt. Рисунок (figsize = (5,5))
    plt.imshow (последующая_маска (20) [0])
    Нет  

    Внимание

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

    Мы обращаем особое внимание на «внимание к масштабируемым точечным продуктам». Вход состоит из запросов и ключей размерности $ d_k $ и значений измерения $ d_v $. Мы вычисляем скалярные произведения запроса со всеми ключами, делим каждый на $ \ sqrt {d_k} $ и примените функцию softmax для получения весов значений.

      Изображение (filename = 'images / ModalNet-19.png')  

    На практике мы вычисляем функцию внимания по набору запросов. одновременно, упакованные в матрицу $ Q $.Ключи и значения также упакованы в матрицы $ K $ и $ V $. Вычисляем матрицу выводит как:

      def Внимание (запрос, ключ, значение, маска = None, dropout = None):
        "Compute 'Scaled Dot Product Attention'"
        d_k = размер запроса (-1)
        scores = torch.matmul (запрос, key.transpose (-2, -1)) \
                 / math.sqrt (d_k)
        если маска не None:
            scores = scores.masked_fill (маска == 0, -1e9)
        p_attn = F.softmax (оценки, dim = -1)
        если выпадения нет:
            p_attn = выпадение (p_attn)
        вернуть факел.matmul (p_attn, value), p_attn  

    Две наиболее часто используемые функции внимания — это аддитивное внимание. (цитировать) и скалярное произведение (мультипликативное) внимание. Точечное внимание идентично нашему алгоритму, за исключением коэффициент масштабирования $ \ frac {1} {\ sqrt {d_k}} $. Аддитивное внимание вычисляет функция совместимости с использованием прямой сети с одним скрытым слоем. Хотя эти два понятия похожи по теоретической сложности, внимание к скалярным произведениям намного быстрее и компактнее на практике, так как это может быть реализовано с использованием оптимизированного кода умножения матриц.

    В то время как для малых значений $ d_k $ два механизма работают одинаково, внимание превосходит внимание скалярного продукта без масштабирования для больших значений $ d_k $ (цитировать). Мы подозреваем, что для больших значения $ d_k $, точечные произведения возрастают по величине, что подталкивает softmax функционируют в регионах, где есть очень маленькие градиенты (чтобы проиллюстрировать, почему скалярные произведения становятся большими, предположим, что компоненты $ q $ и $ k $ равны независимые случайные величины со средним $ 0 $ и дисперсией $ 1 $.{hd_v \ раз d _ {\ text {model}}} $. В этой работе мы используем $ h = 8 $ параллельных слоев внимания, или голов. Для каждого из для них мы используем $ d_k = d_v = d _ {\ text {model}} / h = 64 $. Из-за уменьшенного размера каждая голова, общие вычислительные затраты аналогичны стоимости одной головы внимание с полной размерностью.

      класс MultiHeadedAttention (nn.Module):
        def __init __ (self, h, d_model, dropout = 0.1):
            «Примите во внимание размер модели и количество голов».
            super (MultiHeadedAttention, я).__в этом__()
            утверждать d_model% h == 0
            # Мы предполагаем, что d_v всегда равно d_k
            self.d_k = d_model // ч
            self.h = h
            self.linears = clones (nn.Linear (d_model, d_model), 4)
            self.attn = Нет
            self.dropout = nn.Dropout (p = выпадение)
            
        def forward (self, query, key, value, mask = None):
            «Реализует Рисунок 2»
            если маска не None:
                # Одна и та же маска применена ко всем h головам.
                маска = mask.unsqueeze (1)
            nbatches = query.size (0)
            
            # 1) Выполняйте все линейные проекции в пакетном режиме из d_model => h x d_k
            запрос, ключ, значение = \
                [л (х).view (nbatches, -1, self.h, self.d_k) .transpose (1, 2)
                 для l, x в zip (self.linears, (query, key, value))]
            
            # 2) Обратите внимание на все проецируемые векторы в пакете.
            x, self.attn = внимание (запрос, ключ, значение, маска = маска,
                                     dropout = self.dropout)
            
            # 3) "Concat", используя вид, и примените окончательную линейность.
            х = х.transpose (1, 2). смежный () \
                 .view (nbatches, -1, self.h * self.d_k)
            вернуть себя.linears [-1] (x)  

    Приложения внимания в нашей модели

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

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

    3) Точно так же слои самовнимания в декодере позволяют каждую позицию в декодер для обслуживания всех позиций в декодере, включая это должность. Нам нужно предотвратить левый поток информации в декодере, чтобы сохранить свойство авторегрессии.Мы реализуем это внутри масштабированной точки- внимание продукта путем маскировки (установка $ — \ infty $) всех значений во входных данных softmax, которые соответствуют незаконным соединениям.

    Позиционные сети прямого распространения

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

    Хотя линейные преобразования одинаковы для разных позиций, они использовать разные параметры от слоя к слою. Другой способ описать это: в виде двух сверток с размером ядра 1. Размерность ввода и вывода равно $ d _ {\ text {model}} = 512 $, а размерность внутреннего слоя $ d_ {ff} = 2048 $.

      класс PositionwiseFeedForward (nn.Module):
        «Реализует уравнение FFN».
        def __init __ (self, d_model, d_ff, dropout = 0.1):
            super (PositionwiseFeedForward, сам).__в этом__()
            self.w_1 = nn.Linear (d_model, d_ff)
            self.w_2 = nn.Linear (d_ff, d_model)
            self.dropout = nn.Dropout (выпадение)
    
        def вперед (self, x):
            return self.w_2 (self.dropout (F.relu (self.w_1 (x))))  

    Вложения и Softmax

    Подобно другим моделям трансдукции последовательностей, мы используем заученные вложения для преобразовать входные токены и выходные токены в векторы размерности $ d _ {\ text {model}} $. Мы также используем обычное выученное линейное преобразование и функция softmax для преобразования вывода декодера в предсказанный следующий токен вероятности.В нашей модели мы используем одну и ту же матрицу весов для двух встраивание слоев и линейное преобразование pre-softmax, аналогично (цитировать). В слоях встраивания умножаем эти веса на $ \ sqrt {d _ {\ text {model}}} $.

      вложения класса (nn.Module):
        def __init __ (я, d_model, словарь):
            super (Вложения, собственное) .__ init __ ()
            self.lut = nn.Embedding (словарь, d_model)
            self.d_model = d_model
    
        def вперед (self, x):
            вернуть self.lut (x) * math.sqrt (self.d_model)  

    Позиционное кодирование

    Поскольку наша модель не содержит повторений и сверток, для того, чтобы модель, чтобы использовать порядок последовательности, мы должны ввести некоторую информацию об относительном или абсолютном положении токенов в последовательности. К этому end, мы добавляем «позиционные кодировки» к входным вложениям в нижней части стеки кодировщика и декодера. Позиционные кодировки имеют одинаковую размерность $ d _ {\ text {model}} $ в качестве вложений, чтобы их можно было суммировать.Есть множество вариантов позиционных кодировок, изученных и исправленных (цитировать).

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

    где $ pos $ — позиция, а $ i $ — размерность. То есть каждое измерение позиционного кодирования соответствует синусоиде. Длины волн образуют геометрическая прогрессия от $ 2 \ pi $ до $ 10000 \ cdot 2 \ pi $. Мы выбрали эту функцию потому что мы предположили, что это позволит модели легко научиться посещать относительные позиции, поскольку для любого фиксированного смещения $ k $, $ PE_ {pos + k} $ может быть представлен как линейная функция от $ PE_ {pos} $.

    Кроме того, мы применяем дропаут к суммам вложений и позиционных кодирования в стеке кодировщика и декодера. Для базовой модели мы используем ставка $ P_ {drop} = 0,1 $.

      класс PositionalEncoding (nn.Module):
        «Реализуйте функцию PE».
        def __init __ (self, d_model, dropout, max_len = 5000):
            super (PositionalEncoding, self) .__ init __ ()
            self.dropout = nn.Dropout (p = выпадение)
            
            # Вычислить позиционные кодировки один раз в пространстве журнала.pe = torch.zeros (max_len, d_model)
            position = torch.arange (0, max_len) .unsqueeze (1)
            div_term = torch.exp (torch.arange (0, d_model, 2) *
                                 - (math.log (10000.0) / d_model))
            pe [:, 0 :: 2] = torch.sin (позиция * div_term)
            pe [:, 1 :: 2] = torch.cos (позиция * div_term)
            pe = pe.unsqueeze (0)
            self.register_buffer ('pe', pe)
            
        def вперед (self, x):
            x = x + Variable (self.pe [:,: x.size (1)],
                             requires_grad = Ложь)
            вернуть себя.выпадение (x)  

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

      plt. Рисунок (figsize = (15, 5))
    pe = PositionalEncoding (20, 0)
    y = pe.forward (Переменная (torch.zeros (1, 100, 20)))
    plt.plot (np.arange (100), y [0,:, 4: 8] .data.numpy ())
    plt.legend (["dim% d"% p вместо p в [4,5,6,7]])
    Нет  

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

    Полная модель

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

      def make_model (src_vocab, tgt_vocab, N = 6,
                   d_model = 512, d_ff = 2048, h = 8, dropout = 0.1):
        «Помощник: построить модель по гиперпараметрам».
        c = copy.deepcopy
        attn = MultiHeadedAttention (h, d_model)
        ff = PositionwiseFeedForward (d_model, d_ff, dropout)
        position = PositionalEncoding (d_model, выпадение)
        model = EncoderDecoder (
            Кодировщик (EncoderLayer (d_model, c (attn), c (ff), dropout), N),
            Декодер (DecoderLayer (d_model, c (attn), c (attn),
                                 c (ff), выпадение), N),
            nn.Последовательные (вложения (d_model, src_vocab), c (позиция)),
            nn.Sequential (Вложения (d_model, tgt_vocab), c (позиция)),
            Генератор (d_model, tgt_vocab))
        
        # Это было важно из их кода.
        # Инициализировать параметры с помощью Glorot / fan_avg.
        для p в model.parameters ():
            если p.dim ()> 1:
                nn.init.xavier_uniform (p)
        вернуть модель  
      # Небольшой пример модели.
    tmp_model = make_model (10, 10, 2)
    Нет  

    В этом разделе описан режим обучения наших моделей.

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

    Пакеты и маскирование

    Класс
      Партия:
        «Объект для хранения пакета данных с маской во время обучения».
        def __init __ (self, src, trg = None, pad = 0):
            self.src = src
            self.src_mask = (src! = pad).разжать (-2)
            если trg не равно None:
                self.trg = trg [:,: -1]
                self.trg_y = trg [:, 1:]
                self.trg_mask = \
                    self.make_std_mask (self.trg, pad)
                self.ntokens = (self.trg_y! = pad) .data.sum ()
        
        @staticmethod
        def make_std_mask (tgt, pad):
            «Создайте маску, чтобы скрыть отступы и будущие слова».
            tgt_mask = (tgt! = pad) .unsqueeze (-2)
            tgt_mask = tgt_mask & переменная (
                последующая_маска (tgt.size (-1)). type_as (tgt_mask.данные))
            возврат tgt_mask  

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

    Цикл обучения

      def run_epoch (data_iter, model, loss_compute):
        «Стандартная функция обучения и регистрации»
        start = time.time ()
        total_tokens = 0
        total_loss = 0
        токены = 0
        для i пакет в enumerate (data_iter):
            out = модель.вперед (batch.src, batch.trg,
                                batch.src_mask, batch.trg_mask)
            loss = loss_compute (выход, batch.trg_y, batch.ntokens)
            total_loss + = убыток
            total_tokens + = batch.ntokens
            токены + = пакет. токены
            если я% 50 == 1:
                elapsed = time.time () - начало
                print ("Шаг эпохи:% d Потеря:% f токенов в секунду:% f"%
                        (i, потеря / партия. токенов, токенов / истекло))
                start = time.time ()
                токены = 0
        return total_loss / total_tokens  

    Данные обучения и пакетная обработка

    Мы прошли обучение на стандартном англо-немецком наборе данных WMT 2014, состоящем примерно из 4.5 миллионов пар предложений. Предложения кодировались с использованием кодирования пар байтов, который имеет общий словарь исходных и целевых значений, содержащий около 37000 токенов. Для английского- Французский, мы использовали значительно больший англо-французский набор данных WMT 2014 состоящий из 36 миллионов предложений и разделенных лексем на 32000 словарных частей.

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

    Мы будем использовать текст факела для дозирования. Это обсуждается более подробно ниже. Здесь мы создаем партии в функции torchtext, которая обеспечивает размер нашей партии. заполненный до максимального размера партии, не превышает порогового значения (25000, если у нас 8 графический процессор).

      глобальный max_src_in_batch, max_tgt_in_batch
    def batch_size_fn (новое, количество, софар):
        «Продолжайте увеличивать пакет и вычисляйте общее количество токенов + дополнение».
        глобальный max_src_in_batch, max_tgt_in_batch
        если count == 1:
            max_src_in_batch = 0
            max_tgt_in_batch = 0
        max_src_in_batch = max (max_src_in_batch, len (новый.src))
        max_tgt_in_batch = max (max_tgt_in_batch, len (new.trg) + 2)
        src_elements = количество * max_src_in_batch
        tgt_elements = count * max_tgt_in_batch
        return max (src_elements, tgt_elements)  

    Оборудование и расписание

    Мы обучили наши модели на одной машине с 8 графическими процессорами NVIDIA P100. Для нашей базы модели с использованием гиперпараметров, описанных в статье, каждое обучение шаг занял около 0,4 секунды. Мы обучили базовые модели в общей сложности 100000 шагов или 12 часов.{-9} $. Мы разнообразили обучение ставка в процессе обучения, по формуле: Это соответствует линейному увеличению скорости обучения для первого $ warmup_steps $ шагов обучения, а затем уменьшая его пропорционально обратный квадратный корень из номера шага. Мы использовали $ warmup_steps = 4000 $.

    Примечание: эта часть очень важна. Необходимо потренироваться с этой настройкой модели.

      класс NoamOpt:
        «Оптимальная обертка, реализующая скорость."
        def __init __ (себя, размер_модели, фактор, прогрев, оптимизатор):
            self.optimizer = оптимизатор
            self._step = 0
            self.warmup = разминка
            self.factor = коэффициент
            self.model_size = размер_модели
            self._rate = 0
            
        def step (self):
            «Обновить параметры и скорость»
            self._step + = 1
            рейтинг = self.rate ()
            для p в self.optimizer.param_groups:
                p ['lr'] = ставка
            self._rate = ставка
            self.optimizer.step ()
            
        скорость определения (self, step = None):
            "Реализуйте` lrate` выше "
            если шаг Нет:
                step = self._step
            вернуть self.factor * \
                (размер_амодели ** (-0,5) *
                мин (шаг ** (-0,5), шаг * саморазогрев ** (-1,5)))
            
    def get_std_opt (модель):
        вернуть NoamOpt (model.src_embed [0] .d_model, 2, 4000,
                torch.optim.Adam (параметры модели (), lr = 0, бета-версия = (0,9, 0,98), eps = 1e-9))  

    Пример кривых этой модели для разных размеров модели и для оптимизация гиперпараметров.

      # Три настройки гиперпараметров скорости.opts = [NoamOpt (512, 1, 4000, Нет),
            NoamOpt (512, 1, 8000, Нет),
            NoamOpt (256, 1, 4000, Нет)]
    plt.plot (np.arange (1, 20000), [[opt.rate (i) for opt in opts] для i в диапазоне (1, 20000)])
    plt.legend (["512: 4000", "512: 8000", "256: 4000"])
    Нет  

    Регуляризация

    Сглаживание этикеток

    Во время обучения мы использовали сглаживание меток со значением $ \ epsilon_ {ls} = 0.1 $. (цитировать). Это вызывает недоумение, так как модель учится быть более неуверенным, но повышает точность и оценку BLEU.

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

      класс LabelSmoothing (nn.Module):
        «Осуществить сглаживание этикеток».
        def __init __ (self, size, padding_idx, smoothing = 0.0):
            super (LabelSmoothing, сам) .__ init __ ()
            я.критерий = nn.KLDivLoss (size_average = False)
            self.padding_idx = padding_idx
            self.confidence = 1.0 - сглаживание
            self.smoothing = сглаживание
            self.size = размер
            self.true_dist = Нет
            
        def вперед (self, x, target):
            assert x.size (1) == self.size
            true_dist = x.data.clone ()
            true_dist.fill_ (self.smoothing / (self.size - 2))
            true_dist.scatter_ (1, target.data.unsqueeze (1), самоуверенность)
            true_dist [:, self.padding_idx] = 0
            маска = факел.ненулевое значение (target.data == self.padding_idx)
            если mask.dim ()> 0:
                true_dist.index_fill_ (0, mask.squeeze (), 0.0)
            self.true_dist = true_dist
            return self.criterion (x, Variable (true_dist, requires_grad = False))  

    Здесь мы видим пример того, как масса распределяется по словам на основе по уверенности.

      # Пример сглаживания метки.
    крит = LabelSmoothing (5, 0, 0,4)
    прогнозировать = torch.FloatTensor ([[0, 0.2, 0.7, 0.1, 0],
                                 [0, 0.2, 0,7, 0,1, 0],
                                 [0, 0,2, 0,7, 0,1, 0]])
    v = crit (Переменная (pred.log ()),
             Переменная (torch.LongTensor ([2, 1, 0])))
    
    # Показать целевые распределения, ожидаемые системой.
    plt.imshow (cris.true_dist)
    Нет  

    Сглаживание меток на самом деле начинает штрафовать модель, если уверен в сделанном выборе.

      крит = LabelSmoothing (5, 0, 0,1)
    def потеря (x):
        г = х + 3 * 1
        предсказать = факел.FloatTensor ([[0, x / d, 1 / d, 1 / d, 1 / d],
                                     ])
        #print (прогнозировать)
        вернуть крит (переменная (pred.log ()),
                     Переменная (torch.LongTensor ([1]))). Data [0]
    plt.plot (np.arange (1, 100), [потеря (x) для x в диапазоне (1, 100)])
    Нет  

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

    Синтетические данные

      def data_gen (V, batch, nbatches):
        "Сгенерировать случайные данные для задачи копирования src-tgt."
        для i в диапазоне (nbatches):
            data = torch.from_numpy (np.random.randint (1, V, size = (batch, 10)))
            данные [:, 0] = 1
            src = переменная (данные, requires_grad = False)
            tgt = переменная (данные, requires_grad = False)
            yield Batch (src, tgt, 0)  

    Расчет убытков

      класс SimpleLossCompute:
        «Простая функция вычисления потерь и обучения».
        def __init __ (себя, генератор, критерий, opt = None):
            self.generator = генератор
            self.criterion = критерий
            я.opt = opt
            
        def __call __ (self, x, y, norm):
            х = self.generator (х)
            потеря = self.criterion (x.contiguous (). view (-1, x.size (-1)),
                                  y.contiguous (). view (-1)) / norm
            loss.backward ()
            если self.opt не равен None:
                self.opt.step ()
                self.opt.optimizer.zero_grad ()
            возврат loss.data [0] * норма  

    Greedy Decoding

      # Обучите задачу простого копирования.
    V = 11
    критерий = LabelSmoothing (размер = V, padding_idx = 0, сглаживание = 0.0)
    модель = make_model (V, V, N = 2)
    model_opt = NoamOpt (model.src_embed [0] .d_model, 1, 400,
            torch.optim.Adam (модель.параметры (), lr = 0, бета-версия = (0,9, 0,98), eps = 1e-9))
    
    для эпохи в диапазоне (10):
        model.train ()
        run_epoch (data_gen (V, 30, 20), модель,
                  SimpleLossCompute (модель. Генератор, критерий, модель_опт))
        model.eval ()
        print (run_epoch (data_gen (V, 30, 5), модель,
                        SimpleLossCompute (модель, генератор, критерий, Нет)))  
      Шаг эпохи: 1 Потеря: 3.023465 Токенов в секунду: 403.074173
    Шаг эпохи: 1 Убыток: 1,920030 токенов в секунду: 641,689380
    1,9274832487106324
    Шаг эпохи: 1 Убыток: 1.940011 токенов в секунду: 432.003378
    Шаг эпохи: 1 Потеря: 1,699767 Токенов в секунду: 641,979665
    1.657595729827881
    Шаг эпохи: 1 Убыток: 1,860276 жетонов в секунду: 433,320240
    Шаг эпохи: 1 Потеря: 1,546011 токенов в секунду: 640,537198
    1.4888023376464843
    Шаг эпохи: 1 Убыток: 1.682198 токенов в секунду: 432.092305
    Шаг эпохи: 1 Убыток: 1,313169 токенов в секунду: 639,441857
    1,3485562801361084
    Шаг эпохи: 1 Потеря: 1.278768 токенов в секунду: 433,568756
    Шаг эпохи: 1 Потеря: 1,062384 токенов в секунду: 642,542067
    0,9853351473808288
    Шаг эпохи: 1 Потеря: 1,269471 токенов в секунду: 433,388727
    Шаг эпохи: 1 Потеря: 0,5
      Токенов в секунду: 642,862135 0,5686767101287842 Шаг эпохи: 1 Убыток: 0.997076 Токенов в секунду: 433.009746 Шаг эпохи: 1 Потеря: 0,343118 токенов в секунду: 642,288427 0,34273059368133546 Шаг эпохи: 1 Потеря: 0,459483 токенов в секунду: 434,594030 Шаг эпохи: 1 Потеря: 0,2

      токенов в секунду: 642,519464 0,2612409472465515 Шаг эпохи: 1 Потеря: 1.031042 токенов в секунду: 434.557008 Шаг эпохи: 1 Потеря: 0,437069 Токенов в секунду: 643,630322 0,4323212027549744 Шаг эпохи: 1 Убыток: 0,617165 токенов в секунду: 436,652626 Шаг эпохи: 1 Потеря: 0,258793 токенов в секунду: 644,372296 0,273311292034

    Этот код предсказывает перевод с использованием жадного декодирования для простоты.

      def greedy_decode (модель, src, src_mask, max_len, start_symbol):
        memory = model.encode (src, src_mask)
        ys = torch.ones (1, 1).fill_ (начальный_символ) .type_as (src.data)
        для i в диапазоне (max_len-1):
            out = model.decode (память, src_mask,
                               Переменная (ys),
                               Переменная (secondary_mask (ys.size (1))
                                        .type_as (src.data)))
            prob = model.generator (out [:, -1])
            _, следующее_слово = torch.max (prob, dim = 1)
            next_word = next_word.data [0]
            ys = torch.cat ([ys,
                            torch.ones (1, 1) .type_as (src.data) .fill_ (next_word)], dim = 1)
        вернуть ys
    
    модель.eval ()
    src = Variable (torch.LongTensor ([[1,2,3,4,5,6,7,8,9,10]]))
    src_mask = переменная (torch.ones (1, 1, 10))
    print (greedy_decode (модель, src, src_mask, max_len = 10, start_symbol = 1))  
      1 2 3 4 5 6 7 8 9 10
    [torch.LongTensor размером 1x10]
      

    Теперь рассмотрим реальный пример с использованием немецко-английского языка IWSLT. Задача перевода. Эта задача намного меньше, чем задача WMT, рассмотренная в документ, но он иллюстрирует всю систему.Мы также покажем, как использовать multi-gpu обработка, чтобы сделать это действительно быстро.

      #! Pip install torchtext spacy
    #! python -m spacy download ru
    #! python -m spacy загрузка  

    Загрузка данных

    Мы загрузим набор данных, используя torchtext и spacy для токенизации.

      # Для загрузки данных.
    из данных импорта torchtext, наборов данных
    
    если правда:
        импортный простор
        spacy_de = spacy.load ('де')
        spacy_en = spacy.load ('ru')
    
        def tokenize_de (текст):
            вернуться [ток.текст для токена в spacy_de.tokenizer (текст)]
    
        def tokenize_en (текст):
            return [tok.text для токена в spacy_en.tokenizer (текст)]
    
        BOS_WORD = ''
        EOS_WORD = ''
        BLANK_WORD = "<пусто>"
        SRC = data.Field (tokenize = tokenize_de, pad_token = BLANK_WORD)
        TGT = data.Field (tokenize = tokenize_en, init_token = BOS_WORD,
                         eos_token = EOS_WORD, pad_token = BLANK_WORD)
    
        MAX_LEN = 100
        train, val, test = datasets.IWSLT.splits (
            exts = ('. de', '.ru '), fields = (SRC, TGT),
            filter_pred = lambda x: len (vars (x) ['src']) <= MAX_LEN и
                len (vars (x) ['trg']) <= MAX_LEN)
        MIN_FREQ = 2
        SRC.build_vocab (train.src, min_freq = MIN_FREQ)
        TGT.build_vocab (train.trg, min_freq = MIN_FREQ)  

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

    Итераторы

      класс MyIterator (data.Iterator):
        def create_batches (сам):
            если self.train:
                def pool (d, random_shuffler):
                    для p в data.batch (d, self.batch_size * 100):
                        p_batch = data.batch (
                            отсортировано (p, key = self.sort_key),
                            self.batch_size, self.batch_size_fn)
                        для b в random_shuffler (список (p_batch)):
                            выход b
                я.партии = пул (self.data (), self.random_shuffler)
                
            еще:
                self.batches = []
                для b в data.batch (self.data (), self.batch_size,
                                              self.batch_size_fn):
                    self.batches.append (отсортировано (b, key = self.sort_key))
    
    def rebatch (pad_idx, batch):
        "Исправьте порядок в тексте факела, чтобы он соответствовал нашему"
        src, trg = batch.src.transpose (0, 1), batch.trg.transpose (0, 1)
        return Batch (src, trg, pad_idx)  

    Обучение работе с несколькими GPU

    Наконец, чтобы действительно нацелиться на быстрое обучение, мы будем использовать multi-gpu.Этот код реализует генерацию слов с несколькими графическими процессорами. Это не относится к трансформатору, поэтому я не буду вдаваться в подробности. Идея состоит в том, чтобы разделить генерацию слов на время обучения на куски, которые будут обрабатываться параллельно во многих различных gpus. Мы делаем это с помощью параллельных примитивов pytorch:

    • replicate - разделение модулей на разные графические процессоры.
    • scatter - разбивать партии на разные графические процессоры
    • parallel_apply - применить модуль к пакетам на разных gpus
    • gather - вернуть разрозненные данные на один графический процессор.
    • nn.DataParallel - специальная оболочка модуля, которая вызывает все это раньше оценка.
      # Пропустить, если мультигпу не интересует.
    класс MultiGPULossCompute:
        «Функция вычисления потерь с несколькими графическими процессорами и функция обучения».
        def __init __ (себя, генератор, критерий, устройства, opt = None, chunk_size = 5):
            # Отправлять на разные видеокарты.
            self.generator = генератор
            self.criterion = nn.parallel.replicate (критерий,
                                                   устройства = устройства)
            я.opt = opt
            self.devices = устройства
            self.chunk_size = chunk_size
            
        def __call __ (я, выход, цели, нормализация):
            всего = 0,0
            генератор = nn.parallel.replicate (self.generator,
                                                    devices = self.devices)
            out_scatter = nn.parallel.scatter (out,
                                              target_gpus = self.devices)
            out_grad = [[] для _ in out_scatter]
            target = nn.parallel.scatter (цели,
                                          target_gpus = себя.устройства)
    
            # Разделить генерацию на куски.
            chunk_size = self.chunk_size
            для i в диапазоне (0, out_scatter [0] .size (1), chunk_size):
                # Прогнозировать распределения
                out_column = [[Переменная (o [:, i: i + chunk_size] .data,
                                        requires_grad = self.opt не равно None)]
                               для o в out_scatter]
                gen = nn.parallel.parallel_apply (генератор, выходной_столбец)
    
                # Вычислить потери.
                y = [(g.contiguous ().view (-1, g.size (-1)),
                      t [:, i: i + chunk_size] .contiguous (). view (-1))
                     для g, t в zip (gen, target)]
                потеря = nn.parallel.parallel_apply (self.criterion, y)
    
                # Суммировать и нормализовать убыток
                l = nn.parallel.gather (потеря,
                                       target_device = self.devices [0])
                l = l.sum () [0] / нормализовать
                total + = l.data [0]
    
                # Обратные потери на выходе трансформатора
                если self.opt не равен None:
                    л.назад ()
                    для j, l в enumerate (убыток):
                        out_grad [j] .append (out_column [j] [0] .grad.data.clone ())
    
            # Обратить все потери через трансформатор.
            если self.opt не равен None:
                out_grad = [переменная (torch.cat (og, dim = 1)) для og в out_grad]
                o1 = out
                o2 = nn.parallel.gather (out_grad,
                                        target_device = self.devices [0])
                o1.backward (градиент = o2)
                self.opt.step ()
                я.opt.optimizer.zero_grad ()
            общая сумма возврата * нормализовать  

    Теперь мы создаем нашу модель, критерий, оптимизатор, итераторы данных и параллелизация

      # GPU для использования
    устройства = [0, 1, 2, 3]
    если правда:
        pad_idx = TGT.vocab.stoi ["<пусто>"]
        модель = make_model (len (SRC.vocab), len (TGT.vocab), N = 6)
        model.cuda ()
        критерий = LabelSmoothing (размер = len (TGT.vocab), padding_idx = pad_idx, сглаживание = 0,1)
        критерий.cuda ()
        BATCH_SIZE = 12000
        train_iter = MyIterator (поезд, batch_size = BATCH_SIZE, устройство = 0,
                                repeat = False, sort_key = лямбда x: (len (x.SRC), len (x.trg)),
                                batch_size_fn = batch_size_fn, train = True)
        valid_iter = MyIterator (val, batch_size = BATCH_SIZE, device = 0,
                                repeat = False, sort_key = лямбда x: (len (x.src), len (x.trg)),
                                batch_size_fn = batch_size_fn, train = False)
        model_par = nn.DataParallel (модель, device_ids = устройства)
    Нет  

    Теперь обучаем модель. Я немного поиграю с шагами разминки, но все остальное использует параметры по умолчанию.На AWS p3.8xlarge с 4 Тесла V100s, это работает со скоростью ~ 27000 токенов в секунду с размером пакета 12000

    .

    Обучение системы

      #! Wget https://s3.amazonaws.com/opennmt-models/iwslt.pt  
      если ложно:
        model_opt = NoamOpt (model.src_embed [0] .d_model, 1, 2000,
                torch.optim.Adam (модель.параметры (), lr = 0, бета-версия = (0,9, 0,98), eps = 1e-9))
        для эпохи в диапазоне (10):
            model_par.train ()
            run_epoch ((rebatch (pad_idx, b) для b в train_iter),
                      model_par,
                      MultiGPULossCompute (модель.генератор, критерий,
                                          devices = devices, opt = model_opt))
            model_par.eval ()
            loss = run_epoch ((rebatch (pad_idx, b) для b в valid_iter),
                              model_par,
                              MultiGPULossCompute (модель, генератор, критерий,
                              devices = devices, opt = None))
            печать (потеря)
    еще:
        model = torch.load ("iwslt.pt")  

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

      для i, пакет в enumerate (valid_iter):
        src = batch.src.transpose (0, 1) [: 1]
        src_mask = (src! = SRC.vocab.stoi [""]). unsqueeze (-2)
        out = greedy_decode (модель, src, src_mask,
                            max_len = 60, start_symbol = TGT.vocab.stoi [""])
        print ("Перевод:", end = "\ t")
        для i в диапазоне (1, out.размер (1)):
            sym = TGT.vocab.itos [out [0, i]]
            если sym == "": перерыв
            print (sym, end = "")
        Распечатать()
        print ("Цель:", end = "\ t")
        для i в диапазоне (1, batch.trg.size (0)):
            sym = TGT.vocab.itos [batch.trg.data [i, 0]]
            если sym == "": перерыв
            print (sym, end = "")
        Распечатать()
        break  
      Перевод:. На моем языке это означает большое спасибо.
    Золото:. На моем языке это означает, большое спасибо. 

    Таким образом, это в основном касается самой модели трансформатора. Есть четыре аспекта которые мы не раскрывали прямо. У нас также есть все эти дополнительные функции реализовано в OpenNMT-py.

    1) BPE / Word-piece: мы можем использовать библиотеку для предварительной обработки данных в подсловные единицы. См. Подслово Рико Сеннриха - Реализация nmt. Эти модели будут преобразуйте данные обучения, чтобы они выглядели так:

    E - Mail FTP FTP an Bestimmte n Empfänger gesendet erden.

    2) Общие вложения: при использовании BPE с общим словарем мы можем поделиться одинаковые весовые векторы между источником / целью / генератором. Увидеть (цитировать) для подробностей. Чтобы добавить это в модель просто сделайте это:

      если ложь:
        model.src_embed [0] .lut.weight = model.tgt_embeddings [0] .lut.weight
        model.generator.lut.weight = model.tgt_embed [0] .lut.weight  

    3) Поиск луча: это слишком сложно, чтобы здесь описывать. См. OpenNMT- ру для реализации pytorch.

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

      по умолчанию (модель, модели):
        «Средние модели в модели»
        для ps в zip (* [m.params () для m в [модель] + модели]):
            p [0] .copy_ (torch.sum (* ps [1:]) / len (ps [1:]))  

    По заданию WMT 2014 по переводу с английского на немецкий, модель большого трансформатора (Трансформатор (большой) в Таблице 2) превосходит лучшие ранее представленные модели (включая ансамбли) более чем на 2.0 BLEU, установив новый современный рейтинг BLEU 28,4. Конфигурация этой модели указаны в нижней строке таблицы 3. Обучение длилось 3,5 дня на 8 графических процессорах P100. Даже наша базовая модель превосходит все ранее опубликованные модели и ансамбли на долю стоимость обучения любого из конкурентные модели.

    В задаче перевода с английского на французский язык WMT 2014 наша большая модель достигает Оценка BLEU 41,0, превосходит все ранее опубликованные одиночные модели, менее чем на 1/4 стоимость обучения предыдущая ультрасовременная модель.Модель Transformer (big), обученная для С английского на французский используется коэффициент отсева Pdrop = 0,1 вместо 0,3.

      Изображение (filename = "images / results.png")  

    Код, который мы здесь написали, является версией базовой модели. Есть полностью обученная версия этой системы доступна здесь (Пример Модели).

    С дополнительными расширениями в последнем разделе репликация OpenNMT-py достигает 26,9 на EN-DE WMT. Я загрузил эти параметры в наш повторная реализация.

     ! Wget https://s3.amazonaws.com/opennmt-models/en-de-model.pt  
     Модель , SRC, TGT = torch.load ("en-de-model.pt")  
      модель. Вал ()
    sent = "log файл can журнала sent можно послать тайно с помощью электронной почты или FTP указанному получателю» .split ()
    src = torch.LongTensor ([[SRC.stoi [w] вместо w в отправлено]])
    src = переменная (src)
    src_mask = (src! = SRC.stoi [""]). unsqueeze (-2)
    out = greedy_decode (модель, src, src_mask,
                        max_len = 60, start_symbol = TGT.stoi [""])
    print ("Перевод:", end = "\ t")
    транс = ""
    для i в диапазоне (1, out.size (1)):
        sym = TGT.itos [out [0, i]]
        если sym == "": перерыв
        транс + = сим + ""
    print (trans)  
      Перевод:  Die Protokoll datei kann heimlich per E - Mail oder FTP an.
      

    Визуализация внимания

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

      tgt_sent = trans.split ()
    def draw (data, x, y, ax):
        seaborn.heatmap (данные,
                        xticklabels = x, square = True, yticklabels = y, vmin = 0,0, vmax = 1,0,
                        cbar = False, ax = ax)
        
    для слоя в диапазоне (1, 6, 2):
        fig, axs = plt.subplots (1,4, figsize = (20, 10))
        print ("Слой кодировщика", слой + 1)
        для h в диапазоне (4):
            draw (model.encoder.layers [слой].self_attn.attn [0, h] .data,
                отправлено, отправлено, если h == 0 else [], ax = axs [h])
        plt.show ()
        
    для слоя в диапазоне (1, 6, 2):
        fig, axs = plt.subplots (1,4, figsize = (20, 10))
        print («Слой собственного декодера», слой + 1)
        для h в диапазоне (4):
            draw (model.decoder.layers [слой] .self_attn.attn [0, h] .data [: len (tgt_sent),: len (tgt_sent)],
                tgt_sent, tgt_sent, если h == 0 else [], ax = axs [h])
        plt.show ()
        print ("Decoder Src Layer", слой + 1)
        fig, axs = plt.subplots (1,4, figsize = (20, 10))
        для h в диапазоне (4):
            draw (модель.decoder.layers [слой] .self_attn.attn [0, h] .data [: len (tgt_sent),: len (отправлено)],
                отправлено, tgt_sent, если h == 0 else [], ax = axs [h])
        plt.show ()  

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

      @inproceedings {opennmt,
      author = {Гийом Кляйн и
                   Юн Ким и
                   Юньтянь Дэн и
                   Жан Сенеллар и
                   Александр М. Раш},
      title = {OpenNMT: набор инструментов с открытым исходным кодом для нейронного машинного перевода},
      booktitle = {Proc. ACL},
      год = {2017},
      url = {https://doi.org/10.18653/v1/P17-4012},
      doi = {10.18653 / v1 / P17-4012}
    }
      

    Ура, srush

    Пожалуйста, включите JavaScript для просмотра комментариев, предоставленных Disqus.

    Пожалуйста, включите JavaScript для просмотра комментариев, предоставленных Disqus.

    Глоссарий - трансформаторы 4.2.0 документация

    Входные данные модели

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

    Идентификаторы входа

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

    Каждый токенизатор работает по-разному, но основной механизм остается прежним. Вот пример использования BERT tokenizer, который является токенизатором WordPiece:

     >>> из трансформаторов импортных BertTokenizer
    >>> tokenizer = BertTokenizer.from_pretrained ("bert-base-cased")
    
    >>> sequence = "Titan RTX имеет 24 ГБ видеопамяти"
     

    Токенизатор заботится о разделении последовательности на токены, доступные в словаре токенизатора.

     >>> tokenized_sequence = tokenizer.tokenize (последовательность)
     

    Жетонами являются слова или подслова. Здесь, например, слова «VRAM» не было в словаре модели, поэтому оно было разделено в «В», «РА» и «М». Чтобы указать, что эти токены не являются отдельными словами, а частями одного и того же слова, используется префикс с двойным хешем. добавляется для «РА» и «М»:

     >>> печать (tokenized_sequence)
    ['A', 'Titan', 'R', '## T', '## X', 'has', '24', '## GB', 'of', 'V', '## БАРАН']
     

    Затем эти токены можно преобразовать в идентификаторы, понятные для модели.Это можно сделать путем прямого кормления предложение токенизатору, которое использует реализацию huggingface / tokenizers Rust для максимальной производительности.

     >>> input = tokenizer (последовательность)
     

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

     >>> encoded_sequence = inputs ["input_ids"]
    >>> print (encoded_sequence)
    [101, 138, 18696, 155, 1942, 3190, 1144, 1572, 13745, 1104, 159, 9664, 2107, 102]
     

    Обратите внимание, что токенизатор автоматически добавляет «специальные токены» (если связанная модель полагается на них), которые являются специальными ID, которые иногда использует модель.

    Если мы декодируем предыдущую последовательность идентификаторов,

     >>> decoded_sequence = tokenizer.decode (encoded_sequence)
     

    мы увидим

     >>> печать (decoded_sequence)
    [CLS] Titan RTX имеет 24 ГБ видеопамяти [SEP]
     

    , потому что именно так BertModel будет ожидать своих входных данных.

    Маска внимания

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

    Например, рассмотрим эти две последовательности:

     >>> из трансформаторов импортных BertTokenizer
    >>> tokenizer = BertTokenizer.from_pretrained ("bert-base-cased")
    
    >>> sequence_a = "Это короткая последовательность."
    >>> sequence_b = "Это довольно длинная последовательность. Она как минимум длиннее, чем последовательность A."
    
    >>> encoded_sequence_a = tokenizer (sequence_a) ["input_ids"]
    >>> encoded_sequence_b = tokenizer (sequence_b) ["input_ids"]
     

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

     >>> len (encoded_sequence_a), len (encoded_sequence_b)
    (8, 19)
     

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

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

     >>> padded_sequences = tokenizer ([sequence_a, sequence_b], padding = True)
     

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

     >>> padded_sequences ["input_ids"]
    [[101, 1188, 1110, 170, 1603, 4954, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [101, 1188, 1110, 170, 1897, 1263, 4954, 119, 1135, 1110, 1120, 1655, 2039, 1190, 1103, 4954, 138, 119, 102]]
     

    Затем его можно преобразовать в тензор в PyTorch или TensorFlow.Маска внимания - это двоичный тензор, указывающий положение заполненных индексов так, чтобы модель не обращала на них внимания. Для BertTokenizer , 1 указывает значение, на которое следует обратить внимание, а 0 указывает дополненное значение. Эта маска внимания в словаре, возвращаемом токенизатором под ключом «маска_ внимания»:

     >>> padded_sequences ["маска_ внимания"]
    [[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
     

    Идентификаторы типа токена

    Назначение некоторых моделей - классификация последовательностей или ответы на вопросы.Для этого требуются две разные последовательности быть объединенными в единую запись input_ids, которая обычно выполняется с помощью специальных токенов, таких как классификатор ( [CLS] ) и разделитель ( [SEP] ) токенов. Например, модель BERT строит свои входные данные с двумя последовательностями как такой:

     >>> # [CLS] SEQUENCE_A [SEP] SEQUENCE_B [SEP]
     

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

     >>> из трансформаторов импортных BertTokenizer
    >>> токенизатор = BertTokenizer.from_pretrained ("с опорой на причал")
    >>> sequence_a = "HuggingFace находится в Нью-Йорке"
    >>> sequence_b = "Где основан HuggingFace?"
    
    >>> encoded_dict = токенизатор (последовательность_a, последовательность_b)
    >>> decoded = tokenizer.decode (encoded_dict ["input_ids"])
     

    , который вернет:

     >>> печать (расшифровано)
    [CLS] HuggingFace находится в Нью-Йорке [SEP] Где находится HuggingFace? [SEP]
     

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

    Токенизатор возвращает эту маску как запись «token_type_ids»:

     >>> encoded_dict ['token_type_ids']
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     

    Первая последовательность, «контекст», использованная для вопроса, имеет все свои токены, представленные 0 , тогда как Во второй последовательности, соответствующей «вопросу», все токены представлены как 1 .

    В некоторых моделях, например XLNetModel , используется дополнительный токен, представленный 2 .

    Идентификаторы позиций

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

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

    Абсолютные позиционные вложения выбираются в диапазоне [0, config.max_position_embeddings - 1] . Некоторые модели используют другие типы позиционных вложений, такие как встраивания синусоидального положения или встраивания относительного положения.

    Этикетки

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

    Эти ярлыки различаются в зависимости от модели головки, например:

    • Для моделей классификации последовательностей (например, BertForSequenceClassification ) модель ожидает тензор размерности (batch_size) с каждым значением пакета, соответствующим ожидаемой метке вся последовательность.

    • Для моделей классификации токенов (например, BertForTokenClassification ) модель ожидает тензор измерения (batch_size, seq_length) с каждым значением, соответствующим ожидаемой метке каждого индивидуума токен.

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

    • Для последовательности задач, (например, BartForConditionalGeneration , MBartForConditionalGeneration ) модель ожидает тензор размерности (batch_size, tgt_seq_length) с каждым значением, соответствующим целевым последовательностям, связанным с каждой входной последовательностью.В течение обучение, как BART , так и T5 сделают соответствующие decoder_input_ids и маски внимания декодера внутренне. Их обычно не нужно поставлять. Это не относится к моделям, использующим структуру Encoder-Decoder. Видеть документацию каждой модели для получения дополнительной информации на этикетках каждой конкретной модели.

    Базовые модели (например, BertModel ) не принимают ярлыки, так как они являются базовым трансформатором. модели, просто выводя функции.

    Идентификаторы входа декодера

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

    Большинство моделей кодеров-декодеров (BART, T5) создают свои decoder_input_ids самостоятельно из меток . В такие модели, проходящие по меткам - предпочтительный способ обучения.

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

    Блоки с прямой подачей

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

    Для входа размером [batch_size, sequence_length] , память, необходимая для хранения промежуточной прямой связи вложения [размер_пакции, длина_последовательности, конфиг.промежуточный_размер] может занимать большую часть памяти использовать. Авторы Reformer: The Efficient Transformer заметили, что с вычисление не зависит от размера sequence_length , это математически эквивалентно вычислению вывода встраивание обоих слоев прямой связи [размер_пакета, размер_конфигурации] _0, ..., [размер_пакета, размер_конфигурации] _n индивидуально и затем объединить их в [размер_пакета, длина_последовательности, config.hidden_size] с n = sequence_length , в котором увеличенное время вычислений сочетается с уменьшением использования памяти, но дает математически эквивалент результата.

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

    .

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

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