python数据挖掘(3.scikit-learn估计器分类 近邻算法)

本文介绍了scikit-learn如何使用估计器进行分类任务,特别是K近邻算法。讨论了K近邻算法的原理、距离计算方法(如欧氏距离)以及在大数据集上的挑战。通过实验展示了数据集划分、K近邻分类器的训练与测试,得出约86.4%的准确率,并引入交叉验证来提高结果的可靠性,得到82.3%的准确率。最后提到了调整参数n_neighbors对模型性能的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

scikit-learn为了帮助用户实现大量分类算法,scikit-learn把相关功能封装成了所谓的估计器,他用于分类任务。主要包含了两个函数

  1. fit():训练算法,设置内部参数,该函数接收训练集及其类别两个参数
  2. predict():参数为测试集。预测测试类别,并返回一个包含测试集各条数据类别的数组。
近邻算法

近邻算法可能诗标准数据挖掘算法中最为直观的一种,为了对新个体进行分类,它查找训练集,找到与新个体最为相似的那些个体。
近邻算法几乎可以对任何数据集进行分类。但是要计算数据集中每两个个体的距离,但是当数据量很大时,计算的距离就太多了,比如我们的数据量有1000时,需要计算大约50万个个体之间的距离,除了计算量大之外,就是在特征取离散值的数据集上表现的很差。

距离是数据挖掘的核心概念之一,我们需要知道两个个体之间的距离是多少,进一步说,我们还能解决一对个体相对另一对个体是否更相似等问题
下面有三种计算距离的方法

  1. 欧氏距离:既两个点之间连线的距离
  2. 曼哈顿距离:两个特征值在坐标轴中,横轴距离+纵轴距离之和,也叫街区距离
  3. 余弦距离:计算坐标轴中余弦值忽略特征向量的长度

这章我们主要说欧氏距离,剩下的会在后续章节中

我们的数据集每行有35个值,前34个为17座天线采集的数据,最后一个值为‘g’或’b’,表示数据是否提供了有价值的信息
首先导入我们需要的numpy和csv,加载数据集

In [32]: import csv 
    ...: import numpy as np                                                                                          

In [33]: X = np.zeros((351, 34), dtype='float')                                                                      

In [34]: y = np.zeros((351,), dtype='bool')                                                                          

In [35]: with open('/Users/gn/Downloads/ionosphere.data', 'r') as input_file: 
    ...:     reader = csv.reader(input_file) 
    ...:     for i, row in enumerate(reader): 
    ...:         data = [float(datum) for datum in row[:-1]] 
    ...:         X[i] = data 
    ...:         y[i] = row[-1] == 'g' 
    ...:                                                                                                             

In [36]: X                                                                                                           
Out[36]: 
array([[ 1.     ,  0.     ,  0.99539, ..., -0.54487,  0.18641, -0.453  ],
       [ 1.     ,  0.     ,  1.     , ..., -0.06288, -0.13738, -0.02447],
       [ 1.     ,  0.     ,  1.     , ..., -0.2418 ,  0.56045, -0.38238],
       ...,
       [ 1.     ,  0.     ,  0.94701, ...,  0.00442,  0.92697, -0.00577],
       [ 1.     ,  0.     ,  0.90608, ..., -0.03757,  0.87403, -0.16243],
       [ 1.     ,  0.     ,  0.8471 , ..., -0.06678,  0.85764, -0.06151]])

In [37]: y                                                                                                           
Out[37]: 
array([ True, False,  True, False,  True, False,  True, False,  True,
       False,  True, False,  True, False,  True, False,  True, False,
        True, False,  True, False,  True, False,  True, False,  True,
       False,  True, False,  True, False,  True, False,  True, False,
        True, False,  True, False,  True, False,  True, False,  True,
       False,  True, False,  True, False,  True, False,  True, False,
        True, False,  True, False,  True, False,  True, False,  True,
···

这是我们的数据集True表示这个数据有效

In [38]: from sklearn.model_selection import train_test_split                                                        

In [39]: X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=14)                                  

In [40]: print("有 {} 个样本作为训练集".format(X_train.shape[0])) 
    ...: print("有 {} 个样本作为测试集".format(X_test.shape[0])) 
    ...: print("每个样本有 {} 个特征值".format(X_train.shape[1]))                                                    
有 263 个样本作为训练集
有 88 个样本作为测试集
每个样本有 34 个特征值

In [41]: from sklearn.neighbors import KNeighborsClassifier #导入K近邻分类器                                         

In [42]: estimator = KNeighborsClassifier() #初始化一个K近邻分类器实例,该算法默认选择5个近邻作为分类依据            

In [43]: estimator.fit(X_train, y_train)  #训练                                                                      
Out[43]: 
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=None, n_neighbors=5, p=2,
           weights='uniform')

