Python深度学习--深度学习入门-基于TensorFlow实现Wide&Deep模型(多输入,多输入,单输入,单输出,基于子类API优化)

wide and deep模型

1.背景

Wide and deep 模型是 TensorFlow 在 2016 年 6 月左右发布的一类用于分类和回归的模型,并应用到了 Google Play 的应用推荐中。wide and deep 模型的核心思想是结合线性模型的记忆能力(memorization)和 DNN 模型的泛化能力(generalization),在训练过程中同时优化 2 个模型的参数,从而达到整体模型的预测能力最优。

记忆(memorization)即从历史数据中发现item或者特征之间的相关性。

泛化(generalization)即相关性的传递,发现在历史数据中很少或者没有出现的新的特征组合。

2.原理

2.1 网络结构

1500965e5896703dd49b541.png

可以认为:WideDeep = LR + DNN

3. 稀疏特征

  • 离散值特征: 只能从N个值中选择一个
    • 比如性别, 只能是男女
    • one-hot编码表示的离散特征, 我们就认为是稀疏特征.
    • Eg: 专业= {计算机, 人文, 其他}, 人文 = [0, 1, 0]
    • Eg: 词表 = {人工智能,深度学习,你, 我, 他, 马士兵, …} 他= [0, 0, 0, 0, 1, 0, …]
    • 叉乘 = {(计算机, 人工智能), (计算机, 你)…}
    • 叉乘可以用来精确刻画样本, 实现记忆效果.
    • 优点:
      • 有效, 广泛用于工业界, 比如广告点击率预估(谷歌, 百度的主要业务), 推荐算法.
    • 缺点:
      • 需要人工设计.
      • 叉乘过度, 可能过拟合, 所有特征都叉乘, 相当于记住了每一个样本.
      • 泛化能力差, 没出现过就不会起效果
  • 密集特征
    • 向量表达
      • Eg: 词表 = {人工智能, 你, 我, 他, 马士兵}
      • 他 = [0.3, 0.2, 0.6, …(n维向量)]
      • 每个词都可以用一个密集向量表示, 那么词和词之间就可以计算距离.
    • Word2vec工具可以方便的将词语转化为向量.
      • 男 - 女 = 国王 - 王后
    • 优点:
      • 带有语义信息, 不同向量之间有相关性.
      • 兼容没有出现过的特征组合.
      • 更少人工参与
    • 缺点:
      • 过度泛化, 比如推荐不怎么相关的产品.150096513fa11d119bb20b7.png

    4.简单实现一个Wide&Deep模型(单输入)

#导包
from tensorflow import keras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

#导入数据
from sklearn.datasets import fetch_california_housing

#实例化数据
housing=fetch_california_housing()

#数据处理
#切割数据 
#训练集 验证集 测试集合
from sklearn.model_selection import train_test_split
x_train_all,x_test,y_train_all,y_test=train_test_split(housing.data,housing.target,random_state=7)

x_train,x_valid,y_train,y_valid=train_test_split(x_train_all,y_train_all,random_state=11)
#打印输出数据 简略了解数据情况
x_train.shape,y_train.shape,x_test.shape,y_test.shape,x_valid.shape,y_valid.shape
#((11610, 8), (11610,), (5160, 8), (5160,), (3870, 8), (3870,))

#数据标准化
from sklearn.preprocessing import StandardScaler

scaler=StandardScaler()
x_train_scaled=scaler.fit_transform(x_train)
x_test_scaled=scaler.fit_transform(x_test)
x_valid_scaled=scaler.fit_transform(x_valid)

#定义网络
#函数式api: 每一层结构都可以当做一个函数去使用

#神经网络输入层(单输入)
inputs=keras.layers.Input(shape=x_train.shape[1:])
#隐藏层(deep结构)
hidden1=keras.layers.Dense(32,activation='relu')(inputs)
hidden2=keras.layers.Dense(32,activation='relu')(hidden1)

#wide模型 和deep模型使用相同的输入数据
#wide 模型就是inputs 就是将数据做直接输出 
concat=keras.layers.concatenate([inputs,hidden2])

#输出层
output=keras.layers.Dense(1)(concat)
#包装称一个model
model=keras.models.Model(inputs=[inputs],outputs=output)

#配置
model.compile(loss='mean_squared_error',optimizer='adam',metrics=['MSE'])

his=model.fit(x_train_scaled,y_train,
          validation_data=(x_valid_scaled,y_valid),
          epochs=25)

#检查模型效果
def plot_learn_curves(his):
    pd.DataFrame(his.history).plot(figsize=(8,5))
    plt.grid(True)
    plt.gca().set_ylim(0,1)
    plt.show()

plot_learn_curves(his)

效果展示

在这里插入图片描述

4.1此处可使用子类API写法对简单的wide&deep模型进行优化

优化代码如下

from tensorflow import keras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import fetch_california_housing
housing=fetch_california_housing()

#切割数据 
#训练集 验证集 测试机
from sklearn.model_selection import train_test_split
x_train_all,x_test,y_train_all,y_test=train_test_split(housing.data,housing.target,random_state=7)

x_train,x_valid,y_train,y_valid=train_test_split(x_train_all,y_train_all,random_state=11)
# x_train.shape,y_train.shape,x_test.shape,y_test.shape,x_valid.shape,y_valid.shape
#数据标准化
from sklearn.preprocessing import StandardScaler

scaler=StandardScaler()
x_train_scaled=scaler.fit_transform(x_train)
x_test_scaled=scaler.fit_transform(x_test)
x_valid_scaled=scaler.fit_transform(x_valid)

#定义网络 子类api
class WideDeepModel(keras.models.Model):
    def __init__(self):
        '''定义模型的层次'''
        super().__init__()
        self.hidden1=keras.layers.Dense(32,activation='relu')
        self.hidden2=keras.layers.Dense(32,activation='relu')
        self.outputs=keras.layers.Dense(1)
        
    def call(self,input):
        '''完成正向传播'''
        hidden1=self.hidden1(input)
        hidden2=self.hidden2(hidden1)
        #拼接
        concat=keras.layers.concatenate([input,hidden2])
        outputs=self.outputs(concat)
        return outputs

model=WideDeepModel()
model.build(input_shape=(None,8))
#配置网络
model.compile(loss='mse',optimizer='adam',metrics=['mae'])
his=model.fit(x_train_scaled,y_train,validation_data=(x_valid_scaled,y_valid),epochs=20)

#查看模型效果
def plot_learn_curves(his):
    pd.DataFrame(his.history).plot(figsize=(8,5))
    plt.grid(True)
    plt.gca().set_ylim(0,1)
    plt.show()

plot_learn_curves(his)

在这里插入图片描述

5.实现一个多输入的Wide & Deep模型

from tensorflow import keras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import fetch_california_housing
housing=fetch_california_housing()

#切割数据 
#训练集 验证集 测试集合
from sklearn.model_selection import train_test_split
x_train_all,x_test,y_train_all,y_test=train_test_split(housing.data,housing.target,random_state=7)

x_train,x_valid,y_train,y_valid=train_test_split(x_train_all,y_train_all,random_state=11)
#x_train.shape,y_train.shape,x_test.shape,y_test.shape,x_valid.shape,y_valid.shape
#数据标准化
from sklearn.preprocessing import StandardScaler

scaler=StandardScaler()
x_train_scaled=scaler.fit_transform(x_train)
x_test_scaled=scaler.fit_transform(x_test)
x_valid_scaled=scaler.fit_transform(x_valid)

#定义网络
#函数式api: 每一层结构都可以当做一个函数去使用

#神经网络输入层(多输入)
inputs_wide=keras.layers.Input(shape=[5])#wide输入
inputs_deep=keras.layers.Input(shape=[6])#deep输入
#隐藏层(deep结构)
hidden1=keras.layers.Dense(32,activation='relu')(inputs_deep)
hidden2=keras.layers.Dense(32,activation='relu')(hidden1)

#拼接输出结果
concat=keras.layers.concatenate([inputs_wide,hidden2])

