Python’ом по машинлернингу |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2018-03-19 10:30 Сегодня только ленивый не говорит (пишет, думает) про машинное обучение, нейросети и искусственный интеллект в целом. Всего лишь в прошлом году ML сравнили с подростковым сексом — все хотят, но никто не занимается. Сегодня все озабочены тем, что ИИ нас оставит без работы. Хотя, судя по последним исследованиям Gartner, можно успокоиться, так как к 2020 году благодаря ИИ появится больше рабочих мест, чем ликвидируется. Так что, дорогой друг, учи ML, и будет тебе счастье.
Примечание: мы продолжаем серию публикаций полных версий статей из журнала Хакер. Орфография и пунктуация автора сохранены.
В этой статье мы хотим показать ML на практическом кейсе — на примере проекта, который мы делали для Актион-пресс (сервис онлайн-подписки). Уверен, описанное в этом примере может пригодиться многим. Почему многим? Да потому, что проблема, которую мы решали, называлась «сортировка и пересылка по адресу огромного количества электронных писем». Проблема гигантской переписки, которую менеджерам приходится сортировать и пересылать в соответствующие отделы, практически универсальная, и проблему эту надо решать современными способами. Итак, после консультаций с заказчиком мы решили разработать модель машинного обучения для максимально возможной автоматизации сортировки писем. Модель машинного обучения Думаю, тебя не удивит, что в качестве языка для этого решения мы выбрали Python. Так сложилось исторически, он высокоуровневый, а самое важное — в нем есть множество полезных библиотек для машинного обучения. Про них я расскажу ниже. Честно говоря, про ML в данном случае рассказывать особо нечего. Набор простых бинарных классификаторов на основе логистической регрессии показал многообещающие результаты и позволил несколько абстрагироваться от самой модели, сосредоточившись на подготовке данных и построении вложенного текста. Но сам репозиторий уже использовался как основа для трех других независимых проектов, он хорошо показал себя в нескольких классификационных экспериментах и зарекомендовал себя как надежный фундамент для быстрого перехода к разработке. Поэтому задача данного раздела заключается не в демонстрации «ноу-хау», он нужен как основа для следующего за ним раздела, посвященного операционализации. Здесь я поделюсь своим опытом и дам некоторые рекомендации тебе, чтобы ты мог сам поэкспериментировать с этим кодом или повторно использовать его. Чтобы сохранить конфиденциальность, исходный набор данных был заменен аналогичным общедоступным набором для классификации отзывов о McDonalds. См. файл data/data.csv. Сами данные были представлены в файлах CSV с тремя столбцами: А вот код для инициализации этого самописного модуля чтения
По окончании инициализации нужно извлечь слова из документов и нормализовать их. В нашем случае после ряда экспериментов мы решили использовать набор вспомогательных функций в качестве обертки для всего процесса, чтобы скрыть обращения к библиотекам NLTK и Gensim внутри простого в использовании уровня конфигурации. Ниже мы даем экстрактору команду вернуть документы в виде списка слов, отбрасывая структуру абзацев или предложений (см. Обрати внимание, что приведенный ниже код ориентирован исключительно на выборки данных на английском языке, в то время как в оригинальной версии была реализована русская лемматизация с использованием PyMorphy2, что позволило добиться более точной классификации для русского языка.
Как только мы токенизируем наш корпус, следующим шагом будет построение вложения. Код ниже нужен, чтобы преобразовать каждый документ в ряд бессмысленных цифр для использования в классификаторе. Мы протестировали несколько разных подходов (включая BoW, TF-IDF, LSI, RP и w2v), но классическая модель LSI с 500 извлеченными топиками дала наилучшие результаты (AUC = 0,98) в нашем случае. Для начала код проверяет наличие существующей сериализованной модели в общей папке. Если модели нет, код обучает новую модель с использованием предварительно подготовленных данных и сохраняет результат на диск. Если модель обнаружена, она просто загружается в память. Затем код преобразовывает набор данных и повторяет поток со следующим вложением. По эффективности модель LSI превзошла гораздо более мощный алгоритм векторизации на базе word2vec и другие более сложные подходы, и это может быть обусловлено несколькими возможными причинами. Самая очевидная из них связана с тем, что письма тех типов, которые мы искали, имели предсказуемые и повторяющиеся шаблоны слов, как в случае автоответов (например, «Спасибо за ваше письмо… Меня не будет в офисе до… Если вопрос срочный...»). Поэтому для их обработки вполне достаточно чего-то простого, например TF-IDF. LSI поддерживает общую идеологию, и эту модель можно рассматривать как способ добавления синонимов, подходящих для обработки. В то же время алгоритм word2vec, прошедший обучение на Википедии, вероятно, генерирует ненужный шум из-за сложных синонимичных структур, тем самым «размывая» шаблоны в сообщениях и, следовательно, снижая точность классификации. Этот подход показал, что старые и довольно простые методы по-прежнему стоит пробовать, даже в эпоху word2vec и рекуррентных нейронных сетей.
Как всегда, от обязательного рутинного кода избавиться невозможно. Дальше он нам пригодится при подготовке данных для машинного обучения с применением skit-learn. Как я уже говорил выше, мы используем несколько бинарных вместо одного многоклассового классификатора. Именно поэтому создаем бинарную цель для одного из классов (в этом образце это SlowService). Ты можешь изменять значение переменной
Теперь приступаем к обучению классификатора (в нашем случае это логистическая регрессия), потом сохраним модель в том же общем каталоге, который использовали ранее для встраивания преобразований. Как ты мог заметить, в приведенном ниже коде мы придерживаемся специального формата имени модели: И последнее замечание, прежде чем мы продолжим. В качестве инструмента разработки я выбрал Visual Studio Code. Это простой в использовании легковесный редактор, который даже предоставляет базовые возможности IntelliSense (автозавершение кода и подсказки) для такого динамичного языка, как Python. В то же время расширения Jupyter и Python в сочетании с ядром IPython позволяют выполнять код поячеечно и визуализировать результат без повторного запуска скрипта, что всегда удобно для задач ML. Да, это похоже на стандартный Jupyter, но с IntelliSense и ориентацией на код/git. Я рекомендую тебе попробовать, хотя бы пока ты работаешь с образцом, поскольку для продуктивной разработки тут применяется множество других возможностей, связанных с VS Code. Что касается кода ниже, строка с plot ROC threshold values — это примеры использования расширения Jupyter. Ты можешь нажать специальную кнопку
Теперь настало время скрипта оценки: Score un.py. Нового в нем очень мало, большую часть кода взяли из первоначального обучающего эксперимента, рассмотренного ранее. Ознакомься с содержимым этого файла в репозитории GitHub. На вход подается файл CSV для оценки, на выходе получаем два разных файла, один содержит оцененные классы, другой — идентификаторы строк, оценить которые не представляется возможным. Я объясню причину использования файла позже, когда будем говорить об операционализации. В конце этого раздела хочу пояснить, почему мы используем несколько бинарных вместо одного многоклассового классификатора. Во-первых, так было гораздо проще начать, чтобы работать и оптимизировать производительность на классах по отдельности. Такой подход также позволяет использовать различные математические модели для разных классов, как в случае с автоответами, которые часто имеют довольно жесткую структуру, и их можно обрабатывать с помощью простого bag of words. В то же время, с точки зрения ИТ-специалиста, что-то наподобие кода ниже может упростить развертывание, позволив подключать новые или менять существующие модели, не затрагивая другие.
Ты даже можешь опробовать код прямо сейчас, используя собственные данные со своего локального ПК, и совсем без операционализации:
В VS Code ты даже можешь открыть раздел отладки Debug (Ctrl + Alt + D), выбрать Score (Python) в качестве конфигурации и нажать Start Debugging (Выполнить отладку), чтобы провести построчный анализ кода в редакторе. Когда алгоритмы завершат свою работу, результаты можно будет найти в файлах input.scores.csv и input.unscorable.csv в папке Scoredebug. Операционализация Поддержка Python в Azure Functions до сих пор находится в раннем preview, поэтому использование его для mission critical задач нежелательно. Но часто ML к таким не относится, а потому удобство реализации может перевесить сложности с адаптацией предварительной версии. Итак, на этом этапе у нас было два скрипта. Скрипт ExperimentsTraintExperiment.py обучает модель, затем преобразованную и обученную модель он сохраняет в общий каталог, и, как предполагается, этот обучающий скрипт перезапускается на локальной машине по мере необходимости. Скрипт Score un.py выполняется ежедневно, он сортирует новые электронные письма по мере поступления. В этом разделе мы поговорим об операционализации процесса с помощью Azure Functions. Функции просты в использовании, они позволяют привязать скрипт к множеству различных триггеров (HTTP, очереди, BLOB-объекты хранилища, WebHooks и так далее), предоставляют несколько автоматических привязок вывода и при этом стоят недорого: выбрав план Consumption, ты платишь всего 0,000016 доллара за каждый используемый гигабайт ОЗУ в секунду. Но здесь есть ограничения: твоя функция не может выполняться дольше десяти минут и использовать более 1,5 Гбайт ОЗУ. Если тебя это не устраивает, ты всегда можешь перейти на специальный тарифный план на базе App Service, сохранив при этом доступ к другим преимуществам serverless-подхода. Однако для нашей простой логистической регрессии и пакетов из нескольких сотен писем выбранный план оказался оптимальным. С точки зрения программиста, функция — это папка, которая носит имя самой функции (в нашем случае это просто Score) и содержит два разных файла:
Function.json можно создать вручную или сконфигурировать средствами портала Azure. Код, который мы получили в данном случае, представлен ниже. Первая привязка — inputcsv — запускает скрипт каждый раз, когда файл с именем, соответствующим шаблону
Скрипт
Это все изменения, необходимые для запуска службы при появлении файла CSV в BLOB-хранилище и получения в результате файлов, содержащих прогноз. Если честно, мы тестировали и другие триггеры, но обнаружили, что самая мощная функция Python — модули — становится ее проклятием в бессерверной системе. Модуль в Python — это не статическая библиотека, которую нужно подключить, как во многих других языках, а код, выполняемый при каждом запуске. Для таких долгосрочных решений, как службы, это почти незаметно, но с точки зрения функций Azure полное выполнение скрипта каждый раз влечет за собой довольно большие расходы. Это осложняет использование триггеров HTTP в Python, но batch-обработка на базе CSV-файлов, популярная во многих ML-сценариях, позволяет снизить эти расходы в расчете на строку данных до разумного минимума. Если ты не можешь обойтись без триггеров реального времени с Python, ты можешь попытаться перейти на выделенный тарифный план Azure App Service, поскольку это позволяет значительно увеличить вычислительные ресурсы хоста и ускорить импорт. В нашем случае простота реализации и низкая стоимость плана потребления перевесили преимущества быстрого выполнения. Прежде чем продолжить, давай посмотрим, как можно упростить разработку с помощью Visual Studio Code. На момент написания этой статьи интерфейс Functions CLI обеспечивал начальное формирование шаблонов Python, но функций отладки не было. Тем не менее среду выполнения не так сложно имитировать, используя встроенные функции VS Code. Нам поможет файл .vscodelaunch.json, позволяющий настраивать параметры отладки. Как видно из JSON ниже, при запуске debug в конфигурации Score (Python) мы просим VS Code выполнить отладку скрипта
Если ты хочешь использовать расширение Jupyter для интерактивной поячеечной разработки и выполнения, тебе нужна аналогичная конфигурация в коде функции. Поэкспериментировав, мы остановились на варианте кода ниже. Он выполняется только в среде IPython, а при нормальном выполнении или отладке через Debug игнорируется.
Конфигурация среды Теперь, когда у нас есть готовая модель и код функции, пришло время настроить нужную инфраструктуру Azure. На момент написания этой статьи поддержка Python в функциях Azure все еще находилась на этапе предварительной версии, поэтому требовались дополнительные шаги по настройке. По умолчанию в среде выполнения установлен Python версии 2.7. Чтобы перейти на более популярную версию 3.6, в соответствии с официальной статьей в wiki тебе нужно получить любой доступный пакет Python (можно использовать подготовленную среду) и поместить его в папку D:homesite ools. Все работает достаточно просто. Эта папка предшествует папке с установленным по умолчанию Python 2.7 в переменной PATH в момент поиска python.exe для исполнения. Ты можешь сделать это вручную с помощью встроенного пользовательского интерфейса Kudu, как показано в статье, однако я выяснил, что предусмотренная для него специальная функция более удобна. Функция setup показывает, как мы это делали во время работы над проектом. Сначала функция проверяет, установлена ли версия 3.6, если нет, то она загружает предварительно сконфигурированный архив (.zip) с Python и извлекает его в папку D:homesite ools.
Далее нужно установить требуемые пакеты pip. Pip имеет встроенный API для Python, поэтому работать с ним из Python так же просто, как в обычной командной строке. Из кода ниже видно, что используемые только в Python пакеты (langid, pymorphy) установлены, поэтому от нас не требуется никаких дополнительных действий. Проблема возникнет лишь с пакетами, созданными с помощью C++. В платформе App Service отсутствует компилятор Visual C++, поэтому остается только использовать предварительно скомпилированные пакеты (wheels). Некоторые из них уже присутствуют в репозитории pip (проверить можно здесь), для других специфичных ML-пакетов можно найти необходимый wheel здесь. В данном случае я использовал Azure Blob Storage, чтобы сделать эти пакеты доступными для функции Azure. Ты можешь повторно использовать эти ссылки или перевыложить их в любое публично доступное хранилище.
Этот же подход оказался эффективен для выполнения дополнительных шагов после настройки. Чтобы наше решение работало, нужно установить два корпуса, специфичных для NLTK. Приведенный ниже код выполняется сразу после набора команд install_packages.
Поскольку весь код в функции Setup идемпотентный, ты можешь без проблем добавить другие этапы настройки или установить дополнительные пакеты. Обрати внимание, что в первый раз эта функция должна запуститься дважды: сначала, чтобы перейти на Python 3.6, а затем, чтобы установить нужные пакеты. Заключение Несмотря на сложные настройки и ограничения, связанные с предварительным запуском, Azure Functions показали себя как довольно удобный и эффективный инструмент операционализации ML-моделей Python. Наш первоначальный проект был развернут в производственной среде, и модель ML помогла значительно улучшить результаты по сравнению с уже существующими подходами. Код для изучения и повторного использования доступен в репозитории на GitHub. Напоминаем, что это полная версия статьи из журнала Хакер. Источник: habrahabr.ru Комментарии: |
|