本博客是学习《机器学习实战》例子后,自己对书上的例子代码总结的个人理解。在代码必要的地方,添加了注解。博客书写的目的是,方便后续的复习。
k-邻近算法:选择样本集中特征比较最邻近的k个点,将这K个点中出现次数最多的分类,作为新数据的分类。
k-邻近算法对异常值不敏感(采用k个数据投票的方式),并且预先不需要训练算法(输入特征向量后,全局计算距离,没有之前没有训练好的分类器)。
k-邻近算法是分类数据中最简单有效地算法。但是k-邻近算法具有存储空间和时间复杂度开销大的问题。k-邻近算法必须保存全部的数据集,如果训练的数据很大,必须花费大量的存储空间。此外,必须对数据集中每个数据计算距离数值,非常耗时。
K决策树是k-邻近算法算法的优化版,可以节省大量的资源开销。
机器学习实战中 KNN第1个例子
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#KNN book example 2.1
#learn in 2018.11.6
from numpy import *
import operator
def createDataSet():
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) #array将一个列表转换成数组,所以参数必须是列表 b=array([1,3,3])
labels=['A','A','B','B']
return group,labels
def classify0(inx,dataSet,labels,k):
# shape 输出矩阵的维度,如group是[4,2]。shape[0]输出4,为矩阵的行数,同理shape[1]输出列数。shape[2]以上报错,因为没有第三维度
dataSetSize=dataSet.shape[0]
#tile 格式函数 b = [1, 3, 5] tile(b, [2, 3]) --> array([[1, 3, 5, 1, 3, 5, 1, 3, 5], [1, 3, 5, 1, 3, 5, 1, 3, 5]])
diffMat=tile(inx,(dataSetSize,1))-dataSet
# print 'diffMat',diffMat
sqDiffMat=diffMat**2
print 'sqDiffMat',sqDiffMat
# 当axis=0,就是将一个矩阵的每一列向量相加;当axis=1,就是将一个矩阵的每一行向量相加
sqDistances=sqDiffMat.sum(axis=1)
print 'sqDistances',sqDistances
distances=sqDistances**0.5
print 'distances',distances
#argsort 从小到大排序,提取其对应的index(索引),然后输出到y
sortedDistIndicies=distances.argsort()
print 'sortedDistIndicies',sortedDistIndicies
classCount={}
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]]
#字典中,如果该key不存在,返回默认值
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
#降序排序 reverse=True
#sorted(iterable,key,reverse) iterable表示可以迭代的对象, key是一个函数,
# 用来选取参与比较的元素,reverse则是用来指定排序是倒序还是顺序,
#iteritems()返回一个迭代器
#operator模块提供的itemgetter函数用于获取对象的哪些维的数据,获取对象的第1个域的值
sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
def main():
# help(sorted)
group, labels = createDataSet()
inx=[0,0]
k=3
result=classify0(inx, group, labels, k)
print result
def MkData():
points=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels=['A','A','B','B']
return points,labels
def Classfy(curP,points,labels,k):
shape=points.shape[0]
print shape
Point=(tile(curP,[shape,1])-points)**2
print Point
Pointsum=Point.sum(axis=1)**0.5
print Pointsum
# 列表排序
Pointsort=Pointsum.argsort()
print Pointsort
votecount={}
for i in range(k):
#字典累加赋值
label=labels[Pointsort[i]]
votecount[label]=votecount.get(label,0)+1
print votecount
#字典排序
sortcount=sorted(votecount.iteritems(),key=operator.itemgetter(1),reverse=True)
print sortcount
print sortcount[0][0]
def recode():
points,labels=MkData()
curP=[0,0]
Classfy(curP,points,labels,3)
main()
recode()
机器学习实战中 KNN第2个例子 ---社交约会网站
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#KNN book example 2.2
#learn in 2018.11.6
from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt
def file2matrix(filename):
file=open(filename)
arrayOLines=file.readlines()
# print 'arrayOLines',arrayOLines
#len 函数,求出列表中一共有多少元素
numberLines=len(arrayOLines)
# print 'numberLines',numberLines
# 该函数功能是创建给定类型的矩阵,并初始化为1000行3列0矩阵
#一维数组 zeros(3)
#二维数组 zeros((2,3)) [[ ],[ ],...,[ ]]
returnMat=zeros((numberLines,3))
# print returnMat.shape[0],returnMat.shape[1]
classLabel=[]
index=0
#遍历列表的方法
for line in arrayOLines:
#去除首尾空格,去掉制表符后,返回剩下的列表
line=line.strip()
# print line
listFormLine=line.split('\t')
# print listFormLine
returnMat[index,:]=listFormLine[0:3]
#列表中添加数字,用append方法
if "largeDoses"==listFormLine[-1]:
classLabel.append(3)
elif "smallDoses"==listFormLine[-1]:
classLabel.append(2)
else:
classLabel.append(1)
index=index+1
return returnMat,classLabel
# min(0)返回该矩阵中每一列的最小值
# min(1)返回该矩阵中每一行的最小值
# max(0)返回该矩阵中每一列的最大值
# max(1)返回该矩阵中每一行的最大值
def autoNorm(dataSet):
minVals=dataSet.min(0) #返回每一列最小值,一共3列
# print 'minVals',minVals
maxVals=dataSet.max(0)
# print 'maxVals', maxVals
#列表之间可以对应直接运算的
ranges=maxVals-minVals
# print 'ranges',ranges
normData=zeros(shape(dataSet))
m=dataSet.shape[0]
#有是tile的举证格式运算
normData=dataSet-tile(minVals,(m,1))
normData=normData/tile(ranges,(m,1))
# print 'normData',normData
return normData
def classify0(inx,dataSet,labels,k):
# shape[0]输出4,为矩阵的行数,同理shape[1]输出列数,shape[2]以上报错
dataSetSize=dataSet.shape[0]
diffMat=tile(inx,(dataSetSize,1))-dataSet
# print diffMat
# 矩阵和列表,都可以直接运算的
sqDiffMat=diffMat**2
# print sqDiffMat
sqDistances=sqDiffMat.sum(axis=1)
# print sqDistances
distances=sqDistances**0.5
# print distances
sortedDistIndicies=distances.argsort()
# print sortedDistIndicies
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]
def main():
filename="datingTestSet.txt"
returnMat, classLabel=file2matrix(filename)
# 可视化数据分布
fig=plt.figure()#自定义画布
ax=fig.add_subplot(111) #参数349的意思是:将画布分割成3行4列,图像画在从左到右从上到下的第9块 ax是具体一个局域
ax.scatter(returnMat[:,0],returnMat[:,1],8.0*array(classLabel),8.0*array(classLabel)) #scatter散点图
plt.show()
ax.scatter(returnMat[:, 1], returnMat[:, 2])
plt.show()
normData = autoNorm(returnMat)
testCele=0.1
m=normData.shape[0]
testPart=int(m*testCele)
errorTime=0.0
k=3
for i in range(testPart): #现在操作对象都是矩阵
result=classify0(normData[i,:],normData[testPart:m,:],classLabel[testPart:m],3)
if result!=classLabel[i]:
errorTime=errorTime+1
print "the classifyresult is", result, " the real result is ", classLabel[i]
print errorTime/float(testPart)
main()
机器学习实战中 KNN第3个例子 ---识别手写数字
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from numpy import *
import operator
from os import listdir
from knn import *
# 可以读取文件的名字
#KNN book example three(learn digits) 2.3
#learn in 2018.11.6
def img2vec(filename):
result=zeros((1,1024)) #变成一个矩阵向量
file=open(filename)
for i in range(32):
line=file.readline()
for j in range(32):
result[0,i*32+j]=int(line[j])
return result
def handwritingClassTest():
lables=[]
fileList=listdir('trainingDigits')
print 'fileList',fileList
m=len(fileList)
print m
trainMat=zeros((m,1024))
for i in range(m):
file=fileList[i]
num=int(file.split('.')[0].split('_')[0])
lables.append(num)
trainMat[i,:]=img2vec('trainingDigits/%s' %file) #遍历赋值文件名
TestfileList = listdir('Digits')
errotime=0
Testm = len(TestfileList)
for i in range(Testm):
filename=TestfileList[i]
testnum = int(filename.split('.')[0].split('_')[0])
testVec=img2vec('trainingDigits/%s' %filename)
result=classifyResult=classify0(testVec,trainMat,lables,3)
if result!=testnum:
errotime+=1
print "the right num is ",testnum,", but the classify is ",result
print "error is ",errotime
print errotime / float(Testm)
def main():
handwritingClassTest()
main()
# print img2vec("digits/Digits/0_0.txt")