目录
- 16年发布,用于分类和回归
- 应用到了google play中的应用推荐
1.稀疏特征和密集特征
1.1 稀疏特征
1.1.1 什么是稀疏特征
- 离散值特征
- one-hot编码。若不了解, 可以看一下这篇博客onehot 编码_zhao_crystal的博客-CSDN博客
eg: 专业={计算机,人文,其它}。人文=[0,1,0]
eg: 词表={人工智能,你,他,慕课网,……}。他=[0,0,1,0,……]
1.1.2 稀疏特征的叉乘
叉乘:即“专业”和“词表”中的每一个词作组合。得到{(计算机, 人工智能),(计算机,你),(计算机, 他)……}
叉乘的作用:
- 稀疏特征做叉乘可获取共现信息(共现信息,拿身体特征来说,身高在170,体重在60kg的特征信息)
- 实现记忆效果(每个原始特征都叉乘,则表达的信息更全面,更易“记住”样本)
1.1.3 稀疏特征的优缺点
优点:
- 有效,广泛用于工业界
缺点:
- 需要人工设计(需要选择某些特征做叉乘,以免叉乘后的集合太多,发生维度爆炸)
- 可能过拟合,所有特征都叉乘,相当于记住每一个样本
1.2 密集特征
1.2.1 什么是密集特征
向量的表达
eg: 词表={人工智能,你,他,慕课网,……} n个词
他=[0.3, 0.2, 0.6,……] n维向量
即每个词都用向量表达,用向量之间的距离来表达词(信息)之间的距离
Word2vec可将词语转换成工具(详见链接word2vec_zhao_crystal的博客-CSDN博客)
男-女=国王-王后
1.2.2 密集特征的优缺点
优点:
- 带有语义信息,不同向量之间有相关性(用向量之间的距离表示其相关性)
- 兼容没有出现过的特征组合(遇到一个新的样本,可以通过计算向量之间的差距,来衡量两个样本的相似性,从而不仅可以把记忆的样本预测对,也可以把相似的样本预测对)
- 更少人工参与
缺点:
- 过度泛化,推荐不怎么相关的产品
2 Wide&Deep模型
wide模型用的是稀疏特征,deep模型用的是密集特征
2.1 wide &deep vs. wide
2.2 wide & deep vs. deep
2.3 Google商店推荐算法模型图
3. wide&deep模型的构建
3.1 函数式API
使用regression model
使用两层神经网络,实现deep model
使用函数式API,需要使用Model 将其固化下来
# 函数式API 类似于复合函数 f(x) = h(g(x))
# deep model——> 两层的神经网络
input = keras.layers.Input(shape=x_train.shape[1:])
hidden1 = keras.layers.Dense(30, activation='relu')(input)
hidden2 = keras.layers.Dense(30, activation='relu')(hidden1)
# wide模型即为input
# 将wide模型和deep模型拼接
# 并得到输出(最终是要预测房价,是回归,不是分类,所以output的维度是1)
concat = keras.layers.concatenate([input, hidden2])
output = keras.layers.Dense(1)(concat)
# 用keras.models.Model, 将函数式API构建的层固化为模型
model = keras.models.Model(inputs = [input],
outputs = [output])
model.summary()
代码详见:
3.2 子类API
继承子类API
以上wide 和deep模型都是一样的,实际中,wide 和deep模型的输入是不一样的。
如下一个就是多输入
# 使用子类API构建模型
class WideDeepModel(keras.models.Model):
def __init__(self):
super(WideDeepModel, self).__init__()
"""定义模型的层次"""
self.hidden1_layer = keras.layers.Dense(30, activation='relu')
self.hidden2_layer = keras.layers.Dense(30, activation='relu')
self.output_layer = keras.layers.Dense(1)
def call(self, input):
hidden1 = self.hidden1_layer(input)
hidden2 = self.hidden2_layer(hidden1)
concat = keras.layers.concatenate([input, hidden2])
output = self.output_layer(concat)
return output
model = WideDeepModel()
# 也可以用Sequential,只不过这样,整个模型就被当作了1层
# model = keras.models.Sequential([
# WideDeepModel(),
# ])
model.build(input_shape=(None, 8))
model.summary()
代码详见:
3.3 多输入
wide 和deep模型的输入不一样
# wide&deep多输入模型
# 此处我们使用函数式API 类似于复合函数 f(x) = h(g(x))
# deep model——> 两层的神经网络
input_deep = keras.layers.Input(shape=[6])
hidden1 = keras.layers.Dense(30, activation='relu')(input_deep)
hidden2 = keras.layers.Dense(30, activation='relu')(hidden1)
# wide model
input_wide = keras.layers.Input(shape=[5])
# 将wide模型和deep模型拼接
# 并得到输出(最终是要预测房价,是回归,不是分类,所以output的维度是1)
concat = keras.layers.concatenate([input_wide, hidden2])
output = keras.layers.Dense(1)(concat)
# 用keras.models.Model, 将函数式API构建的层固化为模型
model = keras.models.Model(inputs = [input_wide, input_deep],
outputs = [output])
model.summary()
代码详见:
3.4 拓展——多输出
多输出:主要是针对多任务问题。比如除了预测当前房价,还要预测一年之后的房价。
注:wide&deep模型不是多输出
# 多输入 多输出模型
# 此处我们使用函数式API 类似于复合函数 f(x) = h(g(x))
# deep model——> 两层的神经网络
input_deep = keras.layers.Input(shape=[6])
hidden1 = keras.layers.Dense(30, activation='relu')(input_deep)
hidden2 = keras.layers.Dense(30, activation='relu')(hidden1)
# wide model
input_wide = keras.layers.Input(shape=[5])
# 将wide模型和deep模型拼接
# 并得到输出(最终是要预测房价,是回归,不是分类,所以output的维度是1)
concat = keras.layers.concatenate([input_wide, hidden2])
output1 = keras.layers.Dense(1)(concat)
output2 = keras.layers.Dense(1)(hidden2)
# 用keras.models.Model, 将函数式API构建的层固化为模型
model = keras.models.Model(inputs = [input_wide, input_deep],
outputs = [output1, output2])
model.summary()
代码详见:
4. 参考文献
Wide & Deep Learning for Recommender Systems