KNN算法网上的给出的解释很多,源码也很多,有许多写的很好,所以这个仅作个人理解之用。
KNN算法简介:
KNN算法采用测量不同特征值之间的距离方法进行分类。
工作原理:
存在一个样本数据集,即训练数据集,并且样本集中每个样本数据都存在标签,即我们知道样本数据集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,只选择样本数据集中前K个最相似的数据,这就是KNN算法中的k的出处,通常K是不大于20的整数。最后,选择k个最相似的数据中出现次数最多的分类作为新数据的分类。
算法流程1:
收集数据:提供文本文件
准备数据:使用python解析文本文件
分析数据:使用matplotlib画二维图
处理数据:归一化特征值
测试算法:使用二丫提供的部分数据作为测试集
部署算法:产生简单的命令行程序,然后二丫可以输入一些特征数据以判断对方是否为自己喜欢的类型。
算法流程2:
计算待分类点与已知类别数据集中每个点的距离;
按照距离递增次序排序;
选取与待分类点距离最小的k个点;
确定前k个点类别出现的频率;
返回前k个点出现频率最高的类别作为当前点的预测分类
我们需要将txt中的数据可视化进行需求分析。
这边采用一个网上通用的数据集(来自《机器学习实战》):
这张图片展示的数据集的涵义是:
每行的第一列数据是飞行里程;
第二列是玩游戏所占百分比时间;
第三列是每年吃的冰激凌消耗量;
第四列是某个xx觉得这类人的适合约会的感兴趣程度。
也就是说啦,他一年飞40920公里,有百分之八左右的时间在玩游戏,每年还要吃掉0.9公升哦,这个对象xx觉得好有魅力,非常想和它约会呢,就是这个意思!
首先考虑第一个简单的问题,怎么把第四列的字符串转化成对应的数字:
直接使用if-else语句解决:
#将评价转化为数字
if listFromLine[3] == 'largeDoses':
listFromLine[3] =3
elif listFromLine[3] == 'smallDoses':
listFromLine[3]=2
else:
listFromLine[3]=1
经过转化之后,形式应该和右边那个一样了,非常想约会是3,一般是2,不想是1,就酱紫。这也就是类别了。
第二个问题在于说:怎么把从txt到存入array数组:
如何将txt数据清洗后存入到array也好,存入到database也好,这都是数据处理后续工作避不开的前提
下面上代码:
# -*- coding: utf-8 -*-
from numpy import *
import matplotlib.pyplot as plt
def file2matrix(filename):
fr = open(filename,'r')
arrayOlines = fr.readlines()
numberOfLines = len(arrayOlines)
returnMat = zeros((numberOfLines,3)) #构造全零阵来存放数
classLabelVector = [] #开辟容器
index = 0
for line in arrayOlines:
#清洗数据
line = line.strip()
listFromLine = line.split('\t')
#将评价转化为数字
if listFromLine[3] == 'largeDoses':
listFromLine[3] =3
elif listFromLine[3] == 'smallDoses':
listFromLine[3]=2
else:
listFromLine[3]=1
#存入数据到list
returnMat[index,:] = listFromLine[0:3] #三个特征分别存入一行的三个列
classLabelVector.append(int(listFromLine[3])) #最后一行是类别标签
index +=1
return returnMat,classLabelVector
#将喜欢强度转化为颜色
def ColorOfDatingLable(num):
datingLabels_rgb = []
for i in range(len(num)):
if num[i]==3:
datingLabels_rgb.append('red')
elif num[i]==2:
datingLabels_rgb.append('green')
else:
datingLabels_rgb.append('black')
return datingLabels_rgb
datingDataMat,datingLabels = file2matrix('D:\\PYthon-learning\\Python_test\\knn-test-2\\KNN\\datingTestSet.txt')
##################创建图表1#####################
plt.figure(1) #创建图表1
ax1 = plt.subplot(1,2,1) # 图表1中创建子图1
plt.title("original color")
plt.xlabel('play game/time %')
plt.ylabel('ice cream cost/week')
ax2 = plt.subplot(1,2,2) # 图表1中创建子图2
plt.title("improved color")
plt.xlabel('play game/time %')
plt.ylabel('ice cream cost/week')
###################创建图表2####################
plt.figure(2) #创建图表2
ax3 = plt.subplot(2,2,1) # 图表2中创建子图1
plt.title("play game & ice cream cost")
plt.xlabel('play game/time %')
plt.ylabel('ice cream cost/week')
ax4 = plt.subplot(2,2,2) # 图表2中创建子图2
plt.title("fly distance & play game")
plt.xlabel('fly distance/year')
plt.ylabel('play game/time %')
ax5 = plt.subplot(2,2,3) # 图表2中创建子图2
plt.title("fly distance & ice cream cost")
plt.xlabel('fly distance/year')
plt.ylabel('ice cream cost/week')
#plt.scatter(x[i],y[i],marker = 样式,s=大小半径,color =(np.random.rand(1,3)),label = str(i+1))
ax1.scatter(datingDataMat[:,1],datingDataMat[:,2],15*array(datingLabels),15*array(datingLabels)) #scatter散点图展示第二列和第三列数据
ax2.scatter(datingDataMat[:,1],datingDataMat[:,2],s=15*array(datingLabels),color=ColorOfDatingLable(datingLabels)) #scatter散点图展示第二列和第三列数据,第一个15*array(datingLabels)用来表现不同标签的不同半径
ax3.scatter(datingDataMat[:,1],datingDataMat[:,2],s=15*array(datingLabels),color=ColorOfDatingLable(datingLabels),label='largeDoses/smallDoses/didntLike')
ax4.scatter(datingDataMat[:,0],datingDataMat[:,1],s=15*array(datingLabels),color=ColorOfDatingLable(datingLabels),label='largeDoses/smallDoses/didntLike')
ax5.scatter(datingDataMat[:,0],datingDataMat[:,2],s=15*array(datingLabels),color=ColorOfDatingLable(datingLabels),label='largeDoses/smallDoses/didntLike')
ax3.legend(loc='upper right')
ax4.legend(loc='upper right')
ax5.legend(loc='upper right')
plt.show()
接下来作代码解释:
我们需要引入两个库:numpy和maplotlib,maplotlib主要用于画散点图。
def file2matixr(filename)#用于读取文本文件中的数据 ;
fr = open(filename,'r')#打开文件filename;
arrayOlines = fr.readlines();numberOfLines = len(arrayOlines)
可合并为 numberOfLines = len(fr.readlines())
# 计算文本文件的行数
returnMat = zeros((numberOfLines,3)) #构造全零阵来存放数
classLabelVector = [] # 创建类标签 /开辟容器
index = 0 # 定义索引
for line in arrayOlines:# 读取文件的每一行并处理
#清洗数据
line = line.strip() # 去除行的尾部的换行符
listFromLine = line.split('\t') # 将一行数据按空进行分割
if listFromLine[3] == 'largeDoses':
listFromLine[3] =3
elif listFromLine[3] == 'smallDoses':
listFromLine[3]=2
else:
listFromLine[3]=1 #将评价转化为数字
#然后,存入数据到list
returnMat[index,:] = listFromLine[0:3] #三个特征分别存入一行的三个列
classLabelVector.append(int(listFromLine[3])) #最后一行是类别标签
#至此,循环结束
return returnMat,classLabelVector# 返回数据集和对应的类标签
#将喜欢强度转化为颜色
def ColorOfDatingLable(num):
datingLabels_rgb = []
for i in range(len(num)):
if num[i]==3:
datingLabels_rgb.append('red')
elif num[i]==2:
datingLabels_rgb.append('green')
else:
datingLabels_rgb.append('black')
return datingLabels_rgb
datingDataMat,datingLabels = file2matrix('D:\\PYthon-learning\\Python_test\\knn-test-2\\KNN\\datingTestSet.txt')
看一下数据可视化:
plt.figure(1) #创建图表1
ax1 = plt.subplot(1,2,1) # 图表1中创建子图1
plt.title("original color")
plt.xlabel('play game/time %')
plt.ylabel('ice cream cost/week')
ax2 = plt.subplot(1,2,2) # 图表1中创建子图2
plt.title("improved color")
plt.xlabel('play game/time %')
plt.ylabel('ice cream cost/week')
###################创建图表2####################
plt.figure(2) #创建图表2
ax3 = plt.subplot(2,2,1) # 图表2中创建子图1
plt.title("play game & ice cream cost")
plt.xlabel('play game/time %')
plt.ylabel('ice cream cost/week')
ax4 = plt.subplot(2,2,2) # 图表2中创建子图2
plt.title("fly distance & play game")
plt.xlabel('fly distance/year')
plt.ylabel('play game/time %')
ax5 = plt.subplot(2,2,3) # 图表2中创建子图2
plt.title("fly distance & ice cream cost")
plt.xlabel('fly distance/year')
plt.ylabel('ice cream cost/week')
pyplot是python绘图的一个工具,pyplot是一个有状态的对象,包含了当前的图,画图区域,等。
pyplot通过调用subplot或者add_subplot来增加子图,
如
p1 = plt.subplot(211) 或者 p1 = plt.subplot(2,1,1), 表示创建一个2行,1列的图,p1为第一个子图.
接下来直接绘制散点图:
#plt.scatter(x[i],y[i],marker = 样式,s=大小半径,color =
(np.random.rand(1,3)),label = str(i+1))
ax1.scatter(datingDataMat[:,1],datingDataMat[:,2],15*array(datingLabels),15*array(datingLabels))
#scatter散点图展示第二列和第三列数据
ax2.scatter(datingDataMat[:,1],datingDataMat[:,2],s=15*array(datingLabels),color=ColorOfDatingLable(datingLabels))
#scatter散点图展示第二列和第三列数据,第一个15*array(datingLabels)用来表现不同标签的不同半径
ax3.scatter(datingDataMat[:,1],datingDataMat[:,2],s=15*array(datingLabels),color=ColorOfDatingLable(datingLabels),label='largeDoses/smallDoses/didntLike')
ax4.scatter(datingDataMat[:,0],datingDataMat[:,1],s=15*array(datingLabels),color=ColorOfDatingLable(datingLabels),label='largeDoses/smallDoses/didntLike')
ax5.scatter(datingDataMat[:,0],datingDataMat[:,2],s=15*array(datingLabels),color=ColorOfDatingLable(datingLabels),label='largeDoses/smallDoses/didntLike')
ax3.legend(loc='upper right')
ax4.legend(loc='upper right')
ax5.legend(loc='upper right')
plt.show()
看一下scatter函数的基本的使用方法:
#导入必要的模块
import numpy as np
import matplotlib.pyplot as plt
#产生测试数据
x = np.arange(1,10)
y = x
#产生figure对象
fig = plt.figure()
ax1 = fig.add_subplot(111)
#设置标题
ax1.set_title('Scatter Plot')
#设置X轴标签
plt.xlabel('X')
#设置Y轴标签
plt.ylabel('Y')
#画散点图
ax1.scatter(x,y,c = 'r',marker = 'o')
#设置图标
plt.legend('x1')
#显示所画的图
plt.show()
结果图如下:
这里再对shape函数做一个说明:
shape函数是numpy.core.fromnumeric中的函数,它的功能是查看矩阵或者数组的维数。
举例说明:
建立一个3×3的单位矩阵e, e.shape为(3,3),表示3行3列,第一维的长度为3,第二维的长度也为3
>>> e = eye(3)
>>> e
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
>>> e.shape
(3, 3)
下面上结果图:
figure1:
画散点阵scatter来说,它的参数设置是这样的:
#plt.scatter(x[i],y[i],marker = 样式,s=大小半径,color =颜色,label = 点备注
#15*array(datingLabels)它来规定点的尺度大小
接下来看第二幅图:
figure 2:
这里注释下,可能因为图大小设置的问题,这里文字和图标重复,其中,
绿色表示small;
红色表示large;
黑色表示donot;
我们对所得结果做一个分析:
从上图中可以看出,红点的密集区域以及各个维度之间的联系,其中吃不吃冰激凌,这个貌似并不能作为评判的影响性因素,因为冰激凌量的多少,完全符合了均匀分布。
唯一有价值的算是第二幅图,我们可以看出,飞行时间在40000左右,玩游戏时间所占比例为10%左右,xx女士比较喜欢这样类型的男士,并且表现出了极大兴趣,而飞行时间过长,或者游戏时间很短,却不受她的青睐。
我们这里揣测一下xx女士的想法,她喜欢的类型应该是比较活泼的,见多识广,但又能不经常出差希望陪伴在自己身边的男士,从飞行距离上看出,适当的旅行能增长见识,会更有趣,而过长的飞行时间,只能表明,他要么在出差,要么就属于那种全世界游玩的人,这样的不定性而缺乏安全感,我想这也就是xx女士并不喜欢这类男士的原因吧,而飞行时间很短,缺乏对外界的认识,让xx女士觉得这类男士缺乏见识和有趣度,你想,一个常年待在家的人,会有多少有趣呢,俗话说得好,读万卷书不如行万里路,我想也是xx女士判别一个人是否有趣的因素吧,而游戏时间上来说,过短的游戏时间,可能会让xx女士认为男士缺乏幽默,激情,智商的表现,毕竟游戏很多都是对一个人反应能力,情商,布局能力的各方面体现。
所以,xx女士认为一个不玩游戏,并且飞行距离超长的男士,只能判断为长期出差在外,所以并不喜欢这类,而她对那些‘死宅’却保持着一般的兴趣,这点说明,死宅也有春天啊。
接下来谈一谈归一化数据:
为什么要归一化数据:
假设有两个变量,都是均匀分布,X1范围是100000到200000,X2的范围是1到2。现在请在一张A4纸上画个坐标,点出这些点。很显然,你会点出很多处于同一直线上的点,我们称这条直线为L。也就是说,如果现在我们要做一个classification的话,X2几乎可以被忽略。X2很无辜的被干掉了,仅仅因为所谓量纲的问题。
即便X2不被干掉,我们现在继续求解,来做 gradient descent(梯度下降)。 很显然,如果某一步我们求得的下降方向不在直线L上,几乎可以肯定肯定这步不会下降。这就会导致不收敛,或者收敛但很慢。再来,我们做一遍归一化,全部化为[0,1]区间上。现在再在纸上画个坐标,点出这些点。好了,他们现在均匀的分布在一个圆的范围内。X2不会被忽略了,收敛的问题也解决了。
举个例子:
假定为预测房价的例子,自变量为面积,房间数两个,因变量为房价。
那么可以得到的公式为:
我们在寻找最优解的过程也就是在使得损失函数值最小的theta1,theta2。
上述两幅图代码的是损失函数的等高线。
数据没有归一化的表达式,可以为:
求解过程图示:
数据归一化之后,损失函数的表达式可以表示为:
求解过程图示:
从上可以看出,数据归一化后,最优解的寻优过程明显会变得平缓,更容易正确的收敛到最优解。
分析下数据可以看出,飞行距离相对于其他两个特征的数据来说通常要大的多,如果不进行数据归一化,那么在计算距离的时候飞行距离对结果的影响占绝对主导性,这显然是不合理的,所以需要进行数据归一化
# 归一化函数
def autoNorm(dataSet):
# 求数据矩阵每一列的最小值
minVals = dataSet.min(0)
# 求数据矩阵每一列的最大值
maxVals = dataSet.max(0)
# 求数据矩阵每一列的最大最小值差值
ranges = maxVals - minVals
# 返回数据矩阵第一维的数目
m = dataSet.shape[0]
# 求矩阵每一列减去该列最小值,得出差值
normDataSet = dataSet - tile(minVals,(m,1))
# 用求的差值除以最大最小值差值,即数据的变化范围,即归一化
normDataSet = normDataSet / tile(ranges,(m,1))
# 返回归一化后的数据,最大最小值差值,最小值
验证分类器思想
所以得提前步骤准备妥当之后,可以来测试这个分类器的精度了。
步骤就是
1.把数据集分类测试集和训练集,当然,knn没有训练这个说法
2.测试集遮去标签,只输入数据,直接靠KNN的算法,进行预测判断标签
3.测试集本身自己的标签是正确的,只是暂时不用而已,用来当判断knn算法是否判断正确
4.错误率也就是=贴错的标签总数/总的测试样本数
这里直接上分类器的代码:
def classify0(inX,dataSet,labels,k): # inX用于需要分类的数据,dataSet输入训练集
######输入与训练样本之间的距离计算######
dataSetSize = dataSet.shape[0] # 读取行数,shape[1]则为列数
diffMat = tile(inX,(dataSetSize,1))-dataSet # tile,重复inX数组的行(dataSize)次,列重复1
sqDiffMat = diffMat**2 #平方操作
sqDistances = sqDiffMat.sum(axis=1) # 每一个列向量相加,axis=0为行相加
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort() # argsort函数返回的是数组值从小到大的索引值
#print sortedDistIndicies #产生的是一个排序号组成的矩阵
classCount={}
######累计次数构成字典######
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]] #排名前k个贴标签
classCount[voteIlabel] = classCount.get(voteIlabel,0)+1 # 不断累加计数的过程,体现在字典的更新中
#get(key,default=None),就是造字典
######找到出现次数最大的点######
sortedClassCount = sorted(classCount.iteritems(),key = operator.itemgetter(1),reverse=True)
#以value值大小进行排序,reverse=True降序
#key = operator.itemgetter(1),operator.itemgetter函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值
return sortedClassCount[0][0]
#返回出现次数最多的value的key
测试器分类精度的代码:
#测试分类器精度
def datingTest(HORATIO,K):
hoRatio = HORATIO #取百分之十作为测试数据
datingDataMat,datingLabels = file2matrix("D:\PYthon-learning\Python_test\knn-test-2\KNN\datingTestSet2.txt")
normMat,ranges,minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m*hoRatio) #挑选出多少组测试数据
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],K)
print "the classifier came back with:%d,the real answer is %d"%(classifierResult,datingLabels[i])
if classifierResult !=datingLabels[i]:
errorCount +=1.0
print "the total error rate is : %f" % (errorCount/float(numTestVecs))
if __name__ == '__main__':
HORATIO = input("Please enter test set (%all): ")
K = input("Please enter the k: ")
datingTest(HORATIO,K)
结果如图:
最后错误率是5%。
接下来,改进代码,让这个KNN算法可以依照输入自己判断类型:
def classifyPerson():
resultList = ['not at all','in small doses','in large doses']
percentTats = input("percentage of time spent playing video games?")
ffMiles = input("frequent flier miles earned per year?")
iceCream = input("liters of ice cream consumed per year?")
datingDataMat,datingLabels = file2matrix("D:\PYthon-learning\Python_test\knn-test-2\KNN\datingTestSet2.txt")
normMat,ranges,minVals = autoNorm(datingDataMat)
inArr =array([ffMiles,percentTats,iceCream])
classifierResult = classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
print "You will probably like this person: ",resultList[classifierResult -1]
if __name__ == '__main__':
classifyPerson()
结果如下:
最后,贴一张机器学习实战解决问题的流程图:
Android 应用快捷方式 Shortcuts简介: 快捷方式可帮助用户快速访问您的应用的某些部分,从而为他们呈现特定类型的内容。一次最多可以为应用发布五个快捷方式(静态和动态快捷方式加在一起),但大多数启动器只能显示四个。不过,用户可创建的应用固定快捷方式数量没有限制。应用无法移除固定快捷方式,但仍然可以停用它们。效果图:快捷方式的类型:静态快捷方式:最适合在用户与应用互动的整个生命周期内使用一致结构链接到内容的应用。 由于大多数启动器一次只能显示四个快捷方式,因此静态快捷方式对常见 A
转自:https://www.jianshu.com/p/cc960670e009汇总查看RMAN备份信息的语句:检查某个时间段备份情況[[email protected] ~]$ sql / as sysdbaSQL> SELECT t.START_TIME,t.END_TIME,t.STATUS,t.OBJECT_TYPE,t.RECID FROM V$RMAN_STATUS t where t.START_TIME between trunc(sysdate)-2 and sysdate
翟天临涉嫌学术不端事件经过网上的持续发酵,在人民日报公开发文艾特了翟天临的博士学位授予单位北京电影学院和他的博士后录用单位北京大学后,北京电影学院表态,启动对事件的调查程序,并表示对学术不端行为零容忍。北京大学光华管理学院也发布说明表示,学位高度重视,将根据其博士学位授予单位的调查结论按规定做出处理。光华管理学院的说明似乎没有什么问题,翟天临的博士学位是北京电影学院授予的,他们查出问题我们就按有问题处理,他们调查没问题,我们就按没有问题处理。但是问题在于北京大学录用博士后,要有相关标准和审核程序的,根据目前
公司的项目部署在liunx 上, 访问的时候突然出现 GC overhead limit exceeded ,原因是服务器资源不足。sun公司对此问题的解释是:发现GC overhead limt exceed检查是Hotspot VM 1.6定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。Sun 官方对此的定义是:“并行/并发回收器在GC回收时间过
VISIO也适用如下方式:3. 当然也可以直接是 Ctrl + Alt + V打开选择性粘贴选项卡 来选择其中某项来粘贴也是可以的转:word 2010中设置默认粘贴为 只保留文本粘贴2012年12月21日 21:19:32 小龙王2010 阅读数 6786更多分类专栏: Microsoft Office ...
mysqlslap 可以用于模拟服务器的负载,并输出计时信息。其被包含在 MySQL 5.1 的发行包中。测试时,可以指定并发连接数,可以指定 SQL 语句。如果没有指定 SQL 语句,mysqlslap 会自动生成查询 schema 的 SELECT 语句。1. 查看帮助信息。[[email protected] libmysql]# mysqlslap --helpmysqlslap Ver 1.0 Di...
Android应用资源的两大类:assets目录下,无法通过R资源清单类访问的原生资源,应用程序需要通过AssetManager以二进制流的形式读取资源。res目录下,可通过R资源清单访问的资源,Android SDK会在编译应用时,自动在R.java文件中为这些资源建立索引。
文章目录Javaweb(了解原理,底层)javaweb1.1javaweb的概念1.2 web应用程序1.3静态web1.4动态web1.5web服务器tomcat1.6HTTPTomcatMaven(工具)1.为什么要学这个?2.Maven的下载3.IDEA中使用maven1.创建mavae项目2.创建tomcat3.maven配置Servlet1.什么是Servlet2.怎样使用3.HelloServlet4.Servlet原理5.Servlet和Servlt_mapping6.ServletConte
Load and Performance Test ToolsBrowserMob- On-demand, self-service, low-cost, pay-as-you-go service enables simulation of large volumes of real browsers hitting a website. Utilizes Amazon Web Servi...
USB Over NetworkLinux上常遇到讀卡機無法在 !FireFox 使用的問題,其實這個議題已經有許多的商用軟體已經解決了。許多軟體提供透過驅動程式與網路將裝置掛載到遠端的作業系統中,從下面的網址可以看到現有的 USB Over Network Softwarehttp://usb-over-network.qarchive.org/USB Server如何將本地端的 USB 連接埠...
[FONT=courier new]ads_point pt0;void ident_init(ads_matrix id);int dragsample(ads_point usrpt,ads_matrix matrix);AcDbObjectId create_DragGen_Line(ads_point startPt,ads_point endPt);AcDbObjectId DragGe...
maven入门到精通scope参数相关参数compile默认的scope,表示 dependency 都可以在生命周期中使用。而且,这些dependencies 会传递到依赖的项目中。适用于所有阶段,会随着项目一起发布provided跟compile相似,但是表明了dependency 由JDK或者容器提供,例如Servlet AP和