Классификация изображений с несколькими классами с использованием трансферного обучения с PySpark
В этой статье мы продемонстрируем задачу Computer Vision с возможностью объединения двух современных технологий: Глубокое обучение с Апач Спарк. Мы будем использовать силу Конвейеры глубокого обучения для задачи классификации изображений Multi-Class.
Конвейеры глубокого обучения — это высокоуровневая платформа глубокого обучения, которая упрощает общие рабочие процессы глубокого обучения с помощью API Spark MLlib Pipelines. В настоящее время он поддерживает TensorFlow и Keras с бэкэндом TensorFlow.
Библиотека взята из Databricks и использует Spark для двух своих сильных сторон:
- В духе Spark и Spark MLlib он предоставляет простые в использовании API-интерфейсы, которые позволяют проводить глубокое обучение в очень небольшом количестве строк кода.
- Он использует мощный распределенный движок Spark для масштабирования глубокого обучения на массивных наборах данных.
Трансферное обучение
Трансферное обучение — это метод машинного обучения в целом, который фокусируется на сохранении знаний (весов и смещений), полученных при решении одной проблемы, и дальнейшем применении их к другой, но связанной проблеме.
Конвейеры глубокого обучения предоставляют утилиты для выполнения переноса обучения на изображениях, что является одним из самых быстрых способов начать использовать глубокое обучение. Благодаря концепции Featurizer конвейеры глубокого обучения обеспечивают быструю передачу обучения в Spark-Cluster. Прямо сейчас он предоставляет следующие нейронные сети для трансферного обучения:
- НачалоV3
- Восприятие
- Реснет50
- ВГГ16
- ВГГ19
В демонстрационных целях мы будем работать только на НачалоV3 модель. Вы можете прочитать технические подробности этой модели от здесь.
В следующем примере объединены НачалоV3 модель и полиномиальная логистическая регрессия в Спарке. Вспомогательная функция из конвейеров глубокого обучения, называемая DeepImageFeaturizer автоматически отделяет последний слой предварительно обученной нейронной сети и использует выходные данные всех предыдущих слоев в качестве признаков для алгоритма логистической регрессии.
Набор данных
В бенгальском сценарии десять числовые цифры (графемы или символы, обозначающие числа от 0 до 9). Числа больше 9 записываются на бенгальском языке с использованием позиционной системы счисления с основанием 10.
Мы выбрали NumtaDB в качестве источника нашего набора данных. Это набор данных бенгальских рукописных цифр. Набор данных содержит более 85 000 цифр от более чем 2700 участников. Но здесь мы не планируем работать со всем набором данных, а будем выбирать случайным образом 50 изображений каждого класса.
Рис. 1. Каждая папка содержит 50 изображений. [ Classes (0 to 9) ]
Давайте посмотрим ниже, что у нас есть внутри каждой из десяти папок. Я переименовываю каждое изображение, показанное ниже, в соответствующую метку класса в демонстрационных целях.
Рис. 2: Бенгальская рукописная цифра
Сначала мы загружаем все изображения в SparkData Frame. Затем мы строим модель и обучаем ее. После этого мы оценим производительность нашей обученной модели.
Загрузить изображения
Наборы данных (от 0 до 9) содержат почти 500 рукописных цифр бангла (по 50 изображений каждого класса). Здесь мы вручную загружаем каждое изображение в фрейм данных искры с целевой колонкой. После загрузки всего набора данных мы разделяем его на 8:2 отношение случайным образом для обучающей выборки и окончательной тестовой выборки.
Наша цель — обучить модель с набором обучающих данных и, наконец, оценить производительность модели с набором тестовых данных.
from pyspark.sql import SparkSession
from pyspark.ml.image import ImageSchema
from pyspark.sql.functions import lit
from functools import reduce
spark = SparkSession.builder.appName(‘DigitRecog’).getOrCreate()
zero = ImageSchema.readImages("0").withColumn("label", lit(0))
one = ImageSchema.readImages("1").withColumn("label", lit(1))
two = ImageSchema.readImages("2").withColumn("label", lit(2))
three = ImageSchema.readImages("3").withColumn("label", lit(3))
four = ImageSchema.readImages("4").withColumn("label", lit(4))
five = ImageSchema.readImages("5").withColumn("label", lit(5))
six = ImageSchema.readImages("6").withColumn("label", lit(6))
seven = ImageSchema.readImages("7").withColumn("label", lit(7))
eight = ImageSchema.readImages("8").withColumn("label", lit(8))
nine = ImageSchema.readImages("9").withColumn("label", lit(9))
dataframes = [zero, one, two, three,four,
five, six, seven, eight, nine]
df = reduce(lambda first, second: first.union(second), dataframes)
df = df.repartition(200)
train, test = df.randomSplit([0.8, 0.2], 42)
Здесь мы можем выполнять различные исследовательские анализы данных в Spark DataFrame. Мы также можем просмотреть схему фрейма данных.
df.printSchema()
root
|-- image: struct (nullable = true)
| |-- origin: string (nullable = true)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
| |-- nChannels: integer (nullable = false)
| |-- mode: integer (nullable = false)
| |-- data: binary (nullable = false)
|-- label: integer (nullable = false)
Мы также можем преобразовать Spark-DataFrame к Pandas-DataFrame с использованием .toPanda().
Обучение модели
Здесь мы объединяем НачалоV3 модель и логистическая регрессия в Спарке. DeepImageFeaturizer автоматически отделяет последний слой предварительно обученной нейронной сети и использует выходные данные всех предыдущих слоев в качестве признаков для алгоритма логистической регрессии.
С логистическая регрессия это простой и быстрый алгоритм, это обучение трансферному обучению может быстро сходиться.
from pyspark.ml.evaluation import MulticlassClassificationEvaluator
from pyspark.ml.classification import LogisticRegression
from pyspark.ml import Pipeline
from sparkdl import DeepImageFeaturizer
featurizer = DeepImageFeaturizer(inputCol="image",
outputCol="features",
modelName="InceptionV3")
lr = LogisticRegression(maxIter=5, regParam=0.03,
elasticNetParam=0.5, labelCol="label")
sparkdn = Pipeline(stages=[featurizer, lr])
spark_model = sparkdn.fit(train)
Оценка
Теперь пришло время оценить производительность модели. Теперь нам нравится оценивать четыре метрики оценки, такие как F1-счет, точность, отзыв, точность на тестовом наборе данных.
from pyspark.ml.evaluation import MulticlassClassificationEvaluator
# evaluate the model with test set
evaluator = MulticlassClassificationEvaluator()
tx_test = spark_model.transform(test)
print('F1-Score ', evaluator.evaluate(tx_test,
{evaluator.metricName:
'f1'}))
print('Precision ', evaluator.evaluate(tx_test,
{evaluator.metricName:
'weightedPrecision'}))
print('Recall ', evaluator.evaluate(tx_test,
{evaluator.metricName:
'weightedRecall'}))
print('Accuracy ', evaluator.evaluate(tx_test,
{evaluator.metricName:
'accuracy'}))
Здесь мы получаем результат. Пока это многообещающе.
F1-Score 0.8111782234361806
Precision 0.8422058244785519
Recall 0.8090909090909091
Accuracy 0.8090909090909091
Метрика путаницы
Здесь мы подведем итоги производительности модели классификации, используя матрица путаницы.
import matplotlib.pyplot as plt
import numpy as np
import itertools
def plot_confusion_matrix(cm, classes,
normalize=False,
title='Confusion matrix',
cmap=plt.cm.GnBu):
plt.imshow(cm, interpolation='nearest', cmap=cmap)
plt.title(title)
tick_marks = np.arange(len(classes))
plt.xticks(tick_marks, classes, rotation=45)
plt.yticks(tick_marks, classes)
fmt = '.2f' if normalize else 'd'
thresh = cm.max() / 2.
for i, j in itertools.product(range(cm.shape[0]),
range(cm.shape[1])):
plt.text(j, i, format(cm[i, j], fmt),
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")
plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label')
Для этого нам нужно преобразовать Spark-DataFrame к Pandas-DataFrame сначала, а затем вызовите матрицу путаницы с истинными и предсказанными метками.
from sklearn.metrics import confusion_matrix
y_true = tx_test.select("label")
y_true = y_true.toPandas()
y_pred = tx_test.select("prediction")
y_pred = y_pred.toPandas()
cnf_matrix = confusion_matrix(y_true, y_pred,labels=range(10))
Давайте визуализируем Матрица путаницы
import seaborn as sns
sns.set_style("darkgrid")
plt.figure(figsize=(7,7))
plt.grid(False)
plot_confusion_matrix(cnf_matrix, classes=range(10))
Рис. 3: Матрица путаницы для 10 бенгальских цифр (от 0 до 9)
Отчет о классификации
Здесь же мы можем получить отчет о классификации каждого класса по оценочной матрице.
from sklearn.metrics import classification_report
target_names = ["Class {}".format(i) for i in range(10)]
print(classification_report(y_true, y_pred, target_names = target_names))
Это продемонстрирует гораздо лучшую производительность модели для каждого прогноза метки класса.
precision recall f1-score support
Class 0 1.00 0.92 0.96 13
Class 1 0.57 1.00 0.73 8
Class 2 0.64 1.00 0.78 7
Class 3 0.88 0.70 0.78 10
Class 4 0.90 1.00 0.95 9
Class 5 0.67 0.83 0.74 12
Class 6 0.83 0.62 0.71 8
Class 7 1.00 0.80 0.89 10
Class 8 1.00 0.80 0.89 20
Class 9 0.70 0.54 0.61 13
micro avg 0.81 0.81 0.81 110
macro avg 0.82 0.82 0.80 110
weighted avg 0.84 0.81 0.81 110
Показатель ROC AUC
Давайте также найдем показатель ROC AUC этой модели. Я нашел следующий фрагмент кода из здесь.
from sklearn.metrics import roc_curve, auc, roc_auc_score
from sklearn.preprocessing import LabelBinarizer
def multiclass_roc_auc_score(y_test, y_pred, average="macro"):
lb = LabelBinarizer()
lb.fit(y_test)
y_test = lb.transform(y_test)
y_pred = lb.transform(y_pred)
return roc_auc_score(y_test, y_pred, average=average)
print('ROC AUC score:', multiclass_roc_auc_score(y_true,y_pred))
Он забивает 0,901.
Прогнозируемые образцы
Давайте посмотрим на некоторые его предсказания, сравнение с реальной этикеткой.
# all columns after transformations
print(tx_test.columns)
# see some predicted output
tx_test.select('image', "prediction", "label").show()
И результат будет следующим
['image', 'label', 'features', 'rawPrediction', 'probability', 'prediction']
+------------------+----------+--------+
| image |prediction| label |
+------------------+----------+--------+
|[file:/home/i...| 1.0| 1|
|[file:/home/i...| 8.0| 8|
|[file:/home/i...| 9.0| 9|
|[file:/home/i...| 1.0| 8|
|[file:/home/i...| 1.0| 1|
|[file:/home/i...| 1.0| 9|
|[file:/home/i...| 0.0| 0|
|[file:/home/i...| 2.0| 9|
|[file:/home/i...| 8.0| 8|
|[file:/home/i...| 9.0| 9|
|[file:/home/i...| 0.0| 0|
|[file:/home/i...| 4.0| 0|
|[file:/home/i...| 5.0| 9|
|[file:/home/i...| 1.0| 1|
|[file:/home/i...| 9.0| 9|
|[file:/home/i...| 9.0| 9|
|[file:/home/i...| 1.0| 1|
|[file:/home/i...| 1.0| 1|
|[file:/home/i...| 9.0| 9|
|[file:/home/i...| 3.0| 6|
+--------------------+----------+-----+
only showing top 20 rows
EndNote
Хотя мы использовали Имиджнет Вес нашей модели довольно многообещающий для распознавания рукописных цифр. Кроме того, мы также не выполняли никаких обработка изображений задание на лучшее обобщение. Кроме того, модель обучается на очень небольшом количестве данных по сравнению с набором данных ImageNet.
На очень высоком уровне каждое приложение Spark состоит из программы-драйвера, которая запускает различные параллельные операции в кластере. Программа-драйвер содержит основную функцию наших приложений и определяет распределенные наборы данных в кластере, а затем применяет к ним операции.
Поскольку это отдельное приложение, мы сначала связали приложение со Spark, а затем импортировали пакеты Spark в нашу программу и создали SparkContext с использованием SparkSession. Хотя мы работали на одной машине, мы можем подключить одну и ту же оболочку к кластеру для параллельного обучения данных.
Однако вы можете получить исходный код сегодняшней демонстрации по ссылке ниже, а также подписаться на меня в Гитхаб для будущих обновлений кода.
Исходный код : TL с PySpark
Что дальше?
Далее мы сделаем Распределенная настройка гиперпараметров с помощью Sparkи попробую пользовательский Жесткий модель и несколько новых сложных примеров
Однако, если вы работаете в области здравоохранения с использованием машинного обучения, не стесняйтесь обращаться к нам, если считаете, что есть возможность для сотрудничества. Хотелось бы обсудить. Свяжитесь с нами, мы всегда активны
Передай привет: электронная почта | LinkedIn | Куора | Гитхаб | Середина | Твиттер | Инстаграм
Связанные технологии
- Распределенное DL с Keras и PySpark — слон
- Распределенная библиотека глубокого обучения для Apache Spark — БигДЛ
- TensorFlow в кластеры Apache Spark — TensorFlowOnSpark
использованная литература