Глубокое обучение в Керасе - построение модели глубокого обучения

Введение Глубокое обучение - одна из самых интересных и многообещающих областей искусственного интеллекта (ИИ) и машинного обучения в настоящее время. Благодаря значительным достижениям в области технологий и алгоритмов в последние годы глубокое обучение открыло дверь в новую эру приложений искусственного интеллекта. Во многих из этих приложений алгоритмы глубокого обучения работают наравне с экспертами-людьми, а иногда и превосходят их [https://techcrunch.com/2017/05/24/alphago-beats-planets-best-human-go-player-ke-jie / amp /]. Python имеет b

Вступление

Глубокое обучение - одна из самых интересных и перспективных областей искусственного интеллекта (ИИ) и машинного обучения в настоящее время. Благодаря значительным достижениям в области технологий и алгоритмов в последние годы глубокое обучение открыло дверь в новую эру приложений искусственного интеллекта.

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

Python стал идти к языку для машинного обучения и многие из наиболее популярных и мощных глубоких библиотек обучения и структур , такие как TensorFlow , Keras и PyTorch встроены в Python.

В этой серии статей мы будем использовать Keras для выполнения исследовательского анализа данных (EDA) , предварительной обработки данных и, наконец, построения модели глубокого обучения и ее оценки.

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

Определение модели

Нейронная сеть с глубоким обучением - это просто нейронная сеть со множеством скрытых слоев.

Определение модели можно разбить на несколько характеристик:

  • Количество слоев
  • Типы этих слоев
  • Количество единиц (нейронов) в каждом слое
  • Функции активации каждого слоя
  • Размер ввода и вывода

Уровни глубокого обучения

Есть много типов слоев для моделей глубокого обучения. Сверточные уровни и уровни объединения используются в CNN, которые классифицируют изображения или обнаруживают объекты, в то время как повторяющиеся уровни используются в RNN, которые являются общими для обработки естественного языка и распознавания речи.

Мы будем использовать слои Dense и Dropout. Плотные слои - самый распространенный и популярный тип слоя - это просто обычный слой нейронной сети, где каждый из ее нейронов связан с нейронами предыдущего и следующего слоя.

Каждый плотный слой имеет функцию активации, которая определяет выходной сигнал своих нейронов на основе входных данных и весов синапсов.

Слои исключения - это просто слои регуляризации, которые случайным образом сбрасывают некоторые входные единицы до 0. Это помогает снизить вероятность переобучения нейронной сети.

Функции активации

Есть также много типов функций активации, которые можно применять к слоям. Каждый из них по-разному связывает вход и веса нейрона и заставляет сеть вести себя по-разному.

Действительно распространенными функциями являются ReLU (выпрямленное линейное устройство) , сигмовидная функция и линейная функция. Мы будем смешивать несколько разных функций.

Слои ввода и вывода

В дополнение к скрытым слоям у моделей есть входной и выходной слой:

архитектура нейронной сети с глубокимобучением{.ezlazyload}

Количество нейронов во входном слое такое же, как количество функций в наших данных. Мы хотим научить сеть реагировать на эти особенности. У нас есть 67 функций в train_df и test_df - таким образом, наш входной слой будет иметь 67 нейронов. Это будет точка входа в наши данные.

Для выходного слоя - количество нейронов зависит от вашей цели. Поскольку мы просто прогнозируем цену - одно значение, мы будем использовать только один нейрон. Классификационные модели будут иметь количество выходных нейронов class

Поскольку на выходе модели будет непрерывное число, мы будем использовать linear активации, чтобы ни одно из значений не было обрезано.

Определение модельного кода

Мы будем использовать несколько операций импорта для кода впереди:

 import matplotlib.pyplot as plt 
 from matplotlib import ticker 
 import numpy as np 
 import pandas as pd 
 import seaborn as sns 
 
 import tensorflow as tf 
 from tensorflow import keras 
 from tensorflow.keras import layers 

Помня об этом импорте и параметрах, давайте определим модель с помощью Keras:

 model = keras.Sequential([ 
 layers.Dense(64, activation='relu', input_shape=[train_df.shape[1]]), 
 layers.Dropout(0.3, seed=2), 
 layers.Dense(64, activation='swish'), 
 layers.Dense(64, activation='relu'), 
 layers.Dense(64, activation='swish'), 
 layers.Dense(64, activation='relu'), 
 layers.Dense(64, activation='swish'), 
 layers.Dense(1) 
 ]) 

Здесь мы использовали функцию Keras Sequential() для создания экземпляра модели. Он берет группу последовательных слоев и объединяет их в одну модель. В конструктор Sequential() мы передаем список, содержащий слои, которые мы хотим использовать в нашей модели.

В этой модели мы создали несколько Dense слоев и один Dropout Мы сделали input_shape равным количеству функций в наших данных. Мы определяем это на первом слое как вход этого слоя.

В каждом слое 64 нейрона. Обычно это до тестирования - добавление большего количества нейронов на слой поможет извлечь больше функций, но иногда это также может работать против вас. После некоторого тестирования 64 нейрона на слой в этом примере дали довольно точный результат. Настоятельно рекомендуется поиграть с числами!

Мы быстро отбросили 30% входных данных, чтобы избежать переобучения. Для seed установлено значение 2, поэтому мы получаем более воспроизводимые результаты. Если бы мы просто случайно выбросили их, каждая модель была бы другой.

Наконец, у нас есть Dense слой с одним нейроном в качестве выходного слоя. По умолчанию у него есть linear функция активации, поэтому мы ничего не устанавливали.

Составление модели

После определения нашей модели следующим шагом будет ее компиляция. Составление модели Keras означает ее настройку для обучения.

Для составления модели нам необходимо выбрать:

  • Функция потерь - чем ниже ошибка, тем ближе модель к цели. Для разных задач требуются разные функции потерь, чтобы отслеживать прогресс. Вот список поддерживаемых функций потерь.
  • Оптимизатор - алгоритм оптимизации, который помогает нам достичь лучших результатов для функции потерь.
  • Метрики - метрики, используемые для оценки модели. Например, если у нас есть функция потерь среднеквадратичной ошибки , имеет смысл использовать среднюю абсолютную ошибку в качестве показателя, используемого для оценки.

Имея это в виду, давайте скомпилируем модель:

 optimizer = tf.keras.optimizers.RMSprop(learning_rate=0.001) 
 
 model.compile(loss=tf.keras.losses.MeanSquaredError(), 
 optimizer=optimizer, 
 metrics=['mae']) 

Здесь мы создали RMSprop со скоростью обучения 0.001 . Не стесняйтесь экспериментировать с другими оптимизаторами, такими как оптимизатор Adam

Примечание. Вы можете либо объявить оптимизатор и использовать этот объект, либо передать его строковое представление в методе compile()

Мы установили функцию потерь как среднеквадратичную ошибку . Опять же, не стесняйтесь экспериментировать с другими функциями потерь и оценивать результаты. Поскольку у нас есть MSE в качестве функции потерь, мы выбрали среднюю абсолютную ошибку в качестве метрики для оценки модели.

Обучение модели

После компиляции модели мы можем обучить ее, используя наш train_df данных train_df. Это делается путем подгонки его с помощью функции fit() :

 history = model.fit( 
 train_df, train_labels, 
 epochs=70, validation_split=0.2 
 ) 

Здесь мы передали данные обучения ( train_df ) и метки поездов ( train_labels ).

Кроме того, обучение - это итеративный процесс. Мы сказали сети пройти через этот обучающий набор данных 70 раз, чтобы извлечь из него как можно больше. Результаты моделей в последнюю эпоху будут лучше, чем в первую.

Наконец, мы передаем обучающие данные, которые используются для проверки. В частности, мы сказали ему использовать 0.2 (20%) данных обучения для проверки результатов. Не путайте это с test_df мы будем использовать для его оценки.

20% не будут использоваться для обучения, а скорее для проверки, чтобы убедиться, что он прогрессирует.

Эта функция распечатает результаты каждой эпохи - значение функции потерь и метрику, которую мы выбрали для отслеживания.

Закончив, мы можем посмотреть, как это делается в каждую эпоху:

 Epoch 65/70 
 59/59 [==============================] - 0s 2ms/step - loss: 983458944.0000 - mae: 19101.9668 - val_loss: 672429632.0000 - val_mae: 18233.3066 
 Epoch 66/70 
 59/59 [==============================] - 0s 2ms/step - loss: 925556032.0000 - mae: 18587.1133 - val_loss: 589675840.0000 - val_mae: 16720.8945 
 Epoch 67/70 
 59/59 [==============================] - 0s 2ms/step - loss: 1052588800.0000 - mae: 18792.9805 - val_loss: 608930944.0000 - val_mae: 16897.8262 
 Epoch 68/70 
 59/59 [==============================] - 0s 2ms/step - loss: 849525312.0000 - mae: 18392.6055 - val_loss: 613655296.0000 - val_mae: 16914.1777 
 Epoch 69/70 
 59/59 [==============================] - 0s 2ms/step - loss: 826159680.0000 - mae: 18177.8945 - val_loss: 588994816.0000 - val_mae: 16520.2832 
 Epoch 70/70 
 59/59 [==============================] - 0s 2ms/step - loss: 920209344.0000 - mae: 18098.7070 - val_loss: 571053952.0000 - val_mae: 16419.8359 

После обучения модель (хранящаяся в model ) узнает, на что она способна, и будет готова делать прогнозы. fit() также возвращает словарь, который содержит значения функции потерь и mae после каждой эпохи, так что мы также можем использовать это. Мы поместили это в history переменную.

Перед тем как делать прогнозы, давайте представим себе , как величина потерь и mae изменились с течением времени:

 model_history = pd.DataFrame(history.history) 
 model_history['epoch'] = history.epoch 
 
 fig, ax = plt.subplots(figsize=(14,8)) 
 num_epochs = model_history.shape[0] 
 ax.plot(np.arange(0, num_epochs), model_history["mae"], 
 label="Training MAE", lw=3, color='#f4b400') 
 ax.plot(np.arange(0, num_epochs), model_history["val_mae"], 
 label="Validation MAE", lw=3, color='#0f9d58') 
 ax.legend() 
 plt.tight_layout() 
 plt.show() 

функция mae и потери с течением времени иобучения{.ezlazyload}

Мы ясно видим, как значения mae и loss со временем снижаются. Это именно то, что мы хотим - модель со временем стала более точной с прогнозами.

Прогнозы с помощью модели

Теперь, когда наша модель обучена, давайте воспользуемся ею, чтобы сделать некоторые прогнозы. Берем элемент из тестовых данных (в test_df ):

 test_unit = test_df.iloc[[0]] 

Этот элемент, хранящийся в test_unit имеет следующие значения, для краткости обрезанные всего до 7 записей:


   Lot Frontage   Площадь участка   Общая квалификация   Общая конд.   Год постройки   Итого Bsmt SF   1-й этаж SF

14 0,0157117 -0,446066 1,36581 -0,50805 0,465714 1.01855 0,91085


Это значения единицы функции, и мы будем использовать модель для прогнозирования ее продажной цены:

 test_pred = model.predict(test_unit).squeeze() 

Мы использовали predict() нашей модели и передали в test_unit чтобы сделать прогноз целевой переменной - цены продажи.

Примечание: predict() возвращает массив NumPy, поэтому мы использовали squeeze() , которая является функцией NumPy, чтобы «сжать» этот массив и получить из него значение прогноза в виде числа, а не массива.

Теперь давайте получим реальную цену единицы из test_labels :

 test_lbl = test_labels.iloc[0] 

А теперь сравним прогнозируемую цену и фактическую:

 print("Model prediction = {:.2f}".format(test_pred)) 
 print("Actual value = {:.2f}".format(test_lbl)) 

 Model prediction = 225694.92 
 Actual value = 212000.00 

Таким образом, фактическая цена продажи этого устройства составляет 212 000 долларов, а наша модель предсказывала, что она составит * 225 694 доллара *. Это довольно близко, хотя цена у модели превысила ~ 5%.

Давайте попробуем другой модуль из test_df :

 test_unit = test_df.iloc[[100]] 

И мы повторим тот же процесс, чтобы сравнить цены:

 test_pred = model.predict(test_unit).squeeze() 
 test_lbl = test_labels.iloc[100] 
 print("Model prediction = {:.2f}".format(test_pred)) 
 print("Actual value = {:.2f}".format(test_lbl)) 

 Model prediction = 330350.47 
 Actual value = 340000.00 

Таким образом, фактическая цена этого устройства составляет 340000 долларов США, а прогнозируемая цена - 330 350 долларов США *. Опять же, не совсем по делу, но это ошибка всего ~ 3%. Это очень точно.

Оценка модели

Это заключительный этап нашего пути к созданию модели глубокого обучения Keras. На этом этапе мы будем использовать модель для создания прогнозов для всех единиц в наших данных тестирования ( test_df ), а затем вычислить среднюю абсолютную ошибку этих прогнозов, сравнив их с фактическими истинными значениями ( test_labels ).

Keras предоставляет evaluate() которую мы можем использовать с нашей моделью для ее оценки. evaluate() вычисляет величину потерь и значения всех метрик, которые мы выбрали при компиляции модели.

Мы выбрали MAE в качестве нашей метрики, потому что ее легко интерпретировать. Значение MAE представляет собой среднее значение ошибки модели:
$
\ begin {уравнение *}
\ text {MAE} (y, \ hat {y}) = \ frac {1} {n} \ sum_ {i = 1} ^ {n} \ left | y_i - \ hat {y} _i \ right |.
\ end {уравнение *}
$

Для нашего удобства об этом позаботится функция evaluate()

 loss, mae = model.evaluate(test_df, test_labels, verbose=0) 

В этот метод мы передаем тестовые данные для нашей модели (для оценки) и фактические данные (для сравнения). Кроме того, мы использовали verbose аргумент, чтобы избежать печати каких-либо дополнительных данных, которые на самом деле не нужны.

Запустим код и посмотрим, как он работает:

 print('MAE = {:.2f}'.format(mae)) 

 MAE = 17239.13 

Средняя абсолютная ошибка 17239.13 . То есть для всех единиц модель в среднем прогнозировала на 17 239 долларов выше или ниже фактической цены.

Интерпретация характеристик модели

Насколько хорош этот результат? Если мы SalePrice на EDA, который мы сделали для SalePrice, мы увидим, что средняя цена продажи единиц в наших исходных данных составляет 180 796 долларов США . Тем не менее, MAE 17 239 - это неплохо.

Чтобы интерпретировать эти результаты по-другому, сопоставим прогнозы с фактическими ценами:

 test_predictions_ = model.predict(test_df).flatten() 
 test_labels_ = test_labels.to_numpy().flatten() 
 fig, ax = plt.subplots(figsize=(14,8)) 
 plt.scatter(test_labels_, test_predictions_, alpha=0.6, 
 color='#ff7043', lw=1, ec='black') 
 lims = [0, max(test_predictions_.max(), test_labels_.max())] 
 plt.plot(lims, lims, lw=1, color='#00acc1') 
 plt.tight_layout() 
 plt.show() 

фактические и прогнозируемыезначения{.ezlazyload}

Если бы наша модель была на 100% точной с 0 MAE, все точки были бы точно на диагональной голубой линии. Однако ни одна модель не является точной на 100%, и мы видим, что большинство точек близко к диагональной линии, что означает, что прогнозы близки к фактическим значениям.

Есть несколько выбросов, некоторые из которых сильно отклоняются . Это резко увеличивает средний MAE нашей модели. В действительности для большинства из этих точек MAE намного меньше 17 239 .

Мы можем проверить эти точки и выяснить, можем ли мы выполнить дополнительную предварительную обработку данных и проектирование функций, чтобы модель более точно их предсказывала.

Заключение

В этом руководстве мы построили модель глубокого обучения с использованием Keras, скомпилировали ее, снабдили подготовленными нами чистыми данными и, наконец, выполнили прогнозы на основе того, что узнали.

Хотя точность не 100%, нам удалось получить очень приличные результаты с небольшим количеством выбросов.

comments powered by Disqus