앞서 다루었던 Wide&Deep
은 회귀모델(Regression)을 이용한 변수들의 저차원 관계(low-dim. interaction)와 DNN을 이용한 변수들의 고차원 관계(high-dime. interaction)를 결합한 모델(joint model)이다. Wide&Deep은 Wide인 regression 모델 생성 과정에서 전문가의 feature engineering을 필요로한다는 문제점이 있다. DeepFM
에서는 Wide 부분을 FM
으로 대체하여 feature engineering 없이 학습 가능한 모델을 제시한다.
모델의 전체 구조는 위 그림과 같다. 왼편의 FM Layer
는 저차원 변수 관계(feature interaction)를, 오른쪽의 Hidden Layer
는 고차원 변수 관계를 학습한다. 두 레이어는 같은 Dense Embeddings
를 공유하며(논문에서 의미하는 share same input
) 결과는 Output Units
에서 계산된다. 각 레이어의 결과를 구하는 식은 아래와 같다.
FM
DNN
Output
※ CTR 시리즈의 모든 코드는
FuxiCTR
을 참고했으며 함수 구조와 이름 등은 개인적으로 수정하여 사용하였다.
feature_dict
은 각 변수의 설명이 들어있는 dict()이다. (ex, Dict[str, Dict[str, int]]) EmbeddingDict()
은 각 필드의 임베딩 벡터(embedding vector)를 반환하는 ModuleDict()
으로 아웃풋은 [배치(batch) 크기, 필드 수, 임베딩 크기] 형태이다.
DeepFM
은 FM
과 DNN
을 각각 계산하여 더한 후 nn.Sigmoid
를 취해주면 된다. (nn.BCEWithLogitsLoss
를 사용했기 때문에 코드에 sigmoid를 포함되어있지 않다.) FMLayer()
, DNNLayer()
는 각각 앞의 FM, Wide&Deep 파트에서 다루었기 때문에 생략한다.
class DeepFM(BaseModel):
def __init__(self, feature_dict, hidden_dim_list, embed_dim=CFG.embed_dim):
super(DeepFM, self).__init__()
self._num_fields = len(feature_dict)
self.embedding = EmbeddingDict(feature_dict=feature_dict)
self.fm = FMLayer(feature_dict=feature_dict)
self.dnn = DNNLayer(input_dim = self._num_fields * embed_dim,
hidden_dim_list = hidden_dim_list)
self.compile(CFG.optimizer, CFG.loss, CFG.learning_rate)
self.init_params()
self.model_to_device()
def forward(self, inputs):
X, y = self.inputs_to_device(inputs)
X_emb = self.embedding(X)
y_pred = self.fm(X, X_emb) + self.dnn(X_emb.flatten(start_dim=1))
return {'y_true': y, 'y_pred': y_pred}
DeepFM: A Factorization-Machine based Neural Network for CTR Prediction
FuxiCTR Github