Python机器学习之KNN算法(包含实战)

好的,我们直接进入主题。

首先,我们来笼统的讲讲机器学习的步骤(这里是我自己查阅资料总结,若有不妥,还望指出)

-收集数据

-输入大数据

-提取特征

-机器学习算法训练模型

-测试调整算法

-得出最优模型

关于这些步骤,在后面的实例里我都会和大家具体的讲解。

接下来,我会用KNN的理论和一些KNN代码编程来让大家大致理解KNN算法(这里的代码编程不是实战,只是为了方便大家理解的一个例子)

K-近邻算法,又叫KNN算法,初学者感觉很高级的算法,但他其实只是数据挖掘技术中原理最简单的算法。

KNN的工作原理:给定一个已知标签类别的训练数据集,输入没有标签的新数据后,在训练集中找到与新数据最邻近的k个实例,如果这k个实例的多数属于某个类别,那么新数据就属于这个类别。上述原理是对其的官方解释,可以简单的理解为:你要判断类别的点由他最近的k个点来投票判定要判断的点归为哪一类。

那这个图来说,图中有蓝色和红色两种类型,我现在想要判断这个绿色的点属于哪一种类型——————————设k = 3 时,也就是实心圈里的三个点,这个时候绿色点属于红色三角类型                                                                    设k = 5 时,也就是虚线圈里的五个点,这个时候绿色点属于蓝色正方类型

KNN实现步骤:

(1)计算已知类别数据集中的点与你要判断的点之间的距离

(2)按照距离递增次序排序

(3)选取与当前点距离最小的k个点

(4)确定前k个点所在类别的出现频率

(5)返回前k个点出现频率最高的类别当作你要判断点的类别

对于上述步骤,只有第一步是需要你下功夫自己计算距离,其他的步骤,Python强大的工具包都可以帮你搞定。那么,怎么计算距离呢?

这里,我所使用计算距离的比较简单的欧式距离算法,该算法如下:

\rho =\sqrt{\left ( x_{2}^{} -x_{1}^{}\right )^2+\left ( y_{2}^{}- y{1}^{}\right )^2},这是在二维里的距离算法,三维思维以此类推,很简单吧,小学应该就学过。

好的,我们理解了KNN的大概,接下来就动手编写一下代码吧(代码部分,我不会再过多赘述,在里面注释更容易让大家理解)

import numpy as np
import matplotlib.pyplot as plt
from math import sqrt
from collections import Counter#统计工具包,待会用来统计最短距离最多的点的个数

x = [[1.0,1.3],[1.1,1.3],[1.2,1.4],[1.3,1.4],[1.4,1.8],[2.3,3.2],[2.1,3.7],[2.2,3.2],[2.5,3.9],[2.6,3.6]]
#x里的每一个元素代表,图上的每一个点
y = [0,0,0,0,0,1,1,1,1,1]#y列表里只有0,1两个数代表x里的点分为两类,
                         #y里面0的个数代表x里面点是“0”这一类的个数
X = np.array(x)
Y = np.array(y) 
#将列表转化为数组,这样做是为了便于用函数求最大、最小、排序、均值等的计算
#而列表做上述计算锝自己编码完成
    
plt.scatter(X[Y==0,0],X[Y==0,1],c='red')
plt.scatter(X[Y==1,0],X[Y==1,1],c='blue')#这是我分好类了的数据点,将其可视化

newdata = [1.8,3.0]#这是我要测试的数据点
plt.scatter(newdata[0],newdata[1],c='yellow')

#上述的代码都只是数据处理,为了给接下来KNN算法分析带来方便

#这里是步骤一:为了求数据点到我每一个测试点的距离,用的是欧式距离格式求
dis = []
for i in X:
    d = sqrt(np.sum((i - newdata)**2))
    dis.append(d)
    
#步骤二:使用该函数,让距离从小到大排序,注意这里排的是索引值
near = np.argsort(dis)

#步骤三:设k值为3则,取最小距离前三个的类别,哪个类个数多,就把新数据判给哪个类
k = 3

#步骤四:确定前k个点所在类别的出现频率
topk = [Y[i] for i in near[:3]]
print(topk)#输出最短距离的前三个点都是什么类别
v = Counter(topk)
print(v)#统计topk里,即最短的三个点里,他们所属类别的个数

#步骤五:最后确定要判别的点的类别
v.most_common(1)#表现出最频繁出现的类别,因为他是个二维数组,所有我们表示这个类别可以如下
v = v.most_common(1)[0][0]#所有就得出了newdata的类别了
print(v)



plt.show()

最后一个部分,就是KNN的实战了,实战所用的数据集是经典的约会特征数据集,而且我这里该数据集免费的链接(csdn里都需要vip才取得到),有需要的可以拿去,在文章末尾(好心人记得给个赞,加关注哦)。还有这里的代码,我都是从bi站上 小猴子_哈(作者名)那里学得,再添加了自己的理解,如果我还有解释不清的地方,可以去bi站上搜索这个作者,她讲的非常详细。

import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split,cross_val_score#用于训练集和测试集的划分
from sklearn import preprocessing #导入数据预处理模块
from sklearn.preprocessing import MinMaxScaler #归一化
from sklearn.neighbors import KNeighborsClassifier #knn用于分类的算法,也有做回归的,但knn更擅长做分类


