【机器学习】以KNN为例的交叉验证 网格搜索

KNN

K-Nearest Neighbors 简称为KNN,根据k个最近的邻居的类别判断当前样本的类别,k一般取奇数。

k个邻居中哪种类别的样本多,就判断这个为这个类别

  • 距离判断

    knn首先要判断两个样本之间的距离,距离有多种表示方式

    • 欧氏距离
      • 生活中常用的距离公式,二维空间中的两点 ( x 1 , y 1 ) ( x 2 , y 2 ) (x_1,y_1)(x_2,y_2) (x1,y1)(x2,y2)距离表示为 ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 \sqrt{\left(x_{1}-x_{2}\right)^{2}+\left(y_{1}-y_{2}\right)^{2}} (x1x2)2+(y1y2)2
      • 多个维度差距的综合
    • 曼哈顿距离
      • 二维空间中的两点 ( x 1 , y 1 ) ( x 2 , y 2 ) (x_1,y_1)(x_2,y_2) (x1,y1)(x2,y2)距离表示为 ( x 1 − x 2 ) + ( y 1 − y 2 ) (x_1-x_2)+(y_1-y_2) (x1x2)+(y1y2)
      • 可以理解为是每个维度上的距离之和
  • 缺点

    对于高维数据,并不合适。且当数据量很大计算效率会很低

    维度变大,数据变得稀疏,距离会很远

  • class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, algorithm='auto')

    • n_neighbors n的大小 邻居的数量
    • 创建之后使用fit训练,拟合数据
    • predict进行预测
    • score准确率
    from sklearn.datasets import load_iris
    from sklearn.model_selection import train_test_split
    from sklearn.neighbors import KNeighborsClassifier
    
    x,y = load_iris(return_X_y=True)   # 加载数据集
    x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3,shuffle=True)  # 数据集划分并随机打乱
    model = KNeighborsClassifier(n_neighbors=7)  # 创建预估器
    model.fit(x_train,y_train) # 拟合数据 进行训练
    y_pre = model.predict(x_test) # 进行预测
    print(sum(y_pre==y_test)/y_test.shape[0]) # 进行判断,正确的累加, 求准确率
    model.score(x_test,y_test)# 准确率
    
    '''
    0.9777777777777777
    0.9777777777777777
    '''
    
    

模型的选择和调优(以KNN为例)

  1. 交叉验证
  • 保留交叉验证

    • 把数据集根据比率随机划分为训练集和测试集
    • from sklearn.model_selection import train_test_split
    • x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3,shuffle=True) # 数据集划分并随机打乱
  • K折交叉验证

    • 将数据随机划分为多个部分,每个部分就是一折
    • 每一折作为测试集,其他作为训练集,每一折都会被用于训练
    • from sklearn.model_selection import KFold
    • kfold = KFold() # K折交叉验证 参数n_splits默认值为5,划分为5折
    • index = kfold.split(x,y) # 返回索引
  • 分层k折交叉验证

    • 保证每一折都是原始数据的样本比例
    • sklearn.neighbors.StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
    • 同样返回索引
# 交叉验证
from sklearn.datasets import load_wine
from sklearn.model_selection import KFold,StratifiedKFold
from sklearn.neighbors import KNeighborsClassifier 
from sklearn.preprocessing import StandardScaler
x,y = load_wine(return_X_y=True)  # 获得数据,以data,target 返回

kfold = KFold() # K折交叉验证 
index = kfold.split(x,y) # 返回索引

# S_kfold = StratifiedKFold() # 分层交叉验证
# index = S_kfold.split(x,y)

KNN_class = KNeighborsClassifier(n_neighbors=7)  # KNN
scaler = StandardScaler() # 标准化
score_list = []
for index_train,index_test in index:
    x_train = x[index_train]
    y_train = y[index_train]
    x_test = x[index_test]
    y_test = y[index_test]
    x_train = scaler.fit_transform(x_train) # 标准化
    x_test = scaler.transform(x_test)
    KNN_class.fit(x_train,y_train)
    score = KNN_class.score(x_test,y_test) # 获得准确率
    score_list.append(score)

print(sum(score_list)/len(score_list)) # 获得几次的平均准确率

  1. 超参数搜索(网格搜索)

实例化预估器时,预估器会传入一些人为规定的参数如n_neighbors, 这样的参数被称为超参数。

通过网格搜索,可以找到训练效果最好的超参数

  • sklearn.model_selection.GridSearchCV(estimator, param_grid)
  • estimator 需要进行优化的预估器,模型
  • param_grid 超参数字典 字典的键是参数列表

GridSearchCV这个类有这样的一些属性

best_params_ 最佳参数

best_score_ 在训练集中的准确率

best_estimator_ 最佳估计器

cv_results_ 交叉验证过程描述

best_index_最佳k在列表中的下标

# 超参数搜索 网格搜索
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split,GridSearchCV  # 网格搜索
import joblib
'''
GridSearchCV
best_params_  最佳参数
best_score_ 在训练集中的准确率
best_estimator_ 最佳估计器
cv_results_ 交叉验证过程描述
best_index_最佳k在列表中的下标
'''

x,y = load_breast_cancer(return_X_y=True)
scaler = StandardScaler()
x = scaler.fit_transform(x)  # 标准化

# 数据集划分
train_x,test_x,tain_y,test_y = train_test_split(x,y,shuffle=True,random_state=1,test_size=0.3)

KNN_classfier = KNeighborsClassifier()


n_dic = {
    'n_neighbors':[3,5,7,9]
}

model = GridSearchCV(KNN_classfier,param_grid=n_dic)
model.fit(x_train,y_train)
print(model.score(x_test,y_test))
print(model.best_params_)
print('*'*20)
print(model.best_score_)
print('*'*20)
print(model.best_estimator_)
print(type(model))
'''
0.9142857142857143
{'n_neighbors': 3}
********************
0.9514778325123153
********************
KNeighborsClassifier(n_neighbors=3)

'''

模型的保存和加载

使用joblib中的两个函数

joblib.dump(model.best_estimator_,'./best_KNN_cancer.plk') # 模型保存  保存模型结构和参数
model = joblib.load('./best_KNN_cancer.plk') # 模型加载
print(type(model))
'''
model = joblib.load('./KNN-7.plk')
print(type(model))
'''

你可能感兴趣的:(机器学习,算法,人工智能)