在KNN(K-近邻)算法中,数据均一化(归一化)是预处理的关键步骤,用于消除不同特征量纲差异对距离计算的影响。以下是两种常用的归一化操作及其核心要点:
质押
一 、主要思想
1. 最值归一化(Min-Max Normalization)
公式:
特点:
- 将数据映射到 [0, 1] 区间内。
- 适用场景:特征分布有明显边界(如像素值0-255、评分0-100),且数据中异常值较少16。
- 缺点:对异常值敏感,若存在极端值(如极大或极小值),可能导致大部分数据集中在某个狭窄区间,影响模型性能
2. 均值方差归一化(Z-Score Standardization)
公式:
(其中 μ 为均值,σ为标准差)
特点:
- 将数据转换为均值为 0、方差为 1 的分布。
- 适用场景:数据分布无明显边界,或存在极端值(如收入、房价等连续型特征)。
- 优点:对异常值的鲁棒性优于最值归一化,适用于大多数机器学习算法。
归一化在KNN中的必要性
- 距离计算敏感性问题:KNN依赖距离度量(如欧氏距离),若特征尺度差异大(如年龄0-100 vs. 收入0-100000),大范围特征会主导距离计算,导致模型偏差。
- 模型性能优化:归一化后数据分布更均匀,可提升KNN的分类精度和收敛速度。
3.注意事项
- 训练集与测试集统一处理:需先对训练集计算归一化参数(如min/max、均值/标准差),再对测试集应用相同参数,避免数据泄露
- 算法选择建议:优先使用均值方差归一化,因其对异常值和数据分布的适应性更强
二、算法实现
(1)主要函数:sklearn.preprocessing.StandardScaler()
(2)关键参数
参数 | 作用 | 默认值 |
---|---|---|
copy | 是否创建数据副本(False 时可能直接修改原始数据,需注意数据类型兼容性)4 | True |
with_mean | 是否对数据去均值(设为 False 时跳过中心化,适用于稀疏矩阵处理)4 | True |
with_std | 是否对数据缩放至单位方差(设为 False 时仅中心化,不缩放)4 | True |
scale_
:每个特征的标准差(缩放比例)。mean_
:每个特征的均值。var_
:每个特征的方差。n_samples_seen_
:已处理的样本总数(支持在线学习时统计增量数据)。
(3)示例
1、最大值最小值均一化
import numpy as np
from sklearn import datasets
#加载鸢尾花数据集
iris=datasets.load_iris()
X = iris.data
y = iris.target
#最大最小值归一化
np.max(X[:,0])
np.min(X[:,0])
#对每一列进行最值归一化
X[:,0] = (X[:,0] - np.min(X[:,0])) / (np.max(X[:,0]) - np.min(X[:,0])) #第0列
X[:,1] = (X[:,1] - np.min(X[:,1])) / (np.max(X[:,1]) - np.min(X[:,1])) #第1列
X[:,2] = (X[:,2] - np.min(X[:,2])) / (np.max(X[:,2]) - np.min(X[:,2])) #第2列
X[:,3] = (X[:,3] - np.min(X[:,3])) / (np.max(X[:,3]) - np.min(X[:,3])) #第3列
2、归零均一化
import numpy as np
from sklearn import datasets
#加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
#计算均值、标准差
np.mean(X[:,0])
np.std(X[:,0])
#每列归一化
X[:,0] = (X[:,0] - np.mean(X[:,0]))/np.std(X[:,0])
X[:,1] = (X[:,1] - np.mean(X[:,1]))/np.std(X[:,1])
X[:,2] = (X[:,2] - np.mean(X[:,2]))/np.std(X[:,2])
X[:,3] = (X[:,3] - np.mean(X[:,3]))/np.std(X[:,3])
3、scikit-learn 中的StandardScaler
import numpy as np
from sklearn import datasets
#加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
from sklearn.preprocessing import StandardScaler #均一化模块
standard_scaler = StandardScaler()
standard_scaler.fit(X)
standard_scaler.mean_ #均值
standard_scaler.scale_ #标准差
X = standard_scaler.transform(X)#均一化后重新赋值给X
print(X[:5] )
'''
结果:
array([[-0.90068117, 1.01900435, -1.34022653, -1.3154443 ],
[-1.14301691, -0.13197948, -1.34022653, -1.3154443 ],
[-1.38535265, 0.32841405, -1.39706395, -1.3154443 ],
[-1.50652052, 0.09821729, -1.2833891 , -1.3154443 ],
[-1.02184904, 1.24920112, -1.34022653, -1.3154443 ]])
'''
#使用归一化的数据进行预测分类
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,train_size=0.8,random_state=666)
from sklearn.preprocessing import StandardScaler #均一化模块
standard_scaler = StandardScaler()
standard_scaler.fit(X_train) #适配数据
standard_scaler.mean_ #均值
standard_scaler.scale_ #标准差
X_train_standard = standard_scaler.transform(X_train) #X_train 归一
X_test_standard = standard_scaler.transform(X_test) #X_test 归一
from sklearn.neighbors import KNeighborsClassifier
knn_classifier = KNeighborsClassifier(n_neighbors=5)
knn_classifier.fit(X_train_standard,y_train)
knn_classifier.score(X_test_standard, y_test) #结果:1.0
特别注意:
在进行归零均一化操作时,要对训练集和测试集分别进行归一化后才能进行分类预测。一般先求出训练集的 mean(均值) 和scale (标准差)再进行归一transform操作,但值得注意的是,测试集不用再进行mean和sacle的计算,直接使用训练集即可。因为现实中的数据有时候很难进行归一化。