简介

K-近邻算法(K Nearest Neighbor,简称KNN):如果一个样本在特征空间的k个最相似的样本中的大多数属于某一个类别,则该样本也属于该类别。可以解决分类问题回归问题

关于样本的相似性:样本都属于一个任务数据集的,样本距离越近越相似。

K值过,容易受到异常值的影响,且会导致模型学到“脏数据”,容易发生过拟合

K值过,模型会变得简单,容易发生欠拟合

代码实现思路:

1.导包
2.准备数据集
3.创建KNN模型对象
4.模型训练
5.模型预测

分类问题

适用于:有特征、有标签、且标签是不连续的数据

通过投票,取票数最多。

分类问题小例子:

# 1.导包
from sklearn.neighbors import KNeighborsClassifier
# 2.准备数据集
x_train = [[0],[1],[2],[3]]   # 训练集的特征数据
y_train = [0,0,1,1]           # 训练集的标签数据
x_test = [[5]]                # 测试集的特征数据
# 3.创建KNN模型对象
estimator = KNeighborsClassifier(n_neighbors=3)
# 4.模型训练
estimator.fit(x_train,y_train)
# 5.模型预测
y_pred = estimator.predict(x_test)
print(f'预测结果为:{y_pred}')

运行结果:

回归问题

适用于:有特征、有标签、且标签是连续的数据

取 平均值

回归小例子:

# 1.导包
from sklearn.neighbors import KNeighborsRegressor
# 2.准备数据集
x_train = [[0, 0, 1],[1, 1, 0],[3, 10, 10],[4, 11, 12]]   # 训练集的特征数据
y_train = [0.1, 0.2, 0.3, 0.4]                            # 训练集的标签数据
x_test = [[3, 11, 10]]                                    # 测试集的特征数据
# 3.创建KNN模型对象
estimator = KNeighborsRegressor(n_neighbors=3)
# 4.模型训练
estimator.fit(x_train,y_train)
# 5.模型预测
y_pred = estimator.predict(x_test)
print(f'预测结果为:{y_pred}')

运行结果:

距离度量

1.欧式距离

对应维度差值的平方和再开根号。

2.曼哈顿距离

对应维度差值的绝对值之和。

3.切比雪夫距离

切比雪夫距离 = 对应维度值差值的绝对值,取其中的最大值。

4.闵可夫斯基距离

特征预处理

特征的单位或者大小相差较大,或者某特征的方差相比其他的特征要大出几个数量级,容易影响(支配)目标结果,使得一些模型(算法)无法学习到其它的特征。

1.归一化

公式解释:

x' 是基于公式算出来的结果   x'' 是最终结果   
mx 是你想映射到的区间的最大值 mi 是想映射区间的最小值

该方法容易受到极值的影响,一般用于处理小数据集。

代码示例:

# 导包
from sklearn.preprocessing import MinMaxScaler

# 准备原始数据
x_train = [[90,2,10,40],[60,4,15,45],[75,3,13,46]]

# 创建归一化对象
# 参数feature_range表示生成范围,默认区间是(0,1) 如果是这个区间可以不写
transfer = MinMaxScaler(feature_range=(0,1))

# 对原数据集进行归一化操作
x_train_new = transfer.fit_transform(x_train)

# 打印归一化后的数据
print('归一化后的数据:')
print(x_train_new)

运行结果:

2.标准化

数据标准化:通过对原始数据进行标准化,转为均值为0,标准差为1的标准正态分布的数据。

公式:

x' = \frac{x-mean}{\sigma}

mean:为特征的平均值;\sigma:为特征的标准差。

代码示例:

# 导包
from sklearn.preprocessing import StandardScaler

# 准备原始数据
x_train = [[90,2,10,40],[60,4,15,45],[75,3,13,46]]

# 创建标准差对象
transfer = StandardScaler()

# 对原数据集进行归一化操作
x_train_new = transfer.fit_transform(x_train)

