精华内容
下载资源
问答
  • 我们需要知道手臂状态(位置状态、速度状态)和时间的关系,从而拟合出一条连续(重点)的曲线供机械臂达到目的。这就属于“轨迹规划”内容了。 目录 轨迹规划 Joint space、Actuator space、Cartesian space的...

    引言

    在真实需求中,当我们的机械臂已经拿到了一支笔,那怎么设定轨迹让它画一只鸭子之类的呢,或者怎么样让机械臂拿到杯子后挂在墙上呢?我们需要知道手臂状态(位置状态、速度状态)和时间的关系,从而拟合出一条连续(重点)的曲线供机械臂达到目的。这就属于“轨迹规划”内容了。

    目录

    轨迹规划

     Joint space、Actuator space、Cartesian space的区别

    Joint space下的轨迹规划

    Cartesian space下的轨迹规划

    Joint 、Cartesian space下轨迹规划的优缺点

    如何拟合曲线 (重点)

    三次多项式(Cubic Polynomials)(基础)

    未知中间点速度情况下的求解

    (1)“手动”定义中间点求解

    (2)电脑自动生成中间点(推荐)

    相关例题

    (1)Cartesian space下的求解

    (2)Joint space下的求解


    轨迹规划

    说白了就是给你两个位置点,起始点和终点,你自己定义中间点(via point),把起始点和终点用平滑曲线连起来就行。

    其实就是拟合曲线嘛.........

    我理解的轨迹规划的核心目的在于得到关节的驱动数值的连续平滑曲线,也就是说主要是求解曲线的未知参数。如果没有关节的驱动,你怎么到达目标位置?

    轨迹:机械手臂末端点或参做点的位置、速度、加速度对时间的历程。

    轨迹规划的好处:轨迹规划后,可以使用不同形态类型的机械臂使用相同轨迹。

    理想轨迹是物体运动的位置连续,速度也是连续的。我们都知道,假如速度不连续,忽大忽小,这就要求它的加速度突然变大,这会给机械臂关节造成力的负担,很大可能出现误差,因此我们的轨迹规划最好是连续的。在轨迹规划下,还分两种类型的规划:Joint space、Certesian space下的轨迹规划,在这先解释下。

    •  Joint space、Actuator space、Cartesian space的区别

    由该图可以看到:

    Joint space:提供了关节驱动的数值\large \Theta _{i},使得我们可以顺向计算出手臂末端的位置\large _{}^{W}\textrm{P}

    Cartesian space:提供手臂P相对{W} 的向量位置,即\large _{}^{W}\textrm{P},逆向反推出达到这个位置需要的驱动数值\large \Theta _{i}

    Actuator space:提供了马达的状态数值,以确保得出最终关节的驱动数值(详见(三)扩展中的复合型关节的案例)

     

    [前提假设]

    我们的机械臂是六个自由度的,六个关节都是转轴驱动的。也假设我们已经定义好了起始、中间、终点的位置信息和姿态信息。\large D代表了我们的手末端的位置,\large \Theta代表了手末端的姿态,这两个是我们的需求点。

    • Joint space下的轨迹规划

     

     

    1)知道位置,就能通过逆向运动学(IK),反向求解出有六个自由度的机械臂它六个转轴需要的角度。

    2)拟合曲线,就是轨迹规划啦,得到这些点连续平滑的函数表示(多种)。就是找函数关系(横纵轴的映射)。

    3)再借由顺向运动学(FK)验证这个函数能否经过我们在(1)定义好的点,使得机械臂通过我们规定的点,达到我们想要的位置,以此测试函数是否正确。

    4)检验可行性,比如这个轨迹是不是可能会撞到现实空间中的某些东西之类的。

     

    • Cartesian space下的轨迹规划

    1)拟合曲线,直接做轨迹规划,找出他们的函数式。

    2)逆向求解出达到这个位置需要机械臂的每个转轴转动的度数,检验求解出的角度是否超出了机械臂转动角度的最大范围等。

    3)检验可行性,检测该轨迹在现实中是否会碰到障碍物。

     

    • Joint 、Cartesian space下轨迹规划的优缺点

    一般都是用Cartesian space做规划,因为这个更直接地符合我们的需求,直接根据需求得到轨迹就行了啊,步骤少。然而它有一个缺点是它计算量相对于Joint space大得多,因为我们是先对手臂需要的姿态\large \Theta位置\large D拟合它的曲线(从几个点变成了无数个点),然后才去计算驱动关节需要的角度——反推出好多好多个姿态位置下与之一一对应的所有驱动角度,这十分考核机械臂的算力,尤其对于实时的机械臂。而Joint space就不同了,我们先计算姿态\large \Theta位置\large D需要的关节驱动角度数值,然后再拟合这些角度数值的曲线,拟合曲线的计算比反推无数个姿态位置对应的无数个角度要简单得多。

    我前面说了,我个人理解的轨迹规划的核心求解目的是——得到关节驱动的拟合曲线。如果使用Joint space的话,在第二步就能得到这个曲线,之后的3、4步都是验证而已。那为什么大家很少用计算量更少的Joint space呢?因为Cartesian更直观,他直接规划出位置的轨迹,而Joint规划的是关节角度的变换轨迹,不直观。然而我还是不太理解为啥很少人用 joint....难道是因为它步骤多么?

     


    如何拟合曲线

    拟合曲线的方法很多,可以使用机器学习的监督算法,当然小规模地轨迹也可以直接使用excel /逃。

    我们在轨迹规划中一般使用三次多项式,一整个曲线中往往是多段参数不同的多项式曲线组合起来的。

    我们首先了解单段三次多项式(红色框内),再了解多段中的求解。

     

    • 三次多项式(Cubic Polynomials)(基础)

    已知两侧的点坐标(假设某时刻下的角度、速度已知),用三次多项式求角度 \large \theta 和时间 \large t 的关系式,即需要求出\large a_{0....4}

    一般解法

    未知的\large a_{0....4}很容易如下求解出来:

    其中[\large \Theta]是角度,[\large \Theta点]代表角速度,[\large \Theta点点]代表角加速度。

    矩阵表达

    如果用矩阵来表示上述运算,则是:

    (注:此T矩阵与前几章的信息矩阵不同)

    \large \Theta _{i}代表起点\large i的位置,\large \Theta _{i+1}代表终点\large i+1的位置,\large \Theta _{i}点代表起点i的速度,\large \Theta _{i+1}点代表终点\large i+1的速度。

    由于T矩阵满足性质有逆矩阵,所以该式可以变化为:

    这个是单个三次多项式的求解。

     

    未知中间点速度情况下的求解

    在上面的三项多项式中,我们是假设我们已知两侧的角度和速度才能求解多项式,在实际轨迹规划中,我们只知道头尾点的位置、速度条件,我们并不知道中间点(via point)的位置和速度,那如何定义它呢?有好多种方法:根据特殊的需求直接定义(不推荐)、让电脑自己算出适合的速度(例如多段三次多项式)、广义多项式等等方法。

     

    (1)“手动”定义中间点求解

    这些方式都是定死规则,一开始就定义好了中间点是哪个,所以就能很容易得到速度值,然后利用三次多项式(Cubic Polynomials)(基础)中最后得到的矩阵求解即可。

     

    (2)电脑自动生成中间点(推荐)

    • 多段三次多项式

     使用多段三次多项式的好处是,中间点不用自己定义,它是电脑自己算出来的,而且比手动定义的更有连续性。上面手动定义中间点的图也有个“自动定义”,但是那个是在“人定的死规则”下让电脑生成的我们能知道的中间点,并不是电脑自动算出来的连我们都不知道的中间点。

    直接举例

    [假设条件]

    中间点是\large \Theta_{1},并且已知\large \Theta_{0}\large \Theta_{f}的速度位置情况。即我们需要求解出两段多项式 : \large \Delta t_{1}\large \Delta t_{2} 段的多项式,八个未知数\large a

    [统一符号]

    其中 \large \Theta 是角度,[\large \Theta点]代表角速度,即对\large \Theta求导。[\large \Theta点点]代表角加速度,即对[\large \Theta点]求导。

    在这里\large a_{xy}\large x代表得是这个参数属于第几段(个)多项式,\large y代表的是该参数的幂次。

    举例:\large a_{13} 代表第二个多项式式子的参数,并且它是立方\large a,即第二个多项式的\large a ^{3}

    一般解法:

    由前面的公式:

    (一个多项式包含头尾两个方程式)

    可以直接求解出:

    \large \Theta_{0}\large \Theta_{f}求导可以得出角速度\large \Theta点:

    注:为了方便运算,在这里我们是假设了一开始和最后的点角速度是0的,该值可以根据实际状况改动。) 

    由于我们要保证我们定义的中间点的位置、速度是连续的,所以要求中间点符合条件:

    在第一个多项式中,中间点在此可看作“终点” : \large \Theta_{1} \left ( t=t_{1} \right ) ,\large \Delta t_{1}∈[ \large t_{0} , \large t_{1} ] .

    第二个多项式中,中间点在此可看作“起点”:  \large \Theta_{2} \left ( t=0 \right ) ,\large \Delta t_{2}∈[ \large t_{1} , \large t_{f} ] 。

    为了保证角速度的连续性,要有\large \Theta_{1} \left ( t=t_{1} \right )的导数=\large \Theta_{2} \left ( t=0 \right )的导数.

    为了保证角加速度的连续性,要有\large \Theta_{1} \left ( t=t_{1} \right )的导数的导数=\large \Theta_{2} \left ( t=0 \right )的导数的导数.

    于是有:

    (一个中间点能产生速度、加速度两个方程式)

    联立上面八个等式,就能求解出两个多项式的参数值:

    矩阵解法(重点):

    上面的解法转换为矩阵就是:

    左式第一个代表第一段多项式的起点,第二个代表终点。

    左式第三个代表第二段多项式的起点,第四个代表终点。

    左式第五个代表整个多段式的起点速度,第六个代表终点速度。

    左式第七个代表第一个中间点的速度连续性条件,第八个代表加速度的条件。

    有固定套路,记住就好了,下面例题要用的。

    总结:用多段三次多项式拟合曲线好处是速度、加速度连续,但是需要结合前一段多项式,需要多个式子联立求解就比较麻烦。

     

    •  广义三次多项式

    假设我们有N+1个点,也就是说有N段需要求解的多项式,还表明除了头尾两点,说我们有N-1个中间点。

    它的多项式表达式和多段多项式那个一样的,只是表达方式不同了而已,为:

    可以看到一个多项式里还是有四个未知数,即我们整体有4N个未知数。

    由上面多段多项式的例子可知,一个多项式包含头尾两条方程式,由于我们有N个多项式,所以我们就有2N个方程式。

    而且上面的例子还表明了,一个中间点可以得到两个方程式(速度、加速度),由于我们有N-1个中间点,所以我们就有2(N-1)个方程式。

    然而此时仅有2N+2(N-1)= 4N-2 个方程,我们的未知数有4N个,还差两条方程式,这样怎么联立求解出未知数?

    最后两个条件方程式的补充定义方法:

    1)定义加速度,头尾加速度都是0,符合真实世界的运动

    2)定义速度,按照需求定义头尾的速度情况

    (多段多项式的例题就是已经假设了头尾速度为0的情况下)

    3)将头尾点看作“中间点”,以达到速度和加速度连续。这一条件针对的是头尾连续,做周期运动的机械臂。

    其实广义三次多项式和多段那个一模一样嘛....广义多项式只是扩展了最后两个方程式的定义方法而已....

     

    相关例题

    t 代表时刻点
    x t 时刻下,机械臂第二关节点在x轴上的位置
    y t 时刻下,机械臂第二关节点在y轴上的位置
    theta t 时刻下,机械臂第三杆与x轴的角度

    直接套用多段三次多段式的公式就行:

    (1)Cartesian space下的求解

    在Cartesian下可以直接求解,不用先转换成到达目标坐标的驱动关节的角度,所以直接将表格数据带入公式即可:

    然后就能求解出A矩阵了,就知道整个多项式曲线以及它的轨迹了。

    (2)Joint space下的求解

    首先要先 IK 逆向转换成角度...然后再运算,T矩阵和上面的是一样的,所以也不麻烦。

    ——————————————————————————————————

    最后,补充说明,假如我们想要更多信息,不只有位置、速度信息,还要加速度的信息,也就是一段多项式我们有6个需求量(包括头尾),我们这时候可以选择五次多项式(有六个参数)去拟合曲线。

    感谢:课程内容、PPt来自台湾林沛群教授的《机器人学》课程!

    展开全文
  • 这篇文章中,我们将使用TensorFlow.js来根据数据拟合曲线。即使用多项式产生数据然后再改变其中某些数据(点),然后我们会训练模型来找到用于产生这些数据的多项式的系数。简单的说,就是给一些在二维坐标中的散点...

      这篇文章中,我们将使用TensorFlow.js来根据数据拟合曲线。即使用多项式产生数据然后再改变其中某些数据(点),然后我们会训练模型来找到用于产生这些数据的多项式的系数。简单的说,就是给一些在二维坐标中的散点图,然后我们建立一个系数未知的多项式,通过TensorFlow.js来训练模型,最终找到这些未知的系数,让这个多项式和散点图拟合。

      

    一、运行代码

      这篇文章关注的是创建模型以及学习模型的系数,完整的代码在这里可以找到。为了在本地运行,如下所示:

    $ git clone https://github.com/tensorflow/tfjs-examples.git
    $ cd tfjs-examples/polynomial-regression-core
    $ yarn
    $ yarn watch

      即首先将核心代码下载到本地,然后进入polynomial-regression-core(即多项式回归核心)部分,最后进行yarn安装并运行。

     

    二、输入数据

      我们的数据在x坐标轴和y坐标轴内,看上去就是将之放在了笛卡尔坐标系,如下所示:

      4

      

      即这个图是 y = ax3 + bx2 + cx + d得到的,而在上图中,我们也看到了其真实系数为a=-0.800,b=-0.200,c=0.900,d=0.500,然后这些点是根据真实的点做了一定的偏移。  

      我们的任务就是通过机器学习得到这个函数的系数a、b、c以及d来最好的匹配这些数据。接下来,我们就看看如何通过TensorFlow.js来学习得到这些数据。

     

    三、学习步骤

    第一步 :设置变量

      首先,我们需要创建一些变量。即开始我们是不知道a、b、c、d的值的,所以先给他们一个随机数,入戏所示:

    const a = tf.variable(tf.scalar(Math.random()));
    const b = tf.variable(tf.scalar(Math.random()));
    const c = tf.variable(tf.scalar(Math.random()));
    const d = tf.variable(tf.scalar(Math.random()));

     

     

    第二步:创建模型

      我们可以通过TensorFlow.js中的链式调用操作来实现这个多项式方程  y = ax3 + bx2 + cx + d,下面的代码就创建了一个 predict 函数,这个函数将x作为输入,y作为输出:

    function predict(x) {
      // y = a * x ^ 3 + b * x ^ 2 + c * x + d
      return tf.tidy(() => {
        return a.mul(x.pow(tf.scalar(3))) // a * x^3
          .add(b.mul(x.square())) // + b * x ^ 2
          .add(c.mul(x)) // + c * x
          .add(d); // + d
      });
    }

      其中,在上一篇文章中,我们讲到tf.tify函数用来清除中间张量,其他的都很好理解。

      接着,让我们把这个多项式函数的系数使用之前得到的随机数,可以看到,得到的图应该是这样:

      

      因为开始时,我们使用的系数是随机数,所以这个函数和给定的数据匹配的非常差,而我们写的模型就是为了通过学习得到更精确的系数值。

     

    第三步:训练模型

      最后一步就是要训练这个模型使得系数和这些散点更加匹配,而为了训练模型,我们需要定义下面的三样东西:

    • 损失函数(loss function):这个损失函数代表了给定多项式和数据的匹配程度。 损失函数值越小,那么这个多项式和数据就跟匹配。
    • 优化器(optimizer):这个优化器实现了一个算法,它会基于损失函数的输出来修正系数值。所以优化器的目的就是尽可能的减小损失函数的值。
    • 训练迭代器(traing loop):即它会不断地运行这个优化器来减少损失函数。

      所以,上面这三样东西的 关系就非常清楚了: 训练迭代器使得优化器不断运行,使得损失函数的值不断减小,以达到多项式和数据尽可能匹配的目的。这样,最终我们就可以得到a、b、c、d较为精确的值了。

     

      

    四、定义损失函数

      这篇文章中,我们使用MSE(均方误差,mean squared error)作为我们的损失函数。MSE的计算非常简单,就是先根据给定的x得到实际的y值与预测得到的y值之差 的平方,然后在对这些差的平方求平均数即可

      

      于是,我们可以这样定义MSE损失函数:

    function loss(predictions, labels) {
      // 将labels(实际的值)进行抽象
      // 然后获取平均数.
      const meanSquareError = predictions.sub(labels).square().mean();
      return meanSquareError;
    }

       即这个损失函数返回的就是一个均方差,如果这个损失函数的值越小,显然数据和系数就拟合的越好。

      

     

    五、定义优化器

      对于我们的优化器而言,我们选用 SGD (Stochastic Gradient Descent)优化器,即随机梯度下降SGD的工作原理就是利用数据中任意的点的梯度以及使用它们的值来决定增加或者减少我们模型中系数的值

      TensorFlow.js提供了一个很方便的函数用来实现SGD,所以你不需要担心自己不会这些特别复杂的数学运算。 即 tf.train.sdg 将一个学习率(learning rate)作为输入,然后返回一个SGDOptimizer对象,它与优化损失函数的值是有关的。

      在提高它的预测能力时,学习率(learning rate)会控制模型调整幅度将会有多大。低的学习率会使得学习过程运行的更慢一些(更多的训练迭代获得更符合数据的系数),而高的学习率将会加速学习过程但是将会导致最终的模型可能在正确值周围摇摆。简单的说,你既想要学的快,又想要学的好,这是不可能的。

      下面的代码就创建了一个学习率为0.5的SGD优化器。

    const learningRate = 0.5;
    const optimizer = tf.train.sgd(learningRate);

      

    六、定义训练迭代器

      既然我们已经定义了损失函数和优化器,那么现在我们就可以创建一个训练迭代器了,它会不断地运行SGD优化器来使不断修正、完善模型的系数来减小损失(MSE)。下面就是我们创建的训练迭代器:

    function train(xs, ys, numIterations = 75) {
    
      const learningRate = 0.5;
      const optimizer = tf.train.sgd(learningRate);
    
      for (let iter = 0; iter < numIterations; iter++) {
        optimizer.minimize(() => {
          const predsYs = predict(xs);
          return loss(predsYs, ys);
        });
      }
    }

      现在,让我们一步一步地仔细看看上面的代码。首先,我们定义了训练函数,并且以数据中x和y的值以及制定的迭代次数作为输入:

    function train(xs, ys, numIterations) {
    ...
    }

      接下来,我们定义了之前讨论过的学习率(learning rate)以及SGD优化器:

    const learningRate = 0.5;
    const optimizer = tf.train.sgd(learningRate);

      

      最后,我们定义了一个for循环,这个循环会运行numIterations次训练。在每一次迭代中,我们都调用了optimizer优化器的minimize函数,这就是见证奇迹的地方:

    for (let iter = 0; iter < numIterations; iter++) {
      optimizer.minimize(() => {
        const predsYs = predict(xs);
        return loss(predsYs, ys);
      });
    }

      minimize 接受了一个函数作为参数,这个函数做了下面的两件事情:

    1. 首先它对所有的x值通过我们在之前定义的pridict函数预测了y值。
    2. 然后它通过我们之前定义的损失函数返回了这些预测的均方误差。

        

      minimize函数之后会自动调整这些变量(即系数a、b、c、d)来使得损失函数更小。

      在运行训练迭代器之后,a、b、c以及d就会是通过模型75次SGD迭代之后学习到的结果了。 

      

     

    七、观察结果吧!

      一旦程序运行结束,我们就可以得到最终的a、b、c和d的结果了,然后使用它们来绘制曲线,如下所示:

          

      这个结果已经比开始随机分配系数的结果拟合的好得多了!

    展开全文
  • approxPolyDP()函数是opencv中对指定的点集进行多边形逼近的函数,其逼近的精度可通过参数设置。 对应的函数为: void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed); .....

    approxPolyDP()函数是opencv中对指定的点集进行多边形逼近的函数,其逼近的精度可通过参数设置。

    对应的函数为:
    void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);

    例如:approxPolyDP(contourMat, approxCurve, 10, true);//找出轮廓的多边形拟合曲线

    第一个参数 InputArray curve:输入的点集
    第二个参数OutputArray approxCurve:输出的点集,当前点集是能最小包容指定点集的。画出来即是一个多边形。
    第三个参数double epsilon:指定的精度,也即是原始曲线与近似曲线之间的最大距离。
    第四个参数bool closed:若为true,则说明近似曲线是闭合的;反之,若为false,则断开。


    该函数采用是道格拉斯-普克算法(Douglas-Peucker)来实现。该算法也以Douglas-Peucker算法和迭代终点拟合算法为名。是将曲线近似表示为一系列点,并减少点的数量的一种算法。该算法的原始类型分别由乌尔斯·拉默(Urs Ramer)于1972年以及大卫·道格拉斯(David Douglas)和托马斯·普克(Thomas Peucker)于1973年提出,并在之后的数十年中由其他学者予以完善。

    经典的Douglas-Peucker算法描述如下:

    (1)在曲线首尾两点A,B之间连接一条直线AB,该直线为曲线的弦;

    (2)得到曲线上离该直线段距离最大的点C,计算其与AB的距离d;

    (3)比较该距离与预先给定的阈值threshold的大小,如果小于threshold,则该直线段作为曲线的近似,该段曲线处理完毕。

    (4)如果距离大于阈值,则用C将曲线分为两段AC和BC,并分别对两段取信进行1~3的处理。

    (5)当所有曲线都处理完毕时,依次连接各个分割点形成的折线,即可以作为曲线的近似。

     

    示意图:

    展开全文
  • 多项式曲线拟合

    2018-01-12 10:14:01
    用EMGU_OpenCV的矩阵实现的多项式拟合计算,得到曲线参数。可以更改代码实现不同高次多项式曲线拟合
  • 多项式拟合正弦曲线

    千次阅读 2020-10-11 16:06:23
    用高阶多项式函数拟合曲线; 用解析解求解两种loss的最优解(无正则项和有正则项); 优化方法求解最优解(梯度下降,共轭梯度); 用你得到的实验数据,解释过拟合。 用不同数据量,不同超参数,不同的...

    目标

    掌握最小二乘法求解(无惩罚项的损失函数)、掌握加惩罚项(2范数)的损失函数优化、梯度下降法、共轭梯度法、理解过拟合、克服过拟合的方法(如加惩罚项、增加样本)。

    要求

    1. 生成数据,加入噪声;

    2. 用高阶多项式函数拟合曲线;

    3. 用解析解求解两种loss的最优解(无正则项和有正则项);

    4. 优化方法求解最优解(梯度下降,共轭梯度);

    5. 用你得到的实验数据,解释过拟合。

    6. 用不同数据量,不同超参数,不同的多项式阶数,比较实验效果。

    7. 语言不限,可以用matlab,python。求解解析解时可以利用现成的矩阵求逆。梯度下降,共轭梯度要求自己求梯度,迭代优化自己写。不许用现成的平台,例如pytorch,tensorflow的自动微分工具。

    实验环境

    Windows 10

    PyCharm 2020.3

    Python 3.7.0

    实验步骤

    1. 生成实验数据

    运用随机数生成器,生成一组满足在 [0, 1] 区间上均匀分布的(x, y)数据,其中
    y=sin(2πx)+e y = \sin(2\pi x) + e
    而e即为为满足 (0, 0.01) 正态分布的一个噪声。

    def generate_sin2pi_sample(number):
        x = np.linspace(0, 1, number).T
        y = np.sin(2 * np.pi * x) + np.random.normal(0, 0.1, number).T
        return x, y
    

    接下来将利用这组数据进行训练。

    接下来为了便于矩阵计算,将会用到x的Vandermende矩阵X。

    Vandermende矩阵的计算代码如下:

    def vandermonde(x, order):
        van = np.zeros(shape=(order + 1, x.size))
        van[0] = 1
        for i in range(order):
            van[i + 1] = van[i] * x.T
        return van
    

    2. 利用解析解拟合正弦曲线

    先通过最简单的思路解决问题。

    当我们想要拟合一条曲线时,通常我们得到的只有几个离散的数据样本 (x, y),并且与实际的曲线之间还有一些误差。我们对于目标函数的了解仅此而已。

    在这种已知条件受限的情况下,我们首先需要假设一个大概的模型,比如本次实验我们采用了多项式函数 Y(x, w) 作为拟合的模型。在此之上,还需要对这种模型的一些待定参数进行调整,使得模型能够在给定样本以外的输入上,也能做到与目标函数尽可能贴近。这种贴近的标准可以用一个与待定参数以及输入样本相关的函数来标定,称为loss函数。

    这里我们采用了以下公式作为loss函数:
    E(w)=12i=1n(Y(w,xi)y(xi))2 E(w)=\frac{1}{2} \sum_{i=1}^n{(Y(w,x_i)-y(x_i))^2}
    设多项式的次数为n,式中的 w 为 n+1 维的系数列向量,Y(w, x) 即为作为假设模型的n阶多项式函数。利用由 x 引申出的Vandermende矩阵,可以更简洁地表示成矩阵形式:
    E(w)=12(XTwy)T(XTwy) E(w) = \frac{1}{2}(X^Tw-y)^T(X^Tw-y)
    在这种条件下,我们认为当 w 可以使得 E(w) 达到最小时,预测模型 Y(w, x) 就在给定的样本上尽可能地逼近了目标函数,由此这样的 w 将作为预测模型 Y(x, w) 的参数列向量。故只要 E(w) 对 w 的导数满足:
    E(w)=XXTwXy=0 E'(w) = XX^Tw-Xy = 0

    w=(XXT)1Xy \Rightarrow w = (XX^T)^{-1}Xy

    由此,我们得到了直接通过样本得到结果的算法:

    def analysis_solution(x, y, order, rambda=0):
        van_x = vandermonde(x, order)
        w = np.dot(np.linalg.inv(np.dot(van_x, van_x.T) + rambda * np.eye(order + 1)), np.dot(van_x, y))
        return w
    

    我针对不同的多项式次数(order),以及给定样本训练集大小(sample number),利用同分布的10个样本作为验证集,得到多项式拟合函数的 E(w) (error),以此作为拟合偏差的评估标准。

    这里同一行的多项式拟合曲线次数一致,同一列的训练集大小一致。从总体上看,多项式次数和训练集个数都不是越高或者越低越好。

    这里的图像中,order=7,sample_number=100时拟合效果最好,order=7,sample_number=50则次之。

    横向比较:order=3时,sample_number越大,误差反而越大。order=12时,随着sample_number增大,error先增大,后减小。

    纵向比较:order=3时,拟合效果都是最好的。order=12时,图像都出现了各种程度的震荡,拟合程度也不佳。

    在这里插入图片描述

    3. 利用有正则项的解析解拟合正弦曲线

    在进行拟合的时候,随着拟合曲线训练程度加深,将会逐步贴近目标函数曲线。但是如果只用目前形式 E(w) ,函数在最优化的时候,只会保证尽可能讲过所有的给定训练集上的点,但是在其他点上的拟合效果就未必有那么好了。

    从一定程度上,曲线的复杂程度与系数列向量 w 是相关的。w 的“绝对值”越小,曲线越区域平缓,拟合程度一般都会更好。所以,我们将 w 的2-范数也添加到 E(w) 中,使得训练过程中,算法也会将 w 的2-范数纳入最优化的考察范围中。由此改写 E(w) 如下:
    E(w)=12(XTwy)T(XTwy)+λ2wTw E(w) =\frac{1}{2}(X^Tw-y)^T(X^Tw-y) + \frac{\lambda}{2}w^Tw
    代码同无正则项的解析解之算法,只是传入的参数 rambda 将会是一个正数。

    def analysis_solution(x, y, order, rambda=0):
        van_x = vandermonde(x, order)
        w = np.dot(np.linalg.inv(np.dot(van_x, van_x.T) + rambda * np.eye(order + 1)), np.dot(van_x, y))
        return w
    

    取 rambda = 0.001,图像如下:

    在这里插入图片描述

    取rambda=0.01,图像如下:
    在这里插入图片描述
    取rambda=0.1,图像如下:

    在这里插入图片描述

    可以看到,随着rambda增加,图像整体曲线将趋于平缓,尤其是有效解决了高次数(order=12)时,曲线震荡的问题。但是,rambda也不是越大越好,如果rambda过大,将会使得曲线整体与训练集的点的偏移增加。拟合效果反而变差了。

    4. 利用梯度下降法拟合正弦曲线

    梯度下降法是一种迭代求解的技术,针对想要最优化为最小值的多元函数 E(w) ,梯度下降法每次迭代都求解当前 w 的梯度,并让 w 向逆梯度方向发生一定变化,由此不断迭代到想要的解的邻域内,在一定误差范围内即可输出当前 w 作为 min{E(w)} 的解。

    这种方法实际上只能找到局部最优解,但是由于 E(w) 是一个凸函数,因此局部最优即为全局最优,适合使用梯度下降法。

    具体算法代码如下,其中输入参数rambda=0:

    def gradient_descent(x, y, order, acceptable_grad, learning_rate, rambda):
        van_x = vandermonde(x, order)
        w = np.zeros(order + 1).T
        grad = np.dot(van_x, Y(w, van_x) - y) + (rambda * w)
        cnt = 0
        while np.sum(np.abs(grad)) >= acceptable_grad:
            w = w - learning_rate * grad
            grad = np.dot(van_x, Y(w, van_x) - y) + (rambda * w)
            if cnt % 100000 == 0:
                print("cnt[", cnt, "] grad:")
                print(grad)
                print("w:")
                print(w)
            cnt += 1
        return w
    

    其中的cnt局部变量和标准输出语句是为了确认迭代速度,结束条件是当前 w 所有在梯度的 1-范数 小于一定值acceptable_grad。

    以下为输出结果:

    当acceptable_grad = 0.01时

    在这里插入图片描述

    当acceptable_grad = 0.1时:

    在这里插入图片描述

    另外,梯度下降法比起其他算法,需要的时间都是没有保证的。

    5. 利用有正则项的梯度下降法拟合正弦曲线

    同样的道理,正则项也可以放到梯度下降的损失函数的。

    以下为acceptable_grad=0.001,rambda=0.01的图像。

    在这里插入图片描述

    6. 利用共轭梯度法拟合正弦曲线

    共轭梯度法每次选取一个与之前变化方向共轭的新方向,让 w 向特定的方向进行变化,理论上可以在n步以内达到最优解。(n为目标函数所在空间的维数)

    代码如下,其中rambda=0

    def conjugate_gradient(x, y, order, acceptable_grad, rambda):
        van_x = vandermonde(x, order)
        w = np.zeros(order + 1).T
        A = np.dot(van_x, van_x.T) + rambda * np.eye(order + 1)
        b = np.dot(van_x, y)
        p = b - np.dot(A, w)
        beta = 0
        cnt = 0
        while True:
            grad = np.sum(np.abs(np.dot(A, w) - b))
            if grad < acceptable_grad:
                print("cnt: ", cnt)
                print(w)
                return w
            if cnt % 100000 == 0:
                print("cnt: ", cnt, " grad: ", grad)
            r = b - np.dot(A, w)
            beta = beta * np.dot(-1 * r.T, -1 * r)
            p = r + beta * p
            beta = 1 / np.dot(-1 * r.T, -1 * r)
            w = w + (-1) * (np.dot(-1 * r.T, p) / np.dot(np.dot(p.T, A), p)) * p
            cnt += 1
        print("cnt: ", cnt)
        print(w)
        return w
    

    这里在n步之后输出 w,或者在n不之内已经达到了预想的误差范围内的话,直接输出结果。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BIrEotak-1602403024551)(C:\Users\laish\Desktop\work\con_ac_1e-3.png)]

    7. 利用有正则项的共轭梯度法拟合正弦曲线

    同理使用正则项,应用上一节的代码。其中rambda>0。

    rambda=1e-3:

    在这里插入图片描述

    rambda=1e-10:

    在这里插入图片描述

    rambda=1e-100:

    在这里插入图片描述

    这里可以看出正则项的出现,反而让拟合结果恶化了。

    理解过拟合

    在这里插入图片描述

    可以看到在上述实验结果当中,当rambda很小,样本数量较少,以及多项式次数较高时,都容易产生类似于图中的现象。也许函数还能比较好的拟合给定的训练集,但是明显偏离了目标函数。

    要解决这种问题,一般有3中思路:

    一个是降低多项式次数:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0MarC13w-1602403024557)(C:\Users\laish\AppData\Roaming\Typora\typora-user-images\image-20201011144905448.png)]

    一个是增加训练集的大小:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ddycwYi-1602403024558)(C:\Users\laish\AppData\Roaming\Typora\typora-user-images\image-20201011144924772.png)]

    一个是添加正则项:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g0l6oCj5-1602403024559)(C:\Users\laish\AppData\Roaming\Typora\typora-user-images\image-20201011144951720.png)]

    其中,正则项的参数lambda的选取是有讲究的。lambda不能太小,否则正则项的作用微乎其微;正则项也不能太大,否则拟合曲线将会变成不会经过训练集样本的“平滑”曲线:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jWIpfVmW-1602403024560)(C:\Users\laish\AppData\Roaming\Typora\typora-user-images\image-20201011145213626.png)]

    思考

    1. 我们在进行曲线拟合的时候,运用的评估标准实际上并不能够直接反应拟合曲线对于其他点的拟合情况,而只能让曲线尽可能接近给定的训练集。同样,在使用正则项的时候,正则项也并不能直接反应曲线的曲折程度,也只是一个简洁的量化标准。要想得到一组好的参数,还是需要不断和其他参数以及模型相互比较,才能得到比较实在的结果。
    2. 运用一个最优化算法时,时间复杂度也是一个非常重要的评估标准。比如相对于解析解法和共轭梯度法,梯度下降法的时间复杂度是几乎不可控的,经常会一跑一晚上。在参数优化选择的算法还不明确的情况下,最好的解决办法就是将整个迭代过程的数值变化输出出来,实时监控;当变化非常小,但是离目标值还非常远的时候,就可以停止当前迭代,及时止损,使用更加宽松的参数条件得到结果。
    3. 在进行训练集以及验证集的选择时,在各种向度上都实现等比例划分是困难的。因此这次我使用了两个满足相同正态分布的样本集合,分别作为训练集和验证集。这是严谨的吗?从分布上看,二者确实做到了等价。那么在现实样本当中,为什么还要对得到的样本进行划分呢?前一天选取训练集,后一天选取验证集不好吗?其实在实际场景下,不会有那么大量的数据。在数据量不大的时候,又要拆分成小的集合时,单个集合本身已经很难体现原有的分布了。因此尽管可能有违我们对于“随机采样”的直觉,但是我们需要对数据进行一些预处理,使得划分处的集合能够体现出相同的分布特性。
    4. 接受条件的选择应该基于损失函数的导数,而非损失函数本身。即使用梯度下降法时,结束条件应该是 E’(w)<rate,而不是 E(w) < rate,尽管E(w)可能为0。一方面,利用导数更具有普适性;另一方面,E(w)的最小值在一定步长的情况下,可能非常难达到其邻域。
    5. 更多、更能覆盖样本空间整体的训练集,可以让拟合曲线更贴合现实。我们这次实验选取的样本点均匀分布在考察区间内,实际上是简化了模型训练难度。如果样本都集中在考察区间一个点的附近,那么训练出来的模型在其他的点上拟合效果就很难控制了。
    6. 更复杂的模型表现会更加灵活,但也需要更多训练样本来支持其模型的训练;如果样本数量不够,也可以加入正则项,降低其模型的复杂度。
    7. 参数的选取都是一个折衷的选择,选大选小都有各自的优劣。模型的选取也是。
    展开全文
  • 特别是,五参数对数回归或5PL非线性回归模型通常用于生物测定或免疫测定(例如ELISA,RIA,IRMA或剂量React曲线)中的曲线拟合分析。 标准剂量React曲线有时称为五参数逻辑方程。 它的特点是其经典的“S”或 S 形...
  • 05-曲线拟合 曲线拟合应用案列举例 % 第5节-数据分析与多项式计算 % 05-曲线拟合 % 曲线拟合应用案列举例 % 1、股票预测问题 % 已知一只股票在2016年8月每个交易日的收盘价如下表所示,试预 % 测其后面的大体走势...
  • 05-曲线拟合 % 第四节-matlab 绘图和数据可视化 % 05-曲线拟合 % 引出举例-人口预测问题 % 问题: 数据插值再采样过程中不一定是准确的,可能会存在一定的误差 % 也就是说,数据测试或者采样的准确性直接影响...
  • 03A-参数样条与Bezier第6讲 Bézier曲线 * Bézier曲线 Bé... 例 题 用三次Bézier曲线拟合X-O-Y平面上第一象限内的一段1/4圆弧,圆弧的圆心为(0,0)点,半径为1,要求拟合曲线精确通过该圆弧的两个端点和中点,...
  • matlab学习()数据插值与曲线拟合

    万次阅读 2019-04-06 16:14:53
    与数据插值类似,曲线拟合也是一种函数逼近的方法。 构造函数g(x)去逼近未知函数f(x),使得误差 δi= g(xi)-f(xi)(i=1,2,3,…,n) 在某种意义下达到最小。 最小二乘法(又称最小平方法)是一种数学优化技术。它通过...
  • 一、实验内容已知一组实验数据如下表,求它的拟合曲线。 x(i) 1 2 3 4 5 f(i) 4 4.5 6 8 8.5 w(i) 2 1 3 1 1 二、程序清单与运行结果 M文件代码如下:function S=mypolyfit(X,F,W,m,n) % mypolyfit输出通过最小...
  • 车道线曲线拟合方法

    千次阅读 2020-04-30 19:24:20
    将采集来的车道线数据进行曲线拟合可以很好的估计车道线的参数信息,得知偏移量、倾斜角、曲率半径等信息,从而预测车道线的走向,为驾驶员或车辆自动控制系统提供帮助。现有的主流算法是将采集的车道线数据投影到...
  • 用三次贝塞尔曲线拟合圆弧

    千次阅读 2015-09-16 18:03:12
    三次贝塞尔曲线拟合圆弧的推演过程。
  • 最小二乘法拟合 基本原理: https://baike.baidu.com/item/...fr=aladdin 基本公式: !... 参数方程化: 由于在使用普通方程求解矩阵时,要求XTX可逆。但是我们在局部路径拟合时会经常遇到如下场景,在这种场景下无...
  • 采用matlab实现NURBS逼近曲线拟合,利用app designer实现拟合的界面,辅助验证各种方法。文中主要是自己实现写的算法,可以得到逼近曲线,以及进行曲线性能的简单评判。 文中只简单介绍了一些理论,也是个人的...
  • 用最小二乘法拟合二元多次曲线 高斯消元法代码: C#: public class LeastSquareMethod { ///<summary> ///用最小二乘法拟合二元多次曲线 ///例如y=ax+b ///其中MultiLine将返回a,b两个参数。 ///a...
  • 基于粒子群算法与最小二乘拟合函数参数

    千次阅读 多人点赞 2020-04-07 21:30:49
    今天更新较晚主要还是学业繁忙,学习素材也不是很好找,可能很多同学们都在做数学建模以及应用统计时都会涉及到函数参数拟合的问题,一般最常用的方法是最小二乘法,但是当函数参数很多时,往往去普通最小二乘法迭代...
  • 作者:桂。 时间:2017-03-11 06:45:46 ... 声明:欢迎转载,不过记得注明...数据拟合中,最常用的两个就是曲线拟合(curve fitting)与分布拟合(distribution fitting),不求面面俱到,只希望串出一个思路,篇目如...
  • 航空等 工 业中都 需要很 好地 解决 样条 曲线拟合的问 题 . 即对 于给定 的一组 离散的有序 点列 要求连 出适 当的曲线使得保 持光顺 , 而且 要便 于数控 绘图 的数据处 理 , 本 文目的是提供 一 种曲线 拟合 和...
  • 前面系列文章讲过各种知识,包括绘制曲线、散点图、...这篇文章主要讲述调用Scipy扩展包的curve_fit函数实现曲线拟合,同时计算出拟合的函数、参数等。希望文章对你有所帮助,如果文章中存在错误或不足之处,还请海涵~
  • 一、什么是学习曲线 学习曲线是不同训练集大小,模型在训练集和验证集上的得分变化曲线。 学习曲线图的横坐标是x_train的数据量,纵坐标是对应的train_score, test_score。随着训练样本的逐渐增加,算法练出的模型...
  • 用numpy进行曲线拟合~

    千次阅读 2014-12-09 11:34:21
    # -*- coding: cp936 -*- import numpy import pylab def plot_polynomail_fit(matrix,col,*...但是可以对这一组数据同时拟合多条曲线并显示。 matrix:存放的是需要拟合的数据,其中每一列代表一组待拟合数据。 c
  • 前几天导师给我派了个活: ...本来用origin也能完成这项工作,但是origin里拟合曲线参数复制到excel里居然会自动降低精度,是可忍孰不可忍!我怎么可能用手输入!于是只能自己写代码处理。。。 以下就是
  • 拟合算法

    2020-07-05 23:55:19
    寻求一个函数(曲线),使得该曲线在某种准则...避免极端数据对拟合曲线的影响 最小二乘法得到的结果和MLE极大似然估计一致 不用奇数次方的原因:误差会正负相抵。 求解最小二乘法 Matlab求解最小二乘 clc;clear;.
  • 选择拟合曲线的类型 1.实例介绍 已知 x = [0 0.2 0.50.8 0.9 1.3 1.4 1.9 2.1 2.2 2.5 2.6 2.9 3.0]; y = [1.27792.1596 2.7311 2.5974 2.4068 1.6215 1.4178 0.9955 0.9666 0.8837 0.9639 1.0
  • 章:插值与拟合

    2019-08-12 11:30:36
    %非线性拟合的答案是不唯一的,给出拟合参数的上下界 lb=zeros(2,1); %这里是随意给的拟合参数的下界,无下界时,默认值是空矩阵[] ub=[20;2]; %这里是随意给的拟合参数的上界,无上界时,默认值是空矩阵[] canshu=...
  • 具体的证明过程我也不会,书上提到了对于抛物线采用多项式拟合的方法,好像是将x,x^2,看成了两个变量。 但核心公式只有一个,下面这个正则方程组 把上面这个方程简写成 xa=y(x、a、y分别对应一个矩阵)可以...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,108
精华内容 4,043
关键字:

五参数拟合曲线