这里采用了IRIS数据进行了类别判断处理,如下为源代码,供参考。
说明几点:
1.在getdata函数中对样本数据进行了归一化处理,采用的是传统的标准化方法(Xnorm=(X-Xmin)/(Xmax-Xmin))。
2.在knn函数中用到了np.tile函数,这个tile函数可以用于对现有数据在行或者列方向复制操作,tile(data, (rowsnum,colsnum)),就是将data数据沿着行方向复制num个,沿着列方向复制num个,例如tile(data, (5,5))就是将data数据转换为五行五列的矩阵数据,如果data为[1],那复制操作后变成了
[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]]
3. 在knn函数中使用了argsort方法,这个要好好理解,采用这个方法是对原来行所在的标签号进行排序。
# -*- coding: utf-8 -*-
"""Created on Sat Nov 25 11:19:52 2017
@author: 曹鉴华
"""
import pandas as pd
import numpy as np
def getdata(path):
data = pd.read_csv(path) #读取数据集
character = data.iloc[:,0 :4] #用iloc方法选取第1列到第4列为样本特征集
label = data.iloc[0:130, 4] #用iloc方法选取第5列为花的类别
chara_max = character.max() #获取各列属性的最大值
chara_min = character.min() #获取各列属性的最小值
chara_range = chara_max - chara_min #获得各列属性的最大值与最小值
chara = (character - chara_min) / chara_range #对各列属性数据进行归一化处理
x_train=chara.iloc[0:130,0:4] #取得前130行数据作为已知样本数据
x_test=chara.iloc[148:149,0:4] #选取第149行数据作为测试样本
label=data.iloc[0:130,4] #取得前130行数据作为目标类别数据
return x_train,x_test,label # 获得归一化特征值和标记
#knn函数获得预测的分类
def knn(x_test, x_train, label, k):
datasize=x_train.shape[0] #获得样本数据的数量, 本例数据里结果为130行
data_sub = x_train - np.tile(x_test,(datasize,1)) #计算测试数据与已知样本之间的距离,采用tile函数复制与样本数量一致大小的矩阵,#例如本例中训练数据为130行4列(130x4)矩阵,要计算测试数据与训练数据之间的距离,由于测试数据就一行,要使得矩阵能相减,就先构造一个与训练数据样本数量一致的测试数据矩阵,形成130x1大小的矩阵。
dismat=data_sub**2 #对测试样本与已知样本的距离进行平方计算,注意这里data_sub是一个130x4大小的矩阵
dissum=dismat.sum(axis=1) #沿着行方向对测试点与已知点之间的距离计算距离平方和。
distance=dissum**0.5 #对距离求均方根,获得测试样本与已知样本之间的欧式距离
dis_sort = distance.argsort() #对获得的欧式距离进行标签排序
num=dis_sort[0:k] #选择前k个标签号
k_label=label[num] #获得这k个标签号所对应的类别
countlabel=k_label.value_counts() #对着k个标签号的类别进行个数统计
res_label=countlabel.index[0] #获得个数最多出现频率最高的那个类别,也即是测试样本的类别
return k_label,res_label # knn算法分类
path='iris.data' #给定iris数据集的位置,这里就是将iris.data放在与此py文件同一目录下
k=5 #设定KNN算法里的k值
x_train,x_test,label=getdata(path) #调用getdata函数获得已知样本数据、测试样本、类别数据
k_label,res_label=knn(x_test,x_train,label,k) #调用knn函数求得测试样本的类别
print k_label,res_label #显示具体类别号