一,K-近邻算法简单概述

k-近邻算法(k-Nearest Neighbour algorithm),又称为KNN算法,是数据挖掘技术中原理最简单的算法。KNN的工作原理:给定一个已知标签类别的训练数据集,输入没有标签的新数据后,在训练数据集中找到与新数据最邻近的k个实例,如果这k个实例的多数属于某个类别,那么新数据就属于这个类别。可以简单理解为:由那些离X最近的k个点来投票决定X归为哪一类。

二,代码实现

算法的步骤:

  1. 计算已知类别数据集中的点与当前点之间的距离;
  2. 按照距离进行升序排序;
  3. 选取距离递增次序最小的前K个点;
  4. 确定前K个点中,每个点所属类别出现的频率;
  5. 返回前K个点中频率最高的点所在的类别名称。

import pandas as pd
rowdata={'电影名称':['无问西东','后来的我们','前任3','红海行动','唐人街探案','战狼2'],
		'打斗镜头':[1,5,12,108,112,115],
		'接吻镜头':[101,89,97,5,9,8],
		'电影类型':['爱情片','爱情片','爱情片','动作片','动作片','动作片']}
movie_data = pd.DataFrame(rowdata)
movie_data

python 邻近内插值_K-近邻


new_data = [24,67] #预测的数据打斗镜头和接吻镜头数据
# 计算距离的公式 [(X-x)^2 + (Y-y)^2]*0.05
dist = list((movie_data.iloc[:6, 1:3] - new_data)**2.sum(1))**0.5

dist_l = pd.DataFrame({'dist': dist, 'labels': (movie_data.iloc[:6, 3])})
dr = dist_l.sort_values(by = 'dist')[: k]
dr

python 邻近内插值_代码实现_02


k = 4 # 取最近的4个点
re.dr.loc[:,'label'].value_counts()
re.index[0] # 判断新数据所属的类别

三,封装函数

import pandas as pd
def classify0(inX,dataSet,k):
	"""
	函数功能:KNN分类器
	参数说明:
	    inX:需要预测分类的数据集
	    dataSet:已知分类标签的数据集(训练集)
	    k:k-近邻算法参数,选择距离最小的k个点
	返回:
	    result:分类结果
	"""
    result=[]
    dist = list((((movie_data.iloc[:6,1:3]-new_data)**2).sum(1))**0.5) # 这里是距离的公式
    dist_l = pd.DataFrame({'dist': dist, 'labels': (movie_data.iloc[:6, 3])})
    dr = dist_l.sort_values(by = 'dist')[: k]
    re = dr.loc[:,'labels'].value_counts()
    result.append(re.index[0])
    return result

四,约会网站配对效果判定

# 1.导入数据
data - pd.read_tabel('datingTest.txt', header=None)
data.head()

python 邻近内插值_python 邻近内插值_03

# 由于每个特征数据大小不一样,权重就不一样,因此我们要对数据集进行归一化
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()

python 邻近内插值_python 邻近内插值_04

# 划分训练集测试集(9:1)
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(data)
# 计算距离,判类别
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))**0.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