Туториал: нейронная сеть на JavaScript в 30 строк кода

12 декабря 2018

Туториал: нейронная сеть на JavaScript в 30 строк кода

В этой статье будет показано, как создать и обучить нейронную сеть на JavaScript, используя Synaptic.js. Этот пакет позволяет реализовывать глубокое обучение в Node.js и в браузере. Будет создана простейшая возможная…

В этой статье будет показано, как создать и обучить нейронную сеть на JavaScript, используя Synaptic.js. Этот пакет позволяет реализовывать глубокое обучение в Node.js и в браузере. Будет создана простейшая возможная нейронная сеть — та, которой удается выполнить XOR операцию.

Перевод статьи «How to create a Neural Network in JavaScript in only 30 lines of code». Автор — Per Harald Borgen. Ссылка на оригинал — в подвале статьи. 

Вы можете видеть созданный мною интерактивный Scrimba туториал:

нейронная сеть на javascript

В Scribma туториале вы можете поиграться с сетью. Но перед тем, как посмотреть на код, давайте вспомним основы нейронных сетей.

Нейроны и синапсы

Самый первый строительный элемент любой нейронной сети — нейрон. Он похож на функцию — берет несколько входных значений и возвращает результат алгебраических действий над ними.

Существует множество типов нейронов. Наша сеть использует нейрон с сигмоидной функцией активации, которая принимает любое число и трансформирует его в значение, лежащее в диапазоне от 0 до 1.

Круг ниже показывает сигмоидный нейрон. На входе — 5, на выходе — 1. Стрелочки называются синапсами, они соединяют нейрон с другими слоями в нейросети.

сигмоидный нейрон

Почему красное число это 5? Это сумма из трех синапсов, которые соединены с нейроном. Это показано тремя стрелочками слева от нейрона. Поясню сказанное.

Слева можно видеть два плюс одно значения. Зеленые числа — значения 1 и 0. Параметр сдвига -2 — коричневое число. Сначала входные числа умножаются на соответствующие им веса 7 и 3 соответственно. Значения весов представляют синие числа.

Наконец мы добавляем параметр сдвига и получаем итоговой результат 5 — красное число. Это и есть вход для нашего искусственного нейрона.

веса и смещения - нейронная сеть JS

Такак мы работаем с сигмоидным нейроном, который переводит любое входное значение на отрезок от 0 до 1, выход преобразуется в 1.

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

нейронная сеть

Задача нейронной сети — обучаться находить общие признаки в данных, например, распознавать рукописные символы или спам на электронной почте. Чтобы осуществить эту задачу, требуется точная настройка весов и параметров сдвига во всей сети. Это синие и коричневые числа в примере сверху.

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

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

Подробное техническое рассмотрение обратного распространения ошибки.

Код нейросети JavaScript

Вы получили базовое представление о нейронных сетях, теперь самое время посмотреть на реализацию. Первое, что необходимо сделать, это создать слои. Это делается при помощи функции new Layer в synaptic. Число в скобках определяет, сколько каждый слой должен содержать нейронов.

Если вам трудно представить, что такое слой, посмотрите еще на скринкаст.

const { Layer, Network } = window.synaptic;
var inputLayer = new Layer(2);
var hiddenLayer = new Layer(3);
var outputLayer = new Layer(1);

Далее соединяем эти слои вместе и создаем инстанс новой сети, как показано ниже:

inputLayer.project(hiddenLayer);
hiddenLayer.project(outputLayer);
var myNetwork = new Network({
 input: inputLayer,
 hidden: [hiddenLayer],
 output: outputLayer
});

У нас получилась сеть с 2-3-1 нейронами в входном, скрытом и выходном слое, соответственно. Архитектура этой сети показана ниже:

XOR функция

Теперь давайте обучим нашу сеть:

// train the network - learn XOR
var learningRate = .3;
for (var i = 0; i < 20000; i++) {
  // 0,0 => 0
  myNetwork.activate([0,0]);
  myNetwork.propagate(learningRate, [0]);
  // 0,1 => 1
  myNetwork.activate([0,1]);
  myNetwork.propagate(learningRate, [1]);
  // 1,0 => 1
  myNetwork.activate([1,0]);
  myNetwork.propagate(learningRate, [1]);
  // 1,1 => 0
  myNetwork.activate([1,1]);
  myNetwork.propagate(learningRate, [0]);
}

Запускаем сеть 20 000 раз. Каждый раз распространяемся в прямом и обратном направлении четыре раза, проходя через четыре возможных входа для этой сети: [0,0], [0,1], [1,0], [1,1].

Начинаем с команды myNetwork.activate([0,0]), где [0,0] — данные, которые посылаются в сеть. Это прямое распространение, которое также называется активизацией сети. После каждого прямого распространения требуется сделать и обратное, тогда сеть обновит свои веса и свдиг.

Обратное распротстранение осуществляется командой myNetwork.propagate(learningRate, [0]). Параметр learningRate — константа, которая говорит сети, насколько каждый раз нужно изменять веса. Второй параметр — 0 представляет корректный ответ для заданного входа [0,0].

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

Сеть использует сравнение в качестве базиса для корректировки значений весов и сдвига. Поэтому в следующий раз предсказание будет немного точнее.

После выполнения 20 000 итераций в цикле for мы можем посмотреть, насколько хорошо обучилась сеть, при помощи активизации сети со всеми четырьмя возможными входами:

console.log(myNetwork.activate([0,0])); 
-> [0.015020775950893527]
console.log(myNetwork.activate([0,1]));
->[0.9815816381088985]
console.log(myNetwork.activate([1,0]));
-> [0.9871822457132193]
console.log(myNetwork.activate([1,1]));
-> [0.012950087641929467]

Если округлить эти значения до ближайшего целого числа, получим корректные ответы для XOR операций!

Как-то так. Хотя мы только немного коснулись нейронных сетей, этой статьи должно быть достаточно, чтобы поиграться с Synaptic и начать изучение области самостоятельно. Этот репозиторий содержит много хороших туториалов.

Наконец, когда выучите что-нибудь новое, обязательно поделитесь звоими знаниями с помощью скринкаста Scrimba и написания статьи!

Open source инструмент на Python для выбора признаков нейронной сети

11 декабря 2018
выбор признаков нейронной сети питон

Open source инструмент на Python для выбора признаков нейронной сети

Поиск и выбор наиболее полезных признаков в датасете — одна из наиболее важных частей машинного обучения. Ненужные признаки уменьшают скорость обучения, ухудшают возможности интерпретации результатов и, что самое важное, уменьшают…

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

Перевод статьи «A Feature Selection Tool for Machine Learning in Python» by William Koehrsen, ссылка на оригинал в подвале статьи.

Разочарованный специальными методами выбора признаков, которые я раз за разом применял для задач машинного обучения, я построил класс для их выбора на Python, код доступен на GitHub. FeatureSelector включает в себя некоторые наиболее распространенные методы отбора, а именно:

  1. С высоким процентом пропущенных значений;
  2. Коллинеарные (сильно коррелированные);
  3. С нулевой важностью в древовидной модели;
  4. С низкой важностью;
  5. С единственным уникальным значением.

В этой статье мы рассмотрим работу FeatureSelector. Он позволяет нам быстро внедрять эти методы, обеспечивая более эффективный рабочий процесс. Feature Selector — это незавершенный проект, который будет продолжать улучшаться в зависимости от потребностей сообщества.

Датасет

В этом примере мы будем использовать датасет из соревнования Keggle Home Credit Default Risk machine learning competition. (Информация об этом соревновании приведена здесь). Весь датасет доступен для скачивания, и мы будем использовать его в качестве иллюстративного материала.

Пример данных. TARGET - это метка для классификации
Пример данных. TARGET — это метка для классификации

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

Запуск кода

Чтобы запустить FeatureSelector, нам необходимо передать структурированный датасет с метками в строках и признаками в столбцах. Для некоторых методов нужны только сами признаки, но для анализирующих важность методов также нужны метки. Поскольку рассматривается контролируемая задача классификации, мы будем использовать набор признаков и набор меток.

(Обязательно запустите эти строки в том же каталоге, что и feature_selector.py)

from feature_selector import FeatureSelector
# Features are in train and labels are in train_labels
fs = FeatureSelector(data = train, labels = train_labels)

У нас есть пять методов поиска признаков для удаления. Мы можем получить доступ к любому свойству и удалить его из данных вручную или использовать функцию remove в FeatureSelector.

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

Пропущенные значения

