《用 Python 学微积分》笔记 3
《用 Python 学微积分》原文见参考资料 1。
16、优化
用一个给定边长 4 的正方形来折一个没有盖的纸盒,设纸盒的底部边长为 l,则纸盒的高为 (4-l)/2,那么纸盒的体积为:
$$V(l)=l^2frac{4-l}{2}$$
怎样才能使纸盒的容积最大?也就是在 l>0,4-l>0 的限制条件下,函数 V(l) 的最大值是多少?
优化问题关心的就是这样的问题,在满足限制条件的前提下,怎么才能使目标函数最大(或最小)?
先来看下 V(l) 的函数图形:
import numpy as np import matplotlib.pyplot as plt l = np.linspace(0,4,100) V = lambda l: 0.5*l**2*(4-l) plt.plot(l,V(l)) plt.show()
看得出来,V(l) 在大约 2.5 处最大。
如果给定一个函数,知道它在点 x=a 处的函数导数为 0,或者该点的导数不存在,则称该点为关键点。要想知道 f(a) 是局部最大值还是局部最小值,可以使用二次导数测试。
如果 f''(a)>0,则函数 f 在 a 处的函数值是局部最小值。
如果 f''(a)<0,则函数 f 在 a 处的函数值是局部最大值。
如果 f''(a)=0,则测试无法告诉我们结论。
上述二次导数测试可以从泰勒级数中推导出来。f(x) 在 x=a 处的泰勒级数为:
$$f(x)=f(a)+f'(a)(x-a)+frac{1}{2}f''(a)(x-a)^2+dots$$
因为 a 为关键点,f'(a)=0,所以:
$$f(x)=f(a)+frac{1}{2}f''(a)(x-a)^2+O(x^3)$$
当 f''(a)≠0 时,f(x) 在 x=a 附近的表现近似于二次函数,二次项的系数 0.5f''(a) 决定了抛物线的开口朝向,因而决定了函数值在该点是怎样的。
回到之前求最大盒子体积的问题,解法如下:
import sympy 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处时,纸盒的体积最大
17、线性回归
二维平面上有 n 个数据点,pi=(xi,yi),现尝试找到一条经过原点的直线,y=ax,使得所有数据点到该直线的残差的平方和最小。
import numpy as np import matplotlib.pyplot as plt # 设定好随机函数种子,确保模拟数据的可重现性 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') plt.show()