读书笔记-机器学习实战-kNN
- kNN思想:
已知训练样本集和其对应的标签,对于没有标签的新数据,将新数据的每个特征和训练样本集中数据对应的特征进行比较,提取样本集中最相似的k个数据的标签,选择k个最相似数据中出现最多次数的标签作为新数据的标签。
1.从文本文件中解析数据
对未知类别属性的数据集中的每个点依次执行以下操作:
(1)计算已知类别数据集中的点与当前点之间的距离;
(2)按照距离递增次序排序;
(3)选取与当前点距离最小的k个点;
(4)确定前k个点所在类别的出现频率;
(5)返回前k个点出现频率最高的类别作为当前点的预测分类。
这里书上的demo有点问题,问题就是tile()函数生成array的shape不对。
- numpy.tile(A, reps)
A:输入的array
reps: 沿每个axis重复的次数
返回通过reps次重复A构造的array
example:
修改后的demo:
def classify(inX,dataSet,labels,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()
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
第3行代码,首先group的shape是(4,2),有4行,每行有2列,所以重复次数为dataSet.size。由于输入的inX是一个 1
×
2 的 array,numPy.tile()的目标是将inX复制成一个4
×
2 的array, 所以tile的reps为(dataSet.size,1)
得出结果[0,0]分类为B:
2.约会网站改进匹配对象
- 从文件中读取数据并转化为样本矩阵和类标签
def filematrix(filename):
fr=open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
#生成一个文件行数长度的3列的全是0的array
returnMat = zeros((numberOfLines, 3))
classLabelVector = []
index = 0
for line in arrayOLines:
#去除空格
line = line.strip()
#以\t分割
listFromLine = line.split('\t')
returnMat[index,:] = listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat,classLabelVector
- 用 matplotlib创建散点图
datingDataMat,datingLabels = filematrix('datingTestSet2.txt')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
plt.show()
样本矩阵中的第二和第三列数据,x轴表示特征值“玩视频游戏所花时间百分比”,y轴表示“每周消耗的冰淇淋数”。
图中为一个颜色,自然想到分颜色区分:
修改代码:
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
得到三种颜色不同点大小的散点图:
用不同的属性值会有不同的散点图,如下,显示前两个特征值的散点图为:
图中可以清晰的标示三个类别的数据,具有不同爱好的人其类别区域不一样。
归一化数据
将数据归一到0-1区间:使用当前值减去最小值除以取值范围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
测试分类器
将样本的10%作为测试数据来检验分类器的性能
def datingClassTest():
hoRatio = 0.10
datingDataMat, datingLabels = filematrix('datingTestSet2.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
#测试集,可调整hoRatio
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify(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))
结果为: 分类错误率为5%
- 根据输入数据进行预测
加入获取输入的input:
def classifyPerson():
#预测结果列表
resultList = ['not at all','in samll does','in large does']
#输入
percentTats = float(raw_input("video game?"))
ffMiles = float(raw_input("frequent flier miles earned per year?"))
iceCream = float(raw_input("ice cream?"))
datingDataMat, datingLabels = filematrix('datingTestSet2.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
inArr = array([ffMiles,percentTats,iceCream])
classifierResult = classify((inArr-minVals)/ranges,normMat,datingLabels,3)
print "you will probably like this person:",resultList[classifierResult]
输入结果为: