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

    Привет, хабр!

    image

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

    План


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

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

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


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


    Самыми распространенными методами как всегда являются линейные классификаторы. Обучение линейного классификатора сводится к задаче выпуклой минимизации функционала от вектора весов. Различие заключается в выборе функции потерь, функции регуляризации, количества итераций и множества других параметров. Для примера, рассмотрим ниже логистическую функцию потерь (и, соответственно, т.н. метод логистической регрессии), 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, который разрабатывался для распределенной обработки больших данных. Напомним, что основным преимуществом данного инструмента, как обсуждалось ранее, является то, что данные можно кэшировать в оперативной памяти, что позволяет существенно ускорять вычисления в случае итеративных алгоритмов, какими и являются большинство алгоритмов машинного обучения.
    Метки:
    MLClass 34,36
    Компания
    Поделиться публикацией
    Похожие публикации
    Комментарии 10
    • +1
      Полезная статья, спасибо! Возможно, буду использовать эту библиотеку в своих проектах.
      Подскажите хорошую литературу по machine learning, с которой лучше всего начать изучение области и знакомиться с теоретической базой.
      • 0
        Спасибо!
        Самое лучшее для начала — это курс Andrew Ng на coursera.org — его вполне хватит для того, чтобы начать решать прикладные задачи
        • 0
          Тоже вам бесконечно благодарен, что начали публиковать статьи по анализу данных. Радует постепенное все более глубокое углубление статей в предметную область. Не останавливайтесь.
          Добавлю пару на мой взгляд полезных курсов:
          • Очень легкий и понятный курс по мат. статистике на Udacity: Intro to Statistics. Математику последний раз учил уже давно и без него вышеупомянутый курс от Andrew Ng дался бы мне сложнее.
          • Месяц назад стартовал так же более продвинутый курс по мат. статистике на Stanford Online: Statistical Learning. Курс уже начался и вряд ли к нему еще можно подклчиться, но кому интересно могу поделиться выгруженными оттуда видеолекциями.
          • В апреле на edX начинается 4 недельный курс Introduction to Big Data with Apache Spark. Может тоже кому интересно.
          • 0
            Спасибо, но это всего лишь основы — обзор инструментов, чтобы начать. И это старые материалы — те, которые у меня уже есть. Сложные вещи писать — это надо много времени, которого, к сожалению, не хватает.

            Про курсы — рекомендую больше все-таки решать прикладных задач. Как правило, большинство хороших алгоритмов — это что-то простое + много эвристик, которым можно научиться исключительно на практике
    • 0
      Про градиент бустинг забыли. Он в новом релизе уже есть.
      • 0
        Это старый мануал) А еще в версии 1.3 появятся DataFrame — вот это будет круто!)
        • 0
          В 1.3 уже Pipeline будут во всю. Вот то заживем. А мы уже переехали на 1.3 самособранную
          • 0
            >А мы уже переехали на 1.3 самособранную
            А можно подробнее? Можно в скайп или еще где, например

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое