Рубрики
Без рубрики

Tensorflow 2.0: Решение задач классификации и регрессии

Tensorflow 2.0 представил некоторые изрядные новые функции. Среди них теперь он по умолчанию использует API Keras для классификации и регрессии. В этой статье мы рассмотрим эти классические задачи ML с использованием Tensorflow 2.0.

Автор оригинала: Usman Malik.

Tensorflow 2.0: Решение задач классификации и регрессии

После долгой шумихи Google наконец выпустила TensorFlow 2.0 , которая является последней версией флагманской платформы глубокого обучения Google. В TensorFlow 2.0 появилось много долгожданных функций. В этой статье очень кратко рассказывается о том, как можно разработать простые классификационные и регрессионные модели с помощью TensorFlow 2.0.

Классификация с помощью Tensorflow 2.0

Если вы когда-либо работали с библиотекой Keras, вас ждет настоящее удовольствие. TensorFlow 2.0 теперь использует Keras API в качестве библиотеки по умолчанию для обучения классификационных и регрессионных моделей. До TensorFlow 2.0 одна из основных критических замечаний, с которыми приходилось сталкиваться более ранним версиям TensorFlow, была связана со сложностью создания моделей. Ранее вам нужно было сшить графики, сеансы и заполнители вместе, чтобы создать даже простую модель логистической регрессии. С TensorFlow 2.0 создание классификационных и регрессионных моделей стало простым делом.

Итак, без лишних слов давайте разработаем классификационную модель с помощью TensorFlow.

Набор данных

Набор данных для примера классификации можно свободно загрузить по ссылке this link . Загрузите файл в формате CSV. Если вы откроете загруженный CSV-файл, то увидите, что он не содержит никаких заголовков. Подробная информация о столбцах доступна по адресу UCI machine learning repository . Я рекомендую вам подробно ознакомиться с информацией о наборе данных по ссылке для скачивания. В этом разделе я кратко опишу набор данных.

Набор данных в основном состоит из 7 столбцов:

  1. цена (цена покупки автомобиля)
  2. maint ( стоимость технического обслуживания)
  3. двери (количество дверей)
  4. человек (вместимость сидячих мест)
  5. lung_capacity (вместимость багажа)
  6. безопасность (насколько безопасен автомобиль)
  7. выход (состояние автомобиля)

Учитывая первые 6 столбцов, задача состоит в том, чтобы предсказать значение для 7-го столбца, то есть выход. Выходной столбец может иметь одно из трех значений: “unacc” (неприемлемо), “acc” (приемлемо), хорошо и очень хорошо.

Импорт библиотек

Прежде чем импортировать набор данных в наше приложение, нам нужно импортировать необходимые библиотеки.

import pandas as pd
import numpy as np
import tensorflow as tf

import matplotlib.pyplot as plt
%matplotlib inline

import seaborn as sns
sns.set(style="darkgrid")

Прежде чем мы продолжим, я хочу, чтобы вы убедились, что у вас есть последняя версия TensorFlow, то есть TensorFlow 2.0. Вы можете проверить свою версию TensorFlow с помощью следующей команды:

print(tf.__version__)

Если у вас не установлен TensorFlow 2.0, вы можете обновить его до последней версии с помощью следующей команды:

$ pip install --upgrade tensorflow

Импорт набора данных

Следующий сценарий импортирует набор данных. Измените путь к вашему файлу данных CSV в соответствии с этим.

cols = ['price', 'maint', 'doors', 'persons', 'lug_capacity', 'safety','output']
cars = pd.read_csv(r'/content/drive/My Drive/datasets/car_dataset.csv', names=cols, header=None)

Поскольку CSV-файл по умолчанию не содержит заголовков столбцов, мы передали список заголовков столбцов методу pd.read_csv () .

Теперь давайте посмотрим первые 5 строк набора данных с помощью метода head () .

cars.head()

Выход:

первые 5 строк набора данных

Вы можете увидеть 7 столбцов в наборе данных.

Анализ и предварительная обработка данных

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

plot_size = plt.rcParams["figure.figsize"]
plot_size [0] = 8
plot_size [1] = 6
plt.rcParams["figure.figsize"] = plot_size

И следующий сценарий строит круговую диаграмму, показывающую распределение выходных данных.

