基于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()