Pytorch tutorial代碼

Tensors

#Tensors

#Tensors和numpy中的ndarrays較為相似,因此Tensor也能夠使用GPU來(lái)加速運(yùn)算。

from__future__importprint_function

importtorch

x = torch.Tensor(5,3)#構(gòu)造一個(gè)未初始化的5*3的矩陣

x = torch.rand(5,3)#構(gòu)造一個(gè)隨機(jī)初始化的矩陣

x#此處在notebook中輸出x的值來(lái)查看具體的x內(nèi)容

x.size()

#NOTE: torch.Size事實(shí)上是一個(gè)tuple,所以其支持相關(guān)的操作*

y = torch.rand(5,3)

#此處 將兩個(gè)同形矩陣相加有兩種語(yǔ)法結(jié)構(gòu)

x + y#語(yǔ)法一

torch.add(x,y)#語(yǔ)法二

#另外輸出tensor也有兩種寫(xiě)法

result = torch.Tensor(5,3)#語(yǔ)法一

torch.add(x,y,out=result)#語(yǔ)法二

y.add_(x)#將y與x相加

#特別注明:任何可以改變tensor內(nèi)容的操作都會(huì)在方法名后加一個(gè)下劃線(xiàn)'_'

#例如:x.copy_(y), x.t_(),這倆都會(huì)改變x的值。

#另外python中的切片操作也是資次的。

x[:,1]#這一操作會(huì)輸出x矩陣的第二列的所有值

Numpy橋


Numpy橋

將Torch的Tensor和numpy的array相互轉(zhuǎn)換簡(jiǎn)直就是灑灑水啦。注意Torch的Tensor和numpy的array會(huì)共享他們的存儲(chǔ)空間,修改一個(gè)會(huì)導(dǎo)致另外的一個(gè)也被修改。

# 此處演示tensor和numpy數(shù)據(jù)結(jié)構(gòu)的相互轉(zhuǎn)換

a = torch.ones(5)

b = a.numpy()

# 此處演示當(dāng)修改numpy數(shù)組之后,與之相關(guān)聯(lián)的tensor也會(huì)相應(yīng)的被修改

a.add_(1)

print(a)

print(b)

# 將numpy的Array轉(zhuǎn)換為torch的Tensor

import numpy as np

a = np.ones(5)

b = torch.from_numpy(a)

np.add(a, 1, out=a)

print(a)

print(b)

# 另外除了CharTensor之外,所有的tensor都可以在CPU運(yùn)算和GPU預(yù)算之間相互轉(zhuǎn)換

# 使用CUDA函數(shù)來(lái)將Tensor移動(dòng)到GPU上

# 當(dāng)CUDA可用時(shí)會(huì)進(jìn)行GPU的運(yùn)算

if torch.cuda.is_available():

??????? x = x.cuda()

??????? y = y.cuda()

??????? x + y

Autograd: 自動(dòng)求導(dǎo)

autograd 包提供Tensor所有操作的自動(dòng)求導(dǎo)方法。

這是一個(gè)運(yùn)行時(shí)定義的框架,這意味著你的反向傳播是根據(jù)你代碼運(yùn)行的方式來(lái)定義的,因此每一輪迭代都可以各不相同。

以這些例子來(lái)講,讓我們用更簡(jiǎn)單的術(shù)語(yǔ)來(lái)看看這些特性。

autograd.Variable 這是這個(gè)包中最核心的類(lèi)。 它包裝了一個(gè)Tensor,并且?guī)缀踔С炙械亩x在其上的操作。一旦完成了你的運(yùn)算,你可以調(diào)用 .backward()來(lái)自動(dòng)計(jì)算出所有的梯度。

你可以通過(guò)屬性 .data 來(lái)訪問(wèn)原始的tensor,而關(guān)于這一Variable的梯度則集中于 .grad 屬性中。

還有一個(gè)在自動(dòng)求導(dǎo)中非常重要的類(lèi) Function。

Variable

和 Function 二者相互聯(lián)系并且構(gòu)建了一個(gè)描述整個(gè)運(yùn)算過(guò)程的無(wú)環(huán)圖。每個(gè)Variable擁有一個(gè) .creator

屬性,其引用了一個(gè)創(chuàng)建Variable的 Function。(除了用戶(hù)創(chuàng)建的Variable其 creator 部分是 None)。

如果你想要進(jìn)行求導(dǎo)計(jì)算,你可以在Variable上調(diào)用.backward()。

如果Variable是一個(gè)標(biāo)量(例如它包含一個(gè)單元素?cái)?shù)據(jù)),你無(wú)需對(duì)backward()指定任何參數(shù),然而如果它有更多的元素,你需要指定一個(gè)和tensor的形狀想匹配的grad_output參數(shù)。

from torch.autograd import Variable

x = Variable(torch.ones(2, 2), requires_grad = True)

y = x + 2

y.creator

# y 是作為一個(gè)操作的結(jié)果創(chuàng)建的因此y有一個(gè)creator

z = y * y * 3

out = z.mean()

# 現(xiàn)在我們來(lái)使用反向傳播

out.backward()

# out.backward()和操作out.backward(torch.Tensor([1.0]))是等價(jià)的

# 在此處輸出 d(out)/dx

x.grad

神經(jīng)網(wǎng)絡(luò)

使用 torch.nn 包可以進(jìn)行神經(jīng)網(wǎng)絡(luò)的構(gòu)建。

現(xiàn)在你對(duì)autograd有了初步的了解,而nn建立在autograd的基礎(chǔ)上來(lái)進(jìn)行模型的定義和微分。

nn.Module中包含著神經(jīng)網(wǎng)絡(luò)的層,同時(shí)forward(input)方法能夠?qū)utput進(jìn)行返回。

舉個(gè)例子,來(lái)看一下這個(gè)數(shù)字圖像分類(lèi)的神經(jīng)網(wǎng)絡(luò)。

這是一個(gè)簡(jiǎn)單的前饋神經(jīng)網(wǎng)絡(luò)。 從前面獲取到輸入的結(jié)果,從一層傳遞到另一層,最后輸出最后結(jié)果。

一個(gè)典型的神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過(guò)程是這樣的:

定義一個(gè)有著可學(xué)習(xí)的參數(shù)(或者權(quán)重)的神經(jīng)網(wǎng)絡(luò)

對(duì)著一個(gè)輸入的數(shù)據(jù)集進(jìn)行迭代:

??? 用神經(jīng)網(wǎng)絡(luò)對(duì)輸入進(jìn)行處理

??? 計(jì)算代價(jià)值 (對(duì)輸出值的修正到底有多少)

??? 將梯度傳播回神經(jīng)網(wǎng)絡(luò)的參數(shù)中

??? 更新網(wǎng)絡(luò)中的權(quán)重

?????????? 通常使用簡(jiǎn)單的更新規(guī)則: weight = weight + learning_rate*gradient

讓我們來(lái)定義一個(gè)神經(jīng)網(wǎng)絡(luò):

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(1, 6, 5) # 1 input image channel, 6 output channels, 5x5 square convolution kernel

? ? ? ? self.conv2 = nn.Conv2d(6, 16, 5)

? ?? ?? self.fc1? = nn.Linear(16*5*5, 120) # an affine operation: y = Wx + b

? ?? ?? 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)) # Max pooling over a (2, 2) window

??????? x = F.max_pool2d(F.relu(self.conv2(x)), 2) # If the size is a square you can only specify a single number

??????? 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 x

??? def num_flat_features(self, x):

??????? size = x.size()[1:] # all dimensions except the batch dimension

??????? num_features = 1

??????? for s in size:

??????????? num_features *= s

??????? return num_features

net = Net()

net

'''神經(jīng)網(wǎng)絡(luò)的輸出結(jié)果是這樣的

Net (

(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))

(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))

(fc1): Linear (400 -> 120)

(fc2): Linear (120 -> 84)

(fc3): Linear (84 -> 10)

)

'''

僅僅需要定義一個(gè)forward函數(shù)就可以了,backward會(huì)自動(dòng)地生成。

你可以在forward函數(shù)中使用所有的Tensor中的操作。

模型中可學(xué)習(xí)的參數(shù)會(huì)由net.parameters()返回。


params = list(net.parameters())

print(len(params))

print(params[0].size()) # conv1's .weight

input = Variable(torch.randn(1, 1, 32, 32))

out = net(input)

'''out 的輸出結(jié)果如下

Variable containing:

-0.0158 -0.0682 -0.1239 -0.0136 -0.0645? 0.0107 -0.0230 -0.0085? 0.1172 -0.0393

[torch.FloatTensor of size 1x10]

'''

net.zero_grad() # 對(duì)所有的參數(shù)的梯度緩沖區(qū)進(jìn)行歸零

out.backward(torch.randn(1, 10)) # 使用隨機(jī)的梯度進(jìn)行反向傳播

注意: torch.nn 只接受小批量的數(shù)據(jù)

整個(gè)torch.nn包只接受那種小批量樣本的數(shù)據(jù),而非單個(gè)樣本。 例如,nn.Conv2d能夠結(jié)構(gòu)一個(gè)四維的TensornSamples x nChannels x Height x Width。

如果你拿的是單個(gè)樣本,使用input.unsqueeze(0)來(lái)加一個(gè)假維度就可以了。


復(fù)習(xí)一下前面我們學(xué)到的:

1. torch.Tensor - 一個(gè)多維數(shù)組

2. autograd.Variable - 改變Tensor并且記錄下來(lái)操作的歷史記錄。和Tensor擁有相同的API,以及backward()的一些API。同時(shí)包含著和張量相關(guān)的梯度。

3. nn.Module - 神經(jīng)網(wǎng)絡(luò)模塊。便捷的數(shù)據(jù)封裝,能夠?qū)⑦\(yùn)算移往GPU,還包括一些輸入輸出的東西。

4. nn.Parameter - 一種變量,當(dāng)將任何值賦予Module時(shí)自動(dòng)注冊(cè)為一個(gè)參數(shù)。

5. autograd.Function - 實(shí)現(xiàn)了使用自動(dòng)求導(dǎo)方法的前饋和后饋的定義。每個(gè)Variable的操作都會(huì)生成至少一個(gè)獨(dú)立的Function節(jié)點(diǎn),與生成了Variable的函數(shù)相連之后記錄下操作歷史。

到現(xiàn)在我們已經(jīng)明白的部分:

1.定義了一個(gè)神經(jīng)網(wǎng)絡(luò)。

2.處理了輸入以及實(shí)現(xiàn)了反饋。

仍然沒(méi)整的:

1.計(jì)算代價(jià)。

2.更新網(wǎng)絡(luò)中的權(quán)重。

一個(gè)代價(jià)函數(shù)接受(輸出,目標(biāo))對(duì)兒的輸入,并計(jì)算估計(jì)出輸出與目標(biāo)之間的差距。


代價(jià)函數(shù)

一個(gè)簡(jiǎn)單的代價(jià)函數(shù):nn.MSELoss計(jì)算輸入和目標(biāo)之間的均方誤差。

舉個(gè)例子:

output = net(input)

target = Variable(torch.range(1, 10))? # a dummy target, for example

criterion = nn.MSELoss()

loss = criterion(output, target)

'''loss的值如下

Variable containing:

38.5849

[torch.FloatTensor of size 1]

'''

現(xiàn)在,如果你跟隨loss從后往前看,使用.creator屬性你可以看到這樣的一個(gè)計(jì)算流程圖:

input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d? ? ? ? -> view -> linear -> relu -> linear -> relu -> linear? ? ? -> MSELoss? ? ? -> loss

因此當(dāng)我們調(diào)用loss.backward()時(shí)整個(gè)圖通過(guò)代價(jià)來(lái)進(jìn)行區(qū)分,圖中所有的變量都會(huì)以.grad來(lái)累積梯度。


# For illustration, let us follow a few steps backward

print(loss.creator)#MSELoss

print(loss.creator.previous_functions[0][0])#Linear

print(loss.creator.previous_functions[0][0].previous_functions[0][0])# ReLU

# 現(xiàn)在我們應(yīng)當(dāng)調(diào)用loss.backward(), 之后來(lái)看看 conv1's在進(jìn)行反饋之后的偏置梯度如何

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)

''' 這些步驟的輸出結(jié)果如下

conv1.bias.grad before backward

Variable containing:

0

0

0

0

0

0

[torch.FloatTensor of size 6]

conv1.bias.grad after backward

Variable containing:

0.0346

-0.0141

0.0544

-0.1224

-0.1677

0.0908

[torch.FloatTensor of size 6]

'''

現(xiàn)在我們已經(jīng)了解如何使用代價(jià)函數(shù)了。

閱讀材料:

神經(jīng)網(wǎng)絡(luò)包中包含著諸多用于神經(jīng)網(wǎng)絡(luò)的模塊和代價(jià)函數(shù),帶有文檔的完整清單在這里:torch.nn - PyTorch 0.1.9 documentation

更新網(wǎng)絡(luò)的權(quán)重

最簡(jiǎn)單的更新的規(guī)則是隨機(jī)梯度下降法(SGD):

weight = weight - learning_rate * gradient

我們可以用簡(jiǎn)單的python來(lái)表示:

learning_rate = 0.01

????? for f in net.parameters():

???????????? f.data.sub_(f.grad.data * learning_rate)


然而在你使用神經(jīng)網(wǎng)絡(luò)的時(shí)候你想要使用不同種類(lèi)的方法諸如:SGD, Nesterov-SGD, Adam, RMSProp, etc.

我們構(gòu)建了一個(gè)小的包torch.optim來(lái)實(shí)現(xiàn)這個(gè)功能,其中包含著所有的這些方法。 用起來(lái)也非常簡(jiǎn)單:

import torch.optim as optim

# create your optimizer

optimizer = optim.SGD(net.parameters(), lr = 0.01)

# in your training loop:

optimizer.zero_grad() # zero the gradient buffers

output = net(input)

loss = criterion(output, target)

loss.backward()

optimizer.step() # Does the update

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,214評(píng)論 3 426
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 177,781評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,588評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,315評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,699評(píng)論 1 327
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,882評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,441評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,189評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,388評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,613評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,023評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,310評(píng)論 1 293
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,112評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,334評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容