机器学习小白,各位多多交流
def classify0(inX, dataSet, labels, k): #这个函数就是分类器的函数,要输入4个参数,第一个为测试元素,第二个为数据集,第三个对
#对应的标签,第四个为K-邻值检测的 K值
dataSetSize = dataSet.shape[0] #先求出测试机的行数
diffMat = tile(inX, (dataSetSize,1)) - dataSet #将测试对象(为一个列表),扩展成一个数组。并和数据集里面的每一个对象进行相减
sqDiffMat = diffMat**2 # 将相减之后得到的数组进行平方,及数组对应位置的平方,返回的还是一个数组
sqDistances = sqDiffMat.sum(axis=1) # 按列方向,将平方之后的数字进行相加,得到一个行一样,列为一列的数组
distances = sqDistances**0.5 #在对求出的数组,每个元素进行开方,来求测试对象和每一个样本集之间的距离
sortedDistIndicies = distances.argsort() #然后对求出后的distance 进行排序,并且放回的是这个数在distantces 里面的引索值
classCount={} #建立一个空的字典
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]] #取出排前K个数 在原来的位置的引索值,并取得对应引索值下的label值
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #dict.get()方法, 如果该label值原来没有的
# 则新建这个key=lable 的键 并且赋值为0 原来这个dict里面本来就有这个key 的话 那就对应增加这个value的值加1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
#对classCount这个字典先进性items , 通过对items里面的第二个内容的数字大小进行排序,这里即数字,然后为倒叙先大后小,得到一个以元组为元素的列表
#这里值得注意的是,没办法对字典本身进行排序的,必须先用items方法之后,再进行排序
return sortedClassCount[0][0] #返回排序中最大元组里面的 标签值
def createDataSet():
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = ['A','A','B','B']
return group, labels
def file2matrix(filename):
fr = open(filename) #打开名字为filename 的文件名,如果是绝对路径则输入据对路径,如r'D:/xxx.txt',因为本文采用的是相对路径
numberOfLines = len(fr.readlines()) # 计算改文件的行数,并赋值给 number0fLines
returnMat = zeros((numberOfLines,3)) # 通过zeros 创建一个行数为 number0flines,列数位3 的初始 0 矩阵 名字为returnMat
classLabelVector = [] # 定义了一个classLabelVector 的空列表 用于下面的搜集标签
index = 0 #设置一个值为0 的index 变量
for line in fr.readlines(): #对文本中的每一个值进行预处理
line = line.strip() #先去掉每一行里面首尾的空格及换行符
listFromLine = line.split('\t') #然后根据key= '\t'空格符 进行切片 得到的是 每一行的 分开的列表
returnMat[index,:] = listFromLine[0:3] # 对相应位置的行进行赋值,赋值的内容为listFromLine 列表的前3个元素,有点像Dict 的赋值
# 这里需要主要的 因为数组或者矩阵是先行后列的描述,因此如果数字在冒号前面,及对行进行操作,数字在冒号后面即对列进行操作
classLabelVector.append(int(listFromLine[-1])) #将listFromLine列表的最后一项及标签,按书序添加到classLabelVector
#这里对标签项用Int()函数 是为了让标签是一个整体字符串的形式
index += 1 #然后index 逐步加1 这样就可以 把 txt 里面的所有数据 按照顺序安排带returnMat 中
return returnMat,classLabelVector #结果返回 一个数组(前) 一个列表(后)
def autoNorm(dataSet): #因为每个指标的取指范围是不一样的,那么在进行计算的时候,就会造成取值大的指标对结果的影响更大
#因此需要对原来的数据进行 归一化的处理,类似百分比,这里的dataset 及上一个函数返回的 returnMat
minVals = dataSet.min(0) #取出每一列的最小值,axis=0 表示竖的方向,axis=1表示横着的方向,返回的是一个列表
maxVals = dataSet.max(0) #取出每一行的最大值
ranges = maxVals - minVals #计算出最大值和最小值之间的差值
normDataSet = zeros(shape(dataSet)) #这一步要不要其实都没关系,只是构建了一个和dataset 一样行列的数组而已
m = dataSet.shape[0] #计算出 dataset 的行数,这里是用中括号
normDataSet = dataSet - tile(minVals, (m,1)) # 先看tile()这个函数,因为minVal 只是一个列表, tile将该列表在行方向重复m次,列方向不动
#这样出来的就是和dataset 一样 行列的数组,然后通过数组之间的相减实现批量操作
normDataSet = normDataSet/tile(ranges, (m,1)) #这里的原理和上面一样,只不过是数组之间的相除,只要对应的位置进行相除就可以。
return normDataSet, ranges, minVals #最后返回3个只,最后的normDateSet 为归一化之后的数组,ranges是最大最小值相减之后的数组
def datingClassTest(): #在进行归一化之后,我们得到了最后可用的数据,也就是我们手头上所有的样本,那么我们需要将样本分成训练样本和验证样本,其实还有一个是测试样本
hoRatio = 0.10 #这里的hoRation 从后面可知就是需要进行测试的样本百分比
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') #将函数file2matrix函数返回的数据值和标签列表返回给datingDataMat 和datingLabels
normMat, ranges, minVals = autoNorm(datingDataMat) #上面得到的数据datingDataMat 被函数autoNorm进行处理,然后换回3个值
m = normMat.shape[0] #得知normMat 的行数,给m
numTestVecs = int(m*hoRatio) #行数的百分之10 整体的数 给numTestVecs
errorCount = 0.0 #这里设置了一个 错误的基数器
for i in range(numTestVecs): #假如全部的样本有1000条,这里的numTestVecs 就是100条,对这100条的数据进行测试
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
#其中classify0 是分类器算法,normMat[i, :]表示normMat中第i行 成为测试数据,normMat的100行下所有数据作为训练数据
# datingLabels(它是一个列表)是对应100到最后的标签数据, k-近邻算法里面的K值 取前3个结果对象的标签来确定测试样本的特征值
print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])
#打印出 测试结果和 测试数据本身的标签值
if (classifierResult != datingLabels[i]): errorCount += 1.0
#如果测试结果和测试数据本身标签纸不一样,则错误数加1
print "the total error rate is: %f" % (errorCount/float(numTestVecs))
#打印错误路,因为errorCount是小数浮点数,因此分母也需要改成浮点数格式
print errorCount