一虫几、基本原理
卷積神經(jīng)網(wǎng)絡(convolutional neural network, CNN)是一種具有局部連接、權重共享等特性的深層前饋神經(jīng)網(wǎng)絡翔忽。其啟發(fā)來源于生物學上的感受野(receptive field)瘪吏,一般由卷積層卓研、池化層和全連接層組成趴俘。在圖像處理問題上,普通全連接神經(jīng)網(wǎng)絡參數(shù)過多且不能提取局部不變特性奏赘,卷積神經(jīng)網(wǎng)絡則克服了這些缺點寥闪,取得了很好的效果。
卷積層依靠 濾波器(filter)(又稱卷積核(convolution kernel) )進行特征提取磨淌,可將卷積核看做掃描器疲憋,通過掃描輸入數(shù)據(jù)來提取特征,一般卷積核大小為3x3和5x5梁只。假設輸入輸入矩陣大小為缚柳,卷積核大小為,步長stride為搪锣,零填充(zero padding)為秋忙,則經(jīng)過一輪卷積后,輸出大小為构舟。卷積的基本過程如下動圖所示:
卷積層可以顯著減少網(wǎng)絡中連接的數(shù)量灰追,但特征映射數(shù)組中神經(jīng)元個數(shù)并未顯著減少,如果直接接入分類器,仍然易出現(xiàn)過擬合。為解決這個問題哎垦,在卷積層后加入池化層,以降低特征維數(shù)苦蒿,避免過擬合。常用池化有兩種:最大池化(max pooling)渗稍,即取一個區(qū)域最大值刽肠;平均池化(mean pooling)溃肪,即取一個區(qū)域平均值免胃。通過池化音五,原始數(shù)據(jù)的大小被壓縮,特征也減少羔沙。常用的池化層大小為2x2躺涝。
一個典型的卷積網(wǎng)絡是由卷積層、匯聚層扼雏、全連接層交叉堆疊而成坚嗜。在卷積網(wǎng)絡中,參數(shù)為卷積核中權重以及偏置诗充。和全連接前饋網(wǎng)絡類似苍蔬,卷 積網(wǎng)絡也可以通過誤差反向傳播算法來進行參數(shù)學習。在全連接前饋神經(jīng)網(wǎng)絡中蝴蜓,梯度主要通過每一層的誤差項進行反向傳播碟绑, 并進一步計算每層參數(shù)的梯度。在卷積神經(jīng)網(wǎng)絡中茎匠,主要有兩種不同功能的神經(jīng)層:卷積層和匯聚層格仲。而 參數(shù)為卷積核以及偏置,因此只需要計算卷積層中參數(shù)的梯度诵冒。
二凯肋、基本實現(xiàn)
下面通過pytorch對手寫體數(shù)字識別的例子來實現(xiàn)卷積神經(jīng)網(wǎng)絡的過程。
- 庫的導入以及數(shù)據(jù)的下載汽馋。采用MNIST數(shù)據(jù)集侮东,該數(shù)據(jù)集中,訓練集有6萬張圖片豹芯,測試集有1萬張圖片悄雅,使用torchvision可以非常簡便地下載和讀取數(shù)據(jù)。
import torch
import torchvision
import torch.utils.data
import torchvision.transforms as transforms
from sklearn.manifold import TSNE
import numpy as np
from matplotlib import cm
import matplotlib.pyplot as plt
batch_size = 100
train_dataset = torchvision.datasets.MNIST(root='Data', train=True, transform = transforms.ToTensor(), download = True)
test_dataset = torchvision.datasets.MNIST(root='Data', train=False, transform = transforms.ToTensor(), download = False)
train_loader = torch.utils.data.DataLoader(dataset = train_dataset, batch_size = batch_size, shuffle = True)
test_loader = torch.utils.data.DataLoader(dataset = test_dataset, batch_size = batch_size, shuffle = True)
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
- 函數(shù)結(jié)構的設計告组。用于圖像處理的卷積神經(jīng)網(wǎng)絡一般分為兩個部分:特征提取和特征利用煤伟。特征提取由卷積層完成,經(jīng)過池化層來避免特征的簡單重復木缝,最后全連接層利用特征運算得到目標結(jié)果便锨。其詳細結(jié)構參數(shù)如下圖和代碼所示:
class Net(torch.nn.Module):
def __init__(self):
super(Net,self).__init__()
self.conv1 = torch.nn.Sequential(
torch.nn.Conv2d(1,64,kernel_size=3,padding=1),
torch.nn.ReLU(),
torch.nn.Conv2d(64,128,kernel_size=3,padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(stride=2,kernel_size=2))
self.dense = torch.nn.Sequential(
torch.nn.Linear(128*14*14,1024),
torch.nn.ReLU(),
torch.nn.Dropout(p=0.5),
torch.nn.Linear(1024,10))
def forward(self,x):
x = self.conv1(x)
x = x.view(-1,128*14*14)
x = self.dense(x)
return x
- 網(wǎng)絡訓練過程。損失函數(shù)采用交叉熵我碟,優(yōu)化方法采用Adam放案,共迭代5次,每次中由于batch_size為100矫俺,故需循環(huán)600次才能完成訓練吱殉,每循環(huán)100次掸冤,輸出一下結(jié)果。
net = Net().to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(),lr=0.001)
num_epochs = 5
for epoch in range(num_epochs):
for idx,(images,labels) in enumerate(train_loader):
images = images.to(device)
labels = labels.to(device)
#print(images.shape)
preds = net(images)
loss = criterion(preds,labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if idx % 100 == 0:
print('epoch:{}, batch:{}, loss:{}'.format(epoch,idx,loss))
下圖為訓練過程的不同階段的結(jié)果友雳,從中可以一窺卷積作用的過程稿湿。
- 測試過程。訓練好的結(jié)構在10000張測試圖上的表現(xiàn)為正確率99.07 %押赊,這充分說明了卷積神經(jīng)網(wǎng)絡的有效性饺藤。
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
images = images.to(device)
labels = labels.to(device)
outputs = net(images)
predicted = torch.argmax(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))
Test Accuracy of the model on the 10000 test images: 99.07 %。
- 結(jié)果可視化流礁。為了更加形象說明分類的效果涕俗,通過t-SNE降維方法繪制了其可視化結(jié)果。
def plot_with_labels(lowDWeights, labels):
plt.cla()
X, Y = lowDWeights[:, 0], lowDWeights[:, 1]
for x, y, s in zip(X, Y, labels):
c = cm.rainbow(int(255 * s / 9)); plt.text(x, y, s, backgroundcolor=c, fontsize=9)
plt.xlim(X.min(), X.max()); plt.ylim(Y.min(), Y.max()); plt.title('Visualize last layer'); plt.show(); plt.pause(0.01)
#visualization of trained flatten layer (t-SNE)
tsne = TSNE(perplexity=30,n_components=2,init='pca',n_iter=5000)
plot_only = 500
low_dim_embs = tsne.fit_transform(outputs.data.cpu().numpy())[:plot_only,:]
plot_labels = labels.cpu().numpy()[:plot_only]
plot_with_labels(low_dim_embs,plot_labels)
四神帅、問題探討
圖像的上采樣與下采樣
縮小圖像(或稱為下采樣(subsampled)或降采樣(downsampled))的主要目的有兩個:1再姑、使得圖像符合顯示區(qū)域的大小找御;2元镀、生成對應圖像的縮略圖。
放大圖像(或稱為上采樣(upsampling)或圖像插值(interpolating))的主要目的是放大原圖像,從而可以顯示在更高分辨率的顯示設備上萎坷。
下采樣原理:對于一幅圖像I尺寸為M凹联,對其進行s倍下采樣,即得到(M/s)尺寸的得分辨率圖像哆档,即把原始圖像s*s窗口內(nèi)的圖像變成一個像素蔽挠,這個像素點的值就是窗口內(nèi)所有像素的均值或最大值。
上采樣原理:圖像放大幾乎都是采用內(nèi)插值方法瓜浸,即在原有圖像像素的基礎上在像素點之間采用合適的插值算法插入新的元素澳淑。插值方式有很多種,如最近鄰插值插佛,雙線性插值杠巡,均值插值,中值插值等方法雇寇。
參考資料
[1] Vishnu Subramanian. Deep Learning with PyTorch. Packet Publishing. 2018.
[2] 邱錫鵬 著氢拥,神經(jīng)網(wǎng)絡與深度學習. https://nndl.github.io/ 2019.
[3] 肖智清 著,神經(jīng)網(wǎng)絡與PyTorch實戰(zhàn). 北京:機械工業(yè)出版社. 2018.
[4] 唐進民 編著锨侯,深度學習之PyTorch實戰(zhàn)計算機視覺. 北京:電子工業(yè)出版社. 2018.
[5] Ian Goodfellow 等 著, 趙申劍等 譯, 深度學習. 北京:人民郵電出版社, 2017.
[6] https://blog.csdn.net/stf1065716904/article/details/78450997
丈夫只手把吳鉤嫩海,意氣高于百尺樓∏舫眨——李鴻章《入都十首·其一》