机器学习系列(二)ML经典十大算法之一:决策树算法--从代码和统计学角度谈谈cs是如何预测你的行为

写在前面: 我是「nicedays」,一枚喜爱做特效,听音乐,分享技术大数据开发猿。这名字是来自world order乐队的一首HAVE A NICE DAY。如今,走到现在很多坎坷和不顺,如今终于明白nice day是需要自己赋予的。
白驹过隙,时光荏苒,珍惜当下~~
写博客一方面是对自己学习的一点点总结及记录,另一方面则是希望能够帮助更多对大数据感兴趣的朋友。如果你也对 大数据与机器学习感兴趣,可以关注我的动态 https://blog.csdn.net/qq_35050438,让我们一起挖掘数据与人工智能的价值~

ML经典十大算法之一:决策树算法:

既可以做分类也可以做回归,

是一种不断通过判断你的个人特征来完成预测你对某件事做某种操作的概率的ML算法。

一:如何构建树:

把你的特征做为树节点,而把你对特征的不同情况而做出的不同反应作为分支路径。

1):树的起源:根节点如何选择?

根节点应该选择更好能切分数据得特征

衡量标准:信息熵与信息增益
  • 信息量

在数学上:
当一件事是不太可能发生的时候,我们获取的信息量较大
当一件事是极有可能发生的时候,我们获取的信息量较小

例如:
1.特朗普其实是中国的卧底 (这个信息量就比较大)
2.特朗普是zz (相比之下这个信息量几乎为0)

当事件L的x特征产生的事件与y特征产生的事件不相关时:(x特征与y特征独立同分布,下面我们把x特征产生的事件简写为x事件)

我们获取x和y事件的信息量总和 = x事件信息量+y事件信息量
h ( X , Y ) = h ( X ) + h ( Y ) h(X,Y) = h(X) + h(Y)
由于x,y事件独立:

x,y事件同时发生的概率 = x事件概率*y事件概率

P ( X Y ) = P ( X ) P ( Y ) l o g 2 P ( X Y ) = l o g 2 P ( X ) + l o g 2 P ( Y ) P(XY) = P(X) * P(Y) \\log_2P(XY)= log_2P(X) + log_2P(Y)

对比两式:

P(X)概率在0到1内log后为负数,(常理信息量h(X)应为正数)

所以我们需要将在公式前添负号。

至于log以谁为底,计算机中一般以2(bit)为底,机器学习中一般以e为底。

信息的量度应该依赖于概率分布,
所以说信息量h(X)应该是概率P(X)的单调递减函数。

所以事件X单个随机变量xi的信息量拟合成函数为:
h ( X ) = l o g 2 P ( x i ) h(X)= -log_2P(x_i)

  • 信息熵:

熵是随机变量得不确定性得度量

