import torch as t import numpy as np import torch.nn as nn import torch.nn.functional as F from torch.autograd import Variable import torch.optim as optim import matplotlib.pyplot as plt x = t.Tensor(3, 2) y = t.rand(5, 3) z = t.rand(5, 3) # print(x, y, z)\ # result = t.Tensor(5, 3) #使用t.add(x,y,out=z)時,這裏需要預先分配空間, 注意是t.Tensor 而不是t.tensor # t.add(y,z, out=result) # # print(x.size(), z+y, z.add(y), t.add(y,z)) # print(result) # print(y) # y.add(z) #普通加法,不改變y的內容;會返回一個新的Tensor,而y不變 # print(y) # # y.add_(z) #inplace加法,改變y的內容;函數名後面帶下劃線_的函數會修改Tensor本身 # print(y) #Tensor的選取操作與numpy類似 # print(x, x[:,1]) #Tensor和numpy的數組之間的互操作 # a = t.ones(5) #新建一個全是1的Tensor # print(a) # b = a.numpy() #Tensor -> Numpy # print(b) # a = np.ones(5) # b = t.from_numpy(a) #Numpy -> Tensor # print (a , b) # #Tensor 和Numpy對象共享內存,一個改變,另外一個隨之改變 # b.add_(1) # print(a, b) #Tensor和Numpy共享內存,一變俱變 # #Tensor可通過.cuda方法轉爲GPU的Tensor # if t.cuda.is_available(): # x = x.cuda() # y = y.cuda() # print(x+y) # # #======================================================= # #Autograde:自動微分 # #Tensor在被封裝爲Variable之後,可以調用它的.backward實現反向傳播,自動計算所有梯度 # from torch.autograd import Variable # x = Variable(t.ones(2, 2), requires_grad = True) # y = x.sum() # print(y.grad_fn) #grad_fn指向一個Function對象,其用來反向傳播計算輸入的梯度 # y.backward() # x.grad.data.zero_() #grad在反向傳播過程中是累加的,所以反向傳播之前需要把梯度清零 # y.backward() # print(x.grad) # # #Variable和Tensor具有近乎一致的接口,在實際使用中可以無縫切換 # y = t.cos(x) # x_tensor_cos = t.cos(x.data) # print(y, x_tensor_cos) #2.2.3 神經網絡 #定義網絡,需要繼承nn.Module,並實現它的forward方法,把網絡中具有可學習參數的層數放在構造函數__init__中 # import torch.nn as nn # import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() # 等價於nn.Module.__init__(self) #'1'表示輸入圖片的通道數,'6'表示輸出通道數,'5'表示卷積核爲5*5 self.conv1 = nn.Conv2d(1, 6, 5) #卷積層 self.conv2 = nn.Conv2d(6, 16, 5) #仿射層/全連接層, y = Wx + b self.fc1 = nn.Linear(16*5*5, 120) #16個5x5變成一維, self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): #override nn.Module中的forward方法;只要在nn.Module的子類中定義了fprward函數,backward函數就會自動實現(利用Autograd) #卷積 激活 池化 x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2)) #reshape, '-1'表示自適應 x = x.view(x.size()[0], -1) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x net = Net() # print(net) # 網絡的可學習參數通過net.parameters()返回,net.named_parameters可同時返回可學習的參數及名稱 # params = list(net.parameters()) # print(len(params)) # for name,parameters in net.named_parameters(): # print(name, ':', parameters.size()) #forward函數的輸入和輸出都是Variable,只有Variable才具有自動求導的功能,Tensor是沒有的,所以輸入時,需要把Tensor封裝成Variable # input = Variable(t.randn(1, 1, 32, 32)) #torch.nn只支持mini-batchs,即一次必須是一個batch # out = net(input) # print(out.size()) # net.zero_grad() # out.backward(Variable(t.ones(1, 10))) # #損失函數 # output = net(input) # target = Variable(t.arange(0, 10)) # print(target) # criterion = nn.MSELoss() # loss = criterion(output, target.float()) #這裏需要類型轉換.float(),.long(),.int(),.double(),.byte();Variable.data獲得Tensor變量 # print(loss) # #運行.backward,觀察調用之前和調用之後的grad # net.zero_grad() # print('反向傳播之前conv1.bias的梯度:', net.conv1.bias.grad) # loss.backward() # print('之後:', net.conv1.bias.grad) #SGD的更新策略: weight = weight - learning_rate * gradient #手動實現如下: # learing_rate = 0.01 # for f in net.parameters(): # f.data.sub_(f.grad.data * learing_rate) # inplace 減法 ################################################################################################## # #torch.optim中實現了做大多數的優化方法,例如RMSProp、Adam、SGD等 # # import torch.optim as optim # #新建一個優化器,指定要調整的參數和學習率 # optimizer = optim.SGD(net.parameters(), lr = 0.01) # # #在訓練過程中,先梯度清零 # optimizer.zero_grad() # # input = Variable(t.randn(1, 1, 32, 32)) #torch.nn只支持mini-batchs,即一次必須是一個batch # target = Variable(t.arange(0, 10)) # criterion = nn.MSELoss() # # #計算損失 # output = net(input) # loss = criterion(output, target.float()) # # #反向傳播 # loss.backward() # print(net.conv1.bias) # # #更新參數 # optimizer.step() # # print(net.conv1.bias.data) ############################################################################ #CIFAR-10分類 import torchvision as tv import torchvision.transforms as transforms from torchvision.transforms import ToPILImage show = ToPILImage() #可以把Tensor轉成Image,方便可視化 #定義對數據的預處理 transform = transforms.Compose([ transforms.ToTensor(), #轉爲Tensor transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), #歸一化 ]) #訓練集 trainset = tv.datasets.CIFAR10( root = '\D\Python相關\數據集\cy\data', train = True, download = True, #若沒有下載好的數據集,則爲True transform = transform, ) trainloader = t.utils.data.DataLoader( trainset, batch_size = 4, shuffle = True, num_workers = 0 #未使用if __name__ == '__main__',使用多線程會報錯 ) #測試集 testset = tv.datasets.CIFAR10( r'\D\Python相關\數據集\cy\data', train = False, download = True, transform = transform, ) testloader = t.utils.data.DataLoader( testset, batch_size = 4, shuffle = False, num_workers = 0 ) classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') (data, label) = trainset[100] #Dataset對象是一個數據集,可以按下標訪問,返回形如(data,label)的數據 print(classes[label], '\n--------') # plt.imshow(show((data+1)/2).resize((100, 100))) # plt.show() #顯示圖像plt.imshow(); plt.show() dataiter = iter(trainloader) images, labels = dataiter.next() #返回4張圖片及標籤 print(' '.join('%11s'%classes[labels[j]] for j in range(4))) picture = show(tv.utils.make_grid((images+1)/2)).resize((400, 100)) #將一個batch的圖片顯示在一張圖片上,(400,100)是寬和高? # plt.imshow(picture) # plt.show() #定義網絡 import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 6, 5) # 卷積層 self.conv2 = nn.Conv2d(6, 16, 5) # 仿射層/全連接層, y = Wx + b self.fc1 = nn.Linear(16 * 5 * 5, 120) # 16個5x5變成一維, self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): #override nn.Module中的forward方法;只要在nn.Module的子類中定義了fprward函數,backward函數就會自動實現(利用Autograd) #卷積 激活 池化 x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) x = F.max_pool2d(F.relu(self.conv2(x)), 2) #reshape, '-1'表示自適應 x = x.view(x.size()[0], -1) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x net = Net() #定義損失函數和優化器(loss和optimizer) from torch import optim criterion = nn.CrossEntropyLoss() #交叉熵損失函數 optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # #訓練網絡 不斷執行如下流程:輸入數據 -> 前向傳播+反向傳播 -> 更新參數 # for epoch in range(2): # running_loss = 0.0 # for i, data in enumerate(trainloader, 0): # # #輸入數據 # inputs, labels = data # inputs, labels = Variable(inputs), Variable(labels) # # #梯度清零 # optimizer.zero_grad() # # #forward + backward # outputs = net(inputs) # loss = criterion(outputs, labels) # loss.backward() # # #更新參數 # optimizer.step() # # #打印log信息 # running_loss += loss.data # if i%2000 == 1999: #每2000個batch打印一次訓練狀態 # print('[%d, %5d] loss: %.3f'%(epoch+1, i+1, running_loss/2000)) # running_loss = 0.0 # t.save(net.state_dict(), 'test.pth') # Module對象的保存 # print('Finished Training.') # # dataiter = iter(testloader) # images, labels = dataiter.next() # print('實際的label:', ''.join('%08s'%classes[labels[j]] for j in range(4))) # show(tv.utils.make_grid(images/2-0.5)).resize((400,100)) # # #計算圖片在每個類別上的分數 # outputs = net(Variable(images)) # #得分最高的那個類 # _, predicted = t.max(outputs.data, 1) # print('預測結果:', ''.join('%08s'%classes[predicted[j]] for j in range(4))) #整個測試集上的效果 correct = 0 total = 0 net.load_state_dict(t.load('test.pth')) # Module對象的加載 for data in testloader: images, labels = data outputs = net(Variable(images)) _, predicted = t.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum() print('準確率爲:%d %%'%(100*correct/total)) #因爲沒有保存參數值,所以此次結果爲隨機猜測10% #在GPU上訓練 if t.cuda.is_available(): net.cuda() images = images.cuda() labels = labels.cuda() outputs = net(Variable(images)) loss = criterion(outputs, Variable(labels))
Pytorch入門與實踐——快速入門
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.