机器学习基础算法(5)

机器学习基础算法(5),第1张

机器学习基础算法(5) 5、决策树 5.1 决策树简介 5.1.1 决策树概念

决策树是一种基本的分类和回归方法,用于分类主要是借助每一个叶子节点对应一种属性判定,通过不断的判定导出最终的决策;用于回归则是用均值函数进行多次二分,用子树中数据的均值进行回归。

决策树算法中,主要的步骤有:特征选择,建树,剪枝。接下来将介绍三种典型的决策树算法:ID3,C4.5,CART。

5.1.2 优缺点

优点:

可解释性好,易可视化 ,特征工程中可用特征选择。样本复杂度O(log(n)),维度灾难。

缺点:

易过拟合,学习最优模型N-P难,贪心搜索局部最优。虽然是非线性模型,但不支持异或逻辑。数据不均衡时不适合决策树。决策属性不可逆。 5.2 特征选择

对于决策树而言,每一个非叶子节点都是在进行一次属性的分裂,选择最佳的属性,把不同属性值的样本划分到不同的子树中,不断循环直到叶子节点。其中,如何选择最佳的属性是建树的关键,决策树的一个特征选择的指导思想是熵减思想。

5.2.1 信息增益

为了更清楚的理解信息增益这个概念,我们需要先来了解下信息论中的信息熵,以及条件熵的概念。

熵是一种对随机变量不确定性的度量,不确定性越大,熵越大。

假设离散随机变量Y的概率分布为P(Y),则其熵为:

 其中熵满足不等式0≤H(Y)≤log|Y|。

在进行特征选择时尽可能的选择在属性X确定的条件下,使得分裂后的子集的不确定性越小越好(各个子集的信息熵和最小),即P(Y|X)的条件熵最小。

 

其中  是表示属性 X 取值为 i 构成的子集。

信息增益表示的就是在特征 X 已知的条件下使得类别 Y 的不确定性减少的程度。即为特征 X 对训练数据集 D 的信息增益为:

 

用信息增益来进行特征选择,的确可以选择出那些对于类别敏感的特征。

值得注意的是,信息增益没有考虑属性取值的个数的问题。因为划分的越细,不确定性会大概率越小,因此信息增益倾向于选择取值较多的特征。

如对于数据表中主键这样的属性,用信息增益进行属性选择,那么必然会导致信息增益率最大,因为主键与样本是一一对应关系,而这样做分类是无意义的,即信息增益不考虑分裂后子集的数目问题。

5.2.2 信息增益比

信息增益偏向于选择特征值取值较多的特征,而信息增益比通过将训练集关于特征 X 的信息熵作为分母来限制这种倾向。

信息增益比定义为信息增益比上特征 X 的信息熵:

5.2.3 基尼系数 

基尼指数特征选择准则是CART分类树用于连续值特征选择,其在进行特征选择的同时会决定该特征的最优二分阈值。基尼指数是直接定义在概率上的不确定性度量:

 可以看出,基尼指数与信息熵的定义极为一致。

5.2.4 最小均方差

最小均方差应用于回归树,回归问题一般采用最小均方差作为损失。在特征选择的同时会测试不同的二分阈值的最小均方误差,选择最有的特征和阈值:

其中  是第 i 个模型的回归值。 

特征选择准则对比:

ID3采用信息增益,C4.5采用信息增益率,CART分类采用基尼指数,CART回归采用最小均方误差;信息增益,信息增益率,基尼指数都是用于分类树,最小均方误差用于回归树;信息增益,信息增益率同样可以处理连续值得情况,一般来讲连续值的处理只作二分,所以CART回归是一个标准的二叉树形式。 5.3 建树 5.3.1 ID3

 使用信息增益作为不纯度,核心思想是以信息增益度量属性选择,选择分裂后的信息增益最大的,也就是熵在分裂前后差值最大的属性进行分裂。

根据log(x)的函数可知,p值越小,熵越大,所以当分组完全是会出现p=0此时熵最大,概率为0说明已经最纯了。
学习数据挖掘技术的最好方法是找到详细案例和看懂计算过程。有时算法虽然不难,但公式表达很难理解。

表中S、M和L分别表示小、中和大。
设L、F、H和R表示日志密度、好友密度、是否使用真实头像和账号是否真实,试用ID3算法构造决策树。
解:设D为10个样本集,其中决策属性(真实账户/R)有7个YES、3个NO。决策属性信息熵为:

如果按照日志密度来分类:计算日志密度熵值,日志密度分为3类S,L,M
其中L分类,样本总数10,L类3,L类中假账号0 真实账号3

所以:
所以gain(L) = 0.876-0.603 = 0.273
同理计算好友密度信息增益:

计算真实头像的信息增益:

 

因为好友密度(F)具有最大的信息增益(好友密度信息熵最小,最易分割),所以第一次分裂选择好友密度F为分裂属性(实际中如果特征非常多是随机选择一些特征然后计算后选取的不能遍历所有情况),分裂后的结果如下:

图中:按好友密度(F)分割树,水平M和L为单一水平决策属性分支(树叶),没有必要继续分割。水平S包含决策属性的不同水平,应该继续分割。待分割决策信息表为:

此时,设D为4个样本集,其中决策属性(真实账户/R)有1个YES、3个NO。决策属性信息熵为:

日志密度属性期望信息熵为:

真实头像属性期望信息熵为:

因为日志密度(L)具有最大的信息增益,所以第二次分裂选择日志密度(L)为分裂属性,分裂后的结果如下图表示:

 

图中,日志密度为M时,无法做出判断、也无法继续进行分裂。至此,决策树构建完毕。

设某人在SNS社区中的好友密度为L或M,无论其它属性水平取值如何,均可判定为是真实账户;如果某人在SNS社区中的好友密度为S、日志密度也为S,可判定为是虚假账户;如果某人在SNS社区中的好友密度为S、日志密度为M,应根据真实头像信息做出判断,由于样本过少,无法继续进行。

5.3.2 C4.5算法

使用信息增益率作为不纯度。
ID3算法是决策树的一个经典的构造算法,但ID3算法也存在一些问题,比较突出的缺陷是信息增益的计算依赖于特征水平较多的特征,而属性取值最多的属性并不一定最优。例如,投掷一枚分币和一个色子这两个随机试验,所有可能的期望信息熵为:

