本文不涉及k-近邻算法的原理,只通过python代码实现算法,并且没有用到机器学习库,根据算法流程一步一步实现。
代码实现
数据处理
假设我们已经获取了数据及其标签的文本文件,如下图所示。
数据有3个属性,标签分为3个类型,。python读取数据
# 读取数据并记录
def readFile(filename):
file = open(filename) # 打开文件
lines = file.readlines() # 读取每行数据
num = len(lines) # 数据的数量
X_data = np.zeros((num, 3)) # 准备存储数据特征矩阵
X_label = [] # 准备存储数据标签
index = 0
for line in lines:
line = line.strip() # 丢弃数据后的换行
list = line.split('\t') # 数据分隔
X_data[index, :] = list[0:3] # 存储数据特征
X_label.append(int(list[-1])) # 存储标签
index += 1
return X_data, X_label
读取数据之后,对特征进行归一化处理
# 特征归一化
def norm(data):
min = data.min(0) # 获取每个特征最小值
max = data.max(0) # 每个特征最大值
ranges = max - min # 每个特征极差
normData = np.zeros(np.shape(data)) # 准备存储归一化后的特征
m = data.shape[0] # 获取数据的数量
normData = data - np.tile(min, (m, 1)) # 将最小值扩展成为矩阵的形式,大小与data相同,并相减
normData = normData / np.tile(ranges, (m, 1)) # 将极差扩展成为矩阵的形式,大小与data相同,并相除
数据分类
kNN分类器
# kNN分类
def classify(X_data, X_label, y_data, k):
num = X_data.shape[0] # 训练数据的数量
y = np.tile(y_data, (num, 1)) - X_data # 测试数据扩展为训练数据大小相同的矩阵形式,并相减
y2 = y ** 2 # 计算平方
distances = (y2.sum(axis=1)) ** 0.5 # 计算距离
sortedDisIndex = distances.argsort() # 排序,并获得索引
classCount = {}
# 前k个标签
for i in range(k):
vote = X_label[sortedDisIndex[i]] # 第i个标签
classCount[vote] = classCount.get(vote, 0) + 1 # 标签数量加1
sortedClassCount = sorted(classCount.items(),
key=operator.itemgetter(1), reverse=True) # 标签数量排序
return sortedClassCount[0][0]
算法测试
选取10%的数据用于测试
# 测试
def test():
ratio = 0.10 # 0.1的数据用于测试
X_data, X_label = readFile('set.txt') # 读取数据
normData, ranges, minVals = norm(X_data) # 特征归一化
num = normData.shape[0] # 数据数量
numTest = int(num * ratio) # 测试数据数量
errorCount = 0.0
for i in range(numTest):
result = classify(normData[numTest: num, :], X_label[numTest: num], normData[i, :], 3) # 分类
print("分类结果: %d, 实际结果: %d" % (result, X_label[i]))
if (result != X_label[i]): errorCount += 1.0
print("错误率: %f" % (errorCount / float(numTest)))
print(errorCount)
最后通过运行test()
函数即可进行测试。如果有新的数据,运行classify()
函数获得分类结果。