返回介绍

优化

发布于 2025-02-19 23:54:15 字数 8112 浏览 0 评论 0 收藏 0

高阶导数(Higher Derivatives)

高阶导数的递归式定义为:
函数阶导数(或记为)为:

如果将求导数看作是一个运算符,则相当于反复对运算的结果使用次运算符:

from sympy.abc import x
from sympy.abc import y
f = x**2*y-2*x*y
# 求关于 x 的二次导数
print f.diff(x,2)
# result : 2*y
# 等同于反复关于 x 求两次导数
print f.diff(x).diff(x)
# result : 2*y
# 先求关于 x 的导数,再求关于 y 的导数,这个该怎么解读?
print f.diff(x,y)
# result : 2*(x - 1)

优化问题(Optimization Problem)

很多时候,我们用函数来描述我们关心的问题,例如:

plt.figure(1, figsize=(4,4))
plt.axis('off')
plt.axhspan(0,1,0.2,0.8,ec = "none")
plt.axhspan(0.2,0.8,0,0.2,ec = "none")
plt.axhspan(0.2,0.8,0.8,1,ec = "none")

plt.axhline(0.2,0.2,0.8,linewidth = 2, color = 'black')
plt.axvline(0.2,0.17,0.23,linewidth = 2, color = 'black')
plt.axvline(0.8,0.17,0.23,linewidth = 2, color = 'black')

plt.axvline(0.2,0.8,1,linewidth = 2, color = 'black')
plt.axhline(0.8,0.17,0.23,linewidth = 2, color = 'black')
plt.axhline(1,0.17,0.23,linewidth = 2, color = 'black')

plt.text(0.495,0.22,r"$l$", fontsize = 18,color="black")
plt.text(0.1,0.9,r"$\frac{4-l}{2}$", fontsize = 18,color="black")

plt.show()

09-01Box

用一张给定边长的正方形纸来折一个没有盖的纸盒,设纸盒的底部边长为,纸盒的高为,那么纸盒的体积为:

我们会希望知道怎样才能使得纸盒的容积最大,也就是关心在,的限制条件下,函数的最大值是多少。
优化问题关心的就是这样的问题,在满足限制条件的前提之下,怎样能够使我们的目标函数最大(或最小)。

  l = np.linspace(0,4,100)
  V = lambda l: 0.5*l**2*(4-l)
  plt.plot(l,V(l))

09-02 Volume

通过观察函数图,不难看出,在的值大约在往上去一点的位置处,获得的纸盒的体积最大。

关键点(Critical Points)

通过导数一节,我们知道一个函数在某处的导数所描述的是:当输入值在该位置附近变化时,函数值所发生的相应变化。
因此,如果给定一个函数,如果知道在点处函数的导数不为,则在该点出稍微改变函数的输入值,函数值都会变化,这表示函数在该点的函数值即不可能是局部最大值,也不可能是局部最小值。相反,如果函数在点处函数的导数为,或者该点出的导数不存在则称这个点就被称为关键点。

要想知道一个的关键点处,函数值是一个局部最大值还是局部最小值,可以使用二次导数测试:

  1. 如果,则函数处的函数值是局部最小值
  2. 如果,则函数处的函数值是局部最大值
  3. 如果,则测试无法告诉我们结论

二次导数测试在中学书本中,大多是要求不求甚解地记忆的规则,其实理解起来非常容易。二次导数测试中涉及到函数在某一点处的函数值、一次导数和二次导数,于是想处的泰勒级数:

因为为关键点,,因而:

表明时,函数附近的表现近似于二次函数,二次项的系数决定了抛物线的开口朝向,因而决定了函数值在该点是怎样的。

回到之前的求最大盒子体积的优化问题,解法如下:

from sympy.abc import l
V = 0.5*l**2*(4-l)
# 看看一次导函数:
print V.diff(l)
# output is : -0.5*l**2 + 1.0*l*(-l + 4)
# 一次导函数的定义域为(-oo,oo),因此关键点为 V'(l)=0 的根
cp = sympy.solve(V.diff(l),l)
print cp
# output is: [0.0, 2.66666666666667]
# 找到关键点后,使用二次导数测试:
for p in cp:
  print V.diff(l,2).subs(l,p)
# output is: 4, -4
# 因此知道在 l=2.666666 处时,纸盒的体积最大

线性回归(Linear Regression)

二维平面上有个数据点,,现尝试找到一条经过原点的直线,使得所有数据点到该直线的残差(数据点和回归直线之间的水平距离)的平方和最小。

# 设定好随机函数种子,确保模拟数据的可重现性
np.random.seed(123)

# 随机生成一些带误差的数据
x = np.linspace(0,10,10)
res = np.random.randint(-5,5,10)
y = 3*x + res

# 求解回归线的系数
a = sum(x*y)/sum(x**2)

# 绘图
plt.plot(x,y,'o')
plt.plot(x,a*x,'red')
for i in range(len(x)):
  plt.axvline(x[i],min((a*x[i]+5)/35.0,(y[i]+5)/35.0),\
     max((a*x[i]+5)/35.0,(y[i]+5)/35.0),linestyle = '--',\
     color = 'black')

09-03LinReg

要找到这样一条直线,实际上是一个优化问题:

要找出函数的最小值,首先计算一次导函数:


令该函数为,求解出关键点:
使用二次导数测试:

因此是能够使得函数值最小的输入。

这也是上面 Python 代码中,求解回归线斜率所用的计算方式。

如果我们不限定直线一定经过原点,即公式为,则同样还是一个优化问题,只不过涉及的变量变成 2 个而已:

这个问题就是多元微积分里所要分析的问题了。

虽然在第二部分才会介绍具体解法,这里先给出一种 Python 中的求解方法:

slope, intercept = np.polyfit(x,y,1)
plt.plot(x,y,'o')
plt.plot(x,a*x,'red', linestyle = '--')
plt.plot(x,slope*x+intercept, 'blue')

09-04LinFit

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文