基于python语言的梯度下降算法实现:以 y = sinx/x 为例进行解释

本文通过Python代码演示了如何使用梯度下降算法寻找函数y=sinx/x的局部最小值。首先介绍了梯度下降的基本原理,然后展示了函数的一阶导数和二阶导数的计算。接着,提供了详细的代码实现,包括原函数、一阶导数、二阶导数的定义,以及梯度下降迭代过程。最后,代码在-15到15的范围内绘制了函数图像,并标记了经过梯度下降算法找到的局部最小点。
摘要由CSDN通过智能技术生成

基于python语言的梯度下降算法实现:以 y = sinx/x 为例进行解释

梯度下降原理:

梯度下降原理网址


y = sinx/x 函数图如下:

在这里插入图片描述


现在我们的目的通过梯度下降算法找到如下位置的点

在这里插入图片描述


函数:

原函数
y = sin ⁡ ( x ) x \displaystyle y = \frac{\sin \left(x\right)}{x} y=xsin(x)
一阶导数:
y ′ = cos ⁡ ( x ) x − sin ⁡ ( x ) x 2 y' = \frac{\cos\left(x\right)}{x}-\frac{\sin\left(x\right)}{x^2} y=xcos(x)x2sin(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′′=xsin(x)x22cos(x)+x32sin(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()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BTU_YC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值