import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier #导入knnfrom 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为多少
Es gibt einige neue Probleme. Wenn wir den Datensatz teilen, muss der k-Wert mit der höchsten Punktzahl unterschiedlich sein, da er zufällig geteilt wird. Aus diesem Grund werden wir eine Kreuzvalidierung (k-facher Test) einführen.
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())#方差,查看模型是否稳定
Nun, an dieser Stelle können wir zusammenfassen
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更加稳定
Dann gibt es noch ein weiteres Problem: Da bei der Berechnung von knn die Entfernung berücksichtigt wird, hört es sich überhaupt nicht gut an, wenn der Dimensionsunterschied jedes Index zu diesem Zeitpunkt zu groß ist, also müssen wir [normalisieren]
(Normalisierung, auch bekannt als Min-Max-Skalierung)
Hier gibt es einen bemerkenswerten Punkt: [Teilen Sie zuerst den Datensatz und den Testsatz und normalisieren Sie ihn dann! 】
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为多少
Jetzt gibt es noch ein kleines zusätzliches Problem,
Die Knn-Methode verwendet die Ein-Punkt-Eins-Abstimmungsmethode, um zu sehen, welches Lager mehr Personen in einem Bereich hat.
Aber nach dem gesunden Menschenverstand muss ein unbekannter Punkt einem näher bei ihm liegenden Punkt ähnlicher sein,
Wenn k 8 ist, sind 5 Nachbarn eines Punktes weit von ihm entfernt und 3 Nachbarn sind ihm sehr nahe,
Zu diesem Zeitpunkt wird knn ihn als eine Gruppe von 5 beurteilen, aber im Leben werden wir ihn definitiv als eine Gruppe von drei beurteilen
Zu diesem Zeitpunkt muss [Distanzstrafe] hinzugefügt werden, der Optimierungseffekt muss jedoch in der Praxis sorgfältig berücksichtigt werden.
Geeignet für Datensätze mit vielen Ausreißern
Verwendung: Gewichte hinzufügen = 'Distanz', was bedeutet, dass Entfernungsstrafen hinzugefügt werden
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())