{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "## Открытый курс по машинному обучению\n", "
Автор материала: Шаймарданова Екатерина (@ekaterina)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#
TeaPOT
" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Что такое автоматизированное машинное обучение (automated ml)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теория обучения машин (machine learning, машинное обучение) находится на стыке прикладной статистики, численных методов оптимизации, дискретного анализа, и за последние 50 лет оформилась в самостоятельную математическую дисциплину. Методы машинного обучения составляют основу еще более молодой дисциплины — интеллектуального анализа данных (data mining).\n", "Перенося эти определения на automated machine learning (AML), можно сказать, что это − «Теория автоматического / автоматизированного обучения машин».\n", "\n", "Чтобы применять машинное обучение для решения конкретных кейсов, необходимо постоянно:\n", "\n", "* Настраивать гиперпараметры моделей;\n", "* Пробовать новые алгоритмы;\n", "* Добавлять в модели различные представления исходных признаков\n", "\n", "От этих рутинных операций, как и от части операций в подготовке и очистке данных, аналитиков или data scientist’ов можно избавить с помощью автоматизации.\n", "\n", "Автоматизированный алгоритм может перебрать все стандартные комбинации и выдать некоторое базовое решение, которое квалифицированный специалист сможет взять за основу и дальше улучшать. Однако во многих случаях результатов работы автоматизированного алгоритма окажется достаточно и без дополнительных улучшений, и их можно будет использовать непосредственно.\n", "\n", "На сегодняшний день можно выделить два наиболее результативных пакета автоматизированного машинного обучения. Оба они используют библиотеку машинного обучения sklearn языка Python и активно разрабатываются.\n", "Первый из них — библиотека Auto-sklearn, разработанный во Фрайбургском университете.\n", "Вторым лидирующим решением в области автоматизированного машинного обучения выступает библиотека TeaPOT (TPOT).\n", "\n", "Как определяют TPOT сами авторы - это инструмент Python, который автоматически создает и оптимизирует конвейеры (pipeline) машинного обучения с использованием генетического программирования. TPOT автоматизирует самую утомительную часть машинного обучения, исследуя тысячи возможных конвейеров, чтобы найти лучший для ваших данных." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![img](https://raw.githubusercontent.com/rhiever/tpot/master/images/tpot-ml-pipeline.png)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Установка TPOT" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Требует предварительной установки следующих пакетов: NumPy, SciPy, scikit-learn, DEAP, update_checker, tqdm, pywin32 (для Windows), xgboost, scikit-mdr и skrebate:\n", "\n", "* conda install numpy scipy scikit-learn\n", "* pip install deap update_checker tqdm\n", "* pip install pywin32\n", "* pip install xgboost\n", "* pip install scikit-mdr skrebate\n", "* pip install tpot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Пример использования на Iris Flower Classification" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from sklearn.datasets import load_iris\n", "from sklearn.model_selection import train_test_split\n", "from tpot import TPOTClassifier\n", "\n", "iris = load_iris()\n", "X_train, X_test, y_train, y_test = train_test_split(iris.data.astype(np.float64),\n", " iris.target.astype(np.float64), train_size=0.75, test_size=0.25)\n", "\n", "tpot = TPOTClassifier(generations=5, population_size=50, verbosity=2)\n", "tpot.fit(X_train, y_train)\n", "print(tpot.score(X_test, y_test))\n", "tpot.export('tpot_iris_pipeline.py') " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Содержание 'tpot_iris_pipeline.py' (может отличаться - не зафиксировала random seed):\n", "#import numpy as np\n", "\n", "#from sklearn.model_selection import train_test_split\n", "#from sklearn.naive_bayes import GaussianNB\n", "#from sklearn.pipeline import make_pipeline\n", "#from sklearn.preprocessing import Normalizer\n", "\n", "# NOTE: Make sure that the class is labeled 'class' in the data file\n", "#tpot_data = np.recfromcsv('PATH/TO/DATA/FILE', delimiter='COLUMN_SEPARATOR', dtype=np.float64)\n", "#features = np.delete(tpot_data.view(np.float64).reshape(tpot_data.size, -1), tpot_data.dtype.names.index('class'), axis=1)\n", "#training_features, testing_features, training_classes, testing_classes = \\\n", "# train_test_split(features, tpot_data['class'], random_state=42)\n", "\n", "#exported_pipeline = make_pipeline(\n", "# Normalizer(norm=\"l2\"),\n", "# GaussianNB()\n", "#)\n", "\n", "#exported_pipeline.fit(training_features, training_classes)\n", "#results = exported_pipeline.predict(testing_features)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Получаем точность при тестировании примерно 97%." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Описание некоторых параметров TPOT" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* generations - любое положительное целое число - Число итераций в процессе оптимизации конвейерного процесса. Как правило, TPOT будет работать лучше, если вы дадите ему больше поколений (и, следовательно, времени), чтобы оптимизировать конвейер.\n", "* population_size - любое положительное целое число - Количество особей, оставшихся в популяции для каждого поколения.\n", "* offspring_size - любое положительное целое число - Число потомков в каждом поколении.\n", "* verbosity - Какое количество информации выдает TPOT при запуске. 0 = none, 1 = minimal, 2 = high, 3 = all.\n", "* mutation_rate - [0.0,1.0] - Скорость мутации алгоритма. Для какого количества конвейеров применяются случайные изменения в каждом поколении. Рекомендуется оставить значение по-умолчанию.\n", "* crossover_rate - [0.0,1.0] - Скорость селекции для алгоритма. Показывает какое количество конвейеров \"порождает\" каждое поколение. Также рекомендуется оставить значение по-умолчанию." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Пример использования на данных соревнования Catch Me If You Can" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "# загрузим обучающую и тестовую выборки\n", "train_df = pd.read_csv('../../data/websites_train_sessions.csv',\n", " index_col='session_id')\n", "test_df = pd.read_csv('../../data/websites_test_sessions.csv',\n", " index_col='session_id')\n", "\n", "# приведем колонки time1, ..., time10 к временному формату\n", "times = ['time%s' % i for i in range(1, 11)]\n", "train_df[times] = train_df[times].apply(pd.to_datetime)\n", "test_df[times] = test_df[times].apply(pd.to_datetime)\n", "\n", "# отсортируем данные по времени\n", "train_df = train_df.sort_values(by='time1')\n", "\n", "# посмотрим на заголовок обучающей выборки\n", "train_df.head()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pickle\n", "\n", "# приведем колонки site1, ..., site10 к целочисленному формату и заменим пропуски нулями\n", "sites = ['site%s' % i for i in range(1, 11)]\n", "train_df[sites] = train_df[sites].fillna(0).astype('int')\n", "test_df[sites] = test_df[sites].fillna(0).astype('int')\n", "\n", "# загрузим словарик сайтов\n", "with open(r\"../../data/site_dic.pkl\", \"rb\") as input_file:\n", " site_dict = pickle.load(input_file)\n", "\n", "# датафрейм словарика сайтов\n", "sites_dict = pd.DataFrame(list(site_dict.keys()), index=list(site_dict.values()), columns=['site'])\n", "print(u'всего сайтов:', sites_dict.shape[0])\n", "sites_dict.head()\n", "\n", "# создадим отдельный датафрейм, где будем работать со временем\n", "time_df = pd.DataFrame(index=train_df.index)\n", "time_df['target'] = train_df['target']\n", "\n", "# найдем время начала и окончания сессии\n", "time_df['min'] = train_df[times].min(axis=1)\n", "time_df['max'] = train_df[times].max(axis=1)\n", "\n", "# вычислим длительность сессии и переведем в секунды\n", "time_df['seconds'] = (time_df['max'] - time_df['min']) / np.timedelta64(1, 's')\n", "\n", "#time_df.head()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# наша целевая переменная\n", "\n", "train_df.rename(columns={'target': 'class'}, inplace=True)\n", "y_train = train_df['class']\n", "\n", "\n", "# объединенная таблица исходных данных\n", "full_df = pd.concat([train_df.drop('class', axis=1), test_df])\n", "\n", "# индекс, по которому будем отделять обучающую выборку от тестовой\n", "idx_split = train_df.shape[0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# табличка с индексами посещенных сайтов в сессии\n", "full_sites = full_df[sites]\n", "full_sites.head()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from scipy.sparse import csr_matrix, hstack\n", "\n", "# последовательность с индексами\n", "sites_flatten = full_sites.values.flatten()\n", "\n", "# искомая матрица\n", "full_sites_sparse = csr_matrix(([1] * sites_flatten.shape[0],\n", " sites_flatten,\n", " range(0, sites_flatten.shape[0] + 10, 10)))[:, 1:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Построение модели" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from tpot import TPOTClassifier\n", "\n", "\n", "def get_tpot(X, y,seed=42, ratio = 0.9):\n", " # разделим выборку на обучающую и валидационную\n", " idx = round(X.shape[0] * ratio)\n", " # обучение классификатора\n", " tpot = TPOTClassifier(generations = 2, population_size = 3, verbosity=2,max_time_mins=3, max_eval_time_mins=0.04)\n", " tpot.fit(X[:idx, :], y[:idx])\n", " \n", " return tpot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "# выделим из объединенной выборки только обучающую (для которой есть ответы)\n", "X_train = full_sites_sparse[:idx_split, :]\n", "\n", "tpot = get_tpot(X_train, y_train)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# функция для записи прогнозов в файл\n", "def write_to_submission_file(predicted_labels, out_file,\n", " target='target', index_label=\"session_id\"):\n", " predicted_df = pd.DataFrame(predicted_labels,\n", " index = np.arange(1, predicted_labels.shape[0] + 1),\n", " columns=[target])\n", " predicted_df.to_csv(out_file, index_label=index_label)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X_test = full_sites_sparse[idx_split:,:]\n", "y_test = tpot.predict(X_test)\n", "write_to_submission_file(y_test, 'tpot_baseline.csv')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Вывод" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В результате не удалось побить даже первый бейзлайн. Score = 0.5. Возможно TPOT так работает на разреженных матрицах. В любом случае дальше нужно подбирать параметры классификатора самостоятельно, либо давать свой словарь TPOT-у (параметр config_dict)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Ссылки\n", "* [Будут ли data scientist’ы в ближайшее время заменены автоматизированными алгоритмами и искусственным интеллектом?](https://habrahabr.ru/company/npl/blog/322414/)\n", "* [Automated Machine Learning − как оно есть](http://ko.com.ua/automated_machine_learning_kak_ono_est_116151)\n", "* [ML Wiki](http://www.machinelearning.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%28%D0%BA%D1%83%D1%80%D1%81_%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B9%2C_%D0%9A.%D0%92.%D0%92%D0%BE%D1%80%D0%BE%D0%BD%D1%86%D0%BE%D0%B2%29)\n", "* [TPOT Github](http://rhiever.github.io/tpot/)" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.1" } }, "nbformat": 4, "nbformat_minor": 2 }