机器学习实验(k-近邻算法+模型评估)

目录

一、KNN算法介绍

     1.1概述

     1.2特点

     1.3优缺点

     1.4k-近邻算法的一般流程

二、距离的度量方式

三、代码实现

     3.1数据收集

     3.2数据分析

     3.3归一化数值

     3.4分类

四、模型评估介绍

     4.1概述

     4.2过拟合与欠拟合

     4.3模型泛化能力

五、常见分类模型评估

     5.1混淆矩阵

     5.2准确率、精确率、召回率、F1_score

           5.2.1准确率

           5.2.2精确度

           5.2.3召回率

           5.2.4F1——score

     5.3AUC

     5.4P-R曲线

六、ROC曲线

     6.1ROC曲线的优势

     6.2与P-R曲线的差异

七、ROC曲线绘制

     7.1数据扩充

     7.2绘制曲线

      7.3运行结果

     7.4结果分析

八、总结



一、KNN算法介绍

     1.1概述

        KNN(k-近邻算法)是一种基于实例的学习,或者说基于标签的数据分类方法。这种方法会预测一个新的观察对象的类别,该类别是该对象最接近的已知对象的k个邻居中大多数出现的那一个。即k-近邻算法采用测量不同特征值之间的距离方法进行分类。

     1.2特点

        KNN的主要特点如下:

        1. 它是一种基于统计的分类方法,依赖于已经标注的训练数据。

        2. KNN的决策过程基于距离,距离近的点被认为更有可能是同一类别的点。

        3. KNN方法是一种简单且直观的算法,易于理解和实现。

     1.3优缺点

        优点:精度高、对异常值不敏感、无数据输入假定。

        缺点:计算复杂度高、空间复杂度高。

     1.4k-近邻算法的一般流程

收集数据可以使用任何方法
准备数据距离计算所需要的数值,最好是结构化的数据格式
分析数据可以使用任何方法
训练算法此步骤不适用于k-近邻算法
测试算法计算错误率
使用算法首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理

二、距离的度量方式

       从第一部分的介绍中我们可以得知,得出未知样本与训练样本之间的距离在KNN中是特别重要的(这里的距离大小实际上反映的是两个实例点之间的相似度)。对此,笔者给出以下两个比较常用的计算公式:

       1.欧式距离

                                                d=\sqrt{(x_{0}-x_{1})^{2}+(y_{0}-y_{1})^{2}}

       2.曼哈顿距离

d=\sum_{k=1}^{n}\left | x_{k}-y_{k} \right |

三、代码实现

     3.1数据收集

       这里的实例用的数据集是葡萄酒的品种预测,对不同特点的数据的类别分为黑皮诺和赤珠霞。其样本特征为:颜色深度、酒精浓度。

       代码:

import numpy as np
import pandas as pd

rowdata = {'颜色深度':[14.23,13.2,13.16,14.37,13.24,12.07,12.43,11.79,12.37,12.04],
          '酒精浓度':[5.64,4.38,5.68,4.80,4.32,2.76,3.94,3.  ,2.12,2.6 ],
          '品种':[0,0,0,0,0,1,1,1,1,1]} 

wine_data = pd.DataFrame(rowdata)
X = np.array(wine_data.iloc[:,:2])  #特征(颜色深度/酒精浓度)
y = np.array(wine_data.iloc[:,-1])  #标签 (品种:0黑皮诺,1赤霞珠)
print(wine_data)

       运行结果:

     3.2数据分析

       代码:

import matplotlib.pyplot as plt # 设置中文显示,windows系统
plt.rcParams['font.sans-serif'] = 'SimHei' #设置中文显示,mac系统
plt.rcParams['axes.unicode_minus'] = False

plt.style.use('ggplot')
plt.figure(figsize = (9,6),dpi=200) #设置窗口的宽和高,以及分辨率

#new_data = np.array([12.8,4.1])

