机器学习—K-近邻算法[入门]

k-近邻算法(k-Nearest Neighbour algorithm),又称为KNN算法,是数据挖掘技术中原理最简单的算法。
KNN的工作原理:给定一个已知标签类别的训练数据集,输入没有标签的新数据后,在训练数据集中找到与新数据最邻
近的k个实例,如果这k个实例的多数属于某个类别,那么新数据就属于这个类别。可以简单理解为:由那些离X最
近的k个点来投票决定X归为哪一类。
k-近邻算法步骤
     1.计算已知类别数据集中的点与当前点之间的距离
     2.按照距离递增次序排序
     3.选取与当前点距离最小的k个点
     4.确定前k个点所在类别的出现频率
     5.返回前k个点出现频率最高的类别作为当前点的预测类别
 
 没听懂?我们借图说话。

在这里插入图片描述
图中有红色三角和蓝色方块两种类别,我们现在需要判断绿色圆点属于哪种类别。
当k=3时,绿色圆点属于红色三角这种类别;
当k=5时,绿色圆点属于蓝色方块这种类别(蓝色方块数量为3,大于红色三角的数量)。

是不是很简单?
我们再举个栗子
在这里插入图片描述

电影类型分类

通过电影中出现的打斗镜头和接吻镜头的数量来预测该电影的类型。
在这里插入图片描述

1.准备数据

import pandas as pd

rowdata = {'电影名称':['无问西东','后来的我们','前任3','红海行动','唐人街探案','战狼2'],\
           '打斗镜头':[13,5,32,38,65,78],\
           '接吻镜头':[20,42,40,26,9,28],\
           '电影类型':['爱情片','爱情片','爱情片','动作片','动作片','动作片']}
movie_data = pd.DataFrame(rowdata)
movie_data

2.使用Matplotlib进行可视化(非必要过程)

%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
#把不同标签用颜色区分
Colors = []
df = pd.DataFrame(data=movie_data)
for i in range(movie_data.shape[0]):
    m = df['电影类型'][i]
    if m=='爱情片':
        Colors.append('red')
    if m=='动作片':
        Colors.append('blue')
#绘制两两特征之间的散点图
plt.rcParams['font.sans-serif']=['Simhei'] #图中字体设置为黑体
pl=plt.figure(figsize=(18,13))
fig1=pl.add_subplot(221)
plt.scatter(df['打斗镜头'],df['接吻镜头'],marker='p',c=Colors)
plt.scatter(30,30,marker='x',c='black')
plt.xlabel('打斗镜头')
plt.ylabel('接吻镜头')
plt.title('预测电影类型')
plt.show()

在这里插入图片描述

3.创建KNN分类器进行预测

import pandas as pd
"""
函数功能:KNN分类器
参数说明:
inX:需要预测分类的数据集
dataSet:已知分类标签的数据集(训练集)
k:k-近邻算法参数,选择距离最小的k个点
返回:
result:分类结果
"""
def classify0(inX,dataSet,k):
    result = [] 
    dist = list((((dataSet.iloc[:,1:3]-inX)**2).sum(1))**0.5)     #将各个点的位置带入计算公式,求距离    .iloc为截取数据片段
    dist_l = pd.DataFrame({'dist':dist,'labels':(dataSet.iloc[:, 3])})  #对计算出的距离进行对应,以DataFrame格式赋给dist_1
    dr = dist_l.sort_values(by = 'dist')[: k]   #对距离进行升序排序,并截取前k个
    re = dr.loc[:, 'labels'].value_counts()  #对距离最短的前k个值的labels的数量进行统计,求出k范围内数量最多的标签
                                             #.loc可按条件进行选择'labels'一列的值
    result.append(re.index[0])   #取数量最多的标签并将标签添加到result
    return result

new_data = [24,67]  #这里我们假设预测点为[24,67],读者可自行修改
inX = new_data
dataSet = movie_data
k = 3
print('该电影的类型预测结果为:%s'%classify0(inX,dataSet,k)[0])

输出结果:
在这里插入图片描述
是不是很简单?上面的代码和KNN分类器都是我纯手工打造,你也可以根据我讲的原理自己设计KNN分类器,这样效果会更好。
接下来我再将一个例子,逐步讲解k-近邻算法的详细步骤。

约会网站配对效果判定

