Resnet实例化cifar10分类
使用cifar10数据集和Resnet进行分类。
cifar10数据集下载
下载地址:cifar10数据集下载
下载版本:python
cifar10数据集预处理
本文使用python 3.7 将下载到的cifar 10 数据集读入到程序中,程序如下(注意需要在主函数中放入自己的解压后的cifar文件的路径):
from __future__ import print_function
from six.moves import cPickle as pickle
import numpy as np
import os
# 读取文件
def load_CIFAR_batch(filename):
""" load single batch of cifar """
with open(filename, 'rb') as f:
datadict = pickle.load(f, encoding='latin1') # dict类型
X = datadict['data'] # X, ndarray, 像素值
Y = datadict['labels'] # Y, list, 标签, 分类
# reshape, 一维数组转为矩阵10000行3列。每个entries是32x32
# transpose,转置
# astype,复制,同时指定类型
X = X.reshape(10000, 3, 32, 32).transpose(0, 2, 3, 1).astype("float")
Y = np.array(Y)
return X, Y
def load_CIFAR10(Root):
if Root == ' ':
print("cifar10文件存放的路径不为空")
else:
""" load all of cifar """
xs = [] # list
ys = []
# 训练集batch 1~5
for b in range(1, 6):
f = os.path.join(Root, 'data_batch_%d' % (b,))
X, Y = load_CIFAR_batch(f)
xs.append(X) # 在list尾部添加对象X, x = [..., [X]]
ys.append(Y)
Xtr = np.concatenate(xs) # [ndarray, ndarray] 合并为一个ndarray
Ytr = np.concatenate(ys)
del X, Y
# 读入测试数据
Xte, Yte = load_CIFAR_batch(os.path.join(Root, 'test_batch'))
return Xtr, Ytr, Xte, Yte
if __name__ == "__main__":
X_train, Y_train, X_test, Y_test = load_CIFAR10(Root = r' ' )
print("训练集大小:", X_train.shape, Y_train.shape)
print("测试集大小:", X_test.shape, Y_test.shape)
使用tensorflow2.0中的Load_batch将cifar10导入程序中
from tensorflow.python.keras.datasets.cifar import load_batch
import os
import tensorflow as tf
import numpy as np
path = r'F:\深度学习\学习\tensorflow\cifar-10-batches-py'
xs = []
ys = []
for b in range(1, 6):
f = os.path.join(path, 'data_batch_%d' % (b,))
X, Y = load_batch(f)
xs.append(X)
ys.append(Y)
X_train = np.concatenate(xs) # [ndarray, ndarray] 合并为一个ndarray
Y_train = np.concatenate(ys)
test_path = os.path.join(path, 'test_batch')
x_test, y_test = load_batch(test_path)
X_train = tf.transpose(X_train, [0, 2, 3, 1])
print("训练集大小:", np.array(X_train).shape, np.array(Y_train).shape)
y_train = np.float32(tf.keras.utils.to_categorical(Y_train, num_classes = 10))
x_test = tf.transpose(x_test, [0, 2, 3, 1])
print("测试集大小:", np.array(x_test).shape, np.array(y_test).shape)
y_test = np.float32(tf.keras.utils.to_categorical(y_test, num_classes = 10))
什么是Resnet?
Resnet解决的问题: VGG神经网路的成功也就意味着网络结构不断去变深、变宽、变复杂称为了卷积神经网络搭建的主流,这也就意味着,只需要简单的通过增加神经网络的结构和层数,就可以去得到更好的结果。但随着研究发现,这是不可能的,在训练集上会出现训练集的准确率很难达到100%正确,甚至会下降,但这与我们的思考相反,因为随着神经网络层数的增加,即使后面的神经网络不进行工作也能够得到和前面的神经网络相同的结果,为什么实验结果还会下降?这与人们思考的不同,这不是“过拟合现象”,因为过拟合现象是在训练集上应该表现的准确率过高。最后这个问题被描述为“神经网络退化”。研究发现,随着网络深度的增加,梯度消失问题会出现。随着网络层数的增加,神经网络性能不断趋于饱和。
Resnet基础原理: Resnet出现改变了VGG神经网络所带来的思维,它提出使用模块化思想代替整体的卷积层。提出Resnet的文章, Resnet的框架如下所示:
由上图可以看出,残差框架最大的变化是加入了恒等映射层y=x。这样作就可是使得网络随着深度的增加而不会产生权重衰减、梯度衰减或者消失等问题。
上图中
F
(
x
)
F(x)
F(x)表示的是残差,
F
(
x
)
+
x
F(x)+x
F(x)+x是最终的映射输出,因此可以得到网络输出为
F
(
x
)
+
x
F(x)+x
F(x)+x,最终的输出结果用公式表示如下:
- R 1 ( x ) = r e l u 1 ( ω 1 × x ) R_1(x) = relu1(\omega_1\times x) R1(x)=relu1(ω1×x)
- R 2 ( x ) = r e l u 2 ( ω 2 × R 1 ( x ) ) R_2(x)=relu2(\omega_2\times R_1(x)) R2(x)=relu2(ω2×R1(x))
- R ( x ) = R 2 ( x ) + x R(x) = R_2(x)+x R(x)=R2(x)+x
R i ( x ) , i ∈ { 1 , 2 } R_i(x),i\in\{1,2\} Ri(x),i∈{1,2}代表第i层的输出。
Resnet的代码块实现
这个程序只是为了看懂上述图像中的Resnet基础块的表述
def Basic_block_resnet(input, out_dim):
conv1 = tf.keras.layers.Conv2D(out_dim // 4, kernel_size = 1, padding = 'SAME', activation = tf.nn.relu)(input)
conv2 = tf.keras.layers.BatchNormalization()(conv1)
conv3 = tf.keras.layers.Conv2D(out_dim//4, kernel_size = 3, padding = 'SAME', activation = tf.nn.relu)(conv2)
conv4 = tf.keras.layers.BatchNormalization()(conv3)
conv5 = tf.keras.layers.Conv2D(out_dim, kernel_size = 3, padding = 'SAME', activation = tf.nn.relu)(conv4)
out1 = tf.keras.layers.Add()([input, conv5])
out = tf.nn.relu(out)
return out
使用Resnet对cifar10数据集进行分类
Resnet模型建立程序如下:
def resnet_Model(n_dim = 10):
input_xs = tf.keras.Input(shape = [32, 32, 3])
conv1 = tf.keras.layers.Conv2D(filters = 64, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(input_xs)
# 第一层
out_dim = 64
identity_1 = tf.keras.layers.Conv2D(filters = out_dim, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(conv1)
identity_1 = tf.keras.layers.BatchNormalization()(identity_1)
for x in range(3):
identity_1 = identity_block(identity_1, out_dim)
# 第二层
out_dim = 128
identity_2 = tf.keras.layers.Conv2D(filters = out_dim, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(identity_1)
identity_2 = tf.keras.layers.BatchNormalization()(identity_2)
for x in range(4):
identity_2 = identity_block(identity_2, out_dim)
# 第三层
out_dim = 256
identity_3 = tf.keras.layers.Conv2D(filters = out_dim, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(identity_2)
identity_3 = tf.keras.layers.BatchNormalization()(identity_3)
for x in range(6):
identity_3 = identity_block(identity_3, out_dim)
# 第四层
out_dim = 512
identity_4 = tf.keras.layers.Conv2D(filters = out_dim, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(identity_3)
for x in range(3):
identity_4 = identity_block(identity_4, out_dim)
flat = tf.keras.layers.Flatten()(identity_4)
flat = tf.keras.layers.Dropout(0.217)(flat)
dense = tf.keras.layers.Dense(512, activation = tf.nn.relu)(flat)
dense = tf.keras.layers.BatchNormalization()(dense)
logits = tf.keras.layers.Dense(10, activation = tf.nn.softmax)(dense)
model = tf.keras.Model(inputs = input_xs, outputs = logits)
return model
综合分类程序
这个程序是将读取数据,建立基础Resnet块,建立分类模型,cifar10分类合并到一起。缺点,运行时间较长:大概得20个小时。
import tensorflow as tf
import numpy as np
from tensorflow.python.keras.datasets.cifar import load_batch
import os
# Resnet基础块
def identity_block(input_tensor, out_dim):
conv1 = tf.keras.layers.Conv2D(out_dim // 4, kernel_size = 1, padding = "SAME",
activation = tf.nn.relu)(input_tensor)
conv2 = tf.keras.layers.BatchNormalization()(conv1)
conv3 = tf.keras.layers.Conv2D(out_dim // 4, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(conv2)
conv4 = tf.keras.layers.BatchNormalization()(conv3)
conv5 = tf.keras.layers.Conv2D(out_dim, kernel_size = 1, padding = "SAME")(conv4)
out = tf.keras.layers.Add()([input_tensor, conv5])
out = tf.nn.relu(out)
return out
# resnet 模型
def resnet_Model(n_dim = 10):
input_xs = tf.keras.Input(shape = [32, 32, 3])
conv1 = tf.keras.layers.Conv2D(filters = 64, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(input_xs)
# 第一层
out_dim = 64
identity_1 = tf.keras.layers.Conv2D(filters = out_dim, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(conv1)
identity_1 = tf.keras.layers.BatchNormalization()(identity_1)
for x in range(1):
identity_1 = identity_block(identity_1, out_dim)
# 第二层
out_dim = 128
identity_2 = tf.keras.layers.Conv2D(filters = out_dim, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(identity_1)
identity_2 = tf.keras.layers.BatchNormalization()(identity_2)
for x in range(2):
identity_2 = identity_block(identity_2, out_dim)
# 第三层
out_dim = 256
identity_3 = tf.keras.layers.Conv2D(filters = out_dim, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(identity_2)
identity_3 = tf.keras.layers.BatchNormalization()(identity_3)
for x in range(2):
identity_3 = identity_block(identity_3, out_dim)
# 第四层
out_dim = 512
identity_4 = tf.keras.layers.Conv2D(filters = out_dim, kernel_size = 3, padding = "SAME",
activation = tf.nn.relu)(identity_3)
for x in range(3):
identity_4 = identity_block(identity_4, out_dim)
flat = tf.keras.layers.Flatten()(identity_4)
flat = tf.keras.layers.Dropout(0.217)(flat)
dense = tf.keras.layers.Dense(512, activation = tf.nn.relu)(flat)
dense = tf.keras.layers.BatchNormalization()(dense)
logits = tf.keras.layers.Dense(10, activation = tf.nn.softmax)(dense)
model = tf.keras.Model(inputs = input_xs, outputs = logits)
return model
# 从数据路径中读取数据
def ReadData(path = ""):
xs = []
ys = []
for b in range(1, 6):
f = os.path.join(path, 'data_batch_%d' % (b,))
X, Y = load_batch(f)
xs.append(X) # 在list尾部添加对象X, x = [..., [X]]
ys.append(Y)
X_train = np.concatenate(xs) # [ndarray, ndarray] 合并为一个ndarray
Y_train = np.concatenate(ys)
test_path = os.path.join(path, 'test_batch')
x_test, y_test = load_batch(test_path)
x_train = tf.transpose(X_train, [0, 2, 3, 1])
print("训练集大小:", np.array(X_train).shape, np.array(Y_train).shape)
y_train = np.float32(tf.keras.utils.to_categorical(Y_train, num_classes=10))
x_test = tf.transpose(x_test, [0, 2, 3, 1])
print("测试集大小:", np.array(x_test).shape, np.array(y_test).shape)
y_test = np.float32(tf.keras.utils.to_categorical(y_test, num_classes=10))
return x_train, y_train, x_test, y_test
# 训练模型,并进行拟合
def train_Model(x_train, y_train, x_test, y_test, batch_size = 48):
batch_size = 48
train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(
batch_size * 3).batch(batch_size)
print("训练数据预处理完成")
model = resnet_Model()
print("模型生成")
model.compile(optimizer=tf.optimizers.Adam(1e-2), loss=tf.losses.categorical_crossentropy, metrics=['accuracy'])
print("训练开始")
model.fit(train_data, epochs=4)
print("训练结束")
score = model.evaluate(x_test, y_test)
print(score)
if __name__ == "__main__":
path = r'E:\学习文档\深度学习\cifar-10-batches-py'
x_train, y_train, x_test, y_test = ReadData(path)
train_Model(x_train, y_train, x_test, y_test)