В этом видео мы продолжим разговор о том, как извлекать признаки из текстов и обсудим продвинутые методы, основанные на n-граммах и skip-граммах. «Мешок слов», о котором мы говорили раньше, никак не учитывает порядок слов в документе. Он лишь считает, сколько раз какое слово встретилось в тексте. Понятно, что этот подход не очень хорош. Например, если у нас есть фраза «нравится» и фраза «не нравится», у них противоположный смысл, но при этом «мешок слов» никак не поможет поймать нам эти противоположные смыслы. В «мешке слов» мы будем лишь знать, что в тексте есть слово «нравится» и где-то есть частица «не». Понятно, что в этом не очень много информации. Более того, если бы мы учитывали не только слова, но и словосочетания в тексте, то понятно, что наше признаковое пространство было бы более богатым, более обширным. И вы могли бы находить более сложные закономерности, используя те же самые модели, например, как известно, если добавить новые признаки, то линейные модели смогут находить более сложные разделяющие поверхности или функции. Итак, самый простой подход, который позволяет учитывать порядок слов — это n-граммы. По сути, n-грамма — это просто набор из n подряд идущих слов в тексте. Например, если взять предложение «Наборы подряд идущих токенов», то ее униграммы, то есть n-граммы для n = 1, — это наборы, подряд, идущих, токенов — 4 униграммы; биграммы, то есть пары слов — это наборы подряд, подряд идущих и идущих токенов. А триграммы — это наборы подряд идущих и подряд идущих токенов. После того как мы посчитали все нужные нам n-граммы по тексту, мы пользуемся теми же самыми подходами, как и в случае с «мешком слов». Подсчитываем счетчики для этих n-грамм, вычисляем TF-IDF или делаем что-то еще. Понятно, что чем для большего количество n мы будем подсчитывать n-граммы, тем больше различных признаков у нас будет получаться, тем более богатым будет наше признаковое пространство. При этом, разумеется, значение n — это гиперпараметр. Чем больше n мы берем, тем выше шанс переобучиться. Если мы возьмем n, равное максимальной длине текста в нашей выборке, то у нас у каждого текста будет уникальный признак, и мы сможем идеально подогнаться под обучающую выборку. Но понятно, что такой алгоритм будет переобученным. Кстати, n-граммы можно использовать не только на словах. Понятно, что в качестве токенов можно использовать также и отдельные символы в предложениях. И после того как мы найдем такие токены, для них тоже вычислять n-граммы, так называемые буквенные n-граммы. Этот подход имеет много преимуществ. Например, он позволяет учитывать смайлики, встречающиеся в тексте, или же учитывать более-менее известные слова, но в незнакомых формах, но у которых те же самые корни, что и у знакомых слов. Часто буквенные n-граммы используют вместе с n-граммами по словам. Чуть более расширенный подход к подсчету n-грамм — это skip-граммы или, как они называются более точно, k-skip-n-граммы. k-skip-n-граммы — это такие наборы из n токенов, что между соседними токенами расстояние не более чем k. Если взять наш пример, предложение «Наборы подряд идущих токенов», то, как мы помним, биграммы для него были: наборы подряд, подряд идущих и идущих токенов. Если же мы добавляем один skip биграммы, то есть разрешаем расстояние 1 между соседними словами, то также получаем биграммы: наборы идущих, между словами «наборы идущих» расстояние равно как раз одному, между ними вставлено 1 слово, и «подряд токенов». Между словами «подряд» и «токенов» тоже есть одно слово. Еще один подход, который часто используется при вычислении признаков для текстов — это хэширование. Допустим, у нас есть некоторая функция h(x), которая принимает на вход слово и выдает некоторый хэш. Причем таких хэшей у нее на выходе может быть всего 2 в степени n, где n — некоторое небольшое число. Мы можем заменить все слова в тексте на их хэши, то есть перейти от слова x к его хэшу h(x), и дальше использовать уже эти хэши как токены, и для них вычислять счетчики TF-IDF или что-то еще. Этот подход очень простой — переход от слов к их хэшам, но имеет ряд важных преимуществ. Во-первых, он позволяет легко сократить количество признаков, вы можете не задумываться о том, как именно сгруппировать слова, а просто объединить в одно слово те исходные слова, которые имеют одинаковые хэши. Понятно, что этот подход не очень умный, вы могли бы попытаться группировать слова по их смыслу и объединять похожие слова, но подход с хэшированием тоже работает неплохо и не требует никаких усилий. Но самое главное преимущество, что если вы используете хэширование, то вам не нужно запоминать соответствие между исходными словами в тексте и номерами признаков. Вам не нужно помнить, что слово «токен» — это десятый признак в вашем признаковом пространстве. Нужно лишь посчитать хэш, и значение хэша и будет индексом этого слова. Это существенно позволяет упростить хранение моделей. Хранение соответствия между словами и индексами — это довольно массивная информация. Итак, мы обсудили такие подходы к расширению признакового пространства как n-граммы и skip-граммы и поговорили о том, как можно использовать хэширование при вычислении признаков текстов. А в следующем видео поговорим о том, как обучать модели на текстовых данных.