一、什么是卷積?
必須在深度學習場景中使用卷積才能創(chuàng)建卷積神經(jīng)網(wǎng)絡。
使用Fashion MNIST數(shù)據(jù)集為時尚商品訓練圖像分類器。為您提供了一個非常準確的分類器,但存在明顯的限制:圖像為28x28灰度,并且項目位于圖像的中心。
例如,這是Fashion MNIST中的幾個圖像

您創(chuàng)建的DNN(深度神經(jīng)網(wǎng)絡)只是從原始像素中了解了什么構成了一件毛衣,以及什么構成了一件靴子。但是,考慮如何對圖像進行分類?

雖然很明顯此啟動程序無法,但是分類器由于多種原因而失敗。首先,不是28x28灰度,而是更重要的是,分類器是針對左側靴子的原始像素而不是構成靴子實際功能的功能進行訓練的。要解決此問題,可以使用卷積。
1、 使用卷積
卷積是通過圖像的濾鏡,對其進行處理并提取出在圖像中具有共同性的特征。在本實驗中,您將通過處理圖像以查看是否可以從中提取特征來了解它們的工作原理!
這個過程非常簡單。您只需掃描圖像中的每個像素,然后查看其相鄰像素。您可以將這些像素的值乘以過濾器中的等效權重。
因此,例如,請考慮以下因素:

在這種情況下,將指定一個3x3卷積矩陣。
當前像素值為192,但是您可以通過查看鄰居值,然后將它們乘以過濾器中指定的值,然后將新像素值作為最終值,來計算得到新的像素值。
2. 導入Python庫
import cv2
import numpy as np
from scipy import misc
i = misc.ascent()
我們可以使用pyplot庫繪制圖像,以便我們知道其外觀。
import matplotlib.pyplot as plt
plt.grid(False)
plt.gray()
plt.axis('off')
plt.imshow(i)
plt.show()

我們可以看到這是樓梯間的圖像。這里有很多功能可供我們查看是否可以分隔它們-例如,有很強的垂直線。
該圖像存儲為numpy數(shù)組,因此我們只需復制該數(shù)組即可創(chuàng)建轉換后的圖像。我們還要獲取圖像的尺寸,以便稍后進行循環(huán)。
i_transformed = np.copy(i)
size_x = i_transformed.shape[0]
size_y = i_transformed.shape[1]
3. 創(chuàng)建卷積
在之前的實驗室中,您看到了如何使用包含三層的深度神經(jīng)網(wǎng)絡(DNN)進行時尚圖像識別-輸入層(以輸入數(shù)據(jù)的形式),輸出層(以所需的輸出的形式)和一個隱藏層。您嘗試了幾種會影響最終精度的參數(shù),例如:隱藏層的大小不同和訓練時期的數(shù)量。
運行它,并記下最后打印出的測試精度。
# 這個過濾器能很好地檢測邊緣
# 它產生僅通過尖銳邊緣和直線的卷積。
# 試用不同的值以獲得更好的效果。
# filter = [ [0, 1, 0], [1, -4, 1], [0, 1, 0]]
# 還有更多過濾器可以嘗試!
filter = [ [-1, -2, -1], [0, 0, 0], [1, 2, 1]]
#filter = [ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
# 如果過濾器中的所有數(shù)字加起來不等于0或1,那么您可能應該對其進行加權
# 例如,如果你的權重是1,1,11,2,11,1,1
# 它們加起來是10,所以如果要規(guī)范化它們,可以將權重設置為.1
weight = 1
現(xiàn)在讓我們計算輸出像素。我們將遍歷圖像,保留1個像素的邊距,然后將當前像素的每個相鄰像素乘以濾鏡中定義的值。
這意味著當前像素在其上方和左側的鄰居將與濾鏡中的左上方項目等相乘。然后將結果乘以權重,然后確保結果在0-255范圍內。
最后,我們將新值加載到轉換后的圖像中。
for x in range(1,size_x-1):
for y in range(1,size_y-1):
output_pixel = 0.0
output_pixel = output_pixel + (i[x - 1, y-1] * filter[0][0])
output_pixel = output_pixel + (i[x, y-1] * filter[0][1])
output_pixel = output_pixel + (i[x + 1, y-1] * filter[0][2])
output_pixel = output_pixel + (i[x-1, y] * filter[1][0])
output_pixel = output_pixel + (i[x, y] * filter[1][1])
output_pixel = output_pixel + (i[x+1, y] * filter[1][2])
output_pixel = output_pixel + (i[x-1, y+1] * filter[2][0])
output_pixel = output_pixel + (i[x, y+1] * filter[2][1])
output_pixel = output_pixel + (i[x+1, y+1] * filter[2][2])
output_pixel = output_pixel * weight
if(output_pixel<0):
output_pixel=0
if(output_pixel>255):
output_pixel=255
i_transformed[x, y] = output_pixel
4. 檢查結果
現(xiàn)在我們可以繪制圖像,以查看通過該濾鏡的效果!
# 繪制圖像。請注意軸的大小-它們是512 x 512
plt.gray()
plt.grid(False)
plt.imshow(i_transformed)
#plt.axis('off')
plt.show()

因此,請考慮以下濾鏡值及其對圖像的影響。
使用[-1,0,1,-2,0,2,-1,0,1]為我們提供了非常強大的垂直線集:

使用[-1,-2,-1,0,0,0,1,2,1]給我們水平線:

另外,請嘗試使用其他大小的濾鏡,例如5x5或7x7。
5. 了解池化
除了使用卷積,池化還可以極大地幫助我們檢測特征。目標是減少圖像中的信息總量,同時保持所檢測到的特征存在。
有許多不同類型的池,但是在本實驗中,我們將使用一種稱為MAX池的池。
這里的想法是遍歷圖像,并考慮像素及其在右側,下方和下方的直接鄰居。取其中最大的一個(因此稱為MAX pooling)并將其加載到新映像中。因此,新圖片將是舊圖片的1/4:

此代碼將顯示(2,2)池。運行它以查看輸出,您會看到圖像是原始圖像大小的1/4,同時保留了所有功能。
new_x = int(size_x/2)
new_y = int(size_y/2)
newImage = np.zeros((new_x, new_y))
for x in range(0, size_x, 2):
for y in range(0, size_y, 2):
pixels = []
pixels.append(i_transformed[x, y])
pixels.append(i_transformed[x+1, y])
pixels.append(i_transformed[x, y+1])
pixels.append(i_transformed[x+1, y+1])
pixels.sort(reverse=True)
newImage[int(x/2),int(y/2)] = pixels[0]
# 繪制圖像。請注意軸的大小-現(xiàn)在是256像素而不是512像素
plt.gray()
plt.grid(False)
plt.imshow(newImage)
#plt.axis('off')
plt.show()

請注意該圖的軸-圖像現(xiàn)在為256x256,是原始大小的1/4,并且盡管圖像中的數(shù)據(jù)更少,但檢測到的功能已得到增強。