動手學深度學習-學習筆記【二】(基礎知識)

文章目錄

  • 1、概述
  • 2、課程學習
    • 2.1、深度學習介紹
    • 2.2、安裝
    • 2.3、數據操作
    • 2.4、數據預處理
    • 2.5、線性代數
    • 2.6、微積分
    • 2.7、自動微分
    • 2.8、概率
      • 2.8.1、基本概率論
      • 2.8.2、處理多個隨機變量
      • 2.8.3、期望和方差
    • 2.9、查閱文檔

1、概述

本篇博客用來記錄我學習深度學習的學習筆記,本篇博客主要深度學習所需的一些預備知識,
包括數據操作,線性代數,微積分,概率論等

在這里插入圖片描述


2、課程學習

2.1、深度學習介紹

在這里插入圖片描述

深度學習是機器學習的一種

深度學習在廣告推薦中的案例

在這里插入圖片描述


在這里插入圖片描述


在這里插入圖片描述


2.2、安裝

在這里插入圖片描述

Conda 是一個開源的 軟件包管理系統 和 環境管理系統,專為數據科學、機器學習、生物信息學等領域設計。它允許用戶高效地安裝、管理和切換多個版本的軟件包及其依賴項,同時支持多種編程語言(如 Python、R、Ruby、Java 等)和跨平臺(Linux、macOS、Windows)。
Jupyter Notebook 是一個功能強大的交互式計算工具,廣泛應用于數據科學、教育、研究和開發領域。作用包括:數據分析與可視化,機器學習與建模,教育與教學,科研與報告,合作與共享
D2L 是一個面向中文讀者的深度學習開源項目,由 李沐博士 等人開發,旨在通過 可運行代碼、數學公式和實踐案例 的結合,幫助用戶系統性地學習深度學習。
PyTorch 是一個開源的深度學習框架,由 Facebook 的 AI 研究團隊開發。它基于 Python 語言,支持動態計算圖(Dynamic Computation Graph),廣泛應用于計算機視覺、自然語言處理等領域。
TorchVision 是 PyTorch 生態中專注于 計算機視覺 的核心庫


2.3、數據操作

N 維數組樣例
N維數組是機器學習和神經網絡的主要數據結構。

張量表示一個由數值組成的數組,這個數組可能有多個維度。
具有一個軸的張量對應數學上的向量(vector)
具有兩個軸的張量對應數學上的矩陣(matrix)

具有兩個軸以上的張量沒有特殊的數學名稱。

N 維數組樣例
N 維數組是機器學習和神經網絡的主要數據結構

在這里插入圖片描述

在這里插入圖片描述

創建數組的前提條件

  • 形狀:例如 3 * 4 矩陣
  • 每個元素的數據類型:例如 32 位浮點數
  • 每個元素的值:例如全是0,或者隨機數

在這里插入圖片描述

訪問元素

在這里插入圖片描述


首先,我們可以使用 arange 創建一個行向量 x
這個行向量包含以0開始的前12個整數,它們默認創建為整數。
也可指定創建類型為浮點數。張量中的每個值都稱為張量的 元素(element)

import torchA = torch.arange(5, dtype=torch.float32)
print(A)   # tensor([0., 1., 2., 3., 4.])

我們導入torch。請注意,雖然它被稱為PyTorch,但是代碼中使用torch而不是pytorch


可以通過張量的shape屬性來訪問張量(沿每個軸的長度)的形狀

import torchA = torch.arange(5, dtype=torch.float32)
print(A)        # tensor([0., 1., 2., 3., 4.])
print(A.shape)  # torch.Size([5])

如果只想知道張量中元素的總數,即形狀的所有元素乘積,可以檢查它的大小(size)

import torchA = torch.arange(5, dtype=torch.float32)
print(A)          # tensor([0., 1., 2., 3., 4.])
print(A.numel())  # 5

改變一個張量的形狀而不改變元素數量和元素值,我們可以調用 reshape 函數

import torchA = torch.arange(20, dtype=torch.float32).reshape(5, 4)
print(A)         
# tensor([[ 0.,  1.,  2.,  3.],
#         [ 4.,  5.,  6.,  7.],
#         [ 8.,  9., 10., 11.],
#         [12., 13., 14., 15.],
#         [16., 17., 18., 19.]])

使用全0全1,其他常量或者從特定分布中隨機采樣的數字

在這里插入圖片描述

通過提供包含數值的 Python 列表(或嵌套列表)來為所需張量中的每個元素賦予確定值

在這里插入圖片描述

操作符運算
常見的標準算術運算符(+,-,*,/,**)都可以按升級為按照元素運算

在這里插入圖片描述

我們也可以把多個張量連結在一起

dim=0 表示將 X 和 Y 按照行進行合并
dim=1 表示將 X 和 Y 按照列進行合并

在這里插入圖片描述


我們也可以通過邏輯運算符構建二元張量
在這里插入圖片描述
對張量中的所有元素進行求和會產生一個只有一個元素的張量。
在這里插入圖片描述

廣播機制

即使形狀不同,依然可以進行張量的加減法

廣播(Broadcasting)是 PyTorch 中一種允許不同形狀張量進行逐元素運算的機制。
核心思想是:自動擴展較小的張量,使其形狀與較大的張量兼容,從而避免手動復制數據,節省內存并簡化代碼。

即使形狀不同,我們任然可以通過調用廣播機制來執行按元素操作

在這里插入圖片描述

特殊元素獲取

可以使用 X[-1] 取出最后一行
使用 X[1:3] 取出第二行和第三行

注意:
行和列都是從 0 開始

在這里插入圖片描述

除讀取外,我們還可以通過指定索引來將元素寫入矩陣。

在這里插入圖片描述

按照區域賦值
為多個元素賦值相同的值,我們只需要索引所有元素,然后為他們賦值
在這里插入圖片描述

python 使用 id()獲取變量的地址(類似 C 中的指針)
在 PyTorch 中,id() 是 Python 內置函數,用于返回對象的 唯一標識符(即內存地址)。

運行一些操作可能會導致為新結果分配內存
在這里插入圖片描述

執行原地操作

在這里插入圖片描述

其中上圖第二個樣例中,Z 的內存沒有發生變化,前后是一致的

如果在后續計算中,沒有重復使用 X,我們也可以使用 X[:] = X + YX += Y 來減少操作的內存開銷

在這里插入圖片描述

numPytorch 使用不一樣的數據類型

在這里插入圖片描述

numPytorch 可以互相轉換

torch 轉化為 NumPy 張量
在這里插入圖片描述

將大小為 1 的張量轉換為 Python 標量

在這里插入圖片描述


2.4、數據預處理

為了能用深度學習來解決現實世界的問題,我們經常從預處理原始數據開始, 而不是從那些準備好的張量格式數據開始。

讀取數據集
我們首先創建一個人工數據集,并存儲在CSV(逗號分隔值)文件 ../data/house_tiny.csv

要從創建的CSV文件中加載原始數據集,我們導入pandas包并調用read_csv函數。

import os
import pandas as pdos.makedirs(os.path.join('..', 'data'), exist_ok=True)
data_file = os.path.join('..', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:f.write('NumRooms,Alley,Price\n')  # 列名f.write('NA,Pave,127500\n')  # 每行表示一個數據樣本f.write('2,NA,106000\n')f.write('4,NA,178100\n')f.write('NA,NA,140000\n')data = pd.read_csv(data_file)
print(data)
#    NumRooms Alley   Price
# 0       NaN  Pave  127500
# 1       2.0   NaN  106000
# 2       4.0   NaN  178100
# 3       NaN   NaN  140000

“NaN”項代表缺失值。

處理缺失值

對于缺失值的處理,有兩種處理辦法,插值法刪除法

  • 插值法用一個替代值彌補缺失值
  • 刪除法則直接忽略缺失值。

通過位置索引iloc,我們將data分成inputsoutputs, 其中前者為data的前兩列,而后者為data的最后一列。
對于inputs中缺少的數值,我們用同一列的均值替換“NaN”項。

在這里插入圖片描述

對于inputs中的類別值或離散值,我們將“NaN”視為一個類別。 由于“巷子類型”(“Alley”)列只接受兩種類型的類別值“Pave”和“NaN”, pandas可以自動將此列轉換為兩列“Alley_Pave”和“Alley_nan”。 巷子類型為“Pave”的行會將“Alley_Pave”的值設置為1,“Alley_nan”的值設置為0。 缺少巷子類型的行會將“Alley_Pave”和“Alley_nan”分別設置為0和1。

在這里插入圖片描述

轉換為張量格式
現在inputsoutputs中的所有條目都是數值類型,它們可以轉換為張量格式。

在這里插入圖片描述


2.5、線性代數

標量
僅包含一個數值被稱為標量(scalar)

  • 確定的數值被稱為標量值
  • 不確定的符號被稱為變量

標量由只有一個元素的張量表示。

在這里插入圖片描述

向量
向量可以被視為標量值組成的列表。
這些標量值被稱為向量的元素(element)分量(component)

通過一維張量表示向量。

在這里插入圖片描述

在數學中,我們可以使用下標來引用向量的任一元素
在這里插入圖片描述
在代碼中,我們通過張量的索引來訪問任一元素。
在這里插入圖片描述

長度,維度和形狀
向量的長度通常稱為向量的維度(dimension)
在這里插入圖片描述
當用張量表示一個向量(只有一個軸)時,我們也可以通過.shape屬性訪問向量的長度。
形狀(shape)是一個元素組,列出了張量沿每個軸的長度(維數)。 對于只有一個軸的張量,形狀只有一個元素。

在這里插入圖片描述

矩陣
正如向量將標量從零階推廣到一階,矩陣將向量從一階推廣到二階。
我們可以將任意矩陣 A ∈ R m × n A \in \mathbb{R}^{m \times n} ARm×n
視為一個表格,其中每個元素 aij 屬于第 i 行,第 j
在這里插入圖片描述

當矩陣具有相同數量的行和列時,其形狀將變為正方形; 因此,它被稱為方陣(square matrix)

當調用函數來實例化張量時, 我們可以通過指定兩個分量mn來創建一個形狀為m * n的矩陣。

在這里插入圖片描述

當我們交換矩陣的行和列時,結果稱為矩陣的轉置(transpose)

在這里插入圖片描述

作為方陣的一種特殊類型,對稱矩陣(symmetric matrix)等于其轉置

在這里插入圖片描述

張量

就像向量是標量的推廣,矩陣是向量的推廣一樣,我們可以構建具有更多軸的數據結構。 張量(本小節中的“張量”指代數對象)是描述具有任意數量軸的n維數組的通用方法。

在這里插入圖片描述

張量算法的基本形式

同樣,給定具有相同形狀的任意兩個張量,任何按元素二元運算的結果都將是相同形狀的張量。
例如,將兩個相同形狀的矩陣相加,會在這兩個矩陣上執行元素加法。

在這里插入圖片描述
具體而言,兩個矩陣的按元素乘法稱為Hadamard積(Hadamard product)

在這里插入圖片描述

將張量乘以或加上一個標量不會改變張量的形狀,其中張量的每個元素都將與標量相加或相乘。

在這里插入圖片描述

降維
我們可以對任意張量進行的一個有用的操作是計算其元素的和
在代碼中,求和的函數

import torchx = torch.arange(4, dtype=torch.float32)
print(x)         # tensor([0., 1., 2., 3.])
print(x.sum())   # tensor(6.)

我們可以表示任意形狀張量的元素和。

在這里插入圖片描述

import torchA = torch.arange(20).reshape(5, 4)
print(A)
# tensor([[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11],
#         [12, 13, 14, 15],
#         [16, 17, 18, 19]])print(A.shape)  # torch.Size([5, 4])
print(A.sum())  # tensor(190)

默認情況下,調用求和函數會沿所有的軸降低張量的維度,使它變為一個標量。
我們還可以指定張量沿哪一個軸來通過求和降低維度。
以矩陣為例,為了通過求和所有行的元素來降維(軸0)

  • 可以在調用函數時指定axis=0。 由于輸入矩陣沿0軸降維以生成輸出向量,因此輸入軸0的維數在輸出形狀中消失。(只保留一行
  • 指定axis=1將通過匯總所有列的元素降維(軸1)。因此,輸入軸1的維數在輸出形狀中消失。(只保留一列
import torchA = torch.arange(20).reshape(5, 4)
print(A)
# tensor([[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11],
#         [12, 13, 14, 15],
#         [16, 17, 18, 19]])# 對所有行進行降維,只保留一行
A_sum_axis0 = A.sum(axis=0)
print(A_sum_axis0)         # tensor([40, 45, 50, 55])
print(A_sum_axis0.shape)   # torch.Size([4])# 對所有列進行降維,只保留一列
A_sum_axis1 = A.sum(axis=1)
print(A_sum_axis1)         # tensor([ 6, 22, 38, 54, 70])
print(A_sum_axis1.shape)   # torch.Size([5])

torch.Size([4]) 表示一個 一維張量(向量),其形狀(shape)為 (4,),即該張量只有一個維度,且該維度的長度為 4。
維度(Dimensions):張量的維度數由 torch.Size 中的元素個數決定。例如:

  • torch.Size([]):0 維張量(標量)。
  • torch.Size([4]):1 維張量(向量)。
  • torch.Size([2, 3]):2 維張量(矩陣)。
  • torch.Size([2, 3, 4]):3 維張量。

沿著行和列對矩陣求和(A.sum(axis=[0, 1])),等價于對矩陣的所有元素進行求和(A.sum())。

import torchA = torch.arange(20).reshape(5, 4)
print(A)
# tensor([[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11],
#         [12, 13, 14, 15],
#         [16, 17, 18, 19]])print(A.sum(axis=[0, 1]))  # tensor(190)
print(A.sum())             # tensor(190)

一個與求和相關的量是平均值(mean或average)。 我們通過將總和除以元素總數來計算平均值。

import torchA = torch.arange(20, dtype=torch.float32).reshape(5, 4)
print(A)
# tensor([[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11],
#         [12, 13, 14, 15],
#         [16, 17, 18, 19]])print(A.mean())              # tensor(9.5000)
print(A.sum() / A.numel())   # tensor(9.5000)

numel()PyTorch 中的一個方法,用于返回張量(Tensor)中 所有元素的總數(即 number of elements 的縮寫)。
它通過將張量的所有維度大小相乘,計算出總元素數量。


同樣,計算平均值的函數也可以沿指定軸降低張量的維度。

import torchA = torch.arange(20, dtype=torch.float32).reshape(5, 4)
print(A)
# tensor([[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11],
#         [12, 13, 14, 15],
#         [16, 17, 18, 19]])print(A.mean())              # tensor(9.5000)
print(A.mean(axis=0))        # tensor([ 8.,  9., 10., 11.])
print(A.mean(axis=1))        # tensor([ 1.5000,  5.5000,  9.5000, 13.5000, 17.5000])

非降維求和
有時在調用函數來計算總和或均值時保持軸數不變會很有用。

import torchA = torch.arange(20, dtype=torch.float32).reshape(5, 4)
print(A)
# tensor([[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11],
#         [12, 13, 14, 15],
#         [16, 17, 18, 19]])# 降維求和
sum_A_old = A.sum(axis=1)
print(sum_A_old)         # tensor([ 6., 22., 38., 54., 70.])
print(sum_A_old.shape)   # torch.Size([5])# 非降維求和
sum_A = A.sum(axis=1, keepdims=True)
print(sum_A)             
# tensor([[ 6.],
#         [22.],
#         [38.],
#         [54.],
#         [70.]])
print(sum_A.shape)       # torch.Size([5, 1])

如果我們想沿某個軸計算A元素的累積總和, 比如axis=0(按行計算),可以調用cumsum函數。 此函數不會沿任何軸降低輸入張量的維度。

import torchA = torch.arange(20, dtype=torch.float32).reshape(5, 4)
print(A)
# tensor([[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11],
#         [12, 13, 14, 15],
#         [16, 17, 18, 19]])print(A.cumsum(axis=0))
# tensor([[ 0.,  1.,  2.,  3.],
#         [ 4.,  6.,  8., 10.],
#         [12., 15., 18., 21.],
#         [24., 28., 32., 36.],
#         [40., 45., 50., 55.]])

點積

給定兩個向量,他們的點積是相同位置的元素乘積的和

import torchx = torch.arange(4, dtype=torch.float32)
y = torch.ones(4, dtype = torch.float32)print(x)              # tensor([0., 1., 2., 3.])
print(y)              # tensor([1., 1., 1., 1.])
print(torch.dot(x,y)) # tensor(6.)

矩陣-向量積

矩陣向量積 Ax 是一個長度為 m 的列向量, 其第 i 個元素是點積 aiTx
在這里插入圖片描述

在代碼中使用張量表示矩陣-向量積,我們使用mv函數。
當我們為矩陣A和向量x調用torch.mv(A, x)時,會執行矩陣-向量積。

import torchA = torch.arange(20, dtype=torch.float32).reshape(5, 4)
x = torch.arange(4, dtype=torch.float32)print(A)
# tensor([[ 0.,  1.,  2.,  3.],
#         [ 4.,  5.,  6.,  7.],
#         [ 8.,  9., 10., 11.],
#         [12., 13., 14., 15.],
#         [16., 17., 18., 19.]])
print(x)              # tensor([0., 1., 2., 3.])print(torch.mv(A, x)) # tensor([ 14.,  38.,  62.,  86., 110.])

注意,A的列維數(沿軸1的長度)必須與x的維數(其長度)相同。


矩陣-矩陣乘法

我們可以將矩陣-矩陣乘法 AB 看作簡單地執行 m 次矩陣-向量積,并將結果拼接在一起,形成一個 n * m 矩陣。
在這里插入圖片描述

import torchA = torch.arange(20, dtype=torch.float32).reshape(5, 4)
B = torch.ones(4, 3)print(A)
# tensor([[ 0.,  1.,  2.,  3.],
#         [ 4.,  5.,  6.,  7.],
#         [ 8.,  9., 10., 11.],
#         [12., 13., 14., 15.],
#         [16., 17., 18., 19.]])
print(B)
# tensor([[1., 1., 1.],
#         [1., 1., 1.],
#         [1., 1., 1.],
#         [1., 1., 1.]])
print(torch.mm(A, B))
# tensor([[ 6.,  6.,  6.],
#         [22., 22., 22.],
#         [38., 38., 38.],
#         [54., 54., 54.],
#         [70., 70., 70.]])

范數
向量的范數是表示一個向量有多大。 這里考慮的大小(size)概念不涉及維度,而是分量的大小。

范數的常見性質

  1. 按照常量因子縮放
    在這里插入圖片描述

  2. 三角不等式
    在這里插入圖片描述

  3. 范數的非負性
    在這里插入圖片描述


L2范數
向量元素平方和的平方根
在這里插入圖片描述

import torchu = torch.tensor([3.0, -4.0])
print(torch.norm(u))    # tensor(5.)

L1范數
向量元素的絕對值之和
在這里插入圖片描述

import torchu = torch.tensor([3.0, -4.0])
print(torch.abs(u).sum())  # tensor(7.)

Lp 范數
在這里插入圖片描述


Frobenius范數
Frobenius范數(Frobenius norm)是矩陣元素平方和的平方根

在這里插入圖片描述

import torchA = torch.arange(20, dtype=torch.float32).reshape(5, 4)
print(A)   
# tensor([[ 0.,  1.,  2.,  3.],
#         [ 4.,  5.,  6.,  7.],
#         [ 8.,  9., 10., 11.],
#         [12., 13., 14., 15.],
#         [16., 17., 18., 19.]])
print(torch.norm(A))  # tensor(49.6991)

2.6、微積分

在2500年前,古希臘人把一個多邊形分成三角形,并把它們的面積相加,才找到計算多邊形面積的方法。 為了求出曲線形狀(比如圓)的面積,古希臘人在這樣的形狀上刻內接多邊形。
如下圖所示,內接多邊形的等長邊越多,就越接近圓。 這個過程也被稱為逼近法(method of exhaustion)

在這里插入圖片描述

逼近法就是積分(integral calculus)的起源。

在深度學習中,我們“訓練”模型,不斷更新它們,使它們在看到越來越多的數據時變得越來越好。 通常情況下,變得更好意味著最小化一個損失函數(loss function), 即一個衡量“模型有多糟糕”這個問題的分數。 最終,我們真正關心的是生成一個模型,它能夠在從未見過的數據上表現良好。 但“訓練”模型只能將模型與我們實際能看到的數據相擬合。
因此,我們可以將擬合模型的任務分解為兩個關鍵問題:

  • 優化(optimization):用模型擬合觀測數據的過程;
  • 泛化(generalization):數學原理和實踐者的智慧,能夠指導我們生成出有效性超出用于訓練的數據集本身的模型。

導數和微分
在深度學習中,我們通常選擇對于模型參數可微的損失函數。
簡而言之,對于每個參數, 如果我們把這個參數增加或減少一個無窮小的量,可以知道損失會以多快的速度增加或減少,

導數的定義:
在這里插入圖片描述

如果 f ′ ( α ) f'(\alpha) f(α) 存在,則 f f f α \alpha α 處是可微的
如果 f f f在一個區間內的每個數上都是可微的,則此函數在此區間中是可微的。


微分常見法則
在這里插入圖片描述


繪制圖及其切線

import numpy as np
from matplotlib_inline import backend_inline
from d2l import torch as d2ldef use_svg_display():  #@save"""使用svg格式在Jupyter中顯示繪圖"""backend_inline.set_matplotlib_formats('svg')def set_figsize(figsize=(3.5, 2.5)):  #@save"""設置matplotlib的圖表大小"""use_svg_display()d2l.plt.rcParams['figure.figsize'] = figsize#@save
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):"""設置matplotlib的軸"""axes.set_xlabel(xlabel)axes.set_ylabel(ylabel)axes.set_xscale(xscale)axes.set_yscale(yscale)axes.set_xlim(xlim)axes.set_ylim(ylim)if legend:axes.legend(legend)axes.grid()#@save
def plot(X, Y=None, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear', yscale='linear',fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5), axes=None):"""繪制數據點"""if legend is None:legend = []set_figsize(figsize)axes = axes if axes else d2l.plt.gca()# 如果X有一個軸,輸出Truedef has_one_axis(X):return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list)and not hasattr(X[0], "__len__"))if has_one_axis(X):X = [X]if Y is None:X, Y = [[]] * len(X), Xelif has_one_axis(Y):Y = [Y]if len(X) != len(Y):X = X * len(Y)axes.cla()for x, y, fmt in zip(X, Y, fmts):if len(x):axes.plot(x, y, fmt)else:axes.plot(y, fmt)set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)def f(t):return 3 * t ** 2 - 4 * tx = np.arange(0, 3, 0.1)
plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
d2l.plt.show()

在這里插入圖片描述


偏導數
到目前為止,我們只討論了僅含一個變量的函數的微分。
在深度學習中,函數通常依賴于許多變量。
因此,我們需要將微分的思想推廣到多元函數(multivariate function上。

  • 導數:在一元函數 y = f ( x ) y=f(x) y=f(x)中,導數 f ′ ( x ) f'(x) f(x)表示曲線在點 ( x , f ( x ) ) (x, f(x)) x,f(x)處的切線斜率
  • 偏導數:在多元函數 z = f ( x , y ) z=f(x, y) z=f(x,y)中,偏導數 ? f ? x \frac{\partial f}{\partial x} ?x?f?表示曲面在點 ( x , y , f ( x , y ) ) (x,y,f(x,y)) (x,y,f(x,y))處沿著x軸方向的切線斜率(固定y不變)

在這里插入圖片描述


梯度
我們可以連結一個多元函數對其所有變量的偏導數,以得到該函數的梯度(gradient)向量

在這里插入圖片描述


鏈式法則
然而,上面方法可能很難找到梯度。
這是因為在深度學習中,多元函數通常是復合(composite)的, 所以難以應用上述任何規則來微分這些函數。
幸運的是,鏈式法則可以被用來微分復合函數。

鏈式法則是微積分中用于求解復合函數導數的核心工具
其核心思想是:復合函數的導數等于外層函數的導數乘以內層函數的導數,層層傳遞,如同鏈條一樣。

在這里插入圖片描述


2.7、自動微分

深度學習框架通過自動計算導數,即自動微分(automatic differentiation)來加快求導。
實際中,根據設計好的模型,系統會構建一個計算圖(computational graph), 來跟蹤計算是哪些數據通過哪些操作組合起來產生輸出。
自動微分使系統能夠隨后反向傳播梯度。
這里,反向傳播(backpropagate)意味著跟蹤整個計算圖,填充關于每個參數的偏導數。

反向傳播:反向傳播(Back Propagation, BP) 是神經網絡訓練的核心算法之一,主要用于計算損失函數對網絡參數的梯度,并通過梯度下降等優化方法更新參數,從而最小化損失函數。


計算圖
PyTorch 中的 計算圖(Computational Graph)是深度學習框架中用于描述數學運算的 有向無環圖(DAG)
它通過節點記錄張量(Tensor)之間的運算關系,是 PyTorch 實現 自動求導(Autograd)的核心機制。

  • 節點(Node)
    葉子節點(Leaf Node):用戶直接創建的張量(如 x = torch.tensor(..., requires_grad=True)),grad_fnNone
    中間節點:由運算生成的張量(如 y = x + 2),grad_fn 記錄生成該張量的操作(如 <AddBackward0>)。
  • 邊(Edge)
    表示張量之間的依賴關系,即數據流。例如,y = x * x 中,邊連接 x 和 y,表示 y 的計算依賴于 x。

在這里插入圖片描述


一個簡單的例子
一個簡單的例子,假設我們想要對函數 y = 2 ? x T ? x y=2*x^T*x y=2?xT?x關于列向量 x x x求導。首先,我們創建變量 x x x并為其分配一個初始值。
在我們計算 y y y關于 x x x的梯度之前,需要一個地方來存儲梯度。(避免每次都用新的內存來存儲梯度,造成內存耗盡)

PyTorch 中,x.requires_grad = Truex.requires_grad_(True) 的作用是啟用對張量 x 的梯度追蹤,這是自動求導(Autograd)的核心機制之一。

PyTorch 默認不會追蹤張量的操作,以節省內存
啟用后的作用

  • PyTorch 會記錄所有對 x 的操作(如加法、乘法、矩陣運算等),構建一個動態計算圖
  • 在調用 backward() 進行反向傳播時,可以自動計算 x 的梯度(x.grad)。
import torchx = torch.arange(4.0)
print(x)               # tensor([0., 1., 2., 3.])# 啟動對張量 x 的梯度追蹤
x.requires_grad_(True)
print(x.grad)          # 默認值是 None# 計算 y = 2x^2
y = 2 * torch.dot(x, x)
print(y)               # tensor(28., grad_fn=<MulBackward0>)# 調用反向傳播函數來自動計算 y 關于 x 每個分量的梯度,并打印
y.backward()
print(x.grad)          # tensor([ 0.,  4.,  8., 12.])# 驗證梯度是否正確
print(x.grad == 4 * x) # tensor([True, True, True, True])

grad_fn=<MulBackward0>

  • 含義grad_fn 是張量的一個屬性,表示生成該張量的操作對應的梯度函數(Gradient Function)。
  • <MulBackward0> 表示該張量是通過 乘法操作(*)生成的,并且在反向傳播時會使用乘法的反向傳播規則(即乘法的導數)。
  • 動態計算圖:PyTorch 使用動態計算圖記錄操作歷史。grad_fn 是計算圖中的一部分,用于追蹤該張量是如何從其他張量(葉子節點或中間節點)生成的。

非標量變量的反向傳播
y不是標量時,向量y關于向量x的導數的最自然解釋是一個矩陣。
對于高階和高維的y和x,求導的結果可以是一個高階張量。

import torchx = torch.arange(4.0)
print(x)               # tensor([0., 1., 2., 3.])# 啟動對張量 x 的梯度追蹤
x.requires_grad_(True)
print(x.grad)          # 默認值是 None# 對非標量調用backward需要傳入一個gradient參數,該參數指定微分函數關于self的梯度。
# 本例只想求偏導數的和,所以傳遞一個1的梯度是合適的
y = x * x
# 等價于y.backward(torch.ones(len(x)))
y.sum().backward()
print(x.grad)          # tensor([0., 2., 4., 6.])

為什么需要 .sum()
backward() 默認處理標量。若 y 是向量,需通過 .sum()提供梯度權重(gradient 參數)將其轉換為標量。
對于 y = x2,其導數為 dy/dx = 2x。由于 y.sum()x?2 + x?2 + x?2,其對 x 的梯度是 [2x?, 2x?, 2x?]


分離計算
有時,我們希望將某些計算移動到記錄的計算圖之外。
例如,假設 y y y是作為 x x x的函數計算的,而 z z z則是作為 y y y x x x的函數計算的。
想象一下,我們想計算 z z z關于 x x x的梯度,但由于某種原因,希望將 y y y視為一個常數, 并且只考慮到 x x x y y y被計算后發揮的作用。
這里可以分離 y y y來返回一個新變量 u u u,該變量與 y y y具有相同的值, 但丟棄計算圖中如何計算 y y y的任何信息。

import torchx = torch.arange(4.0)
print(x)               # tensor([0., 1., 2., 3.])# 啟動對張量 x 的梯度追蹤
x.requires_grad_(True)
print(x.grad)          # 默認值是 Noney = x * x
# 創建新張量,與原張量數據相同,但不記錄梯度,防止梯度傳播
u = y.detach()
z = u * xz.sum().backward()
print(x.grad == u)     # tensor([True, True, True, True])

u u u 作為常數處理
隨后可以單獨計算 y y y 關于 x x x 的導數


Python 控制梯度流的計算
使用自動微分的一個好處是: 即使構建函數的計算圖需要通過 Python 控制流(例如,條件、循環或任意函數調用),我們仍然可以計算得到的變量的梯度
在下面的代碼中,while循環的迭代次數和 if 語句的結果都取決于輸入 a 的值。

import torchdef f(a):b = a * 2while b.norm() < 1000:b = b * 2if b.sum() > 0:c = belse:c = 100 * breturn c# 創建一個標量張量(scalar tensor),
# 其數值從標準正態分布(均值為 0,標準差為 1)中隨機生成,
# 并且啟用了梯度追蹤功能。
a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()print(a.grad == d / a)    # tensor(True)

我們現在可以分析上面定義的 f 函數。 請注意,它在其輸入 a 中是分段線性的。 換言之,對于任何 a,存在某個常量標量 k,使得 f(a)=k*a,其中 k 的值取決于輸入 a,因此可以用 d/a 驗證梯度是否正確。


2.8、概率

簡單地說,機器學習就是做出預測。

2.8.1、基本概率論

大數定律(law of large numbers): 將出現的次數除以投擲的總次數, 即此事件(event)概率的估計值。隨著投擲次數的增加,估計值會越來越接近真實的潛在概率。
在統計學中,我們把從概率分布中抽取樣本的過程稱為抽樣(sampling)

import torch
from torch.distributions import multinomial
from d2l import torch as d2l# torch.ones([6]):生成一個形狀為 (6,) 的張量,所有元素初始化為 1,即 [1, 1, 1, 1, 1, 1]。
fair_probs = torch.ones([6]) / 6        # tensor([0.1667, 0.1667, 0.1667, 0.1667, 0.1667, 0.1667])# total_count 實驗的總次數, fair_probs 指定每個類別的概率分布
# sample 從分布中采樣一次,返回一個形狀為 (6, )的張量(one-hot 向量)
# 返回一個 one-hot 向量,其中只有一個元素為 1(表示該類別被選中),其余為 0。
res = multinomial.Multinomial(10000, fair_probs).sample()print(res / 10000)                      # tensor([0.1629, 0.1630, 0.1709, 0.1685, 0.1623, 0.1724])# 繪圖  看到這些概率如何隨著時間的推移收斂到真實概率。 
counts = multinomial.Multinomial(10, fair_probs).sample((500,))
cum_counts = counts.cumsum(dim=0)
estimates = cum_counts / cum_counts.sum(dim=1, keepdims=True)d2l.set_figsize((6, 4.5))
for i in range(6):d2l.plt.plot(estimates[:, i].numpy(),label=("P(die=" + str(i + 1) + ")"))
d2l.plt.axhline(y=0.167, color='black', linestyle='dashed')
d2l.plt.gca().set_xlabel('Groups of experiments')
d2l.plt.gca().set_ylabel('Estimated probability')
d2l.plt.legend()
d2l.plt.show()

在這里插入圖片描述


概率論公理
我們將集合 S = { 1 , 2 , 3 , 4 , 5 , 6 } S = \{1, 2, 3,4,5,6\} S={1,2,3,4,5,6}稱為樣本空間(sample space)結果空間(outcome space)
事件(event)是一組給定樣本空間的隨機結果。
在這里插入圖片描述


隨機變量
隨機變量幾乎可以是任何數量,并且它可以在隨機實驗的一組可能性中取一個值。
我們可以將 P ( X ) P(X) P(X)表示為隨機變量 X X X上的分布(distribution): 分布告訴我們 X X X獲得某一值的概率。
另一方面,我們可以簡單用 P ( a ) P(a) P(a)表示隨機變量取值 a a a的概率。
離散(discrete)隨機變量(如骰子的每一面) 和連續(continuous)隨機變量(如人的體重和身高)之間存在微妙的區別。
如果我們進行足夠精確的測量,最終會發現這個星球上沒有兩個人具有完全相同的身高。 在這種情況下,詢問某人的身高是否落入給定的區間,比如是否在1.79米和1.81米之間更有意義。 在這些情況下,我們將這個看到某個數值的可能性量化為密度(density)

2.8.2、處理多個隨機變量

聯合概率
P ( A = a , B = b ) P(A=a, B=b) P(A=a,B=b)表示: A = a A=a A=a B = b B=b B=b同時滿足的概率

條件概率
P ( B = b ∣ A = a ) P(B=b | A=a) P(B=bA=a)表示:在 a a a已經發生的條件下, A = a A=a A=a B = b B=b B=b同時滿足的概率
P ( B = b ∣ A = a ) = P ( A = a , B = b ) P ( A = a ) P(B=b | A=a) = \frac{P(A=a, B=b)}{P(A = a)} P(B=bA=a)=P(A=a)P(A=a,B=b)?

貝葉斯定理
P ( B = b ∣ A = a ) = P ( A = a ∣ B = b ) ? P ( B = b ) P ( A = a ) P(B=b | A=a) = \frac{P(A=a | B=b) * P(B=b)}{P(A = a)} P(B=bA=a)=P(A=a)P(A=aB=b)?P(B=b)?

邊際化
B B B的概率相當于計算 A A A的所有可能選擇,并將所有選擇的聯合概率聚合在一起
P ( B ) = ∑ A P ( A , B ) P(B) = \sum_{A} P(A,B) P(B)=A?P(A,B)

獨立性
如果兩個隨機變量 A A A B B B獨立的,意味著事件 A A A的發生跟事件 B B B的發生無關。
P ( B = b ∣ A = a ) = P ( B = b ) P(B=b | A=a) =P(B=b) P(B=bA=a)=P(B=b)
P ( B = b , A = a ) = P ( B = b ) ? P ( A = a ) P(B=b, A=a) =P(B=b) * P(A=a) P(B=b,A=a)=P(B=b)?P(A=a)


2.8.3、期望和方差

一個隨機變量 X X X期望(expectation,或平均值(average))表示為
E [ X ] = ∑ x x ? P ( X = x ) E[X] = \sum_{x} x * P(X = x) E[X]=x?x?P(X=x)

衡量隨機變量 X X X與其期望值的偏置。這可以通過方差來量化
V a r [ X ] = E [ ( X ? E [ X ] ) 2 ] Var[X]=E[(X-E[X])^2] Var[X]=E[(X?E[X])2]

方差的平方根就是標準差


2.9、查閱文檔

查找指定函數的方法的作用

help(torch.ones)

返回結果

Help on built-in function ones in module torch:ones(...)ones(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> TensorReturns a tensor filled with the scalar value `1`, with the shape definedby the variable argument :attr:`size`.Args:size (int...): a sequence of integers defining the shape of the output tensor.Can be a variable number of arguments or a collection like a list or tuple.Keyword arguments:out (Tensor, optional): the output tensor.dtype (:class:`torch.dtype`, optional): the desired data type of returned tensor.Default: if ``None``, uses a global default (see :func:`torch.set_default_dtype`).layout (:class:`torch.layout`, optional): the desired layout of returned Tensor.Default: ``torch.strided``.device (:class:`torch.device`, optional): the desired device of returned tensor.Default: if ``None``, uses the current device for the default tensor type(see :func:`torch.set_default_device`). :attr:`device` will be the CPUfor CPU tensor types and the current CUDA device for CUDA tensor types.requires_grad (bool, optional): If autograd should record operations on thereturned tensor. Default: ``False``.Example::>>> torch.ones(2, 3)tensor([[ 1.,  1.,  1.],[ 1.,  1.,  1.]])>>> torch.ones(5)tensor([ 1.,  1.,  1.,  1.,  1.])

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

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

相關文章

瑞盟MS4554N/MS4554N1雙向電平轉換器重新定義混合電壓系統連接

在電子設備的“心臟”——電路系統里&#xff0c;不同功能模塊常因性能需求差異&#xff0c;采用差異化的供電電壓&#xff1a;傳感器用1.8V低功耗運行&#xff0c;主控芯片選3.3V高效處理&#xff0c;傳統接口保留5V穩定傳輸……當這些“電壓孤島”需要互聯時&#xff0c;一個…

二叉樹題解——驗證二叉搜索樹【LeetCode】后序遍歷

98. 驗證二叉搜索樹 一、算法邏輯&#xff08;逐步通順講解每一步思路&#xff09; 這段算法使用了一種遞歸的思路&#xff1a; 每個節點返回它所在子樹的 最小值和最大值&#xff0c;并在返回的過程中檢查 BST 的合法性。 ? 1?? 定義遞歸函數 dfs(node)&#xff0c;其含…

Flink-Source算子點位提交問題(Earliest)

背景 最近在做 Flink 任務數據源切換時遇到 offset 消費問題&#xff0c;遂寫篇文章記錄下來。 切換時只修改了 source 算子的 topic&#xff0c;uid 等其他信息保持不變&#xff1a; 發布時&#xff0c;發現算子的消費者點位重置為earliest&#xff0c;導致消息積壓。消息積…

如何錄制帶備注的演示文稿(LaTex Beamer + Pympress)

參考文獻&#xff1a; Pympress 官網Avidemux 官網Audacity 官網FFmpeg 官網2025年度25大視頻剪輯軟件推薦2025最新音頻降噪軟件盤點&#xff0c;從入門到專業的6個高效工具如何用一段音頻替換mp4視頻格式的原有音頻&#xff1f;免費簡單易用的視頻剪切編輯工具—AvidemuxFFmp…

VS Code 的 Copilot Chat 擴展程序

安裝與啟用 Copilot Chat 擴展 在 VS Code 中打開擴展市場&#xff08;快捷鍵 CtrlShiftX 或點擊左側活動欄的擴展圖標&#xff09;。搜索“GitHub Copilot Chat”&#xff0c;點擊安裝。安裝完成后需登錄 GitHub 賬戶并授權 Copilot 權限。確保已訂閱 GitHub Copilot 服務&am…

bash 腳本比較 100 個程序運行時間,精確到毫秒,腳本

腳本如下&#xff1a; #!/bin/bash# 設置測試次數 NUM_TESTS100 # 設置要測試的程序路徑 PROGRAM"./your_program" # 替換為你的程序路徑 # 設置程序參數&#xff08;如果沒有參數則留空&#xff09; ARGS"" # 例如: "input.txt output.txt"#…

【Linux學習】Linux安裝并配置Redis

安裝Redis在Linux系統上安裝Redis可以通過包管理器或源碼編譯兩種方式進行。以下是兩種方法的詳細步驟。使用包管理器安裝Redis&#xff08;以Ubuntu為例&#xff09;&#xff1a;sudo apt update sudo apt install redis-server通過源碼編譯安裝Redis&#xff1a;wget https:/…

redis每種數據結構對應的底層數據結構原理

Redis 的每種數據結構(String、List、Hash、Set、Sorted Set)在底層都采用了不同的實現方式,根據數據規模和特性動態選擇最優的編碼(encoding)以節省內存和提高性能。以下是詳細原理分析: 1. String(字符串) 底層實現: int:當存儲整數值且可用 long 表示時,直接使用…

WPF控件大全:核心屬性詳解

WPF常用控件及核心屬性 以下是WPF開發中最常用的控件及其關鍵屬性&#xff08;按功能分類&#xff09;&#xff1a; 基礎布局控件 Grid&#xff08;網格布局&#xff09; RowDefinitions&#xff1a;行定義集合&#xff08;如Height"Auto"&#xff09;ColumnDefinit…

馬斯克腦機接口(Neuralink)技術進展,已經實現癱瘓患者通過BCI控制電腦、玩視頻游戲、學習編程,未來盲人也能恢復視力了

目錄 圖片總結文字版總結1. 核心目標與愿景1.1 增強人類能力1.2 解決腦部疾病1.3 理解意識1.4 應對AI風險 2. 技術進展與產品2.1 Telepathy&#xff08;意念操控&#xff09;功能與目標技術細節參與者案例 2.2 Blindsight&#xff08;視覺恢復&#xff09;**功能與目標**技術細…

Vuex身份認證

雖說上一節我們實現了登錄功能&#xff0c;但是實際上還是可以通過瀏覽器的地址來跳過登錄訪問到后臺&#xff0c;這種可有可無的登錄功能使得系統沒有安全性&#xff0c;而且沒有意義 為了讓登錄這個功能有意義&#xff0c;我們應該&#xff1a; 應當在用戶登錄成功之后給用戶…

springboot中使用線程池

1.什么場景下使用線程池&#xff1f; 在異步的場景下&#xff0c;可以使用線程池 不需要同步等待&#xff0c; 不需要管上一個方法是否執行完畢&#xff0c;你當前的方法就可以立即執行 我們來模擬一下&#xff0c;在一個方法里面執行3個子任務&#xff0c;不需要相互等待 …

Flask+LayUI開發手記(十):構建統一的選項集合服務

作為前端最主要的組件&#xff0c;無論是layui-table表格還是layui-form表單&#xff0c;其中都涉及到選項列的處理。如果是普通編程&#xff0c;一個任務對應一個程序&#xff0c;自然可以就事論事地單對單處理&#xff0c;前后端都配制好選項&#xff0c;手工保證兩者的一致性…

redis的數據初始化或增量更新的方法

做系統開發的時候&#xff0c;經常需要切換環境&#xff0c;做一些數據的初始化的工作&#xff0c;而redis的初始化&#xff0c;假如通過命令來執行&#xff0c;又太復雜&#xff0c;因為redis有很多種數據類型&#xff0c;全部通過敲擊命令來初始化的話&#xff0c;打的命令實…

【PaddleOCR】OCR表格識別數據集介紹,包含PubTabNet、好未來表格識別、WTW中文場景表格等數據,持續更新中......

&#x1f9d1; 博主簡介&#xff1a;曾任某智慧城市類企業算法總監&#xff0c;目前在美國市場的物流公司從事高級算法工程師一職&#xff0c;深耕人工智能領域&#xff0c;精通python數據挖掘、可視化、機器學習等&#xff0c;發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN…

sparkjar任務運行

mainclass&#xff1a; test.sparkjar.SparkJarTest

Web攻防-文件下載文件讀取文件刪除目錄遍歷路徑穿越

知識點&#xff1a; 1、WEB攻防-文件下載&讀取&刪除-功能點&URL 2、WEB攻防-目錄遍歷&穿越-功能點&URL 黑盒分析&#xff1a; 1、功能點 文件上傳&#xff0c;文件下載&#xff0c;文件刪除&#xff0c;文件管理器等地方 2、URL特征 文件名&#xff1a; d…

使用LIMIT + OFFSET 分頁時,數據重復的風險

在使用 LIMIT OFFSET 分頁時&#xff0c;數據重復的風險不僅與排序字段的唯一性有關&#xff0c;還與數據變動&#xff08;插入、刪除、更新&#xff09;密切相關。以下是詳細分析&#xff1a; 一、數據變動如何導致分頁異常 1. 插入新數據 場景&#xff1a;用戶在瀏覽第 1 頁…

Excel 數據透視表不夠用時,如何處理來自多個數據源的數據?

當數據透視表感到“吃力”時&#xff0c;我們該怎么辦&#xff1a; 數據量巨大&#xff1a;Excel工作表有104萬行的限制&#xff0c;當有幾十萬行數據時&#xff0c;透視表和公式就會變得非常卡頓。數據來源多樣&#xff1a;數據分散在多個Excel文件、CSV文件、數據庫甚至網頁…

cf(1034)Div3(補題A B C D E F)

哈&#xff0c;這個比賽在開了不久之后&#xff0c;不知道為啥卡了差不多20來分鐘&#xff0c;后面卡著卡著就想睡覺了。實在是太困了.... 題目意思&#xff1a; Alice做一次操作&#xff0c;刪除任意數字a,而Bob做一次操作刪除b使得ab對4取余是3。 獲勝條件&#xff0c;有人…