Мой проект с открытым исходным кодом

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

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

Введение

Для прогнозирования табличных данных чаще всего используются классические методы машинного обучения. Чаще всего реализуется в scikit-learn. Одним из преимуществ этой библиотеки является простота использования. Мы готовим данные, подгоняем и прогнозируем, готово.

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, n_features=4,
                            n_informative=2, n_redundant=0,
                           random_state=0, shuffle=False)
clf = RandomForestClassifier(max_depth=2, random_state=0)
clf.fit(X, y)
print(clf.predict([[0, 0, 0, 0]]))

Использование нейросетей, в частности библиотек Tensorflow или PyTorch, предполагает построение архитектуры нейросетевой модели с последующим обучением и прогнозированием. Требует более высокого порога входа.

Реализовано множество готовых архитектур нейронных сетей для работы с изображениями, текстом и звуком. Не так много работы с табличными данными — пример TabNet.

Основной целью создания DatRet было снижение порога входа для работы с нейросетями. Реализовано обучение и прогнозирование данных, как в классических методах, таких как RandomForestClassifier или CatBoostClassifier. Для этого я создал автоматическую генерацию архитектуры нейронной сети на основе количества выбранных нейронов в первом полносвязном слое. Второй целью была попытка приблизиться к классическим методам с точки зрения точности прогнозирования структурированных табличных данных.

Модель имеет три класса:

  • DatRetClassifier для задач классификации.
  • DatRetRegressor для проблем регрессии
  • DatRetMultilabelClassifier для классификации с несколькими метками.

Преимущества

  • простота и удобство использования. Соответствуйте и прогнозируйте и вуаля!
  • автоматическая генерация архитектуры нейронной сети
  • быстрая настройка параметров модели
  • Поддержка графического процессора
  • высокая точность предсказания
  • поддержка многоуровневой классификации
  • Tensorflow под капотом;)

Где взять?

Исходный код в настоящее время размещен на GitHub по адресу: GitHub — AbdualimovTP/datret: Реализация Tensorflow для структурированных табличных данных

Двоичные установщики для последней выпущенной версии доступны в Python Package Index (PyPI)

# PyPI
pip install datret

Зависимости

Быстрый старт

Обучение и прогнозирование модели реализовано как в scikit-learn. Подготовьте набор для тестирования и тренировки и запустите подгонку. Поддержка автоматической нормализации данных для нейронных сетей.

Обратите внимание! Не забудьте установить зависимости перед использованием модели. Вам потребуются установленные Tensorflow, Numpy, Pandas и Scikit-Learn.

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

# load library
from datret.datret import DatRetClassifier, DatRetRegressor, DatRetMultilabelClassifier

# prepare train, test split. As in sklearn.
# for example
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=i)

# Call the regressor or classifier and train the model.
DR = DatRetClassifier() # DatRetRegressor works on the same principle
DR.fit(X_train, y_train)
# predict the actual label (or class) over a new set of data.
DR_predict = DR.predict(X_test)
# predict the class probabilities for each data point.
DR_predict_proba = DR.predict_proba(X_test) # Missing in DatRetRegressor, DatRetMultilabelClassifier

Индивидуальные параметры модели

Параметры:

  • epoch: int, по умолчанию = 30. Количество эпох для обучения модели.
  • Оптимизатор: строка (имя оптимизатора) или экземпляр оптимизатора. См. tf.keras.optimizers, по умолчанию = Adam(learning_rate=0.001). На DatRetRegressor скорость обучения по умолчанию = 0,01. Встроенные классы оптимизатора тензорного потока.
  • потеря: функция потери. Может быть строкой (имя функции потерь). См. tf.keras.losses, по умолчанию для DatRetClassifier = CategoricalCrossentropy(), для DatRetRegressor = MeanSquaredError(). Встроенные функции потерь.
  • подробно: «авто», 0, 1 или 2, по умолчанию = 0. Многословный режим. 0 = без звука, 1 = индикатор выполнения, 2 = одна строка в эпоху. «auto» по умолчанию равно 1 в большинстве случаев, но 2 при использовании с ParameterServerStrategy=0.
  • number_neurons: int, по умолчанию = 500. Количество слоев в первом полносвязном слое. Последующие слои генерируются автоматически с вдвое меньшим количеством нейронов.
  • validation_split: число с плавающей запятой от 0 до 1, по умолчанию = 0. Доля данных обучения, которые будут использоваться в качестве данных проверки. Модель будет выделять эту часть обучающих данных, не будет обучаться на ней и будет оценивать потери и любые метрики модели на этих данных в конце каждой эпохи.
  • batch_size: целое число, по умолчанию = 1. Количество выборок на обновление градиента. Steps_per_epoch рассчитывается автоматически, X_train.shape[0] // batch_size
  • перемешивание: True или False, по умолчанию = True. Этот аргумент игнорируется, когда x является генератором или объектом tf.data.Dataset. «пакет» — это специальная опция для работы с ограничениями данных HDF5; он перемешивается кусками размером с пакет.
  • обратный вызов: [], по умолчанию = [EarlyStopping(monitor='loss', mode='auto', patience=7, verbose=1), ReduceLROnPlateau(monitor='loss', factor=0.2, patience=3, min_lr=0.00001, verbose=1)]. Обратные вызовы: утилиты, вызываемые в определенные моменты обучения модели.

Настраиваемые параметры метода fit

Параметры:

  • нормализовать: True или False, по умолчанию True. Автоматическая нормализация входных данных. Используется MinMaxScaler.

Пример:

