Книга «Создание приложений машинного обучения: от идеи к продукту»

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

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

image Хорошего настроения, Хаброжители!

Освойте ключевые навыки проектирования, разработки и развертывания приложений на базе машинного обучения (МО)!

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

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

Книга поможет:
  • Определить цель вашего МО-проекта
  • Быстро построить первый сквозной пайплайн и найти исходный датасет
  • Обучить модель и устранить узкие места в ее производительности
  • Развернуть модель и осуществить ее мониторинг


Создание первого сквозного пайплайна


Первая версия приложения не должна быть идеальной. Ее задача — предоставить все элементы пайплайна, чтобы мы могли понять, какие из них следует улучшать в первую очередь. Создание полного прототипа — простейший способ выявить то узкое место, о котором говорила Моника Рогати в разделе «Моника Рогати: как выбирать и приоритизировать МО-проекты» на с. 40.

Давайте начнем с создания простейшего пайплайна для выдачи предсказаний на основе входных данных.

Простейший «каркас» приложения


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

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

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

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

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

Вот два примера отличных эвристических алгоритмов, примененных в компании Insight Data Science, которые мне довелось курировать.

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

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

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

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

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

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

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

Прототип МО-редактора


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

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

input_text = parse_arguments()
processed = clean_input(input_text)
tokenized_sentences = preprocess_input(processed)
suggestions = get_suggestions(tokenized_sentences)

Давайте подробно рассмотрим каждую из этих функций. Функция синтаксического анализатора parse_arguments() очень простая — она принимает от пользователя строку без каких-либо параметров. Исходный код этого и других примеров кода можно найти в GitHub-репозитории нашей книги.

Парсинг и очистка данных


Прежде всего, мы выполним парсинг данных, принимаемых из командной строки. Это достаточно просто реализовать на языке Python:

def parse_arguments():
     """

     :return: Текст, который необходимо отредактировать
     """
     parser = argparse.ArgumentParser(
          description="Receive text to be edited"
     )
     parser.add_argument(
          'text',
          metavar='input text',
          type=str
     )
     args = parser.parse_args()
     return args.text

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

def clean_input(text):
     """

     :param text: Введенный пользователем текст
     :return: Очищенный текст, содержащий только символы в кодировке ASCII
     """
     # В целях упрощения сначала оставим только символы в кодировке ASCII
     return str(text.encode().decode('ascii', errors='ignore'))

Теперь нам нужно предобработать входные данные и выдать рекомендации. Для начала мы можем опереться на результаты исследований в области классификации текста, о которых упоминалось в разделе «Простейший подход: “сам себе алгоритм”» на с. 37. Это подразумевает определение степени сложности текста путем подсчета сводной статистики по количеству слогов, слов и предложений.

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

Токенизация текста


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

«Mr. O’Neill thinks that the boys’ stories about Chile’s capital aren’t amusing.»

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

def preprocess_input(text):
     """

     :param text: Очищенный текст
     :return: Текст, подготовленный к анализу: предложения разбиты на лексемы
     """
     sentences = nltk.sent_tokenize(text)
     tokens = [nltk.word_tokenize(sentence) for sentence in sentences]
     return tokens

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

Генерирование признаков


Последний шаг — написать несколько правил для выдачи рекомендаций пользователям. Для нашего простого прототипа начнем с определения частоты употребления ряда распространенных глаголов, союзов и наречий, а затем вычислим индекс удобочитаемости Флеша (Flesch readability score). После этого мы можем вывести пользователю отчет с этими метриками:

def get_suggestions(sentence_list):
     """

     Возвращает строку, содержащую наши рекомендации
     :param sentence_list: список из предложений, каждое из которых
     является списком слов
     :return: рекомендации по улучшению входных данных
     """
     told_said_usage = sum(
          (count_word_usage(tokens, ["told", "said"]) for tokens in sentence_list)
     )
     but_and_usage = sum(
          (count_word_usage(tokens, ["but", "and"]) for tokens in sentence_list)
     )
     wh_adverbs_usage = sum(
          (
               count_word_usage(
                    tokens,
                    [
                         "when",
                         "where",
                         "why",
                         "whence",
                         "whereby",
                         "wherein",
                         "whereupon",
                    ],
               )
               for tokens in sentence_list
          )
     )
     result_str = ""
     adverb_usage = "Adverb usage: %s told/said, %s but/and, %s wh adverbs" % (
          told_said_usage,
          but_and_usage,
          wh_adverbs_usage,
     )
     result_str += adverb_usage
     average_word_length = compute_total_average_word_length(sentence_list)
     unique_words_fraction = compute_total_unique_words_fraction(sentence_list)

     word_stats = "Average word length %.2f, fraction of unique words %.2f" % (
          average_word_length,
          unique_words_fraction,
     )
     # Используем HTML-тег для отображения в веб-приложении разрыва строки
     result_str += "<br/>"
     result_str += word_stats

     number_of_syllables = count_total_syllables(sentence_list)
     number_of_words = count_total_words(sentence_list)
     number_of_sentences = len(sentence_list)

     syllable_counts = "%d syllables, %d words, %d sentences" % (
     number_of_syllables,
     number_of_words,
     number_of_sentences,
     )
     result_str += "<br/>"
     result_str += syllable_counts

     flesch_score = compute_flesch_reading_ease(
          number_of_syllables, number_of_words, number_of_sentences
     )
     
flesch = "%d syllables, %.2f flesch score: %s" % (
          number_of_syllables,
          flesch_score,
          get_reading_level_from_flesch(flesch_score),
     )
     result_str += "<br/>"
     result_str += flesch

     return result_str

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

Об авторе
Эммануэль Амейзен уже в течение многих лет создает продукты на базе МО. В настоящее время он работает инженером по машинному обучению в компании Stripe1. До этого он возглавлял отдел ИИ в компании Insight Data Science, где курировал более 150 проектов МО. А еще раньше Эммануэль работал специалистом по обработке данных в компании Zipcar2, где участвовал в разработке фреймворков и сервисов, облегчающих развертывание МО-моделей в эксплуатационном окружении. Он получил образование в области МО и бизнеса, имеет диплом магистра в области ИИ от Университета Париж-Юг, магистра технических наук от Университета Париж-Сакле и магистра в области менеджмента от Парижской высшей школы коммерции.

Более подробно с книгой можно ознакомиться на сайте издательства:
» Оглавление
» Отрывок

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Для Хаброжителей скидка 25% по купону — Приложения

P.S.
На сайте издательства продолжается осенняя распродажа.
Источник: https://habr.com/ru/company/piter/blog/695822/


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

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

Привет, Хаброжители! Spring Boot, который скачивают более 75 миллионов раз в месяц, — наиболее широко используемый фреймворк Java. Его удобство и возможности совершили революцию в разработке приложен...
Перевод обновлённого гайда Android по архитектуре приложений. Это — вторая часть из пяти: про слой UI.
Начиная с первых версий .NET Core для сборки приложений, компания Microsoft предоставляет простой и удобный интерфейс командной строки (.NET CLI). Его возможности покрывают большинство потребностей по...
С самого начал работы над Roxy-WI мы думали о максимальном упрощении жизни пользователя с помощью веб-интерфейса. Поэтому мы решили добавить в продукт возможность работы с  WAF (Web Application F...
Привет, Хаброжители! Пора научиться использовать TensorFlow.js для построения моделей глубокого обучения, работающих непосредственно в браузере! Умные веб-приложения захватили мир, а реа...