【问题标题】:Computing probability of occurrence for all alphabets in map reduce计算地图减少中所有字母的出现概率
【发布时间】:2021-05-30 04:39:59
【问题描述】:

我正在尝试使用 Map-reduce 程序计算文件中每个字母出现的概率。

我正在使用以下框架进行 map-reduce。 1 个映射器来映射所有字符,例如 ('a',1)。 1个组合器来计算每个字符的出现总数。 1 个减速器来计算平均值。

但是,我无法计算减速器中的平均值。所以,我添加了一个虚拟字符,每当映射器映射一个新字符时,它就会写入一次。

这个虚拟字符代表字符的总数,我不知道如何在reducer中访问它并将所有其他值除以总数。

例如,以下是组合器的输出。

# 10
a 2
b 2
c 2
d 4

我尝试了 1 个减速器,但没有输出。

我特别需要知道必须写在reducer中的逻辑。

public void reduce(Text key, Iterable<DoubleWritable> values, Context context)
        throws IOException, InterruptedException {

    int wordCount = 0;
    double total = 1;
    System.out.println("In Reducer now!");
    double avg = 0;
    total = values.iterator().next().get();

    avg = values.get() / total;
    context.write(key, new DoubleWritable(avg));
}

上面的代码没有在输出上写任何东西。

映射器

public void map(LongWritable key, Text value, Context context)
        throws IOException, InterruptedException {

    String s = value.toString();

    char[] arrayofChar = s.toCharArray();
    for (char ch : arrayofChar) {
        System.out.print(ch);
        if (Character.isLetter(ch)) {
            context.write(new Text(String.valueOf(ch)), new DoubleWritable(1));
            context.write(new Text("#"), new DoubleWritable(1));

        }
    }
}

组合器

public void reduce(Text key, Iterable<DoubleWritable> values, Context context)
        throws IOException, InterruptedException {

    double total = 0;
    System.out.println("In Combiner now!");
    for (DoubleWritable value : values) {
        total += value.get();
    }
    context.write(key, new DoubleWritable(total));
}

【问题讨论】:

  • 您是否尝试运行您的代码?您必须提供有关使用 id 的对象的更多信息:“values”变量、DoubleWritable 类...
  • 我已经为 Reducer、Combiner 和 Mapper 添加了代码。

标签: java hadoop mapreduce average reducers


【解决方案1】:

为了整理这个我写了单独的消费者:

public class Test {
    public static void main(String[] arg) throws Exception{
        String s= "aabccdaaab"; 
        Averager av = s.chars().collect(Averager::new,Averager::accept, Averager::combine);
        System.out.println(av.averages());
    }
}

class Averager implements IntConsumer  {
    private int count = 0;
    private Map<Character,Integer> data = new HashMap<>();
        
    public  Map<Character, Double>averages() {
        Map<Character, Double> result = new HashMap<>();
        for(Character c : data.keySet()) {
            double d = (double)data.get(c)/count;
            result.put(c,d);
        }
        return result;
    }
        
    public void accept(int c) { 
        Character cc = new Character((char)c);
        count++;
        if(data.containsKey(cc)) {
            int i = data.get(cc);
            i++;
            data.put(cc, i);
        } else {
            data.put(cc, 1);
        }
    }

    public void combine(Averager other) {
        for(Character c : data.keySet()) {
            if(other.data.containsKey(c)) {
                int sum = data.get(c) + other.data.get(c);
                other.data.put(c, sum);
            } else {
                other.data.put(c, data.get(c));
            }
        }
        data = other.data;
    }
}

输出:

{a=0.5, b=0.2, c=0.2, d=0.1}

【讨论】:

  • 是的,这是一个使用 Java Streams 的解决方案,但是 OP 显然使用的是Hadoop MapReduce(类型名称与他的代码匹配)。
  • 谢谢。但是,给定输入所需的输出是 {a=.2,b=.2,c=.2d=.4}。另外,我正在尝试使用 MapReduce 解决问题。
  • 如果您在 OP 中给出公式/示例,那就太好了 :) 在我的代码中,我使用了输入“aabccdaaab”。
  • 我现在已经编辑了我的原始帖子。我通过驱动程序类从文件中读取的实际输入。
猜你喜欢
  • 1970-01-01
  • 2011-02-16
  • 2021-03-18
  • 1970-01-01
  • 2015-12-01
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多