优化器: 构建参数化模型
2019-05-07 本文已影响0人
D_Major
优化器:
- 可以找到函数取最小值时的点
- 从数据中找到参数化模型的参数, 即寻找多项式拟合曲线
- 改善股票投资组合中分配方式
优化器求最小值
import scipy.optimize as spo
def f(X):
Y = (X - 1.5)**2 + 0.5
return Y
def test_run():
Xguess = 2.0
min_result = spo.minimize(f, Xguess, method='SLSQP', options={'disp': True}) # disp表示详细描述结果
print "Minima found at:"
print "X={}, Y={}".format(min_result.x, min_result.fun)
凸函数只有一个局部最小值, 即全局最小值
误差函数
import scipy.optimize as spo
def error(line, data):
"""
line: tuple/list/array (C0, C1), C0斜率, C1截距
data: 2D-array, 点(x, y)
返回实数error
"""
err = np.sum((data[:, 1] - (line[0] * data[:, 0] + line[1])) ** 2)
return err
def fit_line(data, error_func):
"""data: (x,y) array"""
# 生成模型的初始位置guess
l = np.float32([0, np.mean(data[:, 1])]) # 斜率为0, 截距为y的均值, 即一条横着的直线
# 画出初始直线
x_ends = np.float32([-5, 5])
plt.plot(x_ends, l[0] * x_ends + l[1], 'm--', linewidth=2.0, label="Initial guess")
# 调用优化器使损失函数最小, 返回目标直线, args里的数据传给error_func
result = spo.minimize(error_func, l, args=(data,), method='SLSQP', options={'disp': True})
return result.x
def test_run():
l_orig = np.float32([4, 2]) # 原始直线, C0=4, C1=2
Xorig = np.linspace(0, 10, 21) # 等差数列, [0, 10], 21个点(含端点)
Yorig = l_orig[0] * Xorig + l_orig[1]
plt.plot(Xorig, Yorig, 'b--', linewidth=2.0, label="Original line")
# 生成噪声干扰点
noise_sigma = 3.0 # 标准差
noise = np.random.normal(0, noise_sigma, Yorig.shape)
data = np.asarray([Xorig, Yorig + noise]).T
plt.plot(data[:, 0], data[:, 1], 'go', label="Data points")
# 尝试拟合
l_fit = fit_line(data, error) # return [C0, C1]
plt.plot(data[:, 0], l_fit[0] * data[:, 1] + l_fit[1], 'r--', linewidth=2.0, label="Fit line")
plt.show()
拟合多项式曲线 np.polyval()
def error_poly(C, data):
"""
C: numpy.poly1d object or equivalent array representing polynomial coefficients(系数)
data: 2-D array (x, y)
"""
err = np.sum((data[:, 1] - np.polyval(C, data[:, 0])) ** 2)
return err
def fit_poly(data, error_func, degree=3)
"""data: 2-D array (x, y), degree: 多项式次数"""
# initial guess (all coeffs = 1) 初始系数等于1
Cguess = np.poly1d(np.ones(degree + 1, np.float32)) # 4个1, 3次多项式+1个常数项
# 画出initial guess
x = np.linspace(-5, 5, 21)
plt.plot(x, np.polyval(Cguess, x), 'm--', linewidth=2.0, label="Initial guess")
result = spo.minimize(error_func, Cguess, args=(data,), method='SLSQP', options={'disp': True})
return np.poly1d(result.x)
- np.polyfit(), 多项式曲线拟合, 获得多项式各系数:
poly = np.polyfit(x_data, y_data, deg = 1)
- np.polyval(), 多项式曲线求值, 可以理解为代入x求多项式y值:
plt.plot(x_data, np.polyval(poly, x_data))
- np.poly1d(c_or_r, r=False, variable=None), 表征多项式, 当r=False时, 传入系数矩阵c, 返回poly1d多项式对象. 当r=True时, 传入方程根, 反推多项式. variable表示用不同字母表示自变量
方法: p.c返回系数矩阵, p.r返回方程的根, p.o返回最高项次数, p(0.5)表示代入x=0.5时多项式的值, p[1]返回第一项系数
如果f(x) = 2x^2 +x +1
np.poly1d(5) # 或np.poly1d([5])
Out[77]: poly1d([5]) # 常数项
a= np.array([2,1,1])
p = np.poly1d(a)
p
Out[78]: poly1d([2, 1, 1]) # 等同于2*x^2 + 1* x^1 +1*x^0 = 2x^2 + x +1
print(p)
2 x^2 + 1 x + 1
代入值:
p([1,2,3])
Out[80]: array([ 4, 11, 22]) # 分别代入1, 2, 3的返回值
对poly1d( )对象进行加减乘除运算,相当于对应多项式函数进行计算,如:
>>> p+[-2,1] #和p+np.poly1d([-2,1])相同,-2x+1 等于2x^2 +x +1 -2x +1 = 2x^2 -x +2
Out[81]: poly1d([ 2, -1, 2])
>>> p*p #两个3次多项式相乘,得到一个6次多项式 等于(2x^2 +x +1)^2=4x^4 + 4x^3 +5x^2+2x+1
Out[82]:poly1d([4, 4, 5, 2, 1])
>>> p/[1,1] #返回2个多项式除法的结果,分别为商式和余式
Out[83]: (poly1d([ 2., -1.]), poly1d([ 2.])) (x+1)(2x-1)+2 = 2x^2+x +1
多项式对象的deriv( )和integ( )方法分别用于计算多项式函数的微分和积分,如:
>>> p.deriv() #微分
Out[84]: poly1d([4, 1])
>>> p.integ() #积分 integ(m=1,k= 0) m是积几次分,k是常数项是多少
Out[85]: poly1d([ 0.66666667, 0.5 , 1. , 0. ])
多项式函数的根可以用roots( )计算:
>>> np.roots(p)
Out[86]: array([-0.25+0.66143783j, -0.25-0.66143783j])
优化器: 优化投资组合
计算量最少最简单的优化方式是对累计收益进行优化, 只需100%投入到回报最高的股票即可
优化夏普指数:
优化分配比例使负夏普指数最小, 从而使夏普指数最大
优化器加速:
- 限定x范围, 比如将分配比例限制在[0, 1]
- 设定约束条件, 比如分配比例之和要为1