卷積神經網路
卷積
從全連接到卷積
-
分類貓和狗的圖片
- 使用一個還不錯的相機采集圖片(12M像素)
- RGB圖片有36個元素
- 使用100大小的單隱藏層MLP,模型有3.6B個元素
- 遠多于世界上所有的貓和狗的總和(900M狗,600M貓)

- 遠多于世界上所有的貓和狗的總和(900M狗,600M貓)
-
我們在圖片中找Waldo在哪里,這時候我們有兩個原則
- 平移不變性,也就是說在圖片任何地方,我們識別一個東西,這個識別器不需要改變
- 區域性,我們要找一個東西我們只需要看區域的資訊就可以了,
重新考察全連接層
- 在前面全連接層我們識別一張圖片的時候,我們是將圖片展成一個一維的張量了,現在我們將輸入和輸出變形為矩陣(寬度,和高度),因為需要存放一些空間資訊
- 將權重變形為4-D張亮(h,w) 到 ( h ′ , w ′ ) (h', w') (h′,w′),記為: h i , j = ∑ k , l w i , j , k , l x k , l = ∑ a , b v i , j , a , b x i + a , j + b h_{i,j} = \sum_{k,l}w_{i,j,k,l}x_{k,l}=\sum_{a,b}v_{i,j,a,b}x_{i+a,j+b} hi,j?=∑k,l?wi,j,k,l?xk,l?=∑a,b?vi,j,a,b?xi+a,j+b?.這里h是我們的輸出,x是我們的輸入,w是我們的權重,
- V是W的重新索引使得 v i , j , a , b = w i , j , i + a , j + b v_{i,j,a,b}=w_{i,j,i+a,j+b} vi,j,a,b?=wi,j,i+a,j+b?
原則一:平移不變性
- x的平移導致h的平移 h i , j = ∑ a , b v i , j , a , b x i + a , j + b h_{i,j}=\sum_{a,b}v_{i,j,a,b}x_{i+a,j+b} hi,j?=∑a,b?vi,j,a,b?xi+a,j+b?
- v不應該依賴于(i, j)
- 解決方案: v i , j , a , b = v a , b v_{i,j,a,b}=v_{a,b} vi,j,a,b?=va,b?,則 h i , j = ∑ a , b v a , b x i + a , j + b h_{i,j}=\sum_{a,b}v_{a,b}x_{i+a,j+b} hi,j?=∑a,b?va,b?xi+a,j+b?
- 這就是2維卷積,在數學上來說叫做2維的較叉相關
原則二:區域性
h i , j = ∑ a , b v a , b x i + a , j + b h_{i,j}=\sum_{a,b}v_{a,b}x_{i+a,j+b} hi,j?=∑a,b?va,b?xi+a,j+b?
- 當評估 h i , j h_{i,j} hi,j?時,我們不應該用遠離 x i , j x_{i,j} xi,j?的引數
- 解決方案:當$\left | a \right |,\left | b\right | > \Delta , 使 得 ,使得 ,使得v_{a,b}=0 , , ,h_{i,j}=\sum_{a=-\Delta }^{\Delta }\sum_{b=-\Delta }^{\Delta }v_{a,b}x_{i+a,j+b}$
總結

卷積層
二維交叉相關
- 這里我們的輸入是一個33的矩陣,這里的卷積核kernel是一個22的,所有這里的delta是1,這里的輸出是由,kernel乘以輸入的元素得到的,這里是元素的相乘,然后每次移動delta個位置

二維卷積層
-
二維卷積層,從神經網路的角度來說,就是輸入是一個 n h × n w n_h\times n_w nh?×nw?,卷積核是 k h × k w k_h\times k_w kh?×kw?,偏差b是一個實數,輸出是 Y = X ? W + b Y=X*W+b Y=X?W+b,這里的Y中的+1是因為每一步大小為1

-
下面的圖片我們可以看到不同的卷積核可以帶來不同的效果,卷積核是我們學到的

較叉相關vs卷積

一維和三維交叉相關

總結

影像卷積代碼實作
# 互相關運算
import torch
from torch import nn
from d2l import torch as d2l
# 這里的輸入是我們的輸入x和卷積核K
def corr2d(X, K):
"""算二維互相關運算"""
h, w = K.shape # 這里就是拿出卷積核的行和列
Y = torch.zeros(X.shape[0] -h + 1, X.shape[1] - w + 1) # 根據上面理論我們可以得到我們輸出的矩陣的大小,也就是輸入矩陣的行減去卷積核的行+1,列同理
# 下面的兩個for回圈的作用是給,輸出矩陣的每個元素賦值,這里就是拿卷積核和對應的區的元素做乘法運算
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
return Y
# 驗證上述二維互相關運算的輸出
X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
corr2d(X, K)
tensor([[19., 25.],
[37., 43.]])
# 實作二維卷積層
class Conv2D(nn.Module):
def __init__(self, kernel_size): # 這里kernel_size就是卷積核的大小是一個超引數,可以定義為3*3或2*2,都行
super().__init__()
self.weight = nn.Parameter(torch.rand(kernel_size)) # 這個是我們的引數要學的
self.bias = nn.Parameter(torch.zeros(1))
def forward(self, x):
return corr2d(x, self.weight) + self.bias
# 卷積層的一個簡單應用:檢測影像中不同顏色的邊緣
# 我們首先構造一個輸入X,這是一個特殊的矩陣它的前兩列是1,中間4列是0,最后2列是1,這樣我們從0變到1或者從1變到0要么是1要么是-1
X = torch.ones((6, 8))
X[:, 2:6] = 0
X
tensor([[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.]])
# 這邊是構造一個卷積核
K = torch.tensor([[1.0, -1.0]])
Y = corr2d(X, K)
Y
tensor([[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.]])
# 卷積核K只能檢測垂直邊緣
corr2d(X.t(), K)
tensor([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
# 學習由X生成Y的卷積核
# 這里我們直接呼叫了pytorch中定義的一個二維的卷積層,第一個引數的意思是:輸入的通道為1,第二個引數的意思是輸出的通道為1,kernel_size指定核的大小
conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)
X = X.reshape((1, 1, 6, 8)) # 這里reshape的原因是因為,第一個維度是通道維,第二個維度是批量大小維,后面的才是值
Y = Y.reshape((1, 1, 6, 7))
for i in range(10):
Y_hat = conv2d(X) # 這里是將X傳入到網路,計算出輸出
l = (Y_hat - Y) ** 2 # 這里采用了一個均方誤差
conv2d.zero_grad() # 將梯度置為0
l.sum().backward() # 反向傳播求梯度
conv2d.weight.data[:] -= 3e-2 * conv2d.weight.grad # 這里手寫了一個梯度下降,3e-1是學習率
if (i + 1) % 2 == 0:
print(f'batch {i+1}, loss {l.sum():.3f}')
batch 2, loss 11.542
batch 4, loss 2.754
batch 6, loss 0.797
batch 8, loss 0.271
batch 10, loss 0.102
# 學習到的卷積核的權重張量
conv2d.weight.data.reshape((1, 2))
tensor([[ 1.0170, -0.9533]])
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/294618.html
標籤:AI
