Обзор исследований в области глубокого обучения: обработка естественных языков

МЕНЮ


Искусственный интеллект
Поиск
Регистрация на сайте
Помощь проекту

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости



Это третья статья из серии “Обзор исследований в области глубокого обучения” (Deep Learning Research Review) студента Калифорнийского университета в Лос-Анджелесе Адита Дешпанда (Adit Deshpande). Каждые две недели Адит публикует обзор и толкование исследований в определенной области глубинного обучения. В этот раз он сосредоточил свое внимание на применении глубокого обучения для обработки текстов на естественном языке.

Введение в обработку естественных языков

Введение

Под обработкой естественных языков (Natural Language Processing, NLP) понимается создание систем, обрабатывающих или “понимающих” язык с целью выполнения определенных задач. Эти задачи могут включать:
  • Формирование ответов на вопросы (Question Answering) (то, что делают Siri, Alexa и Cortana)
  • Анализ эмоциональной окраски высказываний (Sentiment Analysis) (определение, имеет ли высказывание положительную или отрицательную коннотацию)
  • Нахождение текста, соответствующего изображению (Image to Text Mappings) (генерация подписи к входному изображению)
  • Машинный перевод (Machine Translation) (перевод абзаца текста с одного языка на другой)
  • Распознавание речи (Speech Recognition)
  • Морфологическая разметка (Part of Speech Tagging) (определение частей речи в предложении и их аннотирование)
  • Извлечение сущностей (Name Entity Recognition)

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

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

Мы понимаем, что приставка (prefix) un- означает отрицание, и знаем, что -ed может означать время, к которому относится данное слово (в данном случае – прошедшее время). Распознав значение однокоренного слова interest, мы легко можем сделать вывод о значении и эмоциональной окраске всего слова. Вроде бы просто. Тем не менее, если принять во внимание все многообразие приставок и суффиксов английского языка, понадобится очень умелый лингвист, чтобы понять все возможные комбинации и их значения.


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

Как использовать глубокое обучение

В основе глубокого обучения лежит обучение представлениям. Например, сверточные нейронные сети (Convolutional Neural Network, CNN) включают в себя объединение различных фильтров, предназначенных для классификации объектов по категориям. Здесь мы попытаемся применить похожий подход, создавая представления слов в больших наборах данных.

Структура статьи

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

Векторы слов

Так как глубокое обучение не может жить без математики, представим каждое слово в виде d-мерного вектора. Возьмем d=6.

Теперь подумаем, как заполнить значения. Мы хотим, чтобы вектор был заполнен таким образом, чтобы он каким-то образом представлял слово и его контекст, значение или семантику. Один из способов – построить матрицу совместной встречаемости (cooccurrence matrix). Рассмотрим следующее предложение:

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

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


Строки этой матрицы могут служить в качестве векторных представлений наших слов.

Обратите внимание, что даже из этой простой матрицы мы можем почерпнуть довольно важные сведения. Например, заметим, что векторы слов “love” и “like” содержат единицы в ячейках, отвечающих за их соседство с существительными (“NLP” и “dogs”). У них также стоит “1” там, где они соседствуют с “I”, показывая, что это слово, скорее всего, глагол. Можете себе представить, насколько проще выявлять подобные схожие черты, когда набор данных больше, чем одно предложение: в этом случае векторы таких глаголов, как “love”, “like” и других синонимов, будут похожи, так как эти слова будут использоваться в схожих контекстах.

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

Word2Vec

Главная цель всех методов инициализации вектора слова – хранить в этом векторе как можно больше информации, сохраняя разумную размерность (в идеале, от 25 до 1000). В основе Word2Vec лежит идея научиться прогнозировать окружающие слова для каждого слова. Рассмотрим предложение из предыдущего примера: “I love NLP and I like dogs”. Сейчас нас интересуют только три первые слова. Пусть размер нашего окна и будет равен трем.
Теперь мы хотим взять центральное слово “love” и предсказать слова, идущие до и после него. Как же мы это осуществим? Конечно же, с помощью максимизации и оптимизации функции! Формально наша функция пытается максимизировать логарифмическую вероятность каждого слова-контекста для текущего центрального слова.

Изучим вышеприведенную формулу подробнее. Из нее следует, что мы будем складывать логарифмическую вероятность совместной встречаемости как “I” и “love”, так и “NLP” и “love” (в обоих случаях “love” – центральное слово). Переменная T означает количество обучающих (training) предложений. Рассмотрим логарифмическую вероятность поближе.

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

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

