CNN:识别简单块的挑战
CNN: challenge to recognize simple blocks
我很想获得有关以下挑战的见解和观点。我正在尝试训练 CNN 对具有不同颜色 "block" 的图像进行分类(请参见下面的示例)。图像是二维数组(例如 20 x 100 像素),其中白色编码为 0,蓝色编码为 1,绿色编码为 2。
我正在努力训练一个在这些类型的图像上具有良好性能的网络 - 特别是为了防止在图像尺寸变大(例如 40 x 100).我试图理解/概念化需要哪种类型的 CNN 结构来识别这些类型的特征。
我在下面包含了我当前的网络结构 - 但这种结构往往具有混合性能,并且在图像大小增加时失败或变得非常慢。我假设网络必须从上到下看到整个青色 'block' 才能做出准确的分类。
我很想知道这样做的最佳方法。向网络添加更多层的最佳方法是什么?或者使用更大的卷积windows?或者添加更多转化。过滤到每一层(例如从 64 到 96 等)?我觉得我在基本层面上做错了什么。
非常感谢您的想法和观点。
model = Sequential()
model.add(Conv2D(64, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dropout(0.25))
model.add(Dense(1,activation="sigmoid"))
opt = keras.optimizers.rmsprop(lr=0.001, decay=1e-5)
model.compile(loss='binary_crossentropy',optimizer=opt,metrics=['accuracy'])
所以只是为了向您展示您的设计中的两个可能问题和一些可能的解决方案:
你的网络的感受野太小了:让我们根据原始图片的大小来分析你的网络,其中来自给定层的过滤器看到:
model = Sequential()
model.add(Conv2D(64, (3, 3), input_shape=input_shape)) # RF size = (3, 3)
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) # RF size = (4, 4)
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3))) # RF size = (6, 6)
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) # RF size = (7, 7)
model.add(Dropout(0.25))
...
因此,从您的网络接收信号的区域的最大尺寸远小于您图片的尺寸(高度似乎为 10)。
为了克服这个问题 - 你可以增加第一层的过滤器大小,使其高度等于图片的高度(所以基本上使用了相当于 1D
卷积的东西)。
Flatten
是个坏主意: 当你使用 Flatten
- 你的网络实际上考虑了不同模式的位置在您的图像上-例如它需要分别区分左侧的完整块和右侧的完整块,即使它们是相同的对象。克服这个问题的最佳选择是使用 GlobalMaxPooling2D
,它最适合 检测图像上的 模式(前提是过滤器尺寸足够大)。
我很想获得有关以下挑战的见解和观点。我正在尝试训练 CNN 对具有不同颜色 "block" 的图像进行分类(请参见下面的示例)。图像是二维数组(例如 20 x 100 像素),其中白色编码为 0,蓝色编码为 1,绿色编码为 2。
我正在努力训练一个在这些类型的图像上具有良好性能的网络 - 特别是为了防止在图像尺寸变大(例如 40 x 100).我试图理解/概念化需要哪种类型的 CNN 结构来识别这些类型的特征。
我在下面包含了我当前的网络结构 - 但这种结构往往具有混合性能,并且在图像大小增加时失败或变得非常慢。我假设网络必须从上到下看到整个青色 'block' 才能做出准确的分类。
我很想知道这样做的最佳方法。向网络添加更多层的最佳方法是什么?或者使用更大的卷积windows?或者添加更多转化。过滤到每一层(例如从 64 到 96 等)?我觉得我在基本层面上做错了什么。
非常感谢您的想法和观点。
model = Sequential()
model.add(Conv2D(64, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dropout(0.25))
model.add(Dense(1,activation="sigmoid"))
opt = keras.optimizers.rmsprop(lr=0.001, decay=1e-5)
model.compile(loss='binary_crossentropy',optimizer=opt,metrics=['accuracy'])
所以只是为了向您展示您的设计中的两个可能问题和一些可能的解决方案:
你的网络的感受野太小了:让我们根据原始图片的大小来分析你的网络,其中来自给定层的过滤器看到:
model = Sequential() model.add(Conv2D(64, (3, 3), input_shape=input_shape)) # RF size = (3, 3) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) # RF size = (4, 4) model.add(Dropout(0.25)) model.add(Conv2D(64, (3, 3))) # RF size = (6, 6) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) # RF size = (7, 7) model.add(Dropout(0.25)) ...
因此,从您的网络接收信号的区域的最大尺寸远小于您图片的尺寸(高度似乎为 10)。
为了克服这个问题 - 你可以增加第一层的过滤器大小,使其高度等于图片的高度(所以基本上使用了相当于
1D
卷积的东西)。Flatten
是个坏主意: 当你使用Flatten
- 你的网络实际上考虑了不同模式的位置在您的图像上-例如它需要分别区分左侧的完整块和右侧的完整块,即使它们是相同的对象。克服这个问题的最佳选择是使用GlobalMaxPooling2D
,它最适合 检测图像上的 模式(前提是过滤器尺寸足够大)。