1、KNN

1.1、KNN工作原理

K-Nearest-Neighbors,是监督学习算法,核心思想是通过计算给定样本与数据集中所有样本的距

离,找到距离最近的K个样本,然后根据这K个样本的类别或值来预测当前样本的类别或值。

先计算距离,再选择最近距离的K个样本

K值:K值的选择对结果影响很大。K值过小容易过拟合,K值过大则可能欠拟合。

1.2、KNN_API分类器

K邻近类里可以设置权重weights = distance,这样就会根据距离分类,而不会出现如过K=2一人一

票之后的按原顺序分配

from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=2)
X = [[2, 1], [3, 1], [1, 4], [2, 6]] # 特征
y = [0, 0, 1, 1] # 标签
knn.fit(X,y)
knn_pred = knn.predict([[4,9]])
print(knn_pred)

[1]
1.3、KNN_API回归器
from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor
knn = KNeighborsRegressor(n_neighbors=2,weights='distance')
X = [[2, 1], [3, 1], [1, 4], [2, 6]] # 特征
y = [0.5, 0.33, 4, 3]
knn.fit(X,y)
y_pred = knn.predict([[4,9]])
print(y_pred)

[3.38208553]

2、常见测距方法(了解)

欧式距离(两点之间的直线距离)

曼哈顿距离(参考曼哈顿街道)

切比雪夫距离(两点各坐标数值差的最大值)

闵可夫斯基距离(是一种用于度量多维空间中两点间距离的通用方法)

3、特征转换——归一化、标准化

3.1、归一化

将数据按比例缩放到一个固定范围[𝑚𝑖𝑛,𝑚𝑎𝑥]

消除量纲差异,避免模型被大范围特征主导,加速模型收敛,适配特定模型需求

这里的例子是按列(按特征)归一化的

from sklearn.preprocessing import MinMaxScaler
X = [[2, 1], [3, 1], [1, 4], [2, 6]]
scaler = MinMaxScaler(feature_range=(-1,1)).fit_transform(X)
print(scaler)

[[ 0.  -1. ]
 [ 1.  -1. ]
 [-1.   0.2]
 [ 0.   1. ]]
3.2、标准化

将数据调整为均值为0、标准差为1的标准分布。

from sklearn.preprocessing import StandardScaler
X = [[2, 1], [3, 1], [1, 4], [2, 6]]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print(X_scaled)

[[ 0.         -0.94280904]
 [ 1.41421356 -0.94280904]
 [-1.41421356  0.47140452]
 [ 0.          1.41421356]]

4、KNN案例——心脏病预测

4.1、代码

数据集https://www.kaggle.com/datasets/johnsmith88/heart-disease-dataset

这里用到了ColumnTransformer列转换器,参数是transformers=[],里面传入针对不同特征类型处

理特征的方式,独热编码里的drop = 'first'可以默认去掉第一列避免多重共线性,score =

knn.score(x_test,y_test)这是一个直接查看accuracy的方法

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler,OneHotEncoder
from sklearn.neighbors import KNeighborsClassifier

dataset = pd.read_csv('data/heart_disease.csv')
dataset.dropna(inplace=True)

x = dataset.drop('是否患有心脏病',axis=1)
y = dataset['是否患有心脏病']
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.3,random_state=42)

numerical_features = ["年龄", "静息血压", "胆固醇", "最大心率", "运动后的ST下降", "主血管数量"]
categorical_features = ["胸痛类型", "静息心电图结果", "峰值ST段的斜率", "地中海贫血"]
binary_features = ["性别", "空腹血糖", "运动性心绞痛"]

column_transformer = ColumnTransformer(transformers=[
    ("num",StandardScaler(),numerical_features),
    ('cat',OneHotEncoder(drop = 'first'),categorical_features),
    ('bin','passthrough',binary_features)
])
x_train = column_transformer.fit_transform(x_train)
x_test = column_transformer.transform(x_test)

knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(x_train,y_train)

score = knn.score(x_test,y_test)
print(score)

0.9253246753246753
4.2、模型保存

这是一个保存模型的方式,用来保存已经训练好的模型

import joblib

joblib.dump(knn, 'knn_model.joblib')
knn_loaded = joblib.load('knn_model.joblib')
print(knn_loaded.score(x_test,y_test))
y_pred = knn_loaded.predict(x_test[[10]])
print(y_pred,y_test[10])
4.3、网格搜索(Grid Search)

通过遍历预定义的超参数组合,找到使模型性能最优的参数配置。通过自动化调参避免手动试错,

提高效率。sklearn.model_selection.GridSearchCV

import pandas as pd
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler,OneHotEncoder
from sklearn.neighbors import KNeighborsClassifier

dataset = pd.read_csv('data/heart_disease.csv')
dataset.dropna(inplace=True)

x = dataset.drop('是否患有心脏病',axis=1)
y = dataset['是否患有心脏病']
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.3,random_state=42)

numerical_features = ["年龄", "静息血压", "胆固醇", "最大心率", "运动后的ST下降", "主血管数量"]
categorical_features = ["胸痛类型", "静息心电图结果", "峰值ST段的斜率", "地中海贫血"]
binary_features = ["性别", "空腹血糖", "运动性心绞痛"]

column_transformer = ColumnTransformer(transformers=[
    ("num",StandardScaler(),numerical_features),
    ('cat',OneHotEncoder(drop = 'first'),categorical_features),
    ('bin','passthrough',binary_features)
])
x_train = column_transformer.fit_transform(x_train)
x_test = column_transformer.transform(x_test)

knn = KNeighborsClassifier()
params_grid = {'n_neighbors':list(range(1,11))} # KNN的K值
gs_cv = GridSearchCV(estimator=knn, param_grid=params_grid,cv = 10) # K折交叉验证cv
gs_cv.fit(x_train,y_train)
print(pd.DataFrame(gs_cv.cv_results_).to_string())
print(gs_cv.best_params_)
print(gs_cv.best_score_)
print(gs_cv.best_estimator_)

   mean_fit_time  std_fit_time  mean_score_time  std_score_time  param_n_neighbors               params  split0_test_score  split1_test_score  split2_test_score  split3_test_score  split4_test_score  split5_test_score  split6_test_score  split7_test_score  split8_test_score  split9_test_score  mean_test_score  std_test_score  rank_test_score
0       0.000772      0.000087         0.142634        0.420856                  1   {'n_neighbors': 1}           0.986111           1.000000           0.972222           0.986111           1.000000           0.986111           0.972222           0.985915           0.957746           0.943662         0.979010        0.016953                1
1       0.000873      0.000264         0.002216        0.000183                  2   {'n_neighbors': 2}           0.944444           0.930556           0.916667           0.930556           0.958333           0.944444           0.902778           0.943662           0.901408           0.845070         0.921792        0.031117                2
2       0.000770      0.000159         0.002498        0.000352                  3   {'n_neighbors': 3}           0.930556           0.833333           0.902778           0.861111           0.875000           0.916667           0.888889           0.845070           0.845070           0.774648         0.867312        0.043574                7
3       0.000732      0.000076         0.002418        0.000396                  4   {'n_neighbors': 4}           0.902778           0.805556           0.888889           0.875000           0.888889           0.875000           0.875000           0.859155           0.816901           0.774648         0.856182        0.040169               10
4       0.000802      0.000137         0.002450        0.000418                  5   {'n_neighbors': 5}           0.930556           0.805556           0.847222           0.916667           0.888889           0.902778           0.888889           0.901408           0.802817           0.760563         0.864534        0.054298                8
5       0.000753      0.000093         0.002428        0.000304                  6   {'n_neighbors': 6}           0.916667           0.833333           0.888889           0.888889           0.888889           0.916667           0.902778           0.915493           0.802817           0.760563         0.871498        0.051363                5
6       0.000743      0.000078         0.002412        0.000298                  7   {'n_neighbors': 7}           0.958333           0.875000           0.902778           0.930556           0.902778           0.902778           0.916667           0.915493           0.873239           0.788732         0.896635        0.042995                3
7       0.000717      0.000042         0.002428        0.000313                  8   {'n_neighbors': 8}           0.944444           0.819444           0.888889           0.916667           0.902778           0.888889           0.930556           0.915493           0.845070           0.816901         0.886913        0.042873                4
8       0.000727      0.000057         0.002531        0.000371                  9   {'n_neighbors': 9}           0.916667           0.819444           0.875000           0.902778           0.875000           0.875000           0.902778           0.887324           0.830986           0.816901         0.870188        0.034057                6
9       0.000811      0.000259         0.002538        0.000359                 10  {'n_neighbors': 10}           0.888889           0.791667           0.861111           0.902778           0.875000           0.861111           0.875000           0.887324           0.845070           0.802817         0.859077        0.034666                9
{'n_neighbors': 1}
0.979010172143975
KNeighborsClassifier(n_neighbors=1)

也可以增加超参数来计算

params_grid = {'n_neighbors':list(range(1,11)),'weights':['uniform','distance'],'p':[1,2]} # KNN的K值

{'n_neighbors': 9, 'p': 2, 'weights': 'distance'}
0.9887910798122066
KNeighborsClassifier(n_neighbors=9, weights='distance')

使用最优模型去预测测试集数据

knn = gs_cv.best_estimator_
print(knn.score(x_test,y_test))

1.0

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