PyTorch基礎——張量計算

文章目錄

  • PyTorch基礎——張量計算
    • 1 什么是張量計算?
    • 2 基本算術運算
      • 2.1 加法運算
        • 2.1.2 `torch.add`
        • 2.1.3 `a.add(b) 與 a.add_(b)`
          • `a.add(b)` 方法
          • `a.add_(b)` 方法
          • 核心區別
      • 2.2 減法運算
        • 2.2.1 `toch.sub()`
        • 2.2.2 `a.sub(b) `和`a.sub_(b)`
          • `a.sub(b)` 方法
          • `a.sub_(b)` 方法
          • 核心區別
          • 使用建議
      • 2.3 乘法運算
      • 2.4 除法運算
    • 3 矩陣運算
      • 3.1 矩陣乘法
      • 3.2 高維張量的矩陣乘法
      • 3.3 矩陣轉置
    • 4 廣播機制(Broadcasting)
      • 4.1 廣播的基本規則
    • 5 統計運算
      • 5.1 求和運算
      • 5.2 均值運算
      • 5.3 最大值和最小值
      • 5.4 累加運算
    • 6 張量的其他常用運算
      • 6.1 冪運算
        • 6.1.1 通用計算
        • 6.1.2 底數為e的冪運算
      • 6.2 平方根
      • 6.3 指數和對數運算
    • 7 自動求導(Autograd)與張量計算
      • 7.1 基本概念
      • 7.2 自動求導示例
      • 7.3 多變量函數的求導
    • 8 GPU 加速的張量計算
      • 8.1 張量的設備遷移
      • 8.1 張量的設備遷移

PyTorch基礎——張量計算

張量是PyTorch中所有操作的基礎,類似于多維數組,支持GPU加速和自動求導等高級功能。本篇
博客將專門從基礎運算開始,聚焦于張是的計算部分

1 什么是張量計算?

張量計算指的是對張量進行的各種數學操作,包括基本算術運算、矩陣運算、統計運算等。這些操作是構建神經網絡和實現機器學習算法的基礎。與普通的 Python 數值計算不同,PyTorch 的張量計算可以自動并行化并利用 GPU 加速,大幅提高計算效率。

2 基本算術運算

PyTorch 提供了豐富的算術運算函數,既可以通過運算符直接操作,也可以通過 torch 模塊中的函數進行操作。這些運算均為元素級操作(element-wise operation),即對兩個張量對應位置的元素分別進行計算。

2.1 加法運算

2.1.2 torch.add

函數形式torch.add(input, other, out=None)

  • 參數解析
    • input:第一個輸入張量
    • other:第二個輸入張量(或一個標量)
    • out:可選參數,用于指定輸出張量

計算原理
加法運算對兩個張量的對應元素進行求和。

  • 若為兩個張量相加:result[i][j] = input[i][j] + other[i][j]
  • 若為張量與標量相加:result[i][j] = input[i][j] + scalar

手算示例

張量 a: [[1, 2],[3, 4]]
張量 b: [[5, 6],[7, 8]]
a + b 的結果:
[[1+5, 2+6],[3+7, 4+8]] = [[6, 8], [10, 12]]

代碼示例

import torch# 創建兩個張量
a = torch.tensor([1, 2, 3], dtype=torch.float32)
b = torch.tensor([4, 5, 6], dtype=torch.float32)# 方法1:使用運算符
c = a + b
print("a + b =",c)# 方法2:使用torch.add()函數
print("torch.add(a, b) =", torch.add(a, b))# 與標量相加
print("a + 10 =", a + 10)
print("torch.add(a, 10) =", torch.add(a, 10))

運行結果

a + b = tensor([5., 7., 9.])
torch.add(a, b) = tensor([5., 7., 9.])
a + 10 = tensor([11., 12., 13.])
torch.add(a, 10) = tensor([11., 12., 13.])

結果分析:加法運算會對張量的每個元素執行相應操作,當與標量相加時,標量會自動廣播(broadcast)到與張量相同的形狀。

2.1.3 a.add(b) 與 a.add_(b)

在 PyTorch 中,a.add(b)a.add_(b) 都是用于實現張量加法的方法,但它們的核心區別在于是否修改原張量。這是 PyTorch 中非常重要的一個設計理念,理解這個區別有助于避免代碼中出現意外的數據修改。

a.add(b) 方法
  • 功能:計算 a + b 的結果,但不會修改原張量 a,而是返回一個新的張量來存儲計算結果。
  • 特點:屬于「非原地操作」(non-inplace operation),原張量的數據保持不變。

代碼示例

import torcha = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])# 使用 a.add(b)
result = a.add(b)print("原張量 a:", a)    # 原張量 a 未被修改
print("計算結果 result:", result)

運行結果

原張量 a: tensor([1, 2, 3])
計算結果 result: tensor([5, 6, 9])
a.add_(b) 方法
  • 功能:同樣計算 a + b 的結果,但會直接修改原張量 a,將結果存儲在 a 中,不會創建新張量。
  • 特點:屬于「原地操作」(inplace operation),方法名末尾的下劃線 _ 是 PyTorch 中標記原地操作的約定。

代碼示例

import torcha = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])# 使用 a.add_(b)
a.add_(b)  # 直接修改原張量 aprint("修改后的張量 a:", a)  # 原張量 a 已被更新

運行結果

修改后的張量 a: tensor([5, 6, 9])
核心區別
方法操作類型對原張量 a 的影響返回值
a.add(b)非原地操作不修改,保持原值新張量(存儲 a + b 的結果)
a.add_(b)原地操作直接修改 a,使其等于 a + b修改后的 a(與原張量是同一個對象)

區分:

  1. 內存效率:原地操作(add_)不需要創建新張量,節省內存,適合處理大規模數據。
  2. 計算圖影響:在自動求導(Autograd)中,原地操作可能會破壞計算圖的完整性,導致梯度計算錯誤,因此需謹慎使用。
  3. 代碼可讀性:下劃線 _ 明確標記了原地操作,讓其他開發者能快速識別代碼中存在數據修改的地方。

實際開發中,建議優先使用非原地操作(如 a.add(b)),除非明確需要優化內存使用,再考慮原地操作(如 a.add_(b))。

2.2 減法運算

2.2.1 toch.sub()

函數形式torch.sub(input, other, out=None)

  • 參數解析:與 torch.add() 相同,實現 input - other 的運算

計算原理
減法運算對兩個張量的對應元素進行相減。

  • 若為兩個張量相減:result[i][j] = input[i][j] - other[i][j]
  • 若為張量與標量相減:result[i][j] = input[i][j] - scalar

手算示例

張量 a: [[1, 2],[3, 4]]
張量 b: [[5, 6],[7, 8]]
a - b 的結果:
[[1-5, 2-6],[3-7, 4-8]] = [[-4, -4], [-4, -4]]

代碼示例

# 減法運算
print("a - b =", a - b)
print("torch.sub(a, b) =", torch.sub(a, b))
print("a - 2 =", a - 2)

運行結果

a - b = tensor([-3., -3., -3.])
torch.sub(a, b) = tensor([-3., -3., -3.])
a - 2 = tensor([-1.,  0.,  1.])
2.2.2 a.sub(b) a.sub_(b)

在 PyTorch 中,a.sub(b)a.sub_(b) 都是用于實現張量減法的方法,它們的核心區別與加法操作類似,主要體現在是否修改原張量上。

a.sub(b) 方法
  • 功能:計算 a - b 的結果,但不會修改原張量 a,而是返回一個新的張量來存儲計算結果。
  • 特點:屬于「非原地操作」(non-inplace operation),原張量的數據保持不變。

代碼示例

import torcha = torch.tensor([4, 5, 6])
b = torch.tensor([1, 2, 3])# 使用 a.sub(b)
result = a.sub(b)print("原張量 a:", a)    # 原張量 a 未被修改
print("計算結果 result:", result)

運行結果

原張量 a: tensor([4, 5, 6])
計算結果 result: tensor([3, 3, 3])
a.sub_(b) 方法
  • 功能:同樣計算 a - b 的結果,但會直接修改原張量 a,將結果存儲在 a 中,不會創建新張量。
  • 特點:屬于「原地操作」(inplace operation),方法名末尾的下劃線 _ 是 PyTorch 中標記原地操作的約定。

代碼示例

import torcha = torch.tensor([4, 5, 6])
b = torch.tensor([1, 2, 3])# 使用 a.sub_(b)
a.sub_(b)  # 直接修改原張量 aprint("修改后的張量 a:", a)  # 原張量 a 已被更新

運行結果

修改后的張量 a: tensor([3, 3, 3])
核心區別
方法操作類型對原張量 a 的影響返回值
a.sub(b)非原地操作不修改,保持原值新張量(存儲 a - b 的結果)
a.sub_(b)原地操作直接修改 a,使其等于 a - b修改后的 a(與原張量是同一個對象)
使用建議
  • 非原地操作(a.sub(b))不會改變原始數據,適合需要保留原始張量的場景,且在自動求導中更安全。
  • 原地操作(a.sub_(b))節省內存空間,但會修改原始數據,在使用時需注意后續數據被覆蓋的風險,尤其在構建計算圖時需謹慎使用。

2.3 乘法運算

函數形式torch.mul(input, other, out=None) 哈達瑪積,非矩陣乘法

a.mul(b)a.mul_(b)同2.1-2.2的加減法操作,不作展開講解。

  • 參數解析:與加法類似,實現元素級乘法(不是矩陣乘法)

計算原理
乘法運算對兩個張量的對應元素進行相乘(元素級乘法,element-wise multiplication)。

  • 若為兩個張量相乘:result[i][j] = input[i][j] * other[i][j]
  • 若為張量與標量相乘:result[i][j] = input[i][j] * scalar

手算示例

張量 a: [[1, 2],[3, 4]]
張量 b: [[5, 6],[7, 8]]
a * b 的結果:
[[1×5, 2×6],[3×7, 4×8]] = [[5, 12], [21, 32]]

代碼示例

# 乘法運算(元素級)
print("a * b =", a * b)
print("torch.mul(a, b) =", torch.mul(a, b))
print("a * 3 =", a * 3)

運行結果

a * b = tensor([ 4., 10., 18.])
torch.mul(a, b) = tensor([ 4., 10., 18.])
a * 3 = tensor([3., 6., 9.])

結果分析:這里的乘法是哈達瑪積元素級乘法(element-wise multiplication),即兩個張量對應位置的元素相乘,而不是線性代數中的矩陣乘法。

2.4 除法運算

函數形式torch.div(input, other, out=None)

a.div(b)a.div_(b)同2.1-2.2的加減法操作,不作展開講解。

  • 參數解析:實現 input / other 的元素級除法運算

計算原理
除法運算對兩個張量的對應元素進行相除。

  • 若為兩個張量相除:result[i][j] = input[i][j] / other[i][j]
  • 若為張量與標量相除:result[i][j] = input[i][j] / scalar

手算示例

張量 a: [[1, 2],[3, 4]]
張量 b: [[5, 6],[7, 8]]
a / b 的結果:
[[1/5, 2/6],[3/7, 4/8]] = [[0.2, 0.333...], [0.428..., 0.5]]

代碼示例

# 除法運算
print("a / b =", a / b)
print("torch.div(a, b) =", torch.div(a, b))
print("b / 2 =", b / 2)

運行結果

a / b = tensor([0.2500, 0.4000, 0.5000])
torch.div(a, b) = tensor([0.2500, 0.4000, 0.5000])
b / 2 = tensor([2., 2.5, 3.])

3 矩陣運算

矩陣運算在深度學習中應用廣泛,尤其是在全連接層和卷積層中。PyTorch 提供了多種矩陣運算函數。

3.1 矩陣乘法

二維矩陣乘法運算操作包括:torch.mm()torch.matmul()@,不再有上面說到的類似a.add_()的方法

函數形式torch.matmul(input, other, out=None)

  • 參數解析
    • input:第一個輸入張量(可以是1D或更高維)
    • other:第二個輸入張量
    • 對于2D張量,執行常規的矩陣乘法
    • 對于1D張量,執行點積運算

計算原理
矩陣乘法遵循線性代數中的矩陣乘法規則。對于形狀為 (m, n) 的矩陣 A 和形狀為 (n, p) 的矩陣 B,結果矩陣 C 的形狀為 (m, p),其中每個元素 C[i][j]A 的第 i 行與 B 的第 j 列的點積:

C[i][j] = A[i][0]×B[0][j] + A[i][1]×B[1][j] + ... + A[i][n-1]×B[n-1][j]

手算示例

矩陣 A: [[1, 2],[3, 4]]
矩陣 B: [[5, 6],[7, 8]]
A × B 的結果:
[[1×5 + 2×7, 1×6 + 2×8],[3×5 + 4×7, 3×6 + 4×8]
] = [[19, 22], [43, 50]]

代碼示例

# 創建兩個矩陣
mat1 = torch.tensor([[1, 2], [3, 4]])
mat2 = torch.tensor([[5, 6], [7, 8]])print("矩陣1:\n", mat1)
print("矩陣2:\n", mat2)# 方法1: 使用torch.matmul()
product1 = torch.matmul(mat1, mat2)
print("\n使用torch.matmul()的結果:\n", product1)# 方法2: 使用@運算符
product2 = mat1 @ mat2
print("\n使用@運算符的結果:\n", product2)# 方法3: 使用mm()方法(僅適用于2D張量)
product3 = mat1.mm(mat2)
print("\n使用mm()方法的結果:\n", product3)# 1D張量的點積
vec1 = torch.tensor([1, 2, 3])
vec2 = torch.tensor([4, 5, 6])
print("\n向量點積:", torch.matmul(vec1, vec2))

運行結果

矩陣1:tensor([[1, 2],[3, 4]])
矩陣2:tensor([[5, 6],[7, 8]])使用torch.matmul()的結果:tensor([[19, 22],[43, 50]])使用@運算符的結果:tensor([[19, 22],[43, 50]])使用mm()方法的結果:tensor([[19, 22],[43, 50]])向量點積: tensor(32)

結果分析:矩陣乘法遵循線性代數規則,對于矩陣 mat1(形狀為 2×2)和 mat2(形狀為 2×2),結果是一個 2×2 的矩陣,其中每個元素 (i,j)mat1 的第 i 行與 mat2 的第 j 列的點積。

3.2 高維張量的矩陣乘法

**對于高維(Tensor(dim>2))矩陣乘法運算:**定義其矩陣乘法僅在最后的兩個維度上,要求前面的維度必須保持一致,就像矩陣的索引一樣并且運算操只有torch.matmul()

對于高維張量(維度 > 2),torch.matmul() 會將最后兩個維度視為矩陣維度進行運算:

# 創建3D張量(可以理解為2個2×3的矩陣)
tensor3d = torch.tensor([[[1, 2, 3], [4, 5, 6]],[[7, 8, 9], [10, 11, 12]]
])# 創建另一個3D張量(2個3×2的矩陣)
tensor3d_2 = torch.tensor([[[1, 2], [3, 4], [5, 6]],[[7, 8], [9, 10], [11, 12]]
])print("3D張量1形狀:", tensor3d.shape)
print("3D張量2形狀:", tensor3d_2.shape)# 高維矩陣乘法
result = torch.matmul(tensor3d, tensor3d_2)
print("\n乘法結果形狀:", result.shape)
print("乘法結果:\n", result)

運行結果

3D張量1形狀: torch.Size([2, 2, 3])
3D張量2形狀: torch.Size([2, 3, 2])乘法結果形狀: torch.Size([2, 2, 2])
乘法結果:tensor([[[ 22,  28],[ 49,  64]],[[220, 244],[301, 334]]])

結果分析:對于形狀為 (2,2,3)(2,3,2) 的兩個3D張量,矩陣乘法會對每個對應的2D矩陣(共2對)進行運算,結果形狀為 (2,2,2)

3.3 矩陣轉置

函數形式torch.t(input)input.t()

  • 功能:返回張量的轉置,僅適用于1D或2D張量

計算原理
矩陣轉置將原矩陣的行變為列,列變為行。對于形狀為 (m, n) 的矩陣,轉置后形狀變為 (n, m),其中 result[i][j] = input[j][i]

手算示例

原始矩陣: [[1, 2, 3],[4, 5, 6]]
轉置后:    [[1, 4],[2, 5],[3, 6]]

代碼示例

mat = torch.tensor([[1, 2, 3], [4, 5, 6]])
print("原始矩陣:\n", mat)
print("原始形狀:", mat.shape)# 轉置操作
transposed = mat.t()
print("\n轉置矩陣:\n", transposed)
print("轉置形狀:", transposed.shape)

運行結果

原始矩陣:tensor([[1, 2, 3],[4, 5, 6]])
原始形狀: torch.Size([2, 3])轉置矩陣:tensor([[1, 4],[2, 5],[3, 6]])
轉置形狀: torch.Size([3, 2])

結果分析:矩陣轉置將原矩陣的行變為列,列變為行,形狀從 (2,3) 變為 (3,2)

4 廣播機制(Broadcasting)

廣播是 PyTorch 中一種自動擴展張量形狀的機制,使得不同形狀的張量可以進行算術運算。這是一個非常重要的概念,能簡化代碼并提高效率。

4.1 廣播的基本規則

  1. 如果兩個張量的維度數量不同,維度較少的張量會在前面添加新維度(大小為1)
  2. 如果兩個張量在某個維度上的大小不同,但其中一個為1,則會將大小為1的維度擴展為另一個張量的大小
  3. 如果兩個張量在某個維度上的大小都大于1且不相等,則無法廣播,會拋出錯誤

代碼示例

# 示例1:標量與張量的廣播
a = torch.tensor([1, 2, 3])
b = 2
print("a * b =", a * b)# 示例2:不同形狀張量的廣播
c = torch.tensor([[1], [2], [3]])  # 形狀 (3,1)
d = torch.tensor([4, 5, 6])       # 形狀 (3,)
print("\nc的形狀:", c.shape)
print("d的形狀:", d.shape)
print("c + d的結果:\n", c + d)
print("c + d的形狀:", (c + d).shape)# 示例3:更復雜的廣播
e = torch.ones((2, 3))  # 形狀 (2,3)
f = torch.tensor([[1], [2]])  # 形狀 (2,1)
print("\ne + f的結果:\n", e + f)

運行結果

a * b = tensor([2, 4, 6])c的形狀: torch.Size([3, 1])
d的形狀: torch.Size([3])
c + d的結果:tensor([[5, 6, 7],[6, 7, 8],[7, 8, 9]])
c + d的形狀: torch.Size([3, 3])e + f的結果:tensor([[2., 2., 2.],[3., 3., 3.]])

結果分析:在示例2中,c 形狀為 (3,1)d 形狀為 (3,),廣播后都變為 (3,3) 形狀,然后進行元素級加法。廣播機制避免了我們手動擴展張量形狀,使代碼更簡潔。

5 統計運算

PyTorch 提供了豐富的統計函數,用于計算張量的均值、總和、最大值、最小值等統計量。

5.1 求和運算

函數形式torch.sum(input, dim=None, keepdim=False, out=None)

  • 參數解析
    • input:輸入張量
    • dim:可選參數,指定求和的維度,不指定則對所有元素求和
    • keepdim:布爾值,是否保持原張量的維度,默認為 False

計算原理
求和運算計算張量在指定維度上所有元素的總和。

  • 對整個張量求和:result = sum(input[i][j] for all i,j)
  • 按行求和(dim=1):result[i] = sum(input[i][j] for all j)
  • 按列求和(dim=0):result[j] = sum(input[i][j] for all i)

手算示例

張量: [[1, 2, 3],[4, 5, 6]]
所有元素的和: 1+2+3+4+5+6 = 21
按行求和: [1+2+3, 4+5+6] = [6, 15]
按列求和: [1+4, 2+5, 3+6] = [5, 7, 9]

代碼示例

tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
print("張量:\n", tensor)# 對所有元素求和
print("\n所有元素的和:", tensor.sum())# 按行求和(dim=1)
row_sum = tensor.sum(dim=1)
print("按行求和:", row_sum)
print("按行求和的形狀:", row_sum.shape)# 按列求和(dim=0)并保持維度
col_sum = tensor.sum(dim=0, keepdim=True)
print("\n按列求和(保持維度):\n", col_sum)
print("形狀:", col_sum.shape)

運行結果

張量:tensor([[1., 2., 3.],[4., 5., 6.]])所有元素的和: tensor(21.)
按行求和: tensor([ 6., 15.])
按行求和的形狀: torch.Size([2])按列求和(保持維度):tensor([[5., 7., 9.]])
形狀: torch.Size([1, 3])

結果分析dim=0 表示沿著第一個維度(行方向)求和,得到每列的總和;dim=1 表示沿著第二個維度(列方向)求和,得到每行的總和。keepdim=True 保持了原有的二維結構。

5.2 均值運算

函數形式torch.mean(input, dim=None, keepdim=False, dtype=None, out=None)

  • 參數解析:與 torch.sum() 類似,計算指定維度的均值

計算原理
均值運算計算張量在指定維度上所有元素的平均值,即總和除以元素個數。

  • 整體均值:result = sum(all elements) / number of elements
  • 按行均值:result[i] = sum(row i) / number of elements in row i

代碼示例

# 計算均值
print("所有元素的均值:", tensor.mean())
print("按列求均值:", tensor.mean(dim=0))
print("按行求均值:", tensor.mean(dim=1))

運行結果

所有元素的均值: tensor(3.5000)
按列求均值: tensor([2.5000, 3.5000, 4.5000])
按行求均值: tensor([2., 5.])

5.3 最大值和最小值

函數形式torch.max(input, dim=None, keepdim=False, out=None)torch.min(...)

  • 參數解析
    • 不指定 dim 時,返回張量中的最大值/最小值
    • 指定 dim 時,返回一個元組 (values, indices),包含最大值/最小值及其索引

代碼示例

# 最大值運算
print("所有元素的最大值:", tensor.max())# 按行求最大值
row_max = tensor.max(dim=1)
print("\n按行求最大值:")
print("最大值:", row_max.values)
print("最大值索引:", row_max.indices)# 最小值運算
print("\n所有元素的最小值:", tensor.min())
print("按列求最小值:", tensor.min(dim=0).values)

運行結果

所有元素的最大值: tensor(6.)按行求最大值:
最大值: tensor([3., 6.])
最大值索引: tensor([2, 2])所有元素的最小值: tensor(1.)
按列求最小值: tensor([1., 2., 3.])

結果分析torch.max(dim=1) 返回每行的最大值及其在該行中的索引位置,對于第一行 [1., 2., 3.],最大值是 3.,位于索引 2 處。

5.4 累加運算

函數形式torch.cumsum(input, dim, out=None)

  • 功能:計算指定維度上的累積和

代碼示例

# 累積和
print("按行累積和:\n", tensor.cumsum(dim=1))

運行結果

按行累積和:tensor([[ 1.,  3.,  6.],[ 4.,  9., 15.]])

結果分析:累積和是指每個位置的值等于該位置之前(包括自身)所有元素的和。例如第一行的計算過程是 1, 1+2=3, 3+3=6

6 張量的其他常用運算

6.1 冪運算

6.1.1 通用計算

函數形式torch.pow(input, exponent, out=None)

a.pow(b)a.pow_(b) 邏輯同2.1-2.2的加減法操作,不作展開講解。

  • 功能:計算張量的指數冪,支持元素級運算

代碼示例

a = torch.tensor([1, 2, 3])# 計算a的平方
print("a的平方:", torch.pow(a, 2))
print("a的平方(使用運算符):", a **2)# 計算a的3次方
print("a的3次方:", torch.pow(a, 3))

運行結果

a的平方: tensor([1, 4, 9])
a的平方(使用運算符): tensor([1, 4, 9])
a的3次方: tensor([ 1,  8, 27])
6.1.2 底數為e的冪運算

a.exp(b)a.exp_(b)邏輯同2.1-2.2的加減法操作,不作展開講解。

代碼示例:

import torch# 定義指數張量 x
x = torch.tensor([0, 1, 2], dtype=torch.float32)# 計算 e^x(元素級)
result = torch.exp(x)  # 等價于 x.exp()
print(result)  # 輸出:tensor([1.0000, 2.7183, 7.3891])

6.2 平方根

函數形式torch.sqrt(input, out=None)

a.sqrt_(b)邏輯同2.1-2.2的加減法操作,不作展開講解。

  • 功能:計算張量每個元素的平方根

代碼示例

b = torch.tensor([4.0, 9.0, 16.0])
print("b的平方根:", torch.sqrt(b))

運行結果

b的平方根: tensor([2., 3., 4.])

6.3 指數和對數運算

函數形式torch.exp(input, out=None)torch.log(input, out=None)

  • 功能:分別計算自然指數和自然對數
  • 底數為2: torch.log2(a)
  • 底數為e: torch.log(a)torch.log_(a)
  • 底數為10: torch.log10(a)

代碼示例

import numpy as npc = torch.tensor([1.0, 2.0, 3.0])# 指數運算 e^x
print("e^c:", torch.exp(c))# 對數運算 ln(x)
d = torch.tensor([1.0, np.e, np.e**2])
print("ln(d):", torch.log(d))

運行結果

e^c: tensor([ 2.7183,  7.3891, 20.0855])
ln(d): tensor([0.0000, 1.0000, 2.0000])

7 自動求導(Autograd)與張量計算

PyTorch 的自動求導機制是實現神經網絡反向傳播的核心,它能自動計算張量運算的梯度。

7.1 基本概念

  • 計算圖:PyTorch 會記錄所有對張量的操作,構建一個計算圖
  • 反向傳播:通過計算圖從輸出反向傳播到輸入,計算梯度
  • requires_grad:張量的一個屬性,設為 True 時會追蹤該張量的所有操作

7.2 自動求導示例

# 創建需要計算梯度的張量
x = torch.tensor(2.0, requires_grad=True)
print("x =", x)
print("x是否需要計算梯度:", x.requires_grad)# 定義一個函數 y = x^2 + 3x + 1
y = x**2 + 3*x + 1
print("\ny =", y)
print("y的梯度函數:", y.grad_fn)  # 顯示y是如何從x計算得到的# 計算y對x的導數
y.backward()# 查看導數結果(dy/dx = 2x + 3)
print("\ndy/dx 在x=2處的值:", x.grad)  # 理論值應為 2*2 + 3 = 7

運行結果

x = tensor(2., requires_grad=True)
x是否需要計算梯度: Truey = tensor(11., grad_fn=<AddBackward0>)
y的梯度函數: <AddBackward0 object at 0x7f8a2c3d3d30>dy/dx 在x=2處的值: tensor(7.)

結果分析:當我們設置 requires_grad=True 時,PyTorch 會追蹤該張量的所有操作。調用 y.backward() 會觸發反向傳播,計算 y 對所有需要梯度的張量(這里是 x)的導數,并將結果存儲在張量的 .grad 屬性中。

7.3 多變量函數的求導

# 創建兩個需要計算梯度的張量
x = torch.tensor(1.0, requires_grad=True)
y = torch.tensor(2.0, requires_grad=True)# 定義函數 z = x^2 + 2xy + y^3
z = x**2 + 2*x*y + y**3
print("z =", z)# 計算偏導數
z.backward()# 查看結果(dz/dx = 2x + 2y, dz/dy = 2x + 3y^2)
print("\ndz/dx 在(1, 2)處的值:", x.grad)  # 理論值: 2*1 + 2*2 = 6
print("dz/dy 在(1, 2)處的值:", y.grad)  # 理論值: 2*1 + 3*2^2 = 14

運行結果

z = tensor(13., grad_fn=<AddBackward0>)dz/dx 在(1, 2)處的值: tensor(6.)
dz/dy 在(1, 2)處的值: tensor(14.)

8 GPU 加速的張量計算

PyTorch 最大的優勢之一是能夠利用 GPU 進行加速計算,對于大規模張量運算,GPU 可以顯著提高計算速度。

8.1 張量的設備遷移

函數形式torch.to(device)tensor.cuda() / tensor.cpu()

  • 功能:將張量從 CPU 遷移到 GPU 或從 GPU 遷移到 CPU

代碼示例

# 檢查是否有可用的GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("使用的設備:", device)# 創建一個大張量
large_tensor = torch.randn(1000, 1000)
print("原始張量設備:", large_tensor.device)# 將張量遷移到GPU(如果可用)
large_tensor_gpu = large_tensor.to(device)
print("遷移后張量設備:", large_tensor_gpu.device)# 在GPU上進行計算
result_gpu = torch.matmul(large_tensor_gpu, large_tensor_gpu)
print("GPU計算結果設備:", result_gpu.device)# 將結果遷移回CPU
result_cpu = result_gpu.to("cpu")
print("CPU上的結果設備:", result_cpu.device)

運行結果(如果有GPU):

使用的設備: cuda
原始張量設備: cpu
遷移后張量設備: cuda:0
GPU計算結果設備: cuda:0
CPU上的結果設備: cpu

結果分析:通過 to(device) 方法可以將張量在 CPU 和 GPU 之間遷移。所有計算會在張量所在的設備上進行,因此對于需要頻繁操作的張量,最好將它們放在同一個設備上,避免頻繁的設備間數據傳輸。

一是能夠利用 GPU 進行加速計算,對于大規模張量運算,GPU 可以顯著提高計算速度。

8.1 張量的設備遷移

函數形式torch.to(device)tensor.cuda() / tensor.cpu()

  • 功能:將張量從 CPU 遷移到 GPU 或從 GPU 遷移到 CPU

代碼示例

# 檢查是否有可用的GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("使用的設備:", device)# 創建一個大張量
large_tensor = torch.randn(1000, 1000)
print("原始張量設備:", large_tensor.device)# 將張量遷移到GPU(如果可用)
large_tensor_gpu = large_tensor.to(device)
print("遷移后張量設備:", large_tensor_gpu.device)# 在GPU上進行計算
result_gpu = torch.matmul(large_tensor_gpu, large_tensor_gpu)
print("GPU計算結果設備:", result_gpu.device)# 將結果遷移回CPU
result_cpu = result_gpu.to("cpu")
print("CPU上的結果設備:", result_cpu.device)

運行結果(如果有GPU):

使用的設備: cuda
原始張量設備: cpu
遷移后張量設備: cuda:0
GPU計算結果設備: cuda:0
CPU上的結果設備: cpu

結果分析:通過 to(device) 方法可以將張量在 CPU 和 GPU 之間遷移。所有計算會在張量所在的設備上進行,因此對于需要頻繁操作的張量,最好將它們放在同一個設備上,避免頻繁的設備間數據傳輸。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91614.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91614.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91614.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

云原生聯調利器:Telepresence實戰

Telepresence在云原生聯調中的應用&#xff1a;本地服務直連K8s集群實戰在云原生開發中&#xff0c;調試和測試服務常常需要本地環境與遠程Kubernetes&#xff08;K8s&#xff09;集群無縫集成。Telepresence是一個開源工具&#xff0c;它允許開發者將本地服務“注入”到K8s集群…

瀏覽器【詳解】requestIdleCallback(瀏覽器空閑時執行)

簡介requestIdleCallback 是瀏覽器的一個 API&#xff0c;用于在瀏覽器空閑時間執行低優先級任務&#xff0c;避免阻塞主線程&#xff0c;提升頁面性能和響應速度。 當瀏覽器完成了關鍵任務&#xff08;如渲染、布局、用戶交互處理&#xff09;且暫時沒有更高優先級的工作時&am…

STP技術

一、環路的危害1.現象鏈路指示燈快速閃爍MAC表震蕩&#xff1a;交換機頻繁修改MAC地址表 → 轉發失效。2.環路危害造成的影響鏈路堵塞主機操作系統響應遲緩二層交換機管理緩慢沖擊網關設備的CPU三、STP的作用1.STP基本原理STP即生成樹協議&#xff0c;它通過阻斷冗余鏈路來消除…

RAGFLOW~knowledge graph

start 為了增強多跳問答&#xff0c;RAGFlow在數據提取和索引之間增加了一個知識圖譜構建步驟&#xff0c;如下面所示。這一步驟會從您指定的分塊方法生成的現有塊中創建額外的塊。 從v0.16.0版本開始&#xff0c;RAGFlow支持在知識庫上構建知識圖譜&#xff0c;允許你在知識庫…

機器學習【二】KNN

KNN算法是一種基于實例的惰性學習算法&#xff0c;其核心思想是通過"多數投票"機制進行分類決策。算法流程包括數據準備&#xff08;需歸一化處理&#xff09;、距離計算&#xff08;常用歐氏距離&#xff09;、選擇K值&#xff08;通過交叉驗證確定&#xff09;和決…

preloader

patch調試串口115200--- a/platform/ac8257/default.makb/platform/ac8257/default.mak-40,7 40,7 CFG_USB_DOWNLOAD :1CFG_FUNCTION_PICACHU_SUPPORT :1CFG_PMT_SUPPORT :0CFG_UART_COMMON :1 -CFG_LOG_BAUDRATE :921600 CFG_LOG_BAUDRATE :115200CFG_EVB_UART_CLOCK :260000…

Linux基礎(三)——Bash基礎

1、Bash基礎1.1 Bash簡介從前邊操作系統的組成介紹中&#xff0c;我們可以知道操作系統為上層用戶提供的與內核進行交互的接口稱為shell&#xff0c;其在系統中的位置如下圖所示&#xff0c;shell作為內核和用戶之間的中介&#xff0c;接收用戶發送的指令&#xff0c;將其解析為…

Python 元編程實戰:動態屬性與數據結構轉換技巧

在處理復雜嵌套的 JSON 數據源時&#xff0c;我們常面臨訪問不便、結構不靈活、字段關聯性差等問題。本文將以 O’Reilly 為 OSCON 2014 提供的 JSON 數據源為例&#xff0c;系統講解如何通過 動態屬性轉換、對象封裝、數據庫映射與特性&#xff08;property&#xff09;機制&a…

Android-側邊導航欄的使用

在學習之前&#xff0c;我們先得知道側邊導航欄是什么&#xff1f;它是一個 可以讓內容從屏幕邊緣滑出的布局容器&#xff0c;由安卓官方提供&#xff0c;用于創建側邊菜單&#xff0c;通常搭配 NavigationView 使用&#xff1b;添加依賴&#xff1a;在app下的build.gradle中添…

lesson30:Python迭代三劍客:可迭代對象、迭代器與生成器深度解析

目錄 一、可迭代對象&#xff1a;迭代的起點 可迭代對象的本質特征 可迭代對象的工作原理 自定義可迭代對象 二、迭代器&#xff1a;狀態化的迭代工具 迭代器協議與核心方法 迭代器的狀態管理 內置迭代器的應用 三、生成器&#xff1a;簡潔高效的迭代器 生成器函數&a…

實時語音流分段識別技術解析:基于WebRTC VAD的智能分割策略

引言 在現代語音識別應用中&#xff0c;實時處理音頻流是一項關鍵技術挑戰。不同于傳統的文件式語音識別&#xff0c;流式處理需要面對音頻數據的不確定性、網絡延遲以及實時性要求等問題。本文將深入解析一個基于WebRTC VAD&#xff08;Voice Activity Detection&#xff09;…

word中rtf格式介紹

RTF&#xff08;Rich Text Format&#xff0c;富文本格式&#xff09;是一種由微軟開發的跨平臺文檔文件格式&#xff0c;用于在不同應用程序和操作系統之間交換格式化文本。以下是對RTF格式的簡要說明&#xff1a; RTF格式特點 跨平臺兼容性&#xff1a;RTF文件可以在多種文字…

Springboot 配置 doris 連接

Springboot 配置 doris 連接 一. 使用 druid 連接池 因為 Doris 的前端&#xff08;FE&#xff09;兼容了 MySQL 協議&#xff0c;可以像連 MySQL 一樣連 Doris。這是 Doris 的一個核心設計特性&#xff0c;目的是方便接入、簡化生態兼容。 首先需要引入 pom 依賴:<dependen…

Linux 系統啟動與 GRUB2 核心操作指南

Linux 系統啟動與 GRUB2 核心操作指南 Linux 系統的啟動過程是一個環環相扣的鏈條&#xff0c;從硬件自檢到用戶登錄&#xff0c;每一步都依賴關鍵組件的協作。其中&#xff0c;GRUB2 引導器和systemd 進程是核心樞紐&#xff0c;而運行級別則決定了系統的啟動狀態。以下是系統…

供應鏈分銷代發源碼:一站式打通供應商供貨、平臺定價、經銷商批發及零售環節

在當前復雜的市場環境中&#xff0c;供應鏈管理成為企業發展的關鍵。尤其對于電商平臺來說&#xff0c;高效、精準的供應鏈管理不僅能提升運營效率&#xff0c;還能增強市場競爭力。為了應對日益復雜的供應鏈挑戰&#xff0c;核貨寶供應鏈分銷代發系統應運而生&#xff0c;旨在…

機器學習、深度學習與數據挖掘:核心技術差異、應用場景與工程實踐指南

技術原理與核心概念數據挖掘作為知識發現的關鍵技術&#xff0c;其核心在于通過算法自動探索數據中的潛在模式。關聯規則挖掘可以發現項目之間的有趣關聯&#xff0c;如經典的"啤酒與尿布"案例&#xff1b;聚類分析能夠將相似對象自動分組&#xff0c;常用于客戶細分…

《C++初階之STL》【stack/queue/priority_queue容器適配器:詳解 + 實現】(附加:deque容器介紹)

【stack/queue/priority_queue容器適配器&#xff1a;詳解 實現】目錄前言&#xff1a;------------標準接口介紹------------一、棧&#xff1a;stack標準模板庫中的stack容器適配器是什么樣的呢&#xff1f;1. 棧的基本操作std::stack::topstd::stack::pushstd::stack::pop2…

Thymeleaf 模板引擎原理

Thymeleaf 的模板文件&#xff0c;本質上是標準的 HTML 文件&#xff0c;只是“加了標記&#xff08; th&#xff1a;&#xff09;的屬性”&#xff0c;讓模板引擎在服務端渲染時能 識別并處理 這些屬性&#xff0c;從而完成數據&#xff08;model&#xff09; 的填充。<!DO…

5、生產Redis高并發分布式鎖實戰

一、核心問題與解決方案 問題本質 #mermaid-svg-W1SnVWZe1AotTtDy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-W1SnVWZe1AotTtDy .error-icon{fill:#552222;}#mermaid-svg-W1SnVWZe1AotTtDy .error-text{fill:#5…

CS231n-2017 Lecture8深度學習框架筆記

深度學習硬件&#xff1a;CPU:CPU有數個核心&#xff0c;每個核心可以獨立工作&#xff0c;同時進行多個線程&#xff0c;內存與系統共享GPU&#xff1a;GPU有上千個核心&#xff0c;但每個核心運行速度很慢&#xff0c;適合并行做類似的工作&#xff0c;不能獨立工作&#xff…