plt.scatter(X[y==0,1],X[y==0,0],color = 'purple',label = '黑皮诺')
plt.scatter(X[y==1,1],X[y==1,0],color = 'red',label = '赤霞珠')
#plt.scatter(new_data[1],new_data[0],color = 'yellow')
plt.xlabel('酒精浓度')
plt.ylabel('颜色深度')
plt.legend(loc='lower right')
plt.show()

       运行结果:

     3.3归一化数值

       数据归一化是一种将数据值映射到特定范围内的方法,通常是将数据值映射到[0,1]区间。它是一种常见的预处理步骤,旨在使数据更易于处理和比较。数据归一化的具体方法包括最大-最小归一化、Z-score标准化等,可以根据数据的特点和算法的需求选择适当的方法。在本实例中,采用的是最大-最小归一化处理方法。

       代码:

def autoNorm(dataSet):
    minVals =dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges =maxVals-minVals #最大值与最小值的差值
    normDataSet=np.zeros(np.shape(dataSet)) #创建一个全零矩阵 normDataSet
    m= dataSet.shape[0]
    normDataSet =dataSet-np.tile(minVals,(m,1))#原始值减去最小值
    normDataSet =normDataSet/np.tile(ranges,(m,1)) #对数据进行归一化
    return normDataSet,ranges,minVals  #返回数据集、各特征值的最大最小差值及其最小值
wine_data_after = autoNorm(wine_data)
print(wine_data_after)

       运行结果:

       分析:从运行结果可以看出,数据集中的数据都已经完成了归一化处理。

     3.4分类

       本实例中,分类器计算距离的度量方式为欧拉距离公式。

       代码:

def KNN(inX,dataset,k):
    '''
    函数功能:KNN分类器 
    参数说明:
    inX: 需要预测分类的数据集
    dataSet: 已知分类标签的数据集
    k: k-近邻算法参数,选择距离最小的k个点
    return:
    result: 分类结果 
    '''
    from math import sqrt
    from collections import Counter
    import numpy as np
    import pandas as pd
    result=[]

    distance = [sqrt(np.sum((x-inX)**2)) for x in np.array(dataSet.iloc[:,0:2])]
    sort_dist = np.argsort(distance) #先升序排序,返回排序后的索引
    topK = [dataSet.iloc[:,-1][i] for i in sort_dist[:k]] #返回最近k个点的y值
    result.append(Counter(topK).most_common(1)[0][0])
    return result

#测试
new_data = np.array([12.8,4.1])
inX = new_data
dataSet = wine_data
k = 3
print('输出[0]为黑皮诺,[1]为赤霞珠:')
result = KNN(inX,dataSet,k)
print(result)

       运行结果:

       分类器测试:

#对占样本中百分之四十进行验证检验
hoRatio=0.40
#数据集的行数
m =dataSet.shape[0]
#测试的行数
numTestVecs =int(m*hoRatio)
#错误次数统计
errorCount=0.0
#分类
for i in range(numTestVecs):
    classifierResult= KNN(X[i],dataSet,3)
    print ("分类结果: %d, 真实: %d"%(classifierResult[0],y[i]))
    if(classifierResult[0] != y[i]):
        errorCount += 1.0
print ("the total error rate is:%f"%(errorCount/float(numTestVecs)))

       运行结果:

       分析:此分类器可以将某个例子划分类别,其错误率为0,但由于数据集中的样本案例不够充分,所以可能存在一定的偏差。

四、模型评估介绍

     4.1概述

       模型评估(model assessment)是指对于一种具体方法输出的最终模型,使用一些指标和方法来评价它的泛化能力。模型评估一般可以分为回归、分类、聚类的任务,不同任务有不同评价指标。根据想要得到的目标值,可以把模型评估分为分类模型评估和回归模型评估。

     4.2过拟合与欠拟合

       过拟合:通俗来说,过拟合就是模型在训练数据中学得太好了,以至于它不仅学习了训练数据中的基本模式,还学习了训练数据中的噪声或异常值,把训练集的数据的特点当作所有样本的一般性质,以至于在未见过的测试数据上表现很差。

       欠拟合:欠拟合是指模型对训练样本的一般性质学得不够,导致模型在训练集和测试集上表现都很差。

     4.3模型泛化能力

       是指机器学习算法对新鲜样本的适应能力。学习的目的是学到隐含在数据背后的规律,对具有同一规律的学习集以外的数据,经过训练的网络也能给出合适的输出,该能力称为泛化能力 。

