决策树与K-近邻分类随堂笔记(二)

环境:pycharm
语言:python3.6
时间:2019-8-11
遗留问题:

  • [ √] cross_val_score()交叉验证的底层算法不了解,尤其是准确率
    在交叉验证时,并没有用到测试集。而是,比如5折验证,每次都是训练集的五分之一去验证,循环5次。参考:https://blog.csdn.net/mangobar/article/details/78501068
  • GridSearchCV调参和np.mean(cross_val_score(…))有点晕、
  • 随机森林后面还需要看看

引入包

import numpy as np
import os
import pandas as pd
import pydotplus
import matplotlib.pyplot as plt

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, StratifiedKFold   # 分割数据集用的包
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV, cross_val_score  # 模型调参利器,交叉验证
from sklearn.pipeline import Pipeline  # Pipeline可以将许多算法模型串联起来,比如将特征提取、归一化、分类组织在一起形成一个典型的机器学习问题工作流。
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_digits # 手写数字集

from io import StringIO  # 缓存

最近邻方法

最近邻方法也叫K-近邻或K-NN,是一种常见的分类方法。这个方法遵循紧密性假说:当样本之间的距离较好的满足我们设置的方法(或者说条件),我们就足够有理由认为它们属于同一类。
比如:在下面二分类中,我们足够有理由认为:绿球是属于蓝色球类而不是红色球类。这是因为绿球距离蓝球足够的近。

在这里插入图片描述
最近邻对测试集的数据进行分类,需要以下3步操作:

  • 计算训练集中每个样本之间的距离
  • 从训练集中选取K个距离(对测试数据)足够近的样本
    -测试样本的类别被认为和上一步中K个样本的类别相同

在回归问题中应用最近邻方法很简单,仅需将上述步骤做一个小小的改动:第三步不返回分类,而是返回一个数字,即目标变量在邻居中的均值或中位数。

这一方式的显著特点是它具有惰性:当需要对测试样本进行分类时,计算只在预测阶段进行。由于这种特点,最近邻方法事先并不基于训练样本创建模型,这与上文提到的决策树不同。决策树是基于训练集构建的,在预测阶段仅通过遍历决策树就可以实现快速地分类

最近邻的实际应用

  • K-NN可以作为一个模型的基线
  • 在 Kaggle 竞赛中,k-NN 常常用于构建元特征(即 k-NN 的预测结果作为其他模型的输入),或用于堆叠/混合。
  • 最近邻方法还可以扩展到推荐系统等任务中。
  • 在大型数据集上,常常使用逼近方法搜索最近邻

k-NN 分类/回归的效果取决于一些参数:

  • 邻居数 k。
  • 样本之间的距离度量(常见的包括 Hamming,欧几里得,余弦和 Minkowski距离)。注意,大部分距离要求数据在同一尺度下,例如「薪水」特征的数值在千级,「年龄」特征的数值却在百级,如果直接将他们丢进最近邻模型中,「年龄」特征就会受到比较大的影响。
  • 邻居的权重(每个邻居可能贡献不同的权重,例如,样本越远,权重越低)。

scikit-learn 的 KNeighborsClassifier 类

sklearn.neighbors.KNeighborsClassifier 类的主要参数为:

  • weights:可设为 uniform(所有权重相等),distance(权重和到测试样本的距离成反比),或任何其他用户自定义的函数。
  • algorithm(可选):可设为 brute、ball_tree、KD_tree、auto。若设为brute,通过训练集上的网格搜索来计算每个测试样本的最近邻;若设为 ball_tree 或KD_tree,样本间的距离储存在树中,以加速寻找最近邻;若设为 auto,将基于训练集自动选择合适的寻找最近邻的方法。
  • leaf_size(可选):若寻找最近邻的算法是 BallTree 或 KDTree,则切换为网格搜索所用的阈值。
  • metric:可设为 minkowski、manhattan、euclidean、chebyshev 或其他。
    警告:
    根据Nearest Neighbors算法,如果找到两个邻居,例如邻居k+1和k,他们有着一样的距离但是不一样的标签,最后的结果会根据训练数据的顺序来决定。

选择模型参数和交叉验证

机器学习算法的主要任务是可以「泛化」未曾见过的数据。由于我们无法立刻得知模型在新数据上的表现(因为还不知道目标变量的真值),因此有必要牺牲一小部分数据,来验证模型的质量,即将一小部分数据作为留置集。

通常采用下述两种方法之一来验证模型的质量:

留置法。保留一小部分数据(一般是 20% 到 40%)作为留置集,在其余数据上训练模型(原数据集的 60%-80%),然后在留置集上验证模型的质量。
交叉验证。最常见的情形是 k 折交叉验证,如下图所示。
在这里插入图片描述
在 k 折交叉验证中,模型在原数据集的 K-1K−1 个子集上进行训练(上图白色部分),然后在剩下的 1 个子集上验证表现,重复训练和验证的过程,每次使用不同的子集(上图橙色部分),总共进行 K 次,由此得到 K 个模型质量评估指数,通常用这些评估指数的求和平均数来衡量分类/回归模型的总体质量。

相比留置法,交叉验证能更好地评估模型在新数据上的表现。然而,当你有大量数据时,交叉验证对机器计算能力的要求会变得很高。

交叉验证是机器学习中非常重要的技术,同时也应用于统计学和经济学领域。它有助于我们进行超参数调优、模型比较、特征评估等其他重要操作。

应用样例:

在客户离网率预测任务中使用决策树和最近邻方法
首先读取数据至 DataFrame 并进行预处理。将 State 特征从 DateFrame 转移到单独的 Series 对象中。我们训练的第一个模型将不包括 State 特征,之后再考察 State 特征是否有用。

import pandas as pd

pd.set_option('display.max_columns', 100)
pd.set_option('display.width', 200)
pd.set_option('display.max_colwidth', 1000)


df = pd.read_csv('./telecom_churn.csv')
# print(df)
df['International plan'] = pd.factorize(df['International plan'])[0]
df['Voice mail plan'] = pd.factorize(df['Voice mail plan'])[0]
# print(df['Voice mail plan'])
df['Churn'] = df['Churn'].astype('int')
states = df['State']
y = df['Churn']
df.drop(['State', 'Churn'], axis=1, inplace=True)

print(df.head())

之后将数据集的 70% 划分为训练集(X_train,y_train),30% 划分为留置集(X_holdout,y_holdout)。留置集的数据在调优模型参数时不会被用到,在调优之后,用它评定所得模型的质量。

接下来,训练 2 个模型:决策树和 k-NN。一开始,我们并不知道如何设置模型参数能使模型表现好,所以可以使用随机参数方法,假定树深(max_dept)为 5,近邻数量(n_neighbors)为 10

X_train, X_holdout, y_train, y_holdout = train_test_split(df.values, y, test_size=0.3,
                                                          random_state=17)

tree = DecisionTreeClassifier(max_depth=5, random_state=17)
knn = KNeighborsClassifier(n_ne
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值