机器学习最简单的算法KNN

注:用的pycharm,需要安装sklearn(我安装的anaconda)

KNN(k-nearest neighbors)算法

图1简单例子
简单例子,判断红色处应该是什么颜色的点,找最近的K个邻居,什么颜色多,红色处就应该是什么颜色。
一.步骤:
1.计算已知类别数据集中的点与当前点之间的距离;
2.按照距离递增次序排序,选取与当前点距离最小的k个点;
3.确定前k个点所在类别的出现频率,返回前k个点所出现频率最高的类别作为当前点的预测。
二.影响KNN的因素
1.K值得选择,K太小,分类结果易受噪声点的影响,K太大,近邻中又可能包含太多的其他类别的点,习惯上在0-数据集数量的平方根之间。
2.距离度量(判断两个点间的距离,与数据集的分布规律有关),常见的有欧氏距离,曼哈顿距离,切比雪夫距离,马氏距离,余弦距离,pearson相关距离等。
图2sklearn距离参数选择
metric是sklearn中KNN参数之一,与P来用于设置距离度量
3.权重,weights: 'uniform’都一样,‘distance’,距离近的点比距离远的点影响大,‘callable’,自定义函数 。(什么时候需要改权重,还没有用到)
三.决策规则,计算距离的时候,sklearn会根据数据集大小自动选择分类决策规则减少计算
图3
详情见:http://www.cnblogs.com/pinard/p/6061661.html
三.数据处理,有些数据的属性范围比较大,有些数据属性范围比较小,为了使他们的影响程度一致,需要对数据进行标准化和归一化,全部变成0-1内的数。
图4为什么要标准化归一化
归一化:(X-X.min)/(X.max-X.min)
标准化/Z-Score归一化:(X-X.mean)/X.std mean-平均数,std-标准差
四.交叉验证和网格搜索确定最佳参数
图5参数
KNN参数 n_neighbors是K值,algorithm是决策规则,n_jobs是并发数目。
图6交叉验证原理
交叉验证是验证一个模型的准确率,一般4-6折交叉验证,网格搜索就是所有模型进行交叉验证。
五.代码
鸢尾花例子:

from sklearn import datasets#导入sklearn数据集
from sklearn.neighbors import KNeighborsClassifier#分类

iris = datasets.load_iris()#加载鸢尾花数据集
print(iris.DESCR)#输出数据集的信息,查看属性,数据集数量和种类
X=iris.data#分离数据集的属性和标签,标签就是表明种类
Y=iris.target
print(X.shape)#输出样本数量,属性数量

#分离数据集为训练集和测试集,用测试集判断准确率
from sklearn.model_selection import train_test_split
X_train,X_test,Y_train,Y_test=train_test_split(X,Y,test_size=1/3)#2/3,100个训练,1/3,50个测试验证,每次结果不一样随机分类,

#导包标准化,原理以上说过了,这里直接导包方便
from sklearn.preprocessing import StandardScaler
standardscaler=StandardScaler()
standardscaler.fit(X_train)
X_train=standardscaler.transform(X_train)
X_test=standardscaler.transform(X_test)
print('ok')
'''
#KNN模型参数选择,此处用for循环网格搜索
from sklearn.model_selection import cross_val_score
import numpy as np
#求最佳K值,cv分几份,score越接近于1越好,1-score越接近0越好,求uniform和distance哪个好
result={}
weights=['uniform','distance']
for k in range(1,15):#一个参考标准sqrt(150)==12
    for w in weights:
        knn = KNeighborsClassifier(n_neighbors=k, weights=w,)
        sm=cross_val_score(knn,X,Y,scoring='accuracy',cv=6).mean()#交叉验证cross_val_score选择最合适的参数,分类scoring='accuracy'评价指标
        result[w+str(k)]=sm
print(result)
print(list(result)[np.array(list(result.values())).argmax()])
'''
#导包网格搜索,搜索算法最合适的参数
from sklearn.model_selection import GridSearchCV#grid网格,search搜索
# 构造一些属性
params = {'n_neighbors':[i for i in range(1,15)],
          'weights':['uniform','distance'],
          'p':[1,2]}
# 进行网格搜索
knn=KNeighborsClassifier()
grid = GridSearchCV(knn, params,scoring='accuracy',cv=6)
grid.fit(X_train, Y_train)
# 预测准确率
print("在测试集上准确率:", grid.score(X_test, Y_test))
print("在交叉验证当中最好的结果:", grid.best_score_)
print("选择最好的模型是:", grid.best_estimator_)
#print("每个超参数每次交叉验证的结果:", gcv.cv_results_)

