[引言]張量的概念
1.基本概念
- 張量是一個通用的多維數組,可以表示標量(0 維)、向量(1 維)、矩陣(2 維)以及更高維度的數據。
- 張量是 PyTorch 中的核心數據結構,用于表示和操作數據。
0維張量:標量(scalar)
1維張量:向量(vector)
2維張量:矩陣(matrix)
多維張量: 例如三維張量==>類比魔方
1.張量的創建
張量的基本創建
-
torch.tensor() 根據指定數據創建張量
# 1.根據指定數據創建張量 - torch.tensor print('tensor 方式創建張量')# 1.1 創建張量標量 data = torch.tensor(10) print(f'張量標量:{data}')# 1.2 根據 numpy數組 創建張量 data = np.random.randn(3, 2) data = torch.tensor(data) print(f'根據numpy數組創建張量:\r\n{data}')# 1.3 根據 列表 創建張量 data = [[1, 0, 0], [0, 1, 0]] data = torch.tensor(data) print(f'根據列表創建張量:\r\n{data}')
-
torch.Tensor() 根據形狀創建張量, 其也可用來創建指定數據的張量
# 2. 根據形狀創建張量 - torch.Tensor print('Tensor 方式創建張量') # 2.1 創建 2 行 3 列的張量 默認的dtype為 float32 data = torch.Tensor(2, 3) print(data)# 2.2 注意!! 如果 傳遞列表, 則創建包含指定元素的張量 data = torch.Tensor([10]) print(data)
-
torch.IntTensor()、torch.FloatTensor()、torch.DoubleTensor() 創建指定類型的張量
# 3.創建指定類型的張量 - torch.IntTensor、torch.FloatTensor、torch.DoubleTensor print('創建指定類型的張量-> torch.IntTensor、torch.FloatTensor、torch.DoubleTensor') # 3.1 創建 2 行 3 列,dtype為 int32 的張量 data = torch.IntTensor(2, 3) print(data)# 3.2 注意!! 如果傳遞的類型不正確,則會進行類型轉換 data = torch.IntTensor([2.5, 3.3]) print(data) """ 其他的一些類型 class DoubleTensor(Tensor): ... class FloatTensor(Tensor): ... class BFloat16Tensor(Tensor): ... class LongTensor(Tensor): ... class IntTensor(Tensor): ... class ShortTensor(Tensor): ... class HalfTensor(Tensor): ... class CharTensor(Tensor): ... class ByteTensor(Tensor): ... class BoolTensor(Tensor): ... """
1-總結
小寫 t: 根據指定數據創建
大寫 T: 既可以根據指定數據創建,也可以根據形狀創建
Tensor: 不指定類型
(Type)Tensor: 指定類型
創建線性張量和隨機張量
-
torch.arange() 和 torch.linspace() 創建線性張量
# 1. 創建線性張量 print('=' * 50 + '創建線性張量' + '=' * 50) # 1.1 在指定區間內按照步長生成元素 data = torch.arange(0, 10, 2) print(data)# 1.2 在指定區間按照元素個數生成 data = torch.linspace(0, 10, 9) print(data)
-
torch.random.init_seed() 和 torch.random.manual_seed() 隨機種子設置
-
torch.randn() 創建隨機張量
# 2.創建隨機張量
print('=' * 50 + '創建隨機張量' + '=' * 50)
# 2.1 創建一個 2 行 3列的隨機張量
data = torch.randn(2, 3)
print(data)# 2.2 設置隨機數種子
# - torch.random.init_seed
print(f'隨機數種子: {torch.random.initial_seed()}') # 25338627685600
# - torch.random.manual_seed
torch.random.manual_seed(200)
data = torch.randn(2, 3)
print(data)
print(f'隨機數種子: {torch.random.initial_seed()}') # 100
創建0-1張量
- torch.ones 和 torch.ones_like 創建全1張量
- torch.zeros 和 torch.zeros_like 創建全0張量
- torch.full 和 torch.full_like 創建全為指定值張量
import torch# - torch.ones 和 torch.ones_like 創建全1張量
data = torch.ones(2, 3)
print(f'data:\r\n{data}')
data1 = torch.ones_like(data)
print(f'data1:\r\n{data1}')# - torch.zeros 和 torch.zeros_like 創建全0張量
data = torch.zeros(2, 3)
print(f'data:\r\n{data}')
data1 = torch.zeros_like(data)
print(f'data1:\r\n{data1}')# - torch.full 和 torch.full_like 創建全為指定值張量
data = torch.full([2, 3], 10, dtype=torch.float32)
print(f'data:\r\n{data}')
data1 = torch.full_like(data, 20)
print(f'data1:\r\n{data1}')
print(f'data1.dtype:{data1.dtype}') # float32
2.張量的類型轉換
張量的元素類型轉換
data.type(torch.DoubleTensor)
data.double()
import torch
# 1. data.type(torch.類型)
print('===============data.type(torch.類型)================')
data = torch.full([2, 3], 10)
print(data.dtype)data = data.type(torch.DoubleTensor)
print(data.dtype)# data = data.type(torch.IntTensor)
# print(data.dtype)
# data = data.type(torch.LongTensor)
# print(data.dtype)# 2. data.double()
print('===============data.double()=================')
data = torch.full([2, 3], 20)
print(data.dtype)data = data.double()
print(data.dtype)# data = data.int()
# print(data.dtype)
張量的類型轉換
- 張量轉換為
Numpy
數組的方法
-
使用
Tensor.numpy
函數可以將張量轉換為ndarray
數組,但是共享內存,可以使用 copy 函數避免共享。# 1. 張量轉換為Numpy數組的方法 # - 使用 Tensor.numpy 函數可以將張量轉換為 ndarray 數組,但是共享內存,可以使用 copy 函數避免共享. print('=' * 30 + '使用 Tensor.numpy但不進行copy' + '=' * 30) data_tensor = torch.tensor([2, 3, 4]) data_numpy = data_tensor.numpy() print(type(data_tensor)) print(type(data_numpy))data_numpy[0] = 100 print(data_tensor) print(f'ndarray:{data_numpy}')print('=' * 30 + '使用 Tensor.numpy并進行copy' + '=' * 30) data_tensor = torch.tensor([2, 3, 4]) data_numpy = data_tensor.numpy().copy() print(type(data_tensor)) print(type(data_numpy))data_numpy[0] = 100 print(data_tensor) print(f'ndarray:{data_numpy}')
Numpy
數組轉換為張量的方法
-
使用
from_numpy
可以將ndarray
數組轉換為Tensor
,默認共享內存,使用copy
函數避免共享。 -
使用
torch.tensor
可以將ndarray
數組轉換為Tensor
,默認不共享內存。# 2. Numpy數組轉換為張量的方法 """ 將numpy數組轉換為張量2.1 from_numpy 默認共享內存,使用 copy 函數避免共享。2.2 torch.tensor(ndarray) 默認不共享內存。 """ # - 2.1 使用 from_numpy:會共享內存,可以使用 copy 函數避免共享。 print('=' * 30 + '使用from_numpy但不進行copy' + '=' * 30) data_numpy = np.array([2, 3, 4]) data_tensor = torch.from_numpy(data_numpy) data_tensor[0] = 100 print(data_tensor) print(f'ndarray:{data_numpy}')print('=' * 30 + '使用from_numpy且進行copy' + '=' * 30) data_numpy = np.array([2, 3, 4]) data_tensor = torch.from_numpy(data_numpy.copy()) data_tensor[0] = 100 print(data_tensor) print(f'ndarray:{data_numpy}')# - 2.2 使用 torch.tensor(ndarray) 默認不共享內存。 data_numpy = np.array([2, 3, 4]) data_tensor = torch.tensor(data_numpy)data_tensor[0] = 100 print(data_tensor) print(f'ndarray:{data_numpy}')
- 標量張量和數字轉換方法
- 對于只有一個元素的張量,使用item()函數將該值從張量中提取出來
官方文檔解釋: Returns the value of this tensor as a standard Python number.
This only works for tensors with one element.
# 3. 標量張量和數字轉換方法
# - 對于只有一個元素的張量,使用item()函數將該值從張量中提取出來
data_tensor = torch.tensor([30, ])
print(data_tensor.item())data_tensor = torch.tensor(30)
print(data_tensor.item())
3.張量數值計算
- 張量基本運算
-
不修改原數據
- add、sub、mul、div、neg
-
修改源數據
- add_、sub_、mul_、div_、neg_(帶下劃線的版本會修改原數據)
# 1.張量基本運算 print('=' * 30 + '基本運算' + '=' * 30) data = torch.randint(0, 10, [2, 3]) print(f'原數據data:\r\n{data}')# 1.1 不修改原數據 print('=' * 10 + 'add' + '=' * 10) new_data = data.add(10) print(f'new_data:\r\n{new_data}') print(f'data:\r\n{data}')# 1.2 直接修改原數據 print('=' * 10 + 'add_' + '=' * 10) data.add_(10) print(f'data:\r\n{data}')# print(data.sub(10)) # print(data.mul(10)) # print(data.div(10)) # print(data.neg())
-
張量點乘運算
-
點乘指(Hadamard積)的是兩個 同維[同型]矩陣 對應位置的元素相乘,使用mul 和運算符 * 實現。
# 2. 張量點乘運算 print('=' * 30 + '張量點乘運算' + '=' * 30) A = torch.tensor([[1, 2], [3, 4]]) B = torch.tensor([[5, 6], [7, 8]])# - 2.1 使用 mul(A,B) print('=' * 10 + 'mul 點乘' + '=' * 10) res = torch.mul(A, B) print(f'點乘后的結果:{res}')# - 2.2 使用 * 運算符 print('=' * 10 + '* 點乘' + '=' * 10) res = A * B print(f'點乘后的結果:{res}')
-
-
張量矩陣乘法運算
矩陣乘法運算要求第一個矩陣 shape: (n, m),第二個矩陣 shape: (m, p), 兩個矩陣點積運算 shape 為: (n, p)。
- 1.運算符 @ 用于進行兩個矩陣的乘積運算
- 2.torch.matmul 對進行乘積運算的兩矩陣形狀沒有限定.對數輸入的 shape 不同的張量, 對應的最后幾個維度必須符合矩陣運算規則
# 3. 張量矩陣乘法運算
print('=' * 30 + '張量矩陣乘法運算' + '=' * 30)
A = torch.tensor([[1, 2], [3, 4], [5, 6]])
B = torch.tensor([[5, 6], [7, 8]])# 3.1 使用 matmul(A,B)
# - torch.matmul 對進行乘積運算的兩矩陣形狀沒有限定.對數輸入的 shape 不同的張量, 對應的最后幾個維度必須符合矩陣運算規則
print(f'matmul(A,B) ={torch.matmul(A, B)}')# 3.2 使用@ 運算符
print(f'A @ B = {A @ B}')
4.張量運算函數
"""
- 均值
- 平方根
- 求和
- 指數計算
- 對數計算
.......
"""
import torchdata = torch.randint(0, 10, [2, 3], dtype=torch.float64)
print(data)# 1.均值
# 注意!! tensor必須為 float 或者 Double類型
print('=' * 10 + 'mean' + '=' * 10)
print(data.mean())
print(data.mean(dim=0)) # 按列求均值
print(data.mean(dim=1)) # 按行求均值# 2.求和
print('=' * 10 + 'sum' + '=' * 10)
print(data.sum())
print(data.sum(dim=0))
print(data.sum(dim=1))# 3.計算平方
print('=' * 10 + 'pow' + '=' * 10)
print(torch.pow(data, 2))
print(data.pow(2))# 4.計算平方根
print('=' * 10 + 'sqrt' + '=' * 10)
print(data.sqrt())
print(torch.sqrt(data))# 5.指數計算 e^n 次方
print('=' * 10 + 'exp' + '=' * 10)
print(data.exp())
print(torch.exp(data))# 6.對數計算 :以 e 為底數
print('=' * 10 + 'log' + '=' * 10)
print(data.log())
print(torch.log(data))
print(data.log2())
print(data.log10())
5.張量索引操作
-
簡單行列索引的使用
格式:data[row,col]
代碼
data = torch.randint(0, 10, [4, 5]) print('data->\r\n', data)# 1. 簡單行列索引的使用 print('=' * 20, '簡單行列索引', '=' * 20) print(f'data[0, 0] -> {data[0, 0]}') print(f'data[:,0] -> {data[:, 0]}')
-
列表索引的使用
格式:rows = [a,b,...]cols = [c,d...]訪問:data[rows,cols] 含義:訪問 [a,c] | [b,d]....的值
代碼:
data = torch.randint(0, 10, [4, 5]) print('data->\r\n', data)# 2. 列表索引的使用 print('=' * 20, '列表索引', '=' * 20) # 2.1 返回 (0, 2)、(1, 3) 兩個位置的元素 rows = [0, 1] cols = [2, 3] print(f'data[rows,cols] ->', data[rows, cols]) # 2.2 返回行索引為 0 的第 1、2、3 列的值 print(f'data[[0],[1,2]] ->', data[[0], [1, 2]])# 2.3 range()方式訪問元素:返回 (0, 1) 和 (1, 2) 兩個位置的元素 print(f'data[rows,cols] ->', data[range(2), range(1, 3)])# 2.4 返回行索引為 0 和 1 的第 1、2、3 列的值 print(f'data[[[0], [1]], [1, 2, 3]] ->', data[[[0], [1]], [1, 2, 3]])# 2.5 返回行索引為 0、1、2 的第 0、1、2 列的值 和 行索引為 1、2、3 的第 1、2、3 列的值 print(f'data[[[0, 1, 2], [1, 2, 3]], [[0, 1, 2], [1, 2, 3]]] ->', data[[[0, 1, 2], [1, 2, 3]], [[0, 1, 2], [1, 2, 3]]])# print('data[[[0],[1,2,3]], [0,1,2]] ->',{data[0, 0]}) # 報錯, 因為索引的維度不匹配
-
范圍索引的使用
- 和
Numpy
大致相同,但不 支持反向索引
data = torch.randint(0, 10, [4, 5]) print('data->\r\n', data)# 3. 范圍索引的使用 print('=' * 20, '范圍索引', '=' * 20) # 3.1 獲取前三行前兩列元素的值 print('data[:3,:2]->', data[:3, :2])# 3.2 獲取后兩行后兩列元素的值 print('data[-2:,-2:]->', data[-2:, -2:])# print('data[3:1:-1,-2:]->', data[3:1:-1, -2:]) # 報錯,tensor不支持反向切片
- 和
-
布爾索引的使用
- 和`Numpy`,`Pandas`大致相同
# 4. 布爾索引的使用 print('=' * 20, '布爾索引', '=' * 20) # 4.0 理解布爾索引的原理 bool_index = [True, False, False, True, False] """ 注意它取元素時的方式!!!!第一行中滿足布爾索引的拿出來,當作一行第二行中滿足布爾索引的拿出來,當作一行以此類推 """ print('data[:,bool_index] ->\r\n', data[:, bool_index])# 4.1 獲取第三行大于 5的元素 print(data[data[:, 2] > 5])# 4.2 獲取第二行大于 5的 列 print('data[:,data[1]>5] ->\r\n', data[:, data[1] > 5])
-
多維索引的使用
- 和
Numpy
,Pandas
大致相同
- 和
data = torch.randint(0, 10, [4, 5])
print('data->\r\n', data)# 5. 多維索引的使用
print('=' * 20, '多維索引', '=' * 20)
data = torch.randint(0, 10, [3, 4, 5])
print('data->\r\n', data)
# 5.1 獲取第一維元素
print(data[0, :, :])
# 5.2 獲取第二維元素
print(data[:, 0, :])
# 5.3 獲取第三維元素 # 注意它取元素的方式!!!
print(data[:, :, 0])
6.張量形狀操作
0.形狀信息獲取
使用 shape 屬性或者 size 方法都可以獲得張量的形狀
data = torch.tensor([[10, 20, 30], [40, 50, 60]])# 1. 使用 shape 屬性或者 size 方法都可以獲得張量的形狀
print('使用 shape 屬性或者 size 方法都可以獲得張量的形狀')
print(data.shape, data.shape[0], data.shape[1])
print(data.size(), data.size(0), data.size(1))
print()
1.reshape方式修改形狀
? - reshape()
reshape 函數可以在保證張量數據不變的前提下改變數據的維度,將其轉換成指定的形狀
轉換順序:左右上下
data = torch.tensor([[10, 20, 30], [40, 50, 60]])# 2. 使用 reshape() 修改張量的形狀
print('使用 reshape() 修改張量的形狀')
reshape_data = data.reshape(1, data.shape[0] * data.shape[1])
print(f'reshape_data:{reshape_data}')
print(f'reshape_data:{data.reshape(1, -1)}')
print()
-
升維與降維
-
squeeze()
-
unsqueeze()
- squeeze函數 刪除形狀為 1 的維度(降維) - unsqueeze函數 添加形狀為1的維度(升維)
unsqueeze(dim=i):在索引為i的位置添加一個形狀為1的維度
data = torch.tensor([[10, 20, 30], [40, 50, 60]])# 3. squeeze()和unsqueeze()函數 print('squeeze()和unsqueeze()函數') mydata1 = torch.tensor([1, 2, 3, 4, 5, 6]) print('mydata1->', mydata1.shape, mydata1) # torch.Size([6])mydata2 = mydata1.unsqueeze(dim=0) print('在0維度上 擴展維度:', mydata2, mydata2.shape) # torch.Size([1, 6])mydata3 = mydata1.unsqueeze(dim=1) print('在1維度上 擴展維度:\r\n', mydata3, mydata3.shape) # torch.Size([6, 1])mydata4 = mydata1.unsqueeze(dim=-1) print('在-1維度上 擴展維度:\r\n', mydata3, mydata3.shape) # torch.Size([6, 1])mydata5 = mydata4.squeeze() print('壓縮維度:', mydata5, mydata5.shape) # torch.Size([6]) print()
-
-
修改形狀
-
transpose()
-
permute()
transpose 函數可以實現交換張量形狀的指定維度, 例如: 一個張量的形狀為 (2, 3, 4) 可以通過 transpose 函數把 3 和 4進行交換, 將張量的形狀變為 (2, 4, 3) 。
permute 函數可以一次交換更多的維度。data = torch.tensor([[10, 20, 30], [40, 50, 60]])# 4.transpose() 和 permute() print('transpose() 和 permute()') data = torch.tensor(np.random.randint(0, 10, [2, 3, 3])) print(f'data shape:{data.size()}') print(data) # 4.1 交換1 和 2維度 data_transpose = torch.transpose(data, 1, 2) print(f'data_transpose shape:{data_transpose.size()}')# 4.2 將data 的形狀修改為 (4, 5, 3), 需要變換多次 data_transpose1 = torch.transpose(data, 0, 1) print(data_transpose1) data_transpose1 = torch.transpose(data_transpose1, 1, 2) print(f'data_transpose1 shape:{data_transpose1.size()}')# 4.3 使用 permute 函數將形狀修改為 (4, 5, 3) data_transpose2 = torch.permute(data, (1, 2, 0)) print(f'data_transpose1 shape:{data_transpose2.size()}')
-
view()
view 函數也可以用于修改張量的形狀,只能用于存儲在整塊內存中的張量。
在 PyTorch 中,有些張量是由不同的數據塊組成的,它們并沒有存儲在整塊的內存中,view 函數無法對這樣的張量進行變形處理.
例如: 一個張量經過了transpose 或者 permute 函數的處理之后,就無法使用 view 函數進行形狀操作。 -
contiguous()
若要使用view函數, 需要使用contiguous() 變成連續以后再使用view函數
is_contiguous() 判斷是否 連續存儲
-
data = torch.tensor([[10, 20, 30], [40, 50, 60]])# 5.view()和contiguous()函數"""
1. 一個張量經過了 transpose 或者 permute 函數的處理之后,就無法使用view 函數進行形狀操作若要使用view函數, 需要使用contiguous() 變成連續以后再使用view函數
2. 判斷張量是否使用整塊內存 is_contiguous
"""
print('view()和is_contiguous()函數')
data = torch.tensor([[10, 20, 30], [40, 50, 60]])
print('data--->', data, data.shape)# 5.1 判斷是否使用整塊內存
print(data.is_contiguous()) # True# 5.2 view
data_view = data.view(3, 2)
print('data_view ->', data_view, data_view.shape)# 5.3 判斷是否使用整塊內存
print('data_view.is_contiguous->', data_view.is_contiguous())
print()# 5.4 使用 transpose 函數修改形狀
print('view()和contiguous()函數')
data_transpose = data.transpose(0, 1)
print('data_transpose->', data_transpose, data_transpose.shape)
print('data_transpose.is_contiguous->', data_transpose.is_contiguous())
print(data_transpose.contiguous().is_contiguous())
data_view = data_transpose.contiguous().view(2, 3)
print('data_view->', data_view.shape, data_view)
print('')
7.張量拼接操作
張量拼接(Concatenation)是將多個張量按指定的維度連接起來的操作。
-
torch.cat()
-
torch.cat 是按指定維度將多個張量連接起來,拼接后的維度大小會變化,但總維數保持不變。
-
使用時,所有張量在指定的拼接維度上必須形狀一致。
# 1. torch.cat() print('================cat 方式拼接=====================') data1 = torch.randint(0, 10, [1, 2, 3]) data2 = torch.randint(0, 10, [1, 2, 3]) print(f'data1:{data1}') print(f'data2:{data2}') print() # 1.1 按 0維拼接 new_data = torch.cat([data1, data2], dim=0) print('按 0維 拼接->', new_data, new_data.size())# 1.2 按 1維拼接 new_data = torch.cat([data1, data2], dim=1) print('按 1維 拼接->', new_data, new_data.size())# 1.3 按 2維拼接 new_data = torch.cat([data1, data2], dim=2) print('按 2維 拼接->', new_data, new_data.size()) print()
-
-
torch.stack() [了解]
-
torch.stack 是在新維度上將多個張量連接起來,拼接后的總維數會增加 1。
-
使用時,所有張量的形狀必須完全一致。
# 2.stack print('================stack 方式拼接=====================') data1 = torch.randint(0, 10, [1, 2, 3]) data2 = torch.randint(0, 10, [1, 2, 3]) print(f'data1:{data1}') print(f'data2:{data2}')# 2.1 按 0維連接 new_data = torch.stack([data1, data2], dim=0) print('按 0維 連接->', new_data, new_data.size())# 2.2 按 1維連接 new_data = torch.stack([data1, data2], dim=1) print('按 1維 連接->', new_data, new_data.size())# 2.3 按 2維連接 new_data = torch.stack([data1, data2], dim=2) print('按 2維 連接->', new_data, new_data.size()) print()
-
torch.cat
與 torch.stack
的區別
q特性 | torch.cat | torch.stack |
---|---|---|
總維數變化 | 不增加維數 | 增加 1 個維數 |
形狀要求 | 指定維度一致 | 所有維度必須完全一致 |
典型應用 | 沿某個軸擴展數據 | 創建新的批量或時間步維度 |
8.自動微分模塊
- 反向傳播算法```properties在該算法中,參數(模型權重)會根據損失函數關于對應參數的梯度進行調整。為了計算這些梯度,PyTorch內置了名為 torch.autograd 的微分引擎。它支持任意計算圖的自動梯度計算, 使用 backward 方法、grad 屬性來實現梯度的計算和訪問.```
示例:
# 1. 當X為標量時梯度的計算
def scaler_grad_compute():x = torch.tensor(5)# 目標值: labely = torch.tensor(0.)# 設置要更新的權重和偏置的初始值w = torch.tensor(1, requires_grad=True, dtype=torch.float32)b = torch.tensor(3, requires_grad=True, dtype=torch.float32)# 設置網絡的輸出值z = w * x + b # 矩陣乘法?# 設置損失函數,并進行損失的計算loss = torch.nn.MSELoss()loss = loss(z, y)# 自動微分loss.backward()# 打印 w,b 變量的梯度# backward 函數計算的梯度值會存儲在張量的 grad 變量中print(f'w->{w.grad}')print(f'b->{b.grad}')
# 2.非標量下時梯度的計算
def grad_compute():# 輸入張量(2,5)x = torch.ones(2, 5)# 輸出張量(2,3)y = torch.zeros(2, 3)# 設置要更新的權重和偏置的初始值w = torch.randn(5, 3, requires_grad=True)b = torch.randn(3, requires_grad=True)# 設置神經網絡的輸出值z = torch.matmul(x, w) + b# 設置損失函數,并進行損失的計算loss = torch.nn.MSELoss()loss = loss(z, y) # 底層實現了__call__()方法print(y)# 自動微分loss.backward()# 打印 w,b 變量的梯度# backward 函數計算的梯度值會存儲在張量的 grad 變量中print("W的梯度:", w.grad)print("b的梯度", b.grad)
矩陣乘法?
# 設置損失函數,并進行損失的計算
loss = torch.nn.MSELoss()
loss = loss(z, y)# 自動微分
loss.backward()
# 打印 w,b 變量的梯度
# backward 函數計算的梯度值會存儲在張量的 grad 變量中
print(f'w->{w.grad}')
print(f'b->{b.grad}')
2.非標量下時梯度的計算
def grad_compute():
# 輸入張量(2,5)
x = torch.ones(2, 5)
# 輸出張量(2,3)
y = torch.zeros(2, 3)
# 設置要更新的權重和偏置的初始值
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
# 設置神經網絡的輸出值
z = torch.matmul(x, w) + b
# 設置損失函數,并進行損失的計算
loss = torch.nn.MSELoss()
loss = loss(z, y) # 底層實現了__call__()方法
print(y)
# 自動微分
loss.backward()
# 打印 w,b 變量的梯度
# backward 函數計算的梯度值會存儲在張量的 grad 變量中
print("W的梯度:", w.grad)
print("b的梯度", b.grad)