演算法金 | 詳解過擬合和欠擬合!性感嫵媚 VS 大殺四方

算法金「全网同名」發表於2024-05-30


大俠幸會,在下全網同名「演算法金」 0 基礎轉 AI 上岸,多個演算法賽 Top 「日更萬日,讓更多人享受智慧樂趣」

今天我們來戰 過擬合和欠擬合,特別是令江湖俠客聞風喪膽的 過擬合,簡稱過兒,

Emmm 過兒聽起來有點怪怪的

1. 楔子

機器學習模型是一種能夠從資料中學習規律並進行預測的演算法。我們希望透過演算法預測未來,大殺四方

事實上,可能在內一條龍在外一條蟲

過擬合和欠擬合的定義

  • 欠擬合:模型在訓練資料和測試資料上都表現不佳,在內也是一條蟲蟲啊大郎
  • 過擬合:模型過度擬合訓練資料,如下圖右3。這通常導致模型在訓練資料上表現非常好,但在測試資料上表現很差

2. 過擬合

2.1 過擬合的定義

過擬合現象是指模型過於複雜,捕捉到了訓練資料中的噪聲和細節,從而失去了泛化能力。如下圖右三這隻喵

這種情況下,模型通常在訓練資料上表現極好,但在測試資料上表現很差。

訓練時 海綿寶寶上線了,測試時海綿寶寶不見了,有沒有

2.2 過擬合的原因

資料量不足

當資料量不足時,模型容易記住訓練資料中的每一個細節和噪聲,從而導致過擬合。

模型複雜度過高

過於複雜的模型(例如具有大量引數的神經網路)可以擬合訓練資料中的任何模式,包括噪聲。

2.3 過擬合的表現

過擬合的主要表現是模型在訓練集上的誤差很低,但在測試集上的誤差很高。下面我們用程式碼示例和視覺化來展示過擬合的現象。

程式碼示例

透過增加模型複雜度來展示過擬合的現象。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error

# 生成武俠資料集
np.random.seed(42)
X = np.linspace(1, 10, 100)
y = 2 * X + np.sin(X) * 5 + np.random.randn(100) * 2  # 假設某個武俠角色的武功值與其年齡的關係

# 拆分資料集
X = X.reshape(-1, 1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 多項式迴歸模型(過擬合)
poly_features_high = PolynomialFeatures(degree=20)  # 增加模型複雜度
X_poly_train_high = poly_features_high.fit_transform(X_train)
X_poly_test_high = poly_features_high.transform(X_test)
poly_reg_high = LinearRegression()
poly_reg_high.fit(X_poly_train_high, y_train)
y_poly_train_pred_high = poly_reg_high.predict(X_poly_train_high)
y_poly_test_pred_high = poly_reg_high.predict(X_poly_test_high)

# 訓練集和測試集的表現
print("高階多項式迴歸 - 訓練集誤差:", mean_squared_error(y_train, y_poly_train_pred_high))
print("高階多項式迴歸 - 測試集誤差:", mean_squared_error(y_test, y_poly_test_pred_high))

# 視覺化結果
plt.scatter(X, y, color='blue', label='資料點')
plt.plot(X, poly_reg_high.predict(poly_features_high.transform(X)), color='red', label='高階多項式迴歸擬合線')
plt.xlabel('年齡')
plt.ylabel('武功值')
plt.title('高階多項式迴歸(過擬合)')
plt.legend()
plt.show()

在這個示例中,我們將多項式迴歸的階數提高到了 20,從而增加了模型的複雜度。模型想要迎合每一個樣本資料,透過視覺化可以看到這條擬合的線非常的嫵媚。(記住她的性感小尾巴,下面會有選美環節)

2.4 過擬合的解決方法

增加資料量

透過增加資料量,可以使模型更好地學習到資料中的一般規律,而不是記住每個細節和噪聲。

正則化方法(L1, L2)

正則化是在模型的損失函式中加入一個懲罰項,以防止模型過於複雜。L1 和 L2 正則化是兩種常見的方法。

L1 正則化透過最小化權重的絕對值之和來最佳化模型,這有助於建立一個簡潔且易於理解的模型,並且它對異常值具有較好的抵抗力。

L2 正則化則透過最小化權重值的平方和來工作,這種方法能夠使模型捕捉到資料中的複雜模式,但它對異常值的敏感度較高。

剪枝(對於決策樹)

對於決策樹模型,可以透過剪枝來減少其複雜度,從而防止過擬合。

交叉驗證

透過交叉驗證,可以更好地評估模型的效能,並選擇最合適的模型複雜度。

提前停止訓練

在訓練過程中監控模型在驗證集上的表現,當效能不再提高時停止訓練,可以防止模型過度擬合訓練資料。

Dropout

Dropout 是一種在神經網路中使用的正則化技術,它透過隨機地停用一些神經網路單元來工作。這種技術可以應用於網路中的任意隱藏層或輸入層,但通常不應用於輸出層。Dropout 的作用是減少神經元之間的相互依賴,促使網路學習到更加獨立的特徵表示。透過這種方式,Dropout 有助於降低模型的複雜度,防止過擬合,如下面的圖表所示。

程式碼示例 - 正則化

我們將使用嶺迴歸(L2 正則化)來演示如何減輕過擬合。

from sklearn.linear_model import Ridge

# 嶺迴歸模型
ridge_reg = Ridge(alpha=1)
ridge_reg.fit(X_poly_train_high, y_train)
y_ridge_train_pred = ridge_reg.predict(X_poly_train_high)
y_ridge_test_pred = ridge_reg.predict(X_poly_test_high)

# 訓練集和測試集的表現
print("嶺迴歸 - 訓練集誤差:", mean_squared_error(y_train, y_ridge_train_pred))
print("嶺迴歸 - 測試集誤差:", mean_squared_error(y_test, y_ridge_test_pred))

# 視覺化結果
plt.scatter(X, y, color='blue', label='資料點')
plt.plot(X, ridge_reg.predict(poly_features_high.transform(X)), color='red', label='嶺迴歸擬合線')
plt.xlabel('年齡')
plt.ylabel('武功值')
plt.title('嶺迴歸(減輕過擬合)')
plt.legend()
plt.show()

透過引入嶺迴歸(L2 正則化),我們可以看到模型的複雜度降低了,訓練集和測試集的誤差更加接近,從而減輕了過擬合現象。透過視覺化直觀感受一下,性感小尾巴不見了;跟上面那條線相比,這個擬合的線少了幾分妖嬈,但明顯更加絲滑(是演算法金喜歡的 Style)

3. 欠擬合

3.1 欠擬合的定義

欠擬合現象是指模型在訓練資料和測試資料上都表現不佳。這通常是因為模型過於簡單,無法捕捉資料中的規律。

3.2 欠擬合的原因

模型複雜度過低

當模型的複雜度過低時,無法捕捉資料中的複雜模式,導致欠擬合。

特徵不足

當模型沒有足夠的特徵來描述資料時,也會導致欠擬合。

3.3 欠擬合的表現

欠擬合的主要表現是模型在訓練集和測試集上的誤差都很高。下面我們用程式碼示例和視覺化來展示欠擬合的現象。

程式碼示例

我們將使用一個簡單的線性迴歸模型來展示欠擬合的現象。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# 生成武俠資料集
np.random.seed(42)
X = np.linspace(1, 10, 100)
y = 2 * X + np.sin(X) * 5 + np.random.randn(100) * 2  # 假設某個武俠角色的武功值與其年齡的關係

# 拆分資料集
X = X.reshape(-1, 1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 簡單線性迴歸模型(欠擬合)
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
y_train_pred = lin_reg.predict(X_train)
y_test_pred = lin_reg.predict(X_test)

# 訓練集和測試集的表現
print("線性迴歸 - 訓練集誤差:", mean_squared_error(y_train, y_train_pred))
print("線性迴歸 - 測試集誤差:", mean_squared_error(y_test, y_test_pred))

# 視覺化結果
plt.scatter(X, y, color='blue', label='資料點')
plt.plot(X, lin_reg.predict(X), color='red', label='線性迴歸擬合線')
plt.xlabel('年齡')
plt.ylabel('武功值')
plt.title('線性迴歸(欠擬合)')
plt.legend()
plt.show()

在這個示例中,我們使用簡單的線性迴歸模型來擬合資料。可以看到模型在訓練集和測試集上的誤差都很高,表現出欠擬合的特徵。

3.4 欠擬合的解決方法

增加模型複雜度

透過增加模型的複雜度(例如,使用更復雜的演算法或增加多項式特徵),可以幫助模型更好地擬合資料。

提供更多特徵

透過提供更多有意義的特徵,可以幫助模型捕捉資料中的複雜模式。

減少正則化強度

如果正則化強度過高,模型的複雜度會受到限制,導致欠擬合。可以透過減少正則化強度來緩解這個問題。

程式碼示例 - 增加模型複雜度

我們將使用多項式迴歸模型來演示如何減輕欠擬合。

from sklearn.preprocessing import PolynomialFeatures

# 多項式迴歸模型(減輕欠擬合)
poly_features = PolynomialFeatures(degree=3)
X_poly_train = poly_features.fit_transform(X_train)
X_poly_test = poly_features.transform(X_test)
poly_reg = LinearRegression()
poly_reg.fit(X_poly_train, y_train)
y_poly_train_pred = poly_reg.predict(X_poly_train)
y_poly_test_pred = poly_reg.predict(X_poly_test)

# 訓練集和測試集的表現
print("多項式迴歸 - 訓練集誤差:", mean_squared_error(y_train, y_poly_train_pred))
print("多項式迴歸 - 測試集誤差:", mean_squared_error(y_test, y_poly_test_pred))

# 視覺化結果
plt.scatter(X, y, color='blue', label='資料點')
plt.plot(X, poly_reg.predict(poly_features.transform(X)), color='red', label='多項式迴歸擬合線')
plt.xlabel('年齡')
plt.ylabel('武功值')
plt.title('多項式迴歸(減輕欠擬合)')
plt.legend()
plt.show()

透過使用三階多項式迴歸模型,我們可以看到模型在訓練集和測試集上的表現有所改善,從而減輕了欠擬合現象。

4. 過擬與欠擬合的對比

4.1 視覺化對比

為了更直觀地理解過擬合和欠擬合,我們透過視覺化來展示它們的區別。我們將使用之前生成的武俠資料集,並同時展示欠擬合、適度擬合和過擬合的模型擬合情況。

程式碼示例

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

# 生成武俠資料集
np.random.seed(42)
X = np.linspace(1, 10, 100)
y = 2 * X + np.sin(X) * 5 + np.random.randn(100) * 2  # 假設某個武俠角色的武功值與其年齡的關係

# 拆分資料集
X = X.reshape(-1, 1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 欠擬合模型 - 簡單線性迴歸
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
y_lin_pred = lin_reg.predict(X)

# 適度擬合模型 - 三階多項式迴歸
poly_reg_3 = make_pipeline(PolynomialFeatures(degree=3), LinearRegression())
poly_reg_3.fit(X_train, y_train)
y_poly_3_pred = poly_reg_3.predict(X)

# 過擬合模型 - 二十階多項式迴歸
poly_reg_20 = make_pipeline(PolynomialFeatures(degree=20), LinearRegression())
poly_reg_20.fit(X_train, y_train)
y_poly_20_pred = poly_reg_20.predict(X)

# 視覺化結果
plt.figure(figsize=(14, 7))

# 原始資料點
plt.scatter(X, y, color='blue', label='資料點')

# 欠擬合
plt.plot(X, y_lin_pred, color='green', label='線性迴歸(欠擬合)')

# 適度擬合
plt.plot(X, y_poly_3_pred, color='orange', label='三階多項式迴歸(適度擬合)')

# 過擬合
plt.plot(X, y_poly_20_pred, color='red', label='二十階多項式迴歸(過擬合)')

plt.xlabel('年齡')
plt.ylabel('武功值')
plt.title('過擬合與欠擬合的對比')
plt.legend()
plt.show()

結果分析

在這個視覺化示例中,我們可以清楚地看到三種模型的擬合情況:

  • 欠擬合(綠色線):簡單的線性迴歸模型無法捕捉資料中的複雜模式,導致在訓練集和測試集上都表現不佳。
  • 適度擬合(橙色線):三階多項式迴歸模型能夠較好地捕捉資料中的規律,同時在訓練集和測試集上都有較好的表現。
  • 過擬合(紅色線):二十階多項式迴歸模型雖然在訓練集上表現非常好,但在測試集上表現很差。模型過於複雜,傾向於記住訓練資料中的噪聲和細節。

透過這種對比,可以幫助我們更好地理解過擬合和欠擬合現象,以及如何在模型訓練中找到適度的複雜度。

[ 抱個拳,總個結 ]

在本文中,我們詳細討論了過擬合和欠擬合這兩個機器學習中常見的問題。我們透過定義、原因、表現和解決方法的層層解析,幫助少俠理解和識別這些現象,並提供了實際的程式碼示例和案例研究來進一步說明。

過擬合

過擬合是指模型在訓練資料上表現良好,但在測試資料上表現差。這通常是因為模型過於複雜,記住了訓練資料中的噪聲和細節。解決過擬合的方法包括:

  • 增加資料量
  • 正則化方法(L1, L2)
  • 剪枝(對於決策樹)
  • 交叉驗證
  • 提前停止訓練
  • Dropout

欠擬合

欠擬合是指模型在訓練資料和測試資料上都表現不佳。這通常是因為模型過於簡單,無法捕捉資料中的規律。解決欠擬合的方法包括:

  • 增加模型複雜度
  • 提供更多特徵
  • 減少正則化強度

在實際專案中避免過擬合和欠擬合

在實際專案中,避免過擬合和欠擬合是構建高效能模型的關鍵。以下是一些實用的建議:

  1. 合理選擇模型:根據資料的複雜度選擇合適的模型。如果資料複雜,選擇更復雜的模型;如果資料簡單,選擇簡單的模型。
  2. 充分利用資料:增加訓練資料的量,同時確保資料的多樣性和代表性。
  3. 特徵工程:透過特徵工程來提升模型的效能。可以增加有意義的特徵,或者透過特徵選擇來減少冗餘特徵。
  4. 正則化技術:合理使用正則化技術,如L1正則化和L2正則化,來防止模型過擬合。
  5. 交叉驗證:透過交叉驗證來評估模型的泛化能力,選擇最佳的模型引數。

透過本文的學習,希望少俠能夠更好地理解過擬合和欠擬合的概念,並在實際專案中應用相應的解決方法,構建出效能優良的機器學習模型。

[ 演算法金,碎碎念 ]

全網同名,日更萬日,讓更多人享受智慧樂趣

煩請大俠多多 分享、在看、點贊,助力演算法金又猛又持久、很黃很 BL 的日更下去;

同時邀請大俠 關注、星標 演算法金,圍觀日更萬日,助你功力大增、笑傲江湖

相關文章