심층 및 교차 네트워크 (DCN)

TensorFlow.org에서보기 Google Colab에서 실행 GitHub에서 소스보기 노트북 다운로드

이 자습서는 심층 및 교차 네트워크 (DCN)를 사용하여 기능 교차를 효과적으로 학습하는 방법을 보여줍니다.

배경

특성 교차 란 무엇이며 왜 중요한가요? 블렌더를 고객에게 판매하기 위해 추천 시스템을 구축하고 있다고 상상해보십시오. 그런 다음 구입 _ purchased_bananaspurchased_cooking_books _ 요리 _ 책과 같은 고객의 과거 구매 내역 또는 지리적 기능이 단일 기능입니다. 바나나 요리 책을 모두 구입했다면이 고객은 권장 블렌더를 클릭 할 가능성이 높습니다. purchased_bananaspurchased_cooking_books 의 조합을 기능 교차 라고하며 개별 기능 이외의 추가 상호 작용 정보를 제공합니다.

특성 교차 학습의 어려움은 무엇입니까? 웹 스케일 애플리케이션에서 데이터는 대부분 범주 형이므로 크고 희소 한 기능 공간으로 이어집니다. 이 설정에서 효과적인 특성 교차를 식별하려면 종종 수동 특성 엔지니어링 또는 철저한 검색이 필요합니다. 기존의 피드 포워드 다층 퍼셉트론 (MLP) 모델은 범용 함수 근사값입니다. 그러나 2 차 또는 3 차 특성 교차 [ 1 , 2 ]조차도 효율적으로 근사 할 수 없습니다.

심층 및 교차 네트워크 (DCN) 란 무엇입니까? DCN은 명시적이고 경계가있는 교차 특성을보다 효과적으로 학습하도록 설계되었습니다. 입력 계층 (일반적으로 임베딩 계층)으로 시작하여 명시 적 기능 상호 작용을 모델링하는 여러 교차 계층이 포함 된 교차 네트워크 가 뒤 따르고 암시 적 기능 상호 작용을 모델링하는 심층 네트워크 와 결합됩니다.

  • 교차 네트워크. 이것이 DCN의 핵심입니다. 각 레이어에서 특징 교차를 명시 적으로 적용하고 레이어 깊이에 따라 가장 높은 다항식 차수가 증가합니다. 다음 그림은 $ (i + 1) $ 번째 교차 레이어를 보여줍니다.
  • 딥 네트워크. 전통적인 피드 포워드 다층 퍼셉트론 (MLP)입니다.

그런 다음 딥 네트워크와 교차 네트워크가 결합되어 DCN [ 1 ]을 형성합니다. 일반적으로 우리는 교차 네트워크 (스택 구조) 위에 깊은 네트워크를 쌓을 수 있습니다. 병렬로 배치 할 수도 있습니다 (병렬 구조).

다음에서는 장난감 예제를 통해 DCN의 장점을 먼저 보여준 다음 MovieLen-1M 데이터 세트를 사용하여 DCN을 활용하는 몇 가지 일반적인 방법을 안내합니다.

먼저이 colab에 필요한 패키지를 설치하고 가져 오겠습니다.

pip install -q tensorflow-recommenders
pip install -q --upgrade tensorflow-datasets
import pprint

%matplotlib inline
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds

import tensorflow_recommenders as tfrs

장난감 예

DCN의 이점을 설명하기 위해 간단한 예를 살펴 보겠습니다. 고객이 블렌더 광고를 클릭 할 가능성을 모델링하려는 데이터 세트가 있다고 가정 해 보겠습니다. 그 기능과 레이블은 다음과 같습니다.

기능 / 라벨 기술 값 유형 / 범위
$ x_1 $ = 국가 이 고객이 거주하는 국가 Int in [0, 199]
$ x_2 $ = 바나나 고객이 구매 한 바나나 # 개 Int in [0, 23]
$ x_3 $ = 요리 책 고객이 구매 한 요리 책 # 개 Int in [0, 5]
$ y $ 블렌더 광고를 클릭 할 가능성 -

그런 다음 데이터가 다음 기본 분포를 따르도록합니다.

$$y = f(x_1, x_2, x_3) = 0.1x_1 + 0.4x_2+0.7x_3 + 0.1x_1x_2+3.1x_2x_3+0.1x_3^2$$