In [44]: y_predicted = estimator.predict(X_test)                                                                     

In [45]: accuracy = np.mean(y_test == y_predicted) * 100                                                             

In [46]: print("正确率为{0:.1f}%".format(accuracy))                                                                  
正确率为86.4%

In [47]: y_predicted                                                                                                 
Out[47]: 
array([ True,  True,  True,  True,  True, False,  True, False,  True,
        True,  True,  True,  True,  True, False, False,  True, False,
       False,  True,  True,  True,  True, False,  True,  True,  True,
        True,  True,  True,  True,  True,  True, False, False,  True,
        True,  True,  True,  True,  True, False,  True, False,  True,
        True,  True,  True, False,  True,  True,  True,  True,  True,
       False,  True,  True,  True,  True,  True, False,  True,  True,
        True,  True,  True,  True,  True, False, False, False,  True,
        True, False,  True,  True,  True, False, False,  True, False,
        True,  True, False,  True,  True, False,  True])

In [48]: y_test                                                                                                      
Out[48]: 
array([ True, False,  True,  True,  True, False,  True, False,  True,
        True,  True, False, False,  True, False, False,  True,  True,
       False,  True,  True,  True,  True, False,  True, False,  True,
        True,  True, False,  True,  True,  True, False, False,  True,
        True,  True,  True,  True,  True, False,  True, False,  True,
        True, False,  True, False,  True, False,  True, False,  True,
       False,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True, False,  True, False, False, False,  True,
        True, False, False,  True,  True, False, False,  True, False,
        True,  True, False,  True,  True, False,  True])

这一段就是,我们先将数据分为测试集和训练集
导入K近邻分类器,使用训练集进行训练,再用测试集来判断准确率
最后我们得出86.4%的真确率,当然了针对不同的数据集,根据实验的实际情况,极可能的选择合适的参数,争取到达最佳效果。

在之前的几个试验里,我们把数据集分为训练集和测试机,用训练集训练算法,测试集评估效果,如果我们的结果是碰巧得出了高正确率该怎么办?就需要交叉实验了。
scikit-learn提供了集中交叉检验的方法我们看一下

In [49]: from sklearn.model_selection import cross_val_score                                                         

In [50]: scores = cross_val_score(estimator,X,y,scoring='accuracy')                                                  

In [51]: average_accuracy = np.mean(scores) *100                                                                     

In [52]: average_accuracy                                                                                            
Out[52]: 82.33618233618233

经过交叉实验得到的结果为82.3% 较之前虽然差了一点,但是我们还没有调整过参数,这个结果还是非常好的。下面我们通过调节参数到达更理想的效果

近邻算法有多个参数,最为重要的是选取多少个近邻作为预测依据,这就是n_neighbors。我们测试一下n_neighbors的值,比如从1-20,我们重复多次试验

In [53]: avg_scores = []                                                                                             

In [54]: all_scores = []                                                                                             

In [55]: parameter_values = list(range(1,21))                                                                        

In [56]: for n_neighbors in parameter_values: 
    ...:     estimator = KNeighborsClassifier(n_neighbors=n_neighbors) 
    ...:     scores = cross_val_score(estimator,X,y,scoring='accuracy') 
    ...:     avg_scores.append(np.mean(scores)) 
    ...:     all_scores.append(scores) 
    ...:                                                                                                             

In [57]: from matplotlib import pyplot as plt                                                                        

In [58]: plt.figure(figsize=(32,20)) 
    ...: plt.plot(parameter_values, avg_scores, '-o', linewidth=5, markersize=24) 
    ```
    这一段就是我们分别给这个算法的参数设置为1-20,计算交叉检验的准确率。得到一个列表avg_scores,之后我们用matplotlib来绘制一个准确率的图
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191128230646286.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzA3NDE1Mg==,size_16,color_FFFFFF,t_70)
    趋势是很明显的,随着n_neighbors的增大准确率是下降的。
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值