五、常见分类模型评估

       准确率、精确率、召回率、F1_score,混淆矩阵,AUC,PR等等。

     5.1混淆矩阵

       混淆矩阵也称误差矩阵,是表示精度评价的一种标准格式,是监督学习中的一种可视化工具,主要用于模型的分类结果和实例的真实信息的比较 ,用n行n列的矩阵形式来表示。具体评价指标有总体精度、制图精度、用户精度等,这些精度指标从不同的侧面反映了图像分类的精度。其中,矩阵中的每一行代表实例的预测类别,每一列代表实例的真实类别。

       真实值是positive,模型认为是positive的数量(True Positive=TP);

       真实值是positive,模型认为是negative的数量(False Negative=FN):这就是统计学上的第一类错误(Type I Error);
       真实值是negative,模型认为是positive的数量(False Positive=FP):这就是统计学上的第二类错误(Type II Error);
       真实值是negative,模型认为是negative的数量(True Negative=TN)

混淆矩阵真实值
PositiveNegative
预测值PositiveTPFP(Type II)
NegativeFN(Type I)TN

     5.2准确率、精确率、召回率、F1_score

           5.2.1准确率

                     对于给定的测试集,分类模型正确分类的样本数与总样本数之比;

                     Accuracy = (TP+TN)/(TP+FN+FP+TN)

           5.2.2精确度

                     对于给定测试集的某一个类别,分类模型预测正确的比例,或者说:分类模型预测的正样本中有多少是真正的正样本;

                     Precision = TP/(TP+FP)

           5.2.3召回率

                     对于给定测试集的某一个类别,样本中的正类有多少被分类模型预测正确召回率的定义为:对于给定测试集的某一个类别,样本中的正类有多少被分类模型预测正确;

                     Recall = TP/(TP+FN)

           5.2.4F1——score

                     F值是精确度和召回率的调和值。主要用于评估模型的稳健性。

                     2/F1 = 1/Precision + 1/Recall

     5.3AUC

       AUC(Area Under Curve)被定义为ROC曲线下的面积(ROC的积分),通常大于0.5小于1。随机挑选一个正样本以及一个负样本,分类器判定正样本的值高于负样本的概率就是 AUC 值。AUC值(面积)越大的分类器,性能越好。

     5.4P-R曲线

       PR曲线的横坐标是精确率P,纵坐标是召回率R。前面提到的F1分数就是PR曲线的平衡点。

六、ROC曲线

     6.1ROC曲线的优势

       ROC曲线(Receiver Operating Characteristic curve)和PR曲线(Precision-Recall curve)都是用于评估分类模型性能的可视化工具,但它们关注的指标不同。

       ROC曲线全称为接收者操作特征曲线,是一种用于评估二分类模型性能的工具。是以False Positive Rate(FPR,假阳性率)为横轴,True Positive Rate(TPR,真阳性率)为纵轴绘制的曲线。它主要用于评估模型在不同阈值下对正负样本的区分能力。ROC曲线下的面积(AUC,Area Under Curve)越大,说明模型的性能越好。ROC曲线适用于正负样本不平衡的情况,因为它关注的是整体的区分能力,而不是某一类样本的区分能力。

       P-R曲线是以False Positive Rate(FPR,假阳性率)为横轴,Precision(精确率)为纵轴绘制的曲线。它主要用于评估模型在特定阈值下对正样本的召回能力。PR曲线越靠近左上角,说明模型的性能越好。PR曲线适用于正负样本平衡的情况,因为它关注的是正样本的召回能力。

       相比P-R曲线,ROC曲线有个很好的特性:当测试集中的正负样本的分布发生变化的时候,ROC曲线能够保持稳定。在实际应用中,正例和负例的数量往往存在较大的差异。ROC曲线可以很好地处理这种不平衡情况,因为它关注的是整体的TPR和FPR,而不是某一类别的数量。此外, ROC曲线能够综合考虑模型的敏感性和特异性。通过观察ROC曲线的形状,我们可以了解到在不同阈值下模型的TPR和FPR的变化情况,从而选择最佳的阈值来平衡模型的准确性和误报率。

     6.2与P-R曲线的差异

       1. 关注指标不同:ROC曲线关注的是整体的区分能力,而PR曲线关注的是正样本的召回能力。

       2. 适用场景不同:ROC曲线适用于正负样本不平衡的情况,而PR曲线适用于正负样本平衡的情况。

       3. 阈值选择不同:ROC曲线需要选择一个固定的阈值来绘制曲线,而PR曲线可以针对不同的阈值绘制多条曲线。

       4. 对异常值敏感程度不同:ROC曲线对异常值较为敏感,因为异常值可能导致TPR和FPR的变化;而PR曲线对异常值相对不敏感,因为精确率主要受正样本的影响。

