一、概念
K-近邻算法(KNN)是一种基本的机器学习分类和回归方法。它的核心思想是:如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别。
二、KNN算法的流程
(1)数据准备:准备训练集和测试集,并对数据进行预处理,如特征缩放、缺失值处理等。
归一化数值:用于处理不同取值范围的特征值
newValue = (oldValuye-min)/(max-min)
(2)计算距离:对于测试集中的每个样本,计算它与训练集中每个样本的距离。
①曼哈顿距离
②欧几里得距离
(3)选择邻居:根据计算出的距离,选择距离测试样本最近的k个训练样本作为邻居。
(4)投票分类:根据这k个邻居的类别进行投票,将测试样本归为票数最多的那一类。
三、实例
训练集:
def createDataSet():
# 身高和体重特征,以及对应的性别标签('男'或'女')
group = np.array([[160, 56], [160, 50], [168, 60], [165, 57], [180, 69], [176, 61], [176, 65], [170, 55],
[173, 65], [167, 52],[165, 57],[177,64]])
# 性别标签,0代表'男',1代表'女'
labels = [0, 1, 0, 1, 0, 1, 0, 1,0,1,0,1 ]
return group, labels
欧几里得法计算距离:
#距离计算
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
distances = sqDiffMat.sum(axis=1) ** 0.5
KNN算法:
#选择距离最小的k个点
for i in range(k):
voteIlabel = labels[sortedDistIndices[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# 排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
测试与结果:
test = [178, 70]
# 使用kNN分类(假设k=3)
predicted_gender_label = classify0(test, group, labels, 3)
# 将数字标签转换回性别字符串(假设0代表'男',1代表'女')
predicted_gender = '男' if predicted_gender_label == 0 else '女'
# 打印分类结果
print(f"Predicted gender for the test data {test}: {predicted_gender}")
Predicted gender for the test data [178, 70]: 男
完整代码
import numpy as np
import matplotlib.pyplot as plt
import operator
def createDataSet():
# 身高和体重特征,以及对应的性别标签('男'或'女')
group = np.array([[160, 56], [160, 50], [168, 60], [165, 57], [180, 69], [176, 61], [176, 65], [170, 55],
[173, 65], [167, 52],[165, 57],[177,64]])
# 性别标签,0代表'男',1代表'女'
labels = [0, 1, 0, 1, 0, 1, 0, 1,0,1,0,1 ]
return group, labels
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
#距离计算
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
distances = sqDiffMat.sum(axis=1) ** 0.5
#还回距离并保存
sortedDistIndices = distances.argsort()
classCount = {}
#选择距离最小的k个点
for i in range(k):
voteIlabel = labels[sortedDistIndices[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# 排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
def plotDataSet(dataSet, labels, test=None, test_label=None):
# 创建颜色映射,男用蓝色,女用红色
colors = ['blue' if label == 0 else 'red' for label in labels]
# 绘制训练数据集的散点图
plt.scatter(dataSet[:, 0], dataSet[:, 1], marker='o', c=colors, label='Training Data')
# 如果提供了测试集数据,也绘制它
if test is not None:
# 为测试集数据指定颜色(例如绿色),并绘制
test_color = 'green' if test_label == 0 else 'yellow'
plt.scatter(test[0], test[1], marker='x', c=test_color, label='Test Data')
# 设置坐标轴标签
plt.xlabel('Height (cm)')
plt.ylabel('Weight (kg)')
# 设置图标题
plt.title('Gender Classification based on Height and Weight')
# 设置图例
plt.legend()
# 显示图形
plt.show()
if __name__ == '__main__':
# 创建数据集
group, labels = createDataSet()
# 画出训练数据散点图
# plotDataSet(group, labels)
# 测试集:新的身高和体重数据
test = [178, 70]
# 假设我们不知道测试集的真实标签,先不传入test_label
# 使用kNN分类(假设k=3)
predicted_gender_label = classify0(test, group, labels, 3)
# 将数字标签转换回性别字符串(假设0代表'男',1代表'女')
predicted_gender = '男' if predicted_gender_label == 0 else '女'
# 打印分类结果
print(f"Predicted gender for the test data {test}: {predicted_gender}")
# 使用已预测的标签绘制测试集数据点
plotDataSet(group, labels, test=test, test_label=predicted_gender_label)
四、 总结
KNN算法的特点
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算机复杂度高、空间复杂度高。
适用数据范围:数值型和标称型。
KNN算法是一种简单而有效的机器学习算法,它在许多领域都有着广泛的应用。