(Дополнительно: дальше авторы работы подробно рассказывают о том, как с помощью негативного семплирования (negative sampling) и взятия подвыборок (subsampling) можно получить более точные векторы слов).

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

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

Бонус: еще один классный метод инициализации векторов слов – GloVe (Global Vector for Word Representation) (сочетает идеи матрицы совместной встречаемости с Word2Vec).

Рекуррентные нейронные сети (Recurrent Neural Networks, RNN)

Теперь посмотрим, как с нашими векторами будет работать рекуррентная нейронная сеть. RNN – палочка-выручалочка для большинства современных задач обработки естественного языка. Главное преимущество RNN в том, что они могут эффективно использовать данные с предыдущих шагов. Вот так выглядит маленький кусочек RNN:
Внизу изображены векторы слов ($x_t, x_{t-1}, x_{t+1}$). У каждого вектора на каждом шаге есть скрытый вектор состояния (hidden state vector) ($h_t, h_{t-1}, h_{t+1}$). Будем называть эту пару модулем (module).

Скрытое состояние в каждом модуле RNN – это функция от вектора слова и вектора скрытого состояния с прошлого шага.

Если мы приглядимся к верхним индексам, то увидим, что здесь есть матрица весов $W^{hx}$, которую мы умножаем на входное значение, и есть рекуррентная матрица весов $W^{hh}$, которая умножается на вектор скрытого состояния с предыдущего шага. Имейте в виду, что эти рекуррентные матрицы весов на каждом шаге одинаковы. Это ключевой момент RNN. Если тщательно обдумать, то этот подход значительно отличается от, скажем, традиционных двухслойных нейронных сетей. В этом случае у нас обычно выбирается отдельная матрица W для каждого слоя: $W_1$ и $W_2$. Здесь же рекуррентная матрица весов одна и та же для всей сети.

Для получения выходных значений каждого модуля (Yhat) служит еще одна матрица весов – $W^s$, умноженная на h.


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

Управляемые рекуррентные нейроны (Gated recurrent units, GRU)

Теперь давайте познакомимся с понятием управляемого рекуррентного нейрона, с помощью которых производится вычисление векторов скрытых состояний в RNN. Такой подход позволяет сохранять информацию о более отдаленных зависимостях. Давайте порассуждаем о том, почему отдаленные зависимости для обычных RNN могут стать проблемой. В время работы метода обратного распространения ошибки (backpropagation) ошибка будет двигаться по RNN от последнего шага к самому раннему. При достаточно малом начальном градиенте (скажем, менее 0.25) к третьему или четвертому модулю градиент почти исчезнет (так как по правилу производной сложной функции градиенты будут перемножаться), и тогда скрытые состояния самых первых шагов не обновятся. В обычных RNN вектор скрытых состояний вычисляется по следующей формуле:

Метод GRU позволяет вычислять h(t) иначе. Вычисления разбиваются на три блока: фильтр обновления (update gate), фильтр сброса состояния (reset gate) и новый контейнер памяти (memory container). Обы фильтра – функции от входного векторного представления слова и скрытого состояния на предыдущем шаге.

Главное отличие состоит в том, что для каждого фильтра используются свои веса. Это обозначено разными верхними индексами. Фильтр обновления использует $W^z$ и $U^z$, а фильтр сброса состояния – $W^r$ и $U^r$.
Теперь рассчитаем контейнер памяти:

(пустой кружок здесь обозначает произведение Адамара).

Теперь, если присмотреться к формуле, то можно заметить, что если множитель фильтра сброса состояния близок к нулю, то и все произведение также приблизится к нулю, и таким образом, информация из предыдущего шага $h_{t-1}$ не будет учтена. В этом случай нейрон – всего лишь функция от нового вектора слова $x_{t-1}$.

Окончательную формулу h(t) можно записать как

