【发布时间】:2017-05-03 16:16:47
【问题描述】:
我正在学习决策树算法,并在 Weka 中实现了一个参考 RF 的随机森林。我使用相同的数据集测试了我的实现和 weka 实现(在默认设置下)。然而,我的准确率比 Weka 3.8 版获得的准确率低了约 5%(通过 'train-first1000.arff' 训练集和 'dev-first1000.arff' 测试集获得)。
我使用的 arff 格式数据集是来自 IMDb 的电影评论。对于每个实例,它都包含一些最常用词的频率,并标有“P”(表示肯定)或“N”(表示否定)。
为了比较,我在 Weka 随机森林中使用了默认设置(100 棵树,在拆分期间考虑 log() + 1 个特征,没有装袋等)
这是使用默认设置的 Weka 结果和我使用相同设置的结果(100 棵树,拆分期间考虑的 10 个随机特征):
首先我认为我的数据导入器中存在错误。然后我检查了我的导入器并与 python arff 导入器进行了比较,发现它们执行正确。
然后我查看了weka RF的源码: http://grepcode.com/file/repo1.maven.org/maven2/nz.ac.waikato.cms.weka/weka-dev/3.7.5/weka/classifiers/trees/RandomForest.java
并与我的仔细比较了不止一次,以确保实现是相同的。然而,我无法找到仍然存在 5% 差异的原因。
这是我的实现的链接:
https://github.com/YSZhuoyang/Parallelized-Random-Forests/tree/randomforests
更具体地说,训练算法的主要部分可以在“TreeBuilder.cpp”和“TreeBuilder.h”中找到。
更新:
我分别测试了10个特征数据和50个特征数据,我的实现得到的结果都低于weka实现。
50 个特征(100 个树,6 个在拆分过程中要考虑的特征):
为了稍微整理一下结果并使其在随机化引起的变化方面更具说服力,我将它们分组到下表中(总共 50 个特征,在拆分过程中考虑了 6 个随机特征,两个随机种子都设置为 1 ):
------------------------------------------------------------
| num total features | num trees | weka result | my result |
| 50 | 1 | 55.61 | 52.34 |
| 50 | 5 | 59.08 | 54.35 |
| 50 | 10 | 60.07 | 55.43 |
| 50 | 20 | 62.54 | 57.20 |
| 50 | 50 | 64.14 | 59.56 |
| 50 | 100 | 65.28 | 61.09 |
------------------------------------------------------------
这表明它不是由于随机化。
已解决:
我使用了 weka 提供的糖尿病数据集,它只有 8 个特征(遵循@alexeykuzmin0 给出的建议),并在 weka 上使用随机树对其进行了测试,考虑了拆分过程中的所有特征。然后我将树可视化并与我的树进行比较,发现根节点上选择的分裂点与我的不同,这似乎是我计算的信息增益错误。最后我发现有一个类型错误,将 double 类型的值转换为 int 类型,导致结果不准确。
一段代码:
// Compute entropy of children
for (const vector<unsigned int>& group : groups)
{
double entropyChild = ComputeEntropy( group );
// Before being corrected
// unsigned int numChildren = group.size();
// infoGain -= numChildren / numInstances * entropyChild;
// Corrected
double numChildren = group.size();
infoGain -= numChildren / (double) numInstances * entropyChild;
}
这是我和 weka 比较的更新版本:
------------------------------------------------------------
| num total features | num trees | weka result | my result |
| 50 | 1 | 55.61 | 55.34 |
| 50 | 5 | 59.08 | 58.73 |
| 50 | 10 | 60.07 | 60.86 |
| 50 | 20 | 62.54 | 62.97 |
| 50 | 50 | 64.14 | 64.68 |
| 50 | 100 | 65.28 | 65.35 |
------------------------------------------------------------
感谢所有回答和帮助。
【问题讨论】:
-
这对于这里的普通女孩/男人来说阅读量太大了。如果您希望有任何机会帮助您在此处发布实际代码,那么只有您现在认为导致差异的最小部分。
-
@kabanus 是的,我理解,但是我无法进一步缩小范围,因为我不确定问题出在哪里,对此感到抱歉。我唯一能指出的是类文件“TreeBuilder.cpp”,它可能是出现问题的地方。
-
尝试创建具有不同结果的最小数据集 - 如果您有一些错误,它可能会出现,或者只是一个包含 1-3 个对象的小数据集,这更容易调试
-
这个问题,无论对你的努力有多痛苦,都应该成为一个 [Verifiable ] MCVE 问题。可能已经重新阅读了关于如何最好地在 StackOverflow 上提出问题的建议 >>> stackoverflow.com/help/mcve 所以尝试隔离一个可重新测试的案例,将其与 implementation-source 和 DataSET 一起发布(和也许使用 Weka 预先计算的结果)来追查根本原因。仍然是一组相当高级的麻烦(让随机化差异只是要提到的一个)
标签: c++ machine-learning weka random-forest decision-tree