Быстрое и простое руководство по самому популярному в мире фреймворку глубокого обучения.

Обязательно ознакомьтесь с Часть первая: основы

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

Эти гибридные методы обучения уже разрабатываются Google в магазине Play для получения предложений по приложениям. Даже Youtube использует аналогичные гибридные методы обучения, чтобы предлагать видеоролики.

Код для этой статьи доступен здесь.

Широкая и глубокая сеть

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

Данные

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

Во-первых, мы собираемся определить все наши столбцы как Continuos или Категориальные.

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

Категориальные столбцы - часть конечного набора. Как мужчина или женщина, или даже из какой страны кто-то.

CATEGORICAL_COLUMNS = ["Name", "Sex", "Embarked", "Cabin"]
CONTINUOUS_COLUMNS = ["Age", "SibSp", "Parch", "Fare", "PassengerId", "Pclass"]

Поскольку мы только хотим узнать, выжил ли человек, это проблема бинарной классификации. Мы прогнозируем 1, если этот человек выживет, и 0 ... если нет :(, Затем мы создаем столбец только для нашей категории выживших.

SURVIVED_COLUMN = "Survived"

Сеть

Теперь мы можем перейти к созданию столбцов и добавлению встраиваемых слоев. Когда мы строили нашу модель, нам нужно было изменить наши категориальные столбцы на разреженные столбцы. Для наших столбцов с небольшим набором категорий, таких как Sex или Embarked (S, Q или C), мы преобразуем их в разреженные столбцы с ключами.

sex = tf.contrib.layers.sparse_column_with_keys(column_name="Sex",
                                                     keys=["female",
                                                 "male"])
  embarked = tf.contrib.layers.sparse_column_with_keys(column_name="Embarked",
                                                   keys=["C",
                                                         "S",
                                                         "Q"])

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

cabin = tf.contrib.layers.sparse_column_with_hash_bucket(
      "Cabin", hash_bucket_size=1000)
name = tf.contrib.layers.sparse_column_with_hash_bucket(
      "Name", hash_bucket_size=1000)

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

age = tf.contrib.layers.real_valued_column("Age")
passenger_id = tf.contrib.layers.real_valued_column("PassengerId")
sib_sp = tf.contrib.layers.real_valued_column("SibSp")
parch = tf.contrib.layers.real_valued_column("Parch")
fare = tf.contrib.layers.real_valued_column("Fare")
p_class = tf.contrib.layers.real_valued_column("Pclass")

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

age_buckets = tf.contrib.layers.bucketized_column(age,
                                                    boundaries=[
                                                        5, 18, 25,
                                                        30, 35, 40,
                                                        45, 50, 55,
                                                        65
                                                    ])

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

wide_columns = [sex, embarked, p_class, cabin, name, age_buckets,
                  tf.contrib.layers.crossed_column([p_class, cabin],
                                                   hash_bucket_size=int(1e4)),
                  tf.contrib.layers.crossed_column(
                      [age_buckets, sex],
                      hash_bucket_size=int(1e6)),
                  tf.contrib.layers.crossed_column([embarked, name],
                                                   hash_bucket_size=int(1e4))]

Преимущество наличия этих глубоких столбцов заключается в том, что они сводят наши редкие высокоразмерные элементы к низкоразмерным.

deep_columns = [
      tf.contrib.layers.embedding_column(sex, dimension=8),
      tf.contrib.layers.embedding_column(embarked, dimension=8),
      tf.contrib.layers.embedding_column(p_class,
                                         dimension=8),
      tf.contrib.layers.embedding_column(cabin, dimension=8),
      tf.contrib.layers.embedding_column(name, dimension=8),
      age,
      passenger_id,
      sib_sp,
      parch,
      fare,
  ]

Мы завершаем нашу функцию созданием классификатора с нашими глубокими столбцами и широкими столбцами,

return tf.contrib.learn.DNNLinearCombinedClassifier(
        linear_feature_columns=wide_columns,
        dnn_feature_columns=deep_columns,
        dnn_hidden_units=[100, 50])

Последнее, что нам нужно сделать перед запуском сети, - это создать сопоставления для наших непрерывных и категориальных столбцов. То, что мы делаем здесь, создавая эту функцию, и это стандартно для всего обучающего кода Tensorflow, - это создание функции ввода для нашего фрейма данных. Это преобразует наш фрейм данных во что-то, чем может управлять Tensorflow. Преимущество этого заключается в том, что мы можем изменять и настраивать способ создания наших тензоров. Если бы мы хотели, мы могли бы передать столбцы функций в .fit .feature .predict в виде индивидуально созданного столбца, как у нас выше с нашими функциями, но это гораздо более чистое решение.

def input_fn(df, train=False):
  """Input builder function."""
  # Creates a dictionary mapping from each continuous feature column name (k) to
  # the values of that column stored in a constant Tensor.
  continuous_cols = {k: tf.constant(df[k].values) for k in CONTINUOUS_COLUMNS}
  # Creates a dictionary mapping from each categorical feature column name (k)
  # to the values of that column stored in a tf.SparseTensor.
  categorical_cols = {k: tf.SparseTensor(
    indices=[[i, 0] for i in range(df[k].size)],
    values=df[k].values,
    shape=[df[k].size, 1])
                      for k in CATEGORICAL_COLUMNS}
  # Merges the two dictionaries into one.
  feature_cols = dict(continuous_cols)
  feature_cols.update(categorical_cols)
  # Converts the label column into a constant Tensor.
  if train:
    label = tf.constant(df[SURVIVED_COLUMN].values)
      # Returns the feature columns and the label.
    return feature_cols, label
  else:
    # so we can predict our results that don't exist in the csv
    return feature_cols

Теперь после всего этого мы можем написать нашу обучающую функцию

def train_and_eval():
  """Train and evaluate the model."""
  df_train = pd.read_csv(
      tf.gfile.Open("./train.csv"),
      skipinitialspace=True)
  df_test = pd.read_csv(
      tf.gfile.Open("./test.csv"),
      skipinitialspace=True)
  model_dir = "./models"
  print("model directory = %s" % model_dir)
  m = build_estimator(model_dir)
  m.fit(input_fn=lambda: input_fn(df_train, True), steps=200)
  print m.predict(input_fn=lambda: input_fn(df_test))
  results = m.evaluate(input_fn=lambda: input_fn(df_train, True), steps=1)
  for key in sorted(results):
    print("%s: %s" % (key, results[key]))

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

Эти CSV преобразуются в тензоры с использованием нашего input_fn с помощью лямбда. мы строим наш оценщик, затем печатаем наши прогнозы и распечатываем наши результаты оценки.

Полученные результаты

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

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

Заключение

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

Изначально размещено на Веб-сайте Camron