优化器: 构建参数化模型

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)
poly = np.polyfit(x_data, y_data, deg = 1)
plt.plot(x_data, np.polyval(poly, x_data))
如果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%投入到回报最高的股票即可

优化夏普指数:

优化分配比例使负夏普指数最小, 从而使夏普指数最大

优化器加速:

  1. 限定x范围, 比如将分配比例限制在[0, 1]
  2. 设定约束条件, 比如分配比例之和要为1
上一篇下一篇

猜你喜欢

热点阅读