Углубляемся в технические детали создания регрессионной модели с помощью TensorFlow 2.0 и Keras API. В TensorFlow 2.0 Keras входит в стандартную комплектацию с библиотекой TensorFlow. API стал проще и удобнее в использовании.

TensorFlow 2.0 поставляется с Keras, упакованным внутри, нет необходимости импортировать Keras как отдельный модуль (хотя вы можете сделать это, если вам нужно). API TensorFlow 2.0 упрощен и улучшен. Это хорошая новость для нас - разработчиков машинного обучения.

Вот как вы сейчас импортируете Keras из TensorFlow:

from tensorflow import feature_column
from tensorflow import keras
from tensorflow.keras import layers
print(tf.__version__)
2.0.0

Я использую конвейер ввода tf.data для кодирования категориальных столбцов, Keras API хорошо работает с tf.data. Одним из основных преимуществ tf.data является то, что он действует как мост между данными и моделью. Нет необходимости преобразовывать данные самостоятельно, достаточно определить правило преобразования - преобразованные данные будут автоматически применяться во время обучения.

Данные извлекаются из файла CSV в фреймворк Pandas:

column_names = ['report_id','report_params','day_part','exec_time']
raw_dataframe = pd.read_csv('report_exec_times.csv')
dataframe = raw_dataframe.copy()
dataframe.head()

Значения столбца для report_params различаются, нам нужно нормализовать этот столбец (сделать значения аналогичными по шкале):

eps=0.001 # 0 => 0.1¢
dataframe['report_params'] = np.log(dataframe.pop('report_params')+eps)

Я использую служебный метод (этот метод взят из учебника TensorFlow) для создания набора данных tf.data из фрейма данных Pandas:

def df_to_dataset(dataframe, shuffle=True, batch_size=32):
  dataframe = dataframe.copy()
  labels = dataframe.pop('exec_time')
  ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(dataframe))
  ds = ds.batch(batch_size)
  return ds

Затем нам нужно определить отображение данных для кодирования категориальных столбцов. Я использую функцию списка словаря TensorFlow, включая сопоставление всех уникальных значений (если значений много, лучше использовать API встраивания). Кодируются два столбца - report_id и day_part:

feature_columns = []
feature_columns.append(feature_column.numeric_column('report_params'))
report_id = feature_column.categorical_column_with_vocabulary_list('report_id', ['1', '2', '3', '4', '5'])
report_id_one_hot = feature_column.indicator_column(report_id)
feature_columns.append(report_id_one_hot)
day_part = feature_column.categorical_column_with_vocabulary_list('day_part', ['1', '2', '3'])
day_part_one_hot = feature_column.indicator_column(day_part)
feature_columns.append(day_part_one_hot)

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

feature_layer = tf.keras.layers.DenseFeatures(feature_columns)

Мы закончили с функциями. Затем преобразуйте фрейм данных Pandas в tf.data с помощью служебной функции:

batch_size = 32
train_ds = df_to_dataset(train, batch_size=batch_size)
val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)
test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)

Слой плотных функций используется, когда определена последовательная модель Keras (нет необходимости передавать массив функций позже в функцию fit):

def build_model(feature_layer):
  model = keras.Sequential([
    feature_layer,
    layers.Dense(16, activation='relu'),
    layers.Dense(16, activation='relu'),
    layers.Dense(1)
  ])
  optimizer = keras.optimizers.RMSprop(0.001)
  model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])
  return model

Обучение выполняется с помощью функции model.fit. Мы используем входной конвейер tf.data для передачи обучающих и проверочных наборов:

history = model.fit(train_ds,
              validation_data=val_ds,
              epochs=EPOCHS,
              callbacks=[early_stop])

Самое замечательное в этом - кодирование данных происходит «за кулисами» на основе правил, определенных для векторного слоя.

Как запустить функцию model.predict с tf.data и векторным слоем? Это просто.

Создайте фрейм данных Pandas с входными данными:

headers = ['report_id', 'report_params', 'day_part']
dataframe_input = pd.DataFrame([[1, 15, 3]],
                                columns=headers, 
                                dtype=float,
                                index=['input'])

Преобразуйте значение report_params в тот же масштаб, что и для обучения:

eps=0.001 # 0 => 0.1¢
dataframe_input['report_params'] = np.log(dataframe_input.pop('report_params')+eps)

Создайте конвейер ввода tf.data из фрейма данных Pandas:

input_ds = tf.data.Dataset.from_tensor_slices(dict(dataframe_input))
input_ds = input_ds.batch(1)

Запустите функцию model.predict:

res = model.predict(input_ds)
print(res)

Ресурсы:

  • Исходный код с примерами данных доступен в моем репозитории GitHub.

Наслаждаться !