Первый метод удаления является простым: он находит признаки с долей пропущенных значений выше указанного порога. В приведенном ниже примере ищутся признаки с более чем 60% пропущенных значений (жирным приведен результат поиска).

fs.identify_missing(missing_threshold = 0.6)
17 features with greater than 0.60 missing values.

Мы можем увидеть долю пропущенных значений в каждом столбце таблицы:

fs.missing_stats.head()

доля пропущенных значений

Чтобы увидеть признаки для удаления, мы получаем доступ к атрибуту ops в FeatureSelector:

missing_features = fs.ops['missing']
missing_features[:5]
['OWN_CAR_AGE',
 'YEARS_BUILD_AVG',
 'COMMONAREA_AVG',
 'FLOORSMIN_AVG',
 'LIVINGAPARTMENTS_AVG']

Наконец, можно вывести график распределения пропущенных значений во всех признаках:

fs.plot_missing()
 график распределения пропущенных значений во всех признаках
График распределения пропущенных значений во всех признаках

Коллинеарные признаки

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

Метод identify_collinear находит коллинеарные признаки по заданному значению коэффициента корреляции. Для каждой пары коррелированных свойств он выбирает одно их них для удаления (поскольку нам нужно только удалить только одно из двух):

fs.identify_collinear(correlation_threshold = 0.98)
21 features with a correlation magnitude greater than 0.98.

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

fs.plot_collinear()

Как и раньше, мы можем получить доступ ко всему списку коррелированных свойств, которые будут удалены, или увидеть высококоррелированные пары свойств в таблице.

# list of collinear features to remove
collinear_features = fs.ops['collinear']
# dataframe of collinear features
fs.record_collinear.head()

Если мы хотим исследовать наш датасет, мы также можем построить график всех корреляций в данных с помощью команды plot_all = True:

Признаки с нулевой важностью

Предыдущие два метода могут быть применены к любому структурированному датасету, и эти методы детерминированы — результаты будут одинаковыми каждый раз для заданного порога. Следующий метод предназначен только для контролируемых задач машинного обучения, где у нас есть метки для обучения модели и не является детерминированным. Функция ident_zero_importance находит признаки, которые имеют нулевое значение важности в соответствии с моделью обучения GBM.

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

FeatureSelector вычисляет важность признаков с помощью Gradient Boosting Maching из библиотеки LightGBM. Важность признака усредняется по 10 циклам GBM, для уменьшения дисперсии. Кроме того, модель обучается с датасетом для проверки и ранней остановкой (эту опцию можно отключить), чтобы предотвратить переобучение.

Приведенный ниже код вызывает метод и ищет признаки с нулевой важностью:

# Pass in the appropriate parameters
fs.identify_zero_importance(task = 'classification', 
                            eval_metric = 'auc', 
                            n_iterations = 10, 
                             early_stopping = True)
# list of zero importance features
zero_importance_features = fs.ops['zero_importance']
63 features with zero importance after one-hot encoding.

Мы передаем следующие параметры:

  • task: либо «классификация», либо «регрессия», в зависимости от вашей задачи;
  • eval_metric: показатель, используемый для ранней остановки (не нужно, если ранняя остановка отключена);
  • n_iterations: количество циклов обучения;
  • early_stopping: использовать или не использовать раннюю остановку для обучения модели.

На этот раз мы получим два графика с помощью команды plot_feature_importances:

# plot the feature importances
fs.plot_feature_importances(threshold = 0.99, plot_n = 12)
124 features required for 0.99 of cumulative importance


Слева приведен график важности plot_n количества наиболее важных свойств (нормировка на 1). Справа приведен график зависимости важности от числа свойств. Вертикальная линия означает пороговое значение, в данном случае 99%.

Два важных замечания касательно метрики важности:

  • Обучение GBM является стохастическим, важность свойств будет разной при каждом запуске модели.

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

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

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

Признаки с низкой важностью

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

Например, приведенный ниже код выводит признаки с важностью менее 99%:

fs.identify_low_importance(cumulative_importance = 0.99)
123 features required for cumulative importance of 0.99 after one hot encoding.
116 features do not contribute to cumulative importance of 0.99.

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

Чтобы просмотреть все значения важности, введите:

fs.feature_importances.head(10)

Метод low_importance заимствован из одного из PCA, где обычно остается только PC, необходимый для сохранения определенного процента отклонения (например, 95%). Процент от общей важности учитывается на основе той же идеи.

Методы, основанные на значении важности, действительно применимы только в том случае, если мы собираемся использовать древовидную модель для прогнозирования. Помимо стохастичности, основанные на важности методы используют подход «черного ящика», в котором мы действительно не знаем, почему модель считает какие-то признаки важными. Если вы пользуетесь этими методами, запускайте их по несколько раз, чтобы посмотреть, как меняются результаты. Возможно придется создать несколько датасетов для проверки различных параметров!

Признаки с единственным уникальным значением

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

В этом методе нет параметров для инициализации, в отличие от других методов:

fs.identify_single_unique()
4 features with a single unique value.

Можно построить гистограмму количества уникальных значений в каждой категории:

fs.plot_unique()

Важный момент — NaN по умолчанию отбрасываются до вычисления уникальных значений в Pandas.

Удаление признаков

Как только мы выбрали признаки для удаления, у нас есть два способа это сделать. Все признаки для удаления хранятся в ops, и мы можем использовать списки для удаления признаков вручную. Другой вариант — использовать встроенную функцию remove.

Если мы хотим удалить все признаки, выбранные пятью методами, нужно ввести methods = ‘all’:

# Remove the features from all methods (returns a df)
train_removed = fs.remove(methods = 'all')
['missing', 'single_unique', 'collinear', 'zero_importance', 'low_importance'] methods have been run

Removed 140 features.

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

train_removed_all = fs.remove(methods = 'all', keep_one_hot=False)
Removed 187 features including one-hot features.

Возможно, было бы полезно проверить признаки, которые будут удалены, прежде чем продолжить работу! Исходный датасет хранится атрибуте data FeatureSelector в качестве резервной копии!

Одновременный запуск всех методов

Вместо использования методов по отдельности мы можем использовать все из них с identify_all. Для этого нужен набор параметров для каждого метода:

fs.identify_all(selection_params = {'missing_threshold': 0.6,    
                                    'correlation_threshold': 0.98, 
                                    'task': 'classification',    
                                    'eval_metric': 'auc', 
                                    'cumulative_importance': 0.99})
151 total features out of 255 identified for removal after one-hot encoding.

Обратите внимание, что количество признаков изменилось, потому что мы повторно запускаем модель. Для удаления признаков нужно вызвать функцию remove.

Заключение

Класс FeatureSelector реализует несколько общих операций для удаления признаков перед обучением модели машинного обучения. Он содержит функции для идентификации признаков для удаления, а также для визуализации. Методы могут выполняться индивидуально или сразу для эффективной работы.

Методы missing, collinear и single_unique детерминированы, в то время как методы, основанные на значении важности, будут меняться при каждом запуске. Выбор признаков, как это часто бывает в машинном обучении, в значительной мере эмпирический и требует тестирования нескольких комбинаций для получения оптимального результате. Лучше всего попробовать несколько конфигураций в схеме модели, и FeatureSelector предлагает быстрый анализ параметров для выбора признаков.

Интересные статьи:

Как попасть в топ 2% соревнования Kaggle

26 ноября 2018
kaggle competition

Как попасть в топ 2% соревнования Kaggle

Статья основана на реальном опыте участия в соревнованиях на Kaggle, автор — Abhay Pawar. Ссылка на оригинал в подвале статьи.  Участвовать в соревнованиях Kaggle весело и захватывающе! За последние пару лет…

Статья основана на реальном опыте участия в соревнованиях на Kaggle, автор — Abhay Pawar. Ссылка на оригинал в подвале статьи. 

Участвовать в соревнованиях Kaggle весело и захватывающе! За последние пару лет я разработал несколько простых способов создания более совершенных моделей машинного обучения. Эти простые, но мощные методы помогли мне попасть в топ 2% соревнования Instacart Market Basket Analysis, и я также использую их вне Kaggle. Давайте рассмотрим методы поближе.

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

график признаков

Но проблема с этими графиками заключается в том, что они создаются с использованием обученной модели. Если бы мы могли напрямую создавать эти графики прямо по данным для обучения, это могло бы помочь нам лучше понять принципы работы нашей сети. Фактически, графики могут помочь вам в следующем:

  1. Понимание признаков;
  2. Поиск признаков с большими шумами (самая интересная часть!);
  3. Разработка признаков;
  4. Важность признаков;
  5. Отладка признаков;
  6. Обнаружение утечек;
  7. Мониторинг модели.

