You are on page 1of 66

第八章:

经典卷积神经网络(上)
学习目标 狗熊会 | 深度学习入门

1 . LeNet-5 的网络结构及其代码实现;
2 . AlexNet 的网络结构及其代码实现;
3 . VGG 的网络结构及其代码实现;
4 . Batch Normalization 的原理与应用技巧;
5 . Data Augmentation 的原理与应用技巧。

狗熊会|聚数据英才,助产业振兴
PART 8.1
LeNet-5

狗熊会|聚数据英才,助产业振兴
8.1.1 LeNet-5 网络结构 狗熊会 | 深度学习入门

 LeNet-5 介绍:
 由 Yann LeCun (杨立昆)于 1998 年提出的一种经典的卷积网络结构。
 第一个成功应用于数字识别问题的卷积神经网络。
 LeNet-5 网络结构:共 7 层
 输入层
 卷积层
 池化层
 卷积层
 池化层
 全连接层
 输出层

狗熊会|聚数据英才,助产业振兴
8.1.2 案例: LeNet-5 手写数字识 狗熊会 | 深度学习入门


 MNIST 数据集展示: mnist.load_data() 加载数据集
 数据预处理 输出:
(60000, 28,
 LeNet-5 代码实现
28)
 LeNet-5 编译运行
from Keras.datasets import mnist
(X0,Y0),(X1,Y1) =
mnist.load_data()
print(X0.shape)
from matplotlib import pyplot as
plt
plt.figure()
fig,ax = plt.subplots(2,5)
ax=ax.flatten()
for i in range(10):
Im=X0[Y0==i][0]
ax[i].imshow(Im)
plt.show();

狗熊会|聚数据英才,助产业振兴
8.1.2 案例: LeNet-5from
手写数字识
Keras.utils import 狗熊会 | 深度学习入门


np_utils
N0=X0.shape[0];N1=X1.shape[0]
 MNIST 数据集展示 print([N0,N1])
X0 =
 数据预处理 X0.reshape(N0,28,28,1)/255
X1 =
 LeNet-5 代码实现 X1.reshape(N1,28,28,1)/255
YY0 =
 LeNet-5 编译运行
np_utils.to_categorical(Y0)
YY1 =
np_utils.to_categorical(Y1)
print(YY1)

输出:

[60000, 10000]
[[0 0 0 ... 1 0 0]
[0 0 1 ... 0 0 0]
[0 1 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]
狗熊会|聚数据英才,助产业振兴
8.1.2 案例: LeNet-5 手写数字识 狗熊会 | 深度学习入门


 MNIST 数据集展示
from Keras.layers import
 数据预处理 Conv2D,Dense,Flatten,Input,MaxPooling2D
 LeNet-5 代码实现 from Keras import Model

 LeNet-5 编译运行 input_layer = Input([28,28,1])


x = input_layer
x = Conv2D(6,[5,5],padding = "same", activation = 'relu')(x)
x = MaxPooling2D(pool_size = [2,2], strides = [2,2])(x)
x = Conv2D(16,[5,5],padding = "valid", activation = 'relu')(x)
x = MaxPooling2D(pool_size = [2,2], strides = [2,2])(x)
x = Flatten()(x)
x = Dense(120,activation = 'relu')(x)
x = Dense(84,activation = 'relu')(x)
x = Dense(10,activation = 'softmax')(x)
output_layer=x
model=Model(input_layer,output_layer)
model.summary()

狗熊会|聚数据英才,助产业振兴
8.1.2 案例: LeNet-5 手写数字识 狗熊会 | 深度学习入门

别 输出维度 参数个数
 MNIST 数据集展示
 数据预处理 输入层
 LeNet-5 代码实现 卷积层
 模型结构展示 1
池化层
 LeNet-5 编译运行 1
卷积层
池化层2
2
拉直操作
全连接层 1
全连接层 2
全连接层 3

狗熊会|聚数据英才,助产业振兴
8.1.2 案例: LeNet-5 手写数字识 狗熊会 | 深度学习入门


 MNIST 数据集展示
 数据预处理
 LeNet-5 代码实现
 LeNet-5 编译运行
 通过 model.compile 实现
model.compile(loss='categorical_crossentropy', optimizer='adam',
metrics=['accuracy'])
model.fit(X0, YY0, epochs=10, batch_size=200, validation_data=[X1,YY1])

狗熊会|聚数据英才,助产业振兴
Input X 卷积计算 激活 池化 卷积计算 激活 池化

𝑒𝑥𝑝 ( 𝑥𝑘 )
𝑦 𝑘=
∑ 𝑒𝑥𝑝( 𝑥 𝑘)
𝑘
x

Output y 激活 仿射变换 激活 仿射变换 激活 仿射变换

y=
def softmax(x) def cross_entropy_error(y,t)
交叉熵 exp_x=np.exp(x) delta=1e-7
t= sum_exp_x=np.sum(exp_x) return -
y=exp_x/sum_exp_x np.sum(t*np.log(y+delta))
L=- return y
真值 t
Input X 卷积计算 激活 池化 卷积计算 激活 池化

Output y 激活 仿射变换 激活 仿射变换 激活 仿射变换

反向传播
交叉熵
正向传播

真值 t
Input X 卷积计算 激活 池化 卷积计算 激活 池化

𝑒𝑥𝑝 ( 𝑥𝑘 )
𝑦 𝑘=
∑ 𝑒𝑥𝑝( 𝑥 𝑘)
𝑘
x

Output y 激活 仿射变换 激活 仿射变换 激活 仿射变换

𝜕𝐿
y= =1 𝜕 𝐿 . 𝜕 𝐿 ={ 𝜕 𝐿 } class SoftmaxWithLoss:
𝜕𝐿 𝜕 𝑋 𝜕 𝐿 𝜕𝑥 𝑗 def __init__(self):
损失 - 交叉 self.loss=None
𝜕𝐿 𝜕𝐿
t= 熵 𝑑𝑜𝑢𝑡 ={ } self.y=None
𝜕 𝑋 𝜕𝑥𝑗 self.t=None
L=-
真值 t def forward(self,x,t):
self.t=t
self.y=softmax(x)
def softmax(x): self.loss=cross_entropy_error(self.y,self.t)
exp_x=np.exp(x) return self.loss
sum_exp_x=np.sum(exp_x)
y=exp_x/sum_exp_x def backward(self,dout=1):
return y batch_size=self.t.shape[0]
dx=(self.y-self.t)/batch_size
def cross_entropy_error(y,t):
delta=1e-7 return dx
return -np.sum(t*np.log(y+delta))
Input X 卷积计算 激活 池化 卷积计算 激活 池化

𝑒𝑥𝑝 ( 𝑥𝑘 )
𝑦 𝑘=
∑ 𝑒𝑥𝑝( 𝑥 𝑘)
𝑘
x XX
Output y 激活 仿射变换 激活 仿射变换 激活 仿射变换

y=
𝜕𝐿
=1
𝜕𝐿 𝜕𝐿 𝜕𝐿 𝜕 𝑋
损失 - 交叉 = .

𝜕 𝑋𝑋 𝜕 𝑋 𝜕 𝑋𝑋
t=
𝜕𝐿 𝜕𝐿 𝜕 𝑋
L=- = .
真值 t 𝜕𝑊 𝜕 𝑋 𝜕𝑊
𝜕𝐿 𝜕𝐿 𝜕𝐿 𝜕𝐿 𝜕𝐿 𝜕𝑋 X=W.XX+B
. ={ } = . W .XX
𝜕 𝑋 𝜕 𝐿 𝜕𝑥 𝑗 𝜕𝐵 𝜕 𝑋 𝜕𝐵
XX x
𝑑𝑜𝑢𝑡
𝜕𝐿
={
𝜕𝐿
}
𝜕𝐿
=𝑑𝑜𝑢𝑡 .
𝜕𝑋
W
DOT
仿射变换
+
𝜕 𝑋 𝜕𝑥𝑗 𝜕 𝑋𝑋 𝜕 𝑋𝑋
𝜕𝐿 𝜕𝑋
=𝑑𝑜𝑢𝑡 . B
𝜕𝑊 𝜕𝑊
𝜕𝐿 𝜕𝑋
=𝑑𝑜𝑢𝑡 .
𝜕𝐵 𝜕𝐵
𝜕𝐿 𝜕𝐿 𝜕 𝑋 𝜕𝐿 𝜕𝑋
= . =𝑑𝑜𝑢𝑡 .
X=W.XX+B 𝜕 𝑋𝑋 𝜕 𝑋 𝜕 𝑋𝑋 𝜕 𝑋𝑋 𝜕 𝑋𝑋
XX
W .XX 𝜕𝐿 𝜕𝐿 𝜕 𝑋 𝜕𝐿 𝜕𝑋
= . =𝑑𝑜𝑢𝑡 .
W
DOT
仿射变换
+ 𝜕𝑊
𝜕𝐿
=
𝜕 𝑋 𝜕𝑊
𝜕𝐿 𝜕𝑋
.
𝜕𝑊
𝜕𝐿
=𝑑𝑜𝑢𝑡 .
𝜕𝑊
𝜕𝑋
𝜕𝐵 𝜕 𝑋 𝜕𝐵 𝜕𝐵 𝜕𝐵
B 𝜕𝐿 𝜕𝐿 𝜕 𝑋
= . =𝑊 ‘
𝜕 𝑋𝑋 𝜕 𝑋 𝜕 𝑋𝑋
𝜕𝐿 𝜕𝐿 𝜕 𝑋 𝜕𝐿
= . = 𝑋𝑋 ’ .
𝜕𝑊 𝜕 𝑋 𝜕𝑊 𝜕𝑋
𝜕𝐿 𝜕𝐿 𝜕𝑋
= .
𝜕𝐵 𝜕 𝑋 𝜕𝐵
class Affine:
def __init__(self,w,b):
self.w=w
self.b=b
self.xx=None
self.dw=None
self.db=None
def forward(self,xx,t):
self.xx=xx
out=np.dot(xx,self.w)+self.b
return out
def backward(self,dout):
dxx=np.dot(dout,self.w.T)
self.dw=np.dot(self.xx.T,dout)
self.db=np.sum(dout,axis=0)
return dxx
W .XX X=W.XX+B
XX

W
DOT +
B

𝜕𝐿 𝜕𝐿 𝜕 𝑋 𝜕𝐿 𝜕𝑋 𝜕𝐿 𝜕𝐿 𝜕 𝑋
= . =𝑑𝑜𝑢𝑡 . = . =𝑊 ‘
𝜕 𝑋𝑋 𝜕 𝑋 𝜕 𝑋𝑋 𝜕 𝑋𝑋 𝜕 𝑋𝑋 𝜕 𝑋𝑋 𝜕 𝑋 𝜕 𝑋𝑋
𝜕𝐿 𝜕𝐿 𝜕 𝑋 𝜕𝐿 𝜕𝑋 𝜕𝐿 𝜕𝐿 𝜕 𝑋 𝜕𝐿
= . =𝑑𝑜𝑢𝑡 . = . = 𝑋𝑋 ’ .
𝜕𝑊 𝜕 𝑋 𝜕𝑊 𝜕𝑊 𝜕𝑊 𝜕𝑊 𝜕 𝑋 𝜕𝑊 𝜕𝑋
𝜕𝐿 𝜕𝐿 𝜕𝑋 𝜕𝐿 𝜕𝑋 𝜕𝐿 𝜕𝐿 𝜕𝑋
= . =𝑑𝑜𝑢𝑡 . = .
𝜕𝐵 𝜕 𝑋 𝜕𝐵 𝜕𝐵 𝜕𝐵 𝜕𝐵 𝜕 𝑋 𝜕𝐵
Input X 卷积计算 激活 池化 卷积计算 激活 池化

𝑒𝑥𝑝 ( 𝑥𝑘 )
𝑦 𝑘=
∑ 𝑒𝑥𝑝( 𝑥 𝑘) x
𝑘

Output y 激活 仿射变换 激活 仿射变换 激活 仿射变换

𝜕𝐿 𝜕𝐿 𝜕𝐿 𝜕𝐿 class Affine:
y= =1 𝜕 𝑋 . 𝜕 𝐿 ={ 𝜕𝑥 }class SoftmaxWithLoss: def __init__(self,w,b):
𝜕𝐿 𝑗 def __init__(self):
self.w=w
损失 - 交叉 self.loss=None
self.b=b
t= 熵 self.y=None
self.xx=None
self.t=None
L=- self.dw=None
真值 t def forward(self,x,t):
self.db=None
self.t=t
def forward(self,xx,t):
self.y=softmax(x)
self.xx=xx
def softmax(x): out=np.dot(xx,self.w)+self.b
exp_x=np.exp(x) self.loss=cross_entropy_error(self.y,self.t)
sum_exp_x=np.sum(exp_x) return self.loss return out
y=exp_x/sum_exp_x def backward(self,dout=1): def backward(self,dout):
return y dxx=np.dot(dout,self.w.T)
batch_size=self.t.shape[0]
def cross_entropy_error(y,t): dx=(self.y-self.t)/batch_size self.dw=np.dot(self.xx.T,dout)
delta=1e-7 return dx self.db=np.sum(dout,axis=0)
return -np.sum(t*np.log(y+delta)) return dxx
方法 __init__() 是一个特殊的方法,包含?个形参 。在这个方法的定义中,
形参 self 必不可少,还必须位于其他形参的前面。因为 Python 调用这个
__init__() 方法来创建 实例时,将自动传入实参 self 。每个与类相关联的
方法调用都自动传递实参 self ,它是一个指向实例本身 的引用,让实例能
够访问类中的属性和方法。

class Lenet5:
def __init__(self, input_dim=(1, 32, 32),
conv_param={'filter_num1':6, 'filter_size1':3,'filter_num2':16, 'filter_size2':3, 'pad':1, 'stride':1},
hidden_size1=120,hidden_size2=84, output_size=10, weight_init_std=0.01):
filter_num1 = conv_param['filter_num1']
filter_size1 = conv_param['filter_size1']
filter_num2 = conv_param['filter_num2']
filter_size2 = conv_param['filter_size2']
filter_pad = conv_param['pad']
filter_stride = conv_param['stride']
input_size = input_dim[1]
conv_output_size1 = (input_size - filter_size1 + 2*filter_pad) / filter_stride + 1
pool_output_size1 = (conv_output_size1 - 2) / 2 + 1
conv_output_size2 = (pool_output_size1 - filter_size2 + 2*filter_pad) / filter_stride + 1
pool_output_size2 = int((((conv_output_size2 - 2) / 2 + 1)**2)*filte r_num2)
self.params = {}
self.params['W1'] = weight_init_std * np.random.randn(filter_num1, input_dim[0], filter_size1, filter_size1)
self.params['b1'] = np.zeros(filter_num1)
self.params['W2'] = weight_init_std * np.random.randn(filter_num2, filter_num1, filter_size2, filter_size2)
self.params['b2'] = np.zeros(filter_num2)
self.params['W3'] = weight_init_std *np.random.randn(pool_output_size2, hidden_size1)
self.params['b3'] = np.zeros(hidden_size1)
self.params['W4'] = weight_init_std * np.random.randn(hidden_size1, hidden_size2)
self.params['b4'] = np.zeros(hidden_size2)
self.params['W5'] = weight_init_std * np.random.randn(hidden_size2, output_size)
self.params['b5'] = np.zeros(output_size)
self.layers = OrderedDict()
self.layers['Conv1'] = common.Convolution(self.params['W1'], self.params['b1'],conv_param['stride'], conv_param['pad'])
self.layers['Relu1'] = common.Relu()
self.layers['Pool1'] = common.MaxPooling(pool_h=2, pool_w=2, stride=2)
self.layers['Conv2'] = common.Convolution(self.params['W2'], self.params['b2'],conv_param['stride'], conv_param['pad'])
self.layers['Relu2'] = common.Relu()
self.layers['Pool2'] = common.MaxPooling(pool_h=2, pool_w=2, stride=2)
self.layers['Affine1'] = common.Affine(self.params['W3'], self.params['b3'])
self.layers['Relu3'] = common.Relu()
self.layers['Affine2'] = common.Affine(self.params['W4'], self.params['b4'])
self.layers['Relu4'] = common.Relu()
self.layers['Affine3'] = common.Affine(self.params['W5'], self.params['b5'])
self.last_layer = common.SoftmaxWithCrossEntropy()
def predict(self, x): def accuracy(self, x, t, batch_size=100):
for layer in self.layers.values(): # 从独热编码转回数字编码
x = layer.forward(x) if t.ndim != 1 : t = np.argmax(t, axis=1)
return x acc = 0.0
for i in range(int(x.shape[0] / batch_size)):
def loss(self, x, t): tx = x[i*batch_size:(i+1)*batch_size]
y = self.predict(x) tt = t[i*batch_size:(i+1)*batch_size]
return self.last_layer.forward(y, t) y = self.predict(tx)
y = np.argmax(y, axis=1)
acc += np.sum(y == tt)

return acc / x.shape[0]


def gradient(self, x, t): # 只保留权重信息,不包含网络模型
# forward def save_params(self, file_name="params.pkl"):
self.loss(x, t) params = {}
# backward for key, val in self.params.items():
dout = 1 params[key] = val
dout = self.last_layer.backward(dout) with open(file_name, 'wb') as f:
pickle.dump(params, f)
layers = list(self.layers.values())
layers.reverse() def load_params(self, file_name="params.pkl"):
for layer in layers: with open(file_name, 'rb') as f:
dout = layer.backward(dout) params = pickle.load(f)
# 設定 for key, val in params.items():
grads = {} self.params[key] = val
grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].db
grads['W2'], grads['b2'] = self.layers['Conv2'].dW, self.layers['Conv2'].db for i, key in enumerate(['Conv1', 'Conv2','Affine1',
grads['W3'], grads['b3'] = self.layers['Affine1'].dW, self.layers['Affine1'].db 'Affine2','Affine3']):
grads['W4'], grads['b4'] = self.layers['Affine2'].dW, self.layers['Affine2'].db self.layers[key].W = self.params['W' + str(i+1)]
grads['W5'], grads['b5'] = self.layers['Affine3'].dW, self.layers['Affine3'].db self.layers[key].b = self.params['b' + str(i+1)]
return grads
PART 8.2
AlexNet

狗熊会|聚数据英才,助产业振兴
8.2.1 AlexNet 网络结构 狗熊会 | 深度学习入门

 AlexNet 介绍:
 ImageNet 竞赛冠军获得者 Hinton 和他的学生 Krizhevsky Alex 于 2012 年设计。
 ImageNet 竞赛中第一个使用卷积神经网络的参赛者。
 AlexNet 网络结构: 8 层
 卷积层
 池化层
 卷积层
 池化层
 卷积层
 卷积层
 卷积层
 池化层
 输出层:三个全连接层
狗熊会|聚数据英才,助产业振兴
8.2.2 AlexNet 创新点 狗熊会 | 深度学习入门

 AlexNet 创新点:
 成功使用 ReLU 作为 CNN 的激活函数;
 使用 Dropout 随机忽略一部分神经元,避免模型过拟合;
 在 CNN 中使用重叠的最大值池化 ( 步长小于卷积核 ) ;
 提出局部响应归一化层( Local Response Normalization , LRN ),后逐渐被 BN ( Batch
Normalization )代替;
 使用 CUDA 加速神经网络的训练,利用了 GPU 强大的计算能力;
 采用了数据增强( Data Augmentation )技术,达到增加样本量的目的。

狗熊会|聚数据英才,助产业振兴
8.2.2 AlexNet 创新点 狗熊会 | 深度学习入门

 AlexNet 创新点:
 成功使用 ReLU 作为 CNN 的激活函数;
 使用 Dropout 随机忽略一部分神经元,避免模型过拟合;
 在 CNN 中使用重叠的最大值池化 ( 步长小于卷积核 ) ;
 克服梯度消失的问题
 提出局部响应归一化层( Local Response Normalization , LRN ),后逐渐被 BN ( Batch
 加快训练速度
Normalization )代替;
 使用 CUDA 加速神经网络的训练,利用了 GPU 强大的计算能力;
 采用了数据增强( Data Augmentation )技术,达到增加样本量的目的。

狗熊会|聚数据英才,助产业振兴
8.2.2 AlexNet 创新点 狗熊会 | 深度学习入门

Dropout :指深度学习训练过程中,对于神经网络训练单元,按照一定的概率将其
从网络中移除,注意是暂时,对于随机梯度下降来说,由于是随机丢弃,故而每一
个 mini-batch 都在训练不同的网络

狗熊会|聚数据英才,助产业振兴
8.2.2 AlexNet 创新点 狗熊会 | 深度学习入门

 AlexNet 创新点:
 成功使用 ReLU 作为 CNN 的激活函数;
 使用 Dropout 随机忽略一部分神经元,避免模型过拟合;
 在 CNN 中使用重叠的最大值池化 ( 步长小于卷积核 ) ;
 提出局部响应归一化层( Local Response Normalization , LRN ),后逐渐被 BN ( Batch
Normalization )代替;
 使用 CUDA 加速神经网络的训练,利用了 GPU 强大的计算能力;
 采用了数据增强( Data Augmentation )技术,达到增加样本量的目的。

狗熊会|聚数据英才,助产业振兴
8.2.2 AlexNet 创新点 狗熊会 | 深度学习入门

神经网络在开始的时候并 为了获得更多的数据,微
不是那么聪明。比如,一 小的改变:旋转( flips )、
个欠训练的神经网络会认 移位( translations )、旋
转( rotations )等微小的
为这三个如下的网球是不
改变
同、独特的图片。