#输出层
output=keras.layers.Dense(1)(concat)
#包装称一个model 此处需注意包装的模型结果需要有两个输入
model=keras.models.Model(inputs=[inputs_wide,inputs_deep],outputs=output)

#配置
model.compile(loss='mean_squared_error',optimizer='adam',metrics=['MSE'])

#切分数据集使数据集满足模型输入需求 尤其注意shape大小与定义的输入要一致
x_train_scaled_wide=x_train_scaled[:,:5]
x_train_scaled_deep=x_train_scaled[:,2:]

x_test_scaled_wide=x_test_scaled[:,:5]
x_test_scaled_deep=x_test_scaled[:,2:]

x_valid_scaled_wide=x_valid_scaled[:,:5]
x_valid_scaled_deep=x_valid_scaled[:,2:]


his=model.fit([x_train_scaled_wide,x_train_scaled_deep],y_train,
          validation_data=([x_valid_scaled_wide,x_valid_scaled_deep],y_valid),
          epochs=25)

def plot_learn_curves(his):
    pd.DataFrame(his.history).plot(figsize=(8,5))
    plt.grid(True)
    plt.gca().set_ylim(0,1)
    plt.show()

plot_learn_curves(his)

在这里插入图片描述

6.实现一个多输入 多输出 的Wide & Deep模型

from tensorflow import keras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import fetch_california_housing
housing=fetch_california_housing()

#切割数据 
#训练集 验证集 测试集合
from sklearn.model_selection import train_test_split
x_train_all,x_test,y_train_all,y_test=train_test_split(housing.data,housing.target,random_state=7)

x_train,x_valid,y_train,y_valid=train_test_split(x_train_all,y_train_all,random_state=11)
#x_train.shape,y_train.shape,x_test.shape,y_test.shape,x_valid.shape,y_valid.shape
#数据标准化
from sklearn.preprocessing import StandardScaler

scaler=StandardScaler()
x_train_scaled=scaler.fit_transform(x_train)
x_test_scaled=scaler.fit_transform(x_test)
x_valid_scaled=scaler.fit_transform(x_valid)

#定义网络
#函数式api: 每一层结构都可以当做一个函数去使用

#神经网络输入层(多输入)
inputs_wide=keras.layers.Input(shape=[5])
inputs_deep=keras.layers.Input(shape=[6])
#隐藏层(deep结构)
hidden1=keras.layers.Dense(32,activation='relu')(inputs_deep)
hidden2=keras.layers.Dense(32,activation='relu')(hidden1)

#拼接输出结果
concat=keras.layers.concatenate([inputs_wide,hidden2])

#输出层 (多输出)
output=keras.layers.Dense(1)(concat)
output2=keras.layers.Dense(1)(hidden2) #deep模型的结果
#包装称一个model 需要注意putputs 有两个输出
model=keras.models.Model(inputs=[inputs_wide,inputs_deep],outputs=[output,output2])


#配置
model.compile(loss='mean_squared_error',optimizer='adam',metrics=['MSE'])

#切分数据集使数据集满足模型输入需求 尤其注意shape大小与定义的输入要一致
x_train_scaled_wide=x_train_scaled[:,:5]
x_train_scaled_deep=x_train_scaled[:,2:]

x_test_scaled_wide=x_test_scaled[:,:5]
x_test_scaled_deep=x_test_scaled[:,2:]

x_valid_scaled_wide=x_valid_scaled[:,:5]
x_valid_scaled_deep=x_valid_scaled[:,2:]


#此处也需要对y_train 进行复制 因为y没有变化 且需要保证两个输出
his=model.fit([x_train_scaled_wide,x_train_scaled_deep],[y_train,y_train],
          validation_data=([x_valid_scaled_wide,x_valid_scaled_deep],[y_valid,y_valid]),
          epochs=25)
          
def plot_learn_curves(his):
    pd.DataFrame(his.history).plot(figsize=(8,5))
    plt.grid(True)
    plt.gca().set_ylim(0,1)
    plt.show()

plot_learn_curves(his)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扁舟钓雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值