【18】GlobalAveragePooling 与 Flatten 的差异与比较

Colab连结

今天要探讨的主题在模型从CNN Layer 转变成 Dense Layer 时,使用 GlobalAveragePooling (GAP) 与 Flatten 两者之前的差异。

我们假设最後一层CNN的宽高是W和H,通道数是C,那麽通过 GlobalAveragePooling 後,我们会得到W和H都变成1,通道数维持不变(11C),而又因为是GlobalAverage的关系,他是直接以通道为区分,直接装里面的权重值做平均。

https://ithelp.ithome.com.tw/upload/images/20211002/20107299NjWydi5WWT.png
图片来源

相反的 Flatten 就简单很多,它直接宽乘高乘通道(HxWxC),再继续接上後面的 Dense Layer。了解以上两个概念後我们就可以来做实验。

实验一:GlobalAveragePooling

base = tf.keras.applications.MobileNetV2(input_shape=(224, 224, 3), include_top=False, weights='imagenet')
net = tf.keras.layers.GlobalAveragePooling2D()(base.output)
net = tf.keras.layers.Dense(NUM_OF_CLASS)(net)

model = tf.keras.Model(inputs=[base.input], outputs=[net])
model.summary()

model.compile(
    optimizer=tf.keras.optimizers.SGD(LR),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)

history = model.fit(
    ds_train,
    epochs=EPOCHS,
    validation_data=ds_test,
    verbose=True)

在 model.summary() 中,可以看到经过 GlobalAveragePooling,输出从 7x7x1280 变成 1x1x1280

out_relu (ReLU)                 (None, 7, 7, 1280)   0           Conv_1_bn[0][0]                  
__________________________
global_average_pooling2d_2 (Glo (None, 1280)         0           out_relu[0][0]                   

产出:

loss: 4.0428e-04 - sparse_categorical_accuracy: 1.0000 - val_loss: 0.4005 - val_sparse_categorical_accuracy: 0.9020

https://ithelp.ithome.com.tw/upload/images/20211002/20107299WbtteQ8n98.png

其实这模型前面训练很多遍了,但这次跑出了准确度90%。

实验二:Flatten

base = tf.keras.applications.MobileNetV2(input_shape=(224, 224, 3), include_top=False, weights='imagenet')
net = tf.keras.layers.Flatten()(base.output)
net = tf.keras.layers.Dense(NUM_OF_CLASS)(net)

model = tf.keras.Model(inputs=[base.input], outputs=[net])
model.summary()

model.compile(
    optimizer=tf.keras.optimizers.SGD(LR),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)

history = model.fit(
    ds_train,
    epochs=EPOCHS,
    validation_data=ds_test,
    verbose=True)

model.summary() 中,看到经过 Flatten,输出从 7x7x1280 变成 62720。

out_relu (ReLU)                 (None, 7, 7, 1280)   0           Conv_1_bn[0][0]                  
__________________________
flatten_1 (Flatten)             (None, 62720)        0           out_relu[0][0]                   

产出

loss: 0.0063 - sparse_categorical_accuracy: 0.9990 - val_loss: 9.1377 - val_sparse_categorical_accuracy: 0.0833

https://ithelp.ithome.com.tw/upload/images/20211002/201072997NcoCozNtY.png

效果不太理想,训练失败,由於看到 val_loss 有喷高的现象出现,故我将 LR 降低成0.01後,再次训练一次 Flatten 的实验三。

base = tf.keras.applications.MobileNetV2(input_shape=(224, 224, 3), include_top=False, weights='imagenet')
net = tf.keras.layers.Flatten()(base.output)
net = tf.keras.layers.Dense(NUM_OF_CLASS)(net)

model = tf.keras.Model(inputs=[base.input], outputs=[net])

model.compile(
    optimizer=tf.keras.optimizers.SGD(0.01),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)

history = model.fit(
    ds_train,
    epochs=EPOCHS,
    validation_data=ds_test,
    verbose=True)

产出:

loss: 1.4501e-04 - sparse_categorical_accuracy: 1.0000 - val_loss: 1.0266 - val_sparse_categorical_accuracy: 0.7500

https://ithelp.ithome.com.tw/upload/images/20211002/20107299XDV5LdQF7k.png

降低 LR 後,模型有效成长,虽然最後准确度仍低於 GlobalAveragePooling,但至少是朝着收敛迈进,我自己在执行训练任务时,也是以 GlobalAveragePooling 为主。


<<:  Android Studio初学笔记-Day17-ItemTouchHelper

>>:  Day 27 Compose UI Drawer

【第五天 - Queue 题目分析】

先简单回顾一下,今天预计分析的题目: 如何利用两个 stack 完成 Queue 的概念? 逻辑很简...

[Android Studio 30天自我挑战] ToggleButton元件介绍

ToggleButton为开关按钮,也就是说点一下就显示开启再点一下就显示关闭。 ToggleBut...

总结与未来展望

写在完赛之後 参赛动机与心得 在约莫两个月前与硕班的学长 Richard 的聊天当中,他邀请我参加这...

摊平摊平,愈摊愈平

这也是很多输家最爱用的手段之一,进场时说是「成长型」投资,被套牢了,改口说是「价值型」投资,你真的懂...

[Day - 29] React Hooks useEffect 学习笔记

useEffect - 副作用处理 useEffect:资料获取、订阅或手动方式修改 React C...