K-近邻算法(KNN)

一、概念

K-近邻算法(KNN)是一种基本的机器学习分类和回归方法。它的核心思想是:如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别。

二、KNN算法的流程 

(1)数据准备:准备训练集和测试集,并对数据进行预处理,如特征缩放、缺失值处理等。

        归一化数值:用于处理不同取值范围的特征值

                     newValue = (oldValuye-min)/(max-min)

(2)计算距离:对于测试集中的每个样本,计算它与训练集中每个样本的距离。

        ①曼哈顿距离

        d=\sum_{i=1}^{n}\left | x_{1i}-x_{2i} \right |

        ②欧几里得距离

        d=\sqrt{\sum_{i=1}^{n}\left ( x_{1i}-x_{2i} )*(x_{1i}-x_{2i}\right )}

(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算法是一种简单而有效的机器学习算法,它在许多领域都有着广泛的应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值