что такое бейзлайн в машинном обучении
Видеосказки от ИИ: разбор бейзлайна трека Creative AI в рамках AIIJC
Сегодня мы, команда Sber AI, расскажем про бейзлайн генерации сказок с озвучкой и картинками, который мы предложили в рамках трека по Creative AI международного соревнования для школьников Artificial Intelligence International Junior Contest (AIIJC): рассмотрим аспекты обучения conditional ruGPT-3, генерацию музыки, генерацию изображения по текстовой строке, а также обсудим некоторые проблемы, с которыми пришлось столкнуться во время обучения и дообучения моделей.
В этом посте мы хотим разобрать (и разобраться сами), как можно использовать и объединять генеративные (и не только) модели для решения одной большой задачи — генерации контента. Мы подобрали большое количество материалов про каждую конкретную модель, чтобы ими можно было пользоваться сразу.
Зачем генерировать видеосказки?
Если хочется чего-то интересного в жизни — надо устроить соревнование! В первую очередь мы решили устроить соревновательный трек для школьников: в прошлый раз такая затея уже принесла SOTA в общеизвестной задаче с большим отрывом. Выбрали задачу, которая смогла бы бросить вызов даже современным большим моделям-трансформерам, а именно генерацию полноценного видео по текстовому запросу. Команда Creative AI в Sber AI заинтересовалась этой проблемой. В разное время разными исследователями было предпринято множество попыток решить эту задачу, например:
фильм, снятый по сценарию нейросети (статья видео);
генерация видео по названию (статья);
MoCoGan — генерация ведущих видео (по сути озвучивание сценария).
В целом все эти решения имели как свои плюсы, так и минусы, например, все они требовали вмешательства человека на определённых этапах, необходимо было что-то делать самому.
Мы сделали бейзлайн генерации, где на вход подаётся название сказки, а композиция из нескольких нейронных сетей на выходе даёт результат. Например такой:
Как мы подошли к решению задачи? Понятно, что написание любого рассказа начинается со сценария. Давайте подробнее рассмотрим, как мы его генерировали.
Генерация текста
Прошлой осенью Сбер выпустил ruGPT-3, что стало большим достижением в русском NLP (самая большая модель как по числу параметров, так и по размеру датасета). GPT-образные модели можно использовать для conditional generation, то есть для генерации текста с некими заданными заранее признаками. И мы с командой как раз хотели иметь возможность генерировать текст в нужном жанре и с правильным названием.
Нужно отметить, что в случае с ruGPT-3 речь идёт именно про ГИГАНТСКИЕ генеративные модели, дообучать и обучать с нуля которые крайне проблематично. А нам нужно было, чтобы у участников соревнования была возможность при желании файнтюнить модель самим. Поэтому было принято решение взять ruGPT-3 Small — в отличие от своих старших братьев, её можно файнтюнить даже на домашних видеокартах или Colab за адекватное время (несколько часов на K80), при этом она в состоянии выдавать неплохой результат.
Сначала мы поставили эксперимент на этом датасете русских сказок. Он содержит в себе 28 тысяч рассказов, размеченных на две категории — детские и взрослые. Но сказки не имеют названия, а следовательно нельзя будет обращаться к нейросети как к волшебному горшочку.
Протестировав модель для двух жанров, мы поняли, что это как минимум не очень интересно, и стали копать дальше. Так мы пришли к сайту фанатских рассказов Ficbook.ru. Его плюсы заключаются в обилии тегов, подробной разметке по жанрам, а также размерах текстов (средняя длина составила 1500 токенов). Результаты генерации получились такие (вместо двух весьма размытых жанров у нас появились вполне конкретные):
Имя: Гарри Поттер. Жанр: ужасы. Текст:
«Imagine, I know», — сказал себе Гарри перед тем как уснуть. Он был в комнате и думал о том, что ему нужно делать… Он не мог заснуть, потому то всё это казалось сном… Но нет! Все эти воспоминания были реальностью. Это была реальность его мечты… Но почему же тогда так больно? Может, из-за того, чего я здесь сижу на этой самой кровати? Почему мне хочется кричать от боли?! Что за чувство такое? Не могу понять. Наверное, просто страх потери… А может, боль осознания своей вины? Нет, нет, конечно. Я хочу плакать! Слёзы градом лились по моему лицу!
Имя: Гарри Поттер. Жанр: магический реализм. Текст:
На поляне горел костёр. Пляшущие языки пламени то взвивались вверх, будто пытаясь лизнуть нависающие над ними ветви деревьев и поленьями пробираясь сквозь кустарники; то прижимались к стенам хижины отшельника — импровизированной крепости из колючих стеблей осоки или жёсткого камня с утолщёнными краёвстыми стенками — для защиты от непогоды.
— Хагрид! Гарри! — закричал чародей в сторону источника огня (непонятно откуда взялась зелёная вспышка), но ожидаемой боли не последовало ни по одному боку поляны, либо горящей травы даже под порыв ветра. Выглядящий запуганным Северус Снейп застыл как громом поражённый. Колени затряслись ещё больше от того, что мощный импульс магической энергии ударил прямо через тело мальчика-подростка. В тот самый момент Дамблдор сделал шаг назад со снимающей заклинание палочкой у самого лица директора Шишкиной.
— Ты можешь объяснить нормально? Это ненормально! *тихо рыдая* Тебе нужно отдохнуть! Ты должен вернуться обратно!
Да, стоит отметить проблему того, что качество некоторых текстов было довольно низким, поэтому мы решили использовать только тексты, набравшие не менее 100 лайков, качество которых оказалось вполне удовлетворительным. Строго говоря, было не обязательно так делать, потому что длины окна не хватит в любом случае, и генерировать полноценный рассказ GPT-шкой в один заход — почти утопия, контекст теряют даже самые большие модели. В целом, есть разные способы для того, чтобы заставить модель генерировать более длинные и качественные последовательности, например sparse attention, который и был использован в самых больших версиях GPT-3. Подробнее про то, как генерировать тексты, можно почитать в этой статье от HuggingFace.
А теперь расскажем нашу сказку.
Каждая история должна быть рассказана, а так как сказку написал в некотором роде ИИ, то будет логично, что и расскажет её ИИ.
Генерация речи
Моделей для генерации речи из текста на русском довольно много, каждая крупная компания обязательно обучит свою на основе известной архитектуры или дообучить другую известную архитектуру. Но есть одна маленькая проблема: все существующие крутые решения или закрыты, или доступны в виде приватного API.
Это не подходило под нашу идею использовать открытые решения, которые при желании можно легко файнтюнить, в связи с чем выбор пал на SILERO models, которые делает команда SILERO (github, статьи про модельки)(находятся под лицензией GNU AGPL).
В целом качество синтеза речи было на достаточно хорошем уровне, но так как обучение модели генерации текста проводилось на открытых данных, то возникла одна существенная проблема: у модели были заметные трудности с грамматикой, она часто путалась в окончаниях и в целом говорила не очень грамотно. Это не слишком серьёзная проблема для чтения текста человеком, но большая проблема для вокодера (подробнее про то, как обучаются text2speech-модели, можно почитать тут).
Решение было простым — давайте исправим грамматику с помощью опечаточника JamSpell.
Так как Silero models имеют ограничение в 140 символов, то текст разбивается на батчи по 140 символов, игнорируя целостность слов. Возможность этого улучшения мы предлагаем участникам, как и возможность, например, добавить свои кастомные ударения.
Добавим музыки
Первое, что приходит на ум, когда говорят про музыку, сгенерированную ИИ, — Jukebox от OpenAI. Гигантская модель для генерации (пропевания и продолжения) музыки, основанная на заданном тексте и/или некоторой затравке, созданная в 2020 году.
В её основе лежат модифицированные вариационные автоэнкодеры, которые сжимают огромное входное пространство в более адекватные и пригодные пространства для дальнейших вычислений. Генерация происходит именно в сжатом пространстве с последующим апсемплингом для повышения качества звука сгенерированного трека.
Jukebox может также разнообразно «пропевать» текст песни внутри трека, однако качество такого пропевания и соответствие заданному тексту далеко не всегда удовлетворительное.
На выходе получается уже готовый трек, не требующий серьёзной обработки.
Но с Jukebox есть одна существенная проблема: частота записанной музыки составляет не менее 44100 Гц, а значит, что в одной минуте трека будет более 2,5 млн наблюдений. В связи с чем генерация занимает огромное количество времени (на 30 секунд генерации уходит порядка 4,5 часов), а качество сгенерированной музыки резко падает после 15—20 секунд. Иногда генерация изначально получается плохая.
Также запуск Jukebox на Colab или на домашних мощностях представляется маловозможным, особенно в режиме генерации с нуля — она просто не запустится, ведь требуется карточка или кластер, сопоставимые с V100. И если запуск на мощностях Сбера будет простым, то у участников таких мощностей, скорее всего, нет.
И тогда задачу генерации музыки можно свести к задаче, решаемой современными языковыми моделями, и «просто» предсказывать следующую ноту. Данный подход работает с одной дорожкой, сделать такое для нескольких очень сложно. Поэтому мы взяли самое оптимальное, на наш взгляд, решение — MusicTransformer от Magenta.
В его основе лежит архитектура GPT, с одной поправкой — вместо обычного Self-attention используется Relative Attention (относительное представление зависимостей токенов). Такой тип attention позволяет учитывать зависимости куплет-припев.
В целом качество музыки получается довольно высоким, однако это не готовый трек, а трек, требующий обработки в различных секвенсорах.
Для такого типа модели есть 2 проблемы:
1. Сложный энкодинг, учитывающий всю необходимую информацию, сильно раздувает размер входной последовательности.
В MusicTransformer используется event-based энкодинг, который описывает события включения и выключения нот, громкости нот и временных дельт. Таким образом, на 15 секунд генерации в среднем выходит около 1000 токенов, и генерировать более длительные композиции становится проблематично.
2. Датасет для такой модели собрать достаточно проблематично, т. к. в открытом доступе уж слишком мало данных.
Из возможных вариантов решения — парсить открытые источники и парсить музыку из YouTube с последующим транскрибированием wav-формата в midi (пример хорошей модели транскрибирования).
Существует несколько хороших имплементаций MusicTransformer, которые участники соревнования могут модифицировать для достижения лучших результатов: ссылка, ссылка.
Визуализируем то, что написал ИИ
А теперь давайте визуализируем то, что написала GPT-шка, и добавим к сказке сопутствующий видеоряд.
Задача визуализации по текстовому описанию безумно сложная. Первые попытки её решить были предприняты в 2015—2018 годах, выходило довольно много статей касательно того, что можно сделать. Практически все они либо не имели имплементации в коде, либо ничего не работало так, как было описано в статье.
Так было до января 2020 года, когда OpenAI выпустили статьи «DALL-E — creating images from text» и «CLIP — connecting text and images». И если первая модель всё ещё не в open source, то веса CLIP-а были опубликованы почти сразу после выхода статьи.
Казалось бы, у нас есть проекция картинки и текста в одно и то же пространство, как можно из этого сделать text2image? Ребята с reddit предложили очень простую и в то же время гениальную идею того, как это можно осуществить: давайте возьмём генератор от GAN и заставим его что-то генерировать, а потом будем двигать оптимизатором так, чтобы получать наиболее близкую к текстовому описанию картинку (для этого возьмём из CLIP-а перевод текста в латентное признаковое пространство и будем это векторное представление текста приближать к нужному изображению). Данный подход можно использовать для любого GAN, да и в принципе практически любой сетки для генерации картинок.
В апреле этого года была представлена архитектура Taming transformers, она основана на идее представления картинки в виде CodeBook — состоящего из набора квадратов изображения.
В этой архитектуре используется комбинация идей из GAN и трансформеров. Любопытно, что изначально эта архитектура пригодна для решения многих задач, связанных с генерацией изображений, таких как Depth2Image (воссоздание изображения из карты глубины), а также задаче, решаемой image GPT.
Рассмотрим примеры генерации на VQGAN + CLIP (обычный английский).
Text: картина с цветами в вазе.
Интересный факт: при обучении скорее всего использовались открытые данные, в том числе с сайтов художников вроде ArtStation, где часто встречались ключевые слова типа UNREAL ENGINE| Hyperrealistic.
Что мы имеем в итоге, если добавить такие ключевые слова?
А вот, например, в стиле Сальвадора Дали:
В мае этого года в Индии исследователь опубликовал подход для MTCLIP (примечание автора — MT: multilanguage) на основе mtBERT.
Это позволило добавить русский язык, а вот пример генерации для текстового ввода:
Свежие подходы к генерации
Индустрия развивается динамично — за то время, что мы писали статью, вышел подход на основе Guided Diffusion, который ставит новую планку качества генерации.
Текстовый запрос: Логотип Sber AI.
Текстовый запрос: Цветы в вазе.
Ещё немного про генерацию картинок из текста
А ещё мы собрали ноутбук на VQGAN + Multilanguage CLIP (поддерживает 104 Mtbert языка). Плюс можно настраивать разрешение, но лучше запускать его с Collab pro, а ещё лучше — на отдельном кластере.
Участникам мы предлагаем самим попробовать добавить MT CLIP по примеру того, что написали мы 🙂
Кстати, регистрация на соревнование всё ещё доступна по ссылке, от участников требуется быть младше 18 лет.
What does «baseline» mean in the context of machine learning?
What does «baseline» mean in the context of machine learning and data science?
Hint: An appropriate baseline will give an RMSE of approximately 200.
I don’t get this. Does he mean that if my predictive model on the training data has a RMSE below 500, it’s good?
And what could be a «baseline approach»?
3 Answers 3
A baseline is the result of a very basic model/solution. You generally create a baseline and then try to make more complex solutions in order to get a better result. If you achieve a better score than the baseline, it is good.
A baseline is a method that uses heuristics, simple summary statistics, randomness, or machine learning to create predictions for a dataset. You can use these predictions to measure the baseline’s performance (e.g., accuracy)— this metric will then become what you compare any other machine learning algorithm against.
A machine learning algorithm tries to learn a function that models the relationship between the input (feature) data and the target variable (or label). When you test it, you will typically measure performance in one way or another. For example, your algorithm may be 75% accurate. But what does this mean? You can infer this meaning by comparing with a baseline’s performance.
Typical baselines include those supported by scikit-learn’s «dummy» estimators:
This is useful for metrics that evaluate a non-majority class.
In general, you will want your approach to outperform the baselines you have selected. In the example above, you would want your 75% accuracy to be higher than any baseline you have run on the same data.
Открытый курс машинного обучения. Тема 1. Первичный анализ данных с Pandas
Открытый курс машинного обучения mlcourse.ai сообщества OpenDataScience – это сбалансированный по теории и практике курс, дающий как знания так и навыки (необходимые, но не достаточные) машинного обучения уровня Junior Data Scientist. Нечасто встретите и подробное описание математики, стоящей за используемыми алгоритмами, и соревнования Kaggle, и примеры бизнес-применения машинного обучения в одном курсе. С 2017 по 2020 годы yorko и большая команда ODS проводили живые запуски курса дважды в год – с домашними заданиями, соревнованиями и общим рейтингом учатсников (имена героев все еще запечатлены тут). Верим, что силами ODS такой формат возродится, а пока, на август 2021, курс – в режиме самостоятельного прохождения.
Опубликован план самостоятельного прохождения курса (англ.) – https://mlcourse.ai/roadmap.
Список статей серии
План этой статьи
1. О курсе
Мы не ставим себе задачу разработать еще один исчерпывающий вводный курс по машинному обучению или анализу данных (т.е. это не замена специализации Яндекса и МФТИ, дополнительному образованию ВШЭ и прочим фундаментальным онлайн- и оффлайн-программам и книжкам). Цель этой серии статей — быстро освежить имеющиеся у вас знания или помочь найти темы для дальнейшего изучения. Подход примерно как у авторов книги Deep Learning, которая начинается с обзора математики и основ машинного обучения — краткого, максимально ёмкого и с обилием ссылок на источники.
Если вы планируете пройти курс, то предупреждаем: при подборе тем и создании материалов мы ориентируемся на то, что наши слушатели знают математику на уровне 2 курса технического вуза и хотя бы немного умеют программировать на Python. Это не жёсткие критерии отбора, а всего лишь рекомендации — можно записаться на курс, не зная математики или Python, и параллельно навёрстывать:
Также про курс рассказано в этом анонсе.
Какое ПО нужно
Для прохождения курса нужен ряд Python-пакетов, большинство из них есть в сборке Anaconda с Python 3.6. Чуть позже понадобятся и другие библиотеки, об этом будет сказано дополнительно. Полный список можно посмотреть в Dockerfile.
Также можно воспользоваться Docker-контейнером, в котором все необходимое ПО уже установлено. Подробности – на странице Wiki репозитория.
2. Домашние задания в курсе
Каждая статья сопровождается домашним заданием в виде тетрадки Jupyter, в которую надо дописать код, и на основе этого выбрать правильный ответ в форме Google. Примеры домашних заданий приведены в статьях серии (в конце).
3. Демонстрация основных методов Pandas
Весь код можно воспроизвести в этом Jupyter notebook.
Основными структурами данных в Pandas являются классы Series и DataFrame. Первый из них представляет собой одномерный индексированный массив данных некоторого фиксированного типа. Второй – это двухмерная структура данных, представляющая собой таблицу, каждый столбец которой содержит данные одного типа. Можно представлять её как словарь объектов типа Series. Структура DataFrame отлично подходит для представления реальных данных: строки соответствуют признаковым описаниям отдельных объектов, а столбцы соответствуют признакам.
Будем показывать основные методы в деле, анализируя набор данных по оттоку клиентов телеком-оператора (скачивать не нужно, он есть в репозитории). Прочитаем данные (метод read_csv ) и посмотрим на первые 5 строк с помощью метода head :
В Jupyter-ноутбуках датафреймы Pandas выводятся в виде вот таких красивых табличек, и print(df.head()) выглядит хуже.
По умолчанию Pandas выводит всего 20 столбцов и 60 строк, поэтому если ваш датафрейм больше, воспользуйтесь функцией set_option :
Каждая строка представляет собой одного клиента – это объект исследования.
Столбцы – признаки объекта.
Название | Описание | Тип |
---|---|---|
State | Буквенный код штата | номинальный |
Account length | Как долго клиент обслуживается компанией | количественный |
Area code | Префикс номера телефона | количественный |
International plan | Международный роуминг (подключен/не подключен) | бинарный |
Voice mail plan | Голосовая почта (подключена/не подключена) | бинарный |
Number vmail messages | Количество голосовых сообщений | количественный |
Total day minutes | Общая длительность разговоров днем | количественный |
Total day calls | Общее количество звонков днем | количественный |
Total day charge | Общая сумма оплаты за услуги днем | количественный |
Total eve minutes | Общая длительность разговоров вечером | количественный |
Total eve calls | Общее количество звонков вечером | количественный |
Total eve charge | Общая сумма оплаты за услуги вечером | количественный |
Total night minutes | Общая длительность разговоров ночью | количественный |
Total night calls | Общее количество звонков ночью | количественный |
Total night charge | Общая сумма оплаты за услуги ночью | количественный |
Total intl minutes | Общая длительность международных разговоров | количественный |
Total intl calls | Общее количество международных разговоров | количественный |
Total intl charge | Общая сумма оплаты за международные разговоры | количественный |
Customer service calls | Число обращений в сервисный центр | количественный |
Целевая переменная: Churn – Признак оттока, бинарный признак (1 – потеря клиента, то есть отток). Потом мы будем строить модели, прогнозирующие этот признак по остальным, поэтому мы и назвали его целевым.
Посмотрим на размер данных, названия признаков и их типы.
Видим, что в таблице 3333 строки и 20 столбцов. Выведем названия столбцов:
Чтобы посмотреть общую информацию по датафрейму и всем признакам, воспользуемся методом info :
Метод describe показывает основные статистические характеристики данных по каждому числовому признаку (типы int64 и float64 ): число непропущенных значений, среднее, стандартное отклонение, диапазон, медиану, 0.25 и 0.75 квартили.
State | International plan | Voice mail plan | |
---|---|---|---|
count | 3333 | 3333 | 3333 |
unique | 51 | 2 | 2 |
top | WV | No | No |
freq | 106 | 3010 | 2411 |
Сортировка
DataFrame можно отсортировать по значению какого-нибудь из признаков. В нашем случае, например, по Total day charge ( ascending=False для сортировки по убыванию):
Сортировать можно и по группе столбцов:
спасибо за замечание про устаревший sort makkos
Индексация и извлечение данных
DataFrame можно индексировать по-разному. В связи с этим рассмотрим различные способы индексации и извлечения нужных нам данных из датафрейма на примере простых вопросов.
14,5% — довольно плохой показатель для компании, с таким процентом оттока можно и разориться.
Воспользуемся этим для ответа на вопрос: каковы средние значения числовых признаков среди нелояльных пользователей?
Скомбинировав предыдущие два вида индексации, ответим на вопрос: сколько в среднем в течение дня разговаривают по телефону нелояльные пользователи?
Какова максимальная длина международных звонков среди лояльных пользователей ( Churn == 0 ), не пользующихся услугой международного роуминга ( ‘International plan’ == ‘No’ )?
В первом случае мы говорим «передай нам значения для id строк от 0 до 5 и для столбцов от State до Area code», а во втором — «передай нам значения первых пяти строк в первых трёх столбцах».
Хозяйке на заметку: когда мы передаём slice object в iloc, датафрейм слайсится как обычно. Однако в случае с loc учитываются и начало, и конец слайса (ссылка на документацию, спасибо arkane0906 за замечание).
State | Account length | Area code | |
---|---|---|---|
0 | KS | 128 | 415 |
1 | OH | 107 | 415 |
2 | NJ | 137 | 415 |
3 | OH | 84 | 408 |
4 | OK | 75 | 415 |
5 | AL | 118 | 510 |
State | Account length | Area code | |
---|---|---|---|
0 | KS | 128 | 415 |
1 | OH | 107 | 415 |
2 | NJ | 137 | 415 |
3 | OH | 84 | 408 |
4 | OK | 75 | 415 |
Если нам нужна первая или последняя строчка датафрейма, пользуемся конструкцией df[:1] или df[-1:] :
Применение функций к ячейкам, столбцам и строкам
Применение функции к каждому столбцу: apply
Применение функции к каждой ячейке столбца: map
Например, метод map можно использовать для замены значений в колонке, передав ему в качестве аргумента словарь вида
Аналогичную операцию можно провернуть с помощью метода replace :
Группировка данных
В общем случае группировка данных в Pandas выглядит следующим образом:
Группирование данных в зависимости от значения признака Churn и вывод статистик по трём столбцам в каждой группе.
Сделаем то же самое, но немного по-другому, передав в agg список функций:
Сводные таблицы
Voice mail plan | No | Yes |
---|---|---|
Churn | ||
0 | 0.602460 | 0.252625 |
1 | 0.120912 | 0.024002 |
Мы видим, что большинство пользователей лояльны и при этом пользуются дополнительными услугами (международного роуминга / голосовой почты).
Давайте посмотрим среднее число дневных, вечерних и ночных звонков для разных Area code:
Total day calls | Total eve calls | Total night calls | |
---|---|---|---|
Area code | |||
408 | 100.496420 | 99.788783 | 99.039379 |
415 | 100.576435 | 100.503927 | 100.398187 |
510 | 100.097619 | 99.671429 | 100.601190 |
Преобразование датафреймов
Как и многое другое в Pandas, добавление столбцов в DataFrame осуществимо несколькими способами.
Например, мы хотим посчитать общее количество звонков для всех пользователей. Создадим объект total_calls типа Series и вставим его в датафрейм:
Добавить столбец из имеющихся можно и проще, не создавая промежуточных Series:
4. Первые попытки прогнозирования оттока
Посмотрим, как отток связан с признаком «Подключение международного роуминга» (International plan). Сделаем это с помощью сводной таблички crosstab, а также путем иллюстрации с Seaborn (как именно строить такие картинки и анализировать с их помощью графики – материал следующей статьи).
International plan | False | True | All |
---|---|---|---|
Churn | |||
0 | 2664 | 186 | 2850 |
1 | 346 | 137 | 483 |
All | 3010 | 323 | 3333 |
Видим, что когда роуминг подключен, доля оттока намного выше – интересное наблюдение! Возможно, большие и плохо контролируемые траты в роуминге очень конфликтогенны и приводят к недовольству клиентов телеком-оператора и, соответственно, к их оттоку.
Далее посмотрим на еще один важный признак – «Число обращений в сервисный центр» (Customer service calls). Также построим сводную таблицу и картинку.
Customer service calls | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | All |
---|---|---|---|---|---|---|---|---|---|---|---|
Churn | |||||||||||
0 | 605 | 1059 | 672 | 385 | 90 | 26 | 8 | 4 | 1 | 0 | 2850 |
1 | 92 | 122 | 87 | 44 | 76 | 40 | 14 | 5 | 1 | 2 | 483 |
All | 697 | 1181 | 759 | 429 | 166 | 66 | 22 | 9 | 2 | 2 | 3333 |
Может быть, по сводной табличке это не так хорошо видно (или скучно ползать взглядом по строчкам с цифрами), а вот картинка красноречиво свидетельствует о том, что доля оттока сильно возрастает начиная с 4 звонков в сервисный центр.
Churn | 0 | 1 | All |
---|---|---|---|
Many_service_calls | |||
0 | 2721 | 345 | 3066 |
1 | 129 | 138 | 267 |
All | 2850 | 483 | 3333 |
Объединим рассмотренные выше условия и построим сводную табличку для этого объединения и оттока.
Значит, прогнозируя отток клиента в случае, когда число звонков в сервисный центр больше 3 и подключен роуминг (и прогнозируя лояльность – в противном случае), можно ожидать около 85.8% правильных попаданий (ошибаемся всего 464 + 9 раз). Эти 85.8%, которые мы получили с помощью очень простых рассуждений – это неплохая отправная точка (baseline) для дальнейших моделей машинного обучения, которые мы будем строить.
В целом до появления машинного обучения процесс анализа данных выглядел примерно так. Прорезюмируем:
5. Домашнее задание №1
Далее курс будет проводиться на английском языке (статьи на Медиуме тоже есть). Следующий запуск – 1 октября 2018 г.
Для разминки/подготовки предлагается поанализировать демографические данные с помощью Pandas. Надо заполнить недостающий код в Jupyter-заготовке и выбрать правильные ответы в веб-форме (там же найдете и решение).
6. Обзор полезных ресурсов
Статья написана в соавторстве с yorko (Юрием Кашницким).