如何优雅的拟合非线性曲线

这次真的和阿猪老师学到了,深度学习降维打击数据拟合竟然是这么的高效!
某天下班,小洛在微信上忽然呼叫我:
我一看好家伙,这不是手到擒来?这也太简单了,直接开整:
一、函数拟合
众所周知,scipy就可以进行曲线拟合,直接开整:
输出效果:
某位同学一头雾水:我要的是非线性的函数,为啥出来的是一条直线?还相差这么远?
二、这个表达式是合理的吗?
优化的第一步:可以看到函数内的-b*(x-a) 首先就可以被简化成bx+a,来把参数合并掉(冷知识,在这里其实无所谓参数的正负号,优化方法会自动去进行拟合的)
输出:
这一个简单的改动,直接让mse从8e-8下降到3e-9,约20倍 。
问:为什么拟合的曲线还是一条直线,不是小洛同学想要的那条曲线?
答:因为函数使用最小二乘法对函数进行拟合,适用的范围仅为使用线性参数组合的非线性函数,例如:
其中的a0、a1即为可以拟合的参数,θ0(x)则是非线性的某些函数,而小洛给出的的函数形式并不是这样,因此用拟合出来的效果并不让人满意 。
高中生涯渐渐远去,相信同学们的数学知识忘得也差不多了,在这里简单地提一下函数拟合中需要注意的问题:
1、函数的零点、缩放参数
例如的原始形式为:
在x=0的时候y取得0.5. 如果想要在x轴上做左右平移,就需要把x替换成x+a的形式,成为:
而在y轴上做上下平移,同样地要在y替换成y+b的形式;还有横向、纵向的拉伸,也对应了x需要替换成c*x, y需要替换成d*y。因为期待被拟合的参数自行决定正负,所以放分子和分母都没关系;经过项式调整,我们形成了最终表达式,对于原先函数而言,这个格式可以支持平移和缩放的形式:

如何优雅的拟合非线性曲线

文章插图
我们把原先公式改写为上面的公式套进去,再用优化输出:
可以看到mse进一步下降到2e-9,也终于有了一点点的曲线样子,然鹅还有很大提升空间 。
2、函数的定义域
如果所选用的函数对定义域有要求,比如选用典型的对数函数log(x),y=log(ax+b)的时候 。要复习一下数学知识,知道对数函数的定义域(也就是此处ax+b的范围),要求是大于0的,但是我们给出的这个形式并不能保证ax+b一定大于0,就会超出计算范围,各大计算库此时会返回nan,此时可以在ax+b外面加一个绝对值 。
3、函数的值域
小洛要拟合的除了非线性的特点,还要注意一个问题:它的值域,也就是y能够抵达的范围 。这里如果我们确定定义域的范围是固定的范围内还好,就可以把最终拟合的值域全部算出来 。原始的值域是0~1范围内,因此就算给y加上了缩放,最终也只能到达0~c的范围内
在寻常的非线性函数的拟合里,如果需要继续使用,就需要将其转化为线性的形式,例如指数函数:
它的拟合可以取对数,让其对lny~x的关系进行拟合:
看来,函数并不能用来很好的拟合函数,即使表达式已经已经优化到最终格式,拟合出的却还是只有微微的曲线,并不是曲线的样子 。要强行用的话只能做更复杂的变换去依靠中间表达式去间接拟合 。
(那么,能不能再给力一点,这个好复杂啊不懂.jpg)
三、非线性函数拟合的通用解决法
当然对于很多同学们来说,会发现继续用函数,把非线性函数转化为若干参数与函数的乘法逻辑过于复杂,超出了自己的数学能力,那能不能有一个更通用、简单的方式去解决呢?
当然有!
作为一名工作在人工智障领域的算法工程师,现在的名词“深度学习”正是为了解决超级复杂的非线性问题而产生的,深度学习的模型正是非线性的典型代表 。这个非线性已经叠加到了人类无法用手动去对公式进行优化的复杂度 。