В этой статье объясняются различные компоненты, необходимые для построения модели машинного обучения с использованием spark. В качестве примера мы возьмем логистическую регрессию для набора данных радужной оболочки, чтобы представить различные компоненты.
Более ранняя версия Spark ML имела дело с API на основе RDD [sharan add link], который был не очень удобен для пользователя. Начиная со Spark 2.0, API-интерфейсы на основе RDD в пакете spark.mllib перешли в режим обслуживания. Основным API машинного обучения для Spark теперь является API на основе DataFrame в пакете spark.ml. Для использования любого модуля pyspark необходимо импортировать библиотеки из pyspark.ml.
Типичное обучение модели ML включает в себя чтение данных, извлечение признаков, обучение модели и оценку. Словом искра процедура обозначена как DataFrame, Transformer, Estimator и Evaluator.
Чтение кадра данных:
Spark ML позволяет использовать различные источники данных, такие как реляционные таблицы, CSV и т. д. Например, DataFrame может иметь разные столбцы, в которых хранится текст, векторы признаков, истинные метки и прогнозы.
df = spark.read.csv('./irisdata.csv', header=True, inferSchema=True) df.printSchema() root |-- sepal_length: double (nullable = true) |-- sepal_width: double (nullable = true) |-- petal_length: double (nullable = true) |-- petal_widthCm: double (nullable = true) |-- species: string (nullable = true) df.show(5) +------------+-----------+------------+-------------+-----------+ |sepal_length|sepal_width|petal_length|petal_widthCm| species| +------------+-----------+------------+-------------+-----------+ | 5.1| 3.5| 1.4| 0.2|Iris-setosa| | 4.9| 3.0| 1.4| 0.2|Iris-setosa| | 4.7| 3.2| 1.3| 0.2|Iris-setosa| | 4.6| 3.1| 1.5| 0.2|Iris-setosa| | 5.0| 3.6| 1.4| 0.2|Iris-setosa| +------------+-----------+------------+-------------+-----------+ only showing top 5 rows
Особенности преобразования:
Преобразователь признаков преобразует данные, хранящиеся во фрейме данных, и сохраняет данные обратно в виде нового фрейма данных. Это преобразование обычно происходит путем добавления одного или нескольких столбцов к существующему фрейму данных. Его можно разбить на следующую простую последовательность DataFrame =[transform]=> DataFrame. Методы преобразования обычно выполняются на этапе подготовки и обработки наборов данных. Преобразователь является частью Spark ML и реализован в Java через базовый класс Transformer. В этом классе доступен метод .transform(), который используется для преобразования одного DataFrame в другой.
(I) Индексатор строк: StringIndexer кодирует строковый столбец меток в столбец индексов меток. StringIndexer может кодировать несколько столбцов.
from pyspark.ml.feature import StringIndexer indexer = StringIndexer(inputCol='species', outputCol='speciesIndex') iris = indexer.fit(df).transform(df) iris.sample(fraction=0.1).show() +------------+-----------+------------+-------------+---------------+------------+ |sepal_length|sepal_width|petal_length|petal_widthCm| species|speciesIndex| +------------+-----------+------------+-------------+---------------+------------+ | 4.6| 3.4| 1.4| 0.3| Iris-setosa| 0.0| | 4.4| 2.9| 1.4| 0.2| Iris-setosa| 0.0| | 5.2| 3.4| 1.4| 0.2| Iris-setosa| 0.0| | 5.0| 3.2| 1.2| 0.2| Iris-setosa| 0.0| | 5.1| 3.8| 1.6| 0.2| Iris-setosa| 0.0| | 6.7| 3.1| 4.4| 1.4|Iris-versicolor| 1.0| | 5.8| 2.7| 4.1| 1.0|Iris-versicolor| 1.0| | 5.4| 3.0| 4.5| 1.5|Iris-versicolor| 1.0| | 5.5| 2.6| 4.4| 1.2|Iris-versicolor| 1.0| | 4.9| 2.5| 4.5| 1.7| Iris-virginica| 2.0| | 6.0| 2.2| 5.0| 1.5| Iris-virginica| 2.0| +------------+-----------+------------+-------------+---------------+------------+
(II) OneHotEncoder: горячее кодирование отображает категориальный признак, представленный в виде индекса метки, в двоичный вектор с не более чем одним единичным значением, указывающим на наличие определенного значения признака из набора всех значений признака. Это кодирование позволяет алгоритмам, которые ожидают непрерывных функций, таких как логистическая регрессия, использовать категориальные функции. Для входных данных строкового типа обычно сначала кодируют категориальные признаки с помощью StringIndexer.
from pyspark.ml.feature import OneHotEncoder encoded = OneHotEncoder(inputCol="speciesIndex", outputCol="species_vec") new_df = encoded.fit(iris).transform(iris) new_df.show() +------------+-----------+------------+-------------+-----------+------------+-------------+ |sepal_length|sepal_width|petal_length|petal_widthCm| species|speciesIndex| species_vec| +------------+-----------+------------+-------------+-----------+------------+-------------+ | 5.1| 3.5| 1.4| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.9| 3.0| 1.4| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.7| 3.2| 1.3| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.6| 3.1| 1.5| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.0| 3.6| 1.4| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.4| 3.9| 1.7| 0.4|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.6| 3.4| 1.4| 0.3|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.0| 3.4| 1.5| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.4| 2.9| 1.4| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.9| 3.1| 1.5| 0.1|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.4| 3.7| 1.5| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.8| 3.4| 1.6| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.8| 3.0| 1.4| 0.1|Iris-setosa| 0.0|(2,[0],[1.0])| | 4.3| 3.0| 1.1| 0.1|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.8| 4.0| 1.2| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.7| 4.4| 1.5| 0.4|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.4| 3.9| 1.3| 0.4|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.1| 3.5| 1.4| 0.3|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.7| 3.8| 1.7| 0.3|Iris-setosa| 0.0|(2,[0],[1.0])| | 5.1| 3.8| 1.5| 0.3|Iris-setosa| 0.0|(2,[0],[1.0])| +------------+-----------+------------+-------------+-----------+------------+-------------+ only showing top 20 rows
Векторный ассемблер:
VectorAssembler — это преобразователь, который объединяет заданный список столбцов в один векторный столбец. Это полезно для объединения необработанных функций и функций, созданных различными преобразователями функций, в единый вектор функций, чтобы обучать модели ML, такие как логистическая регрессия и деревья решений. VectorAssembler принимает следующие типы входных столбцов: все числовые типы, логический тип и векторный тип. В каждой строке значения входных столбцов будут объединены в вектор в указанном порядке.
from pyspark.ml.feature import VectorAssembler assembler = VectorAssembler( inputCols=["sepal_length", "sepal_width", "petal_length", "petal_widthCm"], outputCol="features") dataset = assembler.transform(new_df) dataset.show() +------------+-----------+------------+-------------+-----------+------------+-------------+-----------------+ |sepal_length|sepal_width|petal_length|petal_widthCm| species|speciesIndex| species_vec| features| +------------+-----------+------------+-------------+-----------+------------+-------------+-----------------+ | 5.1| 3.5| 1.4| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[5.1,3.5,1.4,0.2]| | 4.9| 3.0| 1.4| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[4.9,3.0,1.4,0.2]| | 4.7| 3.2| 1.3| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[4.7,3.2,1.3,0.2]| | 4.6| 3.1| 1.5| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[4.6,3.1,1.5,0.2]| | 5.0| 3.6| 1.4| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[5.0,3.6,1.4,0.2]| | 5.4| 3.9| 1.7| 0.4|Iris-setosa| 0.0|(2,[0],[1.0])|[5.4,3.9,1.7,0.4]| | 4.6| 3.4| 1.4| 0.3|Iris-setosa| 0.0|(2,[0],[1.0])|[4.6,3.4,1.4,0.3]| | 5.0| 3.4| 1.5| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[5.0,3.4,1.5,0.2]| | 4.4| 2.9| 1.4| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[4.4,2.9,1.4,0.2]| | 4.9| 3.1| 1.5| 0.1|Iris-setosa| 0.0|(2,[0],[1.0])|[4.9,3.1,1.5,0.1]| | 5.4| 3.7| 1.5| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[5.4,3.7,1.5,0.2]| | 4.8| 3.4| 1.6| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[4.8,3.4,1.6,0.2]| | 4.8| 3.0| 1.4| 0.1|Iris-setosa| 0.0|(2,[0],[1.0])|[4.8,3.0,1.4,0.1]| | 4.3| 3.0| 1.1| 0.1|Iris-setosa| 0.0|(2,[0],[1.0])|[4.3,3.0,1.1,0.1]| | 5.8| 4.0| 1.2| 0.2|Iris-setosa| 0.0|(2,[0],[1.0])|[5.8,4.0,1.2,0.2]| | 5.7| 4.4| 1.5| 0.4|Iris-setosa| 0.0|(2,[0],[1.0])|[5.7,4.4,1.5,0.4]| | 5.4| 3.9| 1.3| 0.4|Iris-setosa| 0.0|(2,[0],[1.0])|[5.4,3.9,1.3,0.4]| | 5.1| 3.5| 1.4| 0.3|Iris-setosa| 0.0|(2,[0],[1.0])|[5.1,3.5,1.4,0.3]| | 5.7| 3.8| 1.7| 0.3|Iris-setosa| 0.0|(2,[0],[1.0])|[5.7,3.8,1.7,0.3]| | 5.1| 3.8| 1.5| 0.3|Iris-setosa| 0.0|(2,[0],[1.0])|[5.1,3.8,1.5,0.3]| +------------+-----------+------------+-------------+-----------+------------+-------------+-----------------+ only showing top 20 rows dataset.printSchema() root |-- sepal_length: double (nullable = true) |-- sepal_width: double (nullable = true) |-- petal_length: double (nullable = true) |-- petal_widthCm: double (nullable = true) |-- species: string (nullable = true) |-- speciesIndex: double (nullable = false) |-- species_vec: vector (nullable = true) |-- features: vector (nullable = true)
Оценщики:
Оценщик — это этап алгоритма обучения, который соответствует модели в наборе данных. Весь процесс можно обозначить следующим образом: DataFrame=[fit]=>Model. Оценщик выполняется на этапе построения модели с использованием существующих данных. Сама модель, которую сделает сметчик, служит преобразователем. Кроме того, оценщик доступен в Java через класс Estimator. В этом классе доступен метод .fit(), который используется для построения модели.
from pyspark.ml.classification import LogisticRegression lr = LogisticRegression(featuresCol='features', labelCol='speciesIndex') trainData, testData = dataset.randomSplit([0.7, 0.3]) model = lr.fit(trainData) summary = model.evaluate(testData)
Оценщики:
этап оценки построенной модели.
summary.accuracy 0.9361702127659575
Конвейер в Spark:
Конвейер — это серия действий или преобразований. Машинное обучение выполняется путем реализации набора задач, то есть сбора данных, очистки данных, построения модели, оценки модели и т. д. Все эти шаги необходимо выполнять один за другим в определенной последовательности. Короче говоря, конвейер можно рассматривать как серию действий, объединенных вместе для лучшего представления. Конвейеры в основном имеют четыре основных объекта: DataFrame, Transformer, Estimator и Evaluator.
#Using Pipeline #import module from pyspark.ml import Pipeline df = spark.read.csv('./irisdata.csv', header=True, inferSchema=True) #feature transformers indexer = StringIndexer(inputCol='species', outputCol='speciesIndex') #Apply OneHotEncoder to Species column encoded = OneHotEncoder(inputCol="speciesIndex", outputCol="species_vec") #Merge multiple columns into a vector column assembler = VectorAssembler( inputCols=["sepal_length", "sepal_width", "petal_length", "petal_widthCm"], outputCol="features") #model lr = LogisticRegression(featuresCol='features', labelCol='speciesIndex') #Create pipeline and pass it to stages pipeline = Pipeline(stages=[ indexer, encoded, assembler, lr ]) trainData, testData = df.randomSplit([0.7, 0.3]) #Use .fit() and .transform() on the pipeline df_transformed = pipeline.fit(trainData).transform(trainData) df_transformed.select("species", "features", "probability", "prediction").show() +---------------+-----------------+--------------------+----------+ | species| features| probability|prediction| +---------------+-----------------+--------------------+----------+ | Iris-setosa|[4.3,3.0,1.1,0.1]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.4,2.9,1.4,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.4,3.0,1.3,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.4,3.2,1.3,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.5,2.3,1.3,0.3]|[1.0,5.1584556500...| 0.0| | Iris-setosa|[4.6,3.1,1.5,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.6,3.4,1.4,0.3]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.6,3.6,1.0,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.7,3.2,1.3,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.7,3.2,1.6,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.8,3.0,1.4,0.1]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.8,3.0,1.4,0.3]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.8,3.1,1.6,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.8,3.4,1.6,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.8,3.4,1.9,0.2]| [1.0,0.0,0.0]| 0.0| |Iris-versicolor|[4.9,2.4,3.3,1.0]| [0.0,1.0,0.0]| 1.0| | Iris-virginica|[4.9,2.5,4.5,1.7]|[0.0,2.0755096241...| 2.0| | Iris-setosa|[4.9,3.0,1.4,0.2]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.9,3.1,1.5,0.1]| [1.0,0.0,0.0]| 0.0| | Iris-setosa|[4.9,3.1,1.5,0.1]| [1.0,0.0,0.0]| 0.0| +---------------+-----------------+--------------------+----------+ only showing top 20 rows
Приведенная выше модель прогнозирования правильно классифицирует различные виды, например: Iris-setosa присвоено значение 0, Iris-versicolor — 1, а Iris-virginica — 2.
Полная тетрадь:
Использованная литература :
- https://www.javatpoint.com/machine-learning-pipeline
- Официальные документы от Apache spark.