孕婦做兼職上哪家網(wǎng)站深圳網(wǎng)絡(luò)推廣建站
%matplotlib inline
import random
import torch
from d2l import torch as d2l
1、生成數(shù)據(jù)集:
看最后的效果,用正態(tài)分布弄了一些噪音
上面這個具體實現(xiàn)可以看書,又想了想還是上代碼把:
按照上面生成噪聲,其中最后那個代表服從正態(tài)分布的噪聲
def synthetic_data(w, b, num_examples): # 定義函數(shù) synthetic_data,接受權(quán)重 w、偏差 b 和樣本數(shù)量 num_examples 作為參數(shù)"""生成 y = Xw + b + 噪聲 的合成數(shù)據(jù)集"""# 生成一個形狀為 (num_examples, len(w)) 的特征矩陣 X,其中的元素是從均值為 0、標準差為 1 的正態(tài)分布中隨機采樣得到X = torch.normal(0, 1, (num_examples, len(w)))# 計算目標值 y,通過將特征矩陣 X 與權(quán)重 w 相乘,然后加上偏差 b,模擬線性回歸的預(yù)測過程y = torch.matmul(X, w) + b# 給目標值 y 添加一個小的隨機噪聲,以模擬真實數(shù)據(jù)中的噪聲。噪聲從均值為 0、標準差為 0.01 的正態(tài)分布中隨機采樣得到y += torch.normal(0, 0.01, y.shape)# 返回特征矩陣 X 和目標值 y(將目標值 y 重塑為列向量的形式)return X, y.reshape((-1, 1)
# 定義真實的權(quán)重 true_w 為 [2, -3.4]
true_w = torch.tensor([2, -3.4])# 定義真實的偏差 true_b 為 4.2
true_b = 4.2# 調(diào)用 synthetic_data 函數(shù)生成合成數(shù)據(jù)集,傳入真實的權(quán)重 true_w、偏差 true_b 和樣本數(shù)量 1000
# 這將返回特征矩陣 features 和目標值 labels
features, labels = synthetic_data(true_w, true_b, 1000)
2、讀取數(shù)據(jù)集
注意一般情況下要打亂。
下面函數(shù)的作用是該函數(shù)接收批量??、特征矩陣和標簽向量作為輸?,?成??為batch_size的?批量。每個?批量包含?組特征和標簽。
def data_iter(batch_size, features, labels):num_examples = len(features) # 獲取樣本數(shù)量indices = list(range(num_examples)) # 創(chuàng)建一個樣本索引列表,表示樣本的順序# 將樣本索引列表隨機打亂,以便隨機讀取樣本,沒有特定的順序random.shuffle(indices)# 通過循環(huán)每次取出一個批次大小的樣本for i in range(0, num_examples, batch_size):# 計算當前批次的樣本索引范圍,確保不超出總樣本數(shù)量batch_indices = torch.tensor(indices[i: min(i + batch_size, num_examples)])# 通過索引獲取對應(yīng)的特征和標簽,然后通過 yield 返回這個批次的數(shù)據(jù)# yield 使得函數(shù)可以作為迭代器使用,在每次迭代時產(chǎn)生一個新的批次數(shù)據(jù)yield features[batch_indices], labels[batch_indices]
3、初始化模型參數(shù)
第一步:前面兩行代碼,,我
們通過從均值為0、標準差為0.01的正態(tài)分布中采樣隨機數(shù)來初始化權(quán)重,并將偏置初始化為0。
計算梯度使用2.5節(jié)引入的自動微分
w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
4、定義模型
這里注意b是一個標量和向量相加,咋辦?
前面說過向量的廣播機制,就相當于是加到每一個上面
def linreg(X, w, b): #@save
"""線性回歸模型"""
return torch.matmul(X, w) + b
5、定義損失函數(shù)
y.reshape(y_hat.shape))啥意思?
y_hat是真實值,這里的意思是弄成和y_hat相同的大小
def squared_loss(y_hat, y): #@save
"""均?損失"""
return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
6、優(yōu)化算法
問:這里的參數(shù)是啥參數(shù)?params
更新完的參數(shù)不用返回嗎?
為什么需要梯度清零?
def sgd(params, lr, batch_size): # 定義函數(shù) sgd,接受參數(shù) params、學(xué)習(xí)率 lr 和批次大小 batch_size"""小批量隨機梯度下降"""with torch.no_grad(): # 使用 torch.no_grad() 來關(guān)閉梯度跟蹤,以減少內(nèi)存消耗for param in params: # 遍歷模型參數(shù)列表param -= lr * param.grad / batch_size # 更新參數(shù):參數(shù) = 參數(shù) - 學(xué)習(xí)率 * 參數(shù)梯度 / 批次大小param.grad.zero_() # 清零參數(shù)的梯度,以便下一輪梯度計算
7、訓(xùn)練
問:反向傳播是為了干啥?
是為了計算梯度,那梯度是啥呢
梯度是參數(shù)更快收斂的方向(就是向量)
優(yōu)化方法是干啥的?
優(yōu)化方法就是根據(jù)上面?zhèn)鬟^來的梯度,計算參數(shù)更新
所以,這幾章看完后需要梳理深度學(xué)習(xí)的整個過程,以及每塊有哪些方法,這些方法的特點和用那種方法更好
問(1)每個epoch訓(xùn)練多少數(shù)據(jù)?
整個訓(xùn)練集
(2)損失函數(shù)是啥?
損失函數(shù)是用來計算真實值域預(yù)測值之間的距離,當然是距離越小越好,可以拿均方誤差想一下
(3)l.sum().backward()是啥意思?
看注釋,補充:.backward() 方法用于執(zhí)行自動求導(dǎo),計算總的損失值對于模型參數(shù)的梯度。這將會構(gòu)建計算圖并沿著圖的反向傳播路徑計算梯度。
(4)但是上面所說的梯度保存在哪里呢?
w.grad 和 b.grad 中
(5)但是sgd中也沒有用到w.grad 啊?
用到了,param 可以是 w 或者 b,而 param.grad 則是相應(yīng)參數(shù)的梯度。
(6)新問題:train_l = loss(net(features, w, b), labels)不是在前面已經(jīng)計算過損失函數(shù)了嗎?為啥在這里還需要計算?
前面計算損失函數(shù)是間斷性的,目的是更新模型參數(shù)。
后面仍然計算的目的是根據(jù)更新完的參數(shù)對模型在整個訓(xùn)練集上與真實標簽的差距做一個評估。
lr = 0.03 # 設(shè)置學(xué)習(xí)率為 0.03,控制每次參數(shù)更新的步幅num_epochs = 3 # 設(shè)置訓(xùn)練的輪次(迭代次數(shù))為 3,即遍歷整個數(shù)據(jù)集的次數(shù)net = linreg # 定義模型 net,通常表示線性回歸模型loss = squared_loss # 定義損失函數(shù) loss,通常為均方損失函數(shù),用于衡量預(yù)測值與真實值之間的差距
for epoch in range(num_epochs): # 迭代 num_epochs 輪,進行訓(xùn)練for X, y in data_iter(batch_size, features, labels): # 遍歷數(shù)據(jù)集的每個批次l = loss(net(X, w, b), y) # 計算當前批次的損失值 l,表示預(yù)測值與真實值之間的差距# 因為 l 的形狀是 (batch_size, 1),而不是一個標量。將 l 中的所有元素加起來,# 并計算關(guān)于 [w, b] 的梯度l.sum().backward()sgd([w, b], lr, batch_size) # 使用參數(shù)的梯度更新參數(shù),執(zhí)行隨機梯度下降算法with torch.no_grad():train_l = loss(net(features, w, b), labels) # 在整個訓(xùn)練集上計算損失值# 打印當前迭代輪次和訓(xùn)練損失值的均值print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
8、練習(xí)中的問題
- 如果我們將權(quán)重初始化為零,會發(fā)?什么。算法仍然有效嗎?
無效,為啥?因為,不同的X輸入是相同的輸出