您的位置:首页 > 其它

机器学习实战精读--------K-近邻算法

2017-08-15 13:12 423 查看
对机器学习实战的课本和代码进行精读,帮助自己进步。

开发机器学习应用程序的步骤一、收集数据
爬虫去网上爬取数据。

二、准备要输入的数据
对数据进行处理,确保数据的格式符合要求。

三、分析输入数据
确保数据集中没有垃圾数据。

四、训练算法
训练的结果简单来说就是得到一组模型的参数,最后使用采用这些参数的模型来完成我们的分类任务。

五、测试算法
用来评估算法,如果不满意回到第四步训练算法,但是问题一般是数据收集和准备的有问题,回到收集数据。

六、使用算法
将机器学习算法转换为应用程序,对实际的问题进行处理。









K-近邻算法是监督学习:因为人为的定义了“正确”的答案。
#coding:utf-8
from numpy import *
import operator
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt

#创建数据集和标签
def createDataSet():
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])  #数据集
#python中的list是python的内置数据类型,list中的数据类不必相同的,而array的中的类型必须全部相同。在list中的数据类型保存的是数据的存放的地址,简单的说就是指针,并非数据,这样保存一个list就太麻烦了,例如list1=[1,2,3,'a']需要4个指针和四个数据,增加了存储和消耗cpu。
labels = ['A','A','B','B']    #标签
return group,labels        #输出数据集和标签

'''
KNN算法伪代码

(1)、计算已知类别数据集中的点与当前点之间的距离。
(2)、计算完所有点之间的距离以后,按照距离递增次序排序。
(3)、选取与当前距离最小的k个点。
(4)、确定前k个点所在类别的出现频率。
(5)、返回前k个点出现频率最高的类别作为当前点的预测分类。

'''

#实施KNN算法
def classify0(inX, dataSet, labels, k):
# KNN.classify0([0,0],group,labels,3)
#inX:用于分类的输入向量; dataSet:输入的训练样本集; labels:标签向量; k:选择最近邻居的数目
dataSetSize = dataSet.shape[0]
#读取矩阵第一维度的长度。上面的数据集的情况 值是:4
diffMat = tile(inX, (dataSetSize,1)) - dataSet
'''
在列的方向上重复列1次 行重复四次。
tile(inX, (dataSetSize,1))的值:
[[0,      0],
[0,      0],
[0,      0],
[0,      0]]

diffMat 的值:
[[-1.  -1.1]
[-1.  -1. ]
[ 0.   0. ]
[ 0.  -0.1]]

'''
sqDiffMat = diffMat**2
'''
sqDiffMat的值:
[[ 1.    1.21]
[ 1.    1.  ]
[ 0.    0.  ]
[ 0.    0.01]]
'''
sqDistances = sqDiffMat.sum(axis=1)
'''
sqDistances的值:
[ 2.21  2.    0.    0.01]
'''
#axis=1以后就是将一个矩阵的每一行向量相加
distances = sqDistances**0.5

'''
distances 的值:
[ 1.48660687  1.41421356  0.          0.1       ]
'''
sortedDistIndicies = distances.argsort()
'''
sortedDistIndicies的值:
[2 3 1 0]
'''
#返回的数组值从小到大的索引值.
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)
'''
sortedClassCount 的值:
[('B', 2), ('A', 1)]
'''

return sortedClassCount[0][0]

#step01 :因为直接用的人家的文件,所以我们这一步没有收集数据,我们可以用python爬虫进行海里数据收集

#step02 : 准备数据:从文本文件中解析数据,得到距离计算所需要的数值
def file2matrix(filename):
fr = open(filename)
#打开文件,赋值给fr
numberOfLines = len(fr.readlines())
#得到文件有多少行数据
returnMat = zeros((numberOfLines,3))
#创建给定类型的矩阵,并初始化为0,另一维度设置为固定数值3
classLabelVector = []
fr.close()
#有打开就要有关闭,这个它代码里没有 我把这个加上不影响结果输出。
fr = open(filename)
index = 0
for line in fr.readlines():
#.readline() 和 .readlines() 之间的差异是后者一次读取整个文件,象 .read() 一样。.readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。另一方面,.readline() 每次只读取一行,通常比 .readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 .readline()
line = line.strip()
#截取掉所有的回车字符。
listFromLine = line.split('\t')
#使用tab字符\t将上一步得到的整行数据分割成一个列表
returnMat[index,:] = listFromLine[0:3]
#选取前三个元素,将它们存储到特征矩阵中
classLabelVector.append(int(listFromLine[-1]))
#将列表中最后一列存储到向量classLabelVector中
index += 1
fr.close()
#有打开就要有关闭 ,这个它代码里没有 我把这个加上不影响结果输出。
return returnMat,classLabelVector

#step02:   准备数据:归一化数值
#在处理这种不同取值范围的特征值时,我们通常采用的方法是将数值归一化
#newvalue = (oldValue-min)/(max-min)  将任意取值范围的特征值转化为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))   #element wise divide
return normDataSet, ranges, minVals

#step03 :分析数据:使用Matplotlib创建散点图
def Analysis():
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
fig =plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
plt.savefig('knn.png')

#step04: 测试算法:作为完整程序验证分类器
def datingClassTest():
hoRatio = 0.50      #hold out 10%
datingDataMat,datingLabels = file2matrix('./datingTestSet2.txt')       #load data setfrom file
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],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

#step05  使用算法:构建完整可用系统
def classifyPerson():
resultList = ['not at all','in small doses','in large doses']
percentTats = float(raw_input("percentage of time spent palying video games?"))
ffMiles = float(raw_input("freguent filer miles earned per year?"))
iceCream = float(raw_input("liters of ice cream consumed per year?"))
datingDataMat,datingLabels = file2matrix('./datingTestSet2.txt')
normMat,ranges,minVales = autoNorm(datingDataMat)
inArr = array([ffMiles,percentTats,iceCream])
classifierResult = classify0((inArr - minVales)/ranges,normMat,datingLabels,3)
print "you will probably like this person:",resultList[classifierResult -1]
数据分析图:



重点:
01:K-近邻算法底层算法是欧式距离公式,计算m维空间中两点之间的真实距离,或者向量的自然长度。
02:归一化数值:
newvalue = (oldValue-min)/(max-min)  将任意取值范围的特征值转化为0到1区间的值
这个思想很重要。
03:针对特征空间维数大及训练数据大时,需要考虑如何快速进行k-近邻搜索。
体会:在我看来,整个机器学习从数据采集到最终的程序,整个流程特别重要,算法是核心,处理干扰项的时候,我们用到了归一化。
04:缺点:如果训练集很大,则需要使用大量的存储空间,因为要对每个数据求距离,所以会很耗时!

知识点:
结构化数据:也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进彳存储和管理。

向量:(也称为欧几里得向量、几何向量、矢量),指具有大小(magnitude)和方向的量。它可以形象化地表示为带箭头的线段。箭头所指:代表向量的方向;线段长度:代表向量的大小

分类器的错误率:分类器给出错误结果的次数除以测试执行的总数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息