Что такое Scikit Learn - гайд по популярной библиотеке Python для начинающих
Scikit-learn - один из наиболее широко используемых пакетов Python для Data Science и Machine Learning. Он позволяет выполнять множество операций и предоставляет множество алгоритмов. Scikit-learn также предлагает отличную документацию о своих классах, методах и функциях, а также описание используемых алгоритмов.
Scikit-Learn поддерживает:
- предварительную обработку данных;
- уменьшение размерности;
- выбор модели;
- регрессии;
- классификации;
- кластерный анализ.
Он также предоставляет несколько наборов данных, которые вы можете использовать для тестирования ваших моделей.
Scikit-learn не реализует все, что связано с машинным обучением. Например, он не имеет комплексной поддержки для:
- нейронных сетей;
- самоорганизующихся карт (сетей Кохонена);
- обучения ассоциативным правилам;
- обучения с подкреплением (reinforcement learning).
Scikit-learn основан на NumPy и SciPy, поэтому необходимо понять хотя бы азы этих двух библиотек, чтобы эффективно применять Scikit-learn.
Scikit-learn - это пакет с открытым исходным кодом. Как и большинство материалов из экосистемы Python, он бесплатный даже для коммерческого использования. Он лицензирован под лицензией BSD.
В этой статье кратко представим некоторые возможности scikit-learn.
Предварительная обработка данных
Вы можете использовать scikit-learn для подготовки ваших данных к алгоритмам машинного обучения: стандартизации или нормализации данных, кодирования категориальных переменных и многое другое.
Давайте сначала определим массив NumPy, с которым будем работать:
>>> import numpy as np
>>> x = np.array([[0.1, 1.0, 22.8],
... [0.5, 5.0, 41.2],
... [1.2, 12.0, 2.8],
... [0.8, 8.0, 14.0]])
>>> x
array([[ 0.1, 1. , 22.8],
[ 0.5, 5. , 41.2],
[ 1.2, 12. , 2.8],
[ 0.8, 8. , 14. ]])
Вам часто нужно преобразовывать данные таким образом, чтобы среднее значение каждого столбца (элемента) было равно нулю, а стандартное отклонение - единице. В этом случае, можно использовать sklearn.preprocessing.StandardScaler:
>>> from sklearn.preprocessing import StandardScaler
>>> scaler = StandardScaler()
>>> scaled_x = scaler.fit_transform(x)
>>> scaler.scale_
array([ 0.40311289, 4.03112887, 14.04421589])
>>> scaler.mean_
array([ 0.65, 6.5 , 20.2 ])
>>> scaler.var_
array([1.6250e-01, 1.6250e+01, 1.9724e+02])
>>> scaled_x
array([[-1.36438208, -1.36438208, 0.18512959],
[-0.3721042 , -0.3721042 , 1.4952775 ],
[ 1.36438208, 1.36438208, -1.23894421],
[ 0.3721042 , 0.3721042 , -0.44146288]])
>>> scaled_x.mean().round(decimals=4)
0.0
>>> scaled_x.mean(axis=0)
array([ 1.66533454e-16, -1.38777878e-17, 1.52655666e-16])
>>> scaled_x.std(axis=0)
array([1., 1., 1.])
>>> scaler.inverse_transform(scaled_x)
array([[ 0.1, 1. , 22.8],
[ 0.5, 5. , 41.2],
[ 1.2, 12. , 2.8],
[ 0.8, 8. , 14. ]])
Бывает, что у вас есть некоторые категориальные данные, и вам нужно преобразовать их в числа. Один из способов сделать это - использовать класс sklearn.preprocessing.OneHotEncoder. Рассмотрим следующий пример с массивами ролей в компании:
>>> from sklearn.preprocessing import OneHotEncoder
>>> roles = np.array([('Tom', 'manager'),
... ('Mary', 'developer'),
... ('Ann', 'recruiter'),
... ('Jim', 'developer')])
>>> roles
array([['Tom', 'manager'],
['Mary', 'developer'],
['Ann', 'recruiter'],
['Jim', 'developer']], dtype='<u9')>>> encoder = OneHotEncoder()
>>> encoded_roles = encoder.fit_transform(roles[:, [1]])
>>> encoded_roles.toarray()
array([[0., 1., 0.],
[1., 0., 0.],
[0., 0., 1.],
[1., 0., 0.]])</u9')>
В приведенном выше примере первый столбец объекта encoded_roles указывает, является ли каждый сотрудник разработчиком. Второй и четвертый сотрудник (Мэри и Джим) - разработчики. Второй столбец связан с должностью менеджера. Только первый сотрудник (Том) имеет эту должность. Наконец, третий столбец соответствует должности рекрутера, и им является третий сотрудник (Энн).
Уменьшение размерности
Уменьшение размерности включает в себя выбор или извлечение наиболее важных компонентов (признаков) многомерного набора данных. Scikit-learn предлагает несколько подходов к уменьшению размерности. Одним из них является анализ основных компонентов (PCA).
Выбор модели
Для обучения и тестирования моделей машинного обучения, вам необходимо случайным образом разбивать данные на подмножества. Это включает как входы, так и их соответствующие выходы. Функция sklearn.model_selection.train_test_split () полезна в таких случаях:
>>> import numpy as np
>>> from sklearn.model_selection import train_test_split
>>> x, y = np.arange(1, 21).reshape(-1, 2), np.arange(3, 40, 4)
>>> x
array([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10],
[11, 12],
[13, 14],
[15, 16],
[17, 18],
[19, 20]])
>>> y
array([ 3, 7, 11, 15, 19, 23, 27, 31, 35, 39])
>>> x_train, x_test, y_train, y_test =\
... train_test_split(x, y, test_size=0.4, random_state=0)
>>> x_train
array([[ 3, 4],
[13, 14],
[15, 16],
[ 7, 8],
[ 1, 2],
[11, 12]])
>>> y_train
array([ 7, 27, 31, 15, 3, 23])
>>> x_test
array([[ 5, 6],
[17, 18],
[ 9, 10],
[19, 20]])
>>> y_test
array([11, 35, 19, 39])
В дополнение к обычному разделению наборов данных, scikit-learn предоставляет средства для осуществления перекрестной проверки, настройки гиперпараметров ваших моделей с помощью поиска по сетке, вычисления многих величин, которые показывают производительность модели (например, коэффициент детерминации, среднеквадратичная ошибка, показатель отклонения с пояснением, матрица ошибок, отчет о классификации, f-показатели и многое другое).
Набор данных
Scikit-learn предоставляет несколько наборов данных, подходящих для изучения и тестирования ваших моделей. В основном, это известные наборы данных. Они представляют собой достаточный объем данных для тестирования моделей и в то же время не очень большой, что обеспечивает приемлемую продолжительность обучения.
Например, функция sklearn.datasets.load_boston () отображает данные о ценах на дома в районе Бостона (цены не обновляются!). Есть 506 наблюдений, а входная матрица имеет 13 столбцов (признаков):
>>> from sklearn.datasets import load_boston
>>> x, y = load_boston(return_X_y=True)
>>> x.shape, y.shape
((506, 13), (506,))
Этот набор данных подходит для многовариантной регрессии.
Другой пример - набор данных, связанный с вином. Его можно получить с помощью функции sklearn.datasets.load_wine ():
>>> from sklearn.datasets import load_wine
>>> x, y = load_wine(return_X_y=True)
>>> x.shape, y.shape
((178, 13), (178,))
>>> np.unique(y)
array([0, 1, 2])
Этот набор данных подходит для классификации. Он содержит 13 функций, связанных с тремя различными винодельческими компаниями из Италии, и 178 наблюдений.
Регрессия
Scikit-learn поддерживает различные методы регрессии начиная с линейной регрессии, метода k-ближайших соседей посредством полиномиальной регрессии, регрессии опорных векторов, деревьев принятия решений и т.д., до ансамбля методов, таких как random forest и градиентный бустинг. Он также поддерживает нейронные сети, но не в такой степени, как специализированные библиотеки, например, как TensorFlow.
Ниже покажем регрессию random forest.
Обычно мы начинаем наше регрессионное путешествие с импорта необходимых нам пакетов, классов и функций:
>>> import numpy as np
>>> from sklearn.datasets import load_boston
>>> from sklearn.ensemble import RandomForestRegressor
>>> from sklearn.model_selection import train_test_split
Следующим шагом является получение данных для работы и разделение этих данных на обучающее и тестовое подмножества. Мы будем использовать набор данных Бостона:
>>> x, y = load_boston(return_X_y=True)
>>> x_train, x_test, y_train, y_test =\
... train_test_split(x, y, test_size=0.33, random_state=0)
Некоторые методы требуют масштабирования (стандартизации) данных, в то время как для других методов это необязательно. На этот раз мы продолжим без масштабирования.
Теперь нам нужно создать наш регрессор и обучить его с помощью подмножества данных, выбранного для обучения:
>>> regressor = RandomForestRegressor(n_estimators=10, random_state=0)
>>> regressor.fit(x_train, y_train)
RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,
max_features='auto', max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=10,
n_jobs=None, oob_score=False, random_state=0, verbose=0,
warm_start=False)
После того, как модель обучена, мы проверяем коэффициент детерминации на обучающем подмножестве данных и, что более важно, на тестовом подмножестве данных, который не использовался при обучении моделей.
>>> regressor.score(x_train, y_train)
0.9680930547240916
>>> regressor.score(x_test, y_test)
0.8219576562705848
Модель, обученная достаточно хорошо, может использоваться для прогнозирования выходных данных при других новых входных данных x_new. В данном случае, используется команда .predict(): regressor.predict(x_new).
Классификация
Scikit-learn выполняет классификацию почти так же, как регрессию. Он поддерживает различные методы классификации, такие как логистическая регрессия и k-ближайшие соседи, метод опорных векторов, наивный байесовский классификатор, дерево принятия решений, а также ансамбль методов, такие как random forest, AdaBoost и градиентный бустинг.
В этой статье показано, как использовать метод random forest для классификации. Этот подход весьма аналогичен подходу, применяемому в случае регрессии. Но теперь мы будем использовать набор данных, связанных с вином, определять классификатор и оценивать его с точностью классификации вместо коэффициента детерминации.
>>> import numpy as np
>>> from sklearn.datasets import load_wine
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.model_selection import train_test_split
>>> x, y = load_wine(return_X_y=True)
>>> x_train, x_test, y_train, y_test =\
... train_test_split(x, y, test_size=0.33, random_state=0)
>>> classifier = RandomForestClassifier(n_estimators=10, random_state=0)
>>> classifier.fit(x_train, y_train)
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
max_depth=None, max_features='auto', max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=10,
n_jobs=None, oob_score=False, random_state=0, verbose=0,
warm_start=False)
>>> classifier.score(x_train, y_train)
1.0
>>> classifier.score(x_test, y_test)
1.0
Модель, обученная достаточно хорошо, может использоваться для прогнозирования выходных данных при других новых входных данных. В данном случае, используется команда .predict(): regressor.predict(x_new).
Кластерный анализ
Кластеризация - это ветвь неконтролируемого обучения, широко поддерживаемая в scikit-learn. В дополнение к методу k-средних, есть возможность применять метод распространения близости, спектральную кластеризацию, агломеративную кластеризацию и т.д.
В этой статье мы покажем метод k-средних. При его реализации, будьте внимательны, имеет ли смысл стандартизировать или нормализовать ваши данные и особенно, какая мера расстояния подходит (в большинстве случаев, это евклидово расстояние).
Опять же, мы начинаем с импорта и получения данных. На этот раз мы возьмем NumPy и sklearn.cluster.KMeans:
>>> import numpy as np
>>> from sklearn.cluster import KMeans
>>> x = np.array([(0.0, 0.0),
... (9.9, 8.1),
... (-1.0, 1.0),
... (7.1, 5.6),
... (-5.0, -5.5),
... (8.0, 9.8),
... (0.5, 0.5)])
>>> x
array([[ 0. , 0. ],
[ 9.9, 8.1],
[-1. , 1. ],
[ 7.1, 5.6],
[-5. , -5.5],
[ 8. , 9.8],
[ 0.5, 0.5]])
Следующим шагом является масштабирование данных, но это не всегда обязательно. Однако во многих случаях это действительно хорошая идея. Как только предварительная обработка данных завершена, мы создаем копию KMeans и подгоняем ее под наши данные:
>>> cluster_analyzer = KMeans(n_clusters=3, init='k-means++')
>>> cluster_analyzer.fit()
>>> cluster_analyzer.fit(x)
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
n_clusters=3, n_init=10, n_jobs=None, precompute_distances='auto',
random_state=None, tol=0.0001, verbose=0)
Итак, мы готовы получить результаты, такие как координаты центров кластеров и метки кластеров, которым принадлежит каждое наблюдение:
>>> cluster_analyzer.cluster_centers_
array([[ 8.33333333, 7.83333333],
[-0.16666667, 0.5 ],
[-5. , -5.5 ]])
>>> cluster_analyzer.labels_
array([1, 0, 1, 0, 2, 0, 1], dtype=int32)
Вы можете использовать метод . predict() для получения ближайших кластеров для новых наблюдений.
Заключение
В этой статье представлены только основы Scikit-Learn, очень популярного пакета Python по data science и machine learning. Это одна из основных библиотек Python для этих целей.
Спасибо за чтение!