瞭解有關最大池化特徵提取的更多資訊。
簡介
在第二課中,我們開始討論卷積神經網路(convnet)的基礎如何進行特徵提取。我們瞭解了這個過程中的前兩個操作是在帶有 relu 啟用的 Conv2D 層中進行的。
在這一課中,我們將看一下這個序列中的第三個(也是最後一個)操作:透過最大池化進行壓縮,這在 Keras 中是透過 MaxPool2D 層完成的。
透過最大池化進行壓縮
在我們之前的模型中新增壓縮步驟,將得到以下結果:
In [1]:
from tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
layers.Conv2D(filters=64, kernel_size=3), # activation is None
layers.MaxPool2D(pool_size=2),
# More layers follow
])
MaxPool2D 層很像 Conv2D 層,只不過它使用一個簡單的最大函式而不是核心,其中 pool_size 引數類似於 kernel_size。然而,MaxPool2D 層沒有像卷積層在其核心中那樣的可訓練權重。
讓我們再看一下上一課中的提取圖。記住,MaxPool2D 是 Condense 步驟。
注意,應用 ReLU 函式(Detect)後,特徵圖最終會有很多“死區”,即只包含 0 的大面積區域(影像中的黑色區域)。如果讓這些 0 啟用值透過整個網路,將會增加模型的大小,而不會新增太多有用的資訊。相反,我們希望壓縮特徵圖,只保留最有用的部分——特徵本身。
這實際上就是最大池化所做的。最大池化在原始特徵圖的啟用塊中取最大的啟用值。
當在 ReLU 啟用後應用時,它具有“強化”特徵的效果。池化步驟增加了活動畫素與零畫素的比例。
示例 - 應用最大池化
讓我們在第二課中的示例中新增“壓縮”步驟。這個下一個隱藏單元將帶我們回到我們之前的位置。
In [2]:
import tensorflow as tf
import matplotlib.pyplot as plt
import warnings
plt.rc('figure', autolayout=True)
plt.rc('axes', labelweight='bold', labelsize='large',
titleweight='bold', titlesize=18, titlepad=10)
plt.rc('image', cmap='magma')
warnings.filterwarnings("ignore") # to clean up output cells
# Read image
image_path = '../input/computer-vision-resources/car_feature.jpg'
image = tf.io.read_file(image_path)
image = tf.io.decode_jpeg(image)
# Define kernel
kernel = tf.constant([
[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1],
], dtype=tf.float32)
# Reformat for batch compatibility.
image = tf.image.convert_image_dtype(image, dtype=tf.float32)
image = tf.expand_dims(image, axis=0)
kernel = tf.reshape(kernel, [*kernel.shape, 1, 1])
# Filter step
image_filter = tf.nn.conv2d(
input=image,
filters=kernel,
# we'll talk about these two in the next lesson!
strides=1,
padding='SAME'
)
# Detect step
image_detect = tf.nn.relu(image_filter)
# Show what we have so far
plt.figure(figsize=(12, 6))
plt.subplot(131)
plt.imshow(tf.squeeze(image), cmap='gray')
plt.axis('off')
plt.title('Input')
plt.subplot(132)
plt.imshow(tf.squeeze(image_filter))
plt.axis('off')
plt.title('Filter')
plt.subplot(133)
plt.imshow(tf.squeeze(image_detect))
plt.axis('off')
plt.title('Detect')
plt.show();
我們將使用 tf.nn 中的另一個函式來應用池化步驟,即 tf.nn.pool。這是一個 Python 函式,它做的事情與你在模型構建時使用的 MaxPool2D 層相同,但是,作為一個簡單的函式,直接使用更容易。
In [3]:
import tensorflow as tf
image_condense = tf.nn.pool(
input=image_detect, # image in the Detect step above
window_shape=(2, 2),
pooling_type='MAX',
# we'll see what these do in the next lesson!
strides=(2, 2),
padding='SAME',
)
plt.figure(figsize=(6, 6))
plt.imshow(tf.squeeze(image_condense))
plt.axis('off')
plt.show();
非常酷!希望你能看到池化步驟是如何透過在最活躍的畫素周圍壓縮影像來強化特徵的。
平移不變性
我們稱零畫素為“不重要”。這是否意味著它們根本不攜帶任何資訊?實際上,零畫素攜帶位置資訊。空白空間仍然將特徵定位在影像中。當 MaxPool2D 移除其中一些畫素時,它移除了特徵圖中的一些位置資訊。這給卷積網路賦予了一種稱為平移不變性的屬性。這意味著一個帶有最大池化的卷積網路傾向於不透過影像中的位置來區分特徵。(“平移”是改變某物位置而不旋轉它或改變其形狀或大小的數學詞彙。)
觀察當我們反覆應用最大池化到以下特徵圖時會發生什麼。
池化傾向於破壞位置資訊
原始影像中的兩個點在反覆池化後變得無法區分。換句話說,池化破壞了它們的一些位置資訊。由於網路在特徵圖中無法再區分它們,所以它也無法在原始影像中區分它們:它對位置差異已經不變。
實際上,池化只在網路中的小距離上建立平移不變性,就像影像中的兩個點一樣。開始時相距很遠的特徵在池化後仍然會保持不同;只有一些位置資訊丟失了,但並非全部。
但只在小距離上。兩個相距很遠的點保持分離
對於影像分類器來說,對特徵位置的小差異具有不變性是一個很好的屬性。僅僅因為視角或構圖的差異,同一種型別的特徵可能會位於原始影像的各個部分,但我們仍然希望分類器能夠識別出它們是相同的。因為這種不變性是內建在網路中的,我們可以使用更少的資料進行訓練:我們不再需要教它忽略那種差異。這使得卷積網路比只有密集層的網路具有很大的效率優勢。(你將在第6課中看到另一種免費獲得不變性的方法——資料增強!)
結論
在這一課中,我們學習了關於特徵提取的最後一步:使用 MaxPool2D 進行壓縮。在第4課中,我們將完成我們對卷積和池化的討論,以滑動視窗結束。
AI演算法蔣同學致力於資訊學奧賽教學、人工智慧演算法研究工作! B站 ! 淘寶 !