引用:www.cnblogs.com/xiaofeng-bl… 算法简介: 其工作原理是:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中的每一数据与所属分类的对应关系。
输入没有标签的新数据后,将新数据的每个特征与样本集中对应的数据对应的特征进行比较,然后算法提取出样本集中特征最相似数据(最近邻)的分类标签。(一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。)
最后,我们选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
代码实现
#!/usr/bin/python
#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import numpy as np
import pandas as pd
from sklearn import preprocessing
import operator
#获取并加工源数据
def createDataSet():
#sheet_name也是指索引,从0开始
offline_ml_data=pd.read_excel(r"/Users/fabrice/python-test/test_juzhen.xlsx" ,sheet_name=0)
data_cols =offline_ml_data.columns.tolist()
#对分类变量做one_hot转换
one_hot_col=[u'城市']
offline_ml_data=offline_ml_data.join(pd.get_dummies(offline_ml_data.loc[:,one_hot_col]))
#做了one-hot转换后需要删除掉原始的分类变量,以免影响接下来的计算
del offline_ml_data[u'城市']
print(offline_ml_data)
#数据标准化,消除量纲的影响
scaler = preprocessing.StandardScaler().fit(offline_ml_data)
#得到每列的平均值,是一维数组
mean = scaler.mean_
print("mean:",mean)
#得到每列的标准差,是一维数组
std = scaler.var_
print("std:",std)
#直接标准化数据,转换之后,是一个二维数组
data_nomal = scaler.transform(offline_ml_data)
#如果没有经过转换,需要手动把dataFrame转换成二维数组
#offline_ml_data_arr=offline_ml_data.values
return data_nomal,mean,std
# inX: 分类的输入向量
# dataSet: 输入的训练样本集
# labels: 标签向量
# k: 选择最近邻居的数目
def classify0(inX, dataSet, labels, k):
# 1.计算距离,这里采用的是欧式距离
dataSetSize = dataSet.shape[0] # 获取数据集大小,也就是有多少条数据
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet # 将待测试数据扩展
sqDiffMat = diffMat ** 2 # 差值矩阵中,矩阵元素分别平方
sqDistances = sqDiffMat.sum(axis = 1) # 横向求和,得到矩阵
distances = sqDistances ** 0.5 # 矩阵中,每个元素都开方
print("distances:",distances)
sortedDistIndicies = distances.argsort() # 距离排序
print("sortedDistIndicies",sortedDistIndicies)
# 2.选择距离最小的k个点
classCount = {}
for i in range(k):
print('i:',i)
voteIlabel = labels[sortedDistIndicies[i]]
print('voteIlabel:',voteIlabel)
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
print("classCount:",classCount)
# 3.排序,选择label出现频率最高的那个
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
#测试代码是否正确执行
predictData,mean,std=createDataSet()
#在createDataSet里对训练集和验证集做同样的标准化
#训练集和验证集划分
##对预测集做和验证集相同的标准化
#假设待验证的数据是m*n,首先把均值和标准差列表转换成m*n矩阵
mean2=np.tile(mean,(m,1))
std2=np.tile(std,(m,1))
#对预测集做矩阵减法,标准化数据
predictData=(predictData-mean2)/std2
labels=['A','A','B']
bb=classify0(inX,aa,labels,1)
print(bb)