机器学习笔记——3。分类学习KNN与python实现,及


KNN

1、分类学习

1.什么是分类(监督学习)

输入:一组有标签的训练数据(也称观察和评估),标签表明了这些数据(观察)的所署类别。

输出:分类模型根据这些训练数据,训练自己的模型参数,学习出一个适合这组数据的分类器,当有新数据(非训练数据)需要进行类别判断,就可以将这组新数据作为输入送给学好的分类器进行判断。

2.分类学习-评价

  • 训练集(training set) :顾名思义用来训练模型的已标注数据,用来建立模型,发现规律。
  • 测试集(testing set) :也是已标注数据,通常做法是将标注隐藏,输送给训练好的模型,通过结果与真实标注进行对比,评估模型的学习能力。

训练集/测试集的划分方法:根据已有标注数据,随机选出一部分数据 (75%)数据作为训练数据,余下的作为测试数据,此外还有交叉验证法, 自助法用来评估分类模型。

1 精确率

精确率:精确率是针对我们预测结果而言的,(以二分类为例)它表示的是预测为正的样本中有多少是真正的正样本。那么预测为正就有两种可能,一种就是把正类预测为正类(TP),另一种就是把负类预测为正类(FP), 也就是
在这里插入图片描述

2 召回率

召回率:是针对我们原来的样本而言的,它表示的是样本中的正例有多少被预测正确了。
那也有两种可能,一种是把原来的正类预测成正类(TP), 另一种就是把原来的正类预测为负类(FN),也就是
在这里插入图片描述
假设我们手上有60个正样本,40个负样本,我们要找出所有的正样本,分类算法查找出50个,其中只有40个是真正的正样本

  • TP: 将正类预测为正类数 40;
  • FN: 将正类预测为负类数 20;
  • FP: 将负类预测为正类数10;
  • TN: 将负类预测为负类数 30
    准确率(accuracy)=预测对的/所有 = (TP+TN)/(TP+FN+FP+TN) = 70%
    精确率(precision)= TP/(TP+FP)=80%
    召回率(recall)=TP/(TP+FN)= 66%

3.Sklearn中的分类

与聚类算法被统一封装在sklearn.cluster 模块不同,sklearn库中的分类算法并未被统一封装在一个子模块中,因此对分类算法的import 方式各有不同。
Sklearn提供的分类函数包括:

  • k近邻(knn)
  • 朴素贝叶斯(naivebayes)
  • 支持向量机(svm)
  • 决策树 (decision tree)
  • 神经网络模型(Neural networks)等
    这其中有线性分类器,也有非线性分类器。

4.分类算法的应用

  • 金融:贷款是否批准进行评估 
  • 医疗诊断:判断一个肿瘤是恶性还是良性 
  • 欺诈检测:判断一笔银行的交易是否涉嫌欺诈 
  • 网页分类:判断网页的所属类别,财经或者是娱乐

2、什么是KNN

kNN(k-Nearest Neighbor Classification),即K-近邻分类算法

近朱者赤,近墨者黑

  • 一个样本在特征空间中,总会有k个最相似(即特征空间中最邻近)的样本。其中,大多数样本属于某一个类别,则该样本也属于这个类别。

  • 是理论上比较成熟的方法,也是最简单的机器学习算法之一。

在这里插入图片描述

行业应用:

  • 客户流失预测

  • 欺诈侦测等(更适合于稀有事件的分类问题)

3、计算步骤

  • 算距离:给定测试对象,计算它与训练集中的每个对象的距离

  • 找邻居:圈定距离最近的k个训练对象,作为测试对象的近邻

  • 做分类:根据这k个近邻归属的主要类别,来对测试对象分类

你还可以这样想 懒惰算法

  • 平时不好好学习,考试(对测试样本分类)时才临阵磨枪(临时去找k个近邻)。
  • 懒惰的后果:模型简单,计算开销大。

1. 算距离

距离越近应该意味着这两个点属于一个分类的可能性越大。

•计算的距离衡量包括欧式距离、夹角余弦等。

•欧式距离:

在这里插入图片描述

典型的距离定义
在这里插入图片描述

2. 找邻居

由哪几个(K)已知样本决定测试样本类别?

在这里插入图片描述

3. 做分类

  • 投票决定:少数服从多数;

  • 加权投票法:根据距离的远近,距离越近则权重越大(权重为距离平方的倒数)。

4、算法流程

  • 计算已知类别数据集中的点与当前点之间的距离;

  • 按照距离递增次序排序;

  • 选取与当前点距离最小的k个点;

  • 确定前k个点所在类别对应的出现频率;

  • 返回前k个点出现频率最高的类别作为当前点的预测分类。

5、KNN分类器主要参数