$ y $ 가능성은 $ x_i $의 기능뿐만 아니라 $ x_i $ 간의 곱셈 상호 작용에도 선형 적으로 의존합니다. 우리의 경우 믹서기 ($ y $)를 구매할 가능성은 바나나 ($ x_2 $) 또는 요리 책 ($ x_3 $)을 구매하는 것뿐만 아니라 바나나와 요리 책을 함께 구매 ($ x_2x_3 $)에 달려 있다고 말할 수 있습니다. ).

이에 대한 데이터를 다음과 같이 생성 할 수 있습니다.

합성 데이터 생성

먼저 위에서 설명한대로 $ f (x_1, x_2, x_3) $를 정의합니다.

def get_mixer_data(data_size=100_000, random_seed=42):
  # We need to fix the random seed
  # to make colab runs repeatable.
  rng = np.random.RandomState(random_seed)
  country = rng.randint(200, size=[data_size, 1]) / 200.
  bananas = rng.randint(24, size=[data_size, 1]) / 24.
  coockbooks = rng.randint(6, size=[data_size, 1]) / 6.

  x = np.concatenate([country, bananas, coockbooks], axis=1)

  # # Create 1st-order terms.
  y = 0.1 * country + 0.4 * bananas + 0.7 * coockbooks

  # Create 2nd-order cross terms.
  y += 0.1 * country * bananas + 3.1 * bananas * coockbooks + (
        0.1 * coockbooks * coockbooks)

  return x, y

분포를 따르는 데이터를 생성하고 데이터를 학습용 90 %와 테스트 용 10 %로 나눕니다.

x, y = get_mixer_data()
num_train = 90000
train_x = x[:num_train]
train_y = y[:num_train]
eval_x = x[num_train:]
eval_y = y[num_train:]

모델 구성

우리는 교차 네트워크가 추천자에게 가져올 수있는 이점을 설명하기 위해 교차 네트워크와 심층 네트워크를 모두 시험해 볼 것입니다. 방금 생성 한 데이터에는 2 차 기능 상호 작용 만 포함되어 있으므로 단일 계층 교차 네트워크로 설명하는 것으로 충분합니다. 고차 기능 상호 작용을 모델링하려는 경우 여러 교차 계층을 쌓고 다중 계층 교차 네트워크를 사용할 수 있습니다. 우리가 구축 할 두 가지 모델은 다음과 같습니다.

  1. 교차 레이어가 하나 뿐인 교차 네트워크
  2. 더 넓고 더 깊은 ReLU 계층이있는 심층 네트워크.

먼저 손실이 평균 제곱 오차 인 통합 모델 클래스를 빌드합니다.

class Model(tfrs.Model):

  def __init__(self, model):
    super().__init__()
    self._model = model
    self._logit_layer = tf.keras.layers.Dense(1)

    self.task = tfrs.tasks.Ranking(
      loss=tf.keras.losses.MeanSquaredError(),
      metrics=[
        tf.keras.metrics.RootMeanSquaredError("RMSE")
      ]
    )

  def call(self, x):
    x = self._model(x)
    return self._logit_layer(x)

  def compute_loss(self, features, training=False):
    x, labels = features
    scores = self(x)

    return self.task(
        labels=labels,
        predictions=scores,
    )

그런 다음 교차 네트워크 (크기 3의 교차 계층 1 개) 및 ReLU 기반 DNN (계층 크기 [512, 256, 128])을 지정합니다.

crossnet = Model(tfrs.layers.dcn.Cross())
deepnet = Model(
    tf.keras.Sequential([
      tf.keras.layers.Dense(512, activation="relu"),
      tf.keras.layers.Dense(256, activation="relu"),
      tf.keras.layers.Dense(128, activation="relu")
    ])
)

모델 훈련

이제 데이터와 모델이 준비되었으므로 모델을 훈련 할 것입니다. 먼저 모델 학습을 준비하기 위해 데이터를 섞고 일괄 처리합니다.

train_data = tf.data.Dataset.from_tensor_slices((train_x, train_y)).batch(1000)
eval_data = tf.data.Dataset.from_tensor_slices((eval_x, eval_y)).batch(1000)

그런 다음 Epoch의 수와 학습률을 정의합니다.

epochs = 100
learning_rate = 0.4

좋습니다. 이제 모든 것이 준비되었으며 모델을 컴파일하고 학습 시키겠습니다. 모델이 어떻게 진행되는지 보려면 verbose=True 설정할 수 있습니다.

crossnet.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate))
crossnet.fit(train_data, epochs=epochs, verbose=False)
WARNING:tensorflow:Layer model is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because its dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.

