cs231n assignment2 PyTorch

Barebones PyTorch

Three-Layer ConvNet

使用pytorch抽象等級1的方式實現卷積神經網絡。

three_layer_convnet()

out1 = F.conv2d(x, conv_w1, bias=conv_b1, stride=1, padding=(2,2))
relu1 = F.relu(out1)
out2 = F.conv2d(relu1, conv_w2, bias=conv_b2, stride=1, padding=(1,1))
relu2 = F.relu(out2)
scores = torch.mm(flatten(relu2), fc_w) + fc_b

Training a ConvNet

使用上面完成的卷積神經網絡,訓練模型。下面需要完成初始化參數。

conv_w1 = random_weight((channel_1,3,5,5))
conv_b1 = zero_weight((channel_1,))
conv_w2 = random_weight((channel_2,channel_1,3,3))
conv_b2 = zero_weight((channel_2,))
fc_w = random_weight((32*32*channel_2,10))
fc_b = zero_weight((10,))

PyTorch Module API

接下來的代碼使用nn.Module來完成,與上面的代碼進行比較可以發現,使用nn.Module的代碼更具有層次性,符合面向對象的編程思想。並且在上面的代碼中,需要手動實現參數初始化,但是在下面的代碼中可以直接通過nn的函數來實現。

class ThreeLayerConvNet

def __init__(self, in_channel, channel_1, channel_2, num_classes):
    super().__init__()
	self.conv1 = nn.Conv2d(in_channel, channel_1, kernel_size=5,stride=1, padding=2)
    nn.init.kaiming_normal_(self.conv1.weight)
    self.conv2 = nn.Conv2d(channel_1, channel_2, kernel_size=3, stride=1,padding=1)
    nn.init.kaiming_normal_(self.conv2.weight)
    self.fc = nn.Linear(channel_2 * 32 * 32, num_classes)
    nn.init.kaiming_normal_(self.fc.weight)
def forward(self, x):
	scores = None
	relu1 = F.relu(self.conv1(x))
	relu2 = F.relu(self.conv2(relu1))
	scores = self.fc(flatten(relu2)
	return scores

Module API: Train a Three-Layer ConvNet

使用已經寫好的網絡,訓練一個模型,使之在CIFAR10的準確率達到45%以上。
PyTorch.ipynb

in_channel = 3
num_classes = 10
model = ThreeLayerConvNet(in_channel=in_channel, channel_1=channel_1, channel_2=channel_2, num_classes=num_classes)
optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=0.9)

Part IV. PyTorch Sequential API

可以從上面的代碼中發現,使用模塊API需要完成在__init__中的定義,以及在forward函數中實現每一層的連接。下面使用Sequential API,它把所有步驟合成爲一個了,這也就決定了他的靈活性不如Module API,但是對於絕大多數場景來說是夠用了。

model = nn.Sequential(
    nn.Conv2d(3,channel_1,kernel_size=5, padding=2, bias=True),
    nn.ReLU(),
    nn.Conv2d(channel_1, channel_2, kernel_size=3, padding=1, bias=True),
    nn.ReLU(),
    Flatten(),
    nn.Linear(channel_2 * 32 * 32, 10, bias=True)
)
optimizer = optim.SGD(model.parameters(), momentum=0.9, lr=learning_rate, nesterov=True)

Part V. CIFAR-10 open-ended challenge

使用自定義的網絡結構,完成對CIFAR-10數據集的訓練和分類,使之準確率達到70%以上,我才用的結構爲
[conv-relu-pool]xN -> [affine]xM -> [softmax or SVM]

channel_1 = 20
channel_2 = 30
learning_rate=0.001

model = nn.Sequential(
    nn.Conv2d(3, 32, kernel_size=5, stride=1, padding=2),
    nn.ReLU(),
    nn.MaxPool2d(2, 2),
    nn.Conv2d(32, 64, kernel_size=5, stride=1, padding=2),
    nn.ReLU(),
    nn.MaxPool2d(2, 2),
    nn.Conv2d(64, 128, kernel_size=5, stride=1, padding=2),
    nn.ReLU(),
    nn.MaxPool2d(2, 2),
    Flatten(),
    nn.Linear(128 * 4 * 4, 20),
    nn.Linear(20, 10)
)
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

最後的準確率有76%


搭建卷積神經網絡需要注意的事項

在搭建網絡的過程中,要注意每一層的結構大小,需要按照一定的公式進行計算。

卷積層:

F爲卷積核大小,W爲圖片的寬,H爲圖片的高,S爲步長,P爲padding大小
D:圖像深度(通道數),N:卷積核(過濾器)個數

卷積層後輸出的大小爲:
	W' = (W - F + 2P)/S + 1
	H' = (H - F + 2P)/S + 1 
卷積後輸出圖像深度:
	N' = N

池化層:

    W:圖像寬,H:圖像高,D:圖像深度(通道數)
    F:卷積核寬高,S:步長

池化後的大小爲:
	 W=(W-F)/S+1
     H=(H-F)/S+1
池化後輸出圖像深度:
	 N' = D(保持上一層不變)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章