编程以及操作思路
画彩虹图
画彩虹图需要导入以下三个包
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
彩虹图有三个坐标系,X,Y,Z 也就是说可以简单的描绘成 Z=F(X,Y) 即Z由X, Y通过某种函数关系转换而来
在画彩虹图之前我们需要确定好X Y的范围 例如:
x = np.arange(-15, 15, 0.1)
y = np.arange(-15, 15, 0.1)
然后将其转换成网格数据,不然输送给计算机的就只是间隔很大的零散点,转换成网格数据可以使用以下函数
X, Y = np.meshgrid(x, y)
然后我们来表示Z与X Y的关系,这里需要用网格化的数据,例如
Z = (10*X**2 + Y**2)/2
最后我们便可以通过Axes3D将将彩虹图画出
fig = plt.figure()
ax = Axes3D(fig)
# 画出Z的关于X Y函数图像
figure1 = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap="rainbow")
在彩虹图上画梯度下降(非gif)
好像python可以画出gif图,这里先不做讲解 等后续鄙人用到时再进行更新
梯度下降实际就是类似于求导的概念,每次X,Y减少一丢丢,看看Z变化是啥样子。故这里有两个变量:X Y下降多少----梯度值 Z变化多少---变化值
梯度值我们正常使用
来表示 , 所以X Y的梯度值可以表示为
和
, 因为
是已知的,所以
和
便也是已知的(就是对函数求个偏导)。OK,到这里便一目了然了,影响函数梯度的变量就是learningrate了,learningrate越大 X Y下降就越多,收敛就越快。
X Y一直减小,Z也跟着变。当Z变化量越来越小,就说明函数收敛了,到了极小值了(也可能极大值,那就是反向梯度了) 。那么变化量究竟要到多小,我们才能说他收敛了?那是不是得研究变化量的变化量了。其实也不用那么麻烦 就直接自己给个小一点的值吧,比如0.0000000000000001 哈哈哈哈,看个人需要。变化量越小越接近极值。
综上所述 我们要设置两个变量:learningrate 和 变化量的比较值
learningrate = 0.001
com_p = 0.0000001
做个循环,X Y每次下降
和
,去对比下Z的变化值是不是小于com_p。如果小于了 则说明收敛了,就可以退出循环,此时的X Y便最接近极值。
#a=[x,y]
#给x,y一个初始值,即你想从哪个点开始进行梯度下降
def Stochastic_GD(a):
X_t = a
while 1:
X1_list.append(X_t[0])
X2_list.append(X_t[1])
Y_list.append(Func(X_t))
X_t1 = X_t -learningrate*Der_Func(X_t)
if abs(Func(X_t1) - Func(X_t)) < com_p:
print("X minimum :", X_t1)
print("Y=", Func(X_t1))
X_list.append(X_t1[0])
Y_list.append(X_t1[1])
Z_list.append(Func(X_t1))
break
pass
X_t = X_t1
pass
在上述的循环中 我们建立了三个变量,用了记录 X Y Z每一次变化 这样 我们只需要在彩虹图中将这三个数组对应画上去便可以描绘梯度下降了。
X_list = []
Y_list = []
Z_list = []
利用plot函数把这三个数组画到彩虹图上:
figure2 = ax.plot(X_list, Y_list, Z_list, c='b')
实战
目标:利用python绘制
通过梯度下降球极小值的过程
代码实现:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
com_p = 0.0000001
learningrate = 0.001
x_1 = np.arange(-15, 15, 0.1)
x_2 = np.arange(-15, 15, 0.1)
X = [x_1, x_2]
X = np.array(X)
print(np.shape(X))
print(X.T[1, :2])
X1_list = []
X2_list = []
Y_list = []
#定义函数
def Func(x):
return (1/2*np.dot(np.array([10,1]), (x.T**2)))
#定义求导函数 对两个X分别求导
def Der_Func(x):
return np.array([10*x[0], x[1]])
#梯度下降过程
def Stochastic_GD(x):
X_t = x
while 1:
X1_list.append(X_t[0])
X2_list.append(X_t[1])
Y_list.append(Func(X_t))
X_t1 = X_t -learningrate*Der_Func(X_t)
if abs(Func(X_t1) - Func(X_t)) < com_p:
print("X minimum :", X_t1)
print("Y=", Func(X_t1))
X1_list.append(X_t1[0])
X2_list.append(X_t1[1])
Y_list.append(Func(X_t1))
break
pass
X_t = X_t1
pass
Stochastic_GD(np.array([-10, 5]))
#####################################################
# 生成网格数据
X_1, X_2 = np.meshgrid(x_1, x_2)
Y = (10*X_1**2 + X_2**2)/2
fig = plt.figure()
ax = Axes3D(fig)
# 画出y的函数图像
figure1 = ax.plot_surface(X_1, X_2, Y, rstride=1, cstride=1, cmap="rainbow")
# 画出梯度下降的过程
figure2 = ax.plot(X1_list, X2_list, Y_list, c='b')
plt.show()
实验结果: