GoogLeNet—tensorflow2.0实战(Fashion mnist数据集)

GoogLeNet—tensorflow2.0实战(Fashion mnist数据集)

目录

GoogLeNet—tensorflow2.0实战(Fashion mnist数据集)

1、GoogLeNet —V1简单介绍

2、Inception结构介绍

3、Inception作用

4、结构细节

5、GooLeNet网络结构

6、实验代码

7、结论

8、参考


1、GoogLeNet —V1简单介绍

这是GoogLeNet的最早版本,出现在2014年的《Going deeper with convolutions》。之所以名为“GoogLeNet”而非“GoogleNet”,文章说是为了向早期的LeNet致敬。深度学习以及神经网络快速发展,人们不再只关注硬件、数据集、模型,而是更在意新的创意、新的算法以及模型的改进。一般来说,提升网络性能最直接的办法就是增加网络深度和宽度,这也就意味着需要训练大量的参数。过多的参数可能会导致结果过拟合,并且计算量增大。

最终解决过拟合以及计算量大这两个问题的根本方法是从全连接层的结构过渡到稀疏的连接结构,甚至在卷积内部也是如此。

2、Inception结构介绍

Inception结构最初是作为第一作者的案例研究来评估复杂网络拓扑构造算法的假设提出的,该算法试图逼近暗示的视觉网络的稀疏结构,并通过密集,易于获得的方法覆盖了假设的结果。 在进一步调整学习率,超参数和改进的训练方法之后,我们确定了所得的Inception体系结构在定位和目标检测中特别有用。 有趣的是,尽管大多数原始结构选择都受到了质疑和测试,但事实证明它们至少是局部最优的。尽管提出的体系结构已经可以用于计算机视觉,但是其质量是否可以归功于导致其构建的指导原则仍然值得怀疑。 确保将需要进行更彻底的分析和验证:例如,如果基于下述原理的自动化工具能够为视觉网络找到相似但更好的拓扑结构。 最有说服力的证明是,如果一个自动化系统创建的网络拓扑结构能够使用相同的算法,但在全局架构上却大不相同,从而在其他域中获得相似的收益。 至少,Inception结构的最初成功为在此方向上未来的激动人心的工作产生了坚定的动力。

3、Inception作用

显著增加了每一步的单元数目,计算复杂度不会不受限制,尺度较大的块卷积之前先降维。 视觉信息在不同尺度上进行处理聚合,这样下一步可以从不同尺度提取特征。文章指出Inception的作用:代替人工确定卷积层中的过滤器类型或者确定是否需要创建卷积层和池化层,即:不需要人为的决定使用哪个过滤器,是否需要池化层等,由网络自行决定这些参数,可以给网络添加所有可能值,将输出连接起来,网络自己学习它需要什么样的参数。

4、结构细节

GoogLeNet—tensorflow2.0实战(Fashion mnist数据集)_第1张图片

对上图做以下说明: 
1、采用不同大小的卷积核意味着不同大小的感受野,最后拼接意味着不同尺度特征的融合; 
2、之所以卷积核大小采用1、3和5,主要是为了方便对齐。设定卷积步长stride=1之后,只要分别设定padding=0、1、2,3、之后便可以得到相同维度的特征,然后这些特征就可以直接拼接在一起了; 
4、Inception里面也嵌入了pooling,结果挺有效;
5、网络越到后面,特征越抽象,而且每个特征所涉及的感受野也更大了,因此随着层数的增加,3x3和5x5卷积的比例也要增加。

5、GooLeNet网络结构

1、平均池化层采用5×5的卷积核大小,步长为3,导致(4a)的输出为4×4×512,(4d)的输出为4×4×528。

2、具有128个1×1大小的卷积核,用于减小尺寸和校正线性激活。

3、具有1024个节点的全连接层,并具有线性校正激活功能。

