KNN算法的代码实现

时间:2023-03-09 18:46:41
KNN算法的代码实现

# -*- coding: utf-8 -*-
"""
Created on Wed Mar 7 09:17:17 2018


@author: admin
"""


#######################################################
#kNN cluster
#author:niucas
#date:2-18-03-07
#homePage:http://www.cnblogs.com/PiPifamily/
#email:maowankui@163.com
#命名规则采用驼峰命名
#######################################################
#导入对应的包
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import operator


############
#准备数据
############
def creatDataSet():
'''
函数的作用是创建一个训练数据集,并且对应各个数据的label(标签)
'''
testData = np.array([
[1.0,1.1],
[1.0,1.1],
[0.,0.],
[0.,0.1]
])
testLabel = ['A','A','B','B']
return testData,testLabel
def classify(inData,dataSet,labels,k):
'''
此函数是用来进行分类;
参数定义如下:
inData:输入数据
dataSet:训练数据集
labels:训练数据对应的labels
k:选取的K值
'''
dataSetSize = dataSet.shape[0]
#第一步计算欧式距离
diff = np.tile(inData,(dataSetSize,1)) - dataSet #训练数据集每个对象与测试数据的差值
distance = ((diff**2).sum(axis=1)) ** 0.5#求差值的平方和
#############
#开始进行投票
#############
sortedDistIndex = np.argsort(distance) #将欧式距离进行升序排列,结果对应的是索引号
#存放最终结果的字典,初始化
classCount = {}
#投票就是计算前K个值中,概率的最大的类,哪个labels值最大
for i in range(k):
voteLabel = labels[sortedDistIndex[i]]
#print(voteLabel)
classCount[voteLabel] = classCount.get(voteLabel,0) + 1

#将classCount中的分类结果进行排序,返回得票数最高的label
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1), reverse = True)#降序排列,默认是升序排列

# class = max(classCount.items(),Key = lambda x : x[1])[0]

return sortedClassCount[0][0]


if __name__ == "__main__":
#导入数据
dataSet,labels = creatDataSet()
inData = [0.1,0.1]
#简单分类
className = classify(inData,dataSet,labels,3)
print('the class of test sample is %s' % className)


#从文件中读取数据
def readFile(filepath):
'''
从文件中读取数据,并存储为矩阵形式
'''
#path = "E:\\1\ML\ML Data\machinelearninginaction\Ch02\datingTestSet.txt"
file = open(filepath)
dataSetLine = len(file.readlines()) #获取样本的行数
newDataMat = np.zeros((dataSetLine,3)) #初始化一个矩阵存放训练数据
newDataLabel = [] #创建一个list存放标签
index = 0

for line in file.readlines():
line = line.strip().split('\t')
#把分割好的数据放入数据集中,index是样本的下标
newDataMat[index,:] = line[0:3]
#把样本中的标签放到数据集中
newDataLabel = newDataLabel.append(int(line[-1]))
index += 1
return newDataMat,newDataLabel


#filepath = "E:\\1\ML\ML Data\machinelearninginaction\Ch02\datingTestSet.txt"
#Mat,Label = readFile(filepath)


def autoNormal(dataSet):
'''
数据集归一化处理
归一化是因为数据集中的‘每个月飞行里程数远大于其他的特征参数’,通过归一化
处理后可以将不同的特征数值转化为0-1之间的数值
'''
#step01:获取每一列的最小值和最大值
minValue = dataSet.min(0)
maxValue = dataSet.max(0)
#step02:最大值与最小值之间做差
diffValue = maxValue -minValue
#step03:新建一个等shape的矩阵,存放归一化后的数据
normalDataMat = np.zeros(dataSet.shape)
#step04:计算归一化后的矩阵
m = dataSet.shape[0]
normalDataMat = dataSet - np.tile(minValue,(m,1))
normalDataMat = normalDataMat/(np.tile(diffValue,(m,1)))

return normalDataMat,diffValue,minValue


def classTest():
'''
将原始数据的10%用作测试数据,其余90%用作训练数据
'''
testRatio = 0.10 #测试数据集比例10%
#导入数据归一化处理
path = "E:\\1\ML\ML Data\machinelearninginaction\Ch02\datingTestSet.txt"
testDataMat,testDataLabel = readFile(path)
norData,diffVal,minVal = autoNormal(testDataMat)
#确定测试集数目
m = norData.shape[0]#数据集的行数,代表数据大小
numTestDataset = int(m*testRatio)#测试数据集大小
#错误率
errorRatio = 0.0
#
print(norData)
#
for i in range(numTestDataset):
classifyResult = classify(norData[i,:],norData[numTestDataset:m,:],testDataLabel[numTestDataset,m],3)
print("分类器返回值:%d,真实的结果应该是:%d" % (classifyResult,testDataLabel[i]))
if (classifyResult != testDataLabel[i]):
errorRatio += 1.0
print(errorRatio)

classTest()