Чтобы вы легко могли попробовать сами, я решил включить эти методы в пакет featexp на Python, и в этой статье мы увидим, как их можно использовать для исследования признаков. Мы будем использовать датасет из соревнования Kaggle Home Credit Default Risk. Задача конкурса — предсказать неплательщиков по известным данным о клиентах.

Понимание признаков

понимание признаков - kaggle соревнование
График зависимости признака от цели ничего не дает

Если зависимая переменная (цель) является двоичной, строить графики бессмысленно, потому что все точки имеют значение либо 0, либо 1. Для цели с непрерывной областью значений большое количество точек затрудняет понимание взаимосвязи цели и признаки. Featexp создает более полезные графики. Посмотрим на них:

Зависимость признака от цели
Зависимость признака от цели — DAYS_BIRTH (возраст)

Featexp создает бины (ось X) признака. Затем он вычисляет среднее значение цели в каждом бине и отображает его на рисунке слева. Из графика следует, что у клиентов с высокими отрицательными значениями для DAYS_BIRTH (с большим возрастом) более низкие ставки. Это имеет смысл, поскольку молодые люди обычно чаще просрочивают платежи. Эти графики помогают нам понять, что свойство может сказать о клиентах и ​​как это повлияет на модель. Участок справа показывает количество клиентов в каждом бине.

Поиск признаков с большим шумом

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

решение для соревнований kaggle
Сравнение признака при обучении и при проверке

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

  1. Корреляция тренда (показана на графике проверки): если признак ведет себя по-разному при обучении и при проверке, это может приводить к перегрузке модели. Так происходит, потому что модель обучается тому, что не применимо на тестовых данных. Коррекция тренда помогает понять, насколько схоже поведение признака при обучении и при проверке. Признак на графике выше имеет корреляцию 99%. Это не «шумящее» свойство!
  2. Изменения тренда: внезапные и повторяющиеся изменения тренда могут означать наличие шумов. Но такое изменение тренда может произойти, потому что у данного бина совсем другое количество значений в других признаках и, следовательно, его частота не может сравниваться с другими бинами.

Приведенная ниже функция имеет различный тренд и, следовательно, низкую корреляцию: 85%. Эти две метрики можно использовать для отключения признаков с большими шумами.

Пример функции с большими шумами

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

Используйте тестовые данные на другом интервале времени. Тогда вы будете уверены, что тренд не меняется со временем.

Функция get_trend_stats() в featexp возвращает таблицу с корреляцией тренда и изменением каждого признака.

участие в соревновании Kaggle
Результат, возвращаемый функцией get_trend_stats()

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

AUC при включении различных признаков с использованием корреляции тренда

Можно видеть: чем выше порог корреляции тренда, тем выше AUC. Не отключая важные признаки, можно добиться увеличения LB AUC до 0,74. Интересно, что AUC не меняется так сильно, как LB AUC. Важно правильно выбрать стратегию проверки: так, чтобы локальный тест AUC совпадал с LB AUC. Весь код можно найти в featexp_demo.

Разработка признаков

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

Зависимость признака от цели EXT_SOURCE_1
Зависимость признака от цели EXT_SOURCE_1

Клиенты с высоким значением EXT_SOURCE_1 имеют низкие ставки. Но первый бин (ставка ~ 8%) не соответствует тренду признака (идет вверх, а затем вниз). Он имеет только отрицательные значения вблизи -99.985 и большое количество единиц в бине. Это, вероятно, подразумевает, что это специальные значения. К счастью, нелинейные модели не будут испытывать проблемы с обучением этим связям. Но для линейных моделей, таких как логистическая регрессия, такие специальные значения и нули (которые будут показаны как отдельный бин) должны быть поданы в значение из бина с аналогичной ставкой вместо простой подачи со средним значением признака.

Важность признаков

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

Отладка признаков

Глядя на графики Featexp, можно находить ошибки в сложных кодах, делая следующие две вещи:

не изменяющийся признак
Не изменяющийся призак означает один бин
  1. Проверьте, что распределение клиентов для признака по бинам выглядит нормально. Я лично много раз сталкивался с такими случаями, как выше, из-за незначительных ошибок.
  2. Всегда выдвигайте гипотезу о том, как будет выглядеть тренд признака, прежде чем смотреть на графики. То, что тренд выглядит не так, как вы ожидали, может означать некоторые проблемы. И, откровенно говоря, этот процесс предсказания трендов делает создание моделей машинного обучения намного более захватывающим!

Обнаружение утечек

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

Признак с утечкой
Признак с утечкой

Приведенный выше признак имеет частоту 0% в бине нулей и 100% во всех других бинах. Ясно, что это предельный случай утечки. Этот признак имеет значение только тогда, когда клиент неплатежеспособен. Нужно выяснить, почему так происходит: либо есть ошибка, либо признак действительно реагирует только на неплатежеспособных клиентов (и тогда его нужно отключить). Разобравшись, почему признак приводит к утечке, можно быстрее исправить проблему.

Мониторинг модели

Поскольку featexp вычисляет корреляцию трендов между двумя датасетами, ее можно легко использовать для мониторинга модели. Каждый раз, когда модель переобучается, новые данные для обучения могут быть сравнены с хорошо проверенными данными (обычно это данные, которые использовались при первой сборке модели). Корреляция тренда может помочь вам отследить, изменилась ли как-то зависимость признака от цели.

Эти простые проверки часто помогали мне в создании лучших моделей в реальных задачах и в Kaggle. С featexp требуется 15 минут, чтобы посмотреть на графики, и это определенно стоит того.

Реализация Transfer learning с библиотекой Keras

22 ноября 2018
transfer-learning-keras

Реализация Transfer learning с библиотекой Keras

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

Для большинства задач компьютерного зрения не существует больших датасетов (около 50 000 изображений). Даже при экстремальных стратегиях аугментации данных трудно добиться высокой точности. Обучение таких сетей с миллионами параметров обычно имеет тенденцию перегружать модель. В этом случае Transfer learning готов прийти на помощь.

Inception-V3 Google Research

Что такое Transfer learning?

Transfer Learning (TL) — одно из направлений исследований в машинном обучении, которое изучает возможность применения знаний, полученных при решении одной задачи, к другой.

Зачем нужен Trasfer learning?

  • Лишь немногие обучают сверточные сети с нуля (с помощью случайной инициализации), потому что зачастую нужные датасеты отсутствуют. Таким образом, использование предварительно обученных весовых коэффициентов или фиксированного экстрактора свойств помогает разрешить большинство проблем.
  • Сети с большим количеством слоев обучать дорого и долго. Самые сложные модели требуют нескольких недель для обучения с использованием сотен дорогостоящих графических процессоров.
  • Определение структуры сети, методов и параметров обучения — настоящее искусство, так как соответствующей теории, которая поможет разобраться с этими проблемами, просто не существует.

Как может помочь Trasfer learning?

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

transfer learning
Inception V3 Google Research

Простая реализация с помощью Keras


Помня, что свойства СonvNet являются более примитивными на первых слоях и усложняются с каждым последующим слоем, рассмотрим четыре типичных сценария.

1. Новый датасет небольшой и аналогичен исходному датасету

Если мы пытаемся обучить всю сеть сразу, возникает проблема перегрузки модели. Поскольку данные аналогичны исходным, мы ожидаем, что свойства более высокого уровня в ConvNet также будут иметь отношение к этому датасету. Следовательно, лучшей стратегией может быть обучение линейного классификатора по кодам CNN.

Таким образом, давайте отбросим все слои VGG19 и обучим только классификатор:

for layer in model.layers:
   layer.trainable = False
#Now we will be training only the classifiers (FC layers)

2. Новый датасет большой и аналогичен исходному

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

for layer in model.layers:
   layer.trainable = True
#The default is already set to True. I have mentioned it here to make things clear.

Если вы хотите отбросить несколько первых слоев, формирующих самые примитивные свойства, это можно сделать с помощью следующего кода:

for layer in model.layers[:5]:
   layer.trainable = False.
# Here I am freezing the first 5 layers

3. Новый датасет небольшой и сильно отличается от исходного

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

Этот код должен помочь. Он будет извлекать свойства «block2_pool». Обычно это не очень полезно, поскольку слой имеет 64х64х128 свойств и обучение классификатора поверх них может и не помочь. Можно добавить несколько полносвязных слоев и обучить нейронную сеть поверх них. Это нужно делать в следующем порядке:

  1. Добавьте несколько FC слоев и выходной слой.
  2. Задайте весовые коэффициенты для более ранних слоев и отбросьте их.
  3. Обучите сеть.

4. Новый датасет большой и сильно отличается от исходного

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

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

Прогнозирование: какие методы использует Uber

19 ноября 2018
forecasting uber machine learning

Прогнозирование: какие методы использует Uber

Первая статья в серии, посвященной объяснению того, как Uber использует прогнозирование для улучшения своих продуктов. В дополнение к стандартным статистическим алгоритмам Uber строит прогнозы с использованием трех методов: машинное обучение, глубокое…

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

Прогнозирование

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

Прогнозирование рынка uber
Рисунок 1. Прогнозирование рынка в Калифорнийском заливе позволяет направлять водителей в районы с высоким спросом.

Неудивительно, что Убер применяет прогнозирование для разных целей, в том числе:

  • Прогнозирование рынка: критический элемент приложения, который позволяет нам прогнозировать потребительский спрос в виде маленьких гранул в пространственно-временном режиме, чтобы направлять партнеров-водителей в районы повышенного спроса до их возникновения, тем самым увеличивая количество поездок и доходы. Пространственно-временные прогнозы по-прежнему остаются открытой областью для исследования.
  • Планирование расходов на ПО: малые расходы могут привести к сбоям в работе ПО, которые могут подорвать доверие пользователей, но чрезмерные расходы могут оказаться очень дорогостоящими. Прогнозирование поможет найти золотую середину: не слишком много и не слишком мало.
  • Маркетинг: контролируя тенденции, сезонность и другую динамику (например, конкуренцию или ценообразование), крайне важно знать предельную эффективность различных медиаканалов. Мы используем передовые методологии прогнозирования, чтобы строить более надежные оценки и принимать основанные на данных маркетинговые решения в широких масштабах.

Что делает прогнозирование (в Uber) сложной задачей?

Uber работает в реальном, физическом мире с его изменчивыми факторами, такими как поведение и интересы людей, физические ограничения и непредсказуемость. Физические ограничения, например, географическое расстояние и пропускная способность дороги, переводят прогнозирование из временных в пространственно-временные области.

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

Рис. 2 демонстрирует пример данных о поездках Uber в городе за более чем 14 месяцев. Как видно, график сильно изменчив, но видна положительная тенденция и сезонность (например, декабрь часто имеет больше пиковых дат из-за большого количества праздников, разбросанных в течение месяца).

Используя сумму поездок Uber в городе за каждый день, мы можем лучше прогнозировать количество и частоту будущих поездок.
Рисунок 2. Используя сумму поездок Uber в городе за каждый день, мы можем лучше прогнозировать количество и частоту будущих поездок.

Если мы увеличим масштаб (рис. 3) и перейдем к почасовым данным за июль 2017 года, вы заметите как дневную, так и недельную (7 * 24) сезонности. В выходные водители обычно более загружены заказами.

Рисунок 3. Почасовой график поездок Uber за месяц (июль 2017 года)

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

Известные подходы к прогнозированию

Количественные методы прогнозирования можно сгруппировать следующим образом:

  • базирующиеся на модели или причинные;
  • статистические методы и подходы, основанные на компьютерном обучении.

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

Когда лежащие в основе механизмы неизвестны или слишком сложны для понимания, как на фондовом рынке, или известны не полностью (розничные продажи), обычно лучше применять простую статистическую модель. Популярными классическими методам, относящимися к этой категории, являются ARIMA (авторегрессионное интегрированное скользящее среднее), методы экспоненциального сглаживания, такие как Holt-Winters, и метод Theta, который используется менее широко, но работает очень хорошо. На самом деле, метод Theta выиграл M3 Forecasting Competition, и мы также выяснили, что он хорошо работает для динамики Uber (более того, он дешевле для вычислений).

В последние годы подходы к компьютерному обучению, в том числе леса с квантильной регрессией (QRF), кузена известного случайного леса (Random forest), стали частью инструментария прогнозиста. Было показано, что рекуррентные нейронные сети (RNN) очень полезны, если в наличии достаточно данных, особенно экзогенных регрессоров. Как правило, эти модели машинного обучения имеют тип черного ящика и используются, когда не требуется интерпретируемость. Ниже мы предлагаем общий обзор популярных методов прогнозирования классического и машинного обучения.

Классические статистичекие методы:

  • Авторегрессионное интегрированное скользящее среднее — ARIMA
  • Методы экспоненциального сглаживания — Holt-Winters
  • Theta

Методы машинного обучения:

  • Рекуррентные нейронные сети (RNN)
  • Леса с квантильной регрессией (QRF)
  • Gradient boosting trees (GBM)
  • Метод опорных веркторов (SVR)
  • Распределение гауссовского процесса (GP)

Интересно отметить, что победивший на конкурсе проект прогнозирования M4 был гибридной моделью, которая включала как закодированные вручную формулы сглаживания, основанные на хорошо известном методе Холта-Уинтерса, так и стек расширенной долгой краткосрочной памяти (LSTM).

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

В Uber выбор правильного метода прогнозирования для данного варианта — это функция из многих факторов, включая количество исторических данных, если важную роль играют экзогенные переменные (например, погода, концерты и т. д.) и бизнес-потребности (например, нужно ли интерпретировать модель?). Мы не можем заранее знать, какой подход приведет к оптимальной производительности.

Сравнение методов прогнозирования

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

Два основных подхода к тестированию моделей прогнозирования
Рисунок 4: Два основных подхода к тестированию моделей прогнозирования — подход скользящего окна (слева) и подход расширяющегося окна (справа)

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

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

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

Оценка прогноза

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

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

Важность оценки неопределенности

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

Рисунок 5: Интервалы прогнозирования имеют решающее значение при принятии решений. Хоть точечные прогнозы могут быть одинаковыми, их интервалы предсказания могут существенно отличаться.

На рисунке 5 прогнозы, показанные фиолетовым цветом, совпадают. Однако интервал предсказания на левом графике значительно уже, чем на правом. Разница в интервалах прогнозирования приводит к двум очень разным прогнозам, особенно в контексте планирования производительности: второй прогноз требует значительно более высоких резервов мощности, чтобы обеспечить возможность значительного увеличения спроса.

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

Движение вперед

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

FaceNet — пример простой системы распознавания лиц с открытым кодом Github

16 ноября 2018

FaceNet — пример простой системы распознавания лиц с открытым кодом Github

Распознавание лица — последний тренд в авторизации пользователя. Apple использует Face ID, OnePlus — технологию Face Unlock. Baidu использует распознавание лица вместо ID-карт для обеспечения доступа в офис, а при…

Распознавание лица — последний тренд в авторизации пользователя. Apple использует Face ID, OnePlus — технологию Face Unlock. Baidu использует распознавание лица вместо ID-карт для обеспечения доступа в офис, а при повторном пересечении границы в ОАЭ вам нужно только посмотреть в камеру.

В статье разбираемся, как сделать простейшую сеть распознавания лиц самостоятельно с помощью FaceNet.

Ссылка на Гитхаб, кому нужен только код

Немного о FaceNet

FaceNet — нейронная сеть, которая учится преобразовывать изображения лица в компактное евклидово пространство, где дистанция соответствует мере схожести лиц. Проще говоря, чем более похожи лица, тем они ближе.

Триплет потерь

FaceNet использует особую функцию потерь называемую TripletLoss. Она минимизирует дистанцию между якорем и изображениями, которые содержат похожую внешность, и максимизирует дистанцую между разными.

  • f(a) это энкодинг якоря
  • f(p) это энкодинг похожих лиц (positive)
  • f(n) это энкодинг непохожих лиц (negative)
  • Альфа — это константа, которая позволяет быть уверенным, что сеть не будет пытаться оптимизировать напрямую f(a) — f(p) = f(a) — f(n) = 0
  • […]+ экиввалентено max(0, sum)

Сиамские сети

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

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

В FaceNet это делается путем вычисления расстояния между двумя выходами.

Реализация

Переходим к практике.

В реализации мы будем использовать Keras и Tensorflow. Кроме того, мы используем два файла утилиты из репозитория deeplayning.ai, чтобы абстрагироваться от взаимодействий с сетью FaceNet.

  • fr_utils.py содержит функции для подачи изображений в сеть и получения кодирования изображений;
  • inception_blocks_v2.py содержит функции для подготовки и компиляции сети FaceNet.

Компиляция сети FaceNet

Первое, что нам нужно сделать, это собрать сеть FaceNet для нашей системы распознавания лиц.

