В этой статье я попытаюсь охватить важные API TensorFlow. Недавно прошел специализацию на Coursera по теме Машинное обучение с TensorFlow на Google Cloud Platform. Пришлось закончить в спешке, сэкономить немного денег. Меня по-прежнему интересовал TensorFlow. На самом сайте Tensorflow есть очень хорошая документация по API и учебники. Я сослался на эту статью и воссоздал ее для другого набора данных, как было предложено в конце статьи.

Из приведенной выше специализации я узнал, что tf.data, tf.feature_colum и tf.estimator API являются основными API для разработки любой модели машинного обучения и ее развертывания в рабочей среде. Развертывание в рабочей среде не рассматривается в этой статье. В этой статье я хочу больше остановиться на tf.data и tf.feature_column. tf.estimator в этой статье не рассматривается. На него можно сослаться по этой ссылке. О tf.estimator будет рассказано в другой статье с другим набором данных.

Набор данных для этого взят с сайта UCI. Я изменил последний столбец для задачи простоты/классификации и доступен по этой ссылке. Полный код доступен на Github. Он также доступен на Colab. Это в основном состоит из четырех шагов:

  • Загрузка данных из CSV с помощью pandas.
  • Создайте конвейер с tf.data для перемешивания и пакетирования входных данных.
  • Определите feature_columns относительно полей, присутствующих в фрейме данных.
  • Наконец, модель строится, обучается и затем оценивается с помощью тестовых данных.

tf.data

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

dataset = tf.data.Dataset
                 .range(100)
                 .shuffle(100, reshuffle_each_iteration=True)
                 .batch(5)
                 .repeat(5)

Подробнее о tf.data можно прочитать в Руководстве и api_docs.

В этой программе классификации после считывания CSV из pandas он затем преобразуется в набор данных с аналогичным конвейером, показанным выше. Это охватывает первые два пункта выше в бюллетенях.

URL = "./adult.data.csv"
df  = pd.read_csv(URL)
train, test = train_test_split(df, test_size=0.2)
train, val  = train_test_split(train, test_size=0.2)
# Converting Dataframes to Dataset.
def df_to_dataset(df, shuffle=True, batch_size=32):
  df = df.copy()
  labels = df.pop('good_salary')
  ds = tf.data.Dataset.from_tensor_slices((dict(df) , labels))
  if shuffle:
    ds.shuffle(buffer_size=len(df))
  ds = ds.batch(batch_size)
  return ds
#Creating Dataset for training, validation and testing datatframes.
batch_size=32
train_ds = df_to_dataset(train, shuffle=True , 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)

tf.feature_column

FeatureColumn снова является инкапсуляцией для каждого отдельного столбца внутри фрейма данных. Что он делает, так это берет каждый столбец во фрейме данных, инкапсулирует его в объект feature_column и выполняет определенные объекты преобразования. Он выполняет работу по предварительной обработке ввода в процессе машинного обучения. Всякий раз, когда новые данные поступают в модель, автоматически выполняется предварительная обработка, а затем выборка в модель. Нет необходимости в дальнейшей предварительной обработке. Установите правила один раз, а затем предоставьте данные модели. TensorFlow предоставляет множество различных feature_columns. Подробнее можно узнать в этом учебнике. Продолжаем код:

feature_columns = []
numeric_headers = ['age', 'education_num', 'fnlwgt', 'capital_gain', 'capital_loss', 'hours_per_week']
for header in numeric_headers:
  feature_columns.append(feature_column.numeric_column(header))
# embedding
# native_country
country = feature_column.categorical_column_with_vocabulary_list('native_country', df['native_country'].unique())
country_embedding = feature_column.embedding_column(country, dimension=40)
feature_columns.append(country_embedding)
#demo(country_embedding)
occupation = feature_column.categorical_column_with_vocabulary_list('occupation', df['occupation'].unique())
occupation_embedding = feature_column.embedding_column(occupation, dimension=10)
feature_columns.append(occupation_embedding)
#demo(occupation_embedding)
education = feature_column.categorical_column_with_vocabulary_list('education', df['education'].unique())
education_embedding = feature_column.embedding_column(education, dimension=20)
feature_columns.append(education_embedding)
print("*****")
#indicator cols
relationship = feature_column.categorical_column_with_vocabulary_list('relationship', df['relationship'].unique())
relationship_one_hot = feature_column.indicator_column(relationship)
feature_columns.append(relationship_one_hot)
#sex
sex = feature_column.categorical_column_with_vocabulary_list('sex', df['sex'].unique())
sex_one_hot = feature_column.indicator_column(sex)
feature_columns.append(sex_one_hot)
#race
race = feature_column.categorical_column_with_vocabulary_list('race', df['race'].unique())
race_one_hot = feature_column.indicator_column(race)
feature_columns.append(race_one_hot)
#workclass
workclass = feature_column.categorical_column_with_vocabulary_list('workclass', df['workclass'].unique())
workclass_one_hot = feature_column.indicator_column(workclass)
feature_columns.append(workclass_one_hot)
#bucketize cols
age = feature_column.numeric_column('age')
age_buckets = feature_column.bucketized_column(age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])
feature_columns.append(age_buckets)
hours_per_week = feature_column.numeric_column('hours_per_week')
hours_per_week_bucketize = feature_column.bucketized_column(hours_per_week, boundaries=[15, 20, 25, 30, 35, 40, 45, 50, 60])
feature_columns.append(hours_per_week_bucketize)
#hashed bucket
martial_status_hashed = feature_column.categorical_column_with_hash_bucket(
                  'martial_status', hash_bucket_size=1000)
martial_status_one_hot = feature_column.indicator_column(martial_status_hashed)
feature_columns.append(martial_status_one_hot)

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

Модель

И последнее, но не менее важное: создание модели. В этой статье не делается акцент на оценке модели. Я намерен сделать упор на столбец feature_column, поэтому точность может быть невысокой.

feature_layer = tf.keras.layers.DenseFeatures(feature_columns)
model = tf.keras.Sequential([
        feature_layer,
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dense(1)
])
model.compile(optimizer='adam',
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.fit(train_ds, validation_data=val_ds, epochs=10)
loss, accuracy = model.evaluate(test_ds)

Мне удалось достичь точности 81%. Теперь у меня больше мотивации попробовать больше задач классификации и освоить feature_column, а также попробовать crossed_feature_column. И еще одна вещь, которую стоит изучить, — это tf.estimator. Желание исследовать то же самое. А также я рад возможности успешно запустить вышеуказанную программу локально на графическом процессоре. Чтобы запустить программу TensorFlow на GPU, следуйте моей статье. Наслаждайтесь кодированием…