1989年,Yann LeCun提出了一种用反向传导进行更新的卷积神经网络,称为LeNet。
1998年,Yann LeCun提出了一种用反向传导进行更新的卷积神经网络,称为LeNet-5
AlexNet是2012年ISLVRC 2012(ImageNet Large Scale Visual Recognition Challenge)竞赛的冠军网络,分类准确率由传统的 70%+提升到 80%+。 它是由Hinton和他的学生Alex Krizhevsky设计的。也是在那年之后,深度学习开始迅速发展。
VGG在2014年由牛津大学著名研究组VGG (Visual Geometry Group) 提出,斩获该年ImageNet竞 中 Localization Task (定位 任务) 第一名 和 Classification Task (分类任务) 第二名。[1.38亿个参数]
GoogLeNet在2014年由Google团队提出,斩获当年ImageNet竞赛中Classification Task (分类任务) 第一名。[论文:Going deeper with convolutions][600多万参数]
ResNet
(1)减少参数
(2)卷积核比较小,可以扫到细节特征;卷积核大,可以扫描大的结构
左边是inception原始结构(用多个卷积核分别扫描,然后组合起来)
右边加了一个维度缩减(用多个卷积核分别扫描,在卷积核基础上进行堆叠减少维度)
from tensorflow import keras
import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
class Inception(keras.layers.Layer):
def __init__(self, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj, **kwargs):
super().__init__(**kwargs)
self.branch1 = keras.layers.Conv2D(ch1x1, kernel_size=1, activation='relu')
self.branch2 = keras.Sequential([
keras.layers.Conv2D(ch3x3red, kernel_size=1, activation='relu'),
keras.layers.Conv2D(ch3x3, kernel_size=3, padding='SAME', activation='relu')
])
self.branch3 = keras.Sequential([
keras.layers.Conv2D(ch5x5red, kernel_size=1, activation='relu'),
keras.layers.Conv2D(ch5x5, kernel_size=5, padding='SAME', activation='relu')
])
self.branch4 = keras.Sequential([
keras.layers.MaxPool2D(pool_size=3, strides=1, padding='SAME'),
keras.layers.Conv2D(pool_proj, kernel_size=1, activation='relu')
])
def call(self, inputs, **kwargs):
branch1 = self.branch1(inputs)
branch2 = self.branch2(inputs)
branch3 = self.branch3(inputs)
branch4 = self.branch4(inputs)
outputs = keras.layers.concatenate([branch1, branch2, branch3, branch4])
return outputs
# 定义辅助输出结构
class InceptionAux(keras.layers.Layer):
def __init__(self, num_classes, **kwargs):
super().__init__(**kwargs)
self.average_pool = keras.layers.AvgPool2D(pool_size=5, strides=3)
self.conv = keras.layers.Conv2D(128, kernel_size=1, activation='relu')
self.fc1 = keras.layers.Dense(1024, activation='relu')
self.fc2 = keras.layers.Dense(num_classes)
self.softmax = keras.layers.Softmax()
def call(self, inputs, **kwargs):
x = self.average_pool(inputs)
x = self.conv(x)
x = keras.layers.Flatten()(x)
x = keras.layers.Dropout(rate=0.5)(x)
x = self.fc1(x)
x = keras.layers.Dropout(rate=0.5)(x)
x = self.fc2(x)
x = self.softmax(x)
return x
def GoogLeNet(im_height=224, im_width=224, class_num=1000, aux_logits=False):
input_image = keras.layers.Input(shape=(im_height, im_width, 3), dtype='float32')
x = keras.layers.Conv2D(64, kernel_size=7, strides=2, padding='SAME', activation='relu')(input_image)
# 注意MaxPool2D, padding='SAME', 224/2=112, padding='VALID', (224 -(3 -1 )) / 2 = 111, same向上取整.
x = keras.layers.MaxPool2D(pool_size=3, strides=2, padding='SAME')(x)
x = keras.layers.Conv2D(64, kernel_size=1, strides=1, padding='SAME', activation='relu')(x)
x = keras.layers.Conv2D(192, kernel_size=3, strides=1, padding='SAME', activation='relu')(x)
x = keras.layers.MaxPool2D(pool_size=3, strides=2, padding='SAME')(x)
x = Inception(64, 96, 128, 16, 32, 32, name='inception_3a')(x)
x = Inception(128, 128, 192, 32, 96, 64, name='inception_3b')(x)
x = keras.layers.MaxPool2D(pool_size=3, strides=2, padding='SAME')(x)
x = Inception(192, 96, 208, 16, 48, 64, name='inception_4a')(x)
if aux_logits:
aux1 = InceptionAux(class_num, name='aux_1')(x)
x = Inception(160, 112, 224, 24, 64, 64, name='inception_4b')(x)
x = Inception(128, 128, 256, 24, 64, 64, name='inception_4c')(x)
x = Inception(112, 144, 288, 32, 64, 64, name='inception_4d')(x)
if aux_logits:
aux2 = InceptionAux(class_num, name='aux_2')(x)
x = Inception(256, 160, 320, 32, 128, 128, name='inception_4e')(x)
x = keras.layers.MaxPool2D(pool_size=3, strides=2, padding='SAME')(x)
x = Inception(256, 160, 320, 32, 128, 128, name='inception_5a')(x)
x = Inception(384, 192, 384, 48, 128, 128, name='inception_5b')(x)
x = keras.layers.AvgPool2D(pool_size=7, strides=1)(x)
x = keras.layers.Flatten()(x)
x = keras.layers.Dropout(rate=0.4)(x)
x = keras.layers.Dense(class_num)(x)
aux3 = keras.layers.Softmax(name='aux_3')(x)
if aux_logits:
aux = aux1 * 0.2 + aux2 * 0.3 + aux3 * 0.5
model = keras.models.Model(inputs=input_image, outputs=aux)
else:
model = keras.models.Model(inputs=input_image, outputs=aux3)
return model
train_dir = './training/training/'
valid_dir = './validation/validation/'
# 图片数据生成器
train_datagen = keras.preprocessing.image.ImageDataGenerator(
rescale = 1. / 255,
rotation_range = 40,
width_shift_range = 0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True,
vertical_flip = True,
fill_mode = 'nearest'
)
height = 224
width = 224
channels = 3
batch_size = 32
num_classes = 10
train_generator = train_datagen.flow_from_directory(train_dir,
target_size = (height, width),
batch_size = batch_size,
shuffle = True,
seed = 7,
class_mode = 'categorical')
valid_datagen = keras.preprocessing.image.ImageDataGenerator(
rescale = 1. / 255
)
valid_generator = valid_datagen.flow_from_directory(valid_dir,
target_size = (height, width),
batch_size = batch_size,
shuffle = True,
seed = 7,
class_mode = 'categorical')
print(train_generator.samples)
print(valid_generator.samples)
googlenet = GoogLeNet(class_num=10)
googlenet.summary()
googlenet.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['acc'])
history = googlenet.fit(train_generator,
steps_per_epoch=train_generator.samples // batch_size,
epochs=10,
validation_data=valid_generator,
validation_steps = valid_generator.samples // batch_size
)