import os
import glob
import numpy as np
import cv2
import tensorflow as tf
from fr_utils import *
from inception_blocks_v2 import *
from keras import backend as K
K.set_image_data_format('channels_first')
FRmodel = faceRecoModel(input_shape=(3, 96, 96))
def triplet_loss(y_true, y_pred, alpha = 0.3):
    anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]

    pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor,
               positive)), axis=-1)
    neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, 
               negative)), axis=-1)
    basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha)
    loss = tf.reduce_sum(tf.maximum(basic_loss, 0.0))
   
    return loss
FRmodel.compile(optimizer = 'adam', loss = triplet_loss, metrics = ['accuracy'])
load_weights_from_FaceNet(FRmodel)

Мы начнем инициализпцию нашей сети со входа размерности (3, 96, 96). Это означает, что картинка передается в виде трех каналов RGB и размерности 96×96 пикселей.

Теперь давайте определим Triplet Loss функцию. Функция в сниппете кода выше удовлетворяет уравнению Triplet Loss, которое мы определили в предыдущей секции.

Если вы не знакомы с фреймворком TensorFlow, ознакомьтесь с документацией.

Сразу после того, как мы определили функцию потерь, мы можем скомпилировать нашу систему распознавания лиц с помощью Keras. Мы будем использовать Adam optimizer для минимизации потерь, подсчитанных с помощью функции Triplet Loss.

Подготовка базы данных

Теперь когда мы скомпилировали FaceNet, нужно подготовить базу данных личностей, которых сеть будет распознавать. Мы будем использовать все изображения, которые лежат в директории images.

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

def prepare_database():
    database = {}
    for file in glob.glob("images/*"):
        identity = os.path.splitext(os.path.basename(file))[0]
        database[identity] = img_path_to_encoding(file, FRmodel)
    return database

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

Как только мы получили закодированное изображения в базе данных, сеть наконец готова приступить к распознаванию!

Распознавание лиц

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

def who_is_it(image, database, model):
    encoding = img_to_encoding(image, model)
    
    min_dist = 100
    identity = None
    
    # Loop over the database dictionary's names and encodings.
    for (name, db_enc) in database.items():
        dist = np.linalg.norm(db_enc - encoding)
        print('distance for %s is %s' %(name, dist))
        if dist < min_dist:
            min_dist = dist
            identity = name
    
    if min_dist > 0.52:
        return None
    else:
        return identity

Загружаем новое изображение в функцию img_to_encoding. Функция обрабатывает изображения, используя FaceNet и возвращает закодированное изображение. Теперь мы можем сделать предположение о наиболее вероятной личности этого человека.

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

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

 if min_dist > 0.52: 
     return None 
 else:
     return identity

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

На GitHub есть демо работы полученной сети, с входом от простой вебкамеры.

Заключение

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


Интересные статьи:

Искусственный интеллект для малого бизнеса: 5 способов применения

1 ноября 2018

Искусственный интеллект для малого бизнеса: 5 способов применения

В массовой культуре искусственный интеллект (AI) покрыт мифами и считается исключительной силой, подрывающей экономическую стабильность. На самом деле, он похож на любую другую технологию. По мере того, как больше и больше…

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

В Соединенных Штатах в малом бизнесе создается более половины рабочих мест, а его доля в ВВП составляет более 40 процентов. Поэтому разработчики стараются делать свои решения доступными для компаний этой экономической ниши.

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

Используйте AI для сбора и анализа данных

Qualtrics провели исследование, в котором собрали и проанализировали мнения 250 маркетинговых лидеров. Обнаружилось, что 96% ожидают, что в течение пяти лет AI будет справляться с регулярными исследовательскими задачами, например, очисткой данных.  В то же время 63% полагают, что AI заменит статистический анализ в течение следующего десятилетия.

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

Когда небольшие предприятия получают доступ к сложным статистическим инструментам, они могут больше узнать о своих клиентах и ​​привлечь новых. Регрессионный анализ позволяет устанавливать взаимосвязи между большим набором переменных и определять, как они влияют на бизнес. AI – универсальный инструмент для статистических задач, от определения факторов, стимулирующих клиентов возвращаться, до поиска новых рыночных ниш.

Искусственный интеллект помогает собирать данные. Механизмы сбора данных – от анализа тональности текста, до алгоритмов машинного обучения, отслеживающих предпочтения и привычки клиентов, теперь доступны для любых предприятий. В Facebook, например, можно запустить подходящего для этих целей чат-бота, основанного на машинном обучении.

Используйте AI для найма сотрудников

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

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

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

Сделайте организацию бэкэнда более эффективной с AI

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

В статье для Minutehack соучредитель inniAccounts, Джеймс Пойзер, рассказывает, как его малый бизнес сделал «значительные шаги для автоматизации некоторых процессов бухгалтерского учета» с помощью AI. Использование AI для задач бэкэнда также уменьшает давление на сотрудников. Пойзер отмечает: «Когда люди воспринимают искусственный интеллект как конкурента, не ждите ничего хорошего. К счастью, это не наш случай».

С другой стороны, большинство сотрудников приветствуют технологии, которые помогают избавиться от монотонных задач и освободить время для значимых поручений. Как признают респонденты опроса, AI именно это и делает.

Используйте AI для улучшения сервиса

Никогда еще у компаний не было столько способов взаимодействовать с клиентами. Из-за стремительного развития онлайн каналов коммуникации и более требовательных, чем прежде, потребителей пришло время предлагать новые методы для быстрого решения проблем клиента. Это одна из причин, по которой Gartner прогнозирует, что четверть операций в обслуживании клиентов будет «задействовать виртуального помощник клиента (VCA) или чат-бота уже к 2020 году».

Согласно опросу Qualtrics, часть опросов будет проводиться цифровым помощником и это будет реализовано в течение 5 лет. Прогнозы дают веские основания ожидать, что AI будет играть важную роль в общении с клиентами в ближайшие годы.

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

Создайте маркетинговую платформу на основе AI

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

Раньше малый бизнес ограничивался рекламой, которую мог себе позволить на местных рынках, а теперь, размещая объявления онлайн, у него есть возможность охватить широкую аудиторию. Можно использовать рекламные платформы Facebook и Google для поиска конкретных потребителей, которые будут восприимчивы к объявлению, собирать и анализировать потребительские данные из нескольких каналов. И все это без армии маркетологов.

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


Интересные статьи:

 

Как создать нейронную сеть c библиотекой Keras на Python: пример

9 октября 2018
keras нейронаня сеть на python

Как создать нейронную сеть c библиотекой Keras на Python: пример

Keras — популярная библиотека глубокого обучения, которая внесла большой вклад в коммерциализацию глубокого обучения. Библиотека Keras проста в использовании и позволяет создавать нейронные сети с помощью лишь нескольких строк кода…

Keras — популярная библиотека глубокого обучения, которая внесла большой вклад в коммерциализацию глубокого обучения. Библиотека Keras проста в использовании и позволяет создавать нейронные сети с помощью лишь нескольких строк кода Python.

Из статьи вы узнаете, как с помощью Keras создать нейронную сеть, предсказывающую оценку продукта пользователями по их отзывам, классифицируя ее по двум категориям: положительная или отрицательная. Эта задача называется анализом настроений (сентимент-анализ), и мы решим ее с помощью сайта с кинорецензиями IMDb. Модель, которую мы построим, также может быть применена для решения других задач машинного обучения после незначительной модификации.

Обратите внимание, что мы не будем вдаваться в подробности Keras и глубокого обучения. Этот пост предназначен для того, чтобы предоставить схему нейронной сети в Keras и познакомить с ее реализацией.

Содержание:

  • Что такое Keras?
  • Что такое анализ настроений?
  • Датасет IMDB
  • Импорт зависимостей и получение данных
  • Изучение данных
  • Подготовка данных
  • Создание и обучение модели

Что такое Keras?

Keras — это библиотека для Python с открытым исходным кодом, которая позволяет легко создавать нейронные сети. Библиотека совместима с TensorFlow, Microsoft Cognitive Toolkit, Theano и MXNet. Tensorflow и Theano являются наиболее часто используемыми численными платформами на Python для разработки алгоритмов глубокого обучения, но они довольно сложны в использовании.

deep learning frameworks
Оценка популярности фреймворков машинного обучения по 7 категориям

Читайте: TensorFlow туториал. Часть 1: тензоры и векторы