cars.output.value_counts().plot(kind='pie', autopct='%0.05f%%', colors=['lightblue', 'lightgreen', 'orange', 'pink'], explode=(0.05, 0.05, 0.05,0.05))

Выход:

круговая диаграмма анализа данных

Результаты показывают, что большинство автомобилей (70%) находятся в неприемлемом состоянии, в то время как 20% автомобилей находятся в приемлемом состоянии. Соотношение автомобилей в хорошем и очень хорошем состоянии очень низкое.

Все столбцы в нашем наборе данных категориальны. Глубокое обучение основано на статистических алгоритмах, а статистические алгоритмы работают с числами. Поэтому нам нужно преобразовать категориальную информацию в числовые столбцы. Существуют различные подходы к этому, но один из наиболее распространенных подходов-это горячее кодирование . В однократном кодировании для каждого уникального значения в категориальном столбце создается новый столбец. Для строк в фактическом столбце, где существовало уникальное значение, 1 добавляется к соответствующей строке столбца, созданного для этого конкретного значения. Это может показаться сложным, но следующий пример прояснит это.

Следующий скрипт преобразует категориальные столбцы в числовые:

price = pd.get_dummies(cars.price, prefix='price')
maint = pd.get_dummies(cars.maint, prefix='maint')

doors = pd.get_dummies(cars.doors, prefix='doors')
persons = pd.get_dummies(cars.persons, prefix='persons')

lug_capacity = pd.get_dummies(cars.lug_capacity, prefix='lug_capacity')
safety = pd.get_dummies(cars.safety, prefix='safety')

labels = pd.get_dummies(cars.output, prefix='condition')

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

X = pd.concat([price, maint, doors, persons, lug_capacity, safety] , axis=1)

Давайте посмотрим, как теперь выглядит наша колонка этикеток:

labels.head()

Выход:

столбцы набора данных

Столбец label – это в основном одна горячая закодированная версия выходного столбца, который у нас был в нашем наборе данных. Выходной столбец имел четыре уникальных значения: unacc, acc, good и very good. В наборе данных меток с одним горячим кодированием можно увидеть четыре столбца, по одному для каждого уникального значения в выходном столбце. Вы можете увидеть 1 в столбце для уникального значения, которое первоначально существовало в этой строке. Например, в первых пяти строках выходного столбца значение столбца было unacc. В столбце метки вы можете увидеть 1 в первых пяти строках столбца condition_unacc.

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

y = labels.values

Последний шаг, прежде чем мы сможем обучить нашу классификационную модель TensorFlow 2.0, – это разделить набор данных на обучающие и тестовые наборы:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)

Модельное обучение

Чтобы обучить модель, давайте импортируем классы TensorFlow 2.0. Выполните следующий сценарий:

from tensorflow.keras.layers import Input, Dense, Activation,Dropout
from tensorflow.keras.models import Model

Как я уже говорил ранее, TensorFlow 2.0 использует API Keras для обучения модели. В приведенном выше скрипте мы в основном импортируем Input , Device , Activation и Dropout классы из tensorflow.keras.слои модуль. Аналогично, мы также импортируем класс Model из модуля tensorflow.keras.models .

Следующим шагом является создание нашей классификационной модели:

input_layer = Input(shape=(X.shape[1],))
dense_layer_1 = Dense(15, activation='relu')(input_layer)
dense_layer_2 = Dense(10, activation='relu')(dense_layer_1)
output = Dense(y.shape[1], activation='softmax')(dense_layer_2)

model = Model(inputs=input_layer, outputs=output)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])

Как видно из сценария, модель содержит три плотных слоя. Первые два плотных слоя содержат 15 и 10 узлов соответственно с функцией активации relu . Конечный плотный слой содержит 4 узла ( y.shape[1] ) и функцию активации softmax , так как это задача классификации. Модель обучается с использованием categorical_cross entropy loss function и adam optimizer. Метрикой оценки является точность.

Следующий сценарий показывает сводку модели:

print(model.summary())

Выход:

Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         [(None, 21)]              0
_________________________________________________________________
dense (Dense)                (None, 15)                330
_________________________________________________________________
dense_1 (Dense)              (None, 10)                160
_________________________________________________________________
dense_2 (Dense)              (None, 4)                 44
=================================================================
Total params: 534
Trainable params: 534
Non-trainable params: 0
_________________________________________________________________
None