# load library
import tensorflow as tf
from tensorflow.keras.layers import *
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam, Nadam
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
from tensorflow.keras.losses import CategoricalCrossentropy, MeanSquaredError, BinaryCrossentropy
from datret.datret import DatRetClassifier, DatRetRegressor, DatRetMultilabelClassifier

# prepare train, test split. As in sklearn.
# for example
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=i)

# Call the regressor or classifier and train the model.
DR = DatRetClassifier(epoch=50,
                      optimizer=Nadam(learning_rate=0.001),
                      loss=BinaryCrossentropy(),
                      verbose=1,
                      number_neurons=1000,
                      validation_split = 0.1,
                      batch_size=100,
                      shuffle=True,
                      callback=[])
DR.fit(X_train, y_train, normalize=True)
# predict the actual label (or class) over a new set of data.
DR_predict = DR.predict(X_test)
# predict the class probabilities for each data point.
DR_predict_proba = DR.predict_proba(X_test)

Архитектура модели

Например, при использовании number_neurons = 500 входных нейронов и 2 предсказуемых классов модель автоматически будет иметь эту архитектуру.

Model: "DatRet with number_neurons = 500"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, X_train.shape[0)]      0         

 dense (Dense)               (None, 500)               150500    

 dense_1 (Dense)             (None, 250)               125250    

 dense_2 (Dense)             (None, 125)               31375     

 dense_3 (Dense)             (None, 62)                7812      

 dense_4 (Dense)             (None, 31)                1953      

 dense_5 (Dense)             (None, 15)                480       

 dense_6 (Dense)             (None, 7)                 112       

 dense_7 (Dense)             (None, 3)                 24        

 dense_8 (Dense)             (None, 2)                 8         
                       (2 predictable classes)                               
=================================================================
Total params: 317,514
Trainable params: 317,514
Non-trainable params: 0

Сравнение точности с классическими методами машинного обучения

  • DatRetClassifier

Для оценки точности классификатора мы будем использовать Базу данных диабета индейцев пима | Каггл. Сопоставимый показатель RocAucScore. Мы будем сравнивать DatRet с RandomForest и CatBoost из коробки.

for i in [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]:
    X_train, X_test, y_train, y_test = train_test_split(data.drop(["Outcome"], axis=1), data["Outcome"],
                                                random_state=10, test_size=i)
    #RandomForest
    RF = RandomForestClassifier(random_state=0)
    RF.fit(X_train, y_train)
    RF_pred = RF.predict_proba(X_test)
    dataFrameRocAuc.loc['RandomForest'][f'{int(i*100)}%'] = np.round(roc_auc_score(y_test, RF_pred[:,1]), 2)
    
    #Catboost
    CB = CatBoostClassifier(random_state=0, verbose=0)
    CB.fit(X_train, y_train)
    CB_pred = CB.predict_proba(X_test)
    dataFrameRocAuc.loc['CatBoost'][f'{int(i*100)}%'] = np.round(roc_auc_score(y_test, CB_pred[:,1]), 2)
    
    #DatRet
    DR = DatRetClassifier(optimizer=Adam(learning_rate=0.001))
    DR.fit(X_train, y_train)
    DR_pred = DR.predict_proba(X_test)
    dataFrameRocAuc.loc['DatRet'][f'{int(i*100)}%'] = np.round(roc_auc_score(y_test, DR_pred[:,1]), 2)

               10%  20%     30%  40%  50%  60%
RandomForest  0.79  0.81  0.81  0.79  0.82  0.82
CatBoost      0.78  0.82  0.82  0.8   0.81  0.82
DatRet        0.79  0.84  0.82  0.81  0.84  0.81
  • DatRetRegressor

Чтобы оценить точность регрессора, мы будем использовать Персональные наборы данных о медицинских расходах | Каггл. Сопоставимый показатель Среднеквадратическая ошибка. Мы будем сравнивать DatRet с RandomForest и CatBoost из коробки.

for i in [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]:
    X_train, X_test, y_train, y_test = train_test_split(data.drop(["charges"], axis=1), data["charges"],
                                                random_state=10, test_size=i)
    #RandomForest
    RF = RandomForestRegressor(random_state=0)
    RF.fit(X_train, y_train)
    RF_pred = RF.predict(X_test)
    dataFrameRMSE.loc['RandomForest'][f'{int(i*100)}%'] = np.round(mean_squared_error(y_test, RF_pred, squared=False), 2)
    
    #Catboost
    CB = CatBoostRegressor(random_state=0, verbose=0)
    CB.fit(X_train, y_train)
    CB_pred = CB.predict(X_test)
    dataFrameRMSE.loc['CatBoost'][f'{int(i*100)}%'] = np.round(mean_squared_error(y_test, CB_pred, squared=False), 2)
    
    #DatRet
    DR = DatRetRegressor(optimizer=Adam(learning_rate=0.01))
    DR.fit(X_train, y_train)
    DR_pred = DR.predict(X_test)
    dataFrameRMSE.loc['DatRet'][f'{int(i*100)}%'] = np.round(mean_squared_error(y_test, DR_pred, squared=False), 2)

              10%   20%   30%   40%   50%   60%
RandomForest  5736  5295  4777  4956  4904  4793
CatBoost      5732  5251  4664  4986  5044  4989
DatRet        5860  5173  4610  4927  5047  5780

Неплохие результаты для готовой модели.

В задаче классификации 10%, 20%, 30%, 40%, 50% от общего набора данных тестовой выборки лучшие результаты показал DatRet.

В задаче регрессии для 20%, 30%, 40% всего набора данных тестовой выборки DatRet дает наилучшую точность.

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