通过信息熵的定义可知,在给定特征水平数条件下,各水平发生概率相等(如掷筛子6个数字发生的概率都为1/6。期望信息熵最大。所以,当决策信息中某个变量特征水平较多时,ID3算法按信息增益指标往往会选择该变量或属性做为分割节点。
I、“分裂信息”公式
C4.5算法首先定义了“分裂信息”,其定义可以表示成:

II、增益率

III、分裂信息和增益率计算实例
在ID3算法案例中(SNS社区中不真实账号检测),决策属性信息熵为:

把决策属性替换成其它属性,即为各属性分裂信息熵。
日志密度分裂信息:

好友密度分裂信息:

真实头像分裂信息:

由前面ID3算法已知,

各属性增益率为,

由上述计算结果可知“好友密度”在属性中具有最大的信息增益比,取“好友密度”为分割属性,引出一个分枝,样本按此划分。对引出的每一个分枝再用此分类法进行分类,再引出分枝。
某属性的信息增益除以分裂信息,消除了属性水平数量多少的影响,使得分裂属性的选择更加合理。

5.3.3 CART算法

使用基尼系数函数作为不纯度。
决策树方法是会把每个特征都试一遍,然后选取那个,能够使分类分的最好的特征,也就是说将A属性作为父节点,产生的纯度增益(GainA)要大于B属性作为父节点,则A作为优先选取的属性。既可以做分类,也可以做回归。只能形成二叉树。
分支条件:二分类问题

分支方法:对于连续特征的情况:比较阈值,高于某个阈值就属于某一类,低于某个阈值属于另一类。对于离散特征:抽取子特征,比如颜值这个特征,有帅、丑、中等三个水平,可以先分为帅和不帅的,不帅的里面再分成丑和中等的。

得分函数(y):就是上面提到的gt(x),对于分类树取得是分类最多的那个结果(也即众数),对于回归树取得是均值。

损失函数:其实这里的损失函数,就是分类的准则,也就是求最优化的准则

对于分类树(目标变量为离散变量):同一层所有分支假设函数的基尼系数的平均。

对于回归树(目标变量为连续变量):同一层所有分支假设函数的平方差损失

对于分类树(目标变量为离散变量):使用基尼系数作为分裂规则。比较分裂前的gini和分裂后的gini减少多少,减少的越多,则选取该分裂规则,这里的求解方法只能是离散穷举。关于基尼系数,可以参考周志华的西瓜书决策树那章,讲得比较简洁,也比较易懂。“直观来说,(数据集D的基尼系数)Gini(D)反映了从数据集D中随机抽取两个样本,其类别标记不一致的概率,因此Gini(D)越小,则数据集D的纯度越高。”

具体这个的计算,我觉得有例子才好理解,下面这个红绿球的例子很好的说明了,如何根据损失函数最小(也就是基尼系数最小)来选取分裂规则。最后GIINs2更小,因此选择它作为分类规则。

对于回归树(目标变量为连续变量):使用最小方差作为分裂规则。只能生成二叉树。

缺点补充几点,不是很稳点,数据变化一点,你的树就会发生变化;没有考虑变量之间相关性,每次筛选都只考虑一个变量(因此不需要归一化);只能线性分割数据;贪婪算法(可能找不到最好的树)。优点也补充三点,同时可以处理分类变量和数值变量(但是可能决策树对连续变量的划分并不合理,所以可以提前先离散化);可以处理多输出问题;另外决策树不需要做变量筛选,它会自动筛选;适合处理高维度数据。


5.3.4 三种方法对比

ID3的缺点,倾向于选择水平数量较多的变量,可能导致训练得到一个庞大且深度浅的树;另外输入变量必须是分类变量(连续变量必须离散化);最后无法处理空值。
C4.5选择了信息增益率替代信息增益。
CART以基尼系数替代熵;最小化不纯度而不是最大化信息增益。

5.4 剪枝 如何停止分裂:

下面这六种情况都会停止分裂。
其中第一种其实属于树的完全长成,但这会出现过拟合问题,所有之前很流行一种抑制这种情况的方法,叫树的剪枝

树的剪枝分为预剪枝和后剪枝,预剪枝,及早的停止树增长控制树的规模,方法可以参考如下6点停止分类的条件。后剪枝在已生成过拟合决策树上进行剪枝,删除没有意义的组,可以得到简化版的剪枝决策树,包括REP(设定一定的误分类率,减掉对误分类率上升不超过阈值的多余树)、PEP,还有一种CCP,即给分裂准则—基尼系数加上惩罚项,此时树的层数越深,基尼系数的惩罚项会越大。

5.5 sklearn决策树 5.5.1 API

 决策树结构、本地保存:

dot可视化需要安装 graphviz,windows安装教程参考以下链接

 https://www.cnblogs.com/onemorepoint/p/8310996.html

5.5.2举例(泰坦尼克号乘客生存分类模型)

csv文件下载:

泰坦尼克决策树csv文件-机器学习文档类资源-CSDN下载

在泰坦尼克号和titanic2数据帧描述泰坦尼克号上的个别乘客的生存状态。在泰坦尼克号的数据帧不包含从剧组信息,但它确实包含了乘客的一半的实际年龄。关于泰坦尼克号旅客的数据的主要来源是百科全书Titanica。这里使用的数据集是由各种研究人员开始的。其中包括许多研究人员创建的旅客名单,由Michael A. Findlay编辑。

我们提取的数据集中的特征是票的类别,存活,乘坐班,年龄,登陆,home.dest,房间,票,船和性别。乘坐班是指乘客班(1,2,3),是社会经济阶层的代表。 其中age数据存在缺失。

from sklearn.datasets import load_iris, fetch_20newsgroups, load_boston
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.ensemble import RandomForestClassifier
import pandas as pd

def decision():
    """
    决策树对泰坦尼克号进行预测生死
    :return: None
    """
    # 获取数据
    titan = pd.read_csv("data.csv")
    # # 处理数据,找出特征值和目标值
    x = titan[['Pclass', 'Age', 'Sex']]

    y = titan['Survived']

    print(x)
    # 缺失值处理,以平均值填充到缺失值
    x['Age'].fillna(x['Age'].mean(), inplace=True)

    # 分割数据集到训练集合测试集
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)

    # 进行处理(特征工程)特征-》类别-》one_hot编码
    dict = DictVectorizer(sparse=False)

    x_train = dict.fit_transform(x_train.to_dict(orient="records"))

    print(dict.get_feature_names())

    x_test = dict.transform(x_test.to_dict(orient="records"))

    print(x_train)
    # 用决策树进行预测
    dec = DecisionTreeClassifier()

    dec.fit(x_train, y_train)

    # 预测准确率
    print("预测的准确率:", dec.score(x_test, y_test))

    # 导出决策树的结构
    export_graphviz(dec, out_file="./tree.dot", feature_names=['Age', 'Pclass',  'Sex=female', 'Sex=male'])


    return None


