KNN 算法主要是根据计算输入数据的距离进行分类通常使用欧氏距离来进行计算
from numpy import *
import matplotlib
import matplotlib. pyplot as plt
# 数据准备
def creatDataSet():
group=array([[1.0,1.1 ] , [1.0,1.0], [0,0 ], [0,0.1]])
lables=['A','A','B','B']
return group,lables
# group,lables=creatDataSet() 测试数据
KNN分类算法
函 数 有 4 个 输 人 参 数 : 需要进行 分 类 的 输 人 向 量 ,输 人 的 训练 样 本 集 为
标 签 向 量 为 libles, 最 后 的 参 数 义 表 示 用 于 选 择 最 近 邻 居 的 数 目 , 其 中 标 签 向 量 的 元 素 数 目 和 矩
阵 dataset的 行 数 相 同
def clasify(intx,dataSet,lables,k):
计算距离 k为选 取 与 当 前 点距 离 最 小 的 点
dataSetSize=dataSet.shape[0] #读取矩阵第一维度的长度
difMat=tile(intx,(dataSetSize,1))-dataSet #已知数据和输入数据相减
sqdifmat=difMat**2 #相减数据的结果平方 采用欧式距离公式计算
sqdistance=sqdifmat.sum(axis=1) #将一个矩阵的每一行向量相加
distance=sqdistance**0.5#对结果开二次更号
sortDist=distance.argsort() #对结果进行排序
classCount={}
for i in range(k):
votelabel=lables[sortDist[i]] # 选取出相邻的k个数
classCount[votelabel]=classCount.get(votelabel,0)+1
sortClassCount= sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) #排序
return sortClassCount[0][0] # 取出数据
# a=clasify([0,0],group,lables,3)
# print a 测试
下面的算法是根据KNN 算法来进行约会网站的配对效果:
根据样本特征对人群进行分类
特征包括:每 年 获 得 的 飞行 常 客里 程 数 ,玩 视 频 游 戏 所 耗 时 间 百 分 比, 每 周 消 费 的 冰 淇 淋 公 升 数
标签包括:不 喜 欢 的 人,魅 力 一 般 的 人 ,极具 魅 力 的 人
首先是对输入样本进行解析
# 文件读取
def filematrix(filename):
fr = open(filename)# 读取文本
numberOfLines = len(fr.readlines()) #获取文件的长度
returnMat = zeros((numberOfLines,3)) #创建返回的numpy矩阵 所有元素都是0的矩阵
classLabelVector = [] #创建标签矩阵
fr = open(filename)# 读取文本
index = 0
for line in fr.readlines():
line = line.strip()#截取回车字符
listFromLine = line.split('\t') #对数据进行分割
returnMat[index,:] = listFromLine[0:3]#取前三个数据 放入返回的列表中
classLabelVector.append((listFromLine[-1]))#取最后一个数据 ,放入标签列表中
index+=1
return returnMat,classLabelVector
# datingDataMat,datingLabels = filematrix('datingTestSet.txt') 测试数据集是否正确分类,具体数据可在网上下载
使用matplotlib 创建散点图,可视化数据
fig =plt.figure()
ax=fig.add_subplot(111)
# ax.scatter(datingDataMat[:,1],datingDataMat[:,2]) #散点图截取举证的 第二,第三列数据
# plt.show()
由于数据中很多数字差值过大,对计算结果产生影响,对数值进行归一化处理 在机器学习中很多数据都需要进行数据归一化处理。当然也可以利用python第三方库进行数据的特征提取和处理。 例如分类变量的特征提取。通过sklearn的Dictvertiruzer 类来提取特征 以及通过词库模式对文字特征进行提取。 对于图片可以通过像素值提取特征
下面函数自动把数值特征值转化为0,1之间
def autoNorm(dataSet):
minVals = dataSet.min(0) #去列中的最小值
maxVals = dataSet.max(0)#取最大值
ranges = maxVals - minVals #取范围,范围是最大值-最小值
normDataSet = zeros(shape(dataSet)) #创建全为0的返回矩阵
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 测试数据
下面的函数#是一个测 试 算 法 : 作 为 完 整 程 序 验 证 分 类 判断分类器的正确率如何
def dateTest():
hoRatio = 0.50
datingDataMat,datingLabels = filematrix('datingTestSet.txt') #读取数据
normMat, ranges, minVals = autoNorm(datingDataMat) #归一化数据值
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = clasify(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3) #对数据进行分类 , 3 选 择 最 近 邻 数据的 数 目
print u"分类结果是: %s, 真的结果是: %s" % (classifierResult, datingLabels[i])
if (classifierResult != datingLabels[i]): errorCount += 1.0
print u"总共的错误率: %f" % (errorCount/float(numTestVecs))
print u"错误数量%d"%errorCount
# dateTest()
下面是对单个用户进行预测 使用的python版本是2.7
def classifyPerson():
percntTats =float(raw_input(u"每年玩游戏的比例"))
ffmiles=float(raw_input(u"每年飞机里程数 "))
iceCream =float(raw_input(u"每年冰淇淋的消耗?"))
datingDataMat,datingLabels = filematrix('datingTestSet.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
inarr=array([percntTats,ffmiles,iceCream])
result=clasify((inarr-minVals)/ranges,normMat,datingLabels,3)
print result
# classifyPerson()
下面的函数是实现使用k 邻近的手写识别系统
该系统只能是识别数字 0 到9 ,其中train文件中包括2000个例子 ,test文件中大约900个测试数据
将图像转为测试向量
该 函 数 创 建 1乘1024 的 numpy 数
组 , 然 后 打 开 给 定 的 文 件 , 循 环 读 出 文 件 的 前 32 行 , 并 将 每 行 的 头 32 个 字 符 值 存 储 在 数 组
中 , 最 后 返回 数 组
def chageimage(filename):
Vect = zeros((1,1024)) # 创建一个1x1024的数组
fr= open(filename)
for i in range(32):
line=fr.readline()
for j in range(32):
Vect[0,32*i+j] = int(line[j])
return Vect
# a= chageimage('testDigits/0_13.txt')
# print a[0,32:63] 测试
下面函数是书写数字识别系统测试
from os import listdir
def HWClassTest():
hwlibes=[]
trainFile= listdir('trainingDigits')# 列出给定目录的文件名
m = len(trainFile)#获取文件列表的长度
trainingMat=zeros((m,1024)) # 创建数组
for i in range(m):
fileName=trainFile[i] # 获取训练文件
filestr= fileName.split('.')[0]
classNum = int(filestr.split('_')[0]) # 从文件名解析分类数字
hwlibes.append(classNum)
trainingMat[i,:] = chageimage('trainingDigits/%s' % fileName)
testFile= listdir('testDigits')
errorcount = 0.0
mTest = len(testFile)
for i in range(mTest):
fileNameStr = testFile[i]
fileStr = fileNameStr.split('.')[0]
classNumStr = int(fileStr.split('_')[0])
vectorUnderTest = chageimage('testDigits/%s' % fileNameStr)
classifierResult = clasify(vectorUnderTest, trainingMat, hwlibes, 3)
print u"分类结果是: %s, 真的结果是: %s" % (classifierResult, classNumStr)
if (classifierResult != classNumStr): errorcount += 1.0
print u"总共的错误率: %f" % (errorcount/float(mTest))
print u"错误数量%d"%errorcount
# HWClassTest()
改 变 变 量 k 的 值 、修 改 函 数随机选取训练原本、 改 变 训练 样 本 的 数 目 , 都 会 对 K- 近 邻 算 法 的 错 误 率 产 生 影响
而在K 近邻算法的实现中KD 树和KD树搜索是K 近邻算法的优化版,可以节省计算开销
K近邻算法必须保存全部的数据集,如果训练数据集过大,必须使用大量的存储空间
由于需要对数据集中的每个数据计算距离值,实际使用实际是比较耗时的
对于大规模数据的分类一般是不推荐使用KNN的