Рассмотрим библиотеку MlLib в Spark и покажем, как решать задачи машинного обучения — классификации, регресии, кластеризации, а также коллаборативной фильтрации. Кроме этого покажем, как можно исследовать признаки с целью отбора и выделения новых (т.н. Feature Engineering).
Вектора
Для простых «плотных» векторов есть специальный класс Vectors.dense:
1 2 |
from pyspark.mllib.linalg import Vectors my_vec = Vectors.dence ([1.12, 4.10, 1.5, -2.7, 3.5, 10.7, 0.7]) |
Для «разреженных» векторов используется класс Vectors.sparse:
1 2 |
from pyspark.mllib.linalg import Vectors my_vec = Vectors.sparse(10, [0,2,4,9], [-1.2, 3.05, -4.08, 0.46]) |
Здесь первым аргументом является количество признаков (длина вектора), далее идут списком — номера ненулевых признаков, и после — сами значения признаков.
Размеченные вектора
Для размеченных точек в Spark есть специальный класс LabeledPoint:
1 2 |
from pyspark.mllib.regression import LabeledPoint my_point = LabeledPoint(1.0, my_vec) |
Где в классе LabeledPoint мы имеем LabeledPoint.features — любой из описанных выше векторов, а LabeledPoint.label — это, соответственно, метка, которая может принимать любое действительное значение в случае задачи регрессии и значения [0.0,1.0,2.0,…] — для задач классификации
Работа с признаками
Не секрет, что зачастую, чтобы построить хороший алгоритм машинного обучения, достаточно просто посмотреть на признаки, отобрать из наиболее релевантные или придумать новые. Для этой цели в Spark есть класс Statistics, с помощью которого можно делать все эти вещи, например:
1 2 3 4 5 6 7 8 9 10 11 |
from pyspark.mllib.stat import Statistics summary = Statistics.colStats(features) # meas of features summary.mean # non zeros features summary.numNonzeros # variance summary.variance # correlations of features Statistics.corr(features) |
Помимо этого, в Spark есть огромное количество дополнительных возможностей вроде сэмплирования, генерации стандартных признаков (вроде TF-IDF для текстов), а также такая важная вещь, как масштабирование признаков. Для последнего есть специальный класс Scaler:
1 2 3 |
from pyspark.mllib.feature import StandardScaler scaler = StandardScaler(withMean=True, withStd=True).fit(features) scaler.transform (features.map(lambda x:x.toArray())) |
Единственное, что важно помнить — в случае разреженных векторов это не работает и стратегию масштабирования надо продумывать под конкретную задачу. Теперь перейдем непосредственно к задачам машинного обучения.
Классификация и регрессия
Линейные методы
Самыми распространенными методами как всегда являются линейные классификаторы. Обучение линейного классификатора сводится к задаче выпуклой минимизации функционала от вектора весов. Различие заключается в выборе функции потерь, функции регуляризации, количества итераций и множества других параметров. Для примера, рассмотрим ниже логистическую функцию потерь (и, соответственно, т.н. метод логистической регрессии), 500 итераций и L2 — регуляризацию.
1 2 |
import pyspark.mllib.classification as cls model = cls.LogisticRegressionWithSGD.train(train, iterations=500, regType="l2") |
Аналогично делается и линейная регрессия:
1 2 |
import pyspark.mllib.regression as regr model = regr.RidgeRegressionWithSGD.train(train) |
Наивный Байес
В этом случае, алгоритм обучения принимает на вход всего 2 параметра — саму обучающую выборку и параметр сглаживания:
1 2 3 |
from pyspark.mllib.classification import NaiveBayes model = NaiveBayes.train(train, 8.5) model.predict(test.features) |
Решающие деревья
В Spark, как и во многих других пакетах, реализованы деревья регрессии и классификации. Алгоритм обучения принимает на вход множество параметров, такие, как множество классов, максимальная глубина дерева. Также алгоритму необходимо указать, какие категории имеют категориальные признаки, а также множество других параметров. Однако одним из самых важных из них при обучении деревьев является так называемый impurity — критерий вычисления так называемой information gain, который обычно может принимать следующие значения: entropy и gini — для задач классификации, variance — для задач регрессии. Для примера рассмотрим бинарную классификацию с параметрами, определенными ниже:
1 2 3 |
from pyspark.mllib.tree import DecisionTree model = DecisionTree.trainClassifier(train, numClasses=2, impurity='gini', maxDepth=5) model.predict(test.map(lambda x: x.features)) |
Random Forest
Случайные леса, как известно, является одними из универсальных алгоритмов и следовало ожидать, что в этом инструменте они будут реализованы. Используют они деревья, описанные выше. Здесь точно также есть методы trainClassifier и trainRegression — для обучения классификатора и функции регрессии соответственно. Одними из самых важных параметров являются — количество деревьев в лесу, уже известный нам impurity, а также featureSubsetStrategy — количество признаков, которые рассматриваются при разбиении на очередном узле дерева (подробнее о значениях — см. документацию). Соответственно, ниже пример бинарной классификации с помощью 50 деревьев:
1 2 3 |
from pyspark.mllib.tree import RandomForest model = RandomForest.trainClassifier(train, numClasses=2, numTrees=50, featureSubsetStrategy="auto", impurity='gini', maxDepth=20, seed=12) model.predict(test.map(lambda x:x.features)) |
Кластеризация
Как и везде, в Spark реализован всем известный алгоритм KMeans, обучение которого принимает на вход непосредственно датасет, число кластеров, число итераций, а также стратегию выбора начальных центров кластеров (параметр initializationMode, который по умолчанию имеет значение k-means, а также может принимать значение random):
1 2 3 |
from pyspark.mllib.clustering import KMeans clusters = KMeans.train(features, 3, maxIterations=100, runs=5, initializationMode="random") clusters.predict(x.features)) |
Коллаборативная фильтрация
Учитывая, что самый известный пример применения Больших Данных — это рекомендательная система, было бы странным, если бы самые простейшие алгоритмы не были реализованы во многих пакетах. Это касается и Spark’а. В нем реализован алгоритм ALS (Alternative Least Square) — пожалуй, один из самых известных алгоритмов коллаборативной фильтрации. Алгоритм фактически занимается разложением матрицы отзывов (строки которой — это пользователи, а столбцы — продукты) — на матрицы продукт — топик и топик-пользователь, где топики — это некоторые скрытые переменные, смысл которых зачастую не понятен (вся прелесть алгоритма ALS как раз в том, чтобы сами топики и их значения найти). Суть этих топиков в том, что каждый пользователь и каждый фильм теперь характеризуются набором признаков, а скалярное произведение этих векторов — это и есть оценка фильма конкретного пользователя. Обучающая выборка для этого алгоритма задается в виде таблицы userID -> productID -> rating. После чего делается обучение модели с помощью ALS (который, также как и другие алгоритмы, принимает на вход множество параметров):
1 2 3 |
from pyspark.mllib.recommendation import ALS model = ALS.train (ratings, 20, 60) predictions = model.predictAll(ratings.map (lambda x: (x[0],x[1]))) |
Итак, мы кратко рассмотрели библиотеку MlLib из фреймворка Apache Spark, который разрабатывался для распределенной обработки больших данных. Основным преимуществом данного инструмента является то, что данные можно кэшировать в оперативной памяти, что позволяет существенно ускорять вычисления в случае итеративных алгоритмов, какими и являются большинство алгоритмов машинного обучения.