1、相亲案例
import numpy as np
import operator
#matplotata 测试数据集的某行, dataSet 训练数据集 ,labels 训练数据集的类别,k k的值
def classify(normData,dataSet,labels,k):
dataSetSize = dataSet.shape[0]
# print 'dataSetSize 长度 =',dataSetSize
#当前点到所有点的坐标差值
diffMat = np.tile(normData, (dataSetSize,1)) - dataSet
#对每个坐标差值平方
sqDiffMat = diffMat ** 2
#对于二维数组 sqDiffMat.sum(axis=0)指定对数组b对每列求和,sqDiffMat.sum(axis=1)是对每行求和
sqDistances = sqDiffMat.sum(axis = 1)
#欧式距离 最后开方
distance = sqDistances ** 0.5
#argsort() 将x中的元素从小到大排序,提取其对应的index 索引,返回数组
sortedDistIndicies = distance.argsort()
# classCount保存的K是魅力类型 V:在K个近邻中某一个类型的次数
classCount = {}
for i in range(k):
#获取对应的下标的类别
voteLabel = labels[sortedDistIndicies[i]]
#给相同的类别次数计数
classCount[voteLabel] = classCount.get(voteLabel,0) + 1
sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
def file2matrix(filename):
fr = open(filename)
# readlines:是一次性将这个文本的内容全部加载到内存中(列表)
arrayOflines = fr.readlines()
numOfLines = len(arrayOflines)
# print "numOfLines = " , numOfLines
#numpy.zeros 创建给定类型的矩阵 numOfLines 行 ,3列
returnMat = np.zeros((numOfLines,3))
classLabelVector = []
index = 0
for line in arrayOflines:
#去掉一行的头尾空格
line = line.strip()
listFromline = line.split('\t')
returnMat[index,:] = listFromline[0:3]
classLabelVector.append(int(listFromline[-1]))
index += 1
return returnMat,classLabelVector
'''
将训练集中的数据进行归一化
归一化的目的:
训练集中飞行公里数这一维度中的值是非常大,那么这个纬度值对于最终的计算结果(两点的距离)影响是非常大,
远远超过其他的两个维度对于最终结果的影响
实际约会姑娘认为这三个特征是同等重要的
下面使用最大最小值归一化的方式将训练集中的数据进行归一化
'''
#将数据归一化
def autoNorm(dataSet):
# dataSet.min(0) 代表的是统计这个矩阵中每一列的最小值 返回值是一个矩阵1*3矩阵
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
#dataSet.shape[0] 计算行数, shape[1] 计算列数
m = dataSet.shape[0]1列
normDataSet = dataSet - np.tile(minVals,(m,1))
normDataSet = normDataSet / np.tile(ranges,(m,1))
return normDataSet,ranges,minVals
def datingClassTest():
hoRatio = 0.1
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
#将数据归一化
normMat,ranges,minVals = autoNorm(datingDataMat)
# m 为行数 = 1000
m = normMat.shape[0]
# print 'm =%d 行'%m
#取出100行数据测试
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
#normMat[i,:] 取出数据的第i行,normMat[numTestVecs:m,:]取出数据中的100行到1000行 作为训练集,datingLabels[numTestVecs:m] 取出数据中100行到1000行的类别,4是K
classifierResult = classify(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],4)
print '模型预测值: %d ,真实值 : %d' %(classifierResult,datingLabels[i])
if (classifierResult != datingLabels[i]):
errorCount += 1.0
errorRate = errorCount / float(numTestVecs)
print '正确率 : %f' %(1-errorRate)
return 1-errorRate
def classifyperson():
resultList = ['没感觉', '看起来还行','极具魅力']
input_man= [30000,3,0.1]
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
normMat,ranges,minVals = autoNorm(datingDataMat)
result = classify((input_man - minVals)/ranges,normMat,datingLabels,3)
print '你即将约会的人是:' , resultList[result-1]
if __name__ == '__main__':
acc = datingClassTest()
if(acc > 0.9):
classifyperson()
调用python 中 Scikit-learn 实现KNN算法:
from sklearn.neighbors import NearestNeighbors
import numpy as np
from KNNDateOnHand import *
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
normMat,ranges,minVals = autoNorm(datingDataMat)
t作为训练集拟合模型
nbrs = NearestNeighbors(n_neighbors=3).fit(normMat)
input_man= [30000,3,2]
#数据归一化
S = (input_man - minVals)/ranges
#找到当前点的K个临近点,也就是找到临近的3个点
distances, indices = nbrs.kneighbors(S)
print indices
print distances
# classCount K:类别名 V:这个类别中的样本出现的次数
classCount = {}
for i in range(3):应的索引的类别号
voteLabel = datingLabels[indices[0][i]]
classCount[voteLabel] = classCount.get(voteLabel,0) + 1
sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
resultList = ['没感觉', '看起来还行','极具魅力']
print resultList[sortedClassCount[0][0]-1]
2、KNN文本分类案例
import os
import numpy as np
from KNNDateOnHand import classify
方法将每个文件中32*32的矩阵数据,转换到1*1024一行中
def img2vector(filename):
#创建一个1行1024列的矩阵
returnVect = np.zeros((1,1024))
#打开当前的文件
fr = open(filename)
#每个文件中有32行,每行有32列数据,遍历32个行,将32个列数据放入1024的列中
for i in range(32):
lineStr = fr.readline()
for j in range(32):
returnVect[0,32*i+j] = int(lineStr[j])
return returnVect
def IdentifImgClassTest():
hwLabels = []
#读取训练街 TrainData目录下所有的文件和文件夹
trainingFileList = os.listdir('TrainData')
m = len(trainingFileList)
#zeros((m,1024)) 返回一个m行 ,1024列的矩阵,默认是浮点型的
trainingMat = np.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('TrainData/%s' % fileNameStr)
#读取测试集数据
testFileList = os.listdir('TestData')
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('TestData/%s' % fileNameStr)
classifierResult = classify(vectorUnderTest, trainingMat, hwLabels, 3)
print "识别出的数字是: %d, 真实数字是: %d" % (classifierResult, classNumStr)
if (classifierResult != classNumStr):
errorCount += 1.0
print "\n识别错误次数 %d" % errorCount
errorRate = errorCount/float(mTest)
print "\n正确率: %f" % (1-errorRate)
if __name__ == '__main__':
IdentifImgClassTest()