目錄
一、定義
二、舉例說明
三、?數學形式
四、?訓練過程(機器怎么學會這條線?)
五、在 PyTorch 中怎么實現線性回歸?
六、如果你學懂了線性回歸,你也能理解這些
七、綜合應用:線性回歸示例
7.1 執行代碼
7.2 運行效果
7.3 運行圖示效果
7.4 代碼解析
7.4.1?庫名解析
7.4.2 生成數據
7.4.3 定義模型
7.4.4 訓練設置
7.4.5 訓練循環
7.4.6 結果可視化
一、定義
線性回歸是用一條直線,來擬合數據中輸入和輸出之間的關系。
它是最簡單的一種監督學習模型,目標是學會從輸入 x預測輸出 y。
線性回歸就是用一條最合適的“直線”去擬合數據關系,是所有機器學習算法的“入門基礎”和“核心思想的起點”。
二、舉例說明
比如你有下面這些數據點(房屋面積 → 價格):
房屋面積 (㎡) | 房價 (萬) |
---|---|
50 | 100 |
60 | 120 |
70 | 140 |
80 | 160 |
你發現:
面積每增加 10 平方,價格多了 20 萬
→ 明顯是個線性關系:
三、?數學形式
最基本的一元線性回歸:
-
x:輸入特征(如面積)
-
y:目標輸出(如房價)
-
w:權重(斜率)
-
b:偏置(截距)
-
模型要學會找到最合適的 w?和 b,使得預測值?
盡可能接近真實值 y
四、?訓練過程(機器怎么學會這條線?)
通過梯度下降:
-
初始化 w、b(通常是隨機值)
-
預測:算出
-
計算損失 MSE
-
反向傳播(backward):計算損失對 w、b的梯度
-
更新參數:往損失下降的方向調整 w、b
-
重復上述步驟,直到 loss 越來越小,收斂為止
五、在 PyTorch 中怎么實現線性回歸?
model = nn.Linear(1, 1) # 1 個輸入,1 個輸出
?
-
自動幫你創建了可訓練的
weight
和bias
-
使用
MSELoss()
做目標函數 -
使用優化器(如
SGD
)進行參數更新
最終訓練完后你得到的就是:
一個已經學會了你數據規律的函數:
它就可以用來對新樣本進行預測了
六、如果你學懂了線性回歸,你也能理解這些
模型 | 關系與區別 |
---|---|
邏輯回歸 | 用線性回歸的結果接 softmax → 做分類任務 |
神經網絡 | 多層線性回歸 + 激活函數 |
支持向量機(SVM) | 類似線性分類器,只是優化目標不同 |
RNN / LSTM / CNN | 都是在這個思想上發展出來的 |
七、綜合應用:線性回歸示例
7.1 執行代碼
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
# ==============================
# 綜合應用:線性回歸
# ==============================
print("\n" + "=" * 50)
print("綜合應用: 線性回歸")
print("=" * 50)# 生成數據
torch.manual_seed(42) #種子數:42——生成重復的隨機數據
X = torch.linspace(0, 10, 100).reshape(-1, 1) #在0-9之間,定義100個數據,每個數據一個特征
print(X.shape)
true_weights = 2.5 #W:權重:2.5
true_bias = 1.0 #b:偏置項:1.0
y = true_weights * X + true_bias + torch.randn(X.size()) * 1.5 #模擬真實數據# 定義模型
class LinearRegression(nn.Module):def __init__(self):super().__init__()self.linear = nn.Linear(1, 1)def forward(self, x):return self.linear(x)# 訓練設置
model = LinearRegression() #初始化實例
criterion = nn.MSELoss() #定義損失函數,衡量預測和真實的差距
optimizer = torch.optim.SGD(model.parameters(), lr=0.01) #設置優化器,用來更新模型的參數
epochs = 1000 #訓練輪數:1000# 訓練循環
for epoch in range(epochs):optimizer.zero_grad() #outputs = model(X) #loss = criterion(outputs, y) #loss.backward() #optimizer.step() #if (epoch + 1) % 20 == 0:print(f'Epoch [{epoch + 1}/{epochs}], Loss: {loss.item():.4f}')# 結果可視化
predicted = model(X).detach().numpy()
plt.scatter(X.numpy(), y.numpy(), label='Original data')
plt.plot(X.numpy(), predicted, 'r-', label='Fitted line')
plt.legend()
plt.title(f'Final weights: {model.linear.weight.item():.2f}, bias: {model.linear.bias.item():.2f}')
plt.show()
7.2 運行效果
==================================================
綜合應用: 線性回歸
==================================================
torch.Size([100, 1])
Epoch [20/1000], Loss: 2.7219
Epoch [40/1000], Loss: 2.6217
Epoch [60/1000], Loss: 2.5395
Epoch [80/1000], Loss: 2.4722
Epoch [100/1000], Loss: 2.4170
Epoch [120/1000], Loss: 2.3718
Epoch [140/1000], Loss: 2.3348
Epoch [160/1000], Loss: 2.3044
Epoch [180/1000], Loss: 2.2795
Epoch [200/1000], Loss: 2.2591
Epoch [220/1000], Loss: 2.2424
Epoch [240/1000], Loss: 2.2287
Epoch [260/1000], Loss: 2.2175
Epoch [280/1000], Loss: 2.2083
Epoch [300/1000], Loss: 2.2008
Epoch [320/1000], Loss: 2.1946
Epoch [340/1000], Loss: 2.1895
Epoch [360/1000], Loss: 2.1854
Epoch [380/1000], Loss: 2.1820
Epoch [400/1000], Loss: 2.1792
Epoch [420/1000], Loss: 2.1769
Epoch [440/1000], Loss: 2.1750
Epoch [460/1000], Loss: 2.1735
Epoch [480/1000], Loss: 2.1722
Epoch [500/1000], Loss: 2.1712
Epoch [520/1000], Loss: 2.1704
Epoch [540/1000], Loss: 2.1697
Epoch [560/1000], Loss: 2.1691
Epoch [580/1000], Loss: 2.1686
Epoch [600/1000], Loss: 2.1683
Epoch [620/1000], Loss: 2.1679
Epoch [640/1000], Loss: 2.1677
Epoch [660/1000], Loss: 2.1675
Epoch [680/1000], Loss: 2.1673
Epoch [700/1000], Loss: 2.1672
Epoch [720/1000], Loss: 2.1671
Epoch [740/1000], Loss: 2.1670
Epoch [760/1000], Loss: 2.1669
Epoch [820/1000], Loss: 2.1667
Epoch [840/1000], Loss: 2.1667
Epoch [860/1000], Loss: 2.1667
Epoch [880/1000], Loss: 2.1666
Epoch [900/1000], Loss: 2.1666
Epoch [920/1000], Loss: 2.1666
Epoch [940/1000], Loss: 2.1666
Epoch [960/1000], Loss: 2.1666
Epoch [980/1000], Loss: 2.1666
Epoch [1000/1000], Loss: 2.1666
7.3 運行圖示效果
7.4 代碼解析
7.4.1?庫名解析
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
? 1. torch
:PyTorch 的主庫
作用:提供張量運算、自動求導和深度學習模型構建能力。
在本代碼中,torch
的主要作用有:
-
torch.manual_seed(42)
:設置隨機種子,確保每次運行生成的隨機數(如噪聲)一致,方便調試和復現實驗結果。 -
torch.linspace(0, 10, 100)
:生成從 0 到 10 的 100 個等間距值,模擬自變量 XXX。 -
torch.randn(...)
:生成服從正態分布的隨機噪聲,加入到 yyy 中,模擬真實數據中的擾動。 -
X.size()
/.reshape(-1, 1)
:控制張量形狀,確保符合模型輸入要求。 -
所有模型定義、參數、損失計算、反向傳播 (
loss.backward()
)、優化 (optimizer.step()
) 都依賴于torch
的自動求導與計算圖。
? 2. torch.nn
:PyTorch 的神經網絡模塊
作用:構建和使用神經網絡模塊(如線性層、激活函數、損失函數等)。
在本代碼中:
-
nn.Module
:是所有神經網絡模塊的基類。LinearRegression
類繼承自它,定義了一個簡單的線性模型。 -
nn.Linear(1, 1)
:定義一個具有一個輸入特征和一個輸出特征的線性層(即 y=wx+by = wx + by=wx+b)。 -
nn.MSELoss()
:均方誤差損失函數,用于衡量預測值與真實值的差異。
? 3. matplotlib.pyplot
:繪圖庫
作用:用于繪制圖形、數據可視化。
在本代碼中:
-
plt.scatter(...)
:繪制原始數據點(散點圖),表示樣本 (X, y)。 -
plt.plot(...)
:繪制模型擬合出的線性曲線(紅線),表示預測值。 -
plt.legend()
、plt.title(...)
:添加圖例和標題,展示最終模型參數。 -
plt.show()
:展示圖像窗口。
總結表:
依賴庫 | 作用簡述 |
---|---|
torch | 張量操作、反向傳播、優化等底層計算支持 |
torch.nn | 神經網絡層、損失函數的模塊化構建工具 |
matplotlib.pyplot | 數據可視化(繪圖、展示模型預測結果) |
這些依賴共同構成了完整的“模型構建 → 訓練 → 可視化”流程。你也可以理解為:
📦 torch 是“數據和訓練引擎”、📦 torch.nn 是“模型建造工具”、📊 matplotlib.pyplot 是“成果展示板”。
7.4.2 生成數據
# 生成數據
torch.manual_seed(42)
X = torch.linspace(0, 10, 100).reshape(-1, 1)
print(X.shape)
true_weights = 2.5
true_bias = 1.0
y = true_weights * X + true_bias + torch.randn(X.size()) * 1.5
?這段代碼的作用是:生成用于線性回歸的模擬數據集。
🔹
torch.manual_seed(42)
設置隨機數生成器的種子為 42,使得每次運行代碼時,生成的隨機數都是可復現的,即
torch.randn()
生成的噪聲始終一樣。讓隨機過程變得“確定”下來,這樣你的實驗結果每次都一樣,方便復現和調試。🤔它的作用是:
固定隨機數生成器的初始狀態,這樣每次你運行程序時,生成的“隨機數”都是完全一樣的。
這樣你就能保證結果可重復、可調試!
🤔 為什么要用這個?
做實驗、調試時要結果一致:如果你加入了隨機噪聲或模型參數是隨機初始化的,每次運行結果都不同,會很難調試。
寫教學/研究/博客代碼時需要復現:別人運行你代碼時希望結果一樣。
可對比性:你換了一種訓練方式,想驗證哪個更好——如果噪聲不同,是沒法公平比較的。
🔹
X = torch.linspace(0, 10, 100).reshape(-1, 1)
它的作用是:
生成一個形狀為
[100, 1]
的輸入特征張量 X,范圍從 0 到 10,共 100 個樣本點。拆解說明:
▲torch.linspace(0, 10, 100)
:在區間 [0, 10] 上生成 100 個等間距的數,表示自變量(輸入特征)。
tensor([0.0000, 0.1010, 0.2020, ..., 9.8990, 10.0000]) #100個點
▲.reshape(-1, 1)
:? 一句話解釋
把張量變成 2 維,其中:
-1
表示“這一維度讓我自動算”,
1
表示“我想要 1 列”。? 用 .reshape(-1, 1),含義就是: x.reshape(?, 1) # 問號表示“PyTorch 你幫我算出來”
PyTorch 會看:原來你有 100 個數,你要求 1 列,那它自動算出你應該有 100 行。
所以變成:
x.shape → [100, 1]
-1
表示“自動推斷有多少行”,在這里 PyTorch 會計算出是 100 行;
1
表示每行 1 個元素 → 每個樣本有 1 個特征最終結果就變成了二維張量:
[[0.0000],[0.1010],[0.2020],...[9.8990],[10.0000] ] ← shape: [100, 1]
? 為什么
-1
就是“自動算”?PyTorch、Numpy 等都規定:
在 reshape 里,如果某一維寫
-1
,表示“我不想算這個維度,你幫我根據總元素數自動推斷”。比如下面這些例子:
a = torch.arange(12) # shape: (12,)a.reshape(3, 4) # → (3, 4) a.reshape(-1, 4) # → (3, 4) ← -1 讓 PyTorch 自己算出是 3 行 a.reshape(2, -1) # → (2, 6) ← -1 被自動推成 6 列
🚩 錯誤示例(多于一個 -1 會報錯):
a.reshape(-1, -1) # ? 報錯:只能有一個 -1
這是形狀變換的關鍵:
原來
linspace
生成的是 一維張量,形狀是(100,)
注意:這里(100,)表示的是長度為100,不是100行
但我們希望它變成 二維張量,形狀是
(100, 1)
,表示“100 個樣本,每個樣本有 1 個特征”📌 總結公式
你可以記住這句話:
.reshape(-1, n)
就是:
“把這個張量 reshape 成 n 列,行數我不想算,PyTorch 你自動算就行。”
形狀 含義 適合線性回歸嗎? [100, 1]
?? 有 100 個樣本,每個樣本 1 個特征 ? 是 [1, 100]
? 有 1 個樣本,擁有 100 個特征 ? 否 [100]
? 一維張量,不明確樣本維度 ? 否(模型報錯)
部分代碼 含義 torch.linspace(0, 10, 100)
生成 0~10 之間的 100 個點 .reshape(-1, 1)
把一維的 [100]
變成二維[100, 1]
最終的 X
是一個 100 行 1 列的輸入張量
🔹
true_weights = 2.5
這是你自己設定的**“真實模型的權重”**,代表線性函數的斜率:
y = 2.5 * x + 1.0 + 噪聲
🔹
true_bias = 1.0
表示真實模型的偏置項(截距)。
🔹
y = true_weights * X + true_bias + torch.randn(X.size()) * 1.5
🧠主要作用:
生成“模擬的真實數據”(也叫“合成數據”),專門用來做線性回歸訓練的。
這里做了一個WX+b的計算,但是加入了【隨機張量*1.5】,用于模擬噪聲 使其能夠更加貼合真實環境中的數據。
🧠 拆解說明:
這是生成帶有噪聲的目標值 y,用于擬合:
true_weights * X + true_bias
:構造一個理想的線性關系 y=2.5x+1.0y = 2.5x + 1.0y=2.5x+1.0
torch.randn(X.size())
:生成一個與 XXX 形狀相同的隨機張量,服從標準正態分布 N(0,1)
* 1.5
:將噪聲的標準差放大為 1.5,模擬更復雜的實際場景(讓數據點不是完全線性的)結果是:
🧠 總結一下這一塊的直觀含義:
手動生成了一批看起來像“真實世界采集”的數據:
X 是輸入變量,從 0 到 10 均勻分布;
y 是輸出變量,大致符合 y = 2.5x + 1 的關系,但加入了噪聲,使得它不是完美的直線;
這就是后面用來訓練模型擬合出的“模擬數據”。
7.4.3 定義模型
# 定義模型
class LinearRegression(nn.Module):def __init__(self):super().__init__()self.linear = nn.Linear(1, 1)def forward(self, x):return self.linear(x)
這段代碼定義了一個最簡單的線性回歸模型,輸入 1 個數,輸出 1 個數,核心是:
y = w * x + b
,這個公式被封裝在nn.Linear(1, 1)
中。
定義了一個線性回歸模型類,名字叫 LinearRegression
,本質就是實現了:
也就是一個帶權重和偏置的線性變換。
🔹class LinearRegression(nn.Module):
定義一個新的類,名字叫
LinearRegression
,這個類繼承自 PyTorch 提供的nn.Module
。
nn.Module
是 PyTorch 中所有模型的基類。你自定義的神經網絡都應該繼承它。
🔹super().__init__()
這一行是固定寫法,它調用父類
nn.Module
的構造方法。🧠 沒有它,PyTorch 的模型結構和參數注冊系統就沒法正常工作。
🔹self.linear = nn.Linear(1, 1)
這一行很關鍵!
它定義了一個線性層,輸入和輸出都是 1 個特征,也就是:
y = w * x + b
in_features = 1
:說明你每個樣本的輸入只有 1 個數(x)
out_features = 1
:說明模型輸出也只有 1 個數(預測 y)這個層會自動幫你創建兩個參數:
參數 含義 weight
線性函數的斜率 w bias
偏置項 b
🔹def forward(self, x):
這是 PyTorch 模型的核心函數,定義了模型的“前向傳播”邏輯。
也就是說,當你
model(x)
的時候,實際調用的就是這個函數。
🔹return self.linear(x)
輸入
x
會通過self.linear
這個線性層:
PyTorch 會自動處理矩陣乘法、廣播等操作,并計算輸出。
🎯 整體行為總結:
定義了一個“線性變換模型”,它會:
接收一個輸入
x
(形狀是[batch_size, 1]
)自動用參數 w和 b?計算出預測結果 y=wx+b
參與訓練(PyTorch 自動記錄梯度和更新參數)
7.4.4 訓練設置
# 訓練設置
model = LinearRegression()
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
epochs = 1000
這部分是模型訓練的準備工作
🔹model = LinearRegression()
創建定義的線性回歸模型實例
現在
model
就包含了一個線性層nn.Linear(1, 1)
,其中的權重w
和偏置b
是 隨機初始化 的。它準備好接收輸入并產生預測值
y_hat = model(x)
。
🔹criterion = nn.MSELoss()
這是設置損失函數:
它衡量的是:
預測值
y_hat
與真實值y
之間的平均平方差在回歸問題中(輸出是連續數值),MSE 是最常用的損失函數。
MSELoss = Mean Squared Error Loss
,中文叫均方誤差損失。公式是:
🔹optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
這行的作用是:
設置一個優化器,用來更新模型的參數(權重和偏置),以最小化損失函數。
解釋:
SGD
= 隨機梯度下降(Stochastic Gradient Descent),一種常見的優化算法。
model.parameters()
:把模型的所有參數(權重w
、偏置b
)都傳進去,讓優化器負責更新它們。
lr=0.01
:學習率,控制每一步更新的“幅度”。📌 如果學習率太小,訓練會很慢;太大,可能震蕩、甚至不收斂。
🔹epochs = 1000
設置訓練的總輪數(epoch):
一個 epoch = 用全部訓練數據訓練一次模型
你讓模型訓練 1000 次,反復調整參數來逼近真實值
? 總結表格:
代碼 含義 model = LinearRegression()
創建模型實例,準備接收輸入 criterion = nn.MSELoss()
定義損失函數,衡量預測和真實的差距 optimizer = torch.optim.SGD(...)
設置優化器,用來更新模型的參數 epochs = 1000
訓練輪數,表示訓練模型多少遍
?💡 小結一句話:
這四行代碼是在為“模型訓練”做好準備工作:模型、評判標準(損失)、優化方法和訓練時間長度。
7.4.5 訓練循環
# 訓練循環
for epoch in range(epochs):optimizer.zero_grad()outputs = model(X)loss = criterion(outputs, y)loss.backward()optimizer.step()if (epoch + 1) % 20 == 0:print(f'Epoch [{epoch + 1}/{epochs}], Loss: {loss.item():.4f}')
? 一句話總結
這段代碼通過 “預測 → 計算損失 → 反向傳播 → 更新參數” 的過程,反復 1000 次,讓模型學會擬合數據點 X→y,找出最合適的權重和偏置。
這部分代碼是訓練的核心循環,也叫“訓練主干”,負責讓模型學會從數據中提取規律。
🔹for epoch in range(epochs):
這是訓練的主循環,總共會執行
epochs
次(這里是 1000 次)。每一次循環,模型都會用全部的訓練數據
X
,預測一遍,然后更新參數。
🔹optimizer.zero_grad()
每次迭代開始前,清空舊的梯度信息。
因為 PyTorch 會自動累積梯度,所以每次計算新梯度前要先清空。
🔹
outputs = model(X)
把輸入數據
X
喂進模型,得到預測輸出outputs
,也就是?。
這一步會自動調用你模型里的
forward()
函數:def forward(self, x):return self.linear(x)
🔹loss = criterion(outputs, y)
比較模型預測值
outputs
和真實值y
,計算損失值。
criterion = nn.MSELoss()
是均方誤差,越小表示預測越準確。
🔹loss.backward()
反向傳播:根據損失
loss
自動計算模型中所有參數的梯度(導數)。PyTorch 會自動為你完成鏈式法則的求導。
🔹optimizer.step()
使用前面算出來的梯度,更新模型參數(權重
w
和偏置b
)。優化器根據學習率和梯度來調整參數,讓損失變得更小。
🔹
if (epoch + 1) % 20 == 0:
每訓練 20 次,打印一次日志。
loss.item()
把一個標量 tensor 取出數值,用于打印。結果例子:
Epoch [20/1000], Loss: 1.2234 Epoch [40/1000], Loss: 0.8912 ...
?📊 圖示訓練流程:
? ? ? ? ┌────────────┐
? ? ? ? │ ? ?X? ? ? ? ? ? ? ? ? ? ? ? ?│ ?← 輸入
? ? ? ? └────┬───────┘
? ? ? ? ? ? ? ? ? ? ?↓
? ? ? ? ┌────────────┐
? ? ? ? │ ?model(X)? ? ? ? ? ? ? ?│ ?← 前向傳播:預測 outputs
? ? ? ? └────┬───────┘
? ? ? ? ? ? ? ? ? ? ?↓
? ? ? ? ┌────────────┐
? ? ? ? │ loss = MSE? ? ? ? ? ? │ ?← 損失函數:outputs vs y
? ? ? ? └────┬───────┘
? ? ? ? ? ? ? ? ? ? ?↓
? ? ? ? ┌────────────┐
? ? ? ? │ ?backward? ? ? ? ? ? ? │ ?← 自動求導:loss.backward()
? ? ? ? └────┬───────┘
? ? ? ? ? ? ? ? ? ? ?↓
? ? ? ? ┌────────────┐
? ? ? ? │ optimizer? ? ? ? ? ? ? ? │ ?← 參數更新:optimizer.step()
? ? ? ? └────────────┘
?
7.4.6 結果可視化
# 可視化結果
predicted = model(X).detach().numpy()
plt.scatter(X.numpy(), y.numpy(), label='Original data')
plt.plot(X.numpy(), predicted, 'r-', label='Fitted line')
plt.legend()
plt.title(f'Final weights: {model.linear.weight.item():.2f}, bias: {model.linear.bias.item():.2f}')
plt.show()
這段代碼是整個線性回歸項目的最后一步:結果可視化,幫助你直觀地看到模型學得怎么樣。例如:
🔹predicted = model(X).detach().numpy()
含義:讓模型生成預測結果,并把它轉換成 NumPy 格式,方便畫圖。
model(X)
:把輸入X
送入你訓練好的模型,得出預測值(也就是模型估計的y_hat
)
.detach()
:從計算圖中分離出來,不需要梯度,只用于畫圖。
.numpy()
:把結果變成 NumPy 數組。得到的是一個形狀也為
[100, 1]
的數組,對應每個x
值的預測y
。
🔹plt.scatter(X.numpy(), y.numpy(), label='Original data')
畫出原始訓練數據點(帶噪聲的),用“散點圖”表示。
X.numpy()
:把 PyTorch 的張量轉成 NumPy 數組,才能用matplotlib
來畫圖;
y.numpy()
:同樣是把y
轉成 NumPy 數組,方便畫圖;
X.numpy(), y.numpy()
是將你的輸入數據和真實標簽數據從 PyTorch 的 Tensor 轉成 NumPy 數組,以便用matplotlib.pyplot
畫圖;
橫坐標是
X
,縱坐標是y
(真實的目標值)這是你用來訓練模型的數據點
它們并不完美在一條直線上,是故意加了噪聲的
🔹plt.plot(X.numpy(), predicted, 'r-', label='Fitted line')
用 matplotlib 畫一條“紅色直線”,表示模型預測出的結果,即模型學到的線性函數。
畫出模型學習出來的那條“最佳擬合線”
橫坐標:輸入
X
縱坐標:模型預測值
predicted
'r-'
表示紅色(red)實線這是你訓練了這么久之后,模型認為最合適的那條線
🔹plt.legend()
顯示圖例,對應你前面加的
label='...'
標簽:
原始數據:藍色點
擬合線:紅色線
🔹plt.title(...)
給圖加標題:顯示模型最終學到的參數(權重和偏置):
f'Final weights: {model.linear.weight.item():.2f}, bias: {model.linear.bias.item():.2f}'
意思是:
最終權重:比如 2.49,最終偏置:比如 1.02
這能幫你驗證:
模型是不是成功學到了你最初設置的
2.5
和1.0
🔹plt.show()
正式顯示整個圖像窗口。