【发布时间】:2013-02-18 23:22:25
【问题描述】:
我有一个数据集,其中包含一些属于 1 和 2 表示的两个类标签的特征。处理这个数据集是为了构建决策树:在树的构建过程中,我需要计算信息增益以找到数据集的最佳分区。
设N1个特征关联到标签1,N2个特征关联到标签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