狗熊会|聚数据英才,助产业振兴
8.2.3 案例:中文字体识别——隶书和行楷 狗熊会 | 深度学习入门

 数据准备
 二分类问题
 对数据的存储目录结构是有特殊要求
 构造数据生成器
 AlexNet 代码实现
 AlexNet 编译运行

狗熊会|聚数据英才,助产业振兴
8.2.3 案例:中文字体识别——隶书和行楷 狗熊会 | 深度学习入门

 数据准备
 构造数据生成器:一种特有的数据读入方法。按照特定的目录结构和要求把相应少量的、多批次的数据读
入内存,做相应的数据分析。
 代价:时间的延长和效率的降低
 优点:有限的内存资源的支持下,处理非常大的数据
 代码: ImageDataGenerator()
 AlexNet 代码实现
 AlexNet 编译运行

狗熊会|聚数据英才,助产业振兴
8.2.3 案例:中文字体识别——隶书和行楷 狗熊会 | 深度学习入门

 数据准备
 构造数据生成器
from Keras.preprocessing.image import ImageDataGenerator
 数据生成器 IMSIZE=227
validation_generator = ImageDataGenerator(rescale=1./255).flow_from_directory(
 AlexNet 代码实现 './data_alex/ChineseStyle/test/',
target_size=(IMSIZE, IMSIZE),
 AlexNet 编译运行 batch_size=200,
class_mode='categorical')
train_generator = ImageDataGenerator(rescale=1./255).flow_from_directory(
'./data_alex/ChineseStyle/train',
target_size=(IMSIZE, IMSIZE),
batch_size=200,
class_mode='categorical')

狗熊会|聚数据英才,助产业振兴
8.2.3 案例:中文字体识别——隶书和行楷 狗熊会 | 深度学习入门

from matplotlib import pyplot as plt


 数据准备
plt.figure()
 构造数据生成器 fig,ax = plt.subplots(2,5)
fig.set_figheight(7)
 输出图像 fig.set_figwidth(15)
 AlexNet 代码实现 ax=ax.flatten()
X,Y=next(validation_generator)
 AlexNet 编译运行 for i in range(10): ax[i].imshow(X[i,:,:,:])

狗熊会|聚数据英才,助产业振兴
8.2.3 案例:中文字体识别——隶书和行楷 狗熊会 | 深度学习入门

from Keras.layers import Activation,Conv2D, BatchNormalization, Dense


 数据准备 from Keras.layers import Dropout, Flatten, Input, MaxPooling2D, ZeroPadding2D
from Keras import Model
 构造数据生成器
IMSIZE = 227
 AlexNet 代码实现 input_layer = Input([IMSIZE,IMSIZE,3])
x = input_layer
 AlexNet 编译运行 x = Conv2D(96,[11,11],strides = [4,4], activation = 'relu')(x)
x = MaxPooling2D([3,3], strides = [2,2])(x)
x = Conv2D(256,[5,5],padding = "same", activation = 'relu')(x)
x = MaxPooling2D([3,3], strides = [2,2])(x)
x = Conv2D(384,[3,3],padding = "same", activation = 'relu')(x)
x = Conv2D(384,[3,3],padding = "same", activation = 'relu')(x)
x = Conv2D(256,[3,3],padding = "same", activation = 'relu')(x)
x = MaxPooling2D([3,3], strides = [2,2])(x)
x = Flatten()(x)
x = Dense(4096,activation = 'relu')(x)
x = Dropout(0.5)(x)
x = Dense(4096,activation = 'relu')(x)
x = Dropout(0.5)(x)
x = Dense(2,activation = 'softmax')(x)
output_layer=x
model=Model(input_layer,output_layer)
model.summary()

