6.3.3.1 Представление текстовой информации
Для того чтобы использовать нейронные сети в задачах обработки текстов, составленных на естественном языке, нужно решить один важный вопрос: как представить текст в виде набора сигналов на входном или выходном слое нейронной сети? По сути, нам нужно превратить последовательность символов в некий упорядоченный набор чисел, а сделать это можно множеством разных способов. И, что вполне ожидаемо, от того, какой именно способ будет выбран, зависит как скорость обучения нейросетевой модели, так и способность обученной модели эффективно решать поставленную перед ней задачу.
Традиционным способом представления текстовой информации в вычислительной технике является посимвольное кодирование. Каждому символу сопоставляется некоторое число (порядковый номер символа в используемой таблице символов). Например, таблица символов ASCII (American standard code for information interchange, Американский стандартный код для обмена информацией), разработанная в начале 1960-х гг., изначально включала в себя 128 символов, то есть каждому символу таблицы соответствовало число в диапазоне [0…127], для хранения которого необходимо 7 бит информации. Теоретически можно взять, например, рекуррентную сеть с единственным нейроном во входном слое и на вход этого нейрона подавать последовательно коды каждого из символов текста в виде соответствующих сигналов. Или, например, расположить во входном слое семь нейронов, на каждый из которых подавать один из битов двоичного представления каждого из символов. Однако для решения большинства практических задач такие сети не подходят, и вот почему. Допустим, мы хотим создать сеть, которая будет способна, получив на вход некоторое высказывание на естественном языке, сделать вывод о том, ругательное это высказывание или нет. Основной структурной единицей языка является слово. Современные языки насчитывают обычно миллионы словоформ, некоторое подмножество которых относится к инвективной (ругательной) лексике. Чтобы научиться выделять ругательные слова, нейронная сеть в процессе обучения должна будет по сути на основании примеров «изобрести» деление текста на отдельные словоформы, а затем «понять», что наличие в тексте некоторых словоформ (тысячи их!) влияет на значение метки класса. Конечно, достаточно большие сети, обученные с применением огромных вычислительных ресурсов, способны справиться с подобной задачей, однако значительная часть произведённых вычислений будет представлять собой мартышкин труд. Уйма вычислительного времени уйдёт на выяснение того, что мы и так знаем: язык состоит из слов, хорошо известных нам по словарям, и эти слова имеют весьма ограниченный набор значений, лишь иногда зависящих от контекста. Эту информацию было бы неплохо использовать на уровне представления данных на входе сети, что могло бы существенно сократить требуемые для её обучения вычислительные ресурсы. Рассматривая текст в виде последовательности слов, а не символов, сеть могла бы «сосредоточиться» на «изучении» более высокоуровневой структуры высказываний. Если ограничить длину слова 10 буквами, а алфавит 26 английскими буквами, то общее число различных «слов», составленных из произвольных последовательностей символов, превысит 2 × 1014, что минимум в 20 млн раз больше числа реально существующих в английском языке словоформ. Заставлять нейронную сеть искать иголку в таком огромном стоге сена просто контрпродуктивно. Именно поэтому в большинстве случаев в качестве элементарной единицы представления текста в коннекционистских моделях обычно используют слова (словоформы) или части слов.
Взяв словарь, включающий в себя все существующие словоформы (а также знаки препинания и другие элементы текста), мы можем сопоставить каждое слово его порядковому номеру в словаре и использовать этот номер в качестве числового представления слова. Представим для простоты нерекуррентную сеть, которая способна обрабатывать лишь предложения из одного слова. В этом случае наша задача будет сведена к задаче определения того, является одиночное слово ругательством или нет. Получив на вход некоторое число, сеть должна отнести его к одному из двух классов — ругательство или не ругательство. И здесь оказывается, что «обучаемость» нашей сети будет очень сильно зависеть от того, как именно слова расположены в нашем словаре. Если слова-ругательства кто-то уже расположил в начале словаря, то задача становится тривиальной: если порядковый номер слова на входе сети меньше или равен числу ругательств в словаре, то слово является ругательством, в противном случае — не является. Однако, если ругательства рассеяны по словарю случайным образом, единственной возможностью для сети будет по сути запомнить все числа, соответствующие ругательствам, то есть каким-то образом выделить все диапазоны номеров слов, в пределах которых метка класса неизменна. Такая процедура не столь уж тривиальна, и в случае достаточно большого словаря для её выучивания потребуется довольно большая сеть и солидные вычислительные затраты. Да и результат вовсе не гарантирован, поскольку такая задача, скорее всего, не будет линейно разделимой. Поэтому, если мы не имеем дело с каким-то хитрым словарём, в котором порядковые номера слов связаны с их семантикой, лучше не использовать порядковый номер слова в качестве входного сигнала сети. Вместо этого уже на заре коннекционизма стали использовать так называемый прямой унитарный код — двоичный код фиксированной длины, содержащий только одну цифру 1 (например, 000001, 000010, 000100 и т. п.). Длина кода определяется количеством слов в словаре, то есть каждому слову соответствует отдельный разряд кода. Порядковый номер слова в словаре соответствует номеру единичного разряда. Современный специалист по глубокому обучению вместо «прямой унитарный код», скорее всего, скажет «one-hot-векторы», таковы уж причуды сложившегося профессионального жаргона. Хотя во входном слое вашей сети теперь столько же нейронов, сколько слов в вашем словаре, зато наша задача стала линейно разделимой. Размер словаря можно сократить, принеся в жертву редкие, низкочастотные слова, однако даже словарь в несколько десятков тысяч слов в ряде случаев может стать проблемой. Поэтому было придумано ещё несколько способов представления текста, более компактных, чем последовательность унитарных кодов. Рассмотрим наиболее популярные из них.
Первый из них получил название «мешок слов» (bag of words). Мешок слов по сути представляет собой вектор, являющийся суммой прямых унитарных кодов, соответствующих словам предложения. То есть каждый компонент мешка — это число, равное числу вхождений соответствующего слова в текст (такой вариант мешка слов называют мультиномиальной моделью; иногда поступают ещё проще: если слово встречается в тексте хотя бы один раз, то соответствующая компонента вектора устанавливается равной 1 — такой вариант мешка слов называют моделью Бернулли[1]). Для фразы «Дар напрасный, дар случайный, жизнь, зачем ты мне дана?» наш мешок будет выглядеть следующим образом:
Слово из словаря | Компонента вектора |
---|---|
дар | 2 |
напрасный | 1 |
случайный | 1 |
жизнь | 1 |
зачем | 1 |
ты | 1 |
мне | 1 |
дана | 1 |
… (все остальные слова из словаря) | 0 |
Последовательность one-hot-векторов выглядела бы для той же фразы следующим образом:
Слово из словаря | Вектор 1 | Вектор 2 | Вектор 3 | Вектор 4 | Вектор 5 | Вектор 6 | Вектор 7 | Вектор 8 | Вектор 9 |
---|---|---|---|---|---|---|---|---|---|
дар | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
напрасный | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
случайный | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
жизнь | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
зачем | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
ты | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
мне | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
дана | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
… | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Таким образом, в нашем случае мешок слов содержит в девять раз меньше компонентов, чем последовательность one-hot-векторов, и, что не менее важно, его размер всегда будет фиксированным — равным размеру выбранного словаря. А значит, для его обработки можно использовать нерекуррентную нейронную сеть. К сожалению, платой за это стала полная потеря информации о порядке слов в тексте, который в ряде случаев существенно меняет смысл сказанного. Например, «На собрании было десять человек» и «На собрании было человек десять», «Эта книга трудна даже для него» и «Даже эта книга трудна для него», «Я не люблю» и «Не я люблю» и так далее. Несколько снизить остроту этой проблемы можно путём добавления в словарь некоторых биграмм, например пар «частица + слово» и «предлог + слово». В конце концов, можно соорудить мешок биграмм или триграмм, но это резко увеличит размерность вектора, поэтому на практике обычно ограничиваются лишь отдельными n-граммами, добавленными в словарь. Таким образом, альтернативой мешку слов является мешок триграмм.
Как one-hot-векторы, так и мешки слов и n-грамм обладают рядом существенных недостатков, из-за которых успехи моделей, основанных на подобных представлениях текста, были весьма скромными.
Во-первых, размерность данных, даже в случае мешка слов, всё ещё довольно велика. При словаре в миллион слов нейронная сеть, принимающая на вход мешок слов, будет иметь примерно столько же нейронов во входном слое, сколько нейронная сеть, получающая на вход цветное изображение размером 640 × 480 точек, что было явно за пределами нейросетевых технологий начала нулевых годов. При этом если изображения содержат регулярные пространственные структуры, позволяющие применять для их обработки свёрточные сети, то в случае мешка слов или one-hot-векторов ничего подобного не наблюдается, и значит, нам придётся использовать модель с гораздо большим числом параметров. Сокращение размера словаря также не может существенно помочь, поскольку нередко как раз менее частотные слова вносят значительный смыслоразличительный вклад. Например, какое-нибудь заковыристое ругательство легко превратит предложение в оскорбительную тираду.
Во-вторых, рассмотренные нами виды векторов чрезвычайно разрежены. Это значит, что при обучении синаптические веса первого слоя будут изменяться достаточно редко, что не слишком хорошо будет сказываться на сходимости модели. Человек при анализе текста вооружён пониманием семантики слов, выработанным в процессе многолетнего обращения с естественным языком. Мы знаем о том, что некоторые слова близки по смыслу или вовсе являются полными синонимами, мы понимаем метафоры, выстраиваем ассоциативные ряды. Для нейронной сети, получающей на вход one-hot-векторы или мешок слов, разница между «пьяницей» и «алкоголиком» ровно такая же, как и между «бузиной» и «дядькой». Все отношения между словами наша сеть будет пытаться вывести на основе «изучения» обучающей выборки, которая чаще всего будет на много порядков меньше по объёму, чем весь тот корпус текстов, на котором человек обычно формирует понимание естественного языка.
Не поможет тут и посимвольное представление слов, поскольку буквенное написание слов нередко слабо связано с их смыслом. Например, в написании слов «курица», «петух» и «цыплёнок» ничто не намекает нам на то, что речь идёт о представителях одного и того же биологического вида. Точно так же слова «золото» и «долото», хотя и различаются всего одним символом, со смысловой точки зрения имеют мало чего общего.
Мешки слов и n-грамм могут быть усовершенствованы ещё несколькими способами. Например, в случае мешка слов можно использовать группировку, считая все синонимы за одно слово. Впрочем, существенного выигрыша такой подход обычно не даёт — всё-таки полные синонимы в естественном языке встречаются не так уж часто. Другой подход основан на использовании хеш-функций, которые фактически выполняют случайную группировку слов (использование хеш-функций в сочетании с мешком n-грамм называют алгоритмом шинглов — от англ. shingles — чешуйки). Это позволяет уменьшить размерность, но ценой потери семантической информации, ведь в одну группу могут попасть слова, замена которых в тексте может существенно исказить его смысл. В общем, все эти классические методы не позволили достичь значительного прогресса в области обработки естественного языка. Было ясно, что необходимо найти им какую-то более совершенную альтернативу…
- ↑ Manning C. D., Raghavan P., Schütze H. (2008). Introduction to Information Retrieval. Cambridge University Press // https://books.google.ru/books?id=t1PoSh4uwVcC