4、尽管移除了全连接,但是网络中依然使用了Dropout ,避免过拟合。
5、一个具有softmax损失的线性层作为分类器(预测与主分类器相同的1000个分类,但在推理时将其删除)。

 

GoogLeNet—tensorflow2.0实战(Fashion mnist数据集)_第2张图片

6、实验代码

Inception设计

import  tensorflow as tf
import  numpy as np
from    tensorflow import keras
import os
class ConvBNRelu(keras.Model):

    def __init__(self, ch, kernelsz=3, strides=1, padding='same'):
        super(ConvBNRelu, self).__init__()

        self.model = keras.models.Sequential([
            keras.layers.Conv2D(ch, kernelsz, strides=strides, padding=padding),
            keras.layers.BatchNormalization(),
            keras.layers.ReLU()
        ])

    def call(self, x, training=None):
        x = self.model(x, training=training)

        return x


    # Inception Block 模块。
class InceptionBlk(keras.Model):

    def __init__(self, ch, strides=1):
        super(InceptionBlk, self).__init__()

        self.ch = ch
        self.strides = strides

        self.conv1 = ConvBNRelu(ch, strides=strides)
        self.conv2 = ConvBNRelu(ch, kernelsz=3, strides=strides)
        self.conv3_1 = ConvBNRelu(ch, kernelsz=3, strides=strides)
        self.conv3_2 = ConvBNRelu(ch, kernelsz=3, strides=1)

        self.pool = keras.layers.MaxPooling2D(3, strides=1, padding='same')
        self.pool_conv = ConvBNRelu(ch, strides=strides)

    def call(self, x, training=None):
        x1 = self.conv1(x, training=training)

        x2 = self.conv2(x, training=training)

        x3_1 = self.conv3_1(x, training=training)
        x3_2 = self.conv3_2(x3_1, training=training)

        x4 = self.pool(x)
        x4 = self.pool_conv(x4, training=training)

        # concat along axis=channel    通道数
        x = tf.concat([x1, x2, x3_2, x4], axis=3)

        return x


# Res Block 模块。继承keras.Model或者keras.Layer都可以
class Inception(keras.Model):

    def __init__(self, num_layers, num_classes, init_ch=16, **kwargs):
        super(Inception, self).__init__(**kwargs)

        self.in_channels = init_ch
        self.out_channels = init_ch
        self.num_layers = num_layers
        self.init_ch = init_ch

        self.conv1 = ConvBNRelu(init_ch)

        self.blocks = keras.models.Sequential(name='dynamic-blocks')

        for block_id in range(num_layers):

            for layer_id in range(2):

                if layer_id == 0:

                    block = InceptionBlk(self.out_channels, strides=2)

                else:
                    block = InceptionBlk(self.out_channels, strides=1)

                self.blocks.add(block)

            # enlarger out_channels per block
            self.out_channels *= 2

        self.avg_pool = keras.layers.GlobalAveragePooling2D()
        self.fc = keras.layers.Dense(num_classes)

    def call(self, x, training=None):

        out = self.conv1(x, training=training)

        out = self.blocks(out, training=training)

        out = self.avg_pool(out)
        out = self.fc(out)

        return out

 数据集预处理

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
tf.random.set_seed(22)

batchsize = 512

def preprocess(x, y):  #数据预处理
    x = tf.cast(x, dtype=tf.float32)/ 255. - 0.5
    y = tf.cast(y, dtype=tf.int32)
    return x,y

(x_train, y_train),(x_test, y_test) = keras.datasets.fashion_mnist.load_data()
print(x_train.shape, y_train.shape)

# [b, 28, 28] => [b, 28, 28, 1]
x_train, x_test = np.expand_dims(x_train, axis=3), np.expand_dims(x_test, axis=3)

#训练集预处理
db_train = tf.data.Dataset.from_tensor_slices((x_train,y_train)) #构造数据集,这里可以自动的转换为tensor类型了
db_train = db_train.map(preprocess).shuffle(10000).batch(batchsize)