WARNING:tensorflow:Layer ranking is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because its dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.
<tensorflow.python.keras.callbacks.History at 0x7fb9dc772da0>
deepnet.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate))
deepnet.fit(train_data, epochs=epochs, verbose=False)
WARNING:tensorflow:Layer model_1 is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because its dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.

WARNING:tensorflow:Layer ranking_1 is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because its dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.
<tensorflow.python.keras.callbacks.History at 0x7fb9dc4a1860>

모델 평가

평가 데이터 세트에서 모델 성능을 확인하고 평균 제곱근 오차 (RMSE, 낮을수록 좋음)를보고합니다.

crossnet_result = crossnet.evaluate(eval_data, return_dict=True, verbose=False)
print(f"CrossNet(1 layer) RMSE is {crossnet_result['RMSE']:.4f} "
      f"using {crossnet.count_params()} parameters.")

deepnet_result = deepnet.evaluate(eval_data, return_dict=True, verbose=False)
print(f"DeepNet(large) RMSE is {deepnet_result['RMSE']:.4f} "
      f"using {deepnet.count_params()} parameters.")
CrossNet(1 layer) RMSE is 0.0003 using 18 parameters.
DeepNet(large) RMSE is 0.0350 using 166403 parameters.

교차 네트워크가 ReLU 기반 DNN 보다 더 적은 매개 변수로 더 낮은 RMSE를 달성했음을 알 수 있습니다 . 이것은 교차 네트워크 학습에서 교차 네트워크의 효율성을 제안했습니다.

모델 이해

우리는 이미 데이터에서 어떤 특성 교차가 중요한지 알고 있습니다. 모델이 실제로 중요한 특성 교차를 학습했는지 확인하는 것은 재미있을 것입니다. 이는 DCN에서 학습 된 가중치 행렬을 시각화하여 수행 할 수 있습니다. 가중치 $ W_ {ij} $는 $ x_i $ 기능과 $ x_j $ 간의 상호 작용에 대해 학습 된 중요성을 나타냅니다.

mat = crossnet._model._dense.kernel
features = ["country", "purchased_bananas", "purchased_cookbooks"]

plt.figure(figsize=(9,9))
im = plt.matshow(np.abs(mat.numpy()), cmap=plt.cm.Blues)
ax = plt.gca()
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(im, cax=cax)
cax.tick_params(labelsize=10) 
_ = ax.set_xticklabels([''] + features, rotation=45, fontsize=10)
_ = ax.set_yticklabels([''] + features, fontsize=10)
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/ipykernel_launcher.py:11: UserWarning: FixedFormatter should only be used together with FixedLocator
  # This is added back by InteractiveShellApp.init_path()
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/ipykernel_launcher.py:12: UserWarning: FixedFormatter should only be used together with FixedLocator
  if sys.path[0] == '':
<Figure size 648x648 with 0 Axes>

png

더 어두운 색상은 학습 된 상호 작용이 더 강함을 나타냅니다.이 경우 모델이 바바나와 요리 책을 함께 구입하는 것이 중요하다는 것을 알게되었습니다.

더 복잡한 합성 데이터에 관심이 있으시면 이 문서 를 확인하십시오.

Movielens 1M 예

이제 실제 데이터 세트 인 Movielens 1M [ 3 ]에서 DCN의 효과를 조사합니다. Movielens 1M은 추천 연구를위한 인기있는 데이터 세트입니다. 사용자 관련 기능 및 영화 관련 기능을 고려하여 사용자의 영화 등급을 예측합니다. 이 데이터 세트를 사용하여 DCN을 활용하는 몇 가지 일반적인 방법을 설명합니다.

데이터 처리

데이터 처리 절차는 기본 순위 자습서 와 유사한 절차를 따릅니다.

ratings = tfds.load("movie_lens/100k-ratings", split="train")
ratings = ratings.map(lambda x: {
    "movie_id": x["movie_id"],
    "user_id": x["user_id"],
    "user_rating": x["user_rating"],
    "user_gender": int(x["user_gender"]),
    "user_zip_code": x["user_zip_code"],
    "user_occupation_text": x["user_occupation_text"],
    "bucketized_user_age": int(x["bucketized_user_age"]),
})
WARNING:absl:The handle "movie_lens" for the MovieLens dataset is deprecated. Prefer using "movielens" instead.
Downloading and preparing dataset movie_lens/100k-ratings/0.1.0 (download: 4.70 MiB, generated: 32.41 MiB, total: 37.10 MiB) to /home/kbuilder/tensorflow_datasets/movie_lens/100k-ratings/0.1.0...
Shuffling and writing examples to /home/kbuilder/tensorflow_datasets/movie_lens/100k-ratings/0.1.0.incompleteBFZ1VZ/movie_lens-train.tfrecord
Dataset movie_lens downloaded and prepared to /home/kbuilder/tensorflow_datasets/movie_lens/100k-ratings/0.1.0. Subsequent calls will reuse this data.

