使用Sympy

时间:2018-11-09 08:18:50

标签: python python-2.7 sympy gradient-descent

我正在针对Python 2.7中的Sympy库中的两个变量进行梯度下降算法实现的练习。

我的目标是按照以下步骤使用导数向量找到两个变量函数中的最小值:

  1. 对于两个变量的函数f(a,b)定义第一个矩阵 偏微分- M
  2. 然后,我将a,b的指定点(例如 V0 =(1.0,1.0))传递给M,并将其逐步乘以-得到 M0 *矩阵。
  3. 接下来,从的向量减去上面计算的结果 起始值- V0 。这给出了变量a,b- V1 的新向量。
  4. 最后,将 V1 的值再次放入M。如果矩阵 M 的结果小于epsilon =>,则继续迭代。

随附代码和步骤说明。我认为问题出在while循环中,因为它给出了耗损值,并且算法仅执行了第一个i迭代。 enter image description here

能否请您提出改进建议?

import sympy as sp
from sympy import *
from sympy import lambdify

a=Symbol('a')
b=Symbol('b')
alpha=Symbol('alpha')

def test_f(a, b):
    # define a test function of a,b
    test_f=4*a**2 + 25*b**2 
    return test_f

def deriv_matrix(f, a, b):
    # define the matrix of derivatives
    d1=diff(f(a,b), a, 1)
    d2=diff(f(a,b), b, 1)
    M=Matrix([d1,d2])
    return M

epsilon=0.02
alpha=0.1
i=1 # strat the iteration from 1
vector1=Matrix([1,1]) # starting point 

while (i<100) & (f(vector1[0], vector1[1]).all()> epsilon):
    f = lambdify((a,b), deriv_matrix(test_f, a, b))
    vector=vector1
    N=-(alpha/i)*f(vector[0],vector[1])
    vector1=vector1+N
    i+=i
print vector1

1 个答案:

答案 0 :(得分:0)

该代码有太多问题要列出。作为一个小样本:f未定义,但显然它的返回值具有方法.all()(在NumPy中返回布尔值),然后将其与epsilon进行比较?没有意义。通常,使用SymPy时,不需要将符号函数编码为Python函数。它们以SymPy表达式表示,可以在需要速度时进行lambd化,或者在速度不成问题时直接使用subs进行评估。例如:

from sympy import *    
a, b = symbols('a b')
f = 4*a**2 + 25*b**2     # this is a SymPy expression, not a function
grad_f = lambdify((a, b), derive_by_array(f, (a, b)))   # lambda from an expression for graduent

epsilon = 0.02
alpha = 0.01      # the value of 0.1 is too large for convergence here
vector = Matrix([1, 1])  

for i in range(100):    #  to avoid infinite loop
    grad_value = Matrix(grad_f(vector[0], vector[1]))
    vector += -alpha*grad_value
    if grad_value.norm() < epsilon:   #  gradient is small, we are done 
        break          

if grad_value.norm() < epsilon:
    print('Converged to {}'.format(vector))    # only print vector if successful
else:
    print('Failed to converge')