Desc: 从上而下找到叶节点,用测试数据集来判断将这些叶节点合并是否能降低测试误差 Args: tree -- 待剪枝的树 testData -- 剪枝所需要的测试数据 testData Returns: tree -- 剪枝完成的树
(tree, testData)
| 201 | |
| 202 | # 检查是否适合合并分枝 |
| 203 | def prune(tree, testData): |
| 204 | """ |
| 205 | Desc: |
| 206 | 从上而下找到叶节点,用测试数据集来判断将这些叶节点合并是否能降低测试误差 |
| 207 | Args: |
| 208 | tree -- 待剪枝的树 |
| 209 | testData -- 剪枝所需要的测试数据 testData |
| 210 | Returns: |
| 211 | tree -- 剪枝完成的树 |
| 212 | """ |
| 213 | # 判断是否测试数据集没有数据,如果没有,就直接返回tree本身的均值 |
| 214 | if shape(testData)[0] == 0: |
| 215 | return getMean(tree) |
| 216 | |
| 217 | # 判断分枝是否是dict字典,如果是就将测试数据集进行切分 |
| 218 | if (isTree(tree['right']) or isTree(tree['left'])): |
| 219 | lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal']) |
| 220 | # 如果是左边分枝是字典,就传入左边的数据集和左边的分枝,进行递归 |
| 221 | if isTree(tree['left']): |
| 222 | tree['left'] = prune(tree['left'], lSet) |
| 223 | # 如果是右边分枝是字典,就传入左边的数据集和左边的分枝,进行递归 |
| 224 | if isTree(tree['right']): |
| 225 | tree['right'] = prune(tree['right'], rSet) |
| 226 | |
| 227 | # 上面的一系列操作本质上就是将测试数据集按照训练完成的树拆分好,对应的值放到对应的节点 |
| 228 | |
| 229 | # 如果左右两边同时都不是dict字典,也就是左右两边都是叶节点,而不是子树了,那么分割测试数据集。 |
| 230 | # 1. 如果正确 |
| 231 | # * 那么计算一下总方差 和 该结果集的本身不分枝的总方差比较 |
| 232 | # * 如果 合并的总方差 < 不合并的总方差,那么就进行合并 |
| 233 | # 注意返回的结果: 如果可以合并,原来的dict就变为了 数值 |
| 234 | if not isTree(tree['left']) and not isTree(tree['right']): |
| 235 | lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal']) |
| 236 | # power(x, y)表示x的y次方 |
| 237 | errorNoMerge = sum(power(lSet[:, -1] - tree['left'], 2)) + sum(power(rSet[:, -1] - tree['right'], 2)) |
| 238 | treeMean = (tree['left'] + tree['right'])/2.0 |
| 239 | errorMerge = sum(power(testData[:, -1] - treeMean, 2)) |
| 240 | # 如果 合并的总方差 < 不合并的总方差,那么就进行合并 |
| 241 | if errorMerge < errorNoMerge: |
| 242 | print "merging" |
| 243 | return treeMean |
| 244 | else: |
| 245 | return tree |
| 246 | else: |
| 247 | return tree |
| 248 | |
| 249 | |
| 250 | # 得到模型的ws系数:f(x) = x0 + x1*featrue1+ x3*featrue2 ... |
nothing calls this directly
no test coverage detected