3. 多层感知机
3.1 神经网络图
多层感知机 vs 单层神经网络:
在单层神经网络的基础上,引入了一到多个隐藏层(hidden layer)。
隐藏层位于输入层和输出层之间。
如下图所示:
输入和输出个数分别为4和3,中间的隐藏层包含5个隐藏单元(hidden unit)。
多层感知机的层数为2,且隐藏层和输出层都为全连接层。
多层感知机
3.2 矢量计算表达式
给定一个小批量样本,其批量大小为,输入个数为。
若仅有一个隐藏层,且隐藏单元个数为。记隐藏层的输出(隐藏变量)为,有。
设隐藏层的权重参数和偏差参数分别为、,输出层的权重和偏差参数分别为、。
则,有输出的计算为:
即,将隐藏层的输出直接作为输出层的输入。
若将(1)式代入(2)式,可得:
由此可以发现,虽然引入了隐藏层,却依然等价于一个单层神经网络(输出层权重参数为,偏差参数为)。
3.3 激活函数
上述问题根源:
全连接层只对数据做仿射变换(affine transformation),多个仿射变换的叠加仍然是一个仿射变换。
—— 仿射变换:线性变换+平移(变换前是直线的,变换后依然是直线;直线比例保持不变)
解决方法之一:引入非线性变换
如,对隐藏变量使用按元素运算的非线性函数进行变换,然后再作为下一个全连接层的输入。
那么,这个非线性函数称为激活函数(activation function)。
3.3.1 ReLU函数
给定元素,ReLU(rectified linear unit)函数定义为:
即,只保留正数元素,并将负数元素归零。
可直观地绘图如下:
%matplotlib inline
import tensorflow as tf
import matplotlib.pyplot as plt
def use_svg_display():
# 用矢量图显示
%config InlineBackend.figure_format='svg'
def xyplot(x,y,name):
use_svg_display()
fig,ax = plt.subplots(figsize=(5,2.5))
plt.plot(x.numpy(),y.numpy())
plt.xlabel('x')
plt.ylabel(name+'(x)')
x = tf.Variable(tf.range(-8,8,0.1),dtype=tf.float32)
y = tf.nn.relu(x)
xyplot(x,y,'relu')
3.3.2 Sigmoid函数
给定元素,Sigmoid函数定义为:
即,将元素值变换到0至1之间。
可直观地绘图如下:
y = tf.nn.sigmoid(x)
xyplot(x,y,'sigmoid')
3.3.3 tanh函数
给定元素,tanh函数定义为:
即,将元素值变换到-1至1之间。
可直观地绘图如下:
y = tf.nn.tanh(x)
xyplot(x,y,'tanh')
3.4 多层感知机
多层感知机,是含有至少一个隐藏层的由全连接层组成的神经网络,且每个隐藏层的输出通过激活函数进行变换。
以单隐藏层为例,沿用3.2小节定义的符号,多层感知机的输出可计算如下:
其中,表示激活函数。
3.5 代码实现
与softmax回归区别:
增加了一个全连接层作为隐藏层。隐藏单元个数为256,并使用ReLU函数作为激活函数。
import tensorflow as tf
from tensorflow import keras
model = keras.models.Sequential(
[keras.layers.Flatten(input_shape=(28,28)),
keras.layers.Dense(256,activation='relu'),
keras.layers.Dense(10,activation='softmax')]
)
fashion_mnist = keras.datasets.fashion_mnist
(x_train,y_train),(x_test,y_test) = fashion_mnist.load_data()
x_train = x_train/255.0
x_test = x_test/255.0
model.compile(
optimizer=keras.optimizers.SGD(0.5),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
model.fit(x_train,
y_train,
batch_size=256,
epochs=5,
validation_data=(x_test,y_test)
,validation_freq=1)
输出:
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 1s 24us/sample - loss: 0.7909 - accuracy: 0.7127 - val_loss: 0.7150 - val_accuracy: 0.7203
Epoch 2/5
60000/60000 [==============================] - 1s 16us/sample - loss: 0.4734 - accuracy: 0.8257 - val_loss: 0.5336 - val_accuracy: 0.8011
Epoch 3/5
60000/60000 [==============================] - 1s 15us/sample - loss: 0.4192 - accuracy: 0.8453 - val_loss: 0.4297 - val_accuracy: 0.8404
Epoch 4/5
60000/60000 [==============================] - 1s 15us/sample - loss: 0.3895 - accuracy: 0.8572 - val_loss: 0.4431 - val_accuracy: 0.8303
Epoch 5/5
60000/60000 [==============================] - 1s 15us/sample - loss: 0.3680 - accuracy: 0.8648 - val_loss: 0.4280 - val_accuracy: 0.8481