【问题标题】:How do I calculate the value of information gain in order to reduce the floating-point approximation errors?如何计算信息增益值以减少浮点逼近误差?
【发布时间】:2013-02-18 23:22:25
【问题描述】:

我有一个数据集,其中包含一些属于 12 表示的两个类标签的特征。处理这个数据集是为了构建决策树:在树的构建过程中,我需要计算信息增益以找到数据集的最佳分区。

N1个特征关联到标签1N2个特征关联到标签2,那么可以用以下公式计算:

Entropy = - (N1/N)*log2(N1/N) - (N2/N)*log2(N2/N),其中 N = N1 + N2

为了获得信息增益,我需要计算三个熵值:

  • entropyBefore,即当前数据集划分前的熵;
  • entropyLeft,即分割后左分裂的熵;
  • entropyRight,即分区后右拆分的熵。

所以,信息增益等于entropyBefore - (S1/N)*entropyLeft - (S2/N)*entropyRight,其中S1是属于分裂1的类1的特征个数, S2是属于分裂2的类2的特征数。

如何计算信息增益值以减少浮点逼近误差?当我在信息增益必须为零的情况下应用上述公式时,计算值等于一个非常小的负值。

更新(示例代码)

double N = static_cast<double>(this->rows());   // rows count of the dataset

double entropyBefore = this->entropy();   // current entropy (before performing the split)

bool firstCheck = true;
double bestSplitIg;

for each possible split
{
    // ...

    pair<Dataset,Dataset> splitPair = split(...,...);
    double S1 = splitPair.first.rows();
    double S2 = splitPair.second.rows();

    double entropyLeft = splitPair.first.entropy();
    double entropyRight = splitPair.second.entropy();

    double splitIg = entropyBefore - (S1/N*entropyLeft + S2/N*entropyRight);
    if (firstCheck || splitIg > bestSplitIg)
    {
        bestSplitIg = splitIg;
        // ...

        firstCheck = false;
    }
}

【问题讨论】:

  • 我的第一个想法是不使用浮点数。
  • @TonyHopkinson:请解释一下你建议用什么更好的方法来计算没有浮点的 log2。
  • 请显示short, self-contained compilable example,其中包含演示问题的代码和数据。
  • 与浮点数相同,但结果表示不同,例如十进制。这是一个诡计的问题吗?
  • @TonyHopkinson:不同的表示并不能解决问题。人们通常建议使用十进制来处理货币,但这仅是因为所涉及的值通常是十进制数。这些涉及对数的公式在任何表示中都会是不规则的,因此在任何表示中都会存在舍入误差。

标签: c++ math floating-point floating-accuracy numerical-methods


【解决方案1】:

如果你只是用熵来判断哪个方案更好,这样你只需要比较两个熵的结果而不需要它们的实际值,那么你可以省去一些计算。

你有这个函数:熵(N1, N2, N) -> - N1/N*log2(N1/N) - N2/N*log2(N2/N)。

假设 N 在您的问题期间是一个常数,让我们将表达式乘以 N:

  • N1*log2(N1/N)-N2*log2(N2/N)

接下来,将“/N”与对数分开:

  • N1*(log2(N1)-log2(N)) - N2*(log2(N2)-log2(N))

然后展开:

  • N1*log2(N1) - N2*log2(N2) - (N1+N2)*log2(N)

并简化:

  • N1*log2(N1) - N2*log2(N2) - N*log2(N)

显然 N*log2(N) 是一个常数,不会影响一个熵是否大于另一个熵,因此我们可以丢弃它。

此外,乘以 ln(2),这也不会改变一个熵是否大于另一个熵。这具有将 log2 函数更改为 ln 函数的效果,并且可以通过数学库稍微更准确地计算 ln(这是“自然”对数的原因):

E(N1, N2, N) -> - N1*ln(N1) - N2*ln(N2)

这个函数的运算量较少,因此它的计算可能比熵函数更准确,并且它具有(当精确计算时)E(N1, N2, N)

【讨论】:

  • 好吧,我应该比较两个信息增益值,所以我应该在用于计算信息增益的公式上重复你的过程。
猜你喜欢
  • 2014-10-17
  • 2018-03-26
  • 2019-04-29
  • 2015-08-09
  • 2017-06-27
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 2012-04-29
相关资源
最近更新 更多