在尝试使用OpenCV机器学习库时,我尝试举一个例子,使用决策树学习2D,2连杆臂的逆运动学。正向运动学代码如下所示:

const float Link1 = 1;
const float Link2 = 2;

CvPoint2D32f forwardKinematics(float alpha, float beta) 
{
    CvPoint2D32f ret;

    // Simple 2D, 2 link kinematic chain
    ret.x = Link1 * std::cos(alpha) + Link2 * std::cos(alpha - beta);
    ret.y = Link1 * std::sin(alpha) + Link2 * std::sin(alpha - beta);

    return ret;
}


我生成1000个(XY-> alpha)和(XY-> beta)对的随机集合,然后使用该数据可在OpenCV中训练两个决策树模型(一个用于alpha,一个用于beta)。然后,我使用模型预测给定XY位置的关节角度。

有时似乎得到了正确的答案,但却大相径庭。我知道类似的逆运动学问题可以有多种解决方案,但是我得到的一些答案却是错误的。

这是尝试做的合理的选择,还是永远不会奏效?有没有比决策树更适合这种问题的学习算法?

#1 楼

我更改了训练集的生成方式,以均匀地采样关节空间,而不是使用随机样本,并且还限制了第二关节的范围,以防止出现多个解和奇异点。

现在,该算法实际上可以很好地工作,并且可以为我提供合理接近所需位置的答案。我仍然不相信决策树是解决此问题的最佳算法。方式(尤其是在使用统一的训练集时)。

评论


$ \ begingroup $
我只是想观察一下DT可能会起作用,但可能不是该任务的最佳学习算法。使用双线性插值进行逆运动学,我真的很幸运。我认为它也可以很好地解决这个问题。您正在训练两棵树,每棵只有一个特征,这似乎也很奇怪。通常,您会训练一棵具有多种功能的树。最后,如果增加样本数量,您可能会发现性能有所提高,因为您将为真实函数创建更好的近似值。
$ \ endgroup $
– DaemonMaker
2012年11月28日在20:10

$ \ begingroup $
样本数量问题是一个有趣的问题,在我当前的实现中,似乎我实际上用更少的样本获得了更一致的答案。我不完全了解OpenCV是如何构建树的,但是似乎样本较少,也许它被卡在错误的节点上的频率降低了?我使用了两棵树,因为据我所知,CvDTree实现使用单个double作为节点值,因此没有办法存储多个结果值。
$ \ endgroup $
–野生甲壳动物
2012年11月28日在20:21

#2 楼

这里的核心问题是您正在使用两个决策树。据我了解,您正在针对同一数据训练两个不同的决策树。然后,您有一棵树预测所需角度$ \ alpha $,另一棵树预测所需角度$ \ beta $。问题在于$ \ beta $依赖于$ \ alpha $,但是$ \ beta $树没有这个事实的概念。您需要做的是在两个特征上训练一棵树(即$ \ alpha $和$ \ beta $)。

在OpenCV中,每个DT节点都使用一个称为value的双精度来存储该值。节点,它使用一个称为class_idx的整数来确定要在任何给定级别拆分的功能。训练DT时,您需要为其提供矩阵。通常,矩阵的每一行都是特征向量,每一列都是单独的特征。但是,似乎可以通过使用tflag(Cool!)在OpenCV实现中对其进行配置。使用常规方法,您需要创建一个$ m {\ times} n $矩阵,其中$ m = 1000 $是训练样本的数量,$ n = 2 $。

评论


$ \ begingroup $
据我所知,OpenCV DT实现仅支持一维响应矢量,我仍然不确定如何训练一棵树同时给我alpha和beta。
$ \ endgroup $
–野生甲壳动物
2012年11月29日15:22