Наконец, для обучения модели выполните следующий сценарий:

history = model.fit(X_train, y_train, batch_size=8, epochs=50, verbose=1, validation_split=0.2)

Модель будет обучаться в течение 50 эпох, но здесь ради пространства отображается результат только последних 5 эпох:

Epoch 45/50
1105/1105 [==============================] - 0s 219us/sample - loss: 0.0114 - acc: 1.0000 - val_loss: 0.0606 - val_acc: 0.9856
Epoch 46/50
1105/1105 [==============================] - 0s 212us/sample - loss: 0.0113 - acc: 1.0000 - val_loss: 0.0497 - val_acc: 0.9856
Epoch 47/50
1105/1105 [==============================] - 0s 219us/sample - loss: 0.0102 - acc: 1.0000 - val_loss: 0.0517 - val_acc: 0.9856
Epoch 48/50
1105/1105 [==============================] - 0s 218us/sample - loss: 0.0091 - acc: 1.0000 - val_loss: 0.0536 - val_acc: 0.9856
Epoch 49/50
1105/1105 [==============================] - 0s 213us/sample - loss: 0.0095 - acc: 1.0000 - val_loss: 0.0513 - val_acc: 0.9819
Epoch 50/50
1105/1105 [==============================] - 0s 209us/sample - loss: 0.0080 - acc: 1.0000 - val_loss: 0.0536 - val_acc: 0.9856

К концу 50-й эпохи мы имеем точность обучения 100%, а точность проверки 98,56%, что впечатляет.

Давайте наконец оценим эффективность нашей классификационной модели на тестовом наборе:

score = model.evaluate(X_test, y_test, verbose=1)

print("Test Score:", score[0])
print("Test Accuracy:", score[1])

Вот результат:

WARNING:tensorflow:Falling back from v2 loop because of error: Failed to find data adapter that can handle input: , 
346/346 [==============================] - 0s 55us/sample - loss: 0.0605 - acc: 0.9740
Test Score: 0.06045335989359314
Test Accuracy: 0.9739884

Наша модель достигает точности 97,39% на тестовом наборе. Хотя это немного меньше, чем точность обучения 100%, это все равно очень хорошо, учитывая тот факт, что мы случайным образом выбрали количество слоев и узлов. Вы можете добавить больше слоев в модель с большим количеством узлов и посмотреть, сможете ли вы получить лучшие результаты на наборах проверки и тестирования.

Регрессия с TensorFlow 2.0

В регрессионной задаче цель состоит в том, чтобы предсказать непрерывное значение. В этом разделе вы увидите, как решить проблему регрессии с помощью TensorFlow 2.0

Набор данных

Набор данных для этой задачи можно свободно загрузить по ссылке this link . Загрузите CSV-файл.

Следующий сценарий импортирует набор данных. Не забудьте изменить путь к вашему собственному файлу данных CSV.

petrol_cons = pd.read_csv(r'/content/drive/My Drive/datasets/petrol_consumption.csv')

Давайте напечатаем первые пять строк набора данных с помощью функции head() :

petrol_cons.head()

Выход:

строки набора данных

Вы можете видеть, что в наборе данных есть пять столбцов. Регрессионная модель будет обучаться на первых четырех столбцах, то есть Petrol_tax, Average_income, Paved_Highways и Population_Driver_License(%). Будет предсказано значение для последнего столбца, то есть Petrol_Consumption. Как вы можете видеть, для выходного столбца не существует дискретного значения, скорее прогнозируемое значение может быть любым непрерывным значением.

Предварительная обработка данных

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

X = petrol_cons.iloc[:, 0:4].values
y = petrol_cons.iloc[:, 4].values

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

В приведенном выше скрипте в набор объектов X включены первые четыре столбца набора данных. В набор меток y входит только 5-й столбец. Затем набор данных делится на обучающий и тестовый размер с помощью метода train_test_split модуля sklearn.model_selection . Значение атрибута test_size равно 0,2, что означает, что тестовый набор будет содержать 20% исходных данных, а обучающий набор будет состоять из оставшихся 80% исходного набора данных. Наконец, для масштабирования набора данных используется класс StandardScaler из модуля sklearn.preprocessing .