#测试集预处理
db_test = tf.data.Dataset.from_tensor_slices((x_test,y_test)) #构造数据集
db_test = db_test.map(preprocess).shuffle(10000).batch(batchsize)

db_iter = iter(db_train)
sample = next(db_iter)
print("batch: ", sample[0].shape, sample[1].shape)

调用Inception

model = Inception(2, 10) # 第一参数为残差块数,第二个参数为类别数;
# derive input shape for every layers.
model.build(input_shape=(None, 28, 28, 1))
model.summary()

optimizer =keras.optimizers.Adam(learning_rate=1e-3)
criteon = keras.losses.CategoricalCrossentropy(from_logits=True)  # 分类器

acc_meter = keras.metrics.Accuracy()

for epoch in range(100):

    for step, (x, y) in enumerate(db_train):

        with tf.GradientTape() as tape:
            # print(x.shape, y.shape)
            # [b, 10]
            logits = model(x)
            # [b] vs [b, 10]
            loss = criteon(tf.one_hot(y, depth=10), logits)

        grads = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(zip(grads, model.trainable_variables))

        if step % 20 == 0:
            print(epoch, step, 'loss:', loss.numpy())

    # 测试集测试
    acc_meter.reset_states()
    for x, y in db_test:
        # [b, 10]
        logits = model(x, training=False)
        # [b, 10] => [b]
        pred = tf.argmax(logits, axis=1)
        # [b] vs [b, 10]
        acc_meter.update_state(y, pred)
    print(epoch, 'evaluation acc:', acc_meter.result().numpy())
