最近开始系统的做一些机器学习方面的学习,选中了图灵程序设计丛书的《机器学习实战》作为教材。
开发环境上个人选择了集成了python2.7与各类数据分析相关的python包的Anaconda4.4。
k-means算法
概述
“简单地说,k近邻算法采用测量不同特征值之间的距离方法进行分类。”通过将未知分类标签的新数据与已知分类标签的样本数据集进行比较,提取其中前k个最相近的分类标签,将其中出现次数最多的标签作为新数据的分类。
“优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
适用数据范围:数值型和标称型。”
代码分析
进行k近邻算法的函数,k近邻算法本质上是计算点之间的欧氏距离后再进行比较,统计操作。
#参数inX为用于分类的向量,labels为标签向量,k为选择最近邻居的数量
def classify0(inX, dataSet, labels, k):
#用shape[0]取y轴方向的矩阵维度,也就是行数
dataSetSize = dataSet.shape[0]
#tile将inX沿着y轴复制dataSetSize次,沿着x轴复制1次
diffMat = tile(inX, (dataSetSize,1)) – dataset
sqDiffMat = diffMat**2
#将sqDiffMat.sum矩阵每一行相加
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
#argsort()返回数组值从小到大的索引,就是将计算好的距离进行了排序
sortedDistIndicies = distances.argsort()
classCount={}
#统计最近的k个邻居所属的分类
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#此处.iteritems()返回字典键值对的元祖组合,operator.itemgetter(1)为函数,作用为获取对象某一维的数据,此处作为sorted()函数的key参数传入,即代表以classCount的每个votellbel的值作为排序标准,reverse代表是否反向
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
将文本转换为矩阵的函数,用于将一些格式化的文本转换为numpy矩阵方便处理
def file2matrix(filename):
fr = open(filename)
numberOfLines = len(fr.readlines())
#新建numberOfLines*3的矩阵,用0填充
returnMat = zeros((numberOfLines,3))
classLabelVector = []
fr = open(filename)
index = 0
for line in fr.readlines():
#截取掉回车
line = line.strip()
#以tab为分割生成字符列表
listFromLine = line.split('\t')
returnMat[index,:] = listFromLine[0:3]
#利用负索引取分类
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat,classLabelVector
特征值归一化,本质计算newValue = (oldValue-min)/(max-min)
def autoNorm(dataSet):
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
#新建与原数据集大小一致、以0填充的矩阵
normDataSet = zeros(shape(dataSet))
#取行数
m = dataSet.shape[0]
#(oldValue-min)
normDataSet = dataSet - tile(minVals, (m,1))
#除以(max-min)
normDataSet = normDataSet/tile(ranges, (m,1))
return normDataSet, ranges, minVals
分类测试,用于测试算法的准确度
def datingClassTest():
#测试样本所占的比例,此处占一半
hoRatio = 0.50
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
#初始化错误率
errorCount = 0.0
for i in range(numTestVecs):
#对第i个样本用剩下的另一半样本进行测试
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
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))
print errorCount