다음으로 데이터를 훈련 용 80 %와 테스트 용 20 %로 무작위로 나눕니다.

tf.random.set_seed(42)
shuffled = ratings.shuffle(100_000, seed=42, reshuffle_each_iteration=False)

train = shuffled.take(80_000)
test = shuffled.skip(80_000).take(20_000)

그런 다음 각 기능에 대한 어휘를 만듭니다.

feature_names = ["movie_id", "user_id", "user_gender", "user_zip_code",
                 "user_occupation_text", "bucketized_user_age"]

vocabularies = {}

for feature_name in feature_names:
  vocab = ratings.batch(1_000_000).map(lambda x: x[feature_name])
  vocabularies[feature_name] = np.unique(np.concatenate(list(vocab)))

모델 구성

우리가 구축 할 모델 아키텍처는 임베딩 레이어로 시작하며,이 레이어는 교차 네트워크에 공급 된 후 심층 네트워크가 이어집니다. 임베딩 차원은 모든 기능에 대해 32로 설정됩니다. 기능마다 다른 임베딩 크기를 사용할 수도 있습니다.

class DCN(tfrs.Model):

  def __init__(self, use_cross_layer, deep_layer_sizes, projection_dim=None):
    super().__init__()

    self.embedding_dimension = 32

    str_features = ["movie_id", "user_id", "user_zip_code",
                    "user_occupation_text"]
    int_features = ["user_gender", "bucketized_user_age"]

    self._all_features = str_features + int_features
    self._embeddings = {}

    # Compute embeddings for string features.
    for feature_name in str_features:
      vocabulary = vocabularies[feature_name]
      self._embeddings[feature_name] = tf.keras.Sequential(
          [tf.keras.layers.experimental.preprocessing.StringLookup(
              vocabulary=vocabulary, mask_token=None),
           tf.keras.layers.Embedding(len(vocabulary) + 1,
                                     self.embedding_dimension)
    ])

    # Compute embeddings for int features.
    for feature_name in int_features:
      vocabulary = vocabularies[feature_name]
      self._embeddings[feature_name] = tf.keras.Sequential(
          [tf.keras.layers.experimental.preprocessing.IntegerLookup(
              vocabulary=vocabulary, mask_value=None),
           tf.keras.layers.Embedding(len(vocabulary) + 1,
                                     self.embedding_dimension)
    ])

    if use_cross_layer:
      self._cross_layer = tfrs.layers.dcn.Cross(
          projection_dim=projection_dim,
          kernel_initializer="glorot_uniform")
    else:
      self._cross_layer = None

    self._deep_layers = [tf.keras.layers.Dense(layer_size, activation="relu")
      for layer_size in deep_layer_sizes]

    self._logit_layer = tf.keras.layers.Dense(1)

    self.task = tfrs.tasks.Ranking(
      loss=tf.keras.losses.MeanSquaredError(),
      metrics=[tf.keras.metrics.RootMeanSquaredError("RMSE")]
    )

  def call(self, features):
    # Concatenate embeddings
    embeddings = []
    for feature_name in self._all_features:
      embedding_fn = self._embeddings[feature_name]
      embeddings.append(embedding_fn(features[feature_name]))

    x = tf.concat(embeddings, axis=1)

    # Build Cross Network
    if self._cross_layer is not None:
      x = self._cross_layer(x)

    # Build Deep Network
    for deep_layer in self._deep_layers:
      x = deep_layer(x)

    return self._logit_layer(x)

  def compute_loss(self, features, training=False):
    labels = features.pop("user_rating")
    scores = self(features)
    return self.task(
        labels=labels,
        predictions=scores,
    )

모델 훈련

훈련 및 테스트 데이터를 섞고 배치하고 캐시합니다.

cached_train = train.shuffle(100_000).batch(8192).cache()
cached_test = test.batch(4096).cache()

모델을 여러 번 실행하고 여러 실행에서 모델의 RMSE 평균과 표준 편차를 반환하는 함수를 정의 해 보겠습니다.