Model: "inception_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv_bn_relu_42 (ConvBNRelu) multiple                  224       
_________________________________________________________________
dynamic-blocks (Sequential)  multiple                  292704    
_________________________________________________________________
global_average_pooling2d_2 ( multiple                  0         
_________________________________________________________________
dense_2 (Dense)              multiple                  1290      
=================================================================
Total params: 294,218
Trainable params: 293,226
Non-trainable params: 992
_________________________________________________________________
0 0 loss: 2.3045938
0 20 loss: 1.329363
0 40 loss: 0.9938534
0 60 loss: 0.69767785
0 80 loss: 0.7414908
0 100 loss: 0.6246513
1 0 loss: 0.57690525
1 20 loss: 0.7181334
1 40 loss: 0.6372799
1 60 loss: 0.56322277
1 80 loss: 0.519943
1 100 loss: 0.53726363
2 0 loss: 0.60184646
2 20 loss: 0.53243566
2 40 loss: 0.5325299
2 60 loss: 0.4348207
2 80 loss: 0.4384783
2 100 loss: 0.44925293
3 0 loss: 0.67428815
3 20 loss: 0.5142151
3 40 loss: 0.44201934
3 60 loss: 0.41263458
3 80 loss: 0.4190077
3 100 loss: 0.36581862
4 0 loss: 0.4223614
4 20 loss: 0.42564046
4 40 loss: 0.38395065
4 60 loss: 0.39734188
4 80 loss: 0.3508845
4 100 loss: 0.37631914
5 0 loss: 0.36114857
5 20 loss: 0.3901283
5 40 loss: 0.32644668
5 60 loss: 0.41383916
5 80 loss: 0.3583411
5 100 loss: 0.34498602
6 0 loss: 0.45242745
6 20 loss: 0.3334728
6 40 loss: 0.3804313
6 60 loss: 0.34394422
6 80 loss: 0.3270644
6 100 loss: 0.32063553
7 0 loss: 0.31886974
7 20 loss: 0.3142283
7 40 loss: 0.2726599
7 60 loss: 0.29281652
7 80 loss: 0.2711956
7 100 loss: 0.3366116
8 0 loss: 0.44309464
8 20 loss: 0.318788
8 40 loss: 0.3126357
8 60 loss: 0.28127334
8 80 loss: 0.2736734
8 100 loss: 0.27562279
9 0 loss: 0.2749536
9 20 loss: 0.31452334
9 40 loss: 0.24373831
9 60 loss: 0.3058698
9 80 loss: 0.29490903
9 100 loss: 0.2548433
10 0 loss: 0.22642994
10 20 loss: 0.25524795
10 40 loss: 0.25892287
10 60 loss: 0.3305801
10 80 loss: 0.2680674
10 100 loss: 0.24107268
11 0 loss: 0.2675702
11 20 loss: 0.28717366
11 40 loss: 0.30391273
11 60 loss: 0.25676006
11 80 loss: 0.24093005
11 100 loss: 0.25176764
12 0 loss: 0.24184336
12 20 loss: 0.2655635
12 40 loss: 0.24473307
12 60 loss: 0.18223602
12 80 loss: 0.2300067
12 100 loss: 0.24467997
13 0 loss: 0.2915982
13 20 loss: 0.21357125
13 40 loss: 0.21650207
13 60 loss: 0.29005748
13 80 loss: 0.23573406
13 100 loss: 0.23202647
14 0 loss: 0.24281901
14 20 loss: 0.21868399
14 40 loss: 0.19210878
14 60 loss: 0.22449979
14 80 loss: 0.25175282
14 100 loss: 0.20557953
15 0 loss: 0.23304522
15 20 loss: 0.19441521
15 40 loss: 0.22906345
15 60 loss: 0.18750042
15 80 loss: 0.22950414
15 100 loss: 0.25577813
16 0 loss: 0.21919861
16 20 loss: 0.16465753
16 40 loss: 0.21372154
16 60 loss: 0.26617402
16 80 loss: 0.18787542
16 100 loss: 0.22275339
17 0 loss: 0.2142167
17 20 loss: 0.21959808
17 40 loss: 0.21935801
17 60 loss: 0.23098597
17 80 loss: 0.19962177
17 100 loss: 0.1983304
18 0 loss: 0.20799458
18 20 loss: 0.20041838
18 40 loss: 0.1563338
18 60 loss: 0.20617214
18 80 loss: 0.23493534
18 100 loss: 0.14152527
19 0 loss: 0.20739853
19 20 loss: 0.2525779
19 40 loss: 0.2526775
19 60 loss: 0.20153278
19 80 loss: 0.1991007
19 100 loss: 0.22249362
20 0 loss: 0.1700981
20 20 loss: 0.2237401
20 40 loss: 0.19593716
20 60 loss: 0.16197991
20 80 loss: 0.18780659
20 100 loss: 0.18872637
21 0 loss: 0.14666645
21 20 loss: 0.16460156
21 40 loss: 0.1799635
21 60 loss: 0.13943696
21 80 loss: 0.19984484
21 100 loss: 0.1610533
22 0 loss: 0.16185123

......

7、结论

在2014年 ILSVRC 挑战赛 ImageNet 分类任务上获得冠军,如下表所示:

GoogLeNet—tensorflow2.0实战(Fashion mnist数据集)_第3张图片

与较浅和较不宽泛的网络相比,此方法的主要优点是在计算需求适度增加的情况下可显着提高质量。 还要注意,尽管我们既未利用上下文也未执行边界框回归,但检测工作具有竞争优势,这一事实进一步证明了Inception体系结构的实力。 尽管可以预期,通过深度和宽度相近的昂贵得多的网络可以达到类似的结果质量,但是我们的方法得出的确凿证据表明,转向稀疏结构通常是可行且有用的想法。 这表明在[2]的基础上,未来的工作有希望以自动方式创建稀疏和更精细的结构。

8、参考

GoogLeNet论文翻译:《Going deeper with convolutions》

TF2.0深度学习实战(六):搭建GoogLeNet卷积神经网络

GoogLeNetV1,V2系列讲解

感谢以上博主的分享。

你可能感兴趣的:(深度学习实战)