#knn算法流程
knn=grid.best_estimator_#最好的模型赋给knn
knn.fit(X_train,Y_train)#fit用于训练
Y_pred=knn.predict(X_test)#predict用于预测
'''
#预测结果展示
labels = ["setosa", "versicolor", "virginica"]
for i in range(len(Y_pred)):
    print("%d:  真实值:%s  预测值:%s" % ((i+1), labels[Y_test[i]],labels[Y_pred[i]]))
'''
print("准确率:",knn.score(X_test,Y_test))

#绘图,用matplotlib知识,博士比较手生,写的比较简单
import matplotlib.pyplot as pyb
#四个属性,四维空间,降维,切片
pyb.subplot(1, 2, 1)  # 添加子块,第一个图
XX1=X[:,:2]
pyb.scatter(XX1[:,0],XX1[:,1],c=Y)
pyb.subplot(1, 2, 2)  # 添加子块,第一个图
XX2=X[:,2:]
pyb.scatter(XX2[:,0],XX2[:,1],c=Y)
pyb.show()

sepal length ,sepal width ,花萼长度花萼宽度petal length ,petal width 花瓣长度花瓣宽度,四个属性
Setosa,Versicolour,Virginica为三种鸢尾花种类

以上sklearn中的鸢尾花数据集,用于分类,KNN还可以用于回归用于判断,下面用sklearn中的波士顿例子用于回归

from sklearn import datasets
from sklearn.neighbors import KNeighborsRegressor#回归

boston = datasets.load_boston()#加载数据集
print(boston.DESCR)
X=boston.data
Y=boston.target
print(X.shape)#(样本数量,属性数量)

#划分训练集和测试集
from sklearn.model_selection import train_test_split
X_train,X_test,Y_train,Y_test=train_test_split(X,Y,test_size=1/5)

#标准化
from sklearn.preprocessing import StandardScaler
standardscaler=StandardScaler()
standardscaler.fit(X_train)
X_train=standardscaler.transform(X_train)
X_test=standardscaler.transform(X_test)

#KNN模型参数选择,建立模型
from sklearn.model_selection import  GridSearchCV
params=[
    {
        'weights': ['uniform','distance'],
        'n_neighbors': [k for k in range(1, 23)],
        'p':[1,2]
    }
]
knn=KNeighborsRegressor()
grid=GridSearchCV(knn,params,cv=5)
grid.fit(X_train,Y_train)
print("选择最好的模型是:", grid.best_params_)
#print("选择最好的模型是:", grid.best_estimator_)

#建立线性回归模型,并训练测试集
knn=grid.best_estimator_
knn.fit(X_train,Y_train)
Y_pred=knn.predict(X_test)

#回归模型评价
#不同于分类,预测结果是连续的,不能求准确率
#平均绝对误差、均方误差和中值绝对误差越接近0,模型性能越好。可解释方差值和R方差越靠近1,模型性能越好。
from sklearn.metrics import explained_variance_score,\
    mean_absolute_error,mean_squared_error,median_absolute_error,r2_score
print('波士顿线性回归的平均绝对误差为:',mean_absolute_error(Y_test,Y_pred))
print('波士顿线性回归的均方误差为:',mean_squared_error(Y_test,Y_pred))
print('波士顿线性回归的中值绝对误差为:',median_absolute_error(Y_test,Y_pred))
print('波士顿线性回归的可解释方差值为:',explained_variance_score(Y_test,Y_pred))
print('波士顿线性回归的R方差为:',r2_score(Y_test,Y_pred))

#绘图对比
#导入绘图模块并设置绘图参数
import  matplotlib.pyplot as plt
fig=plt.figure(figsize=(12,6))
plt.rcParams['font.family']="sans-serif"
plt.rcParams['font.sans-serif']="SimHei"
plt.rcParams['font.size']=12
plt.rcParams['axes.unicode_minus']=False
#绘图
plt.plot(range(Y_test.shape[0]),Y_test,color='blue',linewidth=1.5,linestyle='-')
plt.plot(range(Y_test.shape[0]),Y_pred,color='red',linewidth=1.5,linestyle='-.')
plt.legend(['原始值','预测值'])
plt.show()

图7运行结果
图8波士顿房价的属性
sklearn中还有很多数据集
图9常见数据集
就说两个例子,一个分类一个回归,还有其他sklearn数据集例子见
https://www.cnblogs.com/nolonely/p/6980160.html
六.总结
优点
1.KNN 理论简单,容易实现,既可以分类也可以回归;
2. 精度高,对异常值不敏感,几个异常值无关大碍;
3. 新数据可以直接加入数据集而不必进行重新训练。
缺点
1.分类计算量大时,内存开销大,必须保存全部数据集,即空间复杂度高;
2.KNN 无法给出基础结构信息,无法知晓平均实例样本与典型实例样本具有什么特征,即无法给出数据的内在含义(决策树),可解释性差;
3.对于稀疏数据集束手无策,要求样本数据平衡,否则预测偏差比较大。
4.只适用于监督学习,就标签表明种类。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