一:K近邻算法
二:实际例子
(1) 判断电影类型
给一组电影,对应是打斗和接吻两个特征值来判断电影类型
import pandas as pd rowdata = {"电影名称":["无问西东","后来的我们","前任3","红海行动","唐人街探案","战狼2"], "打斗次数":[1,5,12,108,112,115], "接吻次数":[101,89,97,5,9,8], "电影类型":["爱情片","爱情片","爱情片","动作片","动作片","动作片"]} # 1.将字典格式,转换为能够处理的数据表格 movie_data = pd.DataFrame(rowdata) print(movie_data)
#
电影名称 打斗镜头 接吻镜头 电影类型
0 无问西东 1 101 爱情片
1 后来的我们 5 89 爱情片
2 前任3 12 97 爱情片
3 红海行动 108 5 动作片
4 唐人街探案 112 9 动作片
5 战狼2 115 8 动作片
对应的用图像去描述的话
from matplotlib import pyplot as plt x = [1,5,12,108,112,115] y = [101,89,97,5,9,8] # 画散点图,x和y里面的对应索引元素组成(x,y) plt.scatter(x,y,s=80) x1 = [24] y1 = [67] # market:表示点的形状 s:表示点的大小 plt.scatter(x1,y1,marker="^",s=80) plt.show()
从图中可以看出,左上角的圆都代表爱情电影,右下角的圆都代表动作电影。图中的三角形,表示要分类的电影。
应为是两个特征值,二维平面就计算点与点的距离,计算结果如下
target_data = {"name":"猜猜看","type":"未知","data":(24,67)} origin_data_list = [{"name":"无问东西","type":"爱情片","data":(1,101)}, {"name":"后来的我们","type":"爱情片","data":(5,89)}, {"name":"前任3","type":"爱情片","data":(12,97)}, {"name":"红海行动","type":"动作片","data":(108,5)}, {"name":"唐人街探案","type":"动作片","data":(112,9)}, {"name":"战狼2","type":"动作片","data":(115,8)}] for info in origin_data_list: result = cmath.sqrt((info.get("data")[0]-target_data.get("data")[0]) ** 2 + (info.get("data")[1]-target_data.get("data")[1]) ** 2) print(target_data.get("name")+"距离" + info.get("name")+":" +str(result)) # 结果 猜猜看距离无问东西:(41.048751503547585+0j) 猜猜看距离后来的我们:(29.068883707497267+0j) 猜猜看距离前任3:(32.31098884280702+0j) 猜猜看距离红海行动:(104.4030650891055+0j) 猜猜看距离唐人街探案:(105.39449701004318+0j) 猜猜看距离战狼2:(108.45275469069469+0j)
距离猜猜看最近电影是后来的我们,类型是爱情片,如果我们根据这种形式进行判断的话,就叫做最近邻算法(KNN:k-nearest neighbor)。
第一步:K就是判定你要选择离你最近的几个点,假如我们选择K为5,那么离猜猜看最近的距离前五位分别是(29,32,41,104,105)
第二步:最近的几个点进行投票,票数多久的一方获胜,猜猜看就属于这一方,爱情片3票,概率为60%,动作片2票,概率为40%,所以猜猜看就属于爱情片。
完整的代码
import pandas as pd rowdata = {"电影名称":["无问西东","后来的我们","前任3","红海行动","唐人街探案","战狼2"], "打斗镜头":[1,5,12,108,112,115], "接吻镜头":[101,89,97,5,9,8], "电影类型":["爱情片","爱情片","爱情片","动作片","动作片","动作片"]} # 1.将字典格式,转换为能够处理的数据表格 movie_data = pd.DataFrame(rowdata) # 2.计算已知类别和当前点的距离 new_data = [24,67] # 对已知类别的数据进行处理 distance = movie_data.iloc[:6,1:3] # pandas数据格式,iloc(行,列)切割方法 # 切割的结果 打斗镜头 接吻镜头 0 1 101 1 5 89 2 12 97 3 108 5 4 112 9 5 115 8 distance = ((distance - new_data)**2) print(distance) # 打印的结果是 打斗镜头 接吻镜头 0 529 1156 1 361 484 2 144 900 3 7056 3844 4 7744 3364 5 8281 3481 distance = distance.sum(1) print(distance) # 打印的结果是 0 1685 1 845 2 1044 3 10900 4 11108 5 11762 print(list(distance**0.5)) # 打印的结果是 dtype: int64 [41.048751503547585, 29.068883707497267, 32.31098884280702, 104.4030650891055, 105.39449701004318, 108.45275469069469] # 3. 对距离进行升序排序 distance = list(disctance**0.5) distance_1 = pd.DataFrame({"distance":distance,"lable":(movie_data.iloc[:6,3])}) print(distance_1) # 结果 distance lable 1 29.068884 爱情片 2 32.310989 爱情片 0 41.048752 爱情片 3 104.403065 动作片 4 105.394497 动作片 5 108.452755 动作片 sort_disctance_1 = distance_1.sort_values(by="distance") # 默认升序 print(sort_disctance_1) # 结果 distance lable 1 29.068884 爱情片 2 32.310989 爱情片 0 41.048752 爱情片 3 104.403065 动作片 4 105.394497 动作片 5 108.452755 动作片 sort_disctance_1 = sort_disctance_1[:5] # 因为k选取的5,因此取前五近的的距离 print(sort_disctance_1) # 结果 distance lable 1 29.068884 爱情片 2 32.310989 爱情片 0 41.048752 爱情片 3 104.403065 动作片 4 105.394497 动作片 # 4.进行概率统计 result = sort_disctance_1.loc[:,"lable"] print(result) # 结果是 1 爱情片 2 爱情片 0 爱情片 3 动作片 4 动作片 result = result.value_counts() print(result) # 结果是 Name: lable, dtype: object 爱情片 3 动作片 2 result = result.index print(result) # 结果是 Name: lable, dtype: int64 Index([‘爱情片‘, ‘动作片‘], dtype=‘object‘) result = result[0] print("电影的分类为:",result) # 结果是 电影的分类为: 爱情片
封装成函数
def classify(new_data,dataSet,k): """ 函数功能:KNN分类器 参数说明 :param new_data: 需要预测的分类数据集 :param dataSet: 已知分类标签的数据集(训练集) :param k: K-近邻算法参数,选择距离最近的k个点 :return: 分类结果 """ result = list() distance = list((((dataSet.iloc[:,1:3]-new_data)**2).sum(1)) ** 0.5) distance_sort = pd.DataFrame({"distance":distance,"lable":dataSet.iloc[:,3]}) distance_sort = distance_sort.sort_values(by="distance")[:k] ret = distance_sort.loc[:,"lable"].value_counts() result.append(ret.index[0]) return result if __name__ == ‘__main__‘: rowdata = {"电影名称": ["无问西东", "后来的我们", "前任3", "红海行动", "唐人街探案", "战狼2"], "打斗镜头": [1, 5, 12, 108, 112, 115], "接吻镜头": [101, 89, 97, 5, 9, 8], "电影类型": ["爱情片", "爱情片", "爱情片", "动作片", "动作片", "动作片"]} movie_data = pd.DataFrame(rowdata) new_data = [24,67] k = 3 result = classify(new_data,movie_data,k) print(result) # 结果 [‘爱情片‘]
三:K近邻算法的局限性
算法的准确性与K的取值有关系
假如K取3的话,那么测试数据就属于三角形,假如k取5的话,测试数据就属于正方形。
K近邻算法的改进:https://blog.csdn.net/qq_36330643/article/details/77532161
# TODO
原文:https://www.cnblogs.com/meloncodezhang/p/13047242.html