原创 化心为海 微阅读札记https://mp.weixin.qq.com/s/vBE3fu9AZDjRFd5niJU0lg 2025年05月06日 18:17 北京

第三章 机器学习算法基础

摘要:本章首先介绍了基础的机器学习算法的实现原理和应用;然后对决策树模型做了详细介绍;最后,讲解了排序问题、神经网络和支持向量机。

3.1 KNN

用一句通俗的话来讲,KNN的算法思想就是“近朱者赤,近墨者黑。”即同一类事务通常在很多方面都很接近。

定义:如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。(来源:百度百科)

如图1:

1.KNN的计算步骤:

1)计算测试样本与训练集中所有(或大部分)样本的距离,该距离可以是欧氏距离,余弦距离等。常用的是欧式距离。

2)找到步骤1)中距离最短的K个样本,作为预测样本的邻居。

3)对于分类问题,通过投票机制选出K个邻居中,最多的类别作为预测样本的预测值。对于回归问题,则采用K个邻居的平均值。

KNN的优点: 简单有效,易于实现;无须训练(或训练很快)。

KNN的缺点:懒惰算法,数据集的样本容量大时,运算量比较大,评分慢;样本不平均时,预测偏差比较大。

3.1.1.KNN的关键因素:

1.度量距离:不同的距离度量方式会影响KNN的结果。距离类别:欧氏距离,明可夫斯基距离(明氏距离,欧氏距离的一般形式,当p=2时即为欧氏距离),曼哈顿距离,余弦相似度等。

2.K值选择:K值比较小,会取较小邻域内的样本与输入样本比较,降低近似误差,但会增加估计误差。相反,如果K值较大,则会降低估计误差,增加近似误差。

3.决策规则:主要应用于分类问题,目前KNN采取的决策规则多为投票表决,多数票所属的类别作为预测样本的预测类别。

4.归一化:归一化把需要处理的数据通过某种算法限制在一定范围内,一般为0~1。

小贴士:关于估计误差和近似误差:

近似误差:像用一把刻度粗糙的尺子测量长度,误差来自工具本身的不精确。

估计误差:像因手抖导致多次测量结果波动,误差来自操作或数据的随机性。 

在科学计算中,通常需要同时控制两者(如选择高精度方法+增加数据量)。

3.1.2 用KNN来预测鸢尾花品种 鸢尾花数据集(iris)是一个经典的多分类数据集,它通过萼片_sepal(长度、宽度)、花瓣_petal(长度、宽度)四个特征数据来预测鸢尾花品种是山鸢尾(Iris-setosa)、变色鸢尾(Iris-versicolor)还是维吉尼亚鸢尾(Iris-virginica)。

数据集的格式如下: 4.9,3.0,1.4,0.2,Iris_setosa 4.7,3.2,1.3,0.2,Iris_setosa ...... ......

数据集中第1~4列分别表示萼片长度、萼片宽度、花瓣长度、花瓣宽度4个特征,第5列表示鸢尾花品种

import pandas as pdiris_data = pd.read_csv('D:/xgboost-master/demo/data/iris.csv', sep=",", names=['sepal_length','sepal_width',                                                   'petal_length','petal_width','class'])iris_data.head(5)

图片

# 导入matplotlib的pyplot模块,用于数据可视化from matplotlib import pyplot as plt
# 柱状图显示组平均数,可以从图中看出不同品种的鸢尾花属性特点
# 按"class"列(鸢尾花种类)对数据进行分组# grouped_data是一个DataFrameGroupBy对象,包含分组后的数据grouped_data = iris_data.groupby("class")
# 计算每个分组(每种鸢尾花)各特征的平均值# grouped_mean是一个DataFrame,包含每个品种各特征的平均值grouped_mean = grouped_data.mean()
# 绘图部分
# 使用DataFrame的plot方法绘制柱状图# kind='bar'指定图表类型为柱状图grouped_mean.plot(kind="bar")
# 设置图例(右面的小图)位置和样式:# loc='center right' - 将图例的定位点设置在中心右侧# bbox_to_anchor=(1.4,0.3) - 将图例放在图表外的(1.4,0.3)坐标位置# ncol=1 - 图例按1列垂直排列plt.legend(    loc='center right',     bbox_to_anchor=(1.4, 0.3),     ncol= 1)
# 显示绘制的图表plt.show()

图片