狗熊会|聚数据英才,助产业振兴
8.2.3 案例:中文字体识别——隶书和行楷 狗熊会 | 深度学习入门

输出维度 参数个数

 数据准备
 构造数据生成器
 AlexNet 代码实现
 模型结构展示
 AlexNet 编译运行

Dropout 操作

狗熊会|聚数据英才,助产业振兴
8.2.3 案例:中文字体识别——隶书和行楷 狗熊会 | 深度学习入门

 数据准备
 构造数据生成器
 AlexNet 代码实现
 AlexNet 编译运行
from Keras.optimizers import Adam
model.compile(loss='categorical_crossentropy',optimizer=Adam(lr=0.001),metrics=['accuracy
'])
model.fit_generator(train_generator,epochs=20,validation_data=validation_generator)

狗熊会|聚数据英才,助产业振兴
PART 8.3
VGG

狗熊会|聚数据英才,助产业振兴
8.3.1 VGG 网络结构 狗熊会 | 深度学习入门

 VGG 介绍
 牛津大学计算机视觉组和 DeepMind 公
司共同研发的一种深度卷积神经网络
 VGG 网络结构: 6 种
 从左到右深度越来越深
 加粗体表示新增的层
 所有网络结构都包含 5 组卷积操作,每组卷积
包含一定数量的卷积层——可以看作一个五阶
段的卷积特征提取。

狗熊会|聚数据英才,助产业振兴
8.3.1 VGG 网络结构 狗熊会 | 深度学习入门

 VGG16 网络结构: 5 组卷积组和 3 个全连接层


 输入层: 224×224×3 的彩色图像。
 第 1 组卷积层( 2 次卷积): Conv2D(3×3 , 64), Stride(1), same, ReLU, Output:
224×224×64 。
 第 1 个池化层: MaxPooling2D(2×2), Stride(2), Output: 112×112×64 。
 第 2 组卷积层( 2 次卷积): Conv2D(3×3 , 128), Stride(1), same, ReLU, Output:
112×112×128 。
 第 2 个池化层: MaxPooling2D(2×2), Stride(2), Output: 。
 第 3 组卷积层( 3 次卷积): Conv2D(3×3 , 256), Stride(1), same, ReLU, Output:
56×56×256 。
 第 3 个池化层: MaxPooling2D(2×2), Stride(2), Output: 。
 第 4 组卷积层( 3 次卷积): Conv2D(3×3 , 512), Stride(1), same, ReLU, Output:
28×28×512 。
 第 4 个池化层: MaxPooling2D(2×2), Stride(2), Output: 。
狗熊会|聚数据英才,助产业振兴
8.3.1 VGG 网络结构 狗熊会 | 深度学习入门

 VGG16 网络结构: 5 组卷积组和 3 个全连接层

狗熊会|聚数据英才,助产业振兴
8.3.2 案例:加利福尼亚理工学院鸟类数据库分类 狗熊会 | 深度学习入门

 数据准备与处理
 数据生成器生成训练集与测试集
 VGG16 代码实现 from Keras.preprocessing.image import ImageDataGenerator
 VGG16 编译运行 IMSIZE = 224
train_generator = ImageDataGenerator(
 VGG16 + BN 代码实现 rescale=1. / 255).flow_from_directory(
'./data_vgg/train',
target_size=(IMSIZE, IMSIZE),
batch_size=100,
class_mode='categorical')
validation_generator = ImageDataGenerator(
rescale=1. / 255).flow_from_directory(
'./data_vgg/test',
target_size=(IMSIZE, IMSIZE),
batch_size=100,
class_mode='categorical')

狗熊会|聚数据英才,助产业振兴
8.3.2 案例:加利福尼亚理工学院鸟类数据库分类 狗熊会 | 深度学习入门

from matplotlib import pyplot as plt

 数据准备与处理 plt.figure()
fig, ax = plt.subplots(2, 5)
 数据生成器生成训练集与测试集
fig.set_figheight(6)
 图像展示 fig.set_figwidth(15)
ax = ax.flatten()
 VGG16 代码实现 X, Y = next(validation_generator)
for i in range(10):
 VGG16 编译运行
ax[i].imshow(X[i, :, :, ])
 VGG16 + BN 代码实现

狗熊会|聚数据英才,助产业振兴
8.3.2 案例:加利福尼亚理工学院鸟类数据库分类 狗熊会 | 深度学习入门

 数据准备与处理
 VGG16 代码实现
 VGG16 结构展示
 VGG16 编译运行
 VGG16 + BN 代码实现

狗熊会|聚数据英才,助产业振兴
8.3.2 案例:加利福尼亚理工学院鸟类数据库分类 狗熊会 | 深度学习入门

 数据准备与处理
 VGG16 代码实现
 VGG16 编译运行
 VGG16 + BN 代码实现

from Keras.optimizers import Adam


model_vgg16.compile(loss='categorical_crossentropy',optimizer=Adam(lr=0.001),
metrics=['accuracy'])
model_vgg16.fit_generator(train_generator,epochs=20,validation_data=validation_generat
or)

狗熊会|聚数据英才,助产业振兴
8.3.2 案例:加利福尼亚理工学院鸟类数据库分类 狗熊会 | 深度学习入门

 数据准备与处理
 VGG16 代码实现
 VGG16 编译运行
 VGG16 + BN 代码实现
 为了提高分类的准确率,可以尝试在每一层进行 Batch Normalization 的操作
x = BatchNormalization(axis=3)
 代码示例: (x)

狗熊会|聚数据英才,助产业振兴
PART 8.4
Batch Normalization 的技巧

狗熊会|聚数据英才,助产业振兴
8.4.1 Batch Normalization 的核心思想 狗熊会 | 深度学习入门

存在问题:感官系统失效了。

狗熊会|聚数据英才,助产业振兴
8.4.1 Batch Normalization 的核心思想 狗熊会 | 深度学习入门

 Batch :只使用训练集中的一小部分样本对模型权重进行一次反向传播的参数更新,这一小部分样本被称
作 batch ,也称之为批次。

 Batch Normalization 的核心思想:

狗熊会|聚数据英才,助产业振兴
8.4.2 带有 BN 的逻辑回归 狗熊会 | 深度学习入门

 数据准备与展示
from keras.preprocessing.image import ImageDataGenerator
 猫狗图像分类数据
IMSIZE=128
 数据生成器生成训练集与测试集
 带有 BN 的逻辑回归模型 validation_generator =
ImageDataGenerator(rescale=1./255).flow_from_directory(
'./data_bn/CatDog/validation',
target_size=(IMSIZE, IMSIZE),
batch_size=200,
class_mode='categorical')

train_generator =
ImageDataGenerator(rescale=1./255).flow_from_directory(
'./data_bn/CatDog/train',
target_size=(IMSIZE, IMSIZE),
batch_size=200,
class_mode='categorical')

狗熊会|聚数据英才,助产业振兴
8.4.2 带有 BN 的逻辑回归 狗熊会 | 深度学习入门

 数据准备与展示
 猫狗图像分类数据
 数据生成器生成训练集与测试集
 展示图像
 带有 BN 的逻辑回归模型

狗熊会|聚数据英才,助产业振兴
8.4.2 带有 BN 的逻辑回归 狗熊会 | 深度学习入门

 数据准备与展示
 带有 BN 的逻辑回归模型

from keras.layers import Flatten,Input,BatchNormalization,Dense


from keras import Model
input_layer=Input([IMSIZE,IMSIZE,3])
x=input_layer
x=BatchNormalization()(x)
x=Flatten()(x)
x=Dense(2,activation='softmax')(x)
output_layer=x
model1=Model(input_layer,output_layer)
model1.summary()

狗熊会|聚数据英才,助产业振兴
8.4.2 带有 BN 的逻辑回归 狗熊会 | 深度学习入门

 数据准备与展示
 带有 BN 的逻辑回归模型
 模型结构展示

狗熊会|聚数据英才,助产业振兴
8.4.2 带有 BN 的逻辑回归 狗熊会 | 深度学习入门

 数据准备与展示
 带有 BN 的逻辑回归模型
 模型结构展示
 带有 BN 的逻辑回归模型与拟合

from keras.optimizers import Adam


model1.compile(loss='categorical_crossentropy',optimizer=Adam(lr=0.01),metrics= ['accuracy'])
model1.fit_generator(train_generator,epochs=200,validation_data=validation_generator)

狗熊会|聚数据英才,助产业振兴
8.4.3 带有 BN 的宽模型 狗熊会 | 深度学习入门

 宽模型用了很多个卷积核,即较深的卷积通道。
 具体代码和 8.4.2 章节的逻辑回归差不多,唯一的区别是增加了两行:
 卷积操作。使用 100 个大小为的卷积核进行 valid 卷积;
 池化操作,进行规格大小为的最大值池化。

狗熊会|聚数据英才,助产业振兴
8.4.4 带有 BN 的深度模型 狗熊会 | 深度学习入门

 这个模型中,卷积核的个数减少,但是模型的层数增加。

 BN 总结:
 Batch Normalization 在很多情况下确实是帮助巨大的,但并不是对所有情况都有帮助。在什么情况
下 Batch Normalization 能够让结果变好,在什么情况下没有帮助是不清楚的,是值得我们思考和
研究的。

狗熊会|聚数据英才,助产业振兴
PART 8.5
Data Augmentation 的技巧

狗熊会|聚数据英才,助产业振兴
8.5 Data Augmentation 的技巧 狗熊会 | 深度学习入门

 Data Augmentation 被翻译成“数据增强”,或者“数据增广”。


 它通过对数据施加各种变换来达到增加样本量的目的。
 数据增强是深度学习中除了 Batch Normalization 外另一个非常常用的技巧。

狗熊会|聚数据英才,助产业振兴
8.5.1 Data Augmentation 的核心思想 狗熊会 | 深度学习入门

 人和计算机处理图像不同。原来的图像被
拉伸、变换或旋转,对计算机而言都是一
个全新的矩阵。
 计算机对图像数据用矩阵形式表达不充分。
 把一张图像变成矩阵的过程中,是有信息
损失的,而这些损失的信息很宝贵,有可
能帮助我们把模型做得更好。

狗熊会|聚数据英才,助产业振兴
8.5 狗熊会 | 深度学习入门

Flip Rotation Scaling

Croping translation GAN/Noise

狗熊会|聚数据英才,助产业振兴
8.5.2 案例:猫狗分类 狗熊会 | 深度学习入门

 数据生成器生成测试集
 利用数据增强技术生成的训练集
 展示数据增强后的图像
 模型搭建
 模型的编译与拟合
from keras.preprocessing.image import ImageDataGenerator

IMSIZE=128

validation_generator = ImageDataGenerator(rescale=1./255).flow_from_directory(
'./data_bn/CatDog/validation',
target_size=(IMSIZE, IMSIZE),
batch_size=200,
class_mode='categorical')

狗熊会|聚数据英才,助产业振兴
8.5.2 案例:猫狗分类 狗熊会 | 深度学习入门

 数据生成器生成测试集
 利用数据增强技术生成的训练集 train_generator = ImageDataGenerator(
rescale=1./255,
 shear_range 表示拉伸变换; shear_range=0.5,
rotation_range=30,
 rotation_range 用于定义图像左右旋转; zoom_range=0.2,
 zoom_range 用于定义图像放大或者缩小的比例; width_shift_range=0.2,
height_shift_range=0.2,
 width_shift_range 表示水平方向上平移的尺度; horizontal_flip=True).flow_from_directory(
'./data_bn/CatDog/train',
 height_shift_range 表示垂直方向上平移的尺度; target_size=(IMSIZE, IMSIZE),
 horizontal_flip=True 表示允许水平方向的翻转。 batch_size=200,
class_mode='categorical')
 展示数据增强后的图像
 模型搭建
 模型的编译与拟合

狗熊会|聚数据英才,助产业振兴
8.5.2 案例:猫狗分类 狗熊会 | 深度学习入门

from matplotlib import pyplot as plt

 数据生成器生成测试集 plt.figure()
fig,ax = plt.subplots(2,5)
 利用数据增强技术生成的训练集 fig.set_figheight(6)
fig.set_figwidth(15)
 展示数据增强后的图像 ax=ax.flatten()
 模型搭建 X,Y=next(train_generator)
for i in range(10): ax[i].imshow(X[i,:,:,:])
 模型的编译与拟合

狗熊会|聚数据英才,助产业振兴
8.5.2 案例:猫狗分类 狗熊会 | 深度学习入门

 数据生成器生成测试集 IMSIZE=128
from keras.layers import BatchNormalization,Conv2D,Dense,Flatten,Input,
 利用数据增强技术生成的训练集 MaxPooling2D
from keras import Model
 展示数据增强后的图像
n_channel=100
 模型搭建 input_layer=Input([IMSIZE,IMSIZE,3])
x=input_layer
 模型的编译与拟合 x=BatchNormalization()(x)
for _ in range(7):
x=BatchNormalization()(x)
x=Conv2D(n_channel,[2,2],padding='same',activation='relu')(x)
x=MaxPooling2D([2,2])(x)

x=Flatten()(x)
x=Dense(2,activation='softmax')(x)
output_layer=x
model=Model(input_layer,output_layer)
model.summary()

狗熊会|聚数据英才,助产业振兴
8.5.2 案例:猫狗分类 狗熊会 | 深度学习入门

 数据生成器生成测试集
 利用数据增强技术生成的训练集
 展示数据增强后的图像
 模型搭建
 模型结构展示
 模型的编译与拟合

狗熊会|聚数据英才,助产业振兴
8.5.2 案例:猫狗分类 狗熊会 | 深度学习入门

 数据生成器生成测试集
 利用数据增强技术生成的训练集
 展示数据增强后的图像
 模型搭建
 模型的编译与拟合

from keras.optimizers import Adam


model.compile(loss='categorical_crossentropy',optimizer=Adam(lr=0.0001),metrics=['accuracy'])
model.fit_generator(train_generator,epochs=200,validation_data=validation_generator)

狗熊会|聚数据英才,助产业振兴
课后习题 狗熊会 | 深度学习入门

 课后习题
 1 .请给出不少于 3 个基于图像的分类问题,并简要描述出 和 。
 2 . LeNet-5 虽然是一个非常经典的模型,但是不是意味着模型中的一些设定不能修改呢?比如卷积
核的数量、大小、层数等,请尝试修改,看看模型精度会有什么变化。
 3 .本章介绍了 3 个经典的卷积神经网络的应用案例,请任选一个数据集,以一个逻辑回归模型作为
benchmark ,将其预测精度与其他 CNN 模型对比。
 4 .本章学习了一些经典的 CNN 神经网络,尝试把原来的一些经典卷积神经网络使用 Batch
Normalization 改造,提高它的预测精度。有的经典神经网络已经考虑了 BN 技巧,那么那些没有考
虑到的,请读者尝试一下,看看效果是变好了,还是变差了。
 5 .思考如果不做数据加强, 8.5.2 节的案例结果会怎么样?

狗熊会|聚数据英才,助产业振兴
THANK YOU 狗熊会
狗熊会|聚数据英才,助产业振兴

You might also like