【19】使用 Pooling 和 Conv 来把图片变小 (subsampling) 的比较实验

Colab连结

早期刚学深度学习时,我们 AlexNet 学到了几个基本的 CNN, Dense, Pooling, Dropout Layers,其中 Pooling 又有 Max 和 Avg 两种版本,但现代的模型中,我们越来越少看到 Pooling Layer 的存在(Global Pooling 不算),近期取而代之的是将多数的 Layer 尽量利用 CNN 来搞定,这样既可以降低下采样(subsampling),同时还多了几个权重让模型去学习,当然,这麽做的代价就是预算比较复杂些。

今天要来做的实验是比较 MaxPooling vs AvgPooling vs Conv 三种用来作为 down sampleing 手段的比较。

资料集我们采用 beans,共有三种分类,辨别叶片的健康状况。

NUM_OF_CLASS = 3

ds_data, ds_info = tfds.load(
    'beans',
    shuffle_files=True,
    as_supervised=True,
    with_info=True,
)

train_split, test_split = ds_data['train'], ds_data['test']


fig = tfds.show_examples(train_split, ds_info)

print(f'number of train: {len(train_split)}')
print(f'number of test: {len(test_split)}')

https://ithelp.ithome.com.tw/upload/images/20211003/20107299EdwJgZfoLC.png

实验一,使用 MaxPooling

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPooling2D, AveragePooling2D, Flatten, Dense

def alexnet_modify_max_pooling():
  model = Sequential()
  model.add(Conv2D(32, (11, 11), padding='valid', input_shape=(227,227,3)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(3, 3)))

  model.add(Conv2D(64, (7, 7), padding='valid'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(3, 3)))

  model.add(Conv2D(96, (3, 3), padding='valid'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(3, 3)))

  model.add(Conv2D(64, (3, 3), padding='same'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(3, 3)))

  model.add(Flatten())
  model.add(Dense(128))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dense(64))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dense(NUM_OF_CLASS))

  return model

产出:

EPOCH 172/200
loss: 0.0015 - sparse_categorical_accuracy: 1.0000 - val_loss: 0.7871 - val_sparse_categorical_accuracy: 0.8438

https://ithelp.ithome.com.tw/upload/images/20211003/20107299Jxb3J35qtT.png

实验二,使用AvgPooling

def alexnet_modify_avg_pooling():
  model = Sequential()
  model.add(Conv2D(32, (11, 11), padding='valid', input_shape=(227,227,3)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(AveragePooling2D(pool_size=(3, 3)))

  model.add(Conv2D(64, (7, 7), padding='valid'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(AveragePooling2D(pool_size=(3, 3)))

  model.add(Conv2D(96, (3, 3), padding='valid'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(AveragePooling2D(pool_size=(3, 3)))

  model.add(Conv2D(64, (3, 3), padding='same'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(AveragePooling2D(pool_size=(3, 3)))

  model.add(Flatten())
  model.add(Dense(128))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dense(64))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dense(NUM_OF_CLASS))

  return model

产出:

EPOCH 155/200
loss: 0.0060 - sparse_categorical_accuracy: 0.9990 - val_loss: 0.7398 - val_sparse_categorical_accuracy: 0.8438

https://ithelp.ithome.com.tw/upload/images/20211003/20107299XI0VExGebx.png

得出的成果和实验一的 MaxPooling 差不多。但两者的准确度上升图表可以看到 MaxPooling 较为稳定,AvgPooling 在中後期准确度仍有低至50%的情况发生。

实验三,使用 Conv(strides=3) 取代 Pooling。

def alexnet_modify_conv_replace_pooling():
  model = Sequential()
  model.add(Conv2D(32, (11, 11), padding='valid', input_shape=(227,227,3)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Conv2D(32, (3, 3), strides=(3, 3), padding='valid'))

  model.add(Conv2D(64, (7, 7), padding='valid'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Conv2D(64, (3, 3), strides=(3, 3), padding='valid'))

  model.add(Conv2D(96, (3, 3), padding='valid'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Conv2D(96, (3, 3), strides=(3, 3), padding='valid'))

  model.add(Conv2D(64, (3, 3), padding='same'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Conv2D(64, (3, 3), strides=(3, 3), padding='valid'))

  model.add(Flatten())
  model.add(Dense(128))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dense(64))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dense(NUM_OF_CLASS))

  return model

产出

EPOCH 194/200
loss: 7.5052e-04 - sparse_categorical_accuracy: 1.0000 - val_loss: 1.0053 - val_sparse_categorical_accuracy: 0.7734

https://ithelp.ithome.com.tw/upload/images/20211003/20107299V70ZxHngu2.png

从结果的准确度来看,使用 Conv 取代 Pooling 并没有比 Pooling 准确度来的高,当然可以再尝试的地方就是将 Flatten 取代成 Global Pooling 并把後面的 Dense 拿掉,但是今天的测试纯属想知道只更换 Pooling 会产生什麽样的变化,就做了这样的实验罗。


<<:  JavaScript学习日记 : Day21 - 数组方法(一)

>>:  Day19|【Git】开始使用分支 - git branch(基本常用指令)

Day 03:转吧转吧七彩霓虹灯之 p10k

我把从第一天到现在每天的 Home 目录都放上 GitHub 了,README.md 里面有说明 ...

Day-5 Excel自动填满的奥妙

大家好~~继昨天提到的自动填满功能,今天将更深入的来探讨这个功能,分别为自动填满等差数列及格式。那在...

02 - Rectangle - 视窗管理工具

macOS 原生并不支援视窗的分割显示,可以达到差不多效果的只有在「空间」中指定左右两边显示的视窗而...

[第二十四只羊] 迷雾森林舞会XVIII 游戏角色设定again_final_final

天亮了 昨晚2号玩家死亡 关於迷雾森林故事 颤栗消逝 洛神:昨晚2号玩家被杀死了,邪恶阵营获胜,可以...

寻找mail server

各位大大好, 第一次发文, 想请教有无推荐的mail server,公司用,约100使用者, 有看过...