文章目录
一、LeNet-51.LeNet-5对cifar10分类实战二、VGG131.VGG13对cifar10分类实战三、AlexNet四、GoogLeNet五、ResNet—深度残差网络1.ResNet18实战cifar10—自定义六、DenseNet网络一、LeNet-5
1998年,LeCun发布了LeNet-5网络架构,权值共享这个词最开始是由LeNet-5模型提出来的。虽然现在大多数人认为,的AlexNet网络是深度学习的开端,但是CNN的开端可以追溯到LeNet-5模型。
输入尺寸为32×32
卷积层为2层
池化层为2层
全连接层为2层
输出为10个类别(数字0-9的概率)
C1层为卷积层,卷积核大小为5×5,有6个卷积核(提取6种局部特征),卷积层输出大小为28×28×6,strides=1
S2层为池化层,池化框为2×2,strides=1,在减小数据量的同时也保留了有用的信息。
C3层为卷积层,卷积核大小为5×5,有16个卷积核(提取16种局部特征),卷积层输出大小为10×10×16,strides=1
S4层为池化层,池化框为2×2,strides=1,在减小数据量的同时也保留了有用的信息。
C5为全连接层,神经元个数为120个
F6为全连接层,神经元个数为84个
1.LeNet-5对cifar10分类实战
数据格式为numpy格式
import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'# GPUfrom pat.v1 import ConfigProto, InteractiveSessionconfig = ConfigProto()config.gpu_options.allow_growth = Truesession = InteractiveSession(config=config)import randomimport numpy as npimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers, metrics, optimizers, losses, Sequential, datasetsimport matplotlib.pyplot as plt# 随机数种子def seed_everying(SEED):os.environ['TF_DETERMINISTIC_OPS'] = '1'os.environ['PYTHONHASHSEED'] = str(SEED)random.seed(SEED)np.random.seed(SEED)tf.random.set_seed(SEED)seed_everying(42)# 加载数据集(x, y), (x_test, y_test) = datasets.cifar10.load_data()print('shape =', x.shape, y.shape, x_test.shape, y_test.shape)# shape = (50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1)x = tf.cast(x, dtype=tf.float32)y = tf.cast(y, dtype=tf.int32)x_test = tf.cast(x_test, dtype=tf.float32)y_test = tf.cast(y_test, dtype=tf.int32)# 分割数据集x_train, x_val = tf.split(x, num_or_size_splits=[40000, 10000])y_train, y_val = tf.split(y, num_or_size_splits=[40000, 10000])x_train, x_val, x_test = x_train / 255.0, x_val / 255.0, x_test / 255.0y_train = tf.one_hot(y_train, depth=10)y_train = tf.reshape(y_train, (-1, 10))y_val = tf.one_hot(y_val, depth=10)y_val = tf.reshape(y_val, (-1, 10))y_test = tf.one_hot(y_test, depth=10)y_test = tf.reshape(y_test, (-1, 10))print(y_test.shape)# 构建网络def LeNet_5():input = tf.keras.Input(shape=(32, 32, 3))network = Sequential([# 2* conv2d and poollayers.Conv2D(6, kernel_size=(5, 5), padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=(2, 2), padding='same', strides=1),layers.Conv2D(16, kernel_size=(5, 5), padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=(2, 2), padding='same', strides=1),])conv = network(input)out = tf.reshape(conv, (-1, 32 * 32 * 16))# 两个全连接层out = layers.Dense(120, activation=tf.nn.relu)(out)out = layers.Dense(84, activation=tf.nn.relu)(out)output = layers.Dense(10, activation=tf.nn.softmax)(out)model = tf.keras.Model(inputs=input, outputs=output)return modelnetwork = LeNet_5()# 编译模型pile(optimizer=optimizers.Adam(learning_rate=0.001),loss=losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy'])# 训练模型early_Stopping = keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=3)history = network.fit(x=x_train, y=y_train, batch_size=128, epochs=30,validation_data=(x_val, y_val),callbacks=[early_Stopping])# 打印迭代图acc = history.history['accuracy']val_acc = history.history['val_accuracy']epochs_range = np.arange(len(acc))fig = plt.figure(figsize=(15, 5))fig.add_subplot()plt.plot(epochs_range, acc, label='Train acc')plt.plot(epochs_range, val_acc, label='Val_acc')plt.legend(loc='upper right')plt.title('Train and Val acc')plt.show()# 预测y_pred = network.predict(x_test)y_pred = np.argmax(y_pred, axis=1)y_true = np.argmax(y_test, axis=1)correct = tf.reduce_sum(tf.cast(tf.equal(y_pred,y_true),dtype=tf.int32))print(int(correct) / len(y_test))
数据格式为张量格式
#!usr/bin/env python# -*- coding:utf-8 -*-"""@author: admin@file: 1.py@time: /02/25@desc:"""import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'# GPUfrom pat.v1 import ConfigProto, InteractiveSessionconfig = ConfigProto()config.gpu_options.allow_growth = Truesession = InteractiveSession(config=config)import randomimport numpy as npimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers, metrics, optimizers, losses, Sequential, datasetsimport matplotlib.pyplot as plt# 随机数种子def seed_everying(SEED):os.environ['TF_DETERMINISTIC_OPS'] = '1'os.environ['PYTHONHASHSEED'] = str(SEED)random.seed(SEED)np.random.seed(SEED)tf.random.set_seed(SEED)seed_everying(42)def proprecess(x, y):x = 2 * tf.cast(x, dtype=tf.float32) / 255.0 - 1 # (-1,1)y = tf.cast(y, dtype=tf.int32)y = tf.one_hot(y, depth=10)# 从张量中移去尺寸为1的维度y = tf.squeeze(y)return x, y# 加载数据集(x, y), (x_test, y_test) = datasets.cifar10.load_data()print('shape =', x.shape, y.shape, x_test.shape, y_test.shape)# shape = (50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1)# 分割数据集x_train, x_val = tf.split(x, num_or_size_splits=[40000, 10000])y_train, y_val = tf.split(y, num_or_size_splits=[40000, 10000])# 构建张量db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))db_train = db_train.map(proprecess).shuffle(40000).batch(128)db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))db_val = db_val.map(proprecess).shuffle(10000).batch(128)db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))db_test = db_test.map(proprecess).batch(128)# 构建网络def LeNet_5():input = tf.keras.Input(shape=(32, 32, 3))network = Sequential([# 2* conv2d and poollayers.Conv2D(6, kernel_size=(5, 5), padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=(2, 2), padding='same', strides=1),layers.Conv2D(16, kernel_size=(5, 5), padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=(2, 2), padding='same', strides=1),])conv = network(input)out = tf.reshape(conv, (-1, 32 * 32 * 16))# 两个全连接层out = layers.Dense(120, activation=tf.nn.relu)(out)out = layers.Dense(84, activation=tf.nn.relu)(out)output = layers.Dense(10, activation=tf.nn.softmax)(out)model = tf.keras.Model(inputs=input, outputs=output)return modelnetwork = LeNet_5()# 编译模型pile(optimizer=optimizers.Adam(learning_rate=0.001),loss=losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy'])# 训练模型early_Stopping = keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=5)history = network.fit(db_train, epochs=50,validation_data=db_val, validation_freq=1,callbacks=[early_Stopping],verbose=2)# 打印迭代图acc = history.history['accuracy']val_acc = history.history['val_accuracy']epochs_range = np.arange(len(acc))fig = plt.figure(figsize=(10, 8))fig.add_subplot()plt.plot(epochs_range, acc, label='Train acc')plt.plot(epochs_range, val_acc, label='Val_acc')plt.legend(loc='upper right')plt.title('Train and Val acc')plt.show()# 预测y_pred = network.predict(db_test)y_pred = np.argmax(y_pred, axis=1)correct = tf.reduce_sum(tf.cast(tf.equal(y_pred,tf.squeeze(y_test)),dtype=tf.int32))print(int(correct) / len(y_test))
shape = (50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1)Epoch 1/100313/313 - 8s - loss: 2.1210 - accuracy: 0.3333 - val_loss: 0.0000e+00 - val_accuracy: 0.0000e+00Epoch 2/100313/313 - 6s - loss: 2.0361 - accuracy: 0.4209 - val_loss: 2.0027 - val_accuracy: 0.4578Epoch 3/100313/313 - 6s - loss: 1.9920 - accuracy: 0.4664 - val_loss: 1.9975 - val_accuracy: 0.4600Epoch 4/100313/313 - 6s - loss: 1.9588 - accuracy: 0.5001 - val_loss: 1.9713 - val_accuracy: 0.4873Epoch 5/100313/313 - 6s - loss: 1.9379 - accuracy: 0.5201 - val_loss: 1.9473 - val_accuracy: 0.5096Epoch 6/100313/313 - 6s - loss: 1.9242 - accuracy: 0.5352 - val_loss: 1.9736 - val_accuracy: 0.4797Epoch 7/100313/313 - 6s - loss: 1.9075 - accuracy: 0.5513 - val_loss: 1.9341 - val_accuracy: 0.5234Epoch 8/100313/313 - 6s - loss: 1.8852 - accuracy: 0.5735 - val_loss: 1.9385 - val_accuracy: 0.5187Epoch 9/100313/313 - 6s - loss: 1.8695 - accuracy: 0.5908 - val_loss: 1.9218 - val_accuracy: 0.5368Epoch 10/100313/313 - 6s - loss: 1.8553 - accuracy: 0.6045 - val_loss: 1.8971 - val_accuracy: 0.5582Epoch 11/100313/313 - 6s - loss: 1.8128 - accuracy: 0.6484 - val_loss: 1.8627 - val_accuracy: 0.5949Epoch 12/100313/313 - 6s - loss: 1.7856 - accuracy: 0.6752 - val_loss: 1.8788 - val_accuracy: 0.5801Epoch 13/100313/313 - 6s - loss: 1.7691 - accuracy: 0.6921 - val_loss: 1.8632 - val_accuracy: 0.5946Epoch 14/100313/313 - 6s - loss: 1.7591 - accuracy: 0.7017 - val_loss: 1.8508 - val_accuracy: 0.6060Epoch 15/100313/313 - 6s - loss: 1.7500 - accuracy: 0.7115 - val_loss: 1.8601 - val_accuracy: 0.5976Epoch 16/100313/313 - 6s - loss: 1.7379 - accuracy: 0.7234 - val_loss: 1.8519 - val_accuracy: 0.6064Epoch 17/100313/313 - 6s - loss: 1.7302 - accuracy: 0.7308 - val_loss: 1.8653 - val_accuracy: 0.5964Epoch 18/100313/313 - 6s - loss: 1.7190 - accuracy: 0.7422 - val_loss: 1.8458 - val_accuracy: 0.6122Epoch 19/100313/313 - 6s - loss: 1.7134 - accuracy: 0.7481 - val_loss: 1.8573 - val_accuracy: 0.6043Epoch 20/100313/313 - 6s - loss: 1.7047 - accuracy: 0.7568 - val_loss: 1.8484 - val_accuracy: 0.6091Epoch 21/100313/313 - 6s - loss: 1.6943 - accuracy: 0.7671 - val_loss: 1.8467 - val_accuracy: 0.6089Epoch 22/100313/313 - 6s - loss: 1.6915 - accuracy: 0.7694 - val_loss: 1.8503 - val_accuracy: 0.6080Epoch 23/100313/313 - 6s - loss: 1.6841 - accuracy: 0.7777 - val_loss: 1.8555 - val_accuracy: 0.60030.5982
二、VGG13
,Simonyan等人在其发表的文章中探讨了“深度”对于CNN网络的重要性,该文通过在现有的网络结构中不断增加具有3×3卷积核的卷积层来增加网络的深度,实验结果表明,当权值层数达到16~19时,模型的性能能够得到有效的提升,该文中的模型也被称为VGG模型。VGG模型用具有小卷积核的多个卷积层替换一个具有较大卷积核的卷积层,如用大小均为3×3卷积核的3层卷积层代替一层具有7×7卷积核的卷积层,这种替换方式减少了参数的数量,而且也能够使决策函数更具有判别性。
卷积层为10层,卷积核的大小为3×3,卷积核的个数分别为:64,64,128,128,256,256,512,512,512,512,strides=1,padding=same
池化层为5层,每层池化框大小为2×2,strides=2,padding=same
1.VGG13对cifar10分类实战
#!usr/bin/env python# -*- coding:utf-8 -*-"""@author: admin@file: VGG13.py@time: /02/25@desc:"""import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'# 内存自动增长from pat.v1 import ConfigProtofrom pat.v1 import InteractiveSessionconfig = ConfigProto()config.gpu_options.allow_growth = Truesession = InteractiveSession(config=config)import randomimport numpy as npimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers, optimizers, datasets, Sequentialimport matplotlib.pyplot as plt# 随机数种子def seed_everying(SEED):os.environ['TF_DETERMINISTIC_OPS'] = '1'os.environ['PYTHONHASHSEED'] = str(SEED)random.seed(SEED)np.random.seed(SEED)tf.random.set_seed(SEED)seed_everying(42)def proprecess(x, y):# [0-1]x = tf.cast(x, dtype=tf.float32) / 255.y = tf.cast(y, dtype=tf.int32)y = tf.one_hot(y, depth=10)y = tf.squeeze(y)return x, y# 加载数据集(x, y), (x_test, y_test) = datasets.cifar10.load_data()print(x.shape, y.shape, x_test.shape, y_test.shape)# (50000, 32, 32, 3) (50000, ) (10000, 32, 32, 3) (10000, )# 分割数据集x_train, x_val = tf.split(x, num_or_size_splits=[40000, 10000])y_train, y_val = tf.split(y, num_or_size_splits=[40000, 10000])# 构建张量db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))db_train = db_train.map(proprecess).shuffle(40000).batch(128)db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))db_val = db_val.map(proprecess).shuffle(10000).batch(128)db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))db_test = db_test.map(proprecess).batch(128)# 构建模型def VGG13():input = tf.keras.Input(shape=( 32, 32, 3))conv_layers = Sequential([ # 5 units of conv + max pooling# unit 1layers.Conv2D(64, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(64, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),# unit 2layers.Conv2D(128, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(128, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),# unit 3layers.Conv2D(256, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(256, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),# unit 4layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),# unit 5layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')])conv_out = conv_layers(input)conv_out = tf.reshape(conv_out, (-1, 512))# 构建全连接层fc_net = Sequential([layers.Dense(256, activation=tf.nn.relu),layers.Dense(128, activation=tf.nn.relu),layers.Dense(10, activation=tf.nn.softmax),])fc_output = fc_net(conv_out)model = tf.keras.Model(inputs=input,outputs=fc_output)return modelmodel = VGG13()# 编译模型pile(optimizer=optimizers.Adam(learning_rate=1e-4),loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy'])# 训练模型early_Stopping = keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=5)history = model.fit(db_train, epochs=100,validation_data=db_val, validation_freq=1,callbacks=[early_Stopping], verbose=2)# 打印迭代图acc = history.history['accuracy']val_acc = history.history['val_accuracy']epochs_range = np.arange(len(acc))fig = plt.figure(figsize=(10, 8))fig.add_subplot()plt.plot(epochs_range, acc, label='Train acc')plt.plot(epochs_range, val_acc, label='Val_acc')plt.legend(loc='upper right')plt.title('Train and Val acc')plt.show()# 预测y_pred = model.predict(db_test)y_pred = np.argmax(y_pred, axis=1)correct = tf.reduce_sum(tf.cast(tf.equal(y_pred, tf.squeeze(y_test)), dtype=tf.int32))print(int(correct) / len(y_test))
(50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1)<BatchDataset shapes: ((None, 32, 32, 3), (None, 10)), types: (tf.float32, tf.float32)>Epoch 1/100313/313 - 33s - loss: 2.2055 - accuracy: 0.2378 - val_loss: 0.0000e+00 - val_accuracy: 0.0000e+00Epoch 2/100313/313 - 26s - loss: 2.1124 - accuracy: 0.3383 - val_loss: 2.0863 - val_accuracy: 0.3659Epoch 3/100313/313 - 26s - loss: 2.0764 - accuracy: 0.3785 - val_loss: 2.0409 - val_accuracy: 0.4169Epoch 4/100313/313 - 26s - loss: 2.0424 - accuracy: 0.4122 - val_loss: 2.0270 - val_accuracy: 0.4286Epoch 5/100313/313 - 26s - loss: 2.0098 - accuracy: 0.4462 - val_loss: 1.9817 - val_accuracy: 0.4712Epoch 6/100313/313 - 27s - loss: 1.9674 - accuracy: 0.4904 - val_loss: 1.9701 - val_accuracy: 0.4864Epoch 7/100313/313 - 26s - loss: 1.9382 - accuracy: 0.5190 - val_loss: 1.9214 - val_accuracy: 0.5362Epoch 8/100313/313 - 26s - loss: 1.9090 - accuracy: 0.5490 - val_loss: 1.9258 - val_accuracy: 0.5292Epoch 9/100313/313 - 26s - loss: 1.8899 - accuracy: 0.5685 - val_loss: 1.8810 - val_accuracy: 0.5781Epoch 10/100313/313 - 27s - loss: 1.8562 - accuracy: 0.6028 - val_loss: 1.8822 - val_accuracy: 0.5755Epoch 11/100313/313 - 26s - loss: 1.8458 - accuracy: 0.6131 - val_loss: 1.8642 - val_accuracy: 0.5950Epoch 12/100313/313 - 27s - loss: 1.8249 - accuracy: 0.6345 - val_loss: 1.8499 - val_accuracy: 0.6101Epoch 13/100313/313 - 27s - loss: 1.8051 - accuracy: 0.6545 - val_loss: 1.8268 - val_accuracy: 0.6324Epoch 14/100313/313 - 27s - loss: 1.7875 - accuracy: 0.6724 - val_loss: 1.7986 - val_accuracy: 0.6636Epoch 15/100313/313 - 27s - loss: 1.7747 - accuracy: 0.6851 - val_loss: 1.8039 - val_accuracy: 0.6578Epoch 16/100313/313 - 27s - loss: 1.7617 - accuracy: 0.6985 - val_loss: 1.7893 - val_accuracy: 0.6690Epoch 17/100313/313 - 27s - loss: 1.7487 - accuracy: 0.7118 - val_loss: 1.7968 - val_accuracy: 0.6656Epoch 18/100313/313 - 27s - loss: 1.7317 - accuracy: 0.7296 - val_loss: 1.7720 - val_accuracy: 0.6896Epoch 19/100313/313 - 27s - loss: 1.7202 - accuracy: 0.7406 - val_loss: 1.7651 - val_accuracy: 0.6948Epoch 20/100313/313 - 27s - loss: 1.7054 - accuracy: 0.7556 - val_loss: 1.7699 - val_accuracy: 0.6879Epoch 21/100313/313 - 27s - loss: 1.6924 - accuracy: 0.7687 - val_loss: 1.7527 - val_accuracy: 0.7072Epoch 22/100313/313 - 27s - loss: 1.6855 - accuracy: 0.7761 - val_loss: 1.7392 - val_accuracy: 0.7185Epoch 23/100313/313 - 27s - loss: 1.6719 - accuracy: 0.7895 - val_loss: 1.7389 - val_accuracy: 0.7203Epoch 24/100313/313 - 27s - loss: 1.6592 - accuracy: 0.8022 - val_loss: 1.7284 - val_accuracy: 0.7302Epoch 25/100313/313 - 27s - loss: 1.6535 - accuracy: 0.8080 - val_loss: 1.7415 - val_accuracy: 0.7185Epoch 26/100313/313 - 27s - loss: 1.6401 - accuracy: 0.8213 - val_loss: 1.7267 - val_accuracy: 0.7323Epoch 27/100313/313 - 27s - loss: 1.6329 - accuracy: 0.8285 - val_loss: 1.7301 - val_accuracy: 0.7277Epoch 28/100313/313 - 27s - loss: 1.6248 - accuracy: 0.8369 - val_loss: 1.7257 - val_accuracy: 0.7346Epoch 29/100313/313 - 27s - loss: 1.6176 - accuracy: 0.8437 - val_loss: 1.7160 - val_accuracy: 0.7439Epoch 30/100313/313 - 27s - loss: 1.6120 - accuracy: 0.8492 - val_loss: 1.7143 - val_accuracy: 0.7463Epoch 31/100313/313 - 27s - loss: 1.6043 - accuracy: 0.8574 - val_loss: 1.7186 - val_accuracy: 0.7424Epoch 32/100313/313 - 27s - loss: 1.5978 - accuracy: 0.8634 - val_loss: 1.7108 - val_accuracy: 0.7480Epoch 33/100313/313 - 26s - loss: 1.5925 - accuracy: 0.8693 - val_loss: 1.7056 - val_accuracy: 0.7564Epoch 34/100313/313 - 27s - loss: 1.5853 - accuracy: 0.8763 - val_loss: 1.7064 - val_accuracy: 0.7549Epoch 35/100313/313 - 26s - loss: 1.5828 - accuracy: 0.8789 - val_loss: 1.7071 - val_accuracy: 0.7514Epoch 36/100313/313 - 27s - loss: 1.5753 - accuracy: 0.8860 - val_loss: 1.7100 - val_accuracy: 0.7504Epoch 37/100313/313 - 27s - loss: 1.5745 - accuracy: 0.8871 - val_loss: 1.7070 - val_accuracy: 0.7512Epoch 38/100313/313 - 26s - loss: 1.5703 - accuracy: 0.8916 - val_loss: 1.7130 - val_accuracy: 0.74760.7422
以上代码没有加trick,准确率相较LeNet—5已有很大提升
尝试添加trick
BatchNormalization—归一化操作
#!usr/bin/env python# -*- coding:utf-8 -*-"""@author: admin@file: VGG13.py@time: /02/25@desc:"""import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'# 内存自动增长from pat.v1 import ConfigProtofrom pat.v1 import InteractiveSessionconfig = ConfigProto()config.gpu_options.allow_growth = Truesession = InteractiveSession(config=config)import randomimport numpy as npimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers, optimizers, datasets, Sequentialimport matplotlib.pyplot as plt# 随机数种子def seed_everying(SEED):os.environ['TF_DETERMINISTIC_OPS'] = '1'os.environ['PYTHONHASHSEED'] = str(SEED)random.seed(SEED)np.random.seed(SEED)tf.random.set_seed(SEED)seed_everying(42)def proprecess(x, y):# [0-1]x = tf.cast(x, dtype=tf.float32) / 255.y = tf.cast(y, dtype=tf.int32)y = tf.one_hot(y, depth=10)y = tf.squeeze(y)return x, y# 加载数据集(x, y), (x_test, y_test) = datasets.cifar10.load_data()print(x.shape, y.shape, x_test.shape, y_test.shape)# (50000, 32, 32, 3) (50000, ) (10000, 32, 32, 3) (10000, )# 分割数据集x_train, x_val = tf.split(x, num_or_size_splits=[40000, 10000])y_train, y_val = tf.split(y, num_or_size_splits=[40000, 10000])# 构建张量db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))db_train = db_train.map(proprecess).shuffle(40000).batch(128)db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))db_val = db_val.map(proprecess).shuffle(10000).batch(128)db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))db_test = db_test.map(proprecess).batch(128)# 构建模型def VGG13():input = tf.keras.Input(shape=( 32, 32, 3))conv_layers = Sequential([ # 5 units of conv + max poolinglayers.BatchNormalization(),# unit 1layers.Conv2D(64, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(64, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),layers.BatchNormalization(),# unit 2layers.Conv2D(128, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(128, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),layers.BatchNormalization(),# unit 3layers.Conv2D(256, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(256, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),layers.BatchNormalization(),# unit 4layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),layers.BatchNormalization(),# unit 5layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')])conv_out = conv_layers(input)conv_out = tf.reshape(conv_out, (-1, 512))# 构建全连接层fc_net = Sequential([layers.BatchNormalization(),layers.Dense(256, activation=tf.nn.relu),layers.BatchNormalization(),layers.Dense(128, activation=tf.nn.relu),layers.BatchNormalization(),layers.Dense(10, activation=tf.nn.softmax),])fc_output = fc_net(conv_out)model = tf.keras.Model(inputs=input,outputs=fc_output)return modelmodel = VGG13()# 编译模型pile(optimizer=optimizers.Adam(learning_rate=1e-4),loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy'])# 训练模型# 训练模型early_Stopping = keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=5)history = model.fit(db_train, epochs=100,validation_data=db_val, validation_freq=1,callbacks=[early_Stopping], verbose=2)# 打印迭代图acc = history.history['accuracy']val_acc = history.history['val_accuracy']epochs_range = np.arange(len(acc))fig = plt.figure(figsize=(10, 8))fig.add_subplot()plt.plot(epochs_range, acc, label='Train acc')plt.plot(epochs_range, val_acc, label='Val_acc')plt.legend(loc='upper right')plt.title('Train and Val acc')plt.show()# 预测y_pred = model.predict(db_test)y_pred = np.argmax(y_pred, axis=1)correct = tf.reduce_sum(tf.cast(tf.equal(y_pred, tf.squeeze(y_test)), dtype=tf.int32))print(int(correct) / len(y_test))
0.7142
Dropout
#!usr/bin/env python# -*- coding:utf-8 -*-"""@author: admin@file: VGG13.py@time: /02/25@desc:"""import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'# 内存自动增长from pat.v1 import ConfigProtofrom pat.v1 import InteractiveSessionconfig = ConfigProto()config.gpu_options.allow_growth = Truesession = InteractiveSession(config=config)import randomimport numpy as npimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers, optimizers, datasets, Sequentialimport matplotlib.pyplot as plt# 随机数种子def seed_everying(SEED):os.environ['TF_DETERMINISTIC_OPS'] = '1'os.environ['PYTHONHASHSEED'] = str(SEED)random.seed(SEED)np.random.seed(SEED)tf.random.set_seed(SEED)seed_everying(42)def proprecess(x, y):# [0-1]x = tf.cast(x, dtype=tf.float32) / 255.y = tf.cast(y, dtype=tf.int32)y = tf.one_hot(y, depth=10)y = tf.squeeze(y)return x, y# 加载数据集(x, y), (x_test, y_test) = datasets.cifar10.load_data()print(x.shape, y.shape, x_test.shape, y_test.shape)# (50000, 32, 32, 3) (50000, ) (10000, 32, 32, 3) (10000, )# 分割数据集x_train, x_val = tf.split(x, num_or_size_splits=[40000, 10000])y_train, y_val = tf.split(y, num_or_size_splits=[40000, 10000])# 构建张量db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))db_train = db_train.map(proprecess).shuffle(40000).batch(128)db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))db_val = db_val.map(proprecess).shuffle(10000).batch(128)db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))db_test = db_test.map(proprecess).batch(128)# 构建模型def VGG13():input = tf.keras.Input(shape=(32, 32, 3))conv_layers = Sequential([ # 5 units of conv + max poolinglayers.BatchNormalization(),# unit 1layers.Conv2D(64, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(64, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),layers.BatchNormalization(),# unit 2layers.Conv2D(128, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(128, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),layers.BatchNormalization(),# unit 3layers.Conv2D(256, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(256, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),layers.BatchNormalization(),# unit 4layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),layers.BatchNormalization(),# unit 5layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')])conv_out = conv_layers(input)conv_out = tf.reshape(conv_out, (-1, 512))# 构建全连接层fc_net = Sequential([layers.BatchNormalization(),layers.Dropout(0.1),layers.Dense(256, activation=tf.nn.relu),layers.BatchNormalization(),layers.Dropout(0.1),layers.Dense(128, activation=tf.nn.relu),layers.BatchNormalization(),layers.Dropout(0.1),layers.Dense(10, activation=tf.nn.softmax),])fc_output = fc_net(conv_out)model = tf.keras.Model(inputs=input,outputs=fc_output)return modelmodel = VGG13()# 编译模型pile(optimizer=optimizers.Adam(learning_rate=1e-4),loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy'])# 训练模型# 训练模型early_Stopping = keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=5)history = model.fit(db_train, epochs=100,validation_data=db_val, validation_freq=1,callbacks=[early_Stopping], verbose=2)# 打印迭代图acc = history.history['accuracy']val_acc = history.history['val_accuracy']epochs_range = np.arange(len(acc))fig = plt.figure(figsize=(10, 8))fig.add_subplot()plt.plot(epochs_range, acc, label='Train acc')plt.plot(epochs_range, val_acc, label='Val_acc')plt.legend(loc='upper right')plt.title('Train and Val acc')plt.show()# 预测y_pred = model.predict(db_test)y_pred = np.argmax(y_pred, axis=1)correct = tf.reduce_sum(tf.cast(tf.equal(y_pred, tf.squeeze(y_test)), dtype=tf.int32))print(int(correct) / len(y_test))
0.7402
trick加上影响不大,原因不知道
三、AlexNet
AlexNet在增加网络深度的同时,采用了很多新技术:采用ReLU代替饱和非线性函数tanh函数,降低了模型的计算复杂度,模型的训练速度也提升了几倍;通过Dropout技术在训练过程中将中间层的一些神经元随机置为0,使模型更具有鲁棒性,也减少了全连接层的过拟合;而且还通过图像平移、图像水平镜像变换、改变图像灰度等方式来增加训练样本,从而减少过拟合。
在两个GPU上训练(由于原网络需要两个GPU,这里就不提供实例进行训练)
单GPU:
输入为224×224×3
第一个卷积层:卷积核为11×11,卷积核个数为96,步长为4,第一个卷积层输出为55×55×96
下面定义各层参考于:从零开始搭建神经网络(五)卷积神经网络(CNN)
import tensorflow as tfimport numpy as np# 定义各层功能# 最大池化层def maxPoolLayer(x, kHeight, kWidth, strideX, strideY, name, padding = "SAME"):"""max-pooling"""return tf.nn.max_pool(x, ksize = [1, kHeight, kWidth, 1],strides = [1, strideX, strideY, 1], padding = padding, name = name)# dropoutdef dropout(x, keepPro, name = None):"""dropout"""return tf.nn.dropout(x, keepPro, name)# 归一化层def LRN(x, R, alpha, beta, name = None, bias = 1.0):"""LRN"""return tf.nn.local_response_normalization(x, depth_radius = R, alpha = alpha,beta = beta, bias = bias, name = name)# 全连接层def fcLayer(x, inputD, outputD, reluFlag, name):"""fully-connect"""with tf.variable_scope(name) as scope:w = tf.get_variable("w", shape = [inputD, outputD], dtype = "float")b = tf.get_variable("b", [outputD], dtype = "float")out = tf.nn.xw_plus_b(x, w, b, name = scope.name)if reluFlag:return tf.nn.relu(out)else:return out# 卷积层def convLayer(x, kHeight, kWidth, strideX, strideY,featureNum, name, padding = "SAME", groups = 1):"""convolution"""channel = int(x.get_shape()[-1])conv = lambda a, b: tf.nn.conv2d(a, b, strides = [1, strideY, strideX, 1], padding = padding)with tf.variable_scope(name) as scope:w = tf.get_variable("w", shape = [kHeight, kWidth, channel/groups, featureNum])b = tf.get_variable("b", shape = [featureNum])xNew = tf.split(value = x, num_or_size_splits = groups, axis = 3)wNew = tf.split(value = w, num_or_size_splits = groups, axis = 3)featureMap = [conv(t1, t2) for t1, t2 in zip(xNew, wNew)]mergeFeatureMap = tf.concat(axis = 3, values = featureMap)# print mergeFeatureMap.shapeout = tf.nn.bias_add(mergeFeatureMap, b)return tf.nn.relu(tf.reshape(out, mergeFeatureMap.get_shape().as_list()), name = scope.name)class alexNet(object):"""alexNet model"""def __init__(self, x, keepPro, classNum, skip, modelPath = "bvlc_alexnet.npy"):self.X = xself.KEEPPRO = keepProself.CLASSNUM = classNumself.SKIP = skipself.MODELPATH = modelPath#build CNNself.buildCNN()# 构建AlexNetdef buildCNN(self):"""build model"""conv1 = convLayer(self.X, 11, 11, 4, 4, 96, "conv1", "VALID")lrn1 = LRN(conv1, 2, 2e-05, 0.75, "norm1")pool1 = maxPoolLayer(lrn1, 3, 3, 2, 2, "pool1", "VALID")conv2 = convLayer(pool1, 5, 5, 1, 1, 256, "conv2", groups = 2)lrn2 = LRN(conv2, 2, 2e-05, 0.75, "lrn2")pool2 = maxPoolLayer(lrn2, 3, 3, 2, 2, "pool2", "VALID")conv3 = convLayer(pool2, 3, 3, 1, 1, 384, "conv3")conv4 = convLayer(conv3, 3, 3, 1, 1, 384, "conv4", groups = 2)conv5 = convLayer(conv4, 3, 3, 1, 1, 256, "conv5", groups = 2)pool5 = maxPoolLayer(conv5, 3, 3, 2, 2, "pool5", "VALID")fcIn = tf.reshape(pool5, [-1, 256 * 6 * 6])fc1 = fcLayer(fcIn, 256 * 6 * 6, 4096, True, "fc6")dropout1 = dropout(fc1, self.KEEPPRO)fc2 = fcLayer(dropout1, 4096, 4096, True, "fc7")dropout2 = dropout(fc2, self.KEEPPRO)self.fc3 = fcLayer(dropout2, 4096, self.CLASSNUM, True, "fc8")def loadModel(self, sess):"""load model"""wDict = np.load(self.MODELPATH, encoding = "bytes").item()#for layers in modelfor name in wDict:if name not in self.SKIP:with tf.variable_scope(name, reuse = True):for p in wDict[name]:if len(p.shape) == 1:#biassess.run(tf.get_variable('b', trainable = False).assign(p))else:#weightssess.run(tf.get_variable('w', trainable = False).assign(p))
四、GoogLeNet
,Szegedy等人大大增加了CNN的深度,提出了一个超过20层的CNN结构,称为GoogleNet。在GoogleNet的结构中采用了3种类型的卷积操作,分别是1×1、3×3、5×5,该结构的主要特点是提升了计算机资源的利用率,它的参数比AlexNet少了12倍,而且GoogleNet的准确率更高,在LSVRC-14中获得了图像分类“指定数据”组的第1名。
五、ResNet—深度残差网络
,He等人采用残差网络(Residual Networks,ResNet)来解决梯度消失的问题。ResNet的主要特点是跨层连接,它通过引入捷径连接技术(shortcut connections)将输入跨层传递并与卷积的结果相加。在ResNet中只有一个池化层,它连接在最后一个卷积层后面。ResNet使得底层的网络能够得到充分训练,准确率也随着深度的加深而得到显著提升。将深度为152层的ResNet用于LSVRC-15的图像分类比赛中,它获得了第1名的成绩。在文献中,还尝试将ResNet的深度设置为1000,并在CIFAR-10图像处理数据集中验证该模型。
网络的层数越深,越有可能获得更好的泛化能力。但是当模型加深以后,网络变得越来越难训练,这主要是由于梯度弥散和梯度爆炸现象造成的。在较深层数的神经网络中,梯度信息由网络的末层逐层传向网络的首层时,传递的过程中会出现梯度接近于0 或梯度值非常大的现象。网络层数越深,这种现象可能会越严重。那么怎么解决深层神经网络的梯度弥散和梯度爆炸现象呢?一个很自然的想法是,既然浅层神经网络不容易出现这些梯度现象,那么可以尝试给深层神经网络添加一种回退到浅层神经网络的机制。当深层神经网络可以轻松地回退到浅层神经网络时,深层神经网络可以获得与浅层神经网络相当的模型性能,而不至于更糟糕。通过在输入和输出之间添加一条直接连接的Skip Connection 可以让神经网络具有回退的能力。以VGG13 深度神经网络为例,假设观察到VGG13 模型出现梯度弥散现象,而10 层的网络模型并没有观测到梯度弥散现象,那么可以考虑在最后的两个卷积层添加SkipConnection,通过这种方式,网络模型可以自动选择是否经由这两个卷积层完成特征变换,还是直接跳过这两个卷积层而选择Skip Connection,亦或结合两个卷积层和Skip Connection 的输出
该网络的架构和 VGGNet 类似,主要包括 3x3 的卷积核。因此可以在 VGGNet 的基础上在层之间添加捷径连接以构建一个残差网络。下图展示了从 VGG-19 的部分早期层合成残差网络的过程。
参考于Tensorflow2.0之深度残差网络resnet18实现
1.ResNet18实战cifar10—自定义
实现18 层的深度残差网络ResNet18,并在CIFAR10 图片数据集上训练与测试,标准的 ResNet18 接受输入为22 × 22 大小的图片数据,我们将ResNet18 进行适量调整,使得它输入大小为32×32,输出维度为10。调整后的ResNet18 网络结构如图所示。
将renet的网络搭建放在一个py文件里,将网络训练放在另一个文件里训练的时候通过import导入进来
实现Basic Block
其中包括两个卷积层
由于梯度的加深导致后面的梯度很难传播到前面的层中,所以增加了短接操作,使得这一层从理论上可以退化为短接线。此时,即使发生过拟合,也可以直接从短接层走,提供了一种深层次网络退化为浅层次网络的能力。
class BasicBlock(layers.Layer):# 残差类模块def __init__(self, filter_num, strides=1):super(BasicBlock, self).__init__()# f(x)包含两个普通卷积层,创建卷积层1# # strides=1时,得到output会略小于inputsize,所有需要设置padding=‘same’,保证两者相同self.conv1 = layers.Conv2D(filter_num, (3, 3), strides=strides, padding='same')self.bh1 = layers.BatchNormalization()self.relu = layers.Activation('relu')# # convolution layer = conv + bn + relu# 创建卷积层2self.conv2 = layers.Conv2D(filter_num, (3, 3), strides=1, padding='same')self.bh2 = layers.BatchNormalization()# 插入identity——短接层if strides != 1:# 下采样self.downsample = Sequential()self.downsample.add(layers.Conv2D(filter_num, (1, 1), strides=strides))else: # 否者就直接连接self.downsample = lambda x: xself.stride = stride# 前向传播def call(self, inputs, training=None):# 下采样——残差residual = self.downsample(inputs)# 前向传播函数con1 = self.conv1(inputs)bh1 = self.bh1(con1)relu1 = self.relu(bh1)conv2 = self.conv2(relu1)bh2 = self.bh2(conv2)# f(x) + x操作output = layers.add([bh2, residual])# 再通过激活函数并返回output = self.relu(output)return output
实现Res Block
在创建resnet的之前,一般按照特征图高宽ℎ/𝑤逐渐减少,通道数𝑐逐渐增大的经验法则。可以通过堆叠通道数逐渐增大的Res Block 来实现高层特征的提取,通过build_resblock 可以一次完成多个残差模块的新建。
def build_resblock(s![elf, filter_num, blocks, stride=1):# 堆叠filter_num个BasicBlockres_blocks = Sequential()# 只有第一个BasicBlock 的步长可能不为1,实现下采样res_blocks.add(BasicBlock(filter_num, stride))for _ in range(1, blocks):#其他BasicBlock 步长都为1res_blocks.add(BasicBlock(filter_num, stride=1))return res_blocks
实现resnet网络
class ResNet(keras.Model):def __init__(self, layer_dims, num_classes=10):super(ResNet, self).__init__()# 预处理层self.stem = Sequential([layers.Conv2D(64, (3, 3), strides=(1, 1)),layers.BatchNormalization(),layers.Activation('relu'),layers.MaxPool2D(pool_size=(2, 2), strides=(1, 1), padding='same')])# 堆叠4个Block, 每个block包含了多个BasicBlock,设置步长不一样# 按照经验chanel从小到大,feature_size从大到小self.layer1 = self.build_resblock(64, layer_dims[0])self.layer2 = self.build_resblock(128, layer_dims[0], strides=2)self.layer3 = self.build_resblock(256, layer_dims[0], strides=2)self.layer4 = self.build_resblock(512, layer_dims[0], strides=2)# 自适应层# 原理是对512个通道上面的feature像素值做一个平均,得到一个像素的平均值,将512个像素值送到下一层做均值self.avgpool = layers.GlobalAveragePooling2D()# 最后连接一个全连接层分类self.fc = layers.Dense(num_classes)def call(self, inputs, training=None):# 通过根网络x = self.stem(inputs)# 一次通过4个模块x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)# 通过池化层x = self.avgpool(x)# 通过全连接层x = self.fc(x)return xdef build_resblock(self, filter_num, blocks, strides=1):# 辅助函数,堆叠filter_num个BasicBlock# 只有第一个BasicBlock的步长可能不为1res_block = Sequential()res_block.add(BasicBlock(filter_num, strides))for _ in range(1, blocks): # 其他BasicBlock步长都为1res_block.add(BasicBlock(filter_num, strides))return res_block
通过给ResNet类传参可以构造出resnet18的网络
def resnet18():return ResNet([2, 2, 2, 2])def resnet34():return ResNet([3, 4, 6, 3])
网络完整代码
#!usr/bin/env python# -*- coding:utf-8 -*-"""@author: admin@file: resnet.py@time: /02/25@desc:"""import numpy as npimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers,Sequentialclass BasicBlock(layers.Layer):# 残差类模块def __init__(self, filter_num, strides=1):super(BasicBlock, self).__init__()# f(x)包含两个普通卷积层,创建卷积层1self.conv1 = layers.Conv2D(filter_num, (3, 3), strides=strides, padding='same')self.bh1 = layers.BatchNormalization()self.relu = layers.Activation('relu')# 创建卷积层2self.conv2 = layers.Conv2D(filter_num, (3, 3), strides=1, padding='same')self.bh2 = layers.BatchNormalization()# 插入identityif strides != 1:# 下采样self.downsample = Sequential()self.downsample.add(layers.Conv2D(filter_num, (1, 1), strides=strides))else: # 否者就直接连接self.downsample = lambda x: xself.stride = stridesdef call(self, inputs, training=None):# 下采样——残差residual = self.downsample(inputs)# 前向传播函数con1 = self.conv1(inputs)bh1 = self.bh1(con1)relu1 = self.relu(bh1)conv2 = self.conv2(relu1)bh2 = self.bh2(conv2)# f(x) + x操作output = layers.add([bh2, residual])# 再通过激活函数并返回output = self.relu(output)return outputdef build_resblock(self, filter_num, blocks, stride=1):# 堆叠filter_num 个BasicBlockres_blocks = Sequential()# 只有第一个BasicBlock 的步长可能不为1,实现下采样res_blocks.add(BasicBlock(filter_num, stride))for _ in range(1, blocks): # 其他BasicBlock 步长都为1res_blocks.add(BasicBlock(filter_num, stride=1))return res_blocksclass ResNet(keras.Model):def __init__(self, layer_dims, num_classes=10):super(ResNet, self).__init__()# 根网络预处理self.stem = Sequential([layers.Conv2D(64, (3, 3), strides=(1, 1)),layers.BatchNormalization(),layers.Activation('relu'),layers.MaxPool2D(pool_size=(2, 2), strides=(1, 1), padding='same')])# 堆叠4个Block, 每个block包含了多个BasicBlock,设置步长不一样self.layer1 = self.build_resblock(64, layer_dims[0])self.layer2 = self.build_resblock(128, layer_dims[0], strides=2)self.layer3 = self.build_resblock(256, layer_dims[0], strides=2)self.layer4 = self.build_resblock(512, layer_dims[0], strides=2)# 通过Pooling层将高管降低为1x1self.avgpool = layers.GlobalAveragePooling2D()# 最后连接一个全连接层分类self.fc = layers.Dense(num_classes)def call(self, inputs, training=None):# 通过根网络x = self.stem(inputs)# 一次通过4个模块x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)# 通过池化层x = self.avgpool(x)# 通过全连接层x = self.fc(x)return xdef build_resblock(self, filter_num, blocks, strides=1):# 辅助函数,堆叠filter_num个BasicBlock# 只有第一个BasicBlock的步长可能不为1res_block = Sequential()res_block.add(BasicBlock(filter_num, strides))for _ in range(1, blocks): # 其他BasicBlock步长都为1res_block.add(BasicBlock(filter_num, strides))return res_blockdef resnet18():return ResNet([2, 2, 2, 2])
网络训练
#!usr/bin/env python# -*- coding:utf-8 -*-"""@author: admin@file: 训练.py@time: /02/25@desc:"""import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'# 内存自动增长from pat.v1 import ConfigProtofrom pat.v1 import InteractiveSessionconfig = ConfigProto()config.gpu_options.allow_growth = Truesession = InteractiveSession(config=config)import randomimport numpy as npimport matplotlib.pyplot as pltimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers, optimizers, datasets, Sequentialfrom resnet import resnet18# 随机数种子def seed_everying(SEED):os.environ['TF_DETERMINISTIC_OPS'] = '1'os.environ['PYTHONHASHSEED'] = str(SEED)random.seed(SEED)np.random.seed(SEED)tf.random.set_seed(SEED)seed_everying(42)def proprecess(x, y):# [0-1]x = tf.cast(x, dtype=tf.float32) / 255.y = tf.cast(y, dtype=tf.int32)y = tf.one_hot(y, depth=10)y = tf.squeeze(y)return x, y# 加载数据集(x, y), (x_test, y_test) = datasets.cifar10.load_data()print(x.shape, y.shape, x_test.shape, y_test.shape)# (50000, 32, 32, 3) (50000, ) (10000, 32, 32, 3) (10000, )# 分割数据集x_train, x_val = tf.split(x, num_or_size_splits=[40000, 10000])y_train, y_val = tf.split(y, num_or_size_splits=[40000, 10000])# 构建张量db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))db_train = db_train.map(proprecess).shuffle(40000).batch(256)db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))db_val = db_val.map(proprecess).shuffle(10000).batch(256)db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))db_test = db_test.map(proprecess).batch(256)sample = next(iter(db_train))print('sample:', sample[0].shape, sample[1].shape,tf.reduce_min(sample[0]), tf.reduce_max(sample[0]))def main():# [b, 32, 32, 3] => [b, 1, 1, 512]model = resnet18()model.build(input_shape=(None, 32, 32, 3))pile(optimizer=optimizers.Adam(learning_rate=1e-4),loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy'])# 训练模型early_Stopping = keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=5)history = model.fit(db_train, epochs=100,validation_data=db_val, validation_freq=1,callbacks=[early_Stopping], verbose=2)# 打印迭代图acc = history.history['accuracy']val_acc = history.history['val_accuracy']epochs_range = np.arange(len(acc))fig = plt.figure(figsize=(10, 8))fig.add_subplot()plt.plot(epochs_range, acc, label='Train acc')plt.plot(epochs_range, val_acc, label='Val_acc')plt.legend(loc='upper right')plt.title('Train and Val acc')plt.show()# 预测y_pred = model.predict(db_test)y_pred = np.argmax(y_pred, axis=1)correct = tf.reduce_sum(tf.cast(tf.equal(y_pred, tf.squeeze(y_test)), dtype=tf.int32))print(int(correct) / len(y_test))if __name__ == '__main__':main()
训练结果为
(50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1)sample: (256, 32, 32, 3) (256, 10) tf.Tensor(0.0, shape=(), dtype=float32) tf.Tensor(1.0, shape=(), dtype=float32)Epoch 1/100157/157 - 56s - loss: 1.7597 - accuracy: 0.3667 - val_loss: 0.0000e+00 - val_accuracy: 0.0000e+00Epoch 2/100157/157 - 44s - loss: 1.2077 - accuracy: 0.5658 - val_loss: 2.5604 - val_accuracy: 0.1443Epoch 3/100157/157 - 45s - loss: 0.8812 - accuracy: 0.6904 - val_loss: 2.2478 - val_accuracy: 0.2889Epoch 4/100157/157 - 45s - loss: 0.5679 - accuracy: 0.8080 - val_loss: 1.6933 - val_accuracy: 0.4793Epoch 5/100157/157 - 45s - loss: 0.3047 - accuracy: 0.9031 - val_loss: 1.7637 - val_accuracy: 0.5010Epoch 6/100157/157 - 45s - loss: 0.1791 - accuracy: 0.9430 - val_loss: 1.8352 - val_accuracy: 0.5466Epoch 7/100157/157 - 45s - loss: 0.1145 - accuracy: 0.9646 - val_loss: 2.0367 - val_accuracy: 0.5480Epoch 8/100157/157 - 45s - loss: 0.0975 - accuracy: 0.9695 - val_loss: 2.1200 - val_accuracy: 0.5478Epoch 9/100157/157 - 45s - loss: 0.1122 - accuracy: 0.9620 - val_loss: 2.2285 - val_accuracy: 0.5350Epoch 10/100157/157 - 45s - loss: 0.1264 - accuracy: 0.9566 - val_loss: 2.1866 - val_accuracy: 0.5516Epoch 11/100157/157 - 45s - loss: 0.1002 - accuracy: 0.9650 - val_loss: 2.1875 - val_accuracy: 0.5533Epoch 12/100157/157 - 45s - loss: 0.0570 - accuracy: 0.9818 - val_loss: 2.2877 - val_accuracy: 0.5549Epoch 13/100157/157 - 45s - loss: 0.0432 - accuracy: 0.9858 - val_loss: 2.5048 - val_accuracy: 0.5558Epoch 14/100157/157 - 45s - loss: 0.0459 - accuracy: 0.9841 - val_loss: 2.4180 - val_accuracy: 0.5649Epoch 15/100157/157 - 45s - loss: 0.1082 - accuracy: 0.9622 - val_loss: 2.4957 - val_accuracy: 0.5413Epoch 16/100157/157 - 45s - loss: 0.1177 - accuracy: 0.9596 - val_loss: 2.2915 - val_accuracy: 0.5543Epoch 17/100157/157 - 45s - loss: 0.0846 - accuracy: 0.9715 - val_loss: 2.3482 - val_accuracy: 0.5795Epoch 18/100157/157 - 45s - loss: 0.0475 - accuracy: 0.9837 - val_loss: 2.2737 - val_accuracy: 0.5816Epoch 19/100157/157 - 45s - loss: 0.0490 - accuracy: 0.9838 - val_loss: 2.4608 - val_accuracy: 0.5698Epoch 20/100157/157 - 45s - loss: 0.0276 - accuracy: 0.9910 - val_loss: 2.3808 - val_accuracy: 0.5964Epoch 21/100157/157 - 45s - loss: 0.0347 - accuracy: 0.9881 - val_loss: 2.6131 - val_accuracy: 0.5756Epoch 22/100157/157 - 45s - loss: 0.0434 - accuracy: 0.9854 - val_loss: 2.5044 - val_accuracy: 0.5694Epoch 23/100157/157 - 45s - loss: 0.0985 - accuracy: 0.9661 - val_loss: 2.5350 - val_accuracy: 0.5713Epoch 24/100157/157 - 45s - loss: 0.0759 - accuracy: 0.9735 - val_loss: 2.4286 - val_accuracy: 0.5650Epoch 25/100157/157 - 45s - loss: 0.0415 - accuracy: 0.9863 - val_loss: 2.3778 - val_accuracy: 0.5991Epoch 26/100157/157 - 45s - loss: 0.0265 - accuracy: 0.9909 - val_loss: 2.4366 - val_accuracy: 0.5902Epoch 27/100157/157 - 45s - loss: 0.0277 - accuracy: 0.9901 - val_loss: 2.5511 - val_accuracy: 0.5897Epoch 28/100157/157 - 45s - loss: 0.0423 - accuracy: 0.9858 - val_loss: 2.7998 - val_accuracy: 0.5601Epoch 29/100157/157 - 45s - loss: 0.0652 - accuracy: 0.9769 - val_loss: 2.6011 - val_accuracy: 0.5833Epoch 30/100157/157 - 45s - loss: 0.0614 - accuracy: 0.9791 - val_loss: 2.6302 - val_accuracy: 0.57370.5643
可以看到该网络过拟合严重,所以训练准确率非常低
这一篇文章的准确率高
六、DenseNet网络
参考于/python_LC_nohtyp/article/details/104477074
Skip Connection 的思想在ResNet 上面获得了巨大的成功,研究人员开始尝试不同的Skip Connection 方案,其中比较流行的就是DenseNet 。DenseNet 将前面所有层的特征图信息通过Skip Connection 与当前层输出进行聚合,与ResNet 的对应位置相加方式不同,DenseNet 采用在通道轴𝑐维度进行拼接操作,聚合特征信息。如下图 所示,输入𝑿0 通过H1卷积层得到输出𝑿1,𝑿1与𝑿 在通道轴上进行拼接,得到聚合后的特征张量,送入H2卷积层,得到输出𝑿2,同样的方法,𝑿2与前面所有层的特征信息 𝑿1与𝑿 进行聚合,再送入下一层。如此循环,直至最后一层的输出𝑿4和前面所有层的特征信息:{𝑿𝑖}𝑖= 1 2 3进行聚合得到模块的最终输出。这样一种基于SkipConnection稠密连接的模块叫做Dense Block。
DenseNet 通过堆叠多个Dense Block 构成复杂的深层神经网络
如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论留言!
如果觉得《深度学习TF—8.经典CNN模型—LeNet-5 VGG13 AlexNet GoogLeNet ResNet DenseNet》对你有帮助,请点赞、收藏,并留下你的观点哦!