Наиболее распространенными инструментами Data Scientist’а на сегодняшний день являются R и Python. У каждого инструмента есть свои плюсы и минусы, но неплохую позицию по всем параметрам занимает Python. Для Питона есть отлично документированная библиотека Scikit-Learn, в которой реализовано большое количество алгоритмов машинного обучения.
Здесь мы остановимся на алгоритмах Machine Learning. Первичный анализ данных лучше обычно проводится средствами пакета Pandas, разобраться с которым можно самостоятельно. Итак, сосредоточимся на реализации, для определенности полагая, что на входе у нас есть матрица обьект-признак, хранящаяюся в файле с расширением *.csv
Загрузка данных
В первую очередь данные необходимо загрузить в оперативную память, чтобы мы имели возможность работать с ними. Сама библиотека Scikit-Learn использует в своей реализации NumPy массивы, поэтому будем загружать *.csv файлы средствами NumPy. Загрузим один из датасетов из репозитория UCI Machine Learning Repository:
1 2 3 4 5 6 7 8 9 10 11 |
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 уже есть готовые для этого функции:
1 2 3 4 5 |
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. В то время как Feature Engineering довольно творческий процесс и полагается больше на интуицию и экспертные знания, для Feature Selection есть уже большое количество готовых алгоритмов. «Древесные» алгоритмы допускают расчёта информативности признаков:
1 2 3 4 5 6 |
from sklearn import metrics from sklearn.ensemble import ExtraTreesClassifier model = ExtraTreesClassifier() model.fit(X, y) # display the relative importance of each attribute print(model.feature_importances_) |
Все остальные методы так или иначе основаны на эффективном переборе подмножеств признаков с целью найти наилучшее подмножество, на которых построенная модель даёт наилучшее качество. Одним из таких алгоритмов перебора является Recursive Feature Elimination алгоритм, который также доступен в библиотеке Scikit-Learn:
1 2 3 4 5 6 7 8 9 |
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 метод). Достоинством этого алгоритма является то, что на выходе для каждого объекта мы имеем вероятность принадлежности классу
1 2 3 4 5 6 7 8 9 10 11 |
from sklearn import metrics from sklearn.linear_model import LogisticRegression model = LogisticRegression() 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)) |
Наивный Байес
Также является одним из самых известных алгоритмов машинного обучения, основной задачей которого является восстановление плотностей распределения данных обучающей выборки. Зачастую этот метод дает хорошее качество в задачах именно многоклассовой классификации.
1 2 3 4 5 6 7 8 9 10 11 |
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 Neighbors) часто используется как составная часть более сложного алгоритма классификации. Например, его оценку можно использовать как признак для объекта. А иногда, простой kNN на хорошо подобранных признаках даёт отличное качество. При грамотной настройке параметров (в основном — метрики) алгоритм даёт зачастую хорошее качество в задачах регрессии
1 2 3 4 5 6 7 8 9 10 11 12 |
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) часто используются в задачах, в которых объекты имеют категориальные признаки и используется для задач регрессии и классификации. Очень хорошо деревья подходят для многоклассовой классификации
1 2 3 4 5 6 7 8 9 10 11 12 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 |
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 уже есть немало реализованных для этого функций
Для примера посмотрим на подбор параметра регуляризации, в котором мы по очереди перебирают несколько значений:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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) |
Иногда более эффективным оказывается много раз выбрать случайно параметр из данного отрезка, померить качество алгоритма при данном параметре и выбрать тем самым лучший:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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 за исключением вывода результатов обратно в файл.
Дополнительно загляните в статью Топ-10 data mining алгоритмов, в которых более подробно и понятно можно посмотреть принцип работы некоторых алгоритмов и посмотреть их реализацию как в Python, так и в R.