def run_models(use_cross_layer, deep_layer_sizes, projection_dim=None, num_runs=5):
  models = []
  rmses = []

  for i in range(num_runs):
    model = DCN(use_cross_layer=use_cross_layer,
                deep_layer_sizes=deep_layer_sizes,
                projection_dim=projection_dim)
    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate))
    models.append(model)

    model.fit(cached_train, epochs=epochs, verbose=False)
    metrics = model.evaluate(cached_test, return_dict=True)
    rmses.append(metrics["RMSE"])

  mean, stdv = np.average(rmses), np.std(rmses)

  return {"model": models, "mean": mean, "stdv": stdv}

모델에 대한 몇 가지 하이퍼 매개 변수를 설정합니다. 이러한 하이퍼 매개 변수는 데모 목적으로 모든 모델에 대해 전역 적으로 설정됩니다. 각 모델에 대해 최상의 성능을 얻거나 모델간에 공정한 비교를 수행하려면 하이퍼 매개 변수를 미세 조정하는 것이 좋습니다. 모델 아키텍처와 최적화 체계는 서로 얽혀 있음을 기억하십시오.

epochs = 8
learning_rate = 0.01

DCN (스택). 먼저 스택 구조로 DCN 모델을 훈련합니다. 즉, 입력이 교차 네트워크에 공급 된 후 심층 네트워크로 전달됩니다.

dcn_result = run_models(use_cross_layer=True,
                        deep_layer_sizes=[192, 192])
5/5 [==============================] - 0s 15ms/step - RMSE: 0.9306 - loss: 0.8662 - regularization_loss: 0.0000e+00 - total_loss: 0.8662
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9339 - loss: 0.8725 - regularization_loss: 0.0000e+00 - total_loss: 0.8725
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9326 - loss: 0.8702 - regularization_loss: 0.0000e+00 - total_loss: 0.8702
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9350 - loss: 0.8750 - regularization_loss: 0.0000e+00 - total_loss: 0.8750
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9339 - loss: 0.8729 - regularization_loss: 0.0000e+00 - total_loss: 0.8729

낮은 순위의 DCN. 교육 및 제공 비용을 줄이기 위해 낮은 순위 기술을 활용하여 DCN 가중치 행렬을 근사합니다. 순위는 projection_dim 인수를 통해 전달됩니다. projection_dim 이 작을수록 비용이 낮아집니다. 비용을 줄이려면 projection_dim 이 (입력 크기) / 2보다 작아야합니다. 실제로 우리는 랭크 (입력 크기) / 4와 함께 낮은 랭크 DCN을 사용하여 전체 랭크 DCN의 정확도를 일관되게 유지하는 것을 관찰했습니다.

dcn_lr_result = run_models(use_cross_layer=True,
                           projection_dim=20,
                           deep_layer_sizes=[192, 192])
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9307 - loss: 0.8669 - regularization_loss: 0.0000e+00 - total_loss: 0.8669
5/5 [==============================] - 0s 4ms/step - RMSE: 0.9312 - loss: 0.8668 - regularization_loss: 0.0000e+00 - total_loss: 0.8668
5/5 [==============================] - 0s 4ms/step - RMSE: 0.9304 - loss: 0.8667 - regularization_loss: 0.0000e+00 - total_loss: 0.8667
5/5 [==============================] - 0s 4ms/step - RMSE: 0.9334 - loss: 0.8718 - regularization_loss: 0.0000e+00 - total_loss: 0.8718
5/5 [==============================] - 0s 4ms/step - RMSE: 0.9300 - loss: 0.8658 - regularization_loss: 0.0000e+00 - total_loss: 0.8658

DNN. 동일한 크기의 DNN 모델을 참조로 훈련합니다.

dnn_result = run_models(use_cross_layer=False,
                        deep_layer_sizes=[192, 192, 192])
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9460 - loss: 0.8985 - regularization_loss: 0.0000e+00 - total_loss: 0.8985
5/5 [==============================] - 0s 4ms/step - RMSE: 0.9358 - loss: 0.8773 - regularization_loss: 0.0000e+00 - total_loss: 0.8773
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9392 - loss: 0.8842 - regularization_loss: 0.0000e+00 - total_loss: 0.8842
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9362 - loss: 0.8772 - regularization_loss: 0.0000e+00 - total_loss: 0.8772
5/5 [==============================] - 0s 3ms/step - RMSE: 0.9377 - loss: 0.8798 - regularization_loss: 0.0000e+00 - total_loss: 0.8798

테스트 데이터에서 모델을 평가하고 5 회 실행 중 평균 및 표준 편차를보고합니다.

print("DCN            RMSE mean: {:.4f}, stdv: {:.4f}".format(
    dcn_result["mean"], dcn_result["stdv"]))
print("DCN (low-rank) RMSE mean: {:.4f}, stdv: {:.4f}".format(
    dcn_lr_result["mean"], dcn_lr_result["stdv"]))
print("DNN            RMSE mean: {:.4f}, stdv: {:.4f}".format(
    dnn_result["mean"], dnn_result["stdv"]))
DCN            RMSE mean: 0.9332, stdv: 0.0015
DCN (low-rank) RMSE mean: 0.9312, stdv: 0.0012
DNN            RMSE mean: 0.9390, stdv: 0.0037

DCN은 ReLU 레이어를 사용하는 동일한 크기의 DNN보다 더 나은 성능을 달성했습니다. 또한 낮은 등급의 DCN은 정확도를 유지하면서 매개 변수를 줄일 수있었습니다.

DCN에 대해 자세히 알아보십시오. 위에서 설명한 것 외에도 DCN을 활용하는 더 창의적이지만 실질적으로 유용한 방법이 있습니다 [ 1 ].

  • 병렬 구조의 DCN . 입력은 교차 네트워크 및 심층 네트워크에 병렬로 공급됩니다.

  • 교차 레이어 연결. 입력은 상호 보완적인 특성 교차를 캡처하기 위해 여러 교차 레이어에 병렬로 공급됩니다.

왼쪽 : 병렬 구조의 DCN; 오른쪽 : 교차 레이어 연결.

모델 이해

DCN의 가중치 행렬 $ W $는 모델이 중요하다고 배운 특징이 무엇인지 보여줍니다. 이전 장난감 예에서 $ i $ -th와 $ j $ -th 기능 간의 상호 작용의 중요성은 $ W $의 ($ i, j $)-번째 요소에 의해 포착됩니다.

여기서 조금 다른 점은 기능 임베딩이 크기 1이 아닌 32 크기라는 것입니다. 따라서 중요성은 차원 인 $ (i, j) $-th 블록 $ W_ {i, j} $에 의해 특성화됩니다. 32 x 32. 다음에서 우리는 각 블록의 Frobenius 노름 [ 4 ] $ || W_ {i, j} || _F $를 시각화하고 더 큰 노름은 더 높은 중요성을 제안합니다 (특징의 임베딩이 유사하다고 가정). 저울).

블록 표준 외에도 전체 행렬 또는 각 블록의 평균 / 중앙값 / 최대 값을 시각화 할 수도 있습니다.

model = dcn_result["model"][0]
mat = model._cross_layer._dense.kernel
features = model._all_features

block_norm = np.ones([len(features), len(features)])

dim = model.embedding_dimension

# Compute the norms of the blocks.
for i in range(len(features)):
  for j in range(len(features)):
    block = mat[i * dim:(i + 1) * dim,
                j * dim:(j + 1) * dim]
    block_norm[i,j] = np.linalg.norm(block, ord="fro")

plt.figure(figsize=(9,9))
im = plt.matshow(block_norm, cmap=plt.cm.Blues)
ax = plt.gca()
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(im, cax=cax)
cax.tick_params(labelsize=10) 
_ = ax.set_xticklabels([""] + features, rotation=45, ha="left", fontsize=10)
_ = ax.set_yticklabels([""] + features, fontsize=10)
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/ipykernel_launcher.py:23: UserWarning: FixedFormatter should only be used together with FixedLocator
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/ipykernel_launcher.py:24: UserWarning: FixedFormatter should only be used together with FixedLocator
<Figure size 648x648 with 0 Axes>

png

이것이이 콜랩의 전부입니다! DCN의 몇 가지 기본 사항과이를 활용하는 일반적인 방법을 즐겁게 배우 셨기를 바랍니다. 더 자세히 알고 싶다면 DCN-v1-paper , DCN-v2-paper 라는 두 가지 관련 문서를 확인하십시오.


참고 문헌

DCN V2 : 시스템 순위를 매기기위한 웹 규모 학습을위한 향상된 심층 및 교차 네트워크 및 실습 .
Ruoxi Wang, Rakesh Shivanna, Derek Zhiyuan Cheng, Sagar Jain, Dong Lin, Lichan Hong, Ed Chi. (2020)

광고 클릭 예측을위한 심층 및 교차 네트워크 .
Ruoxi Wang, Bin Fu, Gang Fu, Mingliang Wang. (AdKDD 2017)