[DeepFM] DeepFM

KIDA·2023년 1월 30일
0

CTR

목록 보기
5/8

Intro

앞서 다루었던 Wide&Deep 은 회귀모델(Regression)을 이용한 변수들의 저차원 관계(low-dim. interaction)와 DNN을 이용한 변수들의 고차원 관계(high-dime. interaction)를 결합한 모델(joint model)이다. Wide&Deep은 Wide인 regression 모델 생성 과정에서 전문가의 feature engineering을 필요로한다는 문제점이 있다. DeepFM에서는 Wide 부분을 FM으로 대체하여 feature engineering 없이 학습 가능한 모델을 제시한다.

Data

  • xRd\mathbf{x} \in \mathbb{R}^{d}: 보통 매우 스파스(sparse)한 고차원 데이터이다.
  • y{0,1}y \in \{0, 1\}: binary label

Model

모델의 전체 구조는 위 그림과 같다. 왼편의 FM Layer는 저차원 변수 관계(feature interaction)를, 오른쪽의 Hidden Layer는 고차원 변수 관계를 학습한다. 두 레이어는 같은 Dense Embeddings를 공유하며(논문에서 의미하는 share same input) 결과는 Output Units에서 계산된다. 각 레이어의 결과를 구하는 식은 아래와 같다.

  • FM

    yFM=<w,x>+j1=1dj2=j1+1d<Vi,Vj>xj1xj2y_{FM} = <w,x> + \sum_{j_1=1}^{d}\sum_{j_2=j_1+1}^{d} <V_i, V_j>x_{j_1}x_{j_2}
  • DNN

    a(0)=[e1,e2,...,em]a^{(0)} = [e_1, e_2, ..., e_m]
    a(l+1)=σ(W(l)a(l)+b(l))a^{(l+1)} = \sigma(W^{(l)}a^{(l)} + b^{(l)})
  • Output

    y^=sigmoid(yFM+yDNN)\hat{y} = sigmoid(y_{FM} + y_{DNN})

Note

  1. DNN 파트에서 hidden layer의 수를 무작정 크게 잡을 필요 없다. 일단은 2~3개로 시작해보자.
  2. Dropout을 적절히 사용하면 성능 향상에 유의미한 영향을 준다.
  3. 앞에서 다루었던 것처럼 FM은 field에 관계없이 모든 feature의 interaction을 계산하기 때문에 학습 성능이 떨어진다. FM을 FFM, FwFM 등 다양하게 변화시켜 사용해보자.

Code

CTR 시리즈의 모든 코드는 FuxiCTR을 참고했으며 함수 구조와 이름 등은 개인적으로 수정하여 사용하였다.

  1. feature_dict은 각 변수의 설명이 들어있는 dict()이다. (ex, Dict[str, Dict[str, int]]) EmbeddingDict()은 각 필드의 임베딩 벡터(embedding vector)를 반환하는 ModuleDict()으로 아웃풋은 [배치(batch) 크기, 필드 수, 임베딩 크기] 형태이다.

  2. DeepFMFMDNN을 각각 계산하여 더한 후 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

profile
까먹지 않기 위한 노트 (ว˙∇˙)ง

0개의 댓글