c++ - 在预期下执行的随机森林

标签 c++ machine-learning weka random-forest decision-tree

我正在学习决策树算法并引用 Weka 中的 RF 实现了一个随机森林。我使用相同的数据集测试了我的实现和 weka 实现(在默认设置下)。然而,我的精度比 Weka 3.8 版(通过“train-first1000.arff”训练集和“dev-first1000.arff”测试集获得)获得的精度低约 5%。

我使用的 arff 格式数据集是来自 IMDb 的电影评论。对于每个实例,它都包含一些最常用词的频率,并标有“P”(正面)或“N”(负面)标签。

为了比较,我在 Weka 随机森林中使用了默认设置(100 棵树,log() + split 时考虑的 1 个特征,没有装袋等)

这是使用默认设置的 Weka 结果和我使用相同设置的结果(100 棵树,拆分期间考虑了 10 个随机特征):

Weka results and my results

首先,我认为我的数据导入器中存在错误。然后我检查了我的导入器并与 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实现。

10 个特征(100 棵树,拆分时要考虑的 4 个特征): 10 features, 100 trees

50 个特征(100 棵树,分割时要考虑的 6 个特征): 50 features, 100 trees

为了对结果进行一些组织并使其在随机化引起的变化方面更具说服力,我将它们分组到下表中(总共 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 上用随机树测试它,考虑了拆分期间的所有特征。然后我把这棵树可视化,和我的树对比,发现根节点上选择的 split 点和我的不一样,看来是我的信息增益计算有误。最后我发现有一个类型错误将 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   |
------------------------------------------------------------

感谢所有的回答和帮助。

最佳答案

(几乎)相同学习算法的两个实现在许多方面将存在主要差异。这引入了一个主要差异,即相同的数据集将从其他类似的高级机器学习过程中收到略有不同的结果。

事件如果实现完全一样,结果不保证完全一样。证明这一点的最佳案例是机器学习学习者的随机森林类:

随机森林是高度随机树的布雷曼森林

注意随机这个词。

如上评论所述,即使读者可能不会对其他实现的差异感兴趣,但随机森林的本质要求随机化——作为一种重复使用的工具——在处理过程中发生.

严格的研究需要使用可重复的实验,因此随机森林学习器通常允许为基础 RNG(随机数生成器)提供明确提供的 seed 值).

在相同的 DataSET 上测试相同的 RandomForest .fit() 方法>,但提供不同的 seed 值会在结果 (im)-precision 中产生一定量的差异,在其他方面基本上相同的过程重复。提供相同的 seed 值应该提供相同的结果(当且仅当,以防万一没有其他主机共存进程损坏随机森林内部使用的 RNG 工厂的临时状态生成阶段)。

enter image description here

好消息是,随着集成的增长,主方差的数量减少了 10% 以上(树的数量越少,主 RNG 引入的方差越低) .

所以 4% ~ 6% 是 RF 这类现象的可及范围。

enter image description here

Z 轴 显示了随机森林集成方法增加的预测性能+ 减少的主方差量(由不同的RNG( seed ) ) 叠加在预测上。

X 轴(向右运行)携带N_trees

Y 轴(向左运行)带有 seed-序号 ~ 100 个不同的显式 seed 值(从 开始aBASE, aBASE+1, +2, +3, ..., +99 )


结语

鉴于 OP,您可以通过在相同的 DataSET 上重新运行您的 RF-learner 实现来重新测试您自己的 RNG-seed 依赖性实现以接收在您的[ Your-Learner, DataSET, ( Your-RNG, seed ) ](现在)-确定性系统上对这种现象进行定量评估。

如果您可以对[ Weka-Learner, DataSET, ( Weka-RNG, seed ) ] complex 执行相同的测试,您将对这个主要景观有更清晰的了解。

关于c++ - 在预期下执行的随机森林,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41208588/

相关文章:

python - 超参调参时简单参数是否也会改变

java - Weka 没有发现主类错误

machine-learning - 反向传播神经网络中的最优特征实例比

c++ - 在现代 C++ 中使用模板替换函数指针数组

c++ - 将参数传递给通用 lambda 时复制构造函数不正确

c++ - pygraphviz 的 Python 3 pip 安装失败, "Microsoft Visual C++ is required",已安装 Visual Studio 2017

python - 如何连接列表数据类型和 int32 数据类型?

java - 如何避免使用@SuppressWarnings?

model - 如何使用这个 smoreg 模型手动预测 future 价格?

c++ - 在链表的末尾插入一个节点