机器学习/数据分析--通俗语言带你入门K-邻近算法(结合案例)

前言

  • 机器学习是深度学习和数据分析的基础,接下来将更新常见的机器学习算法
  • 注意:在打数学建模比赛中,机器学习用的也很多,可以一起学习
  • 欢迎收藏 + 点赞 + 关注

K-邻近算法模型简介

1、模型简介

解决了什么问题?

  • K-邻近,简称KNN,KNN解决了的分类与回归问题,主要运用解决分类问题

例子说明

在这里插入图片描述

首先上图,上图有三类不同形状,O是要预测他属于那一类,KNN算法的思想就是,选取与他最近的K的点,那个类别占比大,他就属于那个类别。上图中:

  • K值为3时候,三角形最多,故它属于三角形类
  • K值为5的时候,正方形最多,故它属于正方形那一类

2、模型难点与求解

KNN难点

  1. K值的选取问题
  2. 选取K值后,如何遍历速度最快?
  3. 距离如何计算问题

解决方法

K值选取问题

在李航老师的《统计学习方法》上所说:

  1. 选择较小的K值,就相当于用较小的领域中的训练实例进⾏预测, “学习”近似误差会减小,只有与输⼊实例较近或相似的训练实例才会对预 测结果起作⽤,与此同时带来的问题是“学习”的估计误差会增⼤, 换句话说,**K值的减小就意味着整体模型变得复杂,容易发生过拟合; **
  2. 选择较大的K值,就相当于⽤较⼤领域中的训练实例进⾏预测, 其优点是可以减少学习的估计误差,但缺点是学习的近似误差会增⼤。这时候,与输⼊实例较远(不相似的)训练实例也会对预测器作⽤,使预测发⽣错误。 且**K值的增大就意味着整体的模型变得简单。 **
  3. K=N(N为训练样本个数),则完全不足取, 因为此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的类,模型过于简单,忽略了训练实例中大量有用信息。 在实际应⽤中,K值⼀般取⼀个比较小的数值,例如采⽤交叉验证法(简单来 说,就是把训练数据在分成两组:训练集和验证集)来选择最优的K值。

方法:网格搜索

网格搜索解决的问题是,当有多个参数选择的时候,选取最优解的参数,如下:

model = KNeighborsClassifier()   # algorithm:自动选择算法确定K值
# 网格搜索查找最优 n_neighors
grid_search = {"n_neighbors": [1, 3, 5, 7, 9]}
model = GridSearchCV(model, param_grid=grid_search, cv=5)  # 交叉验证设置为 5
选取K值后,如何遍历速度最快

这个方法在sklearn库中很好解决,在使用KNeighborsClassifier()创建模型的时候,KNeighborsClassifier()参数列表中有一个algorithm的参数,它包含了一下几个参数,默认是auto,有兴趣的同学可以查阅资料学习Kd_tree的原理,推荐在b站中kd树相关的教程。

  1. ‘auto’:
    • 当选择 'auto' 时,scikit-learn 会根据训练数据的大小和维度自动选择最合适的算法。这是默认选项,通常是一个好的起点,因为它可以根据数据的特性来选择最佳算法。
  2. ‘ball_tree’:
    • 使用 Ball Tree 数据结构。适用于高维空间中的最近邻搜索。Ball Tree 是一种树形数据结构,它可以有效地处理高维数据。
  3. ‘kd_tree’:
    • 使用 KD Tree 数据结构。适用于低至中等维度的空间中的最近邻搜索。KD Tree 也是一种树形数据结构,但更适合低维数据。
  4. ‘brute’:
    • 使用蛮力(Brute Force)方法来计算最近邻。这种方法直接计算每个样本之间的距离,没有使用任何加速数据结构。虽然简单,但在大样本集或高维数据中效率较低。
距离选取

通过查阅资料,发现主要的距离选取分为以下几种类型:

欧式距离

欧氏距离(Euclidean Distance)是最容易直观理解的距离度量方法,我们小学、初中和高中接触到的两个点在空间中的距离一般都是指欧氏距离,他的公式如下:

在这里插入图片描述

曼哈顿距离

在曼哈顿街区要从一个十字路口开车到另一个十字路口,驾驶距离显然不是两点间的直线距离。这个实际驾驶距离就是“曼哈顿距离(Manhattan Distance)”。曼哈顿距离也称为“城市街区距离”(City Block distance)。

在这里插入图片描述

切比雪夫距离

国际象棋中,国王可以直行、横行、斜行,所以国王走一步可以移动到相邻8个方格中的任意一个。国王从格子(x1,y1)走到格子(x2,y2)最少需要多少步?这个距离就叫切比雪夫距离(Chebyshev Distance)。

在这里插入图片描述

在这里插入图片描述

案例求解

背景: 海伦一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但她没有从中找到喜欢的人。经过一番总结,她发现曾交往过三种类型的人:

  • ①不喜欢的人;
  • ②魅力一般的人;
  • ③极具魅力的人。

她现在总结好的数据中(即训练集)包含三种特征:

  • ①每年获得的飞行常客里程数
  • ②玩视频游戏所耗时间百分比
  • ③每周消费的冰淇淋公升数

她希望根据现有的数据来判断一个陌生男人会被她归到哪一类。

求解步骤

  1. 导入数据
  2. 统计分析
  3. 数据预处理
  4. 划分数据集
  5. 模型的创建与训练
  6. 预测结果
  7. 模型评估

1、导入数据

import pandas as pd 

data = pd.read_table('./datingTestSet2.txt', sep='\t', header=None)    
data.head()
0123
0409208.3269760.9539523
1144887.1534691.6739042
2260521.4418710.8051241
37513613.1473940.4289641
4383441.6697880.1342961

分析:pd.read_table(‘./datingTestSet2.txt’, sep=‘\t’, header=None)

  • 第一个参数:路径
  • sep:表示数据字段中用什么分割
  • header:第一行是否是标题,不是,则用0、1、2……代替

2、统计分析

# 查看维度
data.shape

答案:

(1000, 4)
# 查看数据基本信息
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   0       1000 non-null   int64  
 1   1       1000 non-null   float64
 2   2       1000 non-null   float64
 3   3       1000 non-null   int64  
dtypes: float64(2), int64(2)
memory usage: 31.4 KB
# 查看统计
data.describe()
0123
count1000.0000001000.0000001000.0000001000.000000
mean33635.4210006.5599610.8320731.985000
std21957.0068334.2436180.4972390.818196
min0.0000000.0000000.0011561.000000
25%13796.0000002.9339630.4089951.000000
50%31669.0000006.5952040.8094202.000000
75%47716.25000010.0565011.2728473.000000
max91273.00000020.9193491.6955173.000000
# 查看缺失值
data.isnull().sum()   

答案:

0    0
1    0
2    0
3    0
dtype: int64

经过分析,每一列都没有缺失值

# 每个特征之间的相关性
data.iloc[:, :3].corr()
012
01.0000000.465847-0.009171
10.4658471.0000000.008874
2-0.0091710.0088741.000000

3、数据预处理

KNN,特征值来源于生活统计,特征一与特征二、三差距很大,故为了确保特征值在计算距离的时候准确率高一点,故这里对特征数据进行归一化处理

from sklearn.preprocessing import MinMaxScaler
import seaborn as sns
import matplotlib.pyplot as plt 
import numpy as np
 
# 标准化,对特征
scaler = MinMaxScaler()
data_scaled = scaler.fit_transform(data.iloc[:, :3])   
# 将标准化后的数据转为DataFrame
data_scaled = pd.DataFrame(data_scaled)
# 标准化后数据统计信息
print("标准化后数据统计信息:\n", data_scaled.describe())
# 可视化前后数据分布
plt.figure(figsize=(16, 6))
# 标准化前的分布
plt.subplot(1, 2, 1)
sns.histplot(data.iloc[:, 0], kde=True, color='blue')
plt.title('Distribution of Median Income before Standardization')
# 标准化后的分布
plt.subplot(1, 2, 2)
sns.histplot(data_scaled.iloc[:, 0], kde=True, color='red')
plt.title('Distribution of Median Income after Standardization')
plt.show()
标准化后数据统计信息:
                  0            1            2
count  1000.000000  1000.000000  1000.000000
mean      0.368514     0.313583     0.490401
std       0.240564     0.202856     0.293467
min       0.000000     0.000000     0.000000
25%       0.151151     0.140251     0.240703
50%       0.346970     0.315268     0.477032
75%       0.522786     0.480727     0.750543
max       1.000000     1.000000     1.000000

在这里插入图片描述

# 赋值给原数据
data.iloc[:, :3] = data_scaled.iloc[:, :3]
data
0123
00.4483250.3980510.5623343
10.1587330.3419550.9872442
20.2854290.0689250.4744961
30.8232010.6284800.2524891
40.4201020.0798200.0785781
...............
9950.1221060.1630370.3722242
9960.7542870.4768180.3946211
9970.2911590.5091030.5107953
9980.5271110.4366550.4290053
9990.4794080.3768090.7857183

1000 rows × 4 columns

4、划分数据集

from sklearn.model_selection import train_test_split

X = data.iloc[:, :3]
y = data.iloc[:, 3]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

5、模型的创建与训练

from sklearn.neighbors import  KNeighborsClassifier
from sklearn.model_selection import GridSearchCV

model = KNeighborsClassifier()   # algorithm:自动选择算法确定K值
# 网格搜索查找最优 n_neighors
grid_search = {"n_neighbors": [1, 3, 5, 7, 9]}
model = GridSearchCV(model, param_grid=grid_search, cv=5)  # 交叉验证设置为 5
model.fit(X_train, y_train)

6、预测结果

# 对整个模型进行预测
data["预测结果"] = model.predict(data.iloc[:, :3])
data.head(10)
0123预测结果
00.4483250.3980510.56233433
10.1587330.3419550.98724422
20.2854290.0689250.47449611
30.8232010.6284800.25248911
40.4201020.0798200.07857811
50.7997220.4848020.60896111
60.3938510.3265300.71533533
70.4674550.6346450.32031233
80.7395070.4126120.44153611
90.3887570.5866900.88936033
# 查看后 10 行
data.tail(10)
0123预测结果
9900.3040330.4085570.07527933
9910.1081150.1288270.25476422
9920.2008590.1888800.19602922
9930.0414140.4711520.19359822
9940.1992920.0989020.25305822
9950.1221060.1630370.37222422
9960.7542870.4768180.39462111
9970.2911590.5091030.51079533
9980.5271110.4366550.42900533
9990.4794080.3768090.78571833

7、模型评估

scorek = model.score(X_test, y_test)

scorek

答案:

0.93
  • 17
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值