if __name__ == "__main__":
    decision()

可视化结果:

5.5.3 决策树优缺点及改进

优点:

(1)简单的理解和解释,树木可视化。

(2)需要很少的数据准备,其他技术通常需要数据归一化。

 缺点:

(1)决策树学习者可以创建不能很好地推广数据的过于复杂的树,这被称为过拟合。

(2)决策树可能不稳定,因为数据的小变化可能会导致完全不同的树被生成。

改进:

(1)减枝cart算法

(2)随机森林

5.6 集成学习方法—随机森林

集成学习通过建立几个模型组合的来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成单预测,因此优于任何一个单分类的做出预测。

5.6.1 随机森林概念

定义:在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。

尽管有剪枝等等方法,一棵树的生成肯定还是不如多棵树,因此就有了随机森林,解决决策树泛化能力弱的缺点。(可以理解成三个臭皮匠顶过诸葛亮)

而同一批数据,用同样的算法只能产生一棵树,这时Bagging策略可以帮助我们产生不同的数据集。Bagging策略来源于bootstrap aggregation:从样本集(假设样本集N个数据点)中重采样选出Nb个样本(有放回的采样,样本数据点个数仍然不变为N),在所有样本上,对这n个样本建立分类器(ID3C4.5CARTSVMLOGISTIC),重复以上两步m次,获得m个分类器,最后根据这m个分类器的投票结果,决定数据属于哪一类。

随机森林在bagging的基础上更进一步:

    样本的随机:从样本集中用Bootstrap随机选取n个样本

    特征的随机:从所有属性中随机选取K个属性,选择最佳分割属性作为节点建立CART决策树(泛化的理解,这里面也可以是其他类型的分类器,比如SVM、Logistics)

    重复以上两步m次,即建立了m棵CART决策树

    这m个CART形成随机森林,通过投票表决结果,决定数据属于哪一类(投票机制有一票否决制、少数服从多数、加权多数)

关于调参:

1.如何选取K,可以考虑有N个属性,取K=根号N

2.最大深度(不超过8层)

3.棵树

4.最小分裂样本

5.类别比例

5.6.2 随机森林API

 5.6.3 举例(泰坦尼克号乘客生存分类模型)
from sklearn.datasets import load_iris, fetch_20newsgroups, load_boston
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.ensemble import RandomForestClassifier
import pandas as pd

def decision():
    """
    决策树对泰坦尼克号进行预测生死
    :return: None
    """
    # 获取数据
    titan = pd.read_csv("data.csv")
    # # 处理数据,找出特征值和目标值
    x = titan[['Pclass', 'Age', 'Sex']]

    y = titan['Survived']

    print(x)
    # 缺失值处理,以平均值填充到缺失值
    x['Age'].fillna(x['Age'].mean(), inplace=True)

    # 分割数据集到训练集合测试集
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)

    # 进行处理(特征工程)特征-》类别-》one_hot编码
    dict = DictVectorizer(sparse=False)

    x_train = dict.fit_transform(x_train.to_dict(orient="records"))

    print(dict.get_feature_names())

    x_test = dict.transform(x_test.to_dict(orient="records"))

    print(x_train)

    # 随机森林进行预测 (超参数调优)
    rf = RandomForestClassifier()
    #n_estimators:森林里树木数量;max_depth:每个决策树最大特征数量
    # param = {"n_estimators": [120, 200, 300, 500, 800, 1200], "max_depth": [5, 8, 15, 25, 30]}

    # 网格搜索与交叉验证
    gc = GridSearchCV(rf, param_grid=param, cv=2)

    gc.fit(x_train, y_train)

    print("准确率:", gc.score(x_test, y_test))

    print("查看选择的参数模型:", gc.best_params_)

    return None


if __name__ == "__main__":
    decision()
 5.6.4 随机森林优点

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5712180.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存