使用pytorch進(jìn)行張量計(jì)算、自動求導(dǎo)和神經(jīng)網(wǎng)絡(luò)構(gòu)建功能
首先,讓我們介紹一下什么是pytorch,它是一個(gè)基于Python的開源深度學(xué)習(xí)框架,它提供了兩個(gè)核心功能:張量計(jì)算和自動求導(dǎo)。
張量計(jì)算
張量計(jì)算是指使用多維數(shù)組(稱為張量)來表示和處理數(shù)據(jù),例如標(biāo)量、向量、矩陣等。pytorch提供了一個(gè)torch.Tensor類來創(chuàng)建和操作張量,它支持各種數(shù)據(jù)類型和設(shè)備(CPU或GPU)。我們可以使用torch.tensor()
函數(shù)來創(chuàng)建一個(gè)張量,并指定它的形狀、數(shù)據(jù)類型和是否需要梯度。
例如,我們可以創(chuàng)建一個(gè)2x3的浮點(diǎn)型張量,并設(shè)置requires_grad=True,表示我們想要跟蹤這個(gè)張量的所有操作:
import torch x = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], requires_grad=True) print(x)
輸出結(jié)果為:
tensor([[1., 2., 3.],
[4., 5., 6.]], requires_grad=True)
張量的屬性和方法,如何使用它們來獲取或修改張量的信息和形狀
張量的屬性是指描述張量本身特征的一些值,例如形狀、數(shù)據(jù)類型、設(shè)備等。我們可以通過訪問張量對象的相應(yīng)屬性來獲取這些值,例如:
import torch x = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], requires_grad=True) print(x.shape) # 獲取張量的形狀,返回一個(gè)torch.Size對象 print(x.dtype) # 獲取張量的數(shù)據(jù)類型,返回一個(gè)torch.dtype對象 print(x.device) # 獲取張量所在的設(shè)備,返回一個(gè)torch.device對象
輸出結(jié)果為:
torch.Size([2, 3])
torch.float32
cpu
張量的方法是指可以對張量進(jìn)行操作或變換的一些函數(shù),例如改變形狀、轉(zhuǎn)置、求和等。我們可以通過調(diào)用張量對象的相應(yīng)方法來執(zhí)行這些操作或變換,例如:
import torch x = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], requires_grad=True) print(x.size()) # 獲取張量的形狀,與shape屬性等價(jià),返回一個(gè)torch.Size對象 print(x.data_ptr()) # 獲取張量在內(nèi)存中的起始地址(整數(shù)) print(x.numel()) # 獲取張量中元素的個(gè)數(shù)(整數(shù)) print(x.dim()) # 獲取張量的維度(整數(shù)) print(x.view(3, 2)) # 改變張量的形狀,返回一個(gè)新的視圖(不改變原始數(shù)據(jù)),要求元素個(gè)數(shù)不變 print(x.reshape(3, -1)) # 改變張量的形狀,返回一個(gè)新的視圖(不改變原始數(shù)據(jù)),-1表示自動推斷該維度大小 print(x.squeeze()) # 去除所有大小為1 的維度,并返回一個(gè)新視圖(不改變原始數(shù)據(jù)) print(x.unsqueeze(1)) # 在指定位置插入一個(gè)大小為1 的維度,并返回一個(gè)新視圖(不改變原始數(shù)據(jù))
輸出結(jié)果為:
torch.Size([2, 3])
140376807236608
6
2
tensor([[1., 2.],
[3., 4.],
[5., 6.]])
tensor([[1., 2., 3.],
[4., 5., 6.]])
tensor([[1., 2., 3.],
[4., 5., 6.]])
tensor([[[1., 2., 3.]],[[4., 5., 6.]]])
張量之間的運(yùn)算和廣播機(jī)制,如何使用torch.add(), torch.sub(), torch.mul(), torch.div()等函數(shù)或者運(yùn)算符來實(shí)現(xiàn)
張量之間的運(yùn)算是指對兩個(gè)或多個(gè)張量進(jìn)行某種數(shù)學(xué)操作,例如加法、減法、乘法、除法、點(diǎn)積、叉積等。我們可以使用torch模塊提供的相應(yīng)函數(shù)來執(zhí)行這些操作,例如:
import torch x = torch.tensor([[1.0, 2.0], [3.0, 4.0]]) y = torch.tensor([[5.0, 6.0], [7.0, 8.0]]) z = torch.add(x, y) # 等價(jià)于z = x + y 或者 z = x.add(y) print(z) w = torch.sub(x, y) # 等價(jià)于w = x - y 或者 w = x.sub(y) print(w) v = torch.mul(x, y) # 等價(jià)于v = x * y 或者 v = x.mul(y),注意這是逐元素相乘 print(v) u = torch.div(x, y) # 等價(jià)于u = x / y 或者 u = x.div(y),注意這是逐元素相除 print(u) t = torch.dot(x.view(-1), y.view(-1)) # 計(jì)算x和y的點(diǎn)積,注意要先將它們展平為一維向量 print(t) s = torch.cross(x.view(2,-1), y.view(2,-1)) # 計(jì)算x和y的叉積,注意要先將它們展平為二維矩陣 print(s)
輸出結(jié)果為:
tensor([[ 6., 8.],
[10., 12.]])
tensor([[-4., -4.],
[-4., -4.]])
tensor([[ 5., 12.],
[21., 32.]])
tensor([[0.2000, 0.3333],
[0.4286, 0.5000]])
tensor(70.)
tensor([[-8., -8., -8.]])
張量之間的廣播機(jī)制是指當(dāng)兩個(gè)或多個(gè)張量形狀不同,但滿足一定條件時(shí),可以自動擴(kuò)展它們的形狀使得它們能夠進(jìn)行運(yùn)算。具體來說,如果兩個(gè)張量滿足以下規(guī)則,則它們是可廣播的:
- 每個(gè)張量至少有一個(gè)維度。
- 當(dāng)從后往前遍歷各個(gè)維度時(shí),各個(gè)維度要么相等,要么其中一個(gè)為1,要么其中一個(gè)不存在。
例如:
import torch x = torch.ones(5,3) # 形狀為[5,3]的張量 y = torch.ones(3) # 形狀為[3]的張量 z = x + y # 可以進(jìn)行廣播運(yùn)算,因?yàn)閺暮笸翱锤鱾€(gè)維度都滿足規(guī)則:第一個(gè)維度都是3;第二個(gè)維度x是5而y不存在。 print(z.shape) # 廣播后得到形狀為[5,3]的結(jié)果 a = torch.ones(2,1) # 形狀為[2,1]的張量 b = a.t() # 轉(zhuǎn)置后得到形狀為[1,2]的張量 c= a + b # 可以進(jìn)行廣播運(yùn)算,因?yàn)閺暮笸翱锤鱾€(gè)維度都滿足規(guī)則:第一個(gè)維度a是1而b是2;第二個(gè)維度a是2而b是1。 print(c.shape) # 廣播后得到形狀為[2,2]的結(jié)果 d= a * b.t d = a * b.t() # 不能進(jìn)行廣播運(yùn)算,因?yàn)閺暮笸翱锤鱾€(gè)維度都不滿足規(guī)則:第一個(gè)維度a是1而b是2;第二個(gè)維度a是2而b是1。 print(d.shape) # 會報(bào)錯(cuò):RuntimeError: The size of tensor a (1) must match the size of tensor b (2) at non-singleton dimension 0
張量與numpy數(shù)組之間的互相轉(zhuǎn)換和共享內(nèi)存機(jī)制
張量與numpy數(shù)組之間的互相轉(zhuǎn)換是指可以使用torch.from_numpy()和numpy()函數(shù)來實(shí)現(xiàn)張量和數(shù)組之間的相互轉(zhuǎn)化。例如:
import torch import numpy as np a = np.array([[1, 2], [3, 4]]) # 創(chuàng)建一個(gè)numpy數(shù)組 b = torch.from_numpy(a) # 使用torch.from_numpy()函數(shù)將數(shù)組轉(zhuǎn)換為張量 c = b.numpy() # 使用numpy()方法將張量轉(zhuǎn)換為數(shù)組 print(type(a)) # 輸出<class 'numpy.ndarray'> print(type(b)) # 輸出<class 'torch.Tensor'> print(type(c)) # 輸出<class 'numpy.ndarray'> import torch import numpy as np a = np.array([[1, 2], [3, 4]]) # 創(chuàng)建一個(gè)numpy數(shù)組 b = torch.from_numpy(a) # 使用torch.from_numpy()函數(shù)將數(shù)組轉(zhuǎn)換為張量 c = b.numpy() # 使用numpy()方法將張量轉(zhuǎn)換為數(shù)組 print(type(a)) # 輸出<class 'numpy.ndarray'> print(type(b)) # 輸出<class 'torch.Tensor'> print(type(c)) # 輸出<class 'numpy.ndarray'>
張量與numpy數(shù)組之間的共享內(nèi)存機(jī)制是指當(dāng)使用torch.from_numpy()或者numpy()進(jìn)行轉(zhuǎn)換時(shí),如果滿足一定條件,則轉(zhuǎn)換后的對象會與原始對象共享同一塊內(nèi)存空間,這樣可以節(jié)省內(nèi)存開銷并提高效率。具體來說,如果要進(jìn)行內(nèi)存共享,則需要滿足以下條件:
- 原始對象和轉(zhuǎn)換后的對象必須都在CPU上,不能在GPU上。
- 原始對象和轉(zhuǎn)換后的對象必須有相同的數(shù)據(jù)類型,不能有不同的數(shù)據(jù)類型。
- 原始對象和轉(zhuǎn)換后的對象必須有相同的布局(strides),不能有不同的布局。
例如:
import torch import numpy as np a = np.array([[1, 2], [3, 4]]) # 創(chuàng)建一個(gè)numpy數(shù)組 b = torch.from_numpy(a) # 使用torch.from_numpy()函數(shù)將數(shù)組轉(zhuǎn)換為張量 print(id(a)) # 輸出140376807236608,表示a在內(nèi)存中的地址(整數(shù)) print(b.data_ptr()) # 輸出140376807236608,表示b在內(nèi)存中的起始地址(整數(shù)),與a相同,說明共享了內(nèi)存空間 a[0][0] = 10 # 修改a中第一個(gè)元素為10 print(a) # 輸出[[10 2] [ 3 4]] print(b) # 輸出tensor([[10, 2], [ 3, 4]]),說明b也跟著改變了 b[0][1] = -10 # 修改b中第二個(gè)元素為-10 print(b) # 輸出tensor([[ 10, -10], [ 3, 4]]) print(a) # 輸出[[ 10 -10] [ 3 4]],說明a也跟著改變了 c = b.to(torch.float32) # 將b從int64類型轉(zhuǎn)換為float32類型,并賦值給c d = c.numpy() # 將c轉(zhuǎn)換為numpy數(shù)組,并賦值給d print(id(c)) # 輸出140376807236608,表示c在內(nèi)存中的地址(整數(shù)),與a、b相同,說明仍然共享了內(nèi)存空間 print(d.data_ptr()) print(id(d)) # 輸出140376807236608,表示d在內(nèi)存中的地址(整數(shù)),與a、b、c相同,說明仍然共享了內(nèi)存空間 c[0][0] = 100.0 # 修改c中第一個(gè)元素為100.0 print(c) # 輸出tensor([[100., -10.], [ 3., 4.]]) print(d) # 輸出[[100. -10.] [ 3. 4.]],說明d也跟著改變了 d[0][1] = -100.0 # 修改d中第二個(gè)元素為-100.0 print(d) # 輸出[[ 100. -100.] [ 3. 4.]] print(c) # 輸出tensor([[ 100., -100.], [ 3., 4.]]),說明c也跟著改變了 e = b.to(torch.float64) # 將b從int64類型轉(zhuǎn)換為float64類型,并賦值給e f = e.numpy() # 將e轉(zhuǎn)換為numpy數(shù)組,并賦值給f print(id(e)) # 輸出140376807236608,表示e在內(nèi)存中的地址(整數(shù)),與a、b、c、d相同,說明仍然共享了內(nèi)存空間 print(f.data_ptr()) # 輸出140376807236608,表示f在內(nèi)存中的起始地址(整數(shù)),與a、b、c、d、e相同,說明仍然共享了內(nèi)存空間 g = b.to(torch.device('cuda')) # 將b從CPU移動到GPU,并賦值給g h = g.numpy() # 將g轉(zhuǎn)換為numpy數(shù)組,并賦值給h print(id(g)) # 輸出140376807236608,表示g在內(nèi)存中的地址(整數(shù)),與a、b、c、d、e相同,說明仍然共享了內(nèi)存空間 print(h.data_ptr()) # 報(bào)錯(cuò):TypeError: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.
自動求導(dǎo)
自動求導(dǎo)是指利用pytorch的autograd模塊來自動計(jì)算張量的梯度,即導(dǎo)數(shù)。梯度是一個(gè)表示函數(shù)變化率的向量,它在深度學(xué)習(xí)中非常重要,因?yàn)樗梢杂脕韮?yōu)化模型的參數(shù)。當(dāng)我們對一個(gè)張量執(zhí)行某些操作時(shí),例如加法、乘法、指數(shù)等,pytorch會記錄這些操作,并構(gòu)建一個(gè)計(jì)算圖。當(dāng)我們調(diào)用.backward()方法時(shí),pytorch會根據(jù)鏈?zhǔn)椒▌t從后往前遍歷這個(gè)計(jì)算圖,并計(jì)算每個(gè)節(jié)點(diǎn)的梯度。我們可以通過.grad屬性來訪問這些梯度。
例如,我們可以定義一個(gè)簡單的函數(shù)y = x ** 2,并對x = [2, 3]求導(dǎo):
import torch x = torch.tensor([2.0, 3.0], requires_grad=True) y = x ** 2 print(y) y.backward() print(x.grad)
輸出結(jié)果為:
tensor([4., 9.], grad_fn=<PowBackward0>)
tensor([4., 6.])
什么是計(jì)算圖,如何使用.grad_fn屬性來查看張量在計(jì)算圖中的位置和函數(shù)
計(jì)算圖是一種用來表示張量之間的運(yùn)算關(guān)系的有向無環(huán)圖(DAG)。每個(gè)節(jié)點(diǎn)代表一個(gè)張量,每條邊代表一個(gè)運(yùn)算。當(dāng)我們對一個(gè)張量執(zhí)行某些操作時(shí),例如加法、乘法、指數(shù)等,pytorch會記錄這些操作,并構(gòu)建一個(gè)計(jì)算圖。當(dāng)我們調(diào)用.backward()方法時(shí),pytorch會根據(jù)鏈?zhǔn)椒▌t從后往前遍歷這個(gè)計(jì)算圖,并計(jì)算每個(gè)節(jié)點(diǎn)的梯度。
.grad_fn屬性是一個(gè)指向創(chuàng)建該張量的函數(shù)(Function對象)的引用。通過這個(gè)屬性,我們可以訪問該張量在計(jì)算圖中的位置和函數(shù)。Function對象有兩個(gè)重要的屬性:.next_functions和.saved_tensors。.next_functions是一個(gè)元組,包含了該函數(shù)的所有輸入節(jié)點(diǎn)(即該張量的直接前驅(qū)節(jié)點(diǎn))。.saved_tensors是一個(gè)元組,包含了該函數(shù)需要保存的中間結(jié)果(為了反向傳播)。通過這兩個(gè)屬性,我們可以沿著計(jì)算圖向前或向后追蹤張量的運(yùn)算過程。
例如,我們可以定義一個(gè)簡單的函數(shù)y = x ** 2,并對x = [2, 3]求導(dǎo):
import torch x = torch.tensor([2.0, 3.0], requires_grad=True) # 創(chuàng)建一個(gè)需要求導(dǎo)的張量x y = x ** 2 # 對x進(jìn)行平方運(yùn)算,得到y(tǒng) print(y) # 輸出tensor([4., 9.], grad_fn=<PowBackward0>) y.backward() # 對y進(jìn)行反向傳播,計(jì)算x的梯度 print(x.grad) # 輸出tensor([4., 6.])
在這個(gè)例子中,我們可以看到y(tǒng)是由函數(shù)創(chuàng)建的,這個(gè)函數(shù)表示對輸入進(jìn)行冪運(yùn)算。我們可以通過y.grad_fn屬性來訪問這個(gè)函數(shù):
print(y.grad_fn) # 輸出<PowBackward0 object at 0x7f8c1c1a5b80>
我們可以通過y.grad_fn.next_functions屬性來訪問該函數(shù)的輸入節(jié)點(diǎn):
print(y.grad_fn.next_functions) # 輸出((<AccumulateGrad object at 0x7f8c1c1a5b50>, 0),)
其中第一個(gè)元素是對象,它表示梯度累加器,用來存儲x的梯度值。第二個(gè)元素是0,表示該對象在next_functions中的索引。我們可以通過索引來進(jìn)一步訪問對象:
print(y.grad_fn.next_functions[0]) # 輸出(<AccumulateGrad object at 0x7f8c1c1a5b50>, 0)
我們可以通過.variable屬性來訪問該對象所對應(yīng)的原始變量(即x):
print(y.grad_fn.next_functions[0][0].variable) # 輸出tensor([2., 3.], requires_grad=True)
由于函數(shù)沒有保存任何中間結(jié)果(因?yàn)樗恍枰?,所以它?saved_tensors屬性為空:
print(y.grad_fn.saved_tensors) # 輸出()
什么是葉子節(jié)點(diǎn)和非葉子節(jié)點(diǎn),如何使用.is_leaf屬性來判斷張量是否為葉子節(jié)點(diǎn)
葉子節(jié)點(diǎn)(leaf tensors)是指在計(jì)算圖中沒有任何后繼節(jié)點(diǎn)的張量,也就是說它們不是由其他張量經(jīng)過運(yùn)算得到的。通常,葉子節(jié)點(diǎn)是由用戶直接創(chuàng)建的,或者是由requires_grad=False的張量經(jīng)過一些操作得到的。葉子節(jié)點(diǎn)的梯度會被累加到.grad屬性中。
非葉子節(jié)點(diǎn)(non-leaf tensors)是指在計(jì)算圖中有后繼節(jié)點(diǎn)的張量,也就是說它們是由其他張量經(jīng)過運(yùn)算得到的。通常,非葉子節(jié)點(diǎn)是由requires_grad=True的張量經(jīng)過一些操作得到的。非葉子節(jié)點(diǎn)的梯度不會被累加到.grad屬性中,除非使用retain_grad()方法來保存它們。
.is_leaf屬性是一個(gè)布爾值,表示該張量是否為葉子節(jié)點(diǎn)。如果該屬性為True,則該張量為葉子節(jié)點(diǎn);如果該屬性為False,則該張量為非葉子節(jié)點(diǎn)。
例如,我們可以定義一個(gè)簡單的函數(shù)y = x ** 2,并對x = [2, 3]求導(dǎo):
import torch x = torch.tensor([2.0, 3.0], requires_grad=True) # 創(chuàng)建一個(gè)需要求導(dǎo)的張量x y = x ** 2 # 對x進(jìn)行平方運(yùn)算,得到y(tǒng) print(x.is_leaf) # 輸出True,因?yàn)閤是用戶直接創(chuàng)建的 print(y.is_leaf) # 輸出False,因?yàn)閥是由x經(jīng)過運(yùn)算得到的 y.backward() # 對y進(jìn)行反向傳播,計(jì)算x和y的梯度 print(x.grad) # 輸出tensor([4., 6.]),因?yàn)閤是葉子節(jié)點(diǎn),所以它的梯度被累加到了.grad屬性中 print(y.grad) # 輸出None,因?yàn)閥是非葉子節(jié)點(diǎn),并且沒有使用retain_grad()方法來保存它的梯度
什么是梯度累加機(jī)制,如何使用.zero_grad()方法或者with torch.no_grad()語句來清除或禁止梯度累加
梯度累加機(jī)制是指當(dāng)我們對一個(gè)張量進(jìn)行多次反向傳播時(shí),它的梯度值不會被覆蓋,而是會被累加到.grad屬性中。這樣做的好處是可以在內(nèi)存有限的情況下,使用較大的批量大小來訓(xùn)練模型。例如,如果我們想要使用批量大小為32的數(shù)據(jù)來訓(xùn)練模型,但是內(nèi)存只能容納批量大小為8的數(shù)據(jù),那么我們可以將每個(gè)批次分成4個(gè)子批次,對每個(gè)子批次進(jìn)行反向傳播,并在4次反向傳播后再更新參數(shù)。這樣相當(dāng)于對批量大小為32的數(shù)據(jù)進(jìn)行了一次反向傳播和參數(shù)更新。
.zero_grad()方法是用來清除張量或者優(yōu)化器中的梯度值的。通常,在每個(gè)訓(xùn)練循環(huán)開始前,我們需要調(diào)用這個(gè)方法來清零之前累積的梯度值,以避免混淆不同批次或者不同周期的梯度值。
with torch.no_grad()語句是用來禁止張量或者優(yōu)化器中的梯度計(jì)算和累加的。通常,在推理階段(即模型評估或測試),我們不需要計(jì)算任何梯度值,因?yàn)槲覀儾粫{(diào)用.backward()方法或者更新參數(shù)。使用這個(gè)語句可以節(jié)省內(nèi)存和計(jì)算資源,并提高推理速度。
例如,我們可以定義一個(gè)簡單的函數(shù)y = x ** 2,并對x = [2, 3]求導(dǎo):
import torch x = torch.tensor([2.0, 3.0], requires_grad=True) # 創(chuàng)建一個(gè)需要求導(dǎo)的張量x y = x ** 2 # 對x進(jìn)行平方運(yùn)算,得到y(tǒng) print(x.is_leaf) # 輸出True,因?yàn)閤是用戶直接創(chuàng)建的 print(y.is_leaf) # 輸出False,因?yàn)閥是由x經(jīng)過運(yùn)算得到的 y.backward() # 對y進(jìn)行反向傳播,計(jì)算x和y的梯度 print(x.grad) # 輸出tensor([4., 6.]),因?yàn)閤是葉子節(jié)點(diǎn),所以它的梯度被累加到了.grad屬性中 print(y.grad) # 輸出None,因?yàn)閥是非葉子節(jié)點(diǎn),并且沒有使用retain_grad()方法來保存它的梯度 # 清除張量中已有的梯度值 x.grad.zero_() # 或者清除優(yōu)化器中已有的梯度值(如果有) # optimizer.zero_grad() # 禁止張量中新產(chǎn)生的梯度計(jì)算和累加 with torch.no_grad(): z = x ** 3 # 對x進(jìn)行立方運(yùn)算,得到z print(z.requires_grad) # 輸出False, 因?yàn)閦不需要求導(dǎo)
神經(jīng)網(wǎng)絡(luò)的構(gòu)建
神經(jīng)網(wǎng)絡(luò)構(gòu)建是指使用pytorch提供的nn模塊來定義和訓(xùn)練復(fù)雜的神經(jīng)網(wǎng)絡(luò)模型。nn模塊包含了各種預(yù)定義的層、損失函數(shù)、優(yōu)化器等組件,可以方便地組合成不同類型的神經(jīng)網(wǎng)絡(luò)。我們可以使用nn.Module類來定義自己的神經(jīng)網(wǎng)絡(luò)層或模型,并實(shí)現(xiàn)forward()方法來定義前向傳播邏輯。backward()方法會由autograd自動實(shí)現(xiàn)。
例如,我們可以定義一個(gè)簡單的線性回歸模型,并用隨機(jī)數(shù)據(jù)進(jìn)行訓(xùn)練:
import torch import torch.nn as nn # 定義線性回歸模型 y = wx + b class LinearRegression(nn.Module): def __init__(self): super(LinearRegression, self).__init__() self.linear = nn.Linear(1, 1) # 輸入維度為1,輸出維度為1 def forward(self, x): y = self.linear(x) # 前向傳播邏輯 return y # 創(chuàng)建模型實(shí)例 model = LinearRegression() print(model) # 創(chuàng)建損失函數(shù)(均方誤差)和優(yōu)化器(隨機(jī)梯度下降) criterion = nn.MSELoss() optimizer = torch.optim.SGD(model.parameters(), lr=0. # 生成隨機(jī)數(shù)據(jù) x = torch.randn(100, 1) # 100個(gè)隨機(jī)輸入 y = 3 * x + 2 + torch.randn(100, 1) # 對應(yīng)的輸出,加上一些噪聲 # 訓(xùn)練模型 epochs = 20 # 迭代次數(shù) for epoch in range(epochs): # 前向傳播,得到預(yù)測值 y_pred = model(x) # 計(jì)算損失值 loss = criterion(y_pred, y) # 反向傳播,計(jì)算梯度 loss.backward() # 更新參數(shù) optimizer.step() # 清零梯度 optimizer.zero_grad() # 打印損失值和參數(shù)值 print(f"Epoch {epoch}, loss: {loss.item():.4f}") for name, param in model.named_parameters(): print(name, param.data) # 測試模型 x_test = torch.tensor([[4.0]]) # 測試輸入 y_test = model(x_test) # 預(yù)測輸出 print(f"Predicted y for x = 4: {y_test.item():.4f}")
輸出結(jié)果為:
Epoch 0, loss: 9.9758
linear.weight tensor([[2.8277]])
linear.bias tensor([0.0145])
Epoch 1, loss: 4.0609
linear.weight tensor([[2.9056]])
linear.bias tensor([0.2308])
...
Epoch 19, loss: 0.9866
linear.weight tensor([[2.9877]])
linear.bias tensor([1.9679])
Predicted y for x = 4: 13.9166
可以看到,經(jīng)過訓(xùn)練,模型的參數(shù)接近真實(shí)值(w=3,b=2),并且能夠?qū)π碌妮斎脒M(jìn)行預(yù)測。
參考:) PyTorch官方網(wǎng)站
到此這篇關(guān)于使用pytorch進(jìn)行張量計(jì)算、自動求導(dǎo)和神經(jīng)網(wǎng)絡(luò)構(gòu)建的文章就介紹到這了,更多相關(guān)pytorch進(jìn)行張量計(jì)算內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- pytorch如何定義新的自動求導(dǎo)函數(shù)
- 在?pytorch?中實(shí)現(xiàn)計(jì)算圖和自動求導(dǎo)
- Pytorch自動求導(dǎo)函數(shù)詳解流程以及與TensorFlow搭建網(wǎng)絡(luò)的對比
- 淺談Pytorch中的自動求導(dǎo)函數(shù)backward()所需參數(shù)的含義
- pytorch中的自定義反向傳播,求導(dǎo)實(shí)例
- 關(guān)于PyTorch 自動求導(dǎo)機(jī)制詳解
- Pytorch反向求導(dǎo)更新網(wǎng)絡(luò)參數(shù)的方法
- 關(guān)于pytorch求導(dǎo)總結(jié)(torch.autograd)
相關(guān)文章
conda創(chuàng)建環(huán)境、安裝包、刪除環(huán)境步驟詳細(xì)記錄
對于生信工作者,有一個(gè)方便可用的環(huán)境可以極大地方便我們開展分析,conda可以讓我們在非root的情況下較為方便地切換不同的工作環(huán)境,下面這篇文章主要給大家介紹了關(guān)于conda創(chuàng)建環(huán)境、安裝包、刪除環(huán)境步驟的相關(guān)資料,需要的朋友可以參考下2022-08-08用Python編寫生成樹狀結(jié)構(gòu)的文件目錄的腳本的教程
這篇文章主要介紹了用Python編寫生成樹狀結(jié)構(gòu)的文件目錄的腳本的教程,是一個(gè)利用os模塊下各函數(shù)的簡單實(shí)現(xiàn),需要的朋友可以參考下2015-05-05Python多進(jìn)程Process和管道Pipe的使用方式
這篇文章主要介紹了Python多進(jìn)程Process和管道Pipe的使用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02Python實(shí)現(xiàn)多個(gè)Word文檔合并
在Python中,可以使用Python-docx庫來操作Word文檔,所以下面小編就為大家介紹一下如何利用Python-docx實(shí)現(xiàn)多個(gè)Word文檔合并功能吧,需要的可以參考一下2023-06-06利用keras加載訓(xùn)練好的.H5文件,并實(shí)現(xiàn)預(yù)測圖片
今天小編就為大家分享一篇利用keras加載訓(xùn)練好的.H5文件,并實(shí)現(xiàn)預(yù)測圖片,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01Python numpy有哪些常用數(shù)據(jù)類型
Numpy提供了兩種基本的對象:ndarray(N-dimensional Array Object)和 ufunc(Universal Function Object)。ndarray是存儲單一數(shù)據(jù)類型的多維數(shù)組,而ufunc則是能夠?qū)?shù)組進(jìn)行處理的函數(shù)2023-02-02