#机器学习的第一步,收集数据,我们从网上找来了
#这里是机器学习的第二步,输入数据
datingTest = pd.read_table('D:/桌面/代码/Python_2021_11_20/机器学习/datingTestSet.txt',header=None)
#后面这个参数就使第一行不会默认为表格名
#read_csv读取csv文件,read_table读取txt文件
#拿到一个数据集首先看一下数据长什么样子  print(datingTest) 
#也可以只看前面几行的数据  datingTest.head()##括号里的参数是你要看前多少行
#以及看看他的大小形状  datingTest.shape
#还有信息   datingTest.info()

#分类,确定不同喜欢程度的颜色
Colors = []
for i in range(datingTest.shape[0]):#datingTest.shape[0]这里是1000
    m = datingTest.iloc[i,-1]#迭代最后一列所有行的数据
    if m == 'didntLike':
        Colors.append('black')#如果是不喜欢这一类,那点的颜色就用黑色,下面以此类推
    if m == 'smallDoses':
        Colors.append('blue')
    if m == 'largeDoses':
        Colors.append('red')

#将数据可视化
pl = plt.figure(figsize=(15,8))
fig1 = pl.add_subplot(221)
#add_subplot函数不能直接用plt.subplot
#百位上的数代表画布上下分成几块#十位上的数代表画布左右分成几块 #个位上的数代表该块副画布的编号
plt.scatter(datingTest.iloc[:,1],datingTest.iloc[:,2],marker='.',c=Colors)
plt.xlabel('玩游戏视频所占时间比')
plt.ylabel('每周消费冰淇淋公升数')

fig2 = pl.add_subplot(222)#百位上的数代表画布上下分成几块#十位上的数代表画布左右分成几块 #个位上的数代表该块副画布的编号
plt.scatter(datingTest.iloc[:,0],datingTest.iloc[:,1],marker='.',c=Colors)
plt.xlabel('每年飞行常客里程')
plt.ylabel('玩游戏视频所占时间比')

fig3 = pl.add_subplot(223)#百位上的数代表画布上下分成几块#十位上的数代表画布左右分成几块 #个位上的数代表该块副画布的编号
plt.scatter(datingTest.iloc[:,1],datingTest.iloc[:,2],marker='.',c=Colors)
plt.xlabel('每年飞行常客里程')
plt.ylabel('每周消费冰淇淋公升数')
plt.show()

#数据归一化,为什么要归一化?
#因为,从数据可以看出第一列的占比特别大,如果直接用欧式距离的话,那么后面几列的特征值
#就对结果的影响变的很低,而归一化就是将该值减去该列最小值再比上该列的最大值减去最小值
#那么得到的新值的范围就在0和1之间,从而避免了占比过大的情况
def minmax(data):
    mindata = data.min()
    maxdata = data.max()
    newdata = (data - mindata)/(maxdata - mindata)
    return newdata

datingT = minmax(datingTest.iloc[:,:3])
#print(minmax(datingTest.iloc[:,:3]))
datingT = pd.concat([minmax(datingTest.iloc[:,:3]),datingTest.iloc[:,-1]],axis=1)
#横向连接最后一列的标签
#print(datingT)

#因为这里的标签是字符型,而计算机喜欢用数值来处理
laber = preprocessing.LabelEncoder()#该函数用来给标签(这里的标签是喜欢程度)编码(一般是0,1,2,3等)
                                    #这里赋给laber也叫实例化
datingT.iloc[:,-1] = laber.fit_transform(datingT.iloc[:,-1])#再进行拟合和训练,他们可以放在一起
#print(datingT.iloc[:,-1])
#print(datingT)
#上述都是机器学习的第三步,提取特征

#ok,到这里数据以及处理完毕了,我们可以给他训练分析了
X = datingT.iloc[:,:3]
Y = datingT.iloc[:,-1]

Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,Y,test_size=0.3)
#这里我们把数据集分为训练集和测试集,而且Xtrain,Xtest...顺序不能,
#并且这些数据都是随机选取的,所有索引会错乱 
#print(Xtrain)
#后面一个参数的意思是让测试集占数据集的拜访之30

#恢复索引
for i in [Xtrain,Xtest,Ytrain,Ytest ]:
    i.index = range(i.shape[0])#range取连续的数,从0到i.shape[0]
#print[Xtrain]

#其实说到底这还是对数据的处理

#这里就是机器学习的倒数第三步,机器学习算法训练模型
#在这里才是真正用到数据,所有主要还是数据处理
knn = KNeighborsClassifier(n_neighbors=5)#参数的意思就是K值,这步赋值也是实例化
knn.fit(Xtrain,Ytrain)#训练训练集
acc_knn = knn.score(Xtest,Ytest)#用训练集训练后得出的函数再来在测试集上测试可以得多少分
#print(acc_knn)
#如何使得分更高呢?  可以去了解一下网格搜索

#绘制学习曲线,这里用交叉验证,找到最好的k值,这一步也就是机器学习的测试调整算法,得到最优模型
score = []
for i in range(1,11):
    knn = KNeighborsClassifier(n_neighbors=i)
    cvs = cross_val_score(knn,X,Y,cv=5)
#交叉验证就是将整个数据进行等分,假设我把该数据集分为5份,分别是1,2,3,4,5,
#我取其中的4份进行训练,1份测试
#那么我就可以那1,2,3,4训练,5训练,接着把1,2,4,5训练,第3个拿来测试,以此来循环
#每一份都可以是训练集,也可以是测试集
    score.append(cvs.mean())#这里我们取的是均值
plt.plot([*range(1,11)],score)#由该图像最高点就是这个模型最好的K值
plt.show()
 

上述就是我为大家带来的KNN理解,希望对大家有所帮助。

数据集链接:https://github.com/Asia-Lee/KNN

  • 13
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值