都說MNIST相當於機器學習界的Hello World。最近加入實驗室,導師給我們安排了一個任務,但是我才剛剛入門吶!!沒辦法,只能從最基本的學起。
Pytorch是一套開源的深度學習張量庫。或者我傾向於把它當成一個獨立的深度學習框架。為了寫這么一個"Hello World"。查閱了不少資料,也踩了不少坑。不過同時也學習了不少東西,下面我把我的代碼記錄下來,希望能夠從中受益更多,同時幫助其他對Pytorch感興趣的人。代碼的注釋中有不對的地方歡迎批評指正。
代碼進行了注釋,應該很方便閱讀。 dependences: numpy torch torchvision python3 使用pip安裝即可。
1 # encoding: utf-8 2 import torch 3 import torch.nn as nn 4 import torch.nn.functional as F #加載nn中的功能函數 5 import torch.optim as optim #加載優化器有關包 6 import torch.utils.data as Data 7 from torchvision import datasets,transforms #加載計算機視覺有關包 8 from torch.autograd import Variable 9 10 BATCH_SIZE = 64 11 12 #加載torchvision包內內置的MNIST數據集 這里涉及到transform:將圖片轉化成torchtensor 13 train_dataset = datasets.MNIST(root='~/data/',train=True,transform=transforms.ToTensor(),download=True) 14 test_dataset = datasets.MNIST(root='~/data/',train=False,transform=transforms.ToTensor()) 15 16 #加載小批次數據,即將MNIST數據集中的data分成每組batch_size的小塊,shuffle指定是否隨機讀取 17 train_loader = Data.DataLoader(dataset=train_dataset,batch_size=BATCH_SIZE,shuffle=True) 18 test_loader = Data.DataLoader(dataset=test_dataset,batch_size=BATCH_SIZE,shuffle=False) 19 20 #定義網絡模型亦即Net 這里定義一個簡單的全連接層784->10 21 class Model(nn.Module): 22 def __init__(self): 23 super(Model,self).__init__() 24 self.linear1 = nn.Linear(784,10) 25 26 def forward(self,X): 27 return F.relu(self.linear1(X)) 28 29 model = Model() #實例化全連接層 30 loss = nn.CrossEntropyLoss() #損失函數選擇,交叉熵函數 31 optimizer = optim.SGD(model.parameters(),lr = 0.1) 32 num_epochs = 5 33 34 #以下四個列表是為了可視化(暫未實現) 35 losses = [] 36 acces = [] 37 eval_losses = [] 38 eval_acces = [] 39 40 for echo in range(num_epochs): 41 train_loss = 0 #定義訓練損失 42 train_acc = 0 #定義訓練准確度 43 model.train() #將網絡轉化為訓練模式 44 for i,(X,label) in enumerate(train_loader): #使用枚舉函數遍歷train_loader 45 X = X.view(-1,784) #X:[64,1,28,28] -> [64,784]將X向量展平 46 X = Variable(X) #包裝tensor用於自動求梯度 47 label = Variable(label) 48 out = model(X) #正向傳播 49 lossvalue = loss(out,label) #求損失值 50 optimizer.zero_grad() #優化器梯度歸零 51 lossvalue.backward() #反向轉播,刷新梯度值 52 optimizer.step() #優化器運行一步,注意optimizer搜集的是model的參數 53 54 #計算損失 55 train_loss += float(lossvalue) 56 #計算精確度 57 _,pred = out.max(1) 58 num_correct = (pred == label).sum() 59 acc = int(num_correct) / X.shape[0] 60 train_acc += acc 61 62 losses.append(train_loss / len(train_loader)) 63 acces.append(train_acc / len(train_loader)) 64 print("echo:"+' ' +str(echo)) 65 print("lose:" + ' ' + str(train_loss / len(train_loader))) 66 print("accuracy:" + ' '+str(train_acc / len(train_loader))) 67 eval_loss = 0 68 eval_acc = 0 69 model.eval() #模型轉化為評估模式 70 for X,label in test_loader: 71 X = X.view(-1,784) 72 X = Variable(X) 73 label = Variable(label) 74 testout = model(X) 75 testloss = loss(testout,label) 76 eval_loss += float(testloss) 77 78 _,pred = testout.max(1) 79 num_correct = (pred == label).sum() 80 acc = int(num_correct) / X.shape[0] 81 eval_acc += acc 82 83 eval_losses.append(eval_loss / len(test_loader)) 84 eval_acces.append(eval_acc / len(test_loader)) 85 print("testlose: " + str(eval_loss/len(test_loader))) 86 print("testaccuracy:" + str(eval_acc/len(test_loader)) + '\n')
運行后的結果如下:
我們在上面的代碼中,將圖片對應的Pytorchtensor展平,並通過一個全連接層,僅僅是這樣就達到了90%以上的准確率。如果使用卷積層,正確率有望達到更高。
代碼並不完備,還可以增加visualize和predict功能,等我學到更多知識后,有待后續添加。