В этом посте мы рассмотрим одну из самых сложных, но интересных проблем обработки естественного языка, также известную как ответы на вопросы. Мы будем внедрять QANet Google в Tensorflow. Как и его аналог машинного перевода Трансформаторная сеть, QANet вообще не использует RNN, что ускоряет обучение / тестирование. (Исходный код этого эксперимента можно найти здесь)
Я предполагаю, что у вас уже есть некоторые знания о Python и Tensorflow.
Вопросы и ответы - это область компьютерных наук, в которой за последние несколько лет произошел быстрый прогресс. Классический пример ответов на вопросы - участие IBM’s Watson в знаменитой викторине Jeopardy! в 2011 году он встретился с легендарными чемпионами Брэдом Раттером и Кеном Дженнингсом и занял первое место.
В этом посте мы сосредоточимся на понимании прочитанного в открытой области, где вопросы могут поступать из любой области, от американских поп-звезд до абстрактных концепций. Понимание прочитанного - это тип ответа на вопрос, при котором нам дается абзац и задаются вопросы, специально выбранные для ответа из абзаца.
Набор данных (SQuAD)
Набор данных, который мы будем использовать для этого поста, называется Стэнфордский набор данных с ответами на вопросы (SQuAD). У SQuAD есть некоторые проблемы, к которым мы еще вернемся, и это, возможно, не лучший набор данных для понимания машинного чтения, но наиболее широко изученный. Если вам интересно узнать о различных наборах данных, доступных для понимания прочитанного, ознакомьтесь также с этим Удивительным списком наборов данных НЛП.
Одним из отличительных факторов SQuAD является то, что ответ на вопрос находится внутри самого абзаца. Вот пример формата SQuAD.
Как видно из приведенного выше примера, независимо от того, насколько простым или сложным может быть вопрос, ответ на этот вопрос всегда находится внутри самого абзаца.
Но сначала давайте посмотрим, какие вопросы и ответы мы ожидаем найти. Чаще всего вопросы сами по себе являются уже перефразированными версиями отрывков абзацев. Например,
П: «Теория сложности вычислений - это раздел теории вычислений в теоретической информатике, который фокусируется на классификации вычислительных задач в соответствии с присущей им сложности и связывает эти классы друг с другом. Под вычислительной проблемой понимается задача, которая в принципе поддается решению компьютера, что эквивалентно заявлению о том, что проблема может быть решена механическим применением математические шаги, такие как алгоритм ».
В: «Как называется задача, которая обычно поддается решению с помощью компьютера?»
A: «вычислительная проблема»
Из слов, выделенных жирным шрифтом, видно, что вопрос перефразирован из абзаца. Это свойство делает задачу SQuAD проще, чем задачу с ответами на вопросы в открытой области. Потому что все, что нам нужно сделать сейчас, - это найти предложение из абзаца, которое семантически соответствует вопросу, и извлечь общий семантический или синтаксический фактор из контекста. Хотя нам по-прежнему требуется решение семантического и синтаксического извлечения, это намного проще, чем вычитать ответ из словаря, который может содержать десятки тысяч слов.
Обратная сторона SQuAD
Упомянутое выше свойство позволяет нам использовать несколько уловок, чтобы легко предугадывать ответы из заданного абзаца. Однако это также создает некоторые проблемы для модели, обученной с помощью SQuAD. Поскольку модели в значительной степени полагаются на поиск правильного предложения из абзаца, они уязвимы для состязательных предложений, вставленных в абзац, который напоминает вопрос, но предназначен для обмана сетей. Вот пример,
Предложение, выделенное синим цветом, является примером состязательности, введенным с целью обмануть сеть. Для человеческих читателей это не меняет ответа на вопрос: «Как зовут квотербека, которому было 38 лет в Суперкубке XXXIII?» поскольку состязательный приговор говорит о Champ Bowl XXXIV. Однако для сети состязательное предложение лучше согласуется с вопросом, чем предложение, основанное на истине.
Модельная сеть (QANet)
Причина, по которой мы выбрали модель QANet, проста. Благодаря простой архитектуре ее легко реализовать и быстрее обучить, чем большинство сетей для той же задачи. Архитектуру QANet можно увидеть на рисунке ниже:
Модельную сеть можно разделить примерно на 3 секции.
- Встраивание
- Кодировщик
- Внимание
Встраивание - это когда вводимый текст (абзацы и вопросы) преобразуются в представления в виде плотных векторов низкой размерности. Это делается с помощью подхода, аналогичного этой статье.
Наш подход очень похож. Единственная разница в том, что мы используем фиксированный размер ядра 5 для нашего сверточного фильтра. Мы также объединяем представление слова с максимальным представлением объединенных символов перед тем, как поместить их в сеть шоссе.
Кодировщик - это основной строительный блок модели. Детали блока кодировщика можно увидеть с правой стороны рисунка выше. Кодер состоит из позиционного кодирования, нормализации уровня, разделимой по глубине 1d-свертки, самовнимания и слоев с прямой связью.
Наконец, уровень внимания - это основной строительный блок сети, в котором происходит слияние вопроса и абзаца. QANet использует функцию трилинейного внимания, используемую в BiDAF paper.
Давайте начнем!
Реализация
Для простоты мы пропускаем этап обработки данных и сразу переходим к нейронной сети.
Встраивание
Сначала мы определяем заполнители ввода. Как только мы определяем заполнители, мы встраиваем вводимые слова с встраиванием слов, а символьные вводы - с вложениями символов.
Затем мы пропускаем их через однослойную одномерную сверточную нейронную сеть, max-pooling, объединяем представления слово + символ и, наконец, пропускаем их через двухуровневую сеть магистралей. Причина, по которой мы помещаем аргумент повторное использование в функции conv и шоссе, заключается в том, что мы хотим использовать одну и ту же сеть для ОБЕИХ абзацев и вопросов. Функции conv и магистраль - это наша реализация Tensorflow для сверточной сети и магистральной сети. (Исходный код можно найти здесь https://github.com/NLPLearn/QANet)
Мы помещаем выходные данные уровня внедрения в уровень кодировщика, чтобы сгенерировать соответствующий контекст и представление вопроса. «Остаточный_блок» реализует позиционное кодирование - ›Layer_normalization -› Разделимая по глубине свертка - ›Собственное внимание -› Сеть прямого распространения.
Теперь, когда у нас есть контекст и представление вопроса, мы объединяем их вместе с помощью функции внимания, называемой трилинейным вниманием. Объединенные выходные данные теперь содержат обширную информацию о контексте вопроса. Опять же, мы объединяем информацию контекста-вопроса и вопроса-контекста вместе с контекстом и передаем в качестве следующего ввода на уровень кодировщика.
Наконец, у нас есть выходной слой, который принимает выходные данные о внимании и кодирует их в плотный вектор. Здесь пригодится свойство SQuAD. Поскольку мы знаем, что ответ находится где-то внутри абзаца, для каждого слова в абзаце нам просто нужно вычислить вероятность того, что это слово является ответом или нет. Практически мы рассчитываем две вероятности. Вероятность того, что соответствующее слово принадлежит началу ответа, и вероятность того, что соответствующее слово принадлежит концу диапазона ответов. Таким образом, нам не нужно выяснять, какой ответ может быть получен из большого словаря, и эффективно вычислять вероятность.
Вот и все!
Обучение и демонстрация
QANet обучается относительно быстро по сравнению с другими моделями на основе RNN. По сравнению с популярной сетью BiDAF, QANet обучает примерно в 5-6 раз быстрее с лучшей производительностью. Мы обучаем сеть 60000 глобальных шагов, которые занимают около 6 часов в графическом процессоре GTX1080.
Это был довольно минималистичный подход, но я надеюсь, что он помог вам понять ответы на вопросы с помощью нейронных сетей! Если у вас есть вопросы о них, просто оставьте комментарий, и я постараюсь ответить на ваши вопросы.
Спасибо за чтение, оставляйте вопросы или отзывы в комментариях!