$h_t$ – функция от всех трех компонентов: фильтра обновления, фильтра сброса состояния и контейнера памяти. Можно лучше понять это, визуализируя, что происходит с формулой, когда $z_t$ близится к 1 и когда $z_t$ близко к 0. В первом случай вектор скрытого состояния $h_t$ в большей степени зависит от предыдущего скрытого состояния, а текущий контейнер памяти не принимается во внимание, так как (1 – $z_t$) стремится к 0. Когда же $z_t$ близится к 1, новый вектор скрытого состояния $h_t$, наоборот, зависит в основном от контейнера памяти, а предыдущее скрытое состояние не учитывается. Итак, наши три компонента можно интуитивно описать следующим образом:

  • Фильтр обновления
    • Если $z_t$ ~ 1, то $h_t$ не принимает во внимание текущий вектор слова и просто копирует предыдущее скрытое состояние.
    • Если $z_t$ ~ 0, то $h_t$ не учитывает предыдущее скрытое состояние и зависит только от контейнера памяти.
    • Этот фильтр позволяет модели контролировать, как много информации от предыдущего скрытого состояния должно влиять на текущее скрытое состояние.
  • Фильтр сброса состояния
    • Если $r_t$ ~ 1, то контейнер памяти сохраняет информацию с предыдущего скрытого состояния.
    • Если $r_t$ ~ 0, то контейнер памяти не учитывает предыдущее скрытое состояние.
    • Этот фильтр позволяет отбросить часть информации, если в будущем она не будет нас интересовать.
  • Контейнер памяти: зависит от фильтра сброса состояния.

Приведем пример, иллюстрирующий работу GRU. Допустим, у нас есть следующие несколько предложений:

и вопрос: “Чему равна сумма двух чисел?” Так как предложение посередине никак не влияет на ответ, фильтры сброса и обновления позволят модели “забыть” это предложение и понять, что изменять скрытое состояние может только определенная информация (в данном случае, числа).

Нейроны с длительной кратковременной памятью (Long short-term memory, LSTM)

Если вы разобрались с GRU, то LSTM не составит для вас трудности. LSTM также состоит из последовательности фильтров.
LSTM определенно принимает на вход больше информации. Так как ее можно считать расширением GRU, я не буду разбирать ее подробно, а чтобы получить детальное описание каждого фильтра и каждого шага вычислений, вы можете обратиться к прекрасно написанному блог-посту Криса Олаха (Chris Olah). На текущий момент это самый популярный тьюториал по LSTM, и точно поможет тем из вас, кто ищет понятное и интуитивное объяснение работы этого метода.

Сравнение LSTM и GRU

Сначала рассмотрим общие черты. Оба эти метода разработаны для того, чтобы сохранять отдаленные зависимости в последовательностях слов. Под отдаленными зависимостями имеются в виду такие ситуации, когда два слова или фразы могут встретиться на разных временных шагах, но отношения между ними важны для достижения конечной цели. LSTM и GRU отслеживают эти отношения с помощью фильтров, которые могут сохранять или сбрасывать информацию из обрабатываемой последовательности. Различие между двумя методами состоит в количестве фильтров (GRU – 2, LSTM – 3). Это влияет на количество нелинейностей, которое приходит от входных данных и в конечном итоге влияет на процесс вычислений. Кроме того, в GRU отсутствует ячейка памяти $c_t$, как в LSTM.

Перед тем, как углубиться в статьи

Хотел бы сделать небольшое замечание. Если и другие модели глубокого обучения, полезные в NLP. На практике иногда используются рекурсивные и сверточные нейронные сети, хотя они не так распространены, как RNN, которые лежат в основе большинства NLP-систем глубокого обучения. Теперь, когда мы начали хорошо разбираться в рекуррентных нейронных сетях применительно к NLP, давайте ознакомимся с некоторыми работами в этой области. Так как NLP включает в себя несколько различных областей задач (от машинного перевода до формирования ответов на вопросы), мы могли бы рассмотреть довольно много работ, но я выбрал те три, которые нашел особенно информативными. В 2016 году случился ряд серьезных продвижений в области NLP, но начнем с одной работы 2015 года.

Нейронные сети с памятью (Memory Networks)

Введение

Первая работа, которую мы обсудим, оказала большое влияние на развитие области формирования ответов на вопросы. В этой публикации авторства Джейсона Вестона (Jason Weston), Сумита Чопры (Sumit Chopra) и Антуана Бордеса (Antoine Bordes) был впервые описан класс моделей под названием ”сети с памятью”. Интуитивно-понятная идея состоит в следующем: для того, чтобы точно ответить на вопрос, относящийся к фрагменту текста, необходимо каким-то образом хранить предоставленную нам исходную информацию. Если бы я спросил вас: “Что означает аббревиатура RNN?”, вы смогли бы ответить мне, потому что информация, которую вы усвоили, читая первую часть статьи, сохранилась где-то в вашей памяти. Вам понадобилось бы лишь несколько секунд, чтобы найти эту информацию и озвучить ее. Я понятия не имею, как это получается у мозга, но мысль о том, что необходимо пространство для хранения этой информации, остается неизменной.

