數據集的標準化是scikit-learn中實現許多機器學習估計器的普遍要求;如果個別特征看起來或多或少不像標準正態分布數據:均值和單位方差為零的高斯分布,則它們的性能可能不好。
在實踐中,我們通常會忽略分布的形狀,而只是通過刪除每個特征的平均值來實現特征數據中心化,然后除以非常數特征的標準差來縮放數據。
例如,學習算法的目標函數中使用的許多元素(例如支持向量機的RBF內核或線性模型的l1和l2正則化器)都假定所有特征都圍繞零為中心并且具有相同階數的方差。如果某個特征的方差比其他特征大幾個數量級,則它可能會極大影響目標函數,并使估計器無法按預期從其他特征中正確學習。
sklearn 數據預處理中的數據標準化
核心思想
數據標準化(Standardization)是將特征數據轉換為均值為 0、標準差為 1 的分布(即標準正態分布)。其數學公式為:z=(x?μ)/σz = (x - μ) / σz=(x?μ)/σ
其中:
x
是原始特征值μ
是該特征的均值σ
是該特征的標準差z
是標準化后的值
標準化適用于特征尺度差異較大或算法假設數據服從正態分布的情況(如 SVM、邏輯回歸、PCA、神經網絡等)。
常用函數與類
1. sklearn.preprocessing.StandardScaler
這是最常用的標準化工具類。
參數說明:
參數名 | 類型 | 默認值 | 說明 |
---|---|---|---|
copy | bool | True | 是否復制數據。若為 False ,則嘗試在原數據上進行變換(不保證一定原地修改)。 |
with_mean | bool | True | 是否中心化(減去均值)。若為 False ,則不減均值。對稀疏矩陣必須設為 False 。 |
with_std | bool | True | 是否縮放(除以標準差)。若為 False ,則僅中心化。 |
屬性(擬合后可用):
屬性名 | 說明 |
---|---|
mean_ | 每個特征的均值(形狀為 (n_features,) ) |
scale_ | 每個特征的標準差(形狀為 (n_features,) ) |
var_ | 每個特征的方差(形狀為 (n_features,) ) |
n_samples_seen_ | 擬合時看到的樣本數 |
方法:
.fit(X[, y])
:計算均值和標準差。.transform(X)
:使用擬合的參數對數據進行標準化。.fit_transform(X[, y])
:先擬合再轉換。.inverse_transform(X)
:將標準化后的數據還原為原始尺度。.get_feature_names_out(input_features=None)
:獲取輸出特征名(適用于管道)。
返回值:
.fit()
:返回self
(用于鏈式調用).transform(X)
:返回numpy.ndarray
或scipy.sparse matrix
,形狀與輸入相同,類型為float64
簡單示例代碼
from sklearn.preprocessing import StandardScaler
import numpy as np# 創建示例數據
X = np.array([[1, 2],[3, 4],[5, 6],[7, 8]], dtype=float)print("原始數據:")
print(X)# 初始化標準化器
scaler = StandardScaler()# 擬合并轉換數據
X_scaled = scaler.fit_transform(X)print("\n標準化后數據:")
print(X_scaled)print("\n各特征均值:", scaler.mean_)
print("各特征標準差:", scaler.scale_)# 逆變換還原數據
X_original = scaler.inverse_transform(X_scaled)
print("\n逆變換還原數據:")
print(X_original)
輸出示例:
原始數據:
[[1. 2.][3. 4.][5. 6.][7. 8.]]標準化后數據:
[[-1.34164079 -1.34164079][-0.4472136 -0.4472136 ][ 0.4472136 0.4472136 ][ 1.34164079 1.34164079]]各特征均值: [4. 5.]
各特征標準差: [2.23606798 2.23606798]逆變換還原數據:
[[1. 2.][3. 4.][5. 6.][7. 8.]]
管道中使用示例:
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification# 生成示例數據
X, y = make_classification(n_samples=100, n_features=4, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 構建管道:先標準化,再分類
pipeline = Pipeline([('scaler', StandardScaler()),('classifier', SVC())
])pipeline.fit(X_train, y_train)
score = pipeline.score(X_test, y_test)
print(f"測試集準確率:{score:.4f}")
sklearn 數據預處理中的均值去除(Mean Removal / Centering)
核心思想
均值去除(Mean Removal),也稱為數據中心化(Centering),是指對每個特征維度減去其樣本均值,使得處理后的數據在該維度上的均值為 0。
數學公式:xcentered=x?mean(x)x_{centered} = x - mean(x)xcentered?=x?mean(x)
- 不改變數據的方差或分布形狀
- 僅將數據“平移”至以 0 為中心
- 是數據標準化(Standardization)的第一步(標準化 = 均值去除 + 方差縮放)
? 適用場景:
- 某些算法要求輸入數據均值為 0(如 PCA、SVM、神經網絡)
- 避免特征因均值偏移導致模型學習偏差
- 作為預處理步驟,常與縮放結合使用
常用函數與類
1. sklearn.preprocessing.StandardScaler
(最常用)
雖然名為“標準化器”,但通過設置 with_std=False
,可僅執行均值去除。
參數說明:
參數名 | 類型 | 默認值 | 說明 |
---|---|---|---|
copy | bool | True | 是否復制數據。若為 False ,嘗試原地修改(不保證)。 |
with_mean | bool | True | 是否進行均值去除(中心化)。必須為 True 才能去均值。 |
with_std | bool | True | 是否進行標準差縮放。設為 False 時僅做中心化。 |
?? 對稀疏矩陣(如
scipy.sparse
),with_mean=True
會報錯,因為會導致稠密輸出。
屬性(擬合后可用):
屬性名 | 說明 |
---|---|
mean_ | 每個特征的均值(形狀 (n_features,) ) |
scale_ | 若 with_std=True ,為標準差;否則為 None |
n_samples_seen_ | 擬合時看到的樣本數 |
方法:
.fit(X[, y])
:計算每個特征的均值。.transform(X)
:對數據執行中心化(減去均值)。.fit_transform(X[, y])
:先擬合再轉換。.inverse_transform(X)
:還原數據(加上均值)。.get_feature_names_out(...)
:獲取輸出特征名(兼容管道)。
返回值:
.fit()
→ 返回self
.transform(X)
→ 返回numpy.ndarray
或scipy.sparse matrix
(若輸入為稀疏且with_mean=False
),類型為float64
,形狀同輸入
簡單示例代碼
from sklearn.preprocessing import StandardScaler
import numpy as np# 創建示例數據
X = np.array([[1, 10],[2, 20],[3, 30],[4, 40]], dtype=float)print("原始數據:")
print(X)
print("原始均值:", np.mean(X, axis=0))# 初始化僅做均值去除的縮放器
scaler = StandardScaler(with_std=False) # 關閉標準差縮放# 擬合并轉換
X_centered = scaler.fit_transform(X)print("\n中心化后數據:")
print(X_centered)
print("中心化后均值:", np.mean(X_centered, axis=0)) # 應為 [0., 0.]print("\n學習到的均值:", scaler.mean_)# 逆變換還原原始數據
X_original = scaler.inverse_transform(X_centered)
print("\n逆變換還原數據:")
print(X_original)
輸出示例:
原始數據:
[[ 1. 10.][ 2. 20.][ 3. 30.][ 4. 40.]]
原始均值: [ 2.5 25. ]中心化后數據:
[[-1.5 -15. ][-0.5 -5. ][ 0.5 5. ][ 1.5 15. ]]
中心化后均值: [0. 0.]學習到的均值: [ 2.5 25. ]逆變換還原數據:
[[ 1. 10.][ 2. 20.][ 3. 30.][ 4. 40.]]
sklearn 數據預處理中的方差縮放(Scaling to Unit Variance)
核心思想
方差縮放(Variance Scaling) 是指將每個特征維度的數據除以其標準差(或等效統計量),使得縮放后的特征方差為 1(即單位方差)。
數學公式:xscaled=x/σx_{scaled} = x / σxscaled?=x/σ
其中:
x
是原始特征值σ
是該特征的標準差(std(x)
)x_scaled
是方差縮放后的值
? 注意:方差縮放通常不單獨使用,而是與均值去除(中心化) 結合構成完整的標準化(Standardization):
z = (x - μ) / σ
為什么需要方差縮放?
- 某些算法(如 SVM、KNN、PCA、神經網絡)對特征尺度敏感
- 若某特征方差遠大于其他特征,會主導目標函數或距離計算
- 保證所有特征在“相同量級”上,提升模型收斂速度和性能
常用函數與類
1. sklearn.preprocessing.StandardScaler
(最常用)
通過設置 with_mean=False
,可僅執行方差縮放(不中心化)。
參數說明:
參數名 | 類型 | 默認值 | 說明 |
---|---|---|---|
copy | bool | True | 是否復制數據。若為 False ,嘗試原地修改(不保證)。 |
with_mean | bool | True | 是否中心化。設為 False 可僅做方差縮放。 |
with_std | bool | True | 是否進行方差縮放。必須為 True 才生效。 |
?? 對稀疏矩陣,
with_mean=True
會導致報錯(因為中心化會破壞稀疏性),但with_mean=False
是安全的。
屬性(擬合后可用):
屬性名 | 說明 |
---|---|
scale_ | 每個特征的標準差(形狀 (n_features,) ) |
mean_ | 若 with_mean=True ,為均值;否則為 None |
var_ | 每個特征的方差(scale_ ** 2 ) |
n_samples_seen_ | 擬合時看到的樣本數 |
方法:
.fit(X[, y])
:計算每個特征的標準差(和均值,若啟用)。.transform(X)
:對數據執行縮放(和中心化,若啟用)。.fit_transform(X[, y])
:先擬合再轉換。.inverse_transform(X)
:還原數據(乘以標準差,加上均值)。.get_feature_names_out(...)
:獲取輸出特征名(兼容管道)。
返回值:
.fit()
→ 返回self
.transform(X)
→ 返回numpy.ndarray
或scipy.sparse matrix
(若輸入稀疏且with_mean=False
),類型為float64
,形狀同輸入
簡單示例代碼
from sklearn.preprocessing import StandardScaler
import numpy as np# 創建示例數據(注意:不同列方差差異大)
X = np.array([[1, 100],[2, 200],[3, 300],[4, 400]], dtype=float)print("原始數據:")
print(X)
print("原始標準差:", np.std(X, axis=0))# 初始化僅做方差縮放的縮放器(不中心化)
scaler = StandardScaler(with_mean=False, with_std=True)# 擬合并轉換
X_scaled = scaler.fit_transform(X)print("\n方差縮放后數據:")
print(X_scaled)
print("縮放后標準差:", np.std(X_scaled, axis=0)) # 應為 [1., 1.]print("\n學習到的標準差(scale_):", scaler.scale_)# 逆變換還原原始數據
X_original = scaler.inverse_transform(X_scaled)
print("\n逆變換還原數據:")
print(X_original)
輸出示例:
原始數據:
[[ 1. 100.][ 2. 200.][ 3. 300.][ 4. 400.]]
原始標準差: [1.11803399 111.80339887]方差縮放后數據:
[[0.89442719 0.89442719][1.78885438 1.78885438][2.68328157 2.68328157][3.57770876 3.57770876]]
縮放后標準差: [1. 1.]學習到的標準差(scale_): [ 1.11803399 111.80339887]逆變換還原數據:
[[ 1. 100.][ 2. 200.][ 3. 300.][ 4. 400.]]
僅方差縮放 vs 完整標準化 對比示例
import numpy as np
from sklearn.preprocessing import StandardScalerX = np.array([[1, 100],[2, 200],[3, 300],[4, 400]], dtype=float)# 僅方差縮放
scaler_var_only = StandardScaler(with_mean=False)
X_var_scaled = scaler_var_only.fit_transform(X)# 完整標準化(去均值 + 方差縮放)
scaler_full = StandardScaler()
X_standardized = scaler_full.fit_transform(X)print("僅方差縮放:\n", X_var_scaled)
print("完整標準化:\n", X_standardized)
輸出:
僅方差縮放:[[0.89442719 0.89442719][1.78885438 1.78885438][2.68328157 2.68328157][3.57770876 3.57770876]]完整標準化:[[-1.34164079 -1.34164079][-0.4472136 -0.4472136 ][ 0.4472136 0.4472136 ][ 1.34164079 1.34164079]]
在管道中使用示例:
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification# 生成數據(故意制造方差差異)
np.random.seed(42)
X, y = make_classification(n_samples=100, n_features=4, random_state=42)
# 放大第二列方差
X[:, 1] *= 100X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 管道:僅方差縮放 + SVM
pipeline = Pipeline([('var_scaler', StandardScaler(with_mean=False)), # 僅縮放方差('svm', SVC())
])pipeline.fit(X_train, y_train)
score = pipeline.score(X_test, y_test)
print(f"測試集準確率(僅方差縮放):{score:.4f}")# 對比:完整標準化
pipeline_full = Pipeline([('scaler', StandardScaler()), # 完整標準化('svm', SVC())
])
pipeline_full.fit(X_train, y_train)
score_full = pipeline_full.score(X_test, y_test)
print(f"測試集準確率(完整標準化):{score_full:.4f}")
與其他縮放器對比
縮放器 | 是否去均值 | 是否單位方差 | 是否受異常值影響 | 適用場景 |
---|---|---|---|---|
StandardScaler(with_mean=False) | ? | ? | 是 | 僅需統一方差,保留原始均值 |
StandardScaler() (默認) | ? | ? | 是 | 最常用標準化 |
MinMaxScaler | ? (映射到[0,1]) | ? | 是 | 需固定范圍,如圖像像素 |
RobustScaler | ? (中位數) | ? (IQR) | 否 | 含異常值的數據 |
注意事項
重要提醒:
- 方差縮放應在訓練集上擬合,然后應用于測試集/新數據。
- 若特征標準差為 0(常數特征),StandardScaler 會將其縮放為 0(可后續刪除或填充)。
- 對稀疏數據,使用
with_mean=False
是安全的;若需中心化,考慮 RobustScaler 或手動處理。 - 單獨使用方差縮放較少見,通常建議與均值去除結合使用(完整標準化)。
總結
方差縮放是確保所有特征具有相同“能量級別”的關鍵步驟。在 sklearn 中,通過 StandardScaler(with_mean=False) 可實現純方差縮放。雖然實踐中更常用完整標準化(with_mean=True),但在某些特定場景(如保留原始偏移量、處理稀疏數據)下,僅縮放方差仍具有實用價值。