tensorflow2.1.0——如何构建网络(二)

一、构建网络的第二种方式

  • 通过输入层和输出层来构建网络,网络包含输入和输出中间的隐藏层,这会返回一个Model对象,通过该对象可以调用model.compile和model.fit函数,非常方便。
import tensorflow as tf
import tensorflow.keras.layers

x = layers.Input(shape=(784,))  # 输入层,shape可自己定义
h_1 = layers.Dense(x)  # 隐藏层
h_2 = layers.Conv2D(h1)  # 隐藏层
... # 你可以定义任意多的层,每个层可以是任意种类
h_n = layers.Dense(h_n_1) # h_n_1表示第n-1层隐藏层
out = layers.Dense(h_n)  # 输出层

# 构建网络
model = Model(x,out) 

二、对比第一种构建网络方式

第一种方式

1. 第二种方式的优点

  • 建立模型更加的泛化,更加通俗易懂
    ①第一种使用Squential来构建网络,非常的无脑简单,但是当我们需要Squential中间某些层的量来计算一些东西时,此时会变得比较复杂,例如VAE中要在encoder部分计算KL散度,需要对encoder网络的输出做一个函数变换,这其实变得优点困难,当然我们也可以自定义层(熟练之后),也可以使用lambda层,但无疑这回增加我们的难度;
    ②第二种构建方式,可以很巧妙的利用这些隐藏层的结果去做一些事情,例如构建loss,下面展示一下这种巧妙方式在VAE中是如何应用的。
    ③第二种构建模型的方式依然可以使用model.compile和model.fit函数,有几方面的原因:
    (1)整个模型就一个model(因为有的模型会有两个model,例如GAN)
    (2)整个构建过程最终返回的是一个Model()对象,所以可以调用类的方法compile和fit。
# 定义自己的模型
latent_dimension = 50

# 定义重采样函数,方便lambda使用
def sampling(agrs):
    mean,logvar = agrs[0],agrs[1]
    eps = tf.random.normal(tf.shape(mean))
    
    return mean + eps*tf.exp(logvar * 0.5)


# 编码阶段    
x = layers.Input(shape=(784*2,))  # 输入层
    
h1 = layers.Dense(200,activation='softplus')(x)
h2 = layers.Dense(200,activation='softplus')(h1)
# 均值和方差层不需要激活函数
mean = layers.Dense(latent_dimension)(h2)
log_var = layers.Dense(latent_dimension)(h2)
    
# 将采样过程看成一个Lambda层
z = layers.Lambda(sampling,output_shape=(latent_dimension,))([mean,log_var])
    
# 解码阶段
h3 = layers.Dense(200,activation='softplus')
h4 = layers.Dense(200,activation='softplus')
h5 = layers.Dense(200,activation='softplus')
# No activation
end = layers.Dense(784)
z1 = h3(z)
z2 = h4(z1)
z3 = h5(z2)
out = end(z3) # 输出层
    
# 建立模型
model = tf.keras.Model(x,out)

#构建损失函数,这里用到了网络结构中隐藏层的信息:均值和方差    
cross_ent = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=tf.split(x,num_or_size_splits=2,axis=-1)[0],logits=out),axis=-1) # 重构误差
KL = -tf.reduce_sum(1+log_var-tf.square(mean)-tf.exp(log_var),axis=-1)
dvae_loss = tf.reduce_mean(cross_ent + KL)
model.add_loss(dvae_loss)

# 编译
model.compile(optimizer='adam')
# fit
history = model.fit(train_dataset,epochs=80,validation_data=test_dataset) 

第二种方式的缺点

  • 相比于第一种建模方式,第二种很繁琐,同时注意到当我们需要更改网络结构时,第二种方式改起来也比较繁琐

第二种方式的使用场景

  • 网络比较简单,不然代码量会很多,不符合写代码的准则。例如加入现在我们要构建100层神经网络,那么如果用第二种方式,那我选择die!

总结

  • 网络结构比较简单时,方式一和方式二都可以,当网络结构很复杂时,首选用Squential构建网络,后面会讲比较复杂的用Squential构建网络,这时候将不能使用compile和fit函数。
  • 16
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

InceptionZ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值