【问题标题】:Sample the deltas between values using boost::accumulators使用 boost::accumulators 对值之间的增量进行采样
【发布时间】:2010-03-30 22:18:53
【问题描述】:

我有一个包含 N 个样本(例如 13、16、17、20)的数据集,其中每个下一个样本都增加了某个值(在本例中为 3、1、3),我想找到第二个序列 .

样本是增量收集的时间戳(即并非所有样本都同时可用),因此我想使用boost::accumulators::accumulator_set,因为它看起来很符合要求。

我希望能够做这样的事情:

accumulator_set< double, features< tag::mean > > acc;
...
acc(13);
acc(16);
acc(17);
acc(20);

...但是采样差异而不是实际值。

如何在不手动跟踪最后一个值的情况下使用 accumulator_set 做到这一点?

【问题讨论】:

  • 是这样的,还是那样的?差异的平均值就是第一个和最后一个样本之间的差异,除以(样本数-1);-p
  • @Steve Jessop,我还想计算标准差。因此使用累加器框架。

标签: c++ boost


【解决方案1】:

升压累加器没有差异统计。不过你可以自己动手:

http://www.boost.org/doc/libs/1_37_0/doc/html/accumulators/user_s_guide.html#accumulators.user_s_guide.the_accumulators_framework.extending_the_accumulators_framework

在我看来,最好的解决方案就是跟踪最后的增值。

【讨论】:

    【解决方案2】:

    这个答案可能比你想的要复杂一些,但至少它不像我担心的那样离谱。这个想法是首先创建一个迭代器类型,该类型充当从“普通”算法到 Boost 累加器风格算法的适配器。这是比我真正预期的要简单的部分:

    #ifndef ACCUM_ITERATOR_H_INCLUDED
    #define ACCUM_ITERATOR_H_INCLUDED
    
    #include <iterator>
    
    template <class Accumulator>
    class accum_iterator :
        public std::iterator<std::output_iterator_tag,void,void,void,void> {
    protected:
        Accumulator &accumulator;
    public:
        typedef Accumulator accumulator_type;
        explicit accum_iterator(Accumulator& x) : accumulator(x) {}
    
        // The only part that really does anything: handle assignment by 
        // calling the accumulator with the value.
        accum_iterator<Accumulator>&
            operator=(typename Accumulator::sample_type value) {
                accumulator(value);
                return *this;
        }
        accum_iterator<Accumulator>& operator*() { return *this; }
        accum_iterator<Accumulator>& operator++() { return *this; }
        accum_iterator<Accumulator> operator++(int) { return *this; }
    };
    
    // A convenience function to create an accum_iterator for a given accumulator.    
    template <class Accumulator>
    accum_iterator<Accumulator> to_accum(Accumulator &accum) { 
        return accum_iterator<Accumulator>(accum);
    }
    
    #endif
    

    然后是有点不幸的部分。标准库有一个adjacent_difference 算法,它应该产生你想要的流(集合中相邻项目之间的差异)。但是它有一个严重问题:有人认为它会产生一个与输入集合大小相同的结果集合(即使显然比结果多一个输入)。为此,adjacent_difference 将结果中的第一项保留为一些未指定的值,因此您必须忽略第一个值才能从中获得任何有用的信息。

    为了弥补这一点,我重新实现了一种算法类似 std::adjacent_difference 有一个非常小的区别:因为显然结果比输入少一个,所以它只有 产生的结果比输入少一个,并且不会在结果中给出无意义的、未指定的值。将两者结合,我们得到:

    #include "accum_iterator.h"
    #include <iostream>
    #include <vector>
    
    #include <boost/accumulators/accumulators.hpp>
    #include <boost/accumulators/statistics/mean.hpp>
    using namespace boost::accumulators;
    
    // A re-implementation of std::adjacent_difference, but with sensible outputs.
    template <class InIt, class OutIt>
    void diffs(InIt in1, InIt in2, OutIt out) { 
        typename InIt::value_type prev = *in1;
        ++in1;
        while (in1 != in2) {
            typename InIt::value_type temp = *in1;
            *out++ = temp - prev;
            prev = temp;
            ++in1;
        }
    }
    
    int main() {
        // Create the accumulator.
        accumulator_set<double, features< tag::mean > > acc;  
    
        // Set up the test values.
        std::vector<double> values;
        values.push_back(13);
        values.push_back(16);
        values.push_back(17);
        values.push_back(20);
    
        // Use diffs to compute the differences, and feed the results to the 
        // accumulator via the accum_iterator:
        diffs(values.begin(), values.end(), to_accum(acc));
    
        // And print the result from the accumulator:    
        std::cout << "Mean:   " << mean(acc) << std::endl;
        return 0;
    }
    

    【讨论】:

    • 我觉得我应该在我的问题中提供更多信息。我的实际问题是我在延迟敏感系统中不断收集时间戳样本并想要测量抖动,所以理想情况下我需要逐步更新我的统计数据。因此,在这种情况下,收集样本是不可取的。
    • @Checkers:diffs 只需从input_iterator 获取输入并将结果写入output_iterator。对于演示/测试,input_iterator 连接到一个集合——但它可以很容易地从磁盘上的文件或网络连接中读取数据。
    猜你喜欢
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 2015-02-06
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多