#我们需要划分训练集和测试集分别用于训练模型,检验模型的预测能力,所以需要划分训练集和测试集。
import numpy as np# 生成一个与iris_data长度相同的随机数数组,范围在[0,1)之间# 比较每个随机数是否小于0.8,得到一个布尔型掩码(True/False数组)# 约80%的数据会被标记为True,20%为Falsemsk = np.random.rand(len(iris_data)) < 0.8
# 使用掩码进行数据划分:# 选取掩码为True的行作为训练集train_data_origin = iris_data[msk]# 选取掩码为False的行作为测试集test_data_origin = iris_data[~msk]
# 重置数据集的索引:# drop=True表示丢弃原来的索引列,不将其作为新列添加到数据中# 训练集重置索引train_data = train_data_origin.reset_index(drop=True)# 测试集重置索引test_data = test_data_origin.reset_index(drop=True)
#定义训练集、测试集labeltrain_label = train_data['class']test_label = test_data['class']
#定义训练集、测试集的特征train_fea = train_data.drop('class',1)test_fea = test_data.drop('class',1)
##查看数据# train_label.head(10)# test_label.head(10)
# train_fea.head(10)test_fea.head(10)

图片

观察上述数据,萼片长度(sepal_length)和萼片宽度(sepal_width)特征的取值相比于另外两个特征要大很多,实际上我们认为这4个特征对于距离计算是同等重要的。因此,需要对特征进行归一化,即将特征的取值范围映射到0~1之间。常用的归一化方法是min-max标准化,公式如下:newValue = (oldValue - min)/(max - min),其中oldValue是原始值,newValue是归一化后的值。具体到代码如下:

train_norm = (train_fea - train_fea.min()) / (train_fea.max() - train_fea.min())
train_norm.head(10)
test_norm = (test_fea - test_fea.min()) / (test_fea.max() - test_fea.min())
test_norm.head(10)

图片

在执行KNN算法之前,要通过准确率这个评估指标来评估模型预测的正确率。

准确率:即对于给定的测试数据集,模型预测正确的样本数与总样本数之比。

#自定义准确率函数,供后续调用def getAccuracy(testSet,predictions):    correct = 0    #遍历每个测试样本,判断是否预测正确并进行统计    for x in range(len(testSet)):        if testSet[x] == predictions[x]:            correct += 1    #计算并返回准确率    return(correct/float(len(testSet)))* 100.0​​​​​​​
# 从scikit-learn库中导入neighbors模块,该模块包含K近邻(KNN)算法from sklearn import neighbors
# 创建一个KNN分类器实例:# n_neighbors=3 表示使用最近的3个邻居来进行分类# 其他参数使用默认值(如距离度量使用欧氏距离)knn = neighbors.KNeighborsClassifier(n_neighbors=3)
# 训练KNN模型:# train_norm - 经过归一化处理的训练集特征数据# train_label - 训练集对应的标签/类别
# fit()方法会根据训练数据构建KNN模型(!!!实际上是存储训练数据)knn.fit(train_norm, train_label)
# 使用训练好的KNN模型对测试集进行预测:# test_norm - 经过归一化处理的测试集特征数据# predict()方法会返回测试集中每个样本的预测类别predict = knn.predict(test_norm)
# 调用自定义的准确率函数,计算模型在测试集上的准确率:# test_label - 测试集的真实标签# predict - 模型的预测结果
accuracy = getAccuracy(test_label, predict)
# 打印模型准确率:# repr()函数将准确率数值转换为字符串表示# 输出格式示例:"Accuracy:95.0%"print("Accuracy:" + repr(accuracy) + "%")
Accuracy:95.83333333333334%

小贴士:KNN的预测过程(来源:deepseek)

KNN 的预测步骤:

1)计算距离:计算 new_sample 和 train_norm 中每个样本的 欧氏距离(默认距离度量)。

2)找最近 3 个邻居(n_neighbors=3)。

3)投票决定类别:统计这 3 个邻居的类别,选择最多的类别作为预测结果。

例子: 新样本: [5.7, 2.8, 4.1, 1.3]

训练数据:

  1. [5.1, 3.5, 1.4, 0.2] → Setosa (距离较远)

  2. [7.0, 3.2, 4.7, 1.4] → Versicolor (距离最近)

  3. [6.3, 3.3, 6.0, 2.5] → Virginica (距离较远)

  4. [5.8, 2.7, 5.1, 1.9] → Virginica (距离次近)

  5. [4.9, 3.0, 1.4, 0.2] → Setosa (距离最远)

最近的 3 个邻居:

  1. Versicolor (距离最近)

  2. Virginica (次近)

  3. Setosa (第三近)

投票结果:

  • Versicolor: 1 票

  • Virginica: 1 票

  • Setosa: 1 票

如果 n_neighbors=3,可能出现平票情况(取决于 scikit-learn 的默认策略,可能选择排序靠前的类别)。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