1

我正在编写一些算法来构建随机森林,每个森林都将使用单独的函数在单独的数据上进行训练(每棵树将使用一组具有固定签名的函数,但是不同的树将使用不同的函数集进行训练,这些函数可能具有不同的签名),但是我想使用模板编写一次构建随机树的代码。我目前有以下内容:

模板类 T 对应训练数据类型(即图像补丁,或像素) 模板类 V 对应函数指针类型

template<class T, class V>
class RandomTree{

    void build(RandomTreeNode<T>& current_node,
               vector<V>& functions,
               vector<T>& data) {
        ... some code that basically calls a function passing in data T
    }
}

我像这样创建对象:

typedef double (*function_ptr)(TrainingDataPoint& data_point);

RandomTree<TrainingDataPoint, function_ptr> tree = ...

问题是,出于效率原因,对于我正在构建的一棵树,我希望函数集(function_ptr's)不仅包含 TrainingDataPoint(模板类型 T),还包含数据缓存。这样我的函数指针将如下所示:

typedef double (*function_ptr)(TrainingDataPoint&,
                               unordered_map<string, cv::Mat>& preloaded_images);

现在的问题是,我想不出一种方法来保持 RandomTree 类的通用性,但有一些函数集(模板类型 V)不仅仅需要训练点(模板类型 T)。

到目前为止,我想到了:

  1. 使缓存全局化,以便函数可以访问它
  2. 为每个训练数据点添加一个指向缓存的指针(但谁负责清理?)
  3. 将第三个模板参数添加到 RandomTree,但在这种情况下,如果我正在构建不需要第三个参数的树,我应该放什么?

这些选项似乎都没有对我特别有吸引力,希望有人可以提供一些经验并告诉我更好的方法吗?

谢谢

4

2 回答 2

4

对需要状态的函数使用仿函数。C++ 中的仿函数是具有重载的 operator() 的类(或结构),因此仿函数的实例可以像函数一样“调用”。RandomTree 中函子的参数应该正是那些变化并受 RandomTree 控制的参数,其余的应该绑定在外部。具有包装函数的附加状态的示例仿函数:

template<typename Retval, typename Arg1, typename ExtraData>
struct BindExtraData
{
  typedef Retval(*func_type)(Arg1, ExtraData);
  BindExtraData( ExtraData const& d_, func_type func_ ):d(d_), func(func_) {};
  ExtraData d;
  func_type func;
  Retval operator()( Arg1 a1 )
  {
    return func(a1, d);
  }
};

但你可以做得更好。如果这是一次性的,则无需将其设为模板。bind2nd(well, binder2nd) 是上面的标准库版本,会写得更好。

于 2012-10-25T15:20:36.077 回答
0

你能在 RandomTree 中添加另一个参数来接收缓存吗?如果未提供,则默认值为空缓存。例如

template<typename T, typename V, typename CacheDataType = EmptyCache>
class RandomTree{ ... }

RandomTree<TrainingDataPoint, function_ptr, ProloadedImageCache>
于 2012-10-25T15:14:41.567 回答