算法的介绍
机器学习算法可以分为三个大类 —— 监督学习、无监督学习和强化学习。
监督学习,对训练有标签的数据有用,但是对于其他没有标签的数据,则需要预估。
无监督学习,用于对无标签的数据集(数据没有预处理)的处理,需要发掘其内在关系的时候。
强化学习,介于两者之间,虽然没有精准的标签或者错误信息,但是对于每个可预测的步骤或者行为,会有某种形式的反馈。
而k近邻算法是一种监督学习算法,因为需要知道分类的标签来将数据及进行分类
自我介绍
工作中主要使用java编程,基于Spring系列框架进行开发。人工智能一直很火,辞职后闲来无事,很久之前就希望好好研究一下机器学习,这段时间正好得以时间,所以开始自己的机器学习的生涯。本篇博客也是开山之作,希望能够不断的坚持,与大家分分享学习中的点点滴滴。用词不当也请多多指出。
参考文献:《Machine Learning in Action》,知乎百科
k近邻算法思想阐述
用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居), 这K个实例的多数属于某个类,就把该输入实例分类到这个类中。
k近邻算法实例一
目标:
已得到被分为A,B两类点的测试集,对于一个新加入点,判断其属于哪一类别。
伪代码:
- 计算测试集dataSet中每个点与新加入点inX的距离
- 按照距离递增排序
- 选取距离最近的k个点(k一般小于20)
- 确定前k个点的标签的频率分布
- 取占比例最多的为分类结果
python代码如下:
// By Quo &Peter Harrington
from numpy import *
import operator
#初始化数据
def createDataSet():
group=array([[1,1.1],[1,1],[0,0],[0,0.1]])
labels=['A','A','B','B']
return group,labels
group,labels=createDataSet()
#分类器
def classfy0(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
#使得矩阵大小相同,从而做减法运算
diffMat=tile(inX,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
sqDistances=sqDiffMat.sum(axis=1)
#axis=1代表每一行之前求和,为0表示每一列之间求和
distances=sqDistances**0.5
#以上为计算目标矩阵和训练集的距离,即相减之后 求平方的和,最后开方
sortedDistanceRank=distances.argsort()
#argsort排序,首先按照递增排序,之后将值变成原先位置的标号(用以定位)
classCount={}
for i in range(k):
voteIlabel=labels[sortedDistanceRank[i]]
#argsort的作用下 正好对应到之前的位置,所以找到对应的分类标签
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
sortedClassCount= sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
#从根据频率大到小的排名
return sortedClassCount[0][0]
print(classfy0([0,0],group,labels,3))
k近邻算法实例二
根据已有数据文件生成对应的数据矩阵,即海伦相亲问题
海伦已经收集约会数据一段时间了,他把每个相亲对象数据总结为4列
- 每年的飞行里数
- 每天玩游戏所占的时间比例
- 每周吃的冰淇淋KG
- 好感程度(即1为不满意,2为满意,3为非常满意)
数据格式实例
40920 8.326976 0.953952 3
14488 7.153469 1.673904 2
26052 1.441871 0.805124 1
75136 13.147394 0.428964 1
38344 1.669788 0.134296 1
72993 10.141740 1.032955 1
35948 6.830792 1.213192 3
问题:怎样利用已有的1000个数据来写一个分类器帮助海伦选择自己的心动男生呢?
算法思想:
- 文本数据处理,转换为矩阵的形式,以便在程序中使用
- 归一化数据,使三个维度的数据能够具有同样的0到1的范围值
- 选取训练集和测试集,使用实例一中的classfy0的分类器进行分类
- 统计正确率
代码:
from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plot
#文件转化为矩阵
def file2matrix(filename):
fr=open(filename)
arrayOflines =fr.readlines()
numerOfLines=len(arrayOflines)
#获取行数,即数据总量
returnMat=zeros((numerOfLines,3))
#建立空矩阵
classLabelVector=[]
index=0
for line in arrayOflines:
line=line.strip()
#截取回车字符
listFromLine=line.split('\t')
#利用数字之间的tab拆分成一个数组
returnMat[index:]=listFromLine[0:3]
#前三个数录入特征矩阵
classLabelVector.append(int(listFromLine[-1]))
#最后一个数作为分类向量
index=index+1
return returnMat,classLabelVector
#归一化处理
def autoNorm(dataSet):
minVals=dataSet.min(0)
maxVals=dataSet.max(0)
#选出每一列的最小值组成的一维向量
ranges=maxVals-minVals
normDataSet=zeros(shape(dataSet))
m=dataSet.shape[0]
normDataSet=dataSet - tile(minVals,(m,1))
#每一个值减最小值
normDataSet= normDataSet/tile(ranges,(m,1))
#除以最大值和最小值的差
return normDataSet,ranges,minVals
def datingClassTest():
hoRatio=0.1
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
normDataMat, ranges, minVals = autoNorm(datingDataMat)
m=normDataMat.shape[0]
numTestVecs=int(m*hoRatio)
#取百分之十作为测试,百分之九十用来训练
errorCount=0
#本循环,代表着对于测试集中的每一项依次进行分类
for i in range(numTestVecs):
classifierResult = classfy0(normDataMat[i,:],normDataMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
#参数一为待分类元素,参数二为测试集,参数三为测试集对应的标签分类,参数四为k值,这里选取了3
dict0={1:'不满意',2:'满意',3:'非常满意'}
print("分类器返回结果为",dict0.get(classifierResult),"实际结果为",dict0.get(datingLabels[i]))
if(classifierResult!=datingLabels[i]):
errorCount=errorCount+1
print("错误率为",errorCount/numTestVecs)
datingClassTest()