最邻近方法nn_kNN最邻近规则分类
原理介绍:
这一个月来恶补了一下大学的数学知识,把高数、线代、概率论、复变函数和积分变换又温习了一遍,大学里学的差一点就忘光了。大学时每次上数学课可都是昏昏欲睡啊!哈哈!学习人工智能中关于分类的知识,碰到很多数学描述都看不太懂,才意识到自己的数学在不拾一拾就剩加减乘除了。
一个同事,也是搞C++ 的,对预测彩票非常感兴趣。我们认为这是个数学问题。做游戏开发,碰到数学问题还真不多,大部分都是逻辑问题,如A打伤了B,B打死了C诸如此类。然后提到如何实现通过程序为人们推荐手机,发现主要也是数学问题。总结来,在日常的软件开发中,主要涉及逻辑控制和数学建模两大部分,为了实现逻辑控制,我们精通编程语法,熟记API,优雅的涉及模块和类,高效的传输和存储数据。是的,这确实已经是很复杂的学问了。但对于我们来说,数学问题更让人着迷。
其实今天是要记录一下k-NN最近邻规则算法的。最近养成了一个习惯,将一个数学模型掌握以后,应用到一个例子中,并把它用Blog记录下来。K-NN是一种非常朴素的分类算法,但是在步入正题之前,还是要抛个转。
比如要实现一个模型为人人们推荐购买哪一款手机。为简化模型我们只基于协同过滤做推荐(洒家也是在推荐系统论坛长期潜水之人,常用的推荐策略还是略知一二的)。举个例子,已知A、B二人,A是月薪15k年龄28的帅哥,而B是月薪3K的年龄23的实习生,还知道A购买了Iphone, 而B购买了小米。如果C是月薪13K年龄27,那么你十分有可能和A进行相同的选择,也去购买Iphone。数学上认为C的函数值更解决于A。这就是k-NN最近邻规则的思想,找到和目标属性最接近的样本,并把它们归为同一类别。物以类聚,人以群分嘛。
如果已知100 个各个收入阶层、各个年龄段的手机购买数据,把其作为训练样本,从中选择一个和目标情况最为接近的一个样本,并把该样本使用的手机推荐给目标,这种分类方法称之为1-NN最近邻规则。进行推广之,从100 人中选出5个最接近目标情况的样本,并把他们使用最多的一款手机推荐给目标,则称之为k-NN最近邻规则,此时k=5。
设计k-NN最近邻规则时,最重要的是确定k值和设计计算样本之间距离(或相似度)的度量函数。
首先说计算k值。有时可以根据经验。比如上面推荐手机的例子,k=1 显然不合适,比如月薪20k的大牛可能就喜欢android,非要买个三星也是有的,如果目标和此大牛情况相近就会被推荐三星,但是实际上这一类人大部分都在使用iphone。而若选择5,那么虽然这个大牛使用了三星,但是其他四个人都是使用iphone,那么系统仍然会推荐iphone,这就非常符合现实情况了。但是k值又不能太大,太大计算量增大,并且有可能会出现给一个20k的大牛推荐山寨机的结果。更科学的方法是尝试几种最有可能的k值,计算该k值下的误差率,选择误差率最小k值。
下面再说一下如何计算两个样本之间的距离,即确定一个度量函数D。任意两个样本a、b,D(a, b) 得到a、b之间的距离。而a样本又有各个属性,数学表示X=(x1, x2,…..)。最简单计算距离的方法是欧几里得公式:
但是欧几里得法有一个缺陷,若属性的单位发生变化,可能会影响原来各个样本之间的相对距离。如把月薪20k改成月薪20000那么可能会造成原来A更接近于B,但是变成A更接近于C。这里也能说明k值不宜选的太小。
下面附一个小示例:
已知20个样本:
样本
月收入
年龄
手机
1
2k
18
Iphone6
…….
10
5k
23
小米
……
50
10k
25
Iphone
又已知10个测试样本:
样本
月收入
年龄
手机
1
6k
22
三星
…….
2
9k
25
Iphone
距离度量函数选择欧几里得公式,不同的K值测试的误差对比如下:
K值
1
2
3
4
5
6
7
8
9
误差率
19%
19%
10%
28%
19%
28%
28%
28%
28%
所以选择K值为3,
运行代码如下:
train_data =[]
test_data=[]definit_data():
f= open("train_data.txt")
dest=train_datafor line inf.readlines():if len(line) ==0:continue
if line[0] == '#':if -1 != line.find('test_data'):
dest=test_datacontinueline_array=line.strip().split()if len(line_array) == 3:
line_array[0]=float(line_array[0])
line_array[1] = int(line_array[1])
line_array.append(0)
dest.append(line_array)
f.close()defselect_k_neighbour(k, income, age):defmy_cmp(E1, E2):return -cmp(E2[3], E1[3])
distance=[]for item intrain_data:
income2=item[0]
age2= item[1]
item[3] = (income - income2) * (income - income2) + (age - age2) * (age -age2)
distance.append(item)
distance.sort(my_cmp)
select_k={}for k inrange(0, k):
phone= distance[k][2]if False ==select_k.has_key(phone):
select_k[phone]= 1
else:
select_k[phone]= select_k[phone] + 1ret_phone= ''max=0for k inselect_k:if select_k[k] >max:
max=select_k[k]
ret_phone=kreturnret_phonedefknn_train(k):
right= 0.0wrong= 0.0
for item intest_data:
income=item[0]
age= item[1]
phone= item[2]
ret_phone=select_k_neighbour(k, income, age)if ret_phone ==phone:
right= right + 1
else:
wrong= wrong + 1
return right / (right +wrong)
init_data()print("train_data", train_data)print("test_data", test_data)
ret=[]for i in range(0, 10):
rate= 1 - float(int(knn_train(i+1) * 100 )) / 100ret.append(str(rate))print('')print(ret)
数据文件为:
#train_data#income age phone2 20N3 21M3 22N3.5 22N4 23M4 24M5 24M5.5 25M6 25M7 26I7.5 25M7.5 28I8 27I9 27I10 29I11 28M12 27I13 28M14 30I15 30I16 30I#test_data2.5 23N3 24M3.5 24N4 25M4.5 26M5.5 26M6 27I7 26M8 28I9 30I12 31I
k-NN 算法的优化:
很显然的一个问题是k-NN要求遍历所有的训练样本,若训练样本非常庞大,那么计算量可能是不能接受的。针对k-NN算法的优化方法有:
裁剪训练样本
既然训练样本太多,那么我们就把训练样本比较接近的合并成一项,如月薪10k-12k的统一化为10k之类,减少训练样本数量。
建立搜索树
思想就是先分几个大类,在再小类中找相似的,如>10k的在某一类别中,那么一次可以淘汰N多不太可能的计算。
属性降维法
本文中只选择了收入和年龄作为人的属性,实际让远远应比此大的多的多,在遍历训练样本时,可以从中选择有代表性的属性用于计算,或者可以通过变换减少属性。
最邻近方法nn_kNN最邻近规则分类相关推荐
- 麦子学院深度学习基础 —— 机器学习 —— 最近邻规则分类 KNN 算法
最邻近规则分类(K-Nearest Neighbor)KNN 算法 1.综述: 1.1 Cover 和 Hart 在 1968 年提出了最初的近邻算法. 1.2 分类(Classification)算 ...
- Java中类、常量、变量、方法名等命名规则
Java中类.常量.变量.方法名等命名规则 命名规则: 命名由字母.数字.下划线.美元符号($)构成. 命名不可以数字作为开头. 长度无限制,但不可存在空格. 大小写所表述内容含义不同. 命名不可与J ...
- git 命令行忽略提交_Git忽略提交的3种方法及Git忽略规则
在使用Git的过程中,我们喜欢有的文件比如日志,临时文件,编译的中间文件等不要提交到代码仓库,这时就要设置相应的忽略规则,来忽略这些文件的提交. Git 忽略文件提交的方法 有三种方法可以实现忽略Gi ...
- 最邻近方法nn_【庖丁解牛】从零实现RetinaNet(七):使用分布式方法训练RetinaNet...
下列代码均在pytorch1.4版本中测试过,确认正确无误. 如何把nn.DataParallel模式训练代码改为nn.parallel.DistributedDataParallel分布式训练代码 ...
- 一步一步学java(7):jar包使用方法及常用jar包分类汇总(持续更新)
java最大的特点和优势就是纯面向对象.开源,除了JDK.JRE自带的基础类库之外,还有非常多的大牛们开发了各种应用的类库(jar包),本篇主要介绍一下这些类库的使用方法,并把常用jar包分类汇总,以 ...
- 机器学习模型评估的方法总结(回归、分类模型的评估)
建模的评估一般可以分为回归.分类和聚类的评估,本文主要介绍回归和分类的模型评估: 一.回归模型的评估 主要有以下方法: 指标 描述 metrics方法 Mean Absolute Error(MAE) ...
- 织梦tag伪静态html方式,织梦dedecms TAG标签伪静态方法(附伪静态规则)
在之前,织梦帮介绍了关于 织梦dedecms TAG 标签字数长度修改方法 ,今天就分享下dedecms织梦tag标签实现伪静态的方法,关于tags伪静态配置比其它的配置要简单的多了只需要修改几个小地 ...
- 深度学习实战案例:基于LSTM的四种方法进行电影评论情感分类预测(附完整代码)
序列分类是一个预测建模问题,你有一些输入序列,任务是预测序列的类别. 这个问题很困难,因为序列的长度可能不同,包含非常大的输入符号词汇表,并且可能需要模型学习输入序列中符号之间的长期上下文或依赖关系. ...
- 覆盖分类的方法_老罗讲分类|垃圾分类回收模式到底用哪种好?
普通桶?垃圾房?智能设备?关于垃圾分类的回收模式,到底用哪种模式好? 不管是普通垃圾桶,垃圾房,还是智能的垃圾分类回收设备,老罗认为,不管采用哪种垃圾分类回收模式,首先都要让居民可以非常清楚地知道垃圾 ...
最新文章
- 传蔚来计划回国内科创板上市,关闭硅谷办公室
- Spring 事务管理高级应用难点剖析
- SpringCloud微服务云架构构建B2B2C电子商务平台之-(八)消息总线(Spring Cloud Bus)...
- var_export
- python 执行shell命令行效率提升_在python脚本中执行shell命令的方法
- 二维LIS(CDQ分治)
- 利用OpenCV进行人脸识别
- 芯片项目谁支持谁负责 重大损失将予以通报
- 【牛客 - 318E】爱摸鱼的Dillonh(数学,暴力,细节)
- LeetCode - Convert Sorted Array to Binary Search Tree
- UIImage 剪裁的方法
- 在ubuntu纯字符gdb界面下来开发调试嵌入式ARM
- 字节跳动异构场景下的高可用建设实践
- 如何不装软件查看 Mac 温度?
- cad计算机土方软件,土方计算软件FastTFT - 飞时达软件
- Appfuse中文乱码解决
- cadence SPB17.4 - export placement file to openpnp
- 郭敏:高速公路“过山车”式限速乱象的根本并非技术问题,而是管理协作机制缺位...
- mysql dbms是什么_数据库管理系统(DBMS)是用来做什么的?
- 短视频如何做好数据分析 掌握数据分析技巧