tensorflow2实现deepfm
1.deepfm的概述
deepfm是wide&deep的衍生模型,将wide&deep模型中的wide侧替换成FM模型,从而实现二阶的特征组合,增强模型的“记忆性”,deep侧依旧使用传统的DNN模型,增强模型的泛化能力。
2.FM侧的二阶组合tensorflow实现
class FM(Layer):
"""Factorization Machine models pairwise (order-2) feature interactions
without linear term and bias.
Input shape
- 3D tensor with shape: ``(batch_size,field_size,embedding_size)``.
Output shape
- 2D tensor with shape: ``(batch_size, 1)``.
"""
def __init__(self,):
super(FM, self).__init__()
def build(self, input_shape):
if len(input_shape) != 3:
raise ValueError("Unexpected inputs dimensions % d,\
expect to be 3 dimensions" % (len(input_shape)))
def call(self, inputs):
if K.ndim(inputs) != 3:
raise ValueError(
"Unexpected inputs dimensions %d, expect to be 3 dimensions"
% (K.ndim(inputs)))
concated_embeds_value = inputs
square_of_sum = tf.square(tf.math.reduce_sum(
concated_embeds_value, axis=1, keepdims=True)) # (None,1,k)
sum_of_square = tf.math.reduce_sum(
concated_embeds_value * concated_embeds_value, axis=1, keepdims=True) # (None,1,k)
cross_term = square_of_sum - sum_of_square
cross_term = 0.5 * tf.math.reduce_sum(cross_term, axis=2, keepdims=False) # (None,1)
return cross_term
def compute_output_shape(self, input_shape):
return (None, 1)
FM的模块输入的一个3维的embedding向量,输出是个2维的向量,同时基于矩阵的维度对计算进行了优化,减缓了不必要的计算消耗。
3.deepfm的实现
# -*- coding:utf-8 -*-
"""
deepfm
"""
from itertools import chain
import tensorflow as tf
from utils import build_input_features,get_linear_logit,get_sparse_emb_dict
from Layers.core import DNN
from Layers.interaction import FM
from tensorflow.keras.layers import Add,Activation,Flatten,Concatenate,Dense
from utils import get_dense_input
def DeepFM(linear_feature_columns, dnn_feature_columns, dnn_hidden_units=(128,64,16),
l2_reg_linear=0.00001, l2_reg_embedding=0.00001, l2_reg_dnn=0, seed=1024, dnn_dropout=0,
dnn_activation='relu', dnn_use_bn=True, task='binary'):
"""Instantiates the DeepFM Network architecture.
:param linear_feature_columns: An iterable containing all the features used by linear part of the model.
:param dnn_feature_columns: An iterable containing all the features used by deep part of the model.
:param fm_group: list, group_name of features that will be used to do feature interactions.
:param dnn_hidden_units: list,list of positive integer or empty list, the layer number and units in each layer of DNN
:param l2_reg_linear: float. L2 regularizer strength applied to linear part
:param l2_reg_embedding: float. L2 regularizer strength applied to embedding vector
:param l2_reg_dnn: float. L2 regularizer strength applied to DNN
:param seed: integer ,to use as random seed.
:param dnn_dropout: float in [0,1), the probability we will drop out a given DNN coordinate.
:param dnn_activation: Activation function to use in DNN
:param dnn_use_bn: bool. Whether use BatchNormalization before activation or not in DNN
:param task: str, ``"binary"`` for binary logloss or ``"regression"`` for regression loss
:return: A Keras model instance.
"""
features_inputs = build_input_features(linear_feature_columns + dnn_feature_columns)
inputs_list = list(features_inputs.values())
# LR
linear_logit = get_linear_logit(features_inputs, linear_feature_columns, seed=seed, prefix='linear',
l2_reg=l2_reg_linear)
# FM
sparse_emb_dict = get_sparse_emb_dict(features_inputs,dnn_feature_columns,l2_reg_embedding,prefix='sparse_')
fm = FM()
fm_logit = fm(tf.keras.layers.Concatenate(axis=1)(sparse_emb_dict.values()))
# print(sparse_emb_dict)
# DNN
dense_input = get_dense_input(features_inputs, dnn_feature_columns)
dense_input = Concatenate(axis=1)(dense_input)
dnn_input = tf.concat([Flatten()(Concatenate(axis=1)(sparse_emb_dict.values())),dense_input],axis=1)
dnn_output = DNN(dnn_hidden_units, dnn_activation, l2_reg_dnn, dnn_dropout,
dnn_use_bn, seed)(dnn_input)
dnn_logit = Dense(1,use_bias=True, activation='NOne',
name='dnn_output',
kernel_regularizer=tf.keras.regularizers.l2(l2_reg_dnn),
bias_regularizer=tf.keras.regularizers.l2(l2_reg_dnn),
)(dnn_output)
# concat and activation
out_put =Add()([linear_logit,fm_logit,dnn_logit])
out_put = Activation('sigmoid')(out_put)
model = tf.keras.models.Model(inputs=inputs_list, outputs=out_put)
return model
可以看出:deepfm = FM + DNN = LR + 二阶组合 + DNN