Сеть с памятью, описанная в данной работе, уникальна, так как у нее есть ассоциативная память, в которую она может писать и из которой она может читать. Интересно заметить, что подобную память не используют ни CNN, ни Q-Network (для обучения с подкреплением (reinforcement learning), ни традиционные нейронные сети. Это отчасти связано с тем, что задача формирования ответов на вопросы в большой степени полагается на способность моделировать или прослеживать отдаленные зависимости, например, следить за героями истории или запоминать последовательность событий. В CNN или Q-Networks память как бы встроена в веса системы, так как она обучается различным фильтрам или картам соответствий состояний и действий. На первый взгляд, можно было бы использовать RNN или LSTM, но обычно они не способны запоминать входные данные из прошлого (что является критичным для задач формирования ответов на вопросы).

Архитектура сети

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

Память m можно рассматривать как подобие массива, составленного из отдельных блоков памяти $m_i$. Каждый такой блок $m_i$ может быть функцией от всей памяти m, представления в пространстве признаков I(x) и/или самого себя. Функция G может просто хранить все представление I(x) в блоке памяти mi. Функцию G можно изменить так, чтобы она обновляла память о прошлом на основе новых входных данных. Третий и четвертый шаги включают в себя чтение из памяти с учетом вопроса, чтобы найти представление признаков o, и его декодирование, чтобы получить окончательный ответ r.

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

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

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

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

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


Tree-LSTM для анализа эмоциональной окраски высказываний

Введение

Следующая работа рассказывает о прогрессе в области анализа эмоциональной окраски – задачи определения, имеет высказывание положительную или отрицательную коннотацию (значение). Формально эмоциональную окраску можно определить как “взгляд на ситуацию или событие или отношение к ним”. На тот момент наиболее распространенным инструментом для задач распознавания эмоциональной окраски были LSTM. Работа авторства Кай Шенг Тай (Kai Sheng Tai), Ричарда Сочера (Richard Socher) и Кристофера Маннинга (Christopher Manning) вводит принципиально новый способ объединения нескольких LSTM-нейронов в нелинейную структуру. Идея нелинейного расположения компонентов основана на мнении, что естественные языки демонстрируют свойство превращать последовательности слов в фразы. Эти фразы, в зависимости от порядка слов, могут иметь значение, отличное от исходного значения входящих в них компонентов. Чтобы отразить это свойство, сеть из нескольких LSTM-нейронов следует представить в виде дерева, где на каждый нейрон влияют его дочерние узлы.

Архитектура сети

Одно из отличий Tree-LSTM от обычного LSTM состоит в том, что во последнем скрытое состояние – функция от текущих входных данных и и скрытого состояния на предыдущем шаге. В Tree-LSTM скрытое состояние – функция от текущих входных данных и скрытых состояний его дочерних нейронов.

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

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

Нейронный машинный перевод (Neural Machine Translation, NMT)

Введение

Последняя работа, которую мы сегодня рассмотрим, описывает подход к решению задачи машинного перевода. Авторы этой работы – специалисты Google по машинному обучению Джефф Дин (Jeff Dean), Грег Коррадо (Greg Corrado), Ориал Виньялс (Orial Vinyals) и другие – представляют систему машинного обучения, которая лежит в основе широко известного сервиса Google Translate. С введением этой системы количество ошибок перевода сократилось в среднем на 60% по сравнению с прежней системой, используемой Google. Традиционные подходы к автоматическому переводу включают в себя нахождение пофразовых соответствий. Этот подход требовал хорошего знания лингвистики и в конце концов оказался недостаточно стабильным и неспособным к генерализации. Одна из проблем традиционного подхода состояла в том, что исходное предложение переводилось по кусочкам. Оказалось, что переводить все предложение за раз (как это делает NMT) более эффективно, так как в этом случае вовлекается более широкий контекст и порядок слов становится более естественным.

Архитектура сети

Авторы этой статьи описывают глубокую сеть LSTM, которая может быть от обучена с помощью восьми слоем энкодеров и декодеров. Мы можем разделить систему на три компонента: энкодер RNN, декодер RNN и модуль “внимания” (attention module). Энкодер работает над задачей преобразования входного предложения в векторное представление, декодер возвращает выходное представление, затем модуль внимания сообщает декодеру, на чем следует заострить внимание во время операции декодирования (здесь вступает идея использования всего контекста предложения).
Далее статья уделяет внимание проблемам, связанным с развертыванием и масштабированием данного сервиса. В ней обсуждаются такие темы, как вычислительные ресурсы, время задержки и массовое развертывание сервиса.

Заключение

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

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

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

Присоединяйтесь к нашей команде: wunderfund.io


Источник: habrahabr.ru

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