七、ROC曲线绘制

     7.1数据扩充

       由于原始数据集数据过少,呈现的曲线效果不好,因此,先对数据集进行一个数据扩充。

# 扩充数据集
rowdata['颜色深度'].extend(np.random.rand(150) * 15)
rowdata['酒精浓度'].extend(np.random.rand(150) * 7)
rowdata['品种'].extend([0] * 149 + [1])
# 将数据集转换为csv文件
df = pd.DataFrame(rowdata)
df.to_csv('rowdata.csv', index=False)

     7.2绘制曲线

#ROC曲线绘制

from sklearn.metrics import roc_auc_score,roc_curve,auc,precision_recall_curve, average_precision_score
from sklearn import metrics
from sklearn.model_selection import train_test_split
from matplotlib.font_manager import FontProperties
from sklearn.neighbors import KNeighborsClassifier

# 划分特征和标签
X = df[['颜色深度', '酒精浓度']]
y = df['品种']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# kNN模型训练和预测
k_values = [3, 5, 6,7]
for k in k_values:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X_train, y_train)
    y_pred = knn.predict_proba(X_test)[:, 1]
    # 计算ROC曲线和AUC
    fpr, tpr, _ = roc_curve(y_test, y_pred)
    roc_auc = auc(fpr, tpr)
    # 绘制ROC曲线
    plt.figure()
    plt.plot(fpr, tpr, label='KNN (k=%d), AUC = %.2f' % (k, roc_auc))
    plt.plot([0, 1], [0, 1], 'k--')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title('Receiver Operating Characteristic')
    plt.legend(loc="lower right")
    plt.show()

      7.3运行结果

     7.4结果分析

       通过运行上述代码,我们可以得到不同k值的ROC曲线。从图中可以看出,随着k值的增加,ROC曲线下的面积(AUC)逐渐增大。在k值为5时,AUC最大,说明模型的整体性能更好。这说明在分类问题中,增加k值可以提高模型的性能。然而,当k值过大时,可能会导致过拟合,从而降低模型的泛化能力。因此,选择合适的k值对于提高模型性能至关重要。不过,由于该数据集的数据是随机生成的,虽然笔者有进行部分数据调整,但最后曲线呈现的效果也不是很好。建议直接去网上找别人分享的数据集,不要自己写T-T。

八、总结

       通过本次学习,我理解了KNN的基本概念和工作原理,了解数据归一化的重要性,学会了如何选择和调整k值和距离度量方式。其中k值的选择会对分类结果有较大影响。k值太小容易过拟合,k值太大容易欠拟合,因此要根据实际情况选择合适的k值。通过实践应用KNN算法,可以更好地掌握KNN的应用场景和注意事项,提高预测精度和稳定性。

       模型评估是确保模型性能的关键步骤。学习ROC曲线,我深感它的重要性在于: 1. 理解模型的分类能力:ROC曲线越接近左上角,说明模型的分类性能越好,假阳性率和假阴性率都低。 2. 选择最优阈值:曲线下的面积(AUC)越大,模型整体性能越好。通过ROC曲线,可以直观地选择最合适的阈值来平衡敏感性和特异性。 3. 模型比较:不同模型的ROC曲线可以直观比较,曲线之上表示性能优于曲线之下。 通过学习ROC曲线,我更加认识到模型评估的全面性和模型选择的灵活性,这对于优化模型并在实际应用中取得最佳效果至关重要。

  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值