Pytorch是torch的Python版本,對TensorFlow造成很大的沖擊,TensorFlow無疑是最流行的,但是Pytorch號稱在諸多性能上要優於TensorFlow,比如在RNN的訓練上,所以Pytorch也吸引了很多人的關注。之前有一篇關於TensorFlow實現的CNN可以用來做對比。
下面我們就開始用Pytorch實現CNN。
step 0 導入需要的包
1 import torch 2 import torch.nn as nn 3 from torch.autograd import Variable 4 import torch.utils.data as data 5 import matplotlib.pyplot as plt
step 1 數據預處理
這里需要將training data轉化成torch能夠使用的DataLoader,這樣可以方便使用batch進行訓練。
1 import torchvision #數據庫模塊 2 3 torch.manual_seed(1) #reproducible 4 5 #Hyper Parameters 6 EPOCH = 1 7 BATCH_SIZE = 50 8 LR = 0.001 9 10 train_data = torchvision.datasets.MNIST( 11 root='/mnist/', #保存位置 12 train=True, #training set 13 transform=torchvision.transforms.ToTensor(), #converts a PIL.Image or numpy.ndarray 14 #to torch.FloatTensor(C*H*W) in range(0.0,1.0) 15 download=True 16 ) 17 18 test_data = torchvision.datasets.MNIST(root='/MNIST/') 19 #如果是普通的Tensor數據,想使用torch_dataset = data.TensorDataset(data_tensor=x, target_tensor=y) 20 #將Tensor轉換成torch能識別的dataset 21 #批訓練, 50 samples, 1 channel, 28*28, (50, 1, 28 ,28) 22 train_loader = data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) 23 24 test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), volatile=True).type(torch.FloatTensor)[:2000]/255. 25 test_y = test_data.test_lables[:2000]
step 2 定義網絡結構
需要指出的幾個地方:1)class CNN需要繼承Module ; 2)需要調用父類的構造方法:super(CNN, self).__init__() ;3)在Pytorch中激活函數Relu也算是一層layer; 4)需要實現forward()方法,用於網絡的前向傳播,而反向傳播只需要調用Variable.backward()即可。
1 class CNN(nn.Module): 2 def __init__(self): 3 super(CNN, self).__init__() 4 self.conv1 = nn.Sequential( #input shape (1,28,28) 5 nn.Conv2d(in_channels=1, #input height 6 out_channels=16, #n_filter 7 kernel_size=5, #filter size 8 stride=1, #filter step 9 padding=2 #con2d出來的圖片大小不變 10 ), #output shape (16,28,28) 11 nn.ReLU(), 12 nn.MaxPool2d(kernel_size=2) #2x2采樣,output shape (16,14,14) 13 14 ) 15 self.conv2 = nn.Sequential(nn.Conv2d(16, 32, 5, 1, 2), #output shape (32,7,7) 16 nn.ReLU(), 17 nn.MaxPool2d(2)) 18 self.out = nn.Linear(32*7*7,10) 19 20 def forward(self, x): 21 x = self.conv1(x) 22 x = self.conv2(x) 23 x = x.view(x.size(0), -1) #flat (batch_size, 32*7*7) 24 output = self.out(x) 25 return output
step 3 查看網絡結構
使用print(cnn)可以看到網絡的結構詳細信息,ReLU()真的是一層layer。
1 cnn = CNN() 2 print(cnn)
step 4 訓練
指定optimizer,loss function,需要特別指出的是記得每次反向傳播前都要清空上一次的梯度,optimizer.zero_grad()。
1 #optimizer 2 optimizer = torch.optim.Adam(cnn.parameters(), lr=LR) 3 4 #loss_fun 5 loss_func = nn.CrossEntropyLoss() 6 7 #training loop 8 for epoch in range(EPOCH): 9 for i, (x, y) in enumerate(train_loader): 10 batch_x = Variable(x) 11 batch_y = Variable(y) 12 #輸入訓練數據 13 output = cnn(batch_x) 14 #計算誤差 15 loss = loss_func(output, batch_y) 16 #清空上一次梯度 17 optimizer.zero_grad() 18 #誤差反向傳遞 19 loss.backward() 20 #優化器參數更新 21 optimizer.step()
step 5 預測結果
1 test_output =cnn(test_x[:10]) 2 pred_y = torch.max(test_output,1)[1].data.numpy().squeeze() 3 print(pred_y, 'prediction number') 4 print(test_y[:10])
reference: