全连接层
Layers:
- input
- hidden
- output
Heroes:
- BigDATA
- ReLU
- Dropout
- BatchNorm
- ResNet
- XAVIR Initialization
- Caffe/Tensorflow/PyTorch
tf.keras.layers.Dense(units,activation)
layer.Dense类:
.build(num)方法
num为输入节点数
.kernel方法
权值张量𝑾
.bias方法
偏置张量𝒃
.trainable_variables属性
待优化参数列表
.non_trainable_variables属性
所有不需要优化的参数列表
.trainable属性
所有内部张量列表
通过layer.Dense 类,只需要指定输出节点数Units 和激活函数类型activation 即可。需要注意的是,输入节点数会根据第一次运算时的输入shape 确定,同时根据输入、输出节点数自动创建并初始化权值张量𝑾和偏置张量𝒃,因此在新建类Dense 实例时,并不会立即创建权值张量𝑾和偏置张量𝒃,而是需要调用build 函数或者直接进行一次前向计算,才能完成网络参数的创建。其中activation 参数指定当前层的激活函数,可以为常见的激活函数或自定义激活函数,也可以指定为None,即无激活函数。
我们可以通过类内部的成员名kernel 和bias 来获取权值张量𝑾和偏置张量𝒃对象:
1 | import tensorflow as tf |
机制:
利用网络层类对象进行前向计算时,只需要调用类的call方法即可,即写成f(x)方式便可,它会自动调用类的call方法,在call方法中会自动调用call 方法,这一设定由TensorFlow 框架自动完成,因此用户只需要将网络层的前向计算逻辑实现在call 方法中即可。对于全连接层类,在call 方法中实现𝜎(𝑿@𝑾 + 𝒃)的运算逻辑,非常简单,最后返回全连接层的输出张量即可。
神经网络
tf.keras.Sequential([layer1,layer2,…])
可以将每一个层封装起来,调用大类的前向计算函数一次即可完成所有层的前向计算.
.build(num)方法
使用方法同上
.summary( )方法
可以打印出每层的参数列表
call方法
实现大类的向前运算,可以直接用model(x)实现
在假定model=tf.keras.Sequential([layer1,layer2,…])时
实现代码:
1 | import tensorflow as tf |
激活函数
常见的激活函数
Sigmoid函数
它的一个优良特性就是能够把𝑥 ∈ 𝑅的输入“压缩”到𝑥 ∈ (0,1)区间,这个区间的数值在机
器学习常用来表示以下意义:
- 概率分布 (0,1)区间的输出和概率的分布范围[0,1]契合,可以通过Sigmoid 函数将输出
转译为概率输出- 信号强度 一般可以将0~1 理解为某种信号的强度,如像素的颜色强度,1 代表当前通
道颜色最强,0 代表当前通道无颜色;抑或代表门控值(Gate)的强度,1 代表当前门控
全部开放,0代表关闭
- tf.nn.sigmoid(x)
ReLU函数
公式:$ReLU(𝑥) ≜ max(0, 𝑥)$
- tf.nn.relu(x)
LeakyReLU
- tf.nn.leaky_relu(x, alpha= )
Tanh函数
Tanh 函数能够将𝑥 ∈ 𝑅的输入“压缩”到(−1,1)区间
- tf.nn.tanh(x)
输出层函数
恒等函数
tf不对输出层处理即可
回归问题
softmax函数
分类问题
- tf.nn.softmax
在 Softmax 函数的数值计算过程中,容易因输入值偏大发生数值溢出现象;在计算交叉熵时,也会出现数值溢出的问题。为了数值计算的稳定性,TensorFlow 中提供了一个统一的接口,将Softmax 与交叉熵损失函数同时实现,同时也处理了数值不稳定的异常,一般推荐使用这些接口函数,避免分开使用Softmax 函数与交叉熵损失函数。
函数式接口为tf.keras.losses.categorical_crossentropy(y_true,y_pred,from_logits=False),其中y_true 代表了One-hot 编码后的真实标签,y_pred 表示网络的预测值,当from_logits 设置为True 时,y_pred 表示须为未经过Softmax 函数的变量z;
当from_logits 设置为False 时,y_pred 表示为经过Softmax 函数的输出。为了数值计算稳定性,一般设置from_logits 为True,此时tf.keras.losses.categorical_crossentropy 将在内部进行Softmax 函数计算,所以不需要在模型中显式调用Softmax 函数
- tf.keras.losses.categorical_crossentropy(y_true,y_pred,from_logits=False)
1 | import tensorflow as tf |
6.5 输出层设计
我们来特别地讨论网络的最后一层的设计,它除了和所有的隐藏层一样,完成维度变换、特征提取的功能,还作为输出层使用,需要根据具体的任务场景来决定是否使用激活函数,以及使用什么类型的激活函数等。
我们将根据输出值的区间范围来分类讨论。常见的几种输出类型包括:
❑ 𝑜𝑖 ∈ 𝑅𝑑 输出属于整个实数空间,或者某段普通的实数空间,比如函数值趋势的预
测,年龄的预测问题等。
❑ 𝑜𝑖 ∈ [0,1] 输出值特别地落在[0, 1]的区间,如图片生成,图片像素值一般用[0, 1]区间
的值表示;或者二分类问题的概率,如硬币正反面的概率预测问题。
❑ 𝑜𝑖 ∈ [0, 1], 𝑖 𝑜𝑖 = 1 输出值落在[0,1]的区间,并且所有输出值之和为 1,常见的如
多分类问题,如MNIST 手写数字图片识别,图片属于10 个类别的概率之和应为1。
❑ 𝑜𝑖 ∈ [−1, 1] 输出值在[-1, 1]之间
误差分析
Outline:
- MSE
- Cross Entopy Loss
- Hinge Loss
MSE
- tf.losses.MSE(y_true,y_pred)
同时也与tf.reduce_mean( )搭配使用,求出平均误差
Cross Entopy Loss
- tf.keras.losses.categorical_crossentropy(y_true,y_pred,from_logits=False)
对y_true一定要one_hot化
交叉熵使用的更多
反向传播
tf.GradientTape( )
tensorflow有自动求导的功能,如果遇到一定要手动求导的问题,也可以自己构建计算图的方式来求导
tf.GradientTape()可以提供求导的上下文管理器来连接需要计算梯度的函数和变量,一般与with as语句连用
1
2
3
4
5
6import tensorflow as tf
x=tf.constant(3.0)
with tf.GradientTape() as tape:
tape.watch(x)
y=x*x*x
dy_dx=tape.gradient(y,[x])tf.GradientTape(persistent=True,watch_accessed_variables=True)
- persistent: 布尔值,用来指定新创建的gradient tape是否是可持续性的。默认是False,意味着只能够调用一次
gradient()函数。 - watch_accessed_variables: 布尔值,表明这个gradien tap是不是会自动追踪任何能被训练(trainable)的变量。默认是True。要是为False的话,意味着你需要手动去指定你想追踪的那些变量。
但tf.GradientTape只能默认追踪Variable变量,如果是constant变量则需要用.watch( )方法来添加为可追踪变量
- persistent: 布尔值,用来指定新创建的gradient tape是否是可持续性的。默认是False,意味着只能够调用一次
Himmelblau函数优化练习
Himmelblau 函数是用来测试优化算法的常用样例函数之一
用python代码来表示:
1 | import numpy as np |
用Matplotlib 库可视化Himmelblau 函数:
1 | x = np.arange(-6, 6, 0.1) # 可视化的x 坐标范围为-6~6 |
自动求导:
- tf.constant版
1 | # 参数的初始化值对优化的影响不容忽视,可以通过尝试不同的初始化值, |
- tf.Variable版
1 | # 参数的初始化值对优化的影响不容忽视,可以通过尝试不同的初始化值, |
Keras API for tensorflow
网络层类
常见内置模型层介绍
tf.keras.layers下
基础层
- Dense:密集连接层。参数个数 = 输入层特征数× 输出层特征数(weight)+ 输出层特征数(bias)
- Activation:激活函数层。一般放在Dense层后面,等价于在Dense层中指定activation。
- Dropout:随机置零层。训练期间以一定几率将输入置0,一种正则化手段。
- BatchNormalization:批标准化层。通过线性变换将输入批次缩放平移到稳定的均值和标准差。可以增强模型对输入不同分布的适应性,加快模型训练速度,有轻微正则化效果。一般在激活函数之前使用。
- SpatialDropout2D:空间随机置零层。训练期间以一定几率将整个特征图置0,一种正则化手段,有利于避免特征图之间过高的相关性。
- Input:输入层。通常使用Functional API方式构建模型时作为第一层。
- DenseFeature:特征列接入层,用于接收一个特征列列表并产生一个密集连接层。
- Flatten:压平层,用于将多维张量压成一维。
- Reshape:形状重塑层,改变输入张量的形状。
- Concatenate:拼接层,将多个张量在某个维度上拼接。
- Add:加法层。
- Subtract: 减法层。
- Maximum:取最大值层。
- Minimum:取最小值层。
卷积网络相关层
- Conv1D:普通一维卷积,常用于文本。参数个数 = 输入通道数×卷积核尺寸(如3)×卷积核个数
- Conv2D:普通二维卷积,常用于图像。参数个数 = 输入通道数×卷积核尺寸(如3乘3)×卷积核个数
- Conv3D:普通三维卷积,常用于视频。参数个数 = 输入通道数×卷积核尺寸(如3乘3乘3)×卷积核个数
- SeparableConv2D:二维深度可分离卷积层。不同于普通卷积同时对区域和通道操作,深度可分离卷积先操作区域,再操作通道。即先对每个通道做独立卷积操作区域,再用1乘1卷积跨通道组合操作通道。参数个数 = 输入通道数×卷积核尺寸 + 输入通道数×1×1×输出通道数。深度可分离卷积的参数数量一般远小于普通卷积,效果一般也更好。
- DepthwiseConv2D:二维深度卷积层。仅有SeparableConv2D前半部分操作,即只操作区域,不操作通道,一般输出通道数和输入通道数相同,但也可以通过设置depth_multiplier让输出通道为输入通道的若干倍数。输出通道数 = 输入通道数 × depth_multiplier。参数个数 = 输入通道数×卷积核尺寸× depth_multiplier。
- Conv2DTranspose:二维卷积转置层,俗称反卷积层。并非卷积的逆操作,但在卷积核相同的情况下,当其输入尺寸是卷积操作输出尺寸的情况下,卷积转置的输出尺寸恰好是卷积操作的输入尺寸。
- LocallyConnected2D: 二维局部连接层。类似Conv2D,唯一的差别是没有空间上的权值共享,所以其参数个数远高于二维卷积。
- MaxPooling2D: 二维最大池化层。也称作下采样层。池化层无参数,主要作用是降维。
- AveragePooling2D: 二维平均池化层。
- GlobalMaxPool2D: 全局最大池化层。每个通道仅保留一个值。一般从卷积层过渡到全连接层时使用,是Flatten的替代方案。
- GlobalAvgPool2D: 全局平均池化层。每个通道仅保留一个值。
循环网络相关层
- Embedding:嵌入层。一种比Onehot更加有效的对离散特征进行编码的方法。一般用于将输入中的单词映射为稠密向量。嵌入层的参数需要学习。
- LSTM:长短记忆循环网络层。最普遍使用的循环网络层。具有携带轨道,遗忘门,更新门,输出门。可以较为有效地缓解梯度消失问题,从而能够适用长期依赖问题。设置return_sequences = True时可以返回各个中间步骤输出,否则只返回最终输出。
- GRU:门控循环网络层。LSTM的低配版,不具有携带轨道,参数数量少于LSTM,训练速度更快。
- SimpleRNN:简单循环网络层。容易存在梯度消失,不能够适用长期依赖问题。一般较少使用。
- ConvLSTM2D:卷积长短记忆循环网络层。结构上类似LSTM,但对输入的转换操作和对状态的转换操作都是卷积运算。
- Bidirectional:双向循环网络包装器。可以将LSTM,GRU等层包装成双向循环网络。从而增强特征提取能力。
- RNN:RNN基本层。接受一个循环网络单元或一个循环单元列表,通过调用tf.keras.backend.rnn函数在序列上进行迭代从而转换成循环网络层。
- LSTMCell:LSTM单元。和LSTM在整个序列上迭代相比,它仅在序列上迭代一步。可以简单理解LSTM即RNN基本层包裹LSTMCell。
- GRUCell:GRU单元。和GRU在整个序列上迭代相比,它仅在序列上迭代一步。
- SimpleRNNCell:SimpleRNN单元。和SimpleRNN在整个序列上迭代相比,它仅在序列上迭代一步。
- AbstractRNNCell:抽象RNN单元。通过对它的子类化用户可以自定义RNN单元,再通过RNN基本层的包裹实现用户自定义循环网络层。
- Attention:Dot-product类型注意力机制层。可以用于构建注意力模型。
- AdditiveAttention:Additive类型注意力机制层。可以用于构建注意力模型。
- TimeDistributed:时间分布包装器。包装后可以将Dense、Conv2D等作用到每一个时间片段上。
自定义层
对于自定义的网络层,至少需要实现初始化init方法和前向传播逻辑call方法。
如一个没有偏置向量的全连接层:即bias 为0,同时固定激活函数为ReLU 函数。
实现代码如下:
1 | class MyDense(layer.Layer): |
自定义类的前向运算逻辑实现在call(inputs, training=None)函数中,其中inputs代表输入,由用户在调用时传入;training 参数用于指定模型的状态:training 为True 时执行训练模式,training 为False 时执行测试模式,默认参数为None,即测试模式。由于全连接层的训练模式和测试模式逻辑一致,此处不需要额外处理。对于部份测试模式和训练模式不一致的网络层,需要根据training 参数来设计需要执行的逻辑。
网络类
内置网络容器Sequential
1 | from tensorflow.keras import layers, Sequential |
Sequential 容器也可以通过add()方法继续追加新的网络层,实现动态创建网络的功能:
1 | from tensorflow.keras import layers, Sequential |
模型装配、训练与测试
假定有一个全连接模型:
1
2
3
4
5
6
7
8
9
10 from tensorflow.keras import Sequential,optimizers,losses
network = Sequential([
layers.Dense(256, activation='relu'),
layers.Dense(128, activation='relu'),
layers.Dense(64, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(10)
])
network.build(input_shape=(4, 28*28))
network.summary()
在keras.model类中
模型装配
.compile( )方法
可以指定网络使用的优化器对象,损失函数类型,评价指标
1
2
3
4
5
6# 采用Adam 优化器,学习率为0.01;采用交叉熵损失函数,包含Softmax
network.compile(
optimizer=optimizers.Adam(lr=0.01),
loss=losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'] # 设置测量指标为准确率
)
模型训练
.fit( )方法
模型装配完成后,即可通过fit()函数送入待训练的数据集和验证用的数据集,进行训练
1
2
3
4# 指定训练集为train_db,验证集为val_db,训练5 个epochs,每2 个epoch 验证一次
# 返回训练轨迹信息保存在history 对象中
history = network.fit(train_db, epochs=5, validation_data=val_db,
validation_freq=2,callback=[tensorboard])
模型测试,推理
.predict( )方法
可以进行模型推理,并返回预测结果
.evaluate( )方法
可以直接测试指定数据集所有样本,并打印出性能指标
自定义网络
Sequential 容器适合于数据按序从第一层传播到第二层,再从第二层传播到第三层,以
此规律传播的网络模型。对于复杂的网络结构,例如第三层的输入不仅是第二层的输出,
还有第一层的输出,此时使用自定义网络更加灵活。
- 网络层的创建
- 前向运算逻辑
1 | class MyModel(keras.Model): |
模型保存和加载
张量方式
Model.save_weights(path)
通过调用Model.save_weights(path)方法即可将当前的网络参数保存到path 文件上,
Model.load_weights(path)
然后调用网络对象的load_weights(path)方法即可将指定的模型文件中保存的张量数值写入
到当前网络参数中去
网络方式
Model.save(path)
将模型的参数和结构都保存到path上,一般以h5为文件后缀
tf.keras.models.load_model(file)
加载已保存的模型文件( 用Model.save( ) 和tf.saved_model.save( ) )
savemodel方式
将网络及参数保存为pb格式,方便其他工具读取,如pytorch,Netron, 也方便跨平台使用
tf.saved_model.save(model,path)
保存模型与参数数据
tf.saved_model.load(path)
加载模型
Loading Keras models
Keras models are trackable, so they can be saved to SavedModel. The object returned by
tf.saved_model.loadis not a Keras object (i.e. doesn’t have.fit,.predict, etc. methods). A few attributes and functions are still available:.variables,.trainable_variablesand.__call__.所以我们如果要加载回keras模型可以用回tf.keras.models.load_model(file)
加载模型
在keras.application中有多种在ImageNet上训练好参数的模型,可以直接调用
如:
1 | from tensorflow import keras |
测量工具
keras。。。
可视化
关键工具TensorBoard和关键模块tf.summary或来自tf.keras.model模块中的callback里tf.keras.callbacks.TensorBoard
在cmd中使用
1 | tensorboard --logdir=PATH |
> 就是保存log_dir的路径
keras.Model类中fit方法使用callback
Example(Basic):
1 | tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=".\\logs") |
Example(Profile):
1 | # profile a single batch, e.g. the 5th batch. |
关键模块tf.summary
1 | summary_writer=tf.summary.create_file_writer(log_dir) |


