[Из песочницы] Введение в машинное обучение с помощью Python и Scikit-Learn
Привет, хабр!
Меня зовут Александр, я занимаюсь машинным обучением и анализом веб-графов (в основном — теоретическим), а также разработкой Big Data продуктов в одном из операторов Большой Тройки. Это мой первый пост — прошу, не судите строго!)
В последнее время ко мне все чаще стали обращаться люди, которые хотят научиться разрабатывать эффективные алгоритмы и участвовать в соревнованиях по машинному обучению с вопросом: «С чего начать?». Некоторое время назад я руководил разработкой инструментов Big Data для анализа медиа и социальных сетей в одном из учреждений Правительства РФ, и у меня остался некоторый материал, по которому обучалась моя команда и которым можно поделиться. Предполагается, что у читателя есть хорошее знание математики и машинного обучения (в команде были в основном выпускники МФТИ и студенты Школы Анализа Данных).По-сути это было введение в Data Science. В последнее время эта наука стала довольно популярна. Все чаще проводятся соревнования по машинному обучению (например, Kaggle, TudedIT), зачастую с немалым бюджетом. Целью данной статьи является дать читателю быстрое введение инструменты машинного обучения, чтобы он мог как можно скорее участвовать в соревнованиях.
Наиболее распространенными инструментами Data Scientist’а на сегодняшний день являются R и Python. У каждого инструмента есть свои плюсы и минусы, однако, в последнее время по всем параметрам выигрывает Python (это исключительно мнение автора, к тому же пользующегося одновременно и тем и другим). Это стало после того, как появилась отлично документированная библиотека Scikit-Learn, в которой реализовано большое количество алгоритмов машинного обучения.
Сразу отметим, что в статье мы остановимся именно на алгоритмах Machine Learning. Первичный анализ данных лучше обычно проводится средствами пакета Pandas, разобраться с которым можно самостоятельно. Итак, сосредоточимся на реализации, для определенности полагая, что на входе у нас есть матрица обьект-признак, хранящаяюся в файле с расширением *.csv
Загрузка данныхВ первую очередь данные необходимо загрузить в оперативную память, чтобы мы имели возможность работать с ними. Сама библиотека Scikit-Learn использует в своей реализации NumPy массивы, поэтому будем загружать *.csv файлы средствами NumPy. Загрузим один из датасетов из репозитория UCI Machine Learning Repository: import numpy as np import urllib # url with dataset url = «http://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data» # download the file raw_data = urllib.urlopen (url) # load the CSV file as a numpy matrix dataset = np.loadtxt (raw_data, delimiter=»,») # separate the data from the target attributes X = dataset[:,0:7] y = dataset[:,8] Далее во всех примерах будем работать с этим набором данных, а именно с матрицей обьект-признак X и значениями целевой переменной y.Нормализация данных Всем хорошо знакомо, что большинство градиентных методов (на которых по-сути и основаны почти все алгоритмы машинного обучения) сильно чуствительны к шкалированию данных. Поэтому перед запуском алгоритмов чаще всего делается либо нормализация, либо так называемая стандартизация. Нормализация предполагает замену номинальных признаков так, чтобы каждый из них лежал в диапазоне от 0 до 1. Стандартизация же подразумевает такую предобработку данных, после которой каждый признак имеет среднее 0 и дисперсию 1. В Scikit-Learn уже есть готовые для этого функции: from sklearn import preprocessing # normalize the data attributes normalized_X = preprocessing.normalize (X) # standardize the data attributes standardized_X = preprocessing.scale (X) Отбор признаков Не секрет, что зачастую самым важным при решении задачи является умение правильно отобрать и даже создать признаки. В англоязычной литературе это называется Feature Selection и Feature Engineering. В то время как Future Engineering довольно творческий процесс и полагается больше на интуицию и экспертные знания, для Feature Selection есть уже большое количество готовых алгоритмов. Обычно, самое простое — это посмотреть значимост признаков в построеной модели: from sklearn import metrics from sklearn.linear_model import LogisticRegression model = LogisticRegression () model.fit (X, y) # display the relative importance of each attribute print (model.feature_importances_) Все остальные методы так или иначе основаны на эффективном переборе подмножеств признаков с целью найти наилучшее подмножество, на которых построенная модель дает наилучшее качество. Одним из таких алгоритмов перебора является Recursive Feature Elimination алгоритм, который также доступен в библиотеке Scikit-Learn: from sklearn.feature_selection import RFE from sklearn.linear_model import LogisticRegression model = LogisticRegression () # create the RFE model and select 3 attributes rfe = RFE (model, 3) rfe = rfe.fit (X, y) # summarize the selection of the attributes print (rfe.support_) print (rfe.ranking_) Построение алгоритма Как уже было отмечено, в Scikit-Learn реализованы все основные алгоритмы машинного обучения. Рассмотрим основные из них.Логистическая регрессия Чаще всего используется для решения задач классификации (бинарной), но допускается и многоклассовая классификация (так нызываемый one-vs-all метод). Достоинством этого алгоритма являеся то, что на выходе для каждого обьекта мы имеем вероятсность принадлежности классу from sklearn import metrics from sklearn.linear_model import LogisticRegression model = LogisticRegression () model.fit (dataset.data, dataset.target) print (model) # make predictions expected = y predicted = model.predict (X) # summarize the fit of the model print (metrics.classification_report (expected, predicted)) print (metrics.confusion_matrix (expected, predicted)) Наивный Байес Также является одним из самых известных алгоритмов машинного обучения, основной задачей которого является восстановление плотностей распределения данных обучающей выборки. Зачастую этот метод дает хорошее качество в задачах именно многоклассовой классификации. from sklearn import metrics from sklearn.naive_bayes import GaussianNB model = GaussianNB () model.fit (X, y) print (model) # make predictions expected = y predicted = model.predict (X) # summarize the fit of the model print (metrics.classification_report (expected, predicted)) print (metrics.confusion_matrix (expected, predicted)) K-ближайших соседей Метод kNN (k-Nearest Neighbor) часто используется как составная часть более сложного алгоритма классификации. Например, его оценку можно использвать как признак для обьекта. А иногда, простой kNN на хорошо подобранных признаках дает отличное качество. При грамотной настройке параметров (в основном — метрики) алгоритм дает зачастую хорошее качество в задачах регрессии from sklearn import metrics from sklearn.neighbors import KneighborsClassifier # fit a k-nearest neighbor model to the data model = KNeighborsClassifier () model.fit (X, y) print (model) # make predictions expected = y predicted = model.predict (X) # summarize the fit of the model print (metrics.classification_report (expected, predicted)) print (metrics.confusion_matrix (expected, predicted)) Деревья решений Classification and Regression Trees (CART) часто используются в задачах, в которых обьекты имеют категориальные признаки и используется для задач регресии и классификации. Очень хорошо деревья подходят для многоклассовой классификации from sklearn import metrics from sklearn.tree import DecisionTreeClassifier # fit a CART model to the data model = DecisionTreeClassifier () model.fit (X, y) print (model) # make predictions expected = y predicted = model.predict (X) # summarize the fit of the model print (metrics.classification_report (expected, predicted)) print (metrics.confusion_matrix (expected, predicted)) Метод опорных векторов SVM (Support Vector Machines) является одним из самых известных алгоритмов машинного обучения, применяемых в основном для задачи классификации. Также как и логистическая регрессия, SVM допускает многоклассовую классификацию методом one-vs-all. from sklearn import metrics from sklearn.svm import SVC # fit a SVM model to the data model = SVC () model.fit (X, y) print (model) # make predictions expected = y predicted = model.predict (X) # summarize the fit of the model print (metrics.classification_report (expected, predicted)) print (metrics.confusion_matrix (expected, predicted)) Помимо алгоритмов классификации и регрессии, в Scikit-Learn имеется огромное количество более сложных алгоритмов, в том числе кластеризации, а также реализованные техники построения композиций алгоритмов, в том числе Bagging и Boosting.Оптимизация параметров алгоритма Одним из самых сложных этапов в построении действительно эффективных алгоритмов является выбор правильных параметров. Обычно, это делается легче с опытом, но так или иначе приходится делать перебор. К счастью, в Scikit-Learn уже есть немало реализованных для этого функцийДля примера посмотрим на подбор параметра регуляризации, в котором мы по очередь перебираем несколько значений:
import numpy as np from sklearn.linear_model import Ridge from sklearn.grid_search import GridSearchCV # prepare a range of alpha values to test alphas = np.array ([1,0.1,0.01,0.001,0.0001,0]) # create and fit a ridge regression model, testing each alpha model = Ridge () grid = GridSearchCV (estimator=model, param_grid=dict (alpha=alphas)) grid.fit (X, y) print (grid) # summarize the results of the grid search print (grid.best_score_) print (grid.best_estimator_.alpha) Иногда более эффективным оказывается много раз выбрать случайно параметр из данного отрезка, померить качество алгоритма при данном параметре и выбрать тем самым луйший: import numpy as np from scipy.stats import uniform as sp_rand from sklearn.linear_model import Ridge from sklearn.grid_search import RandomizedSearchCV # prepare a uniform distribution to sample for the alpha parameter param_grid = {'alpha': sp_rand ()} # create and fit a ridge regression model, testing random alpha values model = Ridge () rsearch = RandomizedSearchCV (estimator=model, param_distributions=param_grid, n_iter=100) rsearch.fit (X, y) print (rsearch) # summarize the results of the random parameter search print (rsearch.best_score_) print (rsearch.best_estimator_.alpha) Мы рассмотрели весь процесс работы с библиотекой Scikit-Learn за исключением вывода результатов обратно в файл, что предлагается сделать читателю в качестве упражнения, потому как одним из достоинств Python (и самой библиотеки Scikit-Learn) по-сравнению с R является отличная документация. В следующих частях мы рассмотрим подробно каждый из разделов, в частности, затронем такую важную вещь как Feauture Engineering.Я очень надеюсь, что данный материал поможет начинающим Data Scientist’ам как можно скорее приступить к решению задач машинного обучения на практике. В заключение хочу пожелать успехов и терпения тем, кто только начинает участвовать в соревнованиях по машинному обучению!