新的学习征程
之前的blog主要是关于Android和Nodejs的一些开发学习笔记,在经历了一段时间的学习和实习之后,也拿到了几个大厂offer,痛定思痛下决心在大四参加考研,现在考研成功,也要继续开始新的学习了,接下来的学习将主要以Machine Learning为主,由于很多主流的书籍论文都是英文,希望也能锻炼着以后用英文来写一些学习记录blog。我个人之前是没有过任何机器学习相关的学习经验的,现在也是from 0 to n.
项目源代码
这一个系列打算都放在这个project里面,语言是Python,即时更新,希望能点个star
https://github.com/CallMeSp/MachineLearning
正文
机器学习开发大体遵循一定的步骤
- 收集数据
- 准备输入数据
- 分析输入数据
- 训练算法(无监督学习则不需要)
- 测试算法
- 使用算法
机器学习界有个所谓的“十大算法”或者“二十大算法”
今天带来的就是最简单的一个:k-近邻算法
工作原理很简单:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似的分类标签。一般来说只是选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,简称kNN
kNN优劣:
优势 | 劣势 |
---|---|
精度高、对异常值不敏感 | 计算复杂度高 |
无数据输入假定 | 空间复杂度高 |
算法:
def classify0(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
#[0]和[1]分别是行数和列数
diffMat = tile(inX,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
sqDistances=sqDiffMat.sum(axis=1)
#axis=0指同一行相加
distances=sqDistances**0.5
sortedDistIndicies=distances.argsort()
#递增排列的原数组下标组成的新数组
classcount={}
for i in range(k):
#选择距离最小的k个点
vl=labels[sortedDistIndicies[i]]
classcount[vl]=classcount.get(vl,0)+1
sortedclasscount = sorted(classcount.iteritems(),key=operator.itemgetter(1),reverse=True)
#距离最小的k个点中哪个类别占得比重多
return sortedclasscount[0][0]
归一化特征值
这种处理是防止同等权重的特征因为范围差距大,而导致某个特征严重的影响到计算结果,所以进行一下处理,将所有的特征值全都转化到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
示例demo
环境:linux+Python2.7
测试用例:在gihub链接中有
本demo参考《Machine Learning in Action》
from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt
from os import listdir
#分类,inX是待分类向量,dataSet是已有表现的一组数据,labels就是该标签元组,k是kNN中对应的k,
def classify0(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):
vl=labels[sortedDistIndicies[i]]
classcount[vl]=classcount.get(vl,0)+1
sortedclasscount = sorted(classcount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedclasscount[0][0]
#将文本文件转化为元组,这里为了更加直观,测试用例都通过txt形式来展现。
def file2Matrix(filename):
fr=open(filename)
arraylines=fr.readlines()
numberOfLines=len(arraylines)
returnMat=zeros((numberOfLines,3))
classLabelVector=[]
index=0
for line in arraylines:
line=line.strip()
listFromLine=line.split('\t')
returnMat[index,:]=listFromLine[0:3]
classLabelVector.append(listFromLine[-1])
index+=1
return returnMat,classLabelVector
#通过matplotlib绘图
def draw():
datas, labels = file2Matrix('datingTestSet2.txt')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datas[:, 1], datas[:, 2], 15.0 * array(map(int,labels)), 15.0 * array(map(int,labels)))
plt.show()
#归一化
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
#将demo中的示例归一化操作
def normalization():
dataSet,labels=file2Matrix('datingTestSet2.txt')
normMat,ranges,minvals=autoNorm(dataSet)
print normMat
print ranges
print minvals
#自动分类测试,打印错误率
def datingClassTest():
#前10%是用于测试正确率,后90%用于训练分类器
hoRatio=0.10
dataSet,labels=file2Matrix('datingTestSet.txt')
normMat,ranges,minvals=autoNorm(dataSet)
m=normMat.shape[0]
numTestVecs=int(m*hoRatio)
errorCount=0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],labels[numTestVecs:m],3)
print "the classifier came back with : %s,the real answer is : %s"%(classifierResult,labels[i])
if(classifierResult != labels[i]):
errorCount+=1
print "errorCount = %d"%(errorCount)
print "the total error rate is %f"%(errorCount/float(numTestVecs))
#将32*32文本信息转化为1*1024
def img2Vector(filename):
returnVect=zeros((1,1024))
fr=open(filename)
for i in range(32):
lineStr=fr.readline()
for j in range(32):
returnVect[0,32*i+j]=int(lineStr[j])
return returnVect
#手写识别分类器
def handwritingClassTest():
hwLabels=[]
trainingFileList=listdir('trainingDigits')
m=len(trainingFileList)
trainingMat=zeros((m,1024))
for i in range(m):
fileNameStr=trainingFileList[i]
fileStr=fileNameStr.split('.')[0]
classNumStr=int (fileStr.split('_')[0])
hwLabels.append(classNumStr)
trainingMat[i,:]=img2Vector('trainingDigits/%s'%fileNameStr)
testFileList=listdir('testDigits')
errorCount=0.0
mTest=len(testFileList)
for i in range(mTest):
fileNameStr=testFileList[i]
fileStr=fileNameStr.split('.')[0]
classNumStr=int (fileStr.split('_')[0])
vectorUnderTest = img2Vector('testDigits/%s'%fileNameStr)
classifierResult=classify0(vectorUnderTest,trainingMat,hwLabels,3)
print "the classifier came back with : %d,the real answer is : %d"%(classifierResult,classNumStr)
if(classifierResult!=classNumStr):errorCount+=1.0
print "\nthe total number of errors is : %d"%errorCount
print "\nthe total error rate is : %f "%(errorCount/float(mTest))
实战
接下来打算写个python爬虫,获取到测试用例,然后通过kNN算法来进行一些测试。
to be continued