第一学:pytorch入门60min
生活随笔
收集整理的這篇文章主要介紹了
第一学:pytorch入门60min
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
1、Tensor張量
2、自動微分
3、神經網絡
4、pytorch圖像分類器
5、數據并行處理
1、Tensor張量
#Tensors類似于NumPy的ndarrays,同時Tensors可以使用GPU進行計算 #張量就是按照任意維排列的一堆數字的推廣 #其實標量,向量,矩陣它們三個也是張量,標量是零維的張量,向量是一維的張量,矩陣是二維的張量。 import torch x=torch.empty(5,3)#構造一個5x3矩陣,不初始化。 x1=torch.rand(5,3)#構造一個隨機初始化的矩陣 x2=torch.zeros(5,3,dtype=torch.long)#構造一個矩陣全為 0,而且數據類型是 long x3=torch.tensor([5,5,3])#構造一個張量,直接使用數據#創建一個tensor基于已經存在的tensor x4=x3.new_ones(5,3,dtype=torch.double) print(x4) x5=torch.randn_like(x4) print(x5)#獲取它的維度,torch.Size是一個元組,它支持左右的元組操作 print(x5.size())#操作 #加法:方式一 y=torch.rand(5,3) print(x+y) #加法,方式二 print(torch.add(x,y))#加法:提供一個輸出tensor作為參數 result=torch.empty(5,3) torch.add(x,y,out=result) print(result)#加法:in-place,adds x to y #注意,任何使張量發生變化的操作都有一個前綴,如x.copy(y),x.t_(),將會改變x y.add_(x) print(y)#可以使用標準的Numpy類似的索引操作,按行存儲 print(x[:,1])#改變大小:如果想改變一個tensor的大小或形狀,可以使用torch.view x=torch.randn(4,4) y=x.view(16) z=x.view(-1,8)#-1是從其他維度推斷出來的 print(x.size(),y.size(),z.size())#如果有一個元素的tensor,使用.item()來獲取這個value x=torch.randn(1) print(x) print(x.item()) print(x,x1,x2)2、自動微分
""" 1、torch.Tensor 是包的核心類。如果將其屬性?.requires_grad 設置為 True,則會開始跟蹤針對 tensor的所有操作 2、可以調用 .backward() 來自動計算所有梯度。該張量的梯度將累積到.grad 屬性中 3、要停止 tensor 歷史記錄的跟蹤,您可以調用 .detach(),它將其與計算歷史記錄分離,并防止將來的計算被跟蹤 4、要停止跟蹤歷史記錄(和使用內存),您還可以將代碼塊使用 with?torch.no_grad(): 包裝起來。在評估模型時,這是特別有用 5、還有一個類對于 autograd 實現非常重要那就是 Function。Tensor 和 Function 互相連接并構建一個非循環圖,它保存整個完整的計算過程的歷史信息 6、每個張量都有一個 .grad_fn 屬性保存著創建了張量的 Function 的引用 7、如果你想計算導數,你可以調用 Tensor.backward()。如果 Tensor 是標量(即它包含一個元素數據),則不需要指定任何參數backward() 8、如果它有更多元素,則需要指定一個gradient?參數來指定張量的形狀 """ import torch #創建一個張量,設置requires_grad=True來跟蹤與它相關的計算 x=torch.ones(2,2,requires_grad=True) print(x)#針對向量做一個操作 y=x+2 print(y) #y作為操作的結果被創建,所以它有grad_fn print(y.grad_fn)#針對y做更多的操作 z=y*y*3 out=z.mean() print(z,out)#.requires_grad_(...)會改變張量的requires_grad標記。輸入的標記默認是False,如果沒有提供相應的參數 a=torch.randn(2,2) a=((a*3)/(a-1)) print(a.requires_grad) a.requires_grad_(True) print(a.requires_grad) b=(a*a).sum() print(b.grad_fn)#梯度 #現在向后傳播,因為輸出包含一個標量,out.backward()等同于out.backward(torch.tensor(1.)) out.backward() #打印d(out)/dx print(x.grad)#看一個雅可比向量積的例子 x=torch.randn(3,requires_grad=True) y=x*2 while y.data.norm()<1000:#它對張量y中的每個元素進行平方,然后對它們求和,最后取平方根.這些操作計算所謂的L2規范.y=y*2 print(y)""" 現在在這種情況下,y 不再是一個標量。torch.autograd 不能夠直接計算整個雅可比,但是如果我 們只想要雅可比向量積,只需要簡單的傳遞向量給 backward 作為參數。 """ v=torch.tensor([0.1,1.0,0.0001],dtype=torch.float) y.backward(v) print(x.grad)#可以通過將代碼包裹在with torch.no_grad(),來停止對從跟蹤歷史中的.requires_grad=True的張量自動求導 print(x.requires_grad) print((x**2).requires_grad)with torch.no_grad():print((x**2).requires_grad)3、神經網絡
input為1通道32*32,卷積核為5*5,輸出6通道,另一個卷積為5*5,輸出16通道,兩個池化(下采樣)為2*2滑動窗口,三個全連接層
卷積,激活,池化,卷積,激活,池化,全連接,激活,全連接,激活,全連接
import torch import torch.nn as nn import torch.nn.functional as F """ 現在對于自動梯度(autograd)有一些了解,神經網絡是基于自動梯度 (autograd)來定義一些模型。 一個?nn.Module 包括層和一個方法?forward(input) 它會返回輸出(output)。 """ """ 一個典型的神經網絡訓練過程包括以下幾點: 1.定義一個包含可訓練參數的神經網絡 2.迭代整個輸入 3.通過神經網絡處理輸入 4.計算損失(loss) 5.反向傳播梯度到神經網絡的參數 6.更新網絡的參數,典型的用一個簡單的更新方法:weight?=?weight?-?learning_rate?*gradient """ class Net(nn.Module):def __init__(self):super(Net,self).__init__()self.conv1=nn.Conv2d(1,6,5)#5*5的卷積核,1為輸入通道,6為輸出通道self.conv2=nn.Conv2d(6,16,5)self.fc1=nn.Linear(16*5*5,120)#全連接層self.fc2=nn.Linear(120,84)self.fc3=nn.Linear(84,10)def forward(self, x):x=F.max_pool2d(F.relu(self.conv1(x)),(2,2))#池化,2*2的滑動窗口,下采樣,為了降維x=F.max_pool2d(F.relu(self.conv2(x)),2)x=x.view(-1,self.num_flat_features(x))x=F.relu(self.fc1(x))x=F.relu(self.fc2(x))x=self.fc3(x)return xdef num_flat_features(self,x):size=x.size()[1:]num_features=1for s in size:num_features*=sreturn num_featuresnet=Net() print(net) #一個模型可訓練的參數可以通過調用 net.parameters() 返回 params = list(net.parameters()) print(len(params)) print(params[0].size()) # conv1's .weight#讓我們嘗試隨機生成一個?32x32 的輸入。注意:期望的輸入維度是?32x32 。為了使用這個網絡在MNIST 數據及上,你需要把數據集中的圖片維度修改為?32x32 input = torch.randn(1, 1, 32, 32) out = net(input) print(input,input.size()) print(out)#把所有參數梯度緩存器置零,用隨機的梯度來反向傳播 net.zero_grad() out.backward(torch.randn(1,10))#損失函數 """ 一個損失函數需要一對輸入:模型輸出和目標,然后計算一個值來評估輸出距離目標有多遠。 有一些不同的損失函數在 nn 包中。一個簡單的損失函數就是?nn.MSELoss ,這計算了均方誤差 """ output=net(input) target=torch.randn(10) target=target.view(1,-1)#和輸出保持相同的形狀 criterion=nn.MSELoss() loss=criterion(output,target) print(loss)""" 當我們調用?loss.backward(),整個圖都會微分,而且所有的在圖中的requires_grad=True 的張量將會讓他們的?grad 張量累計梯度 """ print(loss.grad_fn) print(loss.grad_fn.next_functions[0][0])#Linear print(loss.grad_fn.next_functions[0][0].next_functions[0][0])#Relu#反向傳播 """ 為了實現反向傳播損失,我們所有需要做的事情僅僅是使用?loss.backward()。你需要清空現存的 梯度,要不然都將會和現存的梯度累計到一起。 現在我們調用?loss.backward() ,然后看一下 conv1 的偏置項在反向傳播之前和之后的變化 """ net.zero_grad()#所有的梯度清零 print('conv1.bias.grad before backward') print(net.conv1.bias.grad)loss.backward() print('conv1.bias.grad after backward') print(net.conv1.bias.grad)""" 現在我們看到了,如何使用損失函數。 唯一剩下的事情就是更新神經網絡的參數。 更新神經網絡參數: 最簡單的更新規則就是隨機梯度下降。 weight?=?weight?-?learning_rate?*?gradient """ learning_rate=0.01 for f in net.parameters():f.data.sub_(f.grad.data*learning_rate)""" 盡管如此,如果你是用神經網絡,你想使用不同的更新規則,類似于 SGD, Nesterov-SGD, Adam, RMSProp, 等。為了讓這可行,我們建立了一個小包:torch.optim 實現了所有的方法。使用它非常 的簡單 """ #創建優化器 optimizer=torch.optim.SGD(net.parameters(),lr=0.01) #訓練區域 optimizer.zero_grad() output=net(input) loss=criterion(output,target) loss.backward() optimizer.step()#權值更新4、pytorch圖像分類器
數據集
""" 現在你也許會想應該怎么處理數據? 通常來說,當你處理圖像,文本,語音或者視頻數據時,你可以使用標準 python 包將數據加載成 numpy 數組格式,然后將這個數組轉換成 torch.*Tensor 對于圖像,可以用 Pillow,OpenCV 對于語音,可以用 scipy,librosa 對于文本,可以直接用 Python 或 Cython 基礎數據加載模塊,或者用 NL TK 和 SpaCy 特別是對于視覺,我們已經創建了一個叫做 totchvision 的包,該包含有支持加載類似Imagenet, CIFAR10,MNIST 等公共數據集的數據加載模塊 torchvision.datasets 和支持加載圖像數據數據轉 換模塊 torch.utils.data.DataLoader。 這提供了極大的便利,并且避免了編寫“樣板代碼”。 對于本教程,我們將使用CIFAR10數據集,它包含十個類別:‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’。CIFAR-10 中的圖像尺寸為3*32*32,也就是RGB的3層顏色 通道,每層通道內的尺寸為32*32。 """""" 訓練一個圖像分類器 我們將按次序的做如下幾步: 1、使用torchvision加載并且歸一化CIFAR10的訓練和測試數據集 2、定義一個卷積神經網絡 3、定義一個損失函數 4、在訓練樣本數據上訓練網絡 5、在測試樣本數據上測試網絡 """ import torch import torchvision import torchvision.transforms as transformsimport matplotlib.pyplot as plt import numpy as npimport torch.nn as nn import torch.nn.functional as Fimport torch.optim as optim """ 加載并歸一化 CIFAR10 使用 torchvision ,用它來加載 CIFAR10 數據非常簡單 torchvision 數據集的輸出是范圍在[0,1]之間的 PILImage,我們將他們轉換成歸一化范圍為[-1,1]之 間的張量 Tensors。 """ transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))]) trainset=torchvision.datasets.CIFAR10(root='data',train=True,download=True,transform=transform) trainloader=torch.utils.data.DataLoader(trainset,batch_size=4,shuffle=True,num_workers=2) testset=torchvision.datasets.CIFAR10(root='data',train=False,download=True,transform=transform) testloader=torch.utils.data.DataLoader(testset,batch_size=4,shuffle=False,num_workers=2) classes=('plane','car','bird','cat','deer','dog','frog','horse','ship','truck')""" 定義一個卷積神經網絡 在這之前先 從神經網絡章節 復制神經網絡,并修改它為3通道的圖片(在此 之前它被定義為1通道) """class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1=nn.Conv2d(3,6,5)self.pool=nn.MaxPool2d(2,2)self.conv2=nn.Conv2d(6,16,5)self.fc1=nn.Linear(16*5*5,120)self.fc2=nn.Linear(120,84)self.fc3=nn.Linear(84,10)def forward(self, x):x=self.pool(F.relu(self.conv1(x)))x=self.pool(F.relu(self.conv2(x)))x=x.view(-1,16*5*5)x=F.relu(self.fc1(x))x=F.relu(self.fc2(x))x=self.fc3(x)return xnet=Net()""" 我們怎么在GPU上跑這些神經網絡? 在GPU上訓練 就像你怎么把一個張量轉移到GPU上一樣,你要將神經網絡轉到GPU上。 如果CUDA 可以用,讓我們首先定義下我們的設備為第一個可見的cuda設備。 """ device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print(device)""" 本節剩余部分都會假定設備就是臺CUDA設備。 接著這些方法會遞歸地遍歷所有模塊,并將它們的參數和緩沖器轉換為CUDA張量。 """ net.to(device)""" 定義一個損失函數和優化器 讓我們使用分類交叉熵Cross-Entropy 作損失函數,動量SGD做優化 器。 """criterion=nn.CrossEntropyLoss() optimizer=optim.SGD(net.parameters(),lr=0.001,momentum=0.9)""" 訓練網絡 這里事情開始變得有趣,我們只需要在數據迭代器上循環傳給網絡和優化器 輸入就可 以。 """ #--------------訓練開始-------------- if __name__=='__main__':print('Start Training')for epoch in range(2):#對數據集進行多次迭代running_loss=0.0#獲取索引列表for i,data in enumerate(trainloader,0):#enumerate is useful for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2])#得到輸入inputs,labels=datainputs,labels=inputs.to(device),labels.to(device)#將輸入數據放到gpu上,如果放在cpu則刪掉這條語句#參數梯度清零optimizer.zero_grad()#前向+反向+梯度outputs=net(inputs)loss=criterion(outputs,labels)loss.backward()optimizer.step()#打印統計數據running_loss+=loss.item()if i%2000==1999:#每2000小批打印一次print('[%d,%5d] loss:%.3f'%(epoch+1,i+1,running_loss/2000))running_loss=0.0print('Finished Training') #----------------訓練結束--------------------# 展示其中的一些訓練圖片 def imshow(img):img = img / 2 + 0.5npimg = img.cpu().numpy()#這里把img放到了gpu上,如果使用img.numpy()會報錯,所以要把img.cpu()才不報錯plt.imshow(np.transpose(npimg, (1, 2, 0)))plt.show()if __name__ == '__main__':# 得到一些隨機的訓練圖片dataiter = iter(trainloader)images, labels = dataiter.next()images,labels=images.to(device),labels.to(device)#將輸入數據放到gpu上,如果放在cpu則刪掉這條語句# 展示圖片imshow(torchvision.utils.make_grid(images))# 打印標簽print(' '.join('%5s' % classes[labels[j]] for j in range(4)))"""在測試集上測試網絡 我們已經通過訓練數據集對網絡進行了2次訓練,但是我們需要檢查網絡是否已經學到了東西。我們將用神經網絡的輸出作為預測的類標來檢查網絡的預測性能,用樣本的真實類標來校對。如果預測是正確的,我們將樣本添加到正確預測的列表里"""outputs=net(images)print(outputs)"""輸出是預測與十個類的近似程度,與某一個類的近似程度越高,網絡就越認為圖像是屬于這一類別。所以讓我們打印其中最相似類別類標"""_,predicted=torch.max(outputs,1)print('Predicted:',' '.join('%5s' % classes[predicted[j]] for j in range(4)))#結果看起開非常好,讓我們看看網絡在整個數據集上的表現correct=0total=0with torch.no_grad():for data in testloader:images,labels=dataimages,labels=images.to(device),labels.to(device)#將輸入數據放到gpu上,如果放在cpu則刪掉這條語句outputs=net(images)_,predicted=torch.max(outputs.data,1)total+=labels.size(0)correct+=(predicted==labels).sum().item()print('Accuracy of the network on the 10000 test images:%d %%'%(100*correct/total))#這看起來比隨機預測要好,隨機預測的準確率為10%(隨機預測出為10類中的哪一類)??磥砭W絡學到了東西class_correct=list(0.for i in range(10))class_total=list(0.for i in range(10))with torch.no_grad():for data in testloader:images,labels=dataimages,labels=images.to(device),labels.to(device)#將輸入數據放到gpu上,如果放在cpu則刪掉這條語句outputs=net(images)_,predicted=torch.max(outputs,1)c=(predicted==labels).squeeze()for i in range(4):label=labels[i]class_correct[label]+=c[i].item()class_total[label]+=1for i in range(10):print('Accuracy of %5s : %2d %%'%(classes[i],100*class_correct[i]/class_total[i]))5、數據并行處理
""" 在這個教程中,我們將學習如何用 DataParallel 來使用多 GPU。 通過 PyTorch 使用多個 GPU 非常 簡單。你可以將模型放在一個 GPU: device = torch.device("cuda:0") model.to(device) 然后,你可以復制所有的張量到 GPU: mytensor = my_tensor.to(device) 請注意,只是調用 my_tensor.to(device) 返回一個 my_tensor 新的復制在GPU上,而不是重寫 my_tensor。你需要分配給他一個新的張量并且在 GPU 上使用這個張量。 """""" 在多 GPU 中執行前饋,后饋操作是非常自然的。盡管如此,PyTorch 默認只會使用一個 GPU。通 過使用 DataParallel 讓你的模型并行運行,你可以很容易的在多 GPU 上運行你的操作。 model = nn.DataParallel(model) """ import torch import torch.nn as nn from torch.utils.data import Dataset,DataLoader#參數 input_size=5 output_size=2 batch_size=30 data_size=100device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")#生成一個實驗數據,只需要實現getitem class RandomDataset(Dataset):def __init__(self,size,length):self.len=lengthself.data=torch.randn(length,size)#100*5def __getitem__(self, index):return self.data[index]def __len__(self):return self.lenrand_loader=DataLoader(dataset=RandomDataset(input_size,data_size),batch_size=batch_size,shuffle=True)""" 簡單模型 為了做一個小 demo,我們的模型只是獲得一個輸入,執行一個線性操作,然后給一個輸出。盡管 如此,你可以使用?DataParallel? ?在任何模型(CNN, RNN, Capsule Net 等等.) 我們放置了一個輸出聲明在模型中來檢測輸出和輸入張量的大小。請注意在 batch rank 0 中的輸 出。 """ class Model(nn.Module):def __init__(self,input_size,output_size):super(Model, self).__init__()self.fc=nn.Linear(input_size,output_size)def forward(self, input):output=self.fc(input)print("\tIn Model:input size",input.size(),"output size",output.size())return output """ 創建模型并且數據并行處理 這是整個教程的核心。首先我們需要一個模型的實例,然后驗證我們是否有多個 GPU。如果我們 有多個 GPU,我們可以用nn.DataParallel來包裹我們的模型。然后我們使用 model.to(device) 把模型放到多 GPU 中。 """ model=Model(input_size,output_size) if torch.cuda.device_count()>1:print("Let's use",torch.cuda.device_count(),"GPUs")model=nn.DataParallel(model)#放到多個GPU上 model.to(device)#運行模型:現在我們可以看到輸入和輸出張量的大小 for data in rand_loader:input = data.to(device)output = model(input)print("Outside:input size", input.size(), "output_size", output.size())""" 總結: 數據并行自動拆分了你的數據并且將任務單發送到多個 GPU 上。當每一個模型都完成自己的任務 之后,DataParallel 收集并且合并這些結果,然后再返回給你。 """豬豬&&憨憨
總結
以上是生活随笔為你收集整理的第一学:pytorch入门60min的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: #ifndef的详细意思
- 下一篇: 2018最新Nginx从入门到精通5阶段