Keras, наоборот, предоставляет простой и удобный способ создания моделей глубокого обучения. Ее создатель, François Chollet, разработал ее для того, чтобы максимально ускорить и упростить процесс создания нейронных сетей. Он сосредоточил свое внимание на расширяемости, модульности, минимализме и поддержке Python. Keras можно использовать с GPU и CPU; она поддерживает как Python 2, так и Python 3. Keras компании Google внесла большой вклад в коммерциализацию глубокого обучения и искусственного интеллекта, поскольку она содержит cовременные алгоритмы глубокого обучения, которые ранее были не только недоступными, но и непригодными для использования.

Что такое анализ настроений (сентимент-анализ)?

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

keras нейронная сеть анализ настроений
Пример шкалы анализа настроений

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

Датасет IMDb

imdb reviews sentiment
Рецензии на сайте IMDb

Датасет IMDb состоит из 50 000 обзоров фильмов от пользователей, помеченных как положительные (1) и отрицательные (0).

  • Рецензии предварительно обрабатываются, и каждая из них кодируется последовательностью индексов слов в виде целых чисел.
  • Слова в обзорах индексируются по их общей частоте появления в датасете. Например, целое число «2» кодирует второе наиболее частое используемое слово.
  • 50 000 обзоров разделены на два набора: 25 000 для обучения и 25 000 для тестирования.

Датасет был создан исследователями Стэнфордского университета и представлен в статье 2011 года, в котором достигнутая точность предсказаний была равна 88,89%. Датасет также использовался в рамках конкурса сообщества Keggle «Bag of Words Meets Bags of Popcorn» в 2011 году.

Импорт зависимостей и получение данных

Начнем с импорта необходимых зависимостей для предварительной обработки данных и построения модели.

%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from keras.utils import to_categorical
from keras import models
from keras import layers

Загрузим датесет IMDb, который уже встроен в Keras. Поскольку мы не хотим иметь данные обучения и тестирования в пропорции 50/50, мы сразу же объединим эти данные после загрузки для последующего разделения в пропорции 80/20:

from keras.datasets import imdb
(training_data, training_targets), (testing_data, testing_targets) = imdb.load_data(num_words=10000)
data = np.concatenate((training_data, testing_data), axis=0)
targets = np.concatenate((training_targets, testing_targets), axis=0)

Изучение данных

Изучим наш датасет:

print("Categories:", np.unique(targets))
print("Number of unique words:", len(np.unique(np.hstack(data))))
Categories: [0 1]
Number of unique words: 9998
length = [len(i) for i in data]
print("Average Review length:", np.mean(length))
print("Standard Deviation:", round(np.std(length)))
Average Review length: 234.75892
Standard Deviation: 173.0

Можно видеть, что все данные относятся к двум категориям: 0 или 1, что представляет собой настроение обзора. Весь датасет содержит 9998 уникальных слов, средний размер обзора составляет 234 слова со стандартным отклонением 173.

Рассмотрим простой способ обучения:

print("Label:", targets[0])
Label: 1
print(data[0])
[1, 14, 22, 16, 43, 530, 973, 1622, 1385, 65, 458, 4468, 66, 3941, 4, 173, 36, 256, 5, 25, 100, 43, 838, 112, 50, 670, 2, 9, 35, 480, 284, 5, 150, 4, 172, 112, 167, 2, 336, 385, 39, 4, 172, 4536, 1111, 17, 546, 38, 13, 447, 4, 192, 50, 16, 6, 147, 2025, 19, 14, 22, 4, 1920, 4613, 469, 4, 22, 71, 87, 12, 16, 43, 530, 38, 76, 15, 13, 1247, 4, 22, 17, 515, 17, 12, 16, 626, 18, 2, 5, 62, 386, 12, 8, 316, 8, 106, 5, 4, 2223, 5244, 16, 480, 66, 3785, 33, 4, 130, 12, 16, 38, 619, 5, 25, 124, 51, 36, 135, 48, 25, 1415, 33, 6, 22, 12, 215, 28, 77, 52, 5, 14, 407, 16, 82, 2, 8, 4, 107, 117, 5952, 15, 256, 4, 2, 7, 3766, 5, 723, 36, 71, 43, 530, 476, 26, 400, 317, 46, 7, 4, 2, 1029, 13, 104, 88, 4, 381, 15, 297, 98, 32, 2071, 56, 26, 141, 6, 194, 7486, 18, 4, 226, 22, 21, 134, 476, 26, 480, 5, 144, 30, 5535, 18, 51, 36, 28, 224, 92, 25, 104, 4, 226, 65, 16, 38, 1334, 88, 12, 16, 283, 5, 16, 4472, 113, 103, 32, 15, 16, 5345, 19, 178, 32]

Здесь вы видите первый обзор из датасета, который помечен как положительный (1). Нижеследующий код производит обратное преобразование индексов в слова, чтобы мы могли их прочесть. В нем каждое неизвестное слово заменяется на «#». Это делается с помощью функции get_word_index ().

index = imdb.get_word_index()
reverse_index = dict([(value, key) for (key, value) in index.items()]) 
decoded = " ".join( [reverse_index.get(i - 3, "#") for i in data[0]] )
print(decoded) 

# this film was just brilliant casting location scenery story direction everyone's really suited the part they played and you could just imagine being there robert # is an amazing actor and now the same being director # father came from the same scottish island as myself so i loved the fact there was a real connection with this film the witty remarks throughout the film were great it was just brilliant so much that i bought the film as soon as it was released for # and would recommend it to everyone to watch and the fly fishing was amazing really cried at the end it was so sad and you know what they say if you cry at a film it must have been good and this definitely was also # to the two little boy's that played the # of norman and paul they were just brilliant children are often left out of the # list i think because the stars that play them all grown up are such a big profile for the whole film but these children are amazing and should be praised for what they have done don't you think the whole story was so lovely because it was true and was someone's life after all that was shared with us all

Подготовка данных

Пришло время подготовить данные. Нужно векторизовать каждый обзор и заполнить его нулями, чтобы вектор содержал ровно 10 000 чисел. Это означает, что каждый обзор, который короче 10 000 слов, мы заполняем нулями. Это делается потому, что самый большой обзор имеет почти такой же размер, а каждый элемент входных данных нашей нейронной сети должен иметь одинаковый размер. Также нужно выполнить преобразование переменных в тип float.

def vectorize(sequences, dimension = 10000):
results = np.zeros((len(sequences), dimension))
for i, sequence in enumerate(sequences):
results[i, sequence] = 1
return results
 
data = vectorize(data)
targets = np.array(targets).astype("float32")

Разделим датасет на обучающий и тестировочный наборы. Обучающий набор будет состоять из 40 000 обзоров, тестировочный — из 10 000.

test_x = data[:10000]
test_y = targets[:10000]
train_x = data[10000:]
train_y = targets[10000:]

Создание и обучение модели

Теперь можно создать простую нейронную сеть. Начнем с определения типа модели, которую мы хотим создать. В Keras доступны два типа моделей: последовательные и с функциональным API.

Затем нужно добавить входные, скрытые и выходные слои. Для предотвращения переобучения будем использовать между ними исключение («dropout»). Обратите внимание, что вы всегда должны использовать коэффициент исключения в диапазоне от 20% до 50%. На каждом слое используется функция «dense» для полного соединения слоев друг с другом. В скрытых слоях будем используем функцию активации «relu», потому это практически всегда приводит к удовлетворительным результатам. Не бойтесь экспериментировать с другими функциями активации. На выходном слое используем сигмоидную функцию, которая выполняет перенормировку значений в диапазоне от 0 до 1. Обратите внимание, что мы устанавливаем размер входных элементов датасета равным 10 000, потому что наши обзоры имеют размер до 10 000 целых чисел. Входной слой принимает элементы с размером 10 000, а выдает — с размером 50.

Наконец, пусть Keras выведет краткое описание модели, которую мы только что создали.

# Input - Layer
model.add(layers.Dense(50, activation = "relu", input_shape=(10000, )))
# Hidden - Layers
model.add(layers.Dropout(0.3, noise_shape=None, seed=None))
model.add(layers.Dense(50, activation = "relu")
model.add(layers.Dropout(0.2, noise_shape=None, seed=None))
model.add(layers.Dense(50, activation = "relu"))
# Output- Layer
model.add(layers.Dense(1, activation = "sigmoid"))model.summary()
model.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 50)                500050    
_________________________________________________________________
dropout_1 (Dropout)          (None, 50)                0         
_________________________________________________________________
dense_2 (Dense)              (None, 50)                2550      
_________________________________________________________________
dropout_2 (Dropout)          (None, 50)                0         
_________________________________________________________________
dense_3 (Dense)              (None, 50)                2550      
_________________________________________________________________
dense_4 (Dense)              (None, 1)                 51        
=================================================================
Total params: 505,201
Trainable params: 505,201
Non-trainable params: 0
_________________________________________________________________