根据以往的交往数据来进行预测对约会对象的喜欢程度,是didntLike,smallDoses,还是largeDoses。

1.准备数据

附上数据下载地址

datingTest = pd.read_table('datingTestSet.txt',header=None)
datingTest.head()
datingTest.shape
datingTest.info()

2.分析数据

使用 Matplotlib 创建散点图,查看各数据的分布情况

%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
#把不同标签用颜色区分
Colors = []
for i in range(datingTest.shape[0]):
    m = datingTest.iloc[i,-1]
    if m=='didntLike':
        Colors.append('blue')
    if m=='smallDoses':
        Colors.append('orange')
    if m=='largeDoses':
        Colors.append('red')
#绘制两两特征之间的散点图
plt.rcParams['font.sans-serif']=['Simhei'] #图中字体设置为黑体
pl=plt.figure(figsize=(14,8))
fig1=pl.add_subplot(221)
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[:,0],datingTest.iloc[:,2],marker='.',c=Colors)
plt.xlabel('每年飞行常客里程')
plt.ylabel('每周消费冰淇淋公升数')
plt.show()

在这里插入图片描述
图中,蓝色的点代表不喜欢,橙色代表有点喜欢,红色代表非常喜欢。

3.数据归一化

什么是归一化?请看下面这张图。在上面的例子中,打斗镜头和接吻镜头数量有的很大,有的很小,数据参差不齐,很难对数据进行精确的预测,那怎么办呢?这里介绍一种常用的方法就是将数据统一归到0-1之间。

在这里插入图片描述
数据归一化后的效果:
在这里插入图片描述
数据归一化的处理方法很多种,比如0-1标准化、Sigmoid压缩法等等。而我们这里讲的0-1标准化的公式如下:
在这里插入图片描述
该方法实现对原始数据的等比例缩放,其中Xscale为归一化后的数据,X为原始数据,Xmax、Xmin分别为原始数据集的最大值和最小值。

"""
函数功能:归一化
参数说明:
dataSet:原始数据集
返回:0-1标准化之后的数据集
"""
def minmax(dataSet):
    minDf = dataSet.min()
    maxDf = dataSet.max()
    normSet = (dataSet - minDf )/(maxDf - minDf)
    return normSet

datingT = pd.concat([minmax(datingTest.iloc[:, :3]), datingTest.iloc[:,3]], axis=1)
datingT.head()

4. 划分训练集和测试集

"""
函数功能:切分训练集和测试集
参数说明:
dataSet:原始数据集
rate:训练集所占比例
返回:切分好的训练集和测试集
"""
def randSplit(dataSet,rate=0.9):
    n = dataSet.shape[0]
    m = int(n*rate)
    train = dataSet.iloc[:m,:]
    test = dataSet.iloc[m:,:]
    test.index = range(test.shape[0])
    return train,test
train,test = randSplit(datingT)
print(train,test)  #打印训练集

5.创建针对于约会网站的KNN分类器

"""函数功能:k-近邻算法分类器
参数说明:
train:训练集
test:测试集
k:k-近邻参数,即选择距离最小的k个点
返回:预测好分类的测试集
"""
def datingClass(train,test,k):
    n = train.shape[1] - 1
    m = test.shape[0]
    result = []
    for i in range(m):
        dist = list((((train.iloc[:, :n] - test.iloc[i, :n]) ** 2).sum(1))**5)
        dist_l = pd.DataFrame({'dist': dist, 'labels': (train.iloc[:, n])})
        dr = dist_l.sort_values(by = 'dist')[: k]
        re = dr.loc[:, 'labels'].value_counts()
        result.append(re.index[0])
    result = pd.Series(result)
    test['predict'] = result
    acc = (test.iloc[:,-1]==test.iloc[:,-2]).mean()
    print(f'模型预测准确率为{acc}')
    return test

datingClass(train,test,5)

输出结果为:
在这里插入图片描述
准确率还不错 n_n

       看到这里,是不是觉得机器学习十大算法之一—k-近邻算法不太难?不过,学习k-近邻算法还有很长路要走,这里我只是用简单的例子和代码来引领大家走进机器学习的大门,也是我做这一期博客的初衷,也希望大家多多支持和鼓励,点个赞,加个关注,我会持续更新机器学习十大算法。
       机器学习-十大算法系列欢迎访问我的主页,我会持续更新,谢谢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值