理论
K-近邻算法是一种基于计算向量距离的方法来判断的算法,具体描述见书,下面把我这次学习到的python语法及代码贴下来
语法
1.shape()查看矩阵或者数组的维数,shape[1] 为第一维的长度,c.shape[0] 为第二维的长度
2.tile(orginal, (a,b))将原来的矩阵行复制b倍,列复制a倍
- **是乘方的意思
- get() 函数返回指定键的值,如果值不在字典中返回默认值。dict.get(key, default=None)
5.sorted()方法升序排列,key参数的值为一个函数,此函数只有一个参数且返回一个值用来进行比较。这个技术是快速的因为key指定的函数将准确地对每个元素调用。
6.Operator 模块函数有itemgetter,attrgetter用复杂对象的某些值来对复杂对象的序列排序,参数reverse(True or False)来表示升序或降序排序
7.Python 字典(Dictionary) items()方法用于返回字典dict的(key,value)元组对的列表
8.zeros(x,y)构建x*y维值为0的矩阵
9.Python strip() 方法用于移除字符串头尾指定的字符(默认为空格)。
10.Python split()通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串 str.split(str="", num=string.count(str)).
11.classLabelVector.append(int(listFromLine[-1])) # 把该样本对应的标签放至标签集,顺序与样本集对应。 python语言中可以使用-1表示列表中的最后一列元素
12.figure()返回一个Figure对象
13.add_subplot返回一个Axes对象,参数111表示画布分割为1行1列,图像画在第一块
14.ax.scatter(datingDataMat[:,1], datingDataMat[:,2])#散点图使用datingDataMat矩阵的第二、第三列数据
15.list[start:end(not include):step] list索引的起始位,结束位,步长
16.其中dataSet.min(0)中的参数0使得函数可以从列中选取最小值,而不是选取当前行的最小值。
17.a = np.array([[1,5,3],[4,2,6]])
print(a.min()) #无参,所有中的最小值
print(a.min(0)) # axis=0; 每列的最小值
print(a.min(1)) # axis=1;每行的最小值
结果:
1
[1 2 3]
[1 2]
18.对于ndarray的切片,格式为[x1:x2, y1:y2],截取行数为[x1,x2),列数为[y1,y2)。左边闭空间,右边开空间。 如果要截取某一行,格式为[x,:],截取某一列:[:,y] 其他截取以此类推
19.readline()是不是调用一次下一次调用就会自动读取下一行,readlines是读取全部形成一个list
20.listdir可 以 列 出 给 定 目 录 的 文 件 名 。
- 语法:str.split(str="", num=string.count(str))[n]
参数说明:
str: 表示为分隔符,默认为空格,但是不能为空('')。若字符串中没有分隔符,则把整个字符串作为列表的一个元素
num:表示分割次数。如果存在参数num,则仅分隔成
num + 1
个子字符串,并且每一个子字符串可以赋给新的变量
[n]: 表示选取第n个分片
注意:当使用空格作为分隔符时,对于中间为空的项会自动忽略
输入
trainingDigits
testDigits
是将图像以数字0和1矩阵储存的文本文件
代码
from numpy import *
import operator
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from os import listdir
def createDataSet():
# array =
# # tuple(array)
group = np.array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
# tuple(array)
labels = ['A', 'A', 'B', 'B']
return group, labels
def classify0(intX, dataSet, labels, k): #返回前K个可能性的类别
dataSetSize = dataSet.shape[0]
#shape()查看矩阵或者数组的维数,shape[1] 为第一维的长度,c.shape[0] 为第二维的长度
diffMat = tile(intX, (dataSetSize, 1)) - dataSet
#tile(orginal, (a,b))将原来的矩阵行复制b倍,列复制a倍
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
# get() 函数返回指定键的值,如果值不在字典中返回默认值。dict.get(key, default=None)
sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True)
#sorted()方法升序排列,key参数的值为一个函数,此函数只有一个参数且返回一个值用来进行比较。这个技术是快速的因为key指定的函数将准确地对每个元素调用。
#Operator 模块函数有itemgetter,attrgetter用复杂对象的某些值来对复杂对象的序列排序,参数reverse(True or False)来表示升序或降序排序
#Python 字典(Dictionary) items()方法用于返回字典dict的(key,value)元组对的列表
return sortedClassCount[0][0]
def file2matrix(filename): # 从文件中读入训练数据,并存储为矩阵
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat = zeros((numberOfLines, 3))
#zeros(x,y)构建x*y维值为0的矩阵
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip()
#Python strip() 方法用于移除字符串头尾指定的字符(默认为空格)。
listFromLine = line.split('\t')
#Python split()通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串 str.split(str="", num=string.count(str)).
returnMat[index, :] = listFromLine[0:3]# 把分割好的数据放至数据集,其中index是该样本数据的下标,就是放到第几行
# labels = {'didntLike': 1, 'smallDoses': 2, 'largeDoses': 3}
classLabelVector.append(int(listFromLine[-1])) # 把该样本对应的标签放至标签集,顺序与样本集对应。 python语言中可以使用-1表示列表中的最后一列元素
index += 1
return returnMat, classLabelVector
#datingDataMat,datingLabels = file2matrix('C:/Users/LRT/PycharmProjects/M_learn/datingTestSet.txt')
# print(datingDataMat,datingLabels)
def matpt():#画散点图
fig = plt.figure()#figure()返回一个Figure对象
ax = fig.add_subplot(111)#add_subplot返回一个Axes对象,参数111表示画布分割为1行1列,图像画在第一块
#ax.scatter(datingDataMat[:,1], datingDataMat[:,2])#散点图使用datingDataMat矩阵的第二、第三列数据
#list[start:end(not include):step] list索引的起始位,结束位,步长
ax.scatter(datingDataMat[:,1], datingDataMat[:,0], 15.0*array(datingLabels), 15.0*array(datingLabels))#利用变量datingLabels存储的类标签属性,在散点图上绘制了色彩不等、尺寸不同的点
plt.show()
def autoNorm(dataSet): #归一化特征值
minVals = dataSet.min(0)#其中dataSet.min(0)中的参数0使得函数可以从列中选取最小值,而不是选取当前行的最小值。
# a = np.array([[1,5,3],[4,2,6]])
# print(a.min()) #无参,所有中的最小值
# print(a.min(0)) # axis=0; 每列的最小值
# print(a.min(1)) # axis=1;每行的最小值
# 结果:
# 1
# [1 2 3]
# [1 2]
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
# normMat, ranges, minVals = autoNorm(datingDataMat)
# print(normMat, ranges, minVals)
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) #normMat前numTestVecs数量的列作为测试集,后numTestVecs数量的列为训练集
# 对于ndarray的切片,格式为[x1:x2, y1:y2],截取行数为[x1,x2),列数为[y1,y2)。左边闭空间,右边开空间。
# 如果要截取某一行,格式为[x,:],截取某一列:[:,y]
# 其他截取以此类推
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)
# datingClassTest()
def classifyPerson(): #预测约会对象喜欢程度函数
resultList = ['not at all', 'in small doses', 'in large doses']
percenTags = float( input("percentage of time spent playing video game?"))
ffMiles = float(input("frequent filer miles earned per year?"))
iceCream = float(input("liters of ice cream consumed per years?"))
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
inArr = array([ffMiles, percenTags, iceCream])
#numpy中封装的array有很强大的功能,里面存放的都是相同的数据类型
classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels, 3)
print("you will probably like this person", resultList[classifierResult - 1])
# classifyPerson()
def img2vector(filename): #将图像转化为向量
returnVect = zeros((1, 1024))
fr = open(filename)
for i in range(32):
lineStr = fr.readline()#readline()是不是调用一次下一次调用就会自动读取下一行,readlines是读取全部形成一个list
for j in range(32):
returnVect[0, 32 * i + j] = int(lineStr[j])
return returnVect
# testVector = img2vector('testDigits/0_13.txt')
# print(testVector[0, 0:31])
def handwritingClassTest():
hwLabels = []
trainingFileList = listdir('trainingDigits') #load the training set listdir可 以 列 出 给 定 目 录 的 文 件 名 。
m = len(trainingFileList)
trainingMat = zeros((m,1024))
for i in range(m):
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0] #take off .txt
classNumStr = int(fileStr.split('_')[0])
# 语法:str.split(str="", num=string.count(str))[n]
# 参数说明:
# str: 表示为分隔符,默认为空格,但是不能为空('')。若字符串中没有分隔符,则把整个字符串作为列表的一个元素
# num:表示分割次数。如果存在参数num,则仅分隔成
# num + 1
# 个子字符串,并且每一个子字符串可以赋给新的变量
# [n]: 表示选取第n个分片
# 注意:当使用空格作为分隔符时,对于中间为空的项会自动忽略
hwLabels.append(classNumStr)
trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)
testFileList = listdir('testDigits') #iterate through the test set
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
fileNameStr = testFileList[i]
fileStr = fileNameStr.split('.')[0] #take off .txt
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)))
handwritingClassTest()