Теперь нужно скомпилировать нашу модель, то есть, по существу, настроить ее для обучения. Будем использовать оптимизатор «adam». Оптимизатор — это алгоритм, который изменяет веса и смещения во время обучения. В качестве функции потерь используем бинарную кросс-энтропию (так как мы работаем с бинарной классификацией), в качестве метрики оценки — точность.

model.compile(
 optimizer = "adam",
 loss = "binary_crossentropy",
 metrics = ["accuracy"]
)

Теперь можно обучить нашу модель. Мы будем делать это с размером партии 500 и только двумя эпохами, поскольку я выяснил, что модель начинает переобучаться, если тренировать ее дольше. Размер партии определяет количество элементов, которые будут распространяться по сети, а эпоха — это один проход всех элементов датасета. Обычно больший размер партии приводит к более быстрому обучению, но не всегда — к быстрой сходимости. Меньший размер партии обучает медленнее, но может быстрее сходиться. Выбор того или иного варианта определенно зависит от типа решаемой задачи, и лучше попробовать каждый из них. Если вы новичок в этом вопросе, я бы посоветовал вам сначала использовать размер партии 32, что является своего рода стандартом.

results = model.fit(
 train_x, train_y,
 epochs= 2,
 batch_size = 500,
 validation_data = (test_x, test_y)
)

Train on 40000 samples, validate on 10000 samples
Epoch 1/2
40000/40000 [==============================] - 5s 129us/step - loss: 0.4051 - acc: 0.8212 - val_loss: 0.2635 - val_acc: 0.8945
Epoch 2/2
40000/40000 [==============================] - 4s 90us/step - loss: 0.2122 - acc: 0.9190 - val_loss: 0.2598 - val_acc: 0.8950

Проведем оценку работы модели:

print(np.mean(results.history["val_acc"]))
0.894750000536

Отлично! Наша простая модель уже побила рекорд точности в статье 2011 года, упомянутой в начале поста. Смело экспериментируйте с параметрами сети и количеством слоев.

Полный код модели приведен ниже:

import numpy as np
from keras.utils import to_categorical
from keras import models
from keras import layers
from keras.datasets import imdb
(training_data, training_targets), (testing_data, testing_targets) = imdb.load_data(num_words=10000)
data = np.concatenate((training_data, testing_data), axis=0)
targets = np.concatenate((training_targets, testing_targets), axis=0)
def vectorize(sequences, dimension = 10000):
 results = np.zeros((len(sequences), dimension))
 for i, sequence in enumerate(sequences):
  results[i, sequence] = 1
 return results
 
data = vectorize(data)
targets = np.array(targets).astype("float32")
test_x = data[:10000]
test_y = targets[:10000]
train_x = data[10000:]
train_y = targets[10000:]
model = models.Sequential()
# Input - Layer
model.add(layers.Dense(50, activation = "relu", input_shape=(10000, )))
# Hidden - Layers
model.add(layers.Dropout(0.3, noise_shape=None, seed=None))
model.add(layers.Dense(50, activation = "relu"))
model.add(layers.Dropout(0.2, noise_shape=None, seed=None))
model.add(layers.Dense(50, activation = "relu"))
# Output- Layer
model.add(layers.Dense(1, activation = "sigmoid"))
model.summary()
# compiling the model
model.compile(
 optimizer = "adam",
 loss = "binary_crossentropy",
 metrics = ["accuracy"]
)
results = model.fit(
 train_x, train_y,
 epochs= 2,
 batch_size = 500,
 validation_data = (test_x, test_y)
)
print("Test-Accuracy:", np.mean(results.history["val_acc"]))

Итоги

Вы узнали, что такое анализ настроений и почему Keras является одной из наиболее популярных библиотек глубокого обучения.

Мы создали простую нейронную сеть с шестью слоями, которая может вычислять настроение авторов кинорецензий с точностью 89%. Теперь вы можете использовать эту модель для анализа бинарных настроений в других источниках, но для этого вам придется сделать их размер равным 10 000 или изменить параметры входного слоя.

Эту модель (с небольшими изменениями) можно применить и для решения других задач машинного обучения.


Интересные статьи:

Как создать чат-бота с нуля на Python: подробная инструкция

4 октября 2018
как создать чат бота на python

Как создать чат-бота с нуля на Python: подробная инструкция

Аналитики Gartner утверждают, что к 2020 году 85% взаимодействий клиентов с сервисами сведется к общению с чат-ботами. В 2018 году они уже обрабатывают около 30% операций. В этой статье мы расскажем, как создать…

Аналитики Gartner утверждают, что к 2020 году 85% взаимодействий клиентов с сервисами сведется к общению с чат-ботами. В 2018 году они уже обрабатывают около 30% операций. В этой статье мы расскажем, как создать своего чат-бота на Python.

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

Несмотря на то что Duolingo позволяет изучить новый язык, у пользователей сервиса возникла проблема. Они почувствовали, что не развивают разговорные навыки, так как обучаются самостоятельно. Пользователи неохотно обучались в парах из-за смущения. Эта проблема не осталась незамеченной для разработчиков.

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

чат-бот пример

Поскольку боты разрабатывались так, чтобы быть разговорчивыми и дружелюбными, пользователи Duolingo практикуются в общении в удобное им время, выбирая «собеседника» из набора, пока не поборят смущение в достаточной степени, чтобы перейти к общению с другими пользователями. Это решило проблему пользователей и ускорило обучение через приложение.

Итак, что такое чат-бот?

Чат-бот — это программа, которая выясняет потребности пользователей, а затем помогает удовлетворить их (денежная транзакция, бронирование отелей, составление документов). Сегодня почти каждая компания имеет чат-бота для взаимодействия с пользователями. Некоторые способы использования чат-ботов:

  • предоставление информации о рейсе;
  • предоставление пользователям доступа к информации об их финансах;
  • служба поддержки.

Возможности безграничны.

История чат-ботов восходит к 1966 году, когда Джозеф Вейценбаум разработал компьютерную программу ELIZA. Программа подражает манере речи психотерапевта и состоит лишь из 200 строк кода. Пообщаться с Элизой можно до сих пор на сайте.

Как работает чат-бот?

Существует два типа ботов: работающие по правилам и самообучающиеся.

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

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

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

В этой статье мы научимся писать код простых поисковых чат-ботов на основе библиотеки NLTK.

Создание бота на Python

Предполагается, что вы умеете пользоваться библиотеками scikit и NLTK. Однако, если вы новичок в обработке естественного языка (NLP), вы все равно можете прочитать статью, а затем изучить соответствующую литературу.

Обработка естественного языка (NLP)

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

Краткое введение в NLKT

NLTK (Natural Language Toolkit) — платформа для создания программ на Python для работы с естественной речью. NLKT предоставляет простые в использовании интерфейсы для более чем 50 корпораций и лингвистических ресурсов, таких как WordNet, а также набор библиотек для обработки текста в целях классификации, токенизации, генерации, тегирования, синтаксического анализа и понимания семантики, создания оболочки библиотек NLP для коммерческого применения.

Книга Natural Language Processing with Python  — практическое введение в программирование для обработки языка. Рекомендуем ее прочитать, если вы владеете английским языком.

Загрузка и установка NLTK

  • Установите NLTK: запустите pip install nltk.
  • Тестовая установка: запустите python, затем введите import nltk.

Инструкции для конкретных платформ смотрите здесь.

Установка пакетов NLTK

Импортируйте NLTK и запустите nltk.download(). Это откроет загрузчик NLTK, где вы сможете выбрать версию кода и модели для загрузки. Вы также можете загрузить все пакеты сразу.

Предварительная обработка текста с помощью NLTK

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

  • Преобразование букв в заглавные или строчные, чтобы алгоритм не обрабатывал одни и те же слова повторно.
  • Токенизация. Токенизация — термин, используемый для описания процесса преобразования обычных текстовых строк в список токенов, то есть слов. Токенизатор предложений используется для составления списка предложений. Токенизатор слов составляет список слов.

Пакет NLTK включает в себя предварительно обученный токенизатор Punkt для английского языка.

  • Удаление шума, то есть всего, что не является цифрой или буквой;
  • Удаление стоп-слов. Иногда из словаря полностью исключаются некоторые крайне распространенные слова, которые, как считается, не имеют большого значения для формирования ответа на вопрос пользователя. Эти слова называются стоп-словами (междометия, артикли, некоторые вводные слова);
  • Cтемминг: приведение слова к коренному значению. Например, если нам нужно провести стемминг слов «стемы», «стемминг», «стемированный» и «стемизация», результатом будет одно слово — «стем».
  • Лемматизация. Лемматизация — немного отличающийся от стемминга метод. Основное различие между ними заключается в том, что стемминг часто создает несуществующие слова, тогда как лемма — это реально существующее слово. Таким образом, ваш исходный стем, то есть слово, которое получается после стемминга, не всегда можно найти в словаре, а лемму — можно. Пример лемматизации: «run» — основа для слов «running» или «ran», а «better» и «good» находятся в одной и той же лемме и потому считаются одинаковыми.

Набор слов

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

  • словаря известных слов;
  • частот, с которыми каждое слово встречается в тексте.

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

Идея «набора слов» состоит в том, что тексты похожи по содержанию, если включают в себя похожие слова. Кроме того, кое-что узнать о содержании текста можно лишь по набору слов.

Например, если словарь содержит слова {Learning, is, the, not, great} и мы хотим составить вектор предложения “Learning is great”, получится вектор (1, 1, 0, 0, 1).

Метод TF-IDF

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

Один из подходов к решению этих проблем состоит в том, чтобы вычислять частоту появления слова не в одном тексте, а во всех сразу. За счет этого вклад, например, артиклей «a» и «the» будет нивелирован. Такой подход называется TF-IDF (Term Frequency-Inverse Document Frequency) и состоит из двух этапов:

  • TF — вычисление частоты появления слова в одном тексте
TF = (Число раз, когда слово "t" встречается в тексте)/(Количество слов в тексте)
  • IDF — вычисление того, на сколько редко слово встречается во всех текстах
IDF = 1+log(N/n), где N - общее количество текстов, n - во скольких текстах встречается "t"

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

Пример

Рассмотрим текст, содержащий 100 слов, в котором слово «телефон» появляется 5 раз. Параметр TF для слова «телефон» равен (5/100) = 0,05.

Теперь предположим, что у нас 10 миллионов документов, и слово телефон появляется в тысяче из них. Коэффициент вычисляется как 1+log(10 000 000/1000) = 4. Таким образом, TD-IDF равен 0,05 * 4 = 0,20.

TF-IDF может быть реализован в scikit так:

from sklearn.feature_extraction.text import TfidfVectorizer

Коэффициент Отиаи

TF-IDF — это преобразование, применяемое к текстам для получения двух вещественных векторов в векторном пространстве. Тогда мы можем получить коэффициент Отиаи любой пары векторов, вычислив их поэлементное произведение и разделив его на произведение их норм. Таким образом, получается косинус угла между векторами. Коэффициент Отиаи является мерой сходства между двумя ненулевыми векторами. Используя эту формулу, можно вычислить схожесть между любыми двумя текстами d1 и d2.

Cosine Similarity (d1, d2) =  Dot product(d1, d2) / ||d1|| * ||d2||

Здесь d1, d2 — два ненулевых вектора.

Подробное объяснение и практический пример TF-IDF и коэффициента Отиаи приведены в посте по ссылке.

Пришло время перейти к решению нашей задачи, то есть созданию чат-бота. Назовем его «ROBO».


Обучение чат-бота

В нашем примере мы будем использовать страницу Википедии в качестве текста. Скопируйте содержимое страницы и поместите его в текстовый файл под названием «chatbot.txt». Можете сразу использовать другой текст.

Импорт необходимых библиотек

import nltk
import numpy as np
import random
import string # to process standard python strings

Чтение данных

Выполним чтение файла corpus.txt и преобразуем весь текст в список предложений и список слов для дальнейшей предварительной обработки.

f=open('chatbot.txt','r',errors = 'ignore')
raw=f.read()
raw=raw.lower()# converts to lowercase
nltk.download('punkt') # first-time use only
nltk.download('wordnet') # first-time use only
sent_tokens = nltk.sent_tokenize(raw)# converts to list of sentences 
word_tokens = nltk.word_tokenize(raw)# converts to list of words

Давайте рассмотрим пример файлов sent_tokens и word_tokens

sent_tokens[:2]
['a chatbot (also known as a talkbot, chatterbot, bot, im bot, interactive agent, or artificial conversational entity) is a computer program or an artificial intelligence which conducts a conversation via auditory or textual methods.',
 'such programs are often designed to convincingly simulate how a human would behave as a conversational partner, thereby passing the turing test.']
word_tokens[:2]
['a', 'chatbot', '(', 'also', 'known']

Предварительная обработка исходного текста

Теперь определим функцию LemTokens, которая примет в качестве входных параметров токены и выдаст нормированные токены.

lemmer = nltk.stem.WordNetLemmatizer()
#WordNet is a semantically-oriented dictionary of English included in NLTK.
def LemTokens(tokens):
    return [lemmer.lemmatize(token) for token in tokens]
remove_punct_dict = dict((ord(punct), None) for punct in string.punctuation)
def LemNormalize(text):
    return LemTokens(nltk.word_tokenize(text.lower().translate(remove_punct_dict)))

Подбор ключевых слов

Определим реплику-приветствие бота. Если пользователь приветствует бота, бот поздоровается в ответ. В ELIZA используется простое сопоставление ключевых слов для приветствий. Будем использовать ту же идею.

GREETING_INPUTS = ("hello", "hi", "greetings", "sup", "what's up","hey",)
GREETING_RESPONSES = ["hi", "hey", "*nods*", "hi there", "hello", "I am glad! You are talking to me"]
def greeting(sentence):
 
    for word in sentence.split():
        if word.lower() in GREETING_INPUTS:
            return random.choice(GREETING_RESPONSES)

Генерация ответа

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

  • Импортируйте векторизатор TFidf из библиотеки, чтобы преобразовать набор необработанных текстов в матрицу свойств TF-IDF.
    from sklearn.feature_extraction.text import TfidfVectorizer
  • Кроме того, импортируйте модуль коэффициента Отиаи из библиотеки scikit
from sklearn.metrics.pairwise import cosine_similarity

Этот модуль будет использоваться для поиска в запросе пользователя ключевых слов. Это самый простой способ создать чат-бота.

Определим функцию отклика, которая возвращает один из нескольких возможных ответов. Если запрос не соответствует ни одному ключевому слову, бот выдает ответ «Извините! Я вас не понимаю».

def response(user_response):
    robo_response=''
TfidfVec = TfidfVectorizer(tokenizer=LemNormalize, stop_words='english')
    tfidf = TfidfVec.fit_transform(sent_tokens)
    vals = cosine_similarity(tfidf[-1], tfidf)
    idx=vals.argsort()[0][-2]
    flat = vals.flatten()
    flat.sort()
    req_tfidf = flat[-2]
    if(req_tfidf==0):
        robo_response=robo_response+"I am sorry! I don't understand you"
        return robo_response
    else:
        robo_response = robo_response+sent_tokens[idx]
        return robo_response

Наконец, мы задаем реплики бота в начале и конце переписки, в зависимости от реплик пользователя.

flag=True
print("ROBO: My name is Robo. I will answer your queries about Chatbots. If you want to exit, type Bye!")
while(flag==True):
    user_response = input()
    user_response=user_response.lower()
    if(user_response!='bye'):
        if(user_response=='thanks' or user_response=='thank you' ):
            flag=False
            print("ROBO: You are welcome..")
        else:
            if(greeting(user_response)!=None):
                print("ROBO: "+greeting(user_response))
            else:
                sent_tokens.append(user_response)
                word_tokens=word_tokens+nltk.word_tokenize(user_response)
                final_words=list(set(word_tokens))
                print("ROBO: ",end="")
                print(response(user_response))
                sent_tokens.remove(user_response)
    else:
        flag=False
        print("ROBO: Bye! take care..")

Вот и все. Мы написали код нашего первого бота в NLTK. Здесь вы можете найти весь код вместе с текстом. Теперь давайте посмотрим, как он взаимодействует с людьми:


Получилось не так уж плохо. Даже если чат-бот не смог дать удовлетворительного ответа на некоторые вопросы, он хорошо справился с другими.

Заключение

Хотя наш примитивный бот едва ли обладает когнитивными навыками, это был неплохой способ разобраться с NLP и узнать о работе чат-ботов. «ROBO», по крайней мере, отвечает на запросы пользователя. Он, конечно, не обманет ваших друзей, и для коммерческой системы вы захотите рассмотреть одну из существующих бот-платформ или фреймворки, но этот пример поможет вам продумать архитектуру бота.


Интересные статьи: