KNNコード

import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier  #导入knn
from sklearn.model_selection import train_test_split  #导入训练集测试集划分
# KNN算法 全部用sklearn的包实现-

# 当我们有一个数据集data,data是包含数据和标签的,我们得先把他们分开

x = data.iloc[:,:-1]  #iloc方法,选择所有行,列不包括最后一个行列(假设最后一列是target)
y = data.iloc[:,-1]   #iloc方法,选所有行,仅选择最后一列(假设最后一列是target)
#还有一个loc的用法,loc是靠columns选择数据的
Xtrain,Xtest,Ytrain,Ytest = train_test_split(x,y,test_size=0.2,random_state=420)  #这里数据集划分要牢记【先x后y】

clf = KNeighborsClassifier(n_neighbors=3)  #n_neighbors表示k的个数
clf = clf.fit(Xtrain,Ytrain)  #开始拟合
score = clf.score(Xtest,Ytest)  #评分
result = clf.predict()  #当然也可以有预测


# 当然平常时候我们不知道k取多少,这时候可以绘制一个学习曲线(循环20次),看看k为多少的时候score最高
import matplotlib.pyplot as plt
score = [ ] 
krange = range(1,20) 
for i in krange:
	clf = KNeighborsClassifier(n_neighbors=i) 
	clf = clf.fit(Xtrain,Ytrain) 
	score.append(clf.score(Xtest,Ytest)) 
plt.plot(krange,score) 
plt.show()
print(score.index(max(score))+1)  #输出一下score最高值对应的k为多少

新たな問題がいくつかあり、データセットを分割する場合、ランダムに分割するため、最もスコアが高い k 値は異なるはずです。そこで、交差検証 (k 分割テスト) を導入します。

from sklearn.model_selection import cross_val_score as CVS
Xtrain,Xtest,Ytrain,Ytest = train_test_split(x,y,test_size=0.2,random_state=420)
clf = KNeighborsClassifier(n_neighbors=3)
cvs = CVS(clf,Xtrain,Ytrain,cv = 5)   #训练集对折五次,一共五个结果输出
print(cvs.mean())  #均值,查看模型的平均效果
print(cvs.var())  #方差,查看模型是否稳定

さて、この時点でまとめると、

score = [ ] 
var = [ ]
krange = range(1,20) 
for i in krange:
	clf = KNeighborsClassifier(n_neighbors=i) 
	cvs = CVS(clf,Xtrain,Ytrain,cv = 5)
	score.append(cvs.mean())
	var.append(cvs.var())
plt.plot(krange,score,color='k') 
plt.plot(krange,np.array(score)+np.array(var)*2,c='red',linestyle='--') 
plt.plot(krange,np.array(score)-np.array(var)*2,c='red',linestyle='--')
# 把图像画出来,另外多画两条,一条是均值+方差,一条均值-方差,这里主要是看近等评分下,那个k更加稳定

そして、もう一つ問題があるのですが、knnの計算には距離が関係するので、この時に各指数の次元差が大きすぎると全くよろしくないので、【正規化】する必要があります。

(正規化、Min-Max スケーリングとも呼ばれます)

ここで注目すべき点があり、 【まずデータセットとテストセットを分割してから正規化する!

from sklearn.preprocessing import MinMaxScaler as mms
Xtrain,Xtest,Ytrain,Ytest = train_test_split(x,y,test_size=0.2,random_state=420)

MMS_01=mms().fit(Xtrain) #求训练集最大/小值 
MMS_02=mms().fit(Xtest) #求测试集最大/小值

#转换 
X_train=MMS_01.transform(Xtrain) 
X_test =MMS_02.transform(Xtest)

score = [ ] 
var = [ ]
krange = range(1,20) 
for i in krange:
	clf = KNeighborsClassifier(n_neighbors=i) 
	cvs = CVS(clf,X_train,Y_train,cv = 5)
	score.append(cvs.mean())
	var.append(cvs.var())
plt.plot(krange,score,color='k') 
plt.plot(krange,np.array(score)+np.array(var)*2,c='red',linestyle='--') 
plt.plot(krange,np.array(score)-np.array(var)*2,c='red',linestyle='--')
print(score.index(max(score))+1)  #输出一下score最高值对应的k为多少

ここで、さらに小さな問題が発生します。

knn方式は範囲内でどちらの陣営が多いかを見る1点1票の方式を採用しており、

しかし常識によれば、未知の点は彼に近い点により似ているはずです。

k が 8 の場合、点の 5 つの隣接点は彼から遠く離れており、3 つの隣接点は彼に非常に近いです。

現時点ではknnは彼を5人グループとして判断しますが、人生では間違いなく彼を3人グループとして判断します

この際、[距離ペナルティ]を追加する必要がありますが、実際には最適化効果を慎重に考慮する必要があります。

外れ値が多いデータセットに適しています

使用法: 重みを追加 = '距離'、これは距離ペナルティを追加することを意味します

score = [ ] 
var = [ ]
krange = range(1,20) 
for i in krange:
	clf = KNeighborsClassifier(n_neighbors=i,weights='distance') 
	cvs = CVS(clf,X_train,Y_train,cv = 5)
	score.append(cvs.mean())
	var.append(cvs.var())

おすすめ

転載: blog.csdn.net/weixin_44820355/article/details/124711623