我有下面的reducer类(mapreduce作业的一部分),它应该计算 score = POS /(-1*sum(NEGs))
.
哪里 POS
是一个正数,并且 NEGs
是两个负数。总是这样。
例如,如果来自Map器的输入是:
<A, A> -15.0
<A, A> 2.0
<A, A> -15.0
预期产出将是:
<A, A> 0.06666666666666667
但是,它正在输出 infinity
对于每个输出记录!
<A, A> Infinity
调试时,如果我添加语句以在while循环中发出值:
score.set(val);
context.write(key, score);
,它可以很好地打印结果,但会重复分割。所以我得到了以下结论:
<A, A> -15.0
<A, A> 2.0
<A, A> -15.0
<A, A> 0.06666666666666667 # correct calculation (2/30)
<A, A> 0.0022222222222222222 # Not sure why it divids twice by 30 (2/30/30)!!
这是 MyReducer
班
private static class MyReducer extends
Reducer<Pair, DoubleWritable, Pair, DoubleWritable> {
private DoubleWritable score = new DoubleWritable();
int counter = 0;
@Override
public void reduce(Pair key, Iterable<DoubleWritable> values, Context context)
throws IOException, InterruptedException {
Iterator<DoubleWritable> iter = values.iterator();
double nor = 0.0;
double don = 0.0;
double val;
while (iter.hasNext()) {
val = iter.next().get();
if (val < 0)
don += val*-1;
else
nor = val;
//uncomment for debugging!
//score.set(val);
//context.write(key, score);
}
score.set(nor / don);
context.write(key, score);
}
有人能解释为什么吗
如果我在while循环中没有发射任何东西,则发射无穷大
除以分母两次?
谢谢!
1条答案
按热度按时间7lrncoxx1#
当然,double在java中表现的滑稽绝非罕见,但在这个特殊的例子中,double的方式并不奇怪,因为它们在hadoop中的兼容性如何。
首先也是最重要的是,这种类型的reduce计算非常关键,只能在作业的reduce阶段使用,而不能在combine阶段(如果有)使用。如果您已将此reduce计算设置为也作为组合器实现,则可以考虑取消设置此设置。这并不是一个经验法则,但是在mapreduce作业中有很多错误,人们不能很好地理解为什么Reducer会得到奇怪的数据或者连续执行两次计算(就像你指出的那样)。
然而,这个问题的罪魁祸首可能是,为了获得安全的双类型划分,您确实需要使用类型转换来获得正确的双类型结果。
为了展示这一点,我使用了一个基于输入数据并存储在
\input
目录。每个唯一键都有一个正数和两个负数作为值(这里的键设置为String
为了简单起见),如下所示:然后使用显式类型转换来计算每个分数,如下面的代码所示:
您可以在
/scores
目录在数学上是有意义的(通过hdfs浏览器截图):