chooseBestSplit(用最佳方式切分数据集 和 生成相应的叶节点) Args: dataSet 加载的原始数据集 leafType 建立叶子点的函数 errType 误差计算函数(求总方差) ops [容许误差下降值,切分的最少样本数]。 Returns: bestIndex feature的index坐标 bestValue 切分的最优值 Raises:
(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4))
| 77 | # 1.用最佳方式切分数据集 |
| 78 | # 2.生成相应的叶节点 |
| 79 | def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)): |
| 80 | """chooseBestSplit(用最佳方式切分数据集 和 生成相应的叶节点) |
| 81 | |
| 82 | Args: |
| 83 | dataSet 加载的原始数据集 |
| 84 | leafType 建立叶子点的函数 |
| 85 | errType 误差计算函数(求总方差) |
| 86 | ops [容许误差下降值,切分的最少样本数]。 |
| 87 | Returns: |
| 88 | bestIndex feature的index坐标 |
| 89 | bestValue 切分的最优值 |
| 90 | Raises: |
| 91 | """ |
| 92 | |
| 93 | # ops=(1,4),非常重要,因为它决定了决策树划分停止的threshold值,被称为预剪枝(prepruning),其实也就是用于控制函数的停止时机。 |
| 94 | # 之所以这样说,是因为它防止决策树的过拟合,所以当误差的下降值小于tolS,或划分后的集合size小于tolN时,选择停止继续划分。 |
| 95 | # 最小误差下降值,划分后的误差减小小于这个差值,就不用继续划分 |
| 96 | tolS = ops[0] |
| 97 | # 划分最小 size 小于,就不继续划分了 |
| 98 | tolN = ops[1] |
| 99 | # 如果结果集(最后一列为1个变量),就返回退出 |
| 100 | # .T 对数据集进行转置 |
| 101 | # .tolist()[0] 转化为数组并取第0列 |
| 102 | if len(set(dataSet[:, -1].T.tolist()[0])) == 1: # 如果集合size为1,也就是说全部的数据都是同一个类别,不用继续划分。 |
| 103 | # exit cond 1 |
| 104 | return None, leafType(dataSet) |
| 105 | # 计算行列值 |
| 106 | m, n = shape(dataSet) |
| 107 | # 无分类误差的总方差和 |
| 108 | # the choice of the best feature is driven by Reduction in RSS error from mean |
| 109 | S = errType(dataSet) |
| 110 | # inf 正无穷大 |
| 111 | bestS, bestIndex, bestValue = inf, 0, 0 |
| 112 | # 循环处理每一列对应的feature值 |
| 113 | for featIndex in range(n-1): # 对于每个特征 |
| 114 | # [0]表示这一列的[所有行],不要[0]就是一个array[[所有行]],下面的一行表示的是将某一列全部的数据转换为行,然后设置为list形式 |
| 115 | for splitVal in set(dataSet[:, featIndex].T.tolist()[0]): |
| 116 | # 对该列进行分组,然后组内的成员的val值进行 二元切分 |
| 117 | mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal) |
| 118 | # 判断二元切分的方式的元素数量是否符合预期 |
| 119 | if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): |
| 120 | continue |
| 121 | newS = errType(mat0) + errType(mat1) |
| 122 | # 如果二元切分,算出来的误差在可接受范围内,那么就记录切分点,并记录最小误差 |
| 123 | # 如果划分后误差小于 bestS,则说明找到了新的bestS |
| 124 | if newS < bestS: |
| 125 | bestIndex = featIndex |
| 126 | bestValue = splitVal |
| 127 | bestS = newS |
| 128 | # 判断二元切分的方式的元素误差是否符合预期 |
| 129 | # if the decrease (S-bestS) is less than a threshold don't do the split |
| 130 | if (S - bestS) < tolS: |
| 131 | return None, leafType(dataSet) |
| 132 | mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue) |
| 133 | # 对整体的成员进行判断,是否符合预期 |
| 134 | # 如果集合的 size 小于 tolN |
| 135 | if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): # 当最佳划分后,集合过小,也不划分,产生叶节点 |
| 136 | return None, leafType(dataSet) |
no test coverage detected