一,K-近邻算法简单概述
k-近邻算法(k-Nearest Neighbour algorithm),又称为KNN算法,是数据挖掘技术中原理最简单的算法。KNN的工作原理:给定一个已知标签类别的训练数据集,输入没有标签的新数据后,在训练数据集中找到与新数据最邻近的k个实例,如果这k个实例的多数属于某个类别,那么新数据就属于这个类别。可以简单理解为:由那些离X最近的k个点来投票决定X归为哪一类。
二,代码实现
算法的步骤:
- 计算已知类别数据集中的点与当前点之间的距离;
- 按照距离进行升序排序;
- 选取距离递增次序最小的前K个点;
- 确定前K个点中,每个点所属类别出现的频率;
- 返回前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
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
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()
# 由于每个特征数据大小不一样,权重就不一样,因此我们要对数据集进行归一化
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()
# 划分训练集测试集(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