forked from ZiyaoGeng/RecLearn
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodel.py
More file actions
130 lines (114 loc) · 4.94 KB
/
Copy pathmodel.py
File metadata and controls
130 lines (114 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
Created on July 13, 2020
model: Deep & Cross Network for Ad Click Predictions
@author: Ziyao Geng
"""
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import Input
from tensorflow.keras.regularizers import l2
from tensorflow.keras.layers import Embedding, Dense, Layer, Dropout
class CrossNetwork(Layer):
"""
Cross Network
"""
def __init__(self, layer_num, reg_w=1e-4, reg_b=1e-4):
"""
:param layer_num: A scalar. The depth of cross network
:param reg_w: A scalar. The regularizer of w
:param reg_b: A scalar. The regularizer of b
"""
super(CrossNetwork, self).__init__()
self.layer_num = layer_num
self.reg_w = reg_w
self.reg_b = reg_b
def build(self, input_shape):
dim = int(input_shape[-1])
self.cross_weights = [
self.add_weight(name='w_' + str(i),
shape=(dim, 1),
initializer='random_uniform',
regularizer=l2(self.reg_w),
trainable=True
)
for i in range(self.layer_num)]
self.cross_bias = [
self.add_weight(name='b_' + str(i),
shape=(dim, 1),
initializer='random_uniform',
regularizer=l2(self.reg_b),
trainable=True
)
for i in range(self.layer_num)]
def call(self, inputs, **kwargs):
x_0 = tf.expand_dims(inputs, axis=2) # (None, dim, 1)
x_l = x_0 # (None, dim, 1)
for i in range(self.layer_num):
x_l1 = tf.tensordot(x_l, self.cross_weights[i], axes=[1, 0]) # (None, dim, dim)
x_l = tf.matmul(x_0, x_l1) + self.cross_bias[i] + x_l # (None, dim, 1)
x_l = tf.squeeze(x_l, axis=2) # (None, dim)
return x_l
class DNN(Layer):
"""
Deep Neural Network
"""
def __init__(self, hidden_units, activation='relu', dropout=0.):
"""
:param hidden_units: A list. Neural network hidden units.
:param activation: A string. Activation function of dnn.
:param dropout: A scalar. Dropout number.
"""
super(DNN, self).__init__()
self.dnn_network = [Dense(units=unit, activation=activation) for unit in hidden_units]
self.dropout = Dropout(dropout)
def call(self, inputs, **kwargs):
x = inputs
for dnn in self.dnn_network:
x = dnn(x)
x = self.dropout(x)
return x
class DCN(keras.Model):
def __init__(self, feature_columns, hidden_units, activation='relu',
dnn_dropout=0., embed_reg=1e-4, cross_w_reg=1e-4, cross_b_reg=1e-4):
"""
Deep&Cross Network
:param feature_columns: A list. dense_feature_columns + sparse_feature_columns
:param hidden_units: A list. Neural network hidden units.
:param activation: A string. Activation function of dnn.
:param dnn_dropout: A scalar. Dropout of dnn.
:param embed_reg: A scalar. The regularizer of embedding.
:param cross_w_reg: A scalar. The regularizer of cross network.
:param cross_b_reg: A scalar. The regularizer of cross network.
"""
super(DCN, self).__init__()
self.dense_feature_columns, self.sparse_feature_columns = feature_columns
self.layer_num = len(hidden_units)
self.embed_layers = {
'embed_' + str(i): Embedding(input_dim=feat['feat_num'],
input_length=1,
output_dim=feat['embed_dim'],
embeddings_initializer='random_uniform',
embeddings_regularizer=l2(embed_reg))
for i, feat in enumerate(self.sparse_feature_columns)
}
self.cross_network = CrossNetwork(self.layer_num, cross_w_reg, cross_b_reg)
self.dnn_network = DNN(hidden_units, activation, dnn_dropout)
self.dense_final = Dense(1)
def call(self, inputs):
dense_inputs, sparse_inputs = inputs
sparse_embed = tf.concat([self.embed_layers['embed_{}'.format(i)](sparse_inputs[:, i])
for i in range(sparse_inputs.shape[1])], axis=-1)
x = tf.concat([sparse_embed, dense_inputs], axis=-1)
# Cross Network
cross_x = self.cross_network(x)
# DNN
dnn_x = self.dnn_network(x)
# Concatenate
total_x = tf.concat([cross_x, dnn_x], axis=-1)
outputs = tf.nn.sigmoid(self.dense_final(total_x))
return outputs
def summary(self):
dense_inputs = Input(shape=(len(self.dense_feature_columns),), dtype=tf.float32)
sparse_inputs = Input(shape=(len(self.sparse_feature_columns),), dtype=tf.int32)
keras.Model(inputs=[dense_inputs, sparse_inputs],
outputs=self.call([dense_inputs, sparse_inputs])).summary()