PyTorch可视化理解卷积神经网络
如今,機器已經能夠在理解、識別圖像中的特征和對象等領域實現99%級別的準確率。生活中,我們每天都會運用到這一點,比如,智能手機拍照的時候能夠識別臉部、在類似于谷歌搜圖中搜索特定照片、從條形碼掃描文本或掃描書籍等。造就機器能夠獲得在這些視覺方面取得優異性能可能是源于一種特定類型的神經網絡——卷積神經網絡(CNN)。如果你是一個深度學習愛好者,你可能早已聽說過這種神經網絡,并且可能已經使用一些深度學習框架比如caffe、TensorFlow、pytorch實現了一些圖像分類器。然而,這仍然存在一個問題:數據是如何在人工神經網絡傳送以及計算機是如何從中學習的。為了從頭開始獲得清晰的視角,本文將通過對每一層進行可視化以深入理解卷積神經網絡。
卷積神經網絡
在學習卷積神經網絡之前,首先要了解神經網絡的工作原理。神經網絡是模仿人類大腦來解決復雜問題并在給定數據中找到模式的一種方法。在過去幾年中,這些神經網絡算法已經超越了許多傳統的機器學習和計算機視覺算法。“神經網絡”是由幾層或多層組成,不同層中具有多個神經元。每個神經網絡都有一個輸入和輸出層,根據問題的復雜性增加隱藏層的個數。一旦將數據送入網絡中,神經元就會學習并進行模式識別。一旦神經網絡模型被訓練好后,模型就能夠預測測試數據。
另一方面,CNN是一種特殊類型的神經網絡,它在圖像領域中表現得非常好。該網絡是由YanLeCunn在1998年提出的,被應用于數字手寫體識別任務中。其它應用領域包括語音識別、圖像分割和文本處理等。在CNN被發明之前,多層感知機(MLP)被用于構建圖像分類器。圖像分類任務是指從多波段(彩色、黑白)光柵圖像中提取信息類的任務。MLP需要更多的時間和空間來查找圖片中的信息,因為每個輸入元素都與下一層中的每個神經元連接。而CNN通過使用稱為局部連接的概念避免這些,將每個神經元連接到輸入矩陣的局部區域。這通過允許網絡的不同部分專門處理諸如紋理或重復模式的高級特征來最小化參數的數量。下面通過比較說明上述這一點。
比較MLP和CNN
因為輸入圖像的大小為28x28=784(MNIST數據集),MLP的輸入層神經元總數將為784。網絡預測給定輸入圖像中的數字,輸出數字范圍是0-9。在輸出層,一般返回的是類別分數,比如說給定輸入是數字“3”的圖像,那么在輸出層中,相應的神經元“3”與其它神經元相比具有更高的類別分數。這里又會出現一個問題,模型需要包含多少個隱藏層,每層應該包含多少神經元?這些都是需要人為設置的,下面是一個構建MLP模型的例子:
Num_classes = 10 Model = Sequntial() Model.add(Dense(512, activation=’relu’, input_shape=(784, ))) Model.add(Dropout(0.2)) Model.add(Dense(512, activation=’relu’)) Model.add(Dropout(0.2)) Model.add(Dense(num_classes, activation=’softmax’))上面的代碼片段是使用Keras框架實現(暫時忽略語法錯誤),該代碼表明第一個隱藏層中有512個神經元,連接到維度為784的輸入層。隱藏層后面加一個dropout層,丟棄比例設置為0.2,該操作在一定程度上克服過擬合的問題。之后再次添加第二個隱藏層,也具有512谷歌神經元,然后再添加一個dropout層。最后,使用包含10個類的輸出層完成模型構建。其輸出的向量中具有最大值的該類將是模型的預測結果。
這種多層感知器的一個缺點是層與層之間完全連接,這導致模型需要花費更多的訓練時間和參數空間。并且,MLP只接受向量作為輸入。
卷積使用稀疏連接的層,并且其輸入可以是矩陣,優于MLP。輸入特征連接到局部編碼節點。在MLP中,每個節點都有能力影響整個網絡。而CNN將圖像分解為區域(像素的小局部區域),每個隱藏節點與輸出層相關,輸出層將接收的數據進行組合以查找相應的模式。
計算機如何查看輸入的圖像?
看著圖片并解釋其含義,這對于人類來說很簡單的一件事情。我們生活在世界上,我們使用自己的主要感覺器官(即眼睛)拍攝環境快照,然后將其傳遞到視網膜。這一切看起來都很有趣。現在讓我們想象一臺計算機也在做同樣的事情。
在計算機中,使用一組位于0到255范圍內的像素值來解釋圖像。計算機查看這些像素值并理解它們。乍一看,它并不知道圖像中有什么物體,也不知道其顏色。它只能識別出像素值,圖像對于計算機來說就相當于一組像素值。之后,通過分析像素值,它會慢慢了解圖像是灰度圖還是彩色圖。灰度圖只有一個通道,因為每個像素代表一種顏色的強度。0表示黑色,255表示白色,二者之間的值表明其它的不同等級的灰灰色。彩色圖像有三個通道,紅色、綠色和藍色,它們分別代表3種顏色(三維矩陣)的強度,當三者的值同時變化時,它會產生大量顏色,類似于一個調色板。之后,計算機識別圖像中物體的曲線和輪廓。。
下面使用PyTorch加載數據集并在圖像上應用過濾器:
# Load the libraries import torch import numpy as npfrom torchvision import datasets import torchvision.transforms as transforms# Set the parameters num_workers = 0 batch_size = 20# Converting the Images to tensors using Transforms transform = transforms.ToTensor()train_data = datasets.MNIST(root='data', train=True,download=True, transform=transform) test_data = datasets.MNIST(root='data', train=False,download=True, transform=transform)# Loading the Data train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size,num_workers=num_workers) test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, num_workers=num_workers)import matplotlib.pyplot as plt %matplotlib inlinedataiter = iter(train_loader) images, labels = dataiter.next() images = images.numpy()# Peeking into dataset fig = plt.figure(figsize=(25, 4)) for image in np.arange(20):ax = fig.add_subplot(2, 20/2, image+1, xticks=[], yticks=[])ax.imshow(np.squeeze(images[image]), cmap='gray')ax.set_title(str(labels[image].item()))?
下面看看如何將單個圖像輸入神經網絡中:
img = np.squeeze(images[7])fig = plt.figure(figsize = (12,12)) ax = fig.add_subplot(111) ax.imshow(img, cmap='gray') width, height = img.shape thresh = img.max()/2.5 for x in range(width):for y in range(height):val = round(img[x][y],2) if img[x][y] !=0 else 0ax.annotate(str(val), xy=(y,x),color='white' if img[x][y]<thresh else 'black')上述代碼將數字'3'圖像分解為像素。在一組手寫數字中,隨機選擇“3”。并且將實際像素值(0-255 )標準化,并將它們限制在0到1的范圍內。歸一化的操作能夠加快模型訓練收斂速度。
構建過濾器
過濾器,顧名思義,就是過濾信息。在使用CNN處理圖像時,過濾像素信息。為什么需要過濾呢,計算機應該經歷理解圖像的學習過程,這與孩子學習過程非常相似,但學習時間會少的多。簡而言之,它通過從頭學習,然后從輸入層傳到輸出層。因此,網絡必須首先知道圖像中的所有原始部分,即邊緣、輪廓和其它低級特征。檢測到這些低級特征之后,傳遞給后面更深的隱藏層,提取更高級、更抽象的特征。過濾器提供了一種提取用戶需要的信息的方式,而不是盲目地傳遞數據,因為計算機不會理解圖像的結構。在初始情況下,可以通過考慮特定過濾器來提取低級特征,這里的濾波器也是一組像素值,類似于圖像。可以理解為連接卷積神經網絡中的權重。這些權重或濾波器與輸入相乘以得到中間圖像,描繪了計算機對圖像的部分理解。之后,這些中間層輸出將與多個過濾器相乘以擴展其視圖。然后提取到一些抽象的信息,比如人臉等。
就“過濾”而言,我們有很多類型的過濾器。比如模糊濾鏡、銳化濾鏡、變亮、變暗、邊緣檢測等濾鏡。
下面用一些代碼片段來理解過濾器的特征:
?
# 轉換為灰度圖 gray = cv2.cvtColor(image, cv2.COLOR_RB2GRAY)# 定義sobel過濾器 sobel = np.array([-1, -2, -1], [0, 0, 0], [1, 2, 1])) # 應用sobel過濾器 Filtered_image = cv2.filter2D(gray, -1, sobel_y) # 畫圖 Plt.imshow(filtered_image, cmp=’gray’)?
以上是應用sobel邊緣檢測濾鏡后圖像的樣子, 可以看到檢測出輪廓信息。
完整的CNN結構
? ? ? ? 到目前為止,已經看到了如何使用濾鏡從圖像中提取特征。現在要完成整個卷積神經網絡,cnn使用的層是:
- 1.卷積層(Convolutional layer)
- 2.池層(Pooling layer)
- 3.全連接層(fully connected layer)
典型的cnn網絡結構是由上述三類層構成:
下面讓我們看看每個圖層起到的的作用:
* 卷積層(CONV)——使用過濾器執行卷積操作。因為它掃描輸入圖像的尺寸。它的超參數包括濾波器大小,可以是2x2、3x3、4x4、5x5(或其它)和步長S。結果輸出O稱為特征映射或激活映射,具有使用輸入層計算的所有特征和過濾器。下面描繪了應用卷積的工作過程:
- ?池化層(POOL)——用于特征的下采樣,通常在卷積層之后應用。池化處理方式有多種類型,常見的是最大池化(max pooling)和平均池化(ave pooling),分別采用特征的最大值和平均值。下面描述了池化的工作過程:
?
- ?全連接層(FC)——在展開的特征上進行操作,其中每個輸入連接到所有的神經元,通常在網絡末端用于將隱藏層連接到輸出層,下圖展示全連接層的工作過程:
在PyTorch中可視化CNN
在了解了CNN網絡的全部構件后,現在讓我們使用PyTorch框架實現CNN。
步驟1:加載輸入圖像:
?
步驟2:可視化過濾器
對過濾器進行可視化,以更好地了解將使用哪些過濾器:
步驟3:定義CNN模型
本文構建的CNN模型具有卷積層和最大池層,并且使用上述過濾器初始化權重:
Net(
(conv): Conv2d(1, 4, kernel_size=(4, 4), stride=(1, 1), bias=False)
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
步驟4:可視化過濾器
快速瀏覽一下所使用的過濾器
?
步驟5:每層過濾器的輸出
在卷積層和池化層輸出的圖像如下所示:
卷積層:
池化層:
可以看到不同層結構得到的效果會有所差別,正是由于不同層提取到的特征不同,在輸出層集合到的特征才能很好地抽象出圖像信息。
?
原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。
總結
以上是生活随笔為你收集整理的PyTorch可视化理解卷积神经网络的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蚂蚁金服金融级容器引擎实践之路
- 下一篇: 寻找 K8s 1.14 Release