Python 言語に基づく勾配降下法アルゴリズムの実装: y = sinx/x を例として説明します。

Python 言語に基づく勾配降下法アルゴリズムの実装: y = sinx/x を例として説明します。

勾配降下の原理:

勾配降下原理の Web サイト


y = sinx/x 関数のグラフは次のとおりです。

ここに画像の説明を挿入します


ここでの目標は、勾配降下法アルゴリズムを通じて次の位置にある点を見つけることです。

ここに画像の説明を挿入します


関数:

元の関数:
y = sin ⁡ ( x ) x \displaystyle y = \frac{\sin \left(x\right)}{x}y=バツ( x )
一阶导数:
y ' = cos ⁡ ( x ) x − sin ⁡ ( x ) x 2 y' = \frac{\cos\left(x\right)}{x}-\frac{\sin\left(x \右)}{x^2}y=バツコス( x )バツ2( x )
二次導関数:
y '' = − sin ⁡ ( x ) x − 2 cos ⁡ ( x ) x 2 + 2 sin ⁡ ( x ) x 3 y''= -\frac{\sin(x)}{x} - \frac{2\cos(x)}{x^2}+\frac{2\sin(x)}{x^3}y「」=バツ( x )バツ22cos ( x )+バツ32( x )


コードのデモンストレーション効果:

ここに画像の説明を挿入します


コードは以下のように表示されます:

コメントは書いてありますのでご自身で閲覧してください

import numpy as np
import matplotlib.pyplot as plt

#plt.rc('text', usetex=True) #使用latex
#原函数
def fun(X):
    return np.sin(X)/X
#一阶导数
def grad(X):
    return np.cos(X)/X - np.sin(X)/(X**2)
#二阶导数
def seconds_grad(x):
    return - np.sin(x) / x - 2 * np.cos(x) / (x ** 2) + 2 * np.sin(x) / (x ** 3)
def gradient_descent(X0, ita):
    #用来保存自变量和因变量的值
    Val=list()
    Func_Value = list()

    print('Initial point is:', X0, '\n')
    X = X0
    f = fun(X) #计算原函数的值,之后用于在图像上用小红点表示出来
    print('The initial function value is:', f, '\n')
    Val.append(X) #将自变量加入
    Func_Value.append(f)#将因变量加入

    count = 0 #迭代次数
    iter_max = 100 #最大允许迭代次数
    Delta = 10 #f(k)-f(k-1) < Delta

    while count < iter_max and Delta > 10**(-4):
        count = count+1
        print('The current iteration is:', count, '\n')
        #梯度下降的公式得到下降后的自变量
        up_X = X - ita*grad(X)
        #得到下降后的因变量
        up_f = fun(up_X)
        #Delta = grad(up_X)
        #原来的函数值与下降后的函数值相减
        Delta = np.abs(f - up_f)

        X = up_X
        f = up_f
        Val.append(X)
        Func_Value.append(f)

        print('The function value is:', f, '\n')
        print('The var is:',X, '\n')
    #循环结束后的X点,即接近函数局部最低点的自变量的值
    X_end = X
    #求一阶导数
    first_grad = grad(X_end)
    #求二阶导数,用于判断是凹函数还是凸函数
    second_grad = seconds_grad(X_end)
    print('It converges after', count, 'iterations, and the local minimal is', X_end,'\n')
    print('Fisrt gradient of the local minimal point is', first_grad, '\n')
    print('Second gradient of the local minimal point is', second_grad, '\n')
    return [Val, Func_Value, count]



if __name__=="__main__":
    # y = x^2 - 2*x + 1
    #有= sin(x)/x 的函数区间为-15 到 15
    x_min = -15
    x_max = 15
    #在-15到15上取1000个平均分布的点,即自变量
    sample_num = 1000
    dot_x = np.linspace(x_min, x_max, sample_num)
    dot_y = fun(dot_x)
    #X0为在函数图像选取的一个点,之后得到会得到y = sin(X0)/X0 ,即X0 = -1 对应的函数值
    X0 = -1
    ita = 1
    #此处Val表示从X0 = -1点开始,沿函数图像的左边不断下降所记录的所有的自变量的值,运行代码是能看到图像上的点是往左下方下降的
    #此处Func_Value表示从X0 = -1点开始,沿函数图像的左边不断下降所记录的所有的的值因变量,运行代码是能看到图像上的点是往左下方下降的
    #count 表示函数迭代的次数
    #gradient_descent函数用于计算并Val和Func_value的值
    [Val, Func_Value, count] = gradient_descent(X0, ita)
    Val = np.array(Val)
    Func_Value = np.array(Func_Value)
    np.set_printoptions(formatter={
    
    'float': '{: 0.3f}'.format})
    print(Val)
    print(Func_Value)
    plt.figure()
    plt.plot(dot_x, dot_y, "-", c='b')
    for i in range(count+1):
        plt.title(r'$\eta = %.3f$, $x_{0} = %.1f$, it iterates %d steps in total' % (ita, X0, count), fontsize=10)
        plt.scatter(Val[i], Func_Value[i], color='r',s =40, marker = 'o')
        text_pt = plt.text(Val[i] + 0.1 , Func_Value[i], '', fontsize=10)
        # text_pt.set_text(r'$x_{%d}$' % i)

        # text_pt = plt.text(0, 6, '', fontsize=10)
        # text_pt.set_text(r'$x_{%d} = %.3f$' % (i, Val[i]))

        plt.pause(0.2)
    # plt.grid()
    plt.show()


おすすめ

転載: blog.csdn.net/qq_60943902/article/details/127428358