Важно понимать, как работают чат-боты. Основным механизмом чат-бота является классификатор текста. Давайте посмотрим на внутреннюю работу искусственной нейронной сети (ИНС) для классификации текста.

Мы будем использовать 2 слоя нейронов (1 скрытый слой) и подход мешок слов для организации наших обучающих данных. Классификация текста бывает трех видов: сопоставление с образцом, алгоритмы, нейронные сети. Хотя алгоритмический подход с использованием полиномиального наивного байеса удивительно эффективен, он страдает 3 фундаментальными недостатками:

  • алгоритм выдает оценку, а не вероятность. Нам нужна вероятность игнорировать прогнозы ниже некоторого порога. Это похоже на «шумоподавитель» на УКВ-радио.
  • алгоритм «учится» на примерах того, что есть в классе, но не того, чего нет. Это изучение закономерностей того, что не принадлежит классу, часто очень важно.
  • классы с непропорционально большими обучающими наборами могут создавать искаженные оценки классификации, вынуждая алгоритм корректировать оценки относительно размера класса. Это не идеально.

Присоединяйтесь к 30 000+ людям, которые читают еженедельную рассылку Машинное обучение, чтобы понять, как ИИ повлияет на их работу и жизнь.

Как и его наивный аналог, этот классификатор не пытается понять значение предложения, он пытается его классифицировать. На самом деле так называемые AI-чат-боты не понимают языка, но это другая история.

Если вы новичок в искусственных нейронных сетях, вот как они работают.

Чтобы понять алгоритмический подход к классификации, см. Здесь.

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

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

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

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

И наши обучающие данные, 12 предложений, принадлежащих 3 классам («намерениям»).

12 sentences in training data

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

12 documents
3 classes ['greeting', 'goodbye', 'sandwich']
26 unique stemmed words ['sandwich', 'hav', 'a', 'how', 'for', 'ar', 'good', 'mak', 'me', 'it', 'day', 'soon', 'nic', 'lat', 'going', 'you', 'today', 'can', 'lunch', 'is', "'s", 'see', 'to', 'talk', 'yo', 'what']

Обратите внимание, что каждое слово в корне и в нижнем регистре. Построение помогает машине уравнять такие слова, как «иметь» и «иметь». Нас не волнует дело.

Наши обучающие данные превращаются в «мешок слов» для каждого предложения.

['how', 'ar', 'you', '?']
[0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0]

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

['how', 'are', 'you', '?']

остановлено:

['how', 'ar', 'you', '?']

затем преобразуется во входные данные: 1 для каждого слова в пакете (? игнорируется)

[0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

и вывод: первый класс

[1, 0, 0]

Обратите внимание, что предложению может быть присвоено несколько классов: или ни одного.

Убедитесь, что сказанное выше имеет смысл, и поиграйте с кодом, пока не разберетесь с ним.

Ваш первый шаг в машинном обучении - получить чистые данные.

Далее у нас есть основные функции для нашей двухуровневой нейронной сети.

Если вы новичок в искусственных нейронных сетях, вот как они работают.

Мы используем numpy, потому что хотим, чтобы умножение нашей матрицы было быстрым.

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

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

А теперь мы кодируем нашу функцию обучения нейронной сети для создания синаптических весов. Не волнуйтесь, это в основном умножение матриц - из класса математики в средней школе.

Теперь мы готовы построить нашу модель нейронной сети, мы сохраним ее как структуру json для представления наших синаптических весов.

Вам следует поэкспериментировать с другим параметром «альфа» (параметр градиентного спуска) и посмотреть, как он влияет на частоту ошибок. Этот параметр помогает нашей корректировке ошибок найти самый низкий уровень ошибок:

synapse_0 + = альфа * synapse_0_weight_update

Мы используем 20 нейронов в нашем скрытом слое, вы можете легко это настроить. Эти параметры будут варьироваться в зависимости от размеров и формы ваших обучающих данных, уменьшите их до ~ 10 ^ -3 как разумную частоту ошибок.

Training with 20 neurons, alpha:0.1, dropout:False 
Input matrix: 12x26    Output matrix: 1x3
delta after 10000 iterations:0.0062613597435
delta after 20000 iterations:0.00428296074919
delta after 30000 iterations:0.00343930779307
delta after 40000 iterations:0.00294648034566
delta after 50000 iterations:0.00261467859609
delta after 60000 iterations:0.00237219554105
delta after 70000 iterations:0.00218521899378
delta after 80000 iterations:0.00203547284581
delta after 90000 iterations:0.00191211022401
delta after 100000 iterations:0.00180823798397
saved synapses to: synapses.json
processing time: 6.501226902008057 seconds

Файл synapse.json содержит все наши синаптические веса, это наша модель.

Эта функция classify () - это все, что нужно для классификации после расчета весов синапсов: ~ 15 строк кода.

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

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

sudo make me a sandwich 
 [['sandwich', 0.99917711814437993]]
how are you today? 
 [['greeting', 0.99864563257858363]]
talk to you tomorrow 
 [['goodbye', 0.95647479275905511]]
who are you? 
 [['greeting', 0.8964283843977312]]
make me some lunch 
 [['sandwich', 0.95371924052636048]]
how was your lunch today? 
 [['greeting', 0.99120883810944971], ['sandwich', 0.31626066870883057]]

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

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

Последняя классификация показывает некоторые внутренние детали:

found in bag: good
found in bag: day
sentence: good day 
 bow: [0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
good day 
 [['greeting', 0.99664077655648697]]

Обратите внимание на набор слов (лук) в предложении, 2 слова соответствуют нашему корпусу. Нейронная сеть также учится на 0, несовпадающих словах.

Классификацию с низкой вероятностью легко показать, предложив предложение, в котором единственным совпадением является «а» (обычное слово), например:

found in bag: a
sentence: a burrito! 
 bow: [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
a burrito! 
 [['sandwich', 0.61776860634647834]]

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