# 打印归一化后的数据
print('归一化后的数据:')
print(x_train_new)

# 打印数据集的均值和方差
print(f"数据集的均值为:{transfer.mean_}")
print(f"数据集的方差为:{transfer.var_}")
print(f"数据集的标准差为:{transfer.scale_}")

运行结果:

3.总结

看到这里可以尝试一下鸢尾花分类的案例看看能不能做出来。

KNN算法对尾花分类

超参数选择方法

交叉验证

交叉验证:是一种数据集的分割方法,将训练集分成n份,拿出一份做验证集(测试集),其他n-1份做训练集。

原理:(用4折交叉验证举例)将数据集划分为cv=4 份

  1. 第一次:k=1,把第一份数据做验证集,其他数据做训练
  2. 第二次:k=2,把第二份数据做验证集,其他数据做训练
  3. k=3、k=4,以此类推,总共训练4次,评估4次
  4. 取上面四次评估的准确率的平均值做交叉验证为模型得分
  5. 若k=4时,模型得分最好,再使用全部训练集(训练集+验证集)。对k=4模型再训练一遍,再使用测试集对k=4模型做评估

网格搜索

为什么需要网格搜索?

模型有很多超参数,其能力也存在很大的差异。需要手动产生很多超参数组合,来训练模型每组超参数都采用交叉验证评估,最后选出最优参数组合建立模型。

网格搜索是模型调参的有力工具。只需要将若干参数传递给网格搜索对象,它自动帮我们完成不同超参数的组合、模型训练、模型评估,最终返回一组最优的超参数。

网格搜索+交叉验证的强力组合(模型选择和调优)

  • 交叉验证解决模型的数据输入问题(数据集划分)得到更可靠的模型
  • 网格搜索解决超参数的组合
  • 两个组合再一起形成一个模型参数调优的解决方案

交叉验证网格搜索API介绍

对估计器的指定参数值进行详尽的搜索

sklearn.model_selection.GridSearchCV(estimator,param_grid=None,cv=b=None)

参1:估计器对象;参2:估计器参数(dict){"n_neighbors":[1,3,5]} ;参3:指定几折交叉验证

结果分析:

  • bestscore_:在交叉验证中验证的最好结果

  • bestestimator:最好的参数模型

  • cvresults:每次交叉验证后的验证集准确率结果和训练集准确率结果

加入了交叉验证和网格搜索的鸢尾花分类实验:

# 导包
from sklearn.model_selection import train_test_split, GridSearchCV  # 分割训练集的测试集, 寻找最优超参(网格搜索+交叉验证)
from sklearn.preprocessing import StandardScaler      # 数据标准化
from sklearn.metrics import accuracy_score            # 模型评估,计算模型预测的准确率
from sklearn.neighbors import KNeighborsClassifier    # KNN算法
from sklearn.datasets import load_iris                # 加载鸢尾花测试集

# 加载数据
iris_data = load_iris()

# 数据预处理
x_train, x_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, test_size=0.2, random_state=25)

# 特征工程
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 模型训练
# 1、创建KNN分类对象
estimator = KNeighborsClassifier()
# 2、定义字典,记录超参数可能出现的值
param_dict = {'n_neighbors':[i for i in range(1, 11)]}
# 3、创建GridSearchCV对象 --> 寻找最优超参
estimator = GridSearchCV(estimator,param_dict,cv=4)
# 4、具体训练
estimator.fit(x_train,y_train)
# 5、打印最优超参组合
print(f'最优评分:{estimator.best_score_}')
print(f'最优超参组合:{estimator.best_params_}')
print(f'最优的估计器对象:{estimator.best_estimator_}')

# 模型评估
# 1.获取最优超参的模型对象
estimator = estimator.best_estimator_
# 2.模型训练
estimator.fit(x_train,y_train)
# 3.模型预测
y_pred = estimator.predict(x_test)
# 4.模型评估
print(f'准确率为:{accuracy_score(y_test,y_pred)}')

运行结果:

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