2

背景

我有一个我喜欢不时想太多的宠物项目。该项目与 RC 飞机控制输入设备有关。熟悉该爱好的人可能也熟悉所谓的“摇杆博览会”,这是 RC 发射器的一个共同特征,其中控制杆在中性中心位置附近或多或少敏感,并随着摇杆靠近其最小值或最大值。

我读过一些我不完全理解的论文。我显然没有数学背景来解决这个问题,所以我希望你们中的一个人可能会。

问题

我决定通过获取预定数量的样本来近似曲线,并使用线性插值来确定样本点之间任何输入值的输出值。 我试图找到一种方法来确定最佳的样本点集。

如果您查看此应用程序的典型增长曲线示例,您会注意到有些部分更线性(更直),而另一些则不太线性(更弯曲)。

典型曲线示例

这些样本彼此之间的距离相等,但并非必须如此。在有更多变化的地方增加样本密度,从而通过从直线段借用冗余点来提高曲线段的分辨率,这将是明智的。

是否可以量化误差程度?如果是,那么是否也可以确定给定函数的最佳样本集和预定数量的样本?

参考代码

使用预先计算的一组点来近似输出值的类的片段。

/* This makes the following assumptions:
 *   1. The _points[] data member contians at least 2 defined Points.
 *   2. All defined Points have x and y values between MIN_VALUE and MAX_VALUE.
 *   3. The Points in the array are ordered by ascending values of x.
 */
int InterpolatedCurve::value( int x ) {
  if( _points[0].x >= x ) { return _points[0].y; }
  for( unsigned int i = 1; i < _point_count; i++ ) {
    if( _points[i].x >= x ) {
      return map(x, _points[i-1].x, _points[i].x,
                    _points[i-1].y, _points[i].y);
    }
  }
  // This is an error condition that is not otherwise reported.
  // It won't happen as long as the points are set up correctly.
  return x;
}

// Example map function (borrowed from Arduino site)
long map( long x, long x1, long x2, long y1, long y2 ) {
  return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
}

尽管我的项目实际上是用 C++ 编写的,但在思考这个问题时,我正在使用 Google 电子表格生成一些数字。

// x: Input value between -1 and 1
// s: Scaling factor for curve between 0 (linear) and 1 (maximum curve)
// c: Tunable constant
function expo_fn( x, s, c ) {
  s = typeof s !== 'undefined' ? s : 1.0;
  c = typeof c !== 'undefined' ? c : 4.0;
  var k = c * ((c - 1.0) * s*s*s + s)/c + 1.0;
  return ((k - 1.0) * x*x*x*x*x + x)/k;
};

下面在输入值 -1 和 1 之间创建一组等距分布(非最佳)点。对于上述示例电子表格,这些输出值已扩展为 -16383 和 16383 之间的整数。因子是一个介于 0 和 1 之间的值,它决定了“曲线”——零是平坦的线性曲线,而 1 是我想要生成的最小线性曲线。

function Point( x, y ) {
  this.x = x;
  this.y = y;
};

function compute_points_iso( count, factor ) {
  var points = [];
  for( var i = 0; i < count; ++i ) {
    var x = 2.0/(count - 1.0) * i - 1.0;
    var y = expo_fn(x, factor);
    points.push(new Point(x,y));
  }
  return points;
};

相关学术工作

我一直在研究这篇论文,描述了一种用于选择重要数据点的算法,但我的程序还不能很好地工作。如果我能让这个东西工作,我会报告回来。

4

1 回答 1

1

这里的关键是要意识到您可以根据函数的二阶导数来限制线性插值的误差。即如果我们近似f(x) \approx f(x_0) + f'(x_0)*(x-x_0),那么这个近似的误差小于abs[ 0.5*f''(x_0)(x-x_0)^2 ]

迭代方法的轮廓可能如下所示:

  1. 构造一个初始的,例如均匀间隔的网格
  2. 计算该网格上函数的二阶导数。
  3. 使用二阶导数和样本间距计算误差的界限
  4. 在误差较大的地方将样本靠得更近;在误差较小的地方将它们移得更远。

我希望这是在步骤 2、3、4 上循环的迭代解决方案。

大部分细节都在步骤 4 中。对于固定数量的样本点,可以使用误差范围的中值来选择需要更精细/更粗略的采样的位置(即,误差大于中值误差的那些位置将具有采样点靠得更近)。

E_0这个误差范围的中值;然后我们可以为点中的每个样本计算一个新的期望样本间距(dx')^2=2*E_0/f''(x);那么您需要一些逻辑来完成并更改网格间距,使其更接近这些理想间距。

我的回答受到对数据使用“自组织图”算法的影响;此或相关算法可能与您的问题相关。但是,我不记得曾经见过像您这样的问题,其目标是使您对整个网格的误差估计一致。

于 2013-10-23T19:51:46.743 回答