在sklearn库中,可以使用sklearn.neighbors.KNeighborsClassifier 创建一个K近邻分类器,主要参数有:

  • n_neighbors :用于指定分类器中K的大小(默认值为5,注意与 kmeans的区别)
  • weights :设置选中的K个点对分类结果影响的权重(默认值为平均 权重“uniform”,可以选择“distance”代表越近的点权重越高, 或者传入自己编写的以距离为参数的权重计算函数)

它的主要参数还有:

  • algorithm:设置用于计算临近点的方法,因为当数据量很大的情况 下计算当前点和所有点的距离再选出最近的k各点,这个计算量是很 费时的,所以(选项中有ball_tree、kd_tree和brute,分别代表不 同的寻找邻居的优化算法,默认值为auto,根据训练数据自动选择)

6、KNN的优点与缺点

优点

  1. 简单,易于理解,易于实现,无需估计参数,无需训练
  2. 适合对稀有事件进行分类(例如当流失率很低时,比如低于0.5%,构造流失预测模型)
  3. 特别适合于多分类问题(multi-modal,对象具有多个类别标签),例如根据基因特征来判断其功能分类,kNN比SVM的表现要好

缺点

  1. 对测试样本分类时的计算量大,内存开销大,评分慢
  2. 可解释性较差,无法给出决策树那样的规则

7、python实现

  • sklearn库中提供KNeighborsClassifier实现kNN算法,此外,还提供RadiusNeighborsClassifier(非均匀采样时比较合适,以半径为选取方法)做最近邻分类
 sklearn.neighbors.KNeighborsClassifier(n_neighbors=5   #邻居数,默认为5
 , weights='uniform'    #用于预测的权重方法
 , algorithm='auto'     #用于计算最近邻的算法(ball_tree、kd_tree、brute、auto)
 , leaf_size=30         #传递给BallTree 或KDTree 叶大小
 , p=2                  #闵可夫斯基距离参数
 , metric='minkowski'   #用于树的度量距离
 , metric_params=None   #度量参数
 , **kwargs)

from sklearn.neighbors import KNeighborsClassifier

8、KNN分类实例

导入相关库,设置参数

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

plt.style.use("seaborn-darkgrid")
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False
plt.rcParams["font.size"] = 12

读取数据,进行训练预测

iris = load_iris()
X = iris.data[:, :2]
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)
# n_neighbors:邻居的数量。
# weights:权重计算方式。可选值为uniform与distance。
#    uniform:所有样本统一权重。
#    distance:样本权重与距离成反比。
knn = KNeighborsClassifier(n_neighbors=3, weights="uniform")
knn.fit(X_train, y_train)
y_hat = knn.predict(X_test)
print(classification_report(y_test, y_hat))

分类评分如下:
在这里插入图片描述
可视化分类效果(全部代码可在GitHub下载):
在这里插入图片描述

9、拓展:网格交叉验证,寻找效果最好的超参数组合

网格交叉验证,寻找效果最好的超参数组合

from sklearn.model_selection import GridSearchCV

knn = KNeighborsClassifier()
# 定义需要尝试的超参数组合。
grid = {"n_neighbors": range(1, 11, 1), "weights": ['uniform', 'distance']}
# estimator:评估器,即对哪个模型调整超参数。
# param_grid:需要检验的超参数组合。从这些组合中,寻找效果最好的超参数组合。
# scoring:模型评估标准。
# n_jobs:并发数量。
# cv:交叉验证折数。
# verbose:输出冗余信息,值越大,输出的信息越多。
gs = GridSearchCV(estimator=knn,
                  param_grid=grid,
                  scoring="accuracy",
                  n_jobs=-1,
                  cv=5,
                  verbose=10,
                  iid=True)
gs.fit(X_train, y_train)

在这里插入图片描述
获得最好超参数信息

# 最好的分值。
print(gs.best_score_)
# 最好的超参数组合。
print(gs.best_params_)
# 使用最好的超参数训练好的模型。
print(gs.best_estimator_)

在这里插入图片描述
模型评估

estimator = gs.best_estimator_
y_hat = estimator.predict(X_test)
print(classification_report(y_test, y_hat))
print(estimator.score(X_test,y_test))

在这里插入图片描述

10、KNN的使用经验

在实际使用时,我们可以使用所有训练数据构成特征 X 和标签 y,使用 fit() 函数进行训练。在正式分类时,通过一次性构造测试集或者一个一个输入 样本的方式,得到样本对应的分类结果。
有关K 的取值:

  • 如果较大,相当于使用较大邻域中的训练实例进行预测,可以减小估计误差, 但是距离较远的样本也会对预测起作用,导致预测错误。
  • 相反地,如果 K 较小,相当于使用较小的邻域进行预测,如果邻居恰好是噪 声点,会导致过拟合。
  • 一般情况下,K 会倾向选取较小的值,并使用交叉验证法选取最优 K 值。(见拓展)

全部代码我将放在GitHub上,需要的小朋友们可自行下载: GitHub

前文回顾:
机器学习笔记 – 1、认识机器学习
机器学习笔记 – 2、回归分析及python实现