- PVSM.RU - https://www.pvsm.ru -

Обучение на больших данных: Spark MLlib

Привет!

image

В прошлый раз [1] мы познакомились с инструментом Apache Spark, который в последнее время становится чуть ли не самым популярным средством для обработки больших данных и в частности, Large Scale Machine Learning. Сегодня мы рассмотрим подробнее библиотеку MlLib, а именно — покажем, как решать задачи машинного обучения — классификации, регресии, кластеризации, а также коллаборативной фильтрации. Кроме этого покажем, как можно исследовать признаки с целью отбора и выделения новых (т.н. Feature Engineering, о котором мы говорили ранее [2], причем не один раз [3]).

План

Прежде всего посмотрим, как хранить объекты нашей обучающей выборки, как считать базовые статистики признаков, после чего — алгоритмы машинного обучения (классификация, регрессия, кластеризация) и наконец, рассмотрим пример построения рекомендательной системы — т.н. методы коллаборативной фильтрации, а если быть точнее — один из самых распространенных алгоритмов ALS.

Вектора

Для простых «плотных» векторов есть специальный класс Vectors.dense:

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:

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:

from pyspark.mllib.regression import LabeledPoint
my_point = LabeledPoint(1.0, my_vec)

Где в классе LabeledPoint мы имеем LabeledPoint.features — любой из описанных выше векторов, а LabeledPoint.label — это, соответственно, метка, которая может принимать любое действительное значение в случае задачи регрессии и значения [0.0,1.0,2.0,...] — для задач классификации

Работа с признаками

Не секрет, что зачастую, чтобы построить хороший алгоритм машинного обучения, достаточно просто посмотреть на признаки, отобрать из наиболее релевантные или придумать новые. Для этой цели в спарке класс Statistics, с помощью которого можно делать все эти вещи, например:

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:

from pyspark.mllib.feature import StandardScaler
scaler = StandardScaler(withMean=True, withStd=True).fit(features)
scaler.transform (features.map(lambda x:x.toArray()))

Единственное, что важно помнить — в случае разреженных векторов это не работает и стратегию масштабирования надо продумывать под конкретную задачу. Теперь перейдем непосредственно к задачам машинного обучения.

Классификация и регрессия

Линейные методы

Самыми распространенными методами как всегда [4] являются линейные классификаторы. Обучение линейного классификатора сводится к задаче выпуклой минимизации функционала от вектора весов. Различие заключается в выборе функции потерь, функции регуляризации, количества итераций и множества других параметров. Для примера, рассмотрим ниже логистическую функцию потерь (и, соответственно, т.н. метод логистической регрессии), 500 итераций и L2 — регуляризацию.

import pyspark.mllib.classification as cls
model = cls.LogisticRegressionWithSGD.train(train, iterations=500, regType="l2")

Аналогично делается и линейная регрессия:

import pyspark.mllib.regression as regr
model = regr.RidgeRegressionWithSGD.train(train)

Наивный Байес

В этом случае, алгоритм обучения принимает на вход всего 2 параметра — саму обучающую выборку и параметр сглаживания:

from pyspark.mllib.classification import NaiveBayes
model = NaiveBayes.train(train, 8.5)
model.predict(test.features)

Решающие деревья

В спарке, как и во многих других пакетах, реализованы деревья регрессии и классификации. Алгоритм обучения принимает на вход множество параметров, такие, как множество классов, максимальная глубина дерева. Также алгоритму необходимо указать, какие категории имеют категориальные признаки, а также множество других параметров. Однако одним из самых важных из них при обучении деревьев является так называемый impurity — критерий вычисления так называемой information gain, который обычно может принимать следующие значения: entropy и gini — для задач классификации, variance — для задач регрессии. Для примера рассмотрим бинарную классификацию с параметрами, определенными ниже:

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 деревьев:

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))

Кластеризация

Как и везде, в спарке реализован всем известный алгоритм KMeans, обучение которого принимает на вход непосредственно датасет, число кластеров, число итераций, а также стратегию выбора начальных центров кластеров (параметр initializationMode, который по умолчанию имеет значение k-means, а также может принимать значение random):

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 (который, также как и другие алгоритмы, принимает на вход множество параметров, прочитать о которых предлагается читателю самостоятельно):

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, который разрабатывался для распределенной обработки больших данных. Напомним, что основным преимуществом данного инструмента, как обсуждалось ранее [1], является то, что данные можно кэшировать в оперативной памяти, что позволяет существенно ускорять вычисления в случае итеративных алгоритмов, какими и являются большинство алгоритмов машинного обучения.

Автор: akrot

Источник [5]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/razrabotka/84133

Ссылки в тексте:

[1] прошлый раз: http://habrahabr.ru/post/250811/

[2] говорили ранее: http://habrahabr.ru/post/248129/

[3] не один раз: http://habrahabr.ru/post/249759/

[4] как всегда: http://habrahabr.ru/post/248779/

[5] Источник: http://habrahabr.ru/post/251471/