换言之:信息熵是对某个事件里面所包含的信息的混乱程度`

数学上:考虑事件X中随机变量xi的所有取值取平均(期望处理)

生活中:针对事件X有有关事件X的所有特征假设有n个,需要将其全部考虑进去
H ( X ) = i = 1 n p ( x i ) l o g 2 P ( x i ) 整个事件的信息熵:H(X)= -\sum_{i=1}^np(x_i)log_2P(x_i)

tips:信息熵刚好与信息量不同,不确定性越大熵值也就越大,

所以很明显,当概率为0.5的时候,事件的不确定性最大,

而这个事件无论是一定会发生还是不可能发生,它的信息熵都比较低。

求整个数据集的信息熵代码附上:

#  度量数据集的无序程度(计算香农信息熵)
def calcShannonEnt(dataSet):  # calculate shannon entropy计算香农熵
    numEntries = len(dataSet)  # 得到数据集的长度,entries词典的条目的数量,就是词条的数量
    labelCounts = {}  # 新建空字典
    for featVec in dataSet:  # 遍历数组
        currentLabel = featVec[-1]  # currentLabel 存储dataSet最后一列的数值,最后一列是最终判断的结果
        if currentLabel not in labelCounts.keys():  # 如果数值不在字典里
            labelCounts[currentLabel] = 0  # 如果判断不在字典里,扩展字典,将currentLabel的键值设为0
        labelCounts[currentLabel] += 1  # 将currentLabel的键值加1,记录当前,类别的判断在字典里出现的次数
    shannonEnt = 0.0
    for key in labelCounts:
        prob = float(labelCounts[key]) / numEntries  # probablity 计算字典中的类别在数据集中出现的概率
        shannonEnt += -prob * log(prob, 2)  # 香农熵的计算公式,其实就是算所以信息的期望值
    return shannonEnt
  • 信息增益:

当信息和数据混乱程度越高,也就代表我们对于处理理清这件事的难度也就越大,可是一般我们遇到一件事情,或者说上级领导给安排一个任务,往往里面包含的信息是极其混乱的,剪不断理还乱,所以我们大家都希望能够将信息熵降低,将信息纯度提高,有效信息有序且多,排除无效信息。

我们把改变信息熵或者说改变信息纯度的行为称为 信息增益

信息熵我们都是希望将它降低,所以信息增益一般大于0

信息增益=分类前的信息熵 - 分类后的信息熵(条件熵)

tips:

从cs角度看:条件熵即为我们分类后剩下的数据,对其特征A划分后剩下的多种可能的数据集都再求一次信息熵。

从统计学看:条件熵即为我们是基于条件Y(Y有多种情况)后产生的情况,即
H ( X Y ) = x , y p ( x , y ) l o g 2 ( p ( x y ) ) H(X|Y) = -\sum_{x,y}p(x,y)log_2(p(x|y))

我们需要选取熵值较低,混乱度较高得特征作为划分点,

不断通过信息增益,来选取二节点,三节点,四节点…

代码附上:

#  按照特征划分数据集,它的方式是去除该value,并返回去除所有value的数据组合起来的数据集
def splitDataSet(dataSet, axis, value):  # 输入带划分数据集,axis列的属性,value(划分数据集的特征),我们需要返回的特征的值
    retDataSet = []  # 创建新的list对象,为了不修改原始数据集
    for featVec in dataSet:
        if featVec[axis] == value:  # 找出每个数据组的axis轴的属性里的特征值,让它和value特征判断,相等去除掉value
            # 下面这个操作其实就是找每个数据组的axis列上是value的,我就删掉
            reducedFeatVec = featVec[:axis]  # 0-axis-1
            reducedFeatVec.extend(featVec[axis + 1:])  # axis+1到最后,两个合并起来
            retDataSet.append(reducedFeatVec)  # 变成[[reducedFeatVec1],[reducedFeatVec2],[reducedFeatVec3]]
    return retDataSet  # 这里面存着所有被删过value的数据组,没有value的数据组没有放进去


#  选择最好的数据集划分方式
def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1
    baseEntropy = calcShannonEnt(dataSet)  # 计算数据集的香农熵
    bestInfoGain = 0.0; bestFeature = -1
    for i in range(numFeatures):
        # 这个写法是遍历数据集中的每一行,把其中的第i个数据取出来组合成一个列表,每个i列表示一种属性
        featList = [example[i] for example in dataSet]  # 把属性i中相同类别的元素划在一个列表,再合起来组合成一个大列表
        uniqueVals = set(featList)  # set可以去掉重复元素
        newEntropy = 0.0
        # 找列表的第一个列表里遍历,在遍历列表里的第二个列表,以此类推
        for value in uniqueVals:  # 把所有类别的所有特征全部划分一次数据集
            subDataSet = splitDataSet(dataSet, i, value)  # 给出在属性i下不同的特征值获取每种不同划分方式的数据集
            # 对应到决策树的情况就是每次选判断条件(特征值),通过这个判断条件之后剩下来的数据集的信息熵是否减少
            prob = len(subDataSet) / float(len(dataSet))  # 计算i轴属性i下有value的数据组占整个数据组的概率
            newEntropy += prob * calcShannonEnt(subDataSet)  # 计算不同划分方式的信息熵
        infoGain = baseEntropy - newEntropy  # 计算所有的信息增益
        if infoGain > bestInfoGain:  # 选出最大的信息增益
            bestInfoGain = infoGain
            bestFeature = i  # 找到最好的划分方式特征并返回
        return bestFeature

2):切分特征做分支路径:

根据特征分类,每一种类别作为一种路径

**将连续值离散化:**二分法,范围法

二:决策树算法种类:

  • ID3:信息增益

    • 缺点:当有id编号时,它就变成信息增益得最优解,然而id来划分是不科学的,因为这种分类得不到任何有用的信息
  • C4.5:信息增益率(信息增益/自身熵值)

    特征A对训练数据集D的信息增益比定义为其信息增益与训练数据D关于特征A的值的熵HA(D)之比

    g R ( D , A ) = H ( D ) H ( D A ) H A ( D ) g_R(D,A)=\frac{H(D)-H(D|A)}{H_A(D)}

  • CART:使用GINI系数来当作衡量标准

    GINI系数:
    G i n i ( p ) = k = 1 K p k ( 1 p k ) = 1 k = 1 K p k 2 Gini(p)=\sum_{k=1}^Kp_k(1-pk) = 1-\sum_{k=1}^Kp_k^2

三:决策树剪枝策略:

为什么要剪枝?

决策树过拟合风险很大,

理论上完全分得开树,每个叶子节点就一个数据,这样就不好,数据分化能力太差

预剪枝:

在建立决策树边遍历边剪枝-实用

  • 限制深度(限制了特征数)
  • 限制叶子节点个数
  • 限制叶子节点样本数(叶子节点里样本<阈值不在分裂)
  • 限制信息增益量(差值到达多少了就不再分裂)

后剪枝:

在建立决策树后来进行剪枝操作

  • 通过一定得衡量标准
    C α ( T ) = C ( T ) + α × T l e a f C_α(T)=C(T)+α\times|T_{leaf}|--叶子节点越大,损失越大

猜你喜欢

转载自blog.csdn.net/qq_35050438/article/details/108298006