Понимание как работают чат-боты полезно. Основным механизмом чат-бота является классификатор текста.

Давайте посмотрим на внутреннюю работу алгоритмического подхода: Полиномиальный наивный байесовский метод. Это классический алгоритм классификации текста и обработки естественного языка (NLP). Замечательные термины, но принцип работы относительно прост, распространен и удивительно эффективен.

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

То есть в предложении лиса перепрыгнула через бревно нет никакой связи между прыгнула и лиса или бревно. Этот набор слов часто называют (любители НЛП) мешком слов. Хотя это невероятно наивно, классификатор не пытается понять значение предложения, он пытается его классифицировать. На самом деле ни один чат-бот не понимает человеческий язык, но это другая история.

Давайте изучим наш классификатор текста по одному разделу за раз. Мы предпримем следующие шаги:

  1. обратитесь к библиотекам, которые нам нужны
  2. предоставить данные обучения
  3. упорядочить наши данные
  4. итерация: код + проверка необходимых алгоритмов
  5. аннотация

Код находится здесь, мы используем iPython notebook, который является суперпродуктивным способом работы над проектами в области науки о данных. Синтаксис кода - Python.

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

Мы используем NLTK (инструментарий естественного языка) для двух вещей:

  • разбиение предложений на слова (токенизация): «удачного дня» токенизируется в список отдельных слов: «иметь», «а», «хорошо», «день»
  • сокращение слов до их основы (основание): «иметь» основы до «hav», что позволяет сопоставить его со словом «имеющий» (та же основа)

Существуют различные стеммеры, которые мы можем использовать, на сегодняшний день мы воспользуемся стеммером Lancaster.

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

результат показан ниже серым цветом:

12 sentences of training data

Вы заметите, что это список [] или словари {}. Каждый словарь имеет атрибуты: «класс» и «предложение». Вы можете легко добавить дополнительные атрибуты, такие как «ответы», которыми может отвечать чат-бот, когда намерение классифицируется.

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

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

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

Corpus words and counts: {'how': 3, 'ar': 1, 'mak': 2, 'see': 1, 'is': 2, 'can': 1, 'me': 1, 'good': 1, 'hav': 3, 'talk': 1, 'lunch': 1, 'soon': 1, 'yo': 1, 'you': 4, 'day': 4, 'to': 1, 'nic': 2, 'lat': 1, 'a': 5, 'what': 1, 'for': 1, 'today': 2, 'sandwich': 3, 'it': 1, 'going': 1} 
Class words: {'goodbye': ['hav', 'a', 'nic', 'day', 'see', 'you', 'lat', 'hav', 'a', 'nic', 'day', 'talk', 'to', 'you', 'soon'], 'sandwich': ['mak', 'me', 'a', 'sandwich', 'can', 'you', 'mak', 'a', 'sandwich', 'hav', 'a', 'sandwich', 'today', 'what', 'for', 'lunch'], 'greeting': ['how', 'ar', 'you', 'how', 'is', 'yo', 'day', 'good', 'day', 'how', 'is', 'it', 'going', 'today']}

Обратите внимание на «корпус» (термин НЛП), состоящий из слов с корнями. Стебель «make» - это «mak», так что он соответствует стеблям для «make», в качестве простого примера.

Теперь мы организовали наши данные в 2 словаря: corpus_words (каждое слово с корнем и количество вхождений), class_words (каждый класс и список слов с корнем в нем). Наш алгоритм будет использовать эти структуры данных для своей работы.

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

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

Давайте попробуем классифицировать предложение «хороший день для нас, чтобы пообедать?»

   match: day
   match: to
   match: hav
Class: goodbye  Score: 3 

   match: for
   match: hav
   match: lunch
Class: sandwich  Score: 3 

   match: good
   match: day
Class: greeting  Score: 2

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

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

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

match: day (0.25)
   match: to (1.0)
   match: hav (0.3333333333333333)
Class: goodbye  Score: 1.5833333333333333 
   match: for (1.0)
   match: hav (0.3333333333333333)
   match: lunch (1.0)
Class: sandwich  Score: 2.333333333333333 
   match: good (1.0)
   match: day (0.25)
Class: greeting  Score: 1.25

Наш последний шаг - абстрагироваться от алгоритма, чтобы его можно было просто использовать.

А теперь мы можем протестировать наш классификатор с помощью нескольких примеров входных данных.

Возможно, наивно, но удивительно эффективно.

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