Модельное обучение

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

input_layer = Input(shape=(X.shape[1],))
dense_layer_1 = Dense(100, activation='relu')(input_layer)
dense_layer_2 = Dense(50, activation='relu')(dense_layer_1)
dense_layer_3 = Dense(25, activation='relu')(dense_layer_2)
output = Dense(1)(dense_layer_3)

model = Model(inputs=input_layer, outputs=output)
model.compile(loss="mean_squared_error" , optimizer="adam", metrics=["mean_squared_error"])

Наша модель состоит из четырех плотных слоев с 100, 50, 25 и 1 узлом соответственно. Для регрессионных задач одной из наиболее часто используемых функций потерь является mean_squared_error . Следующий сценарий печатает сводку модели:

Model: "model_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_4 (InputLayer)         [(None, 4)]               0
_________________________________________________________________
dense_10 (Dense)             (None, 100)               500
_________________________________________________________________
dense_11 (Dense)             (None, 50)                5050
_________________________________________________________________
dense_12 (Dense)             (None, 25)                1275
_________________________________________________________________
dense_13 (Dense)             (None, 1)                 26
=================================================================
Total params: 6,851
Trainable params: 6,851
Non-trainable params: 0

Наконец, мы можем обучить модель с помощью следующего сценария:

history = model.fit(X_train, y_train, batch_size=2, epochs=100, verbose=1, validation_split=0.2)

Вот результат последних 5 тренировочных эпох:

Epoch 96/100
30/30 [==============================] - 0s 2ms/sample - loss: 510.3316 - mean_squared_error: 510.3317 - val_loss: 10383.5234 - val_mean_squared_error: 10383.5234
Epoch 97/100
30/30 [==============================] - 0s 2ms/sample - loss: 523.3454 - mean_squared_error: 523.3453 - val_loss: 10488.3036 - val_mean_squared_error: 10488.3037
Epoch 98/100
30/30 [==============================] - 0s 2ms/sample - loss: 514.8281 - mean_squared_error: 514.8281 - val_loss: 10379.5087 - val_mean_squared_error: 10379.5088
Epoch 99/100
30/30 [==============================] - 0s 2ms/sample - loss: 504.0919 - mean_squared_error: 504.0919 - val_loss: 10301.3304 - val_mean_squared_error: 10301.3311
Epoch 100/100
30/30 [==============================] - 0s 2ms/sample - loss: 532.7809 - mean_squared_error: 532.7809 - val_loss: 10325.1699 - val_mean_squared_error: 10325.1709

Для оценки эффективности регрессионной модели на тестовом наборе одной из наиболее часто используемых метрик является среднеквадратичная ошибка. Мы можем найти среднеквадратичную ошибку между прогнозируемыми и фактическими значениями с помощью класса mean_squared_error модуля sklearn.metrics . Затем мы можем взять квадратный корень из результирующей среднеквадратичной ошибки. Посмотрите на следующий сценарий:

from sklearn.metrics import mean_squared_error
from math import sqrt

pred_train = model.predict(X_train)
print(np.sqrt(mean_squared_error(y_train,pred_train)))

pred = model.predict(X_test)
print(np.sqrt(mean_squared_error(y_test,pred)))

Выходные данные показывают среднеквадратичную ошибку как для обучающего, так и для тестового наборов. Результаты показывают, что производительность модели лучше на обучающем наборе, так как среднеквадратичное значение ошибки для обучающего набора меньше. Наша модель слишком подходит. Причина очевидна, у нас было только 48 записей в наборе данных. Попробуйте обучить регрессионные модели с большим набором данных, чтобы получить лучшие результаты.

50.43599665058207
84.31961060849562

Вывод

TensorFlow 2.0 – это последняя версия библиотеки Google TensorFlow для глубокого обучения. В этой статье кратко рассказывается о том, как создавать классификационные и регрессионные модели с помощью TensorFlow 2.0. Чтобы получить практический опыт, я бы предложил вам попрактиковаться в примерах, приведенных в этой статье, и попытаться создать простые регрессионные и классификационные модели с TensorFlow 2.0, используя некоторые другие наборы данных.