Himmelblau函数是一个二维四次函数,它得名于数学家Himmelblau,该函数常用于测试优化器的性能。
绘制Himmelblau图像
通过作图,初步探查该函数的一些基本性质。
import numpy as np
import sys
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import LinearSegmentedColormap
def Himmelblau(x):
return (x[0]**2 + x[1] - 11 )**2 + (x[0]+x[1]**2 -7) **2
x = np.arange(-6,6,0.1)
y = np.arange(-6,6,0.1)
X,Y = np.meshgrid(x,y)
Z = him([X,Y])
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X,Y,Z)
ax.view_init(90 , 0)
ax.set_xlabel('x[0]')
ax.set_ylabel('x[1]')
fig.show()
效果如下图所示:
不难观察一共有四个极小值点。
求解该函数的最小值
求极值,使用梯度下降的思想,一般情况下推荐选择的优化器为Adam,但是这优化器往往花费大量的迭代次数,傻瓜式迭代器,只要迭代次数足够大(经验值两万)…这里我使用了SGD优化器,给以比较小的学习率和动量值。
给的学习率稍稍过大就会使之发散,而动量值就没有那么娇气了,它的变化范围可以稍微大一点,自选即可。
import torch
def Himmelblau(x):
return (x[0]**2 + x[1] - 11 )**2 + (x[0]+x[1]**2 -7) **2
x = torch.tensor([-1., 0.] , requires_grad = True) # 初始值的设定
optimizer = torch.optim.SGD([x,] , lr = 0.02 , momentum = 0.6 )
for step in range(101) :
if step :
optimizer.zero_grad()
f.backward()
optimizer.step()
f = Himmelblau(x)
if step % 10 == 0 :
print('step {} : x = {} , f(x) = {} '.format(step , x.tolist() , f))
本代码迭代100次即可求解该函数的四个极值点.
其中初始值的设定
可以分别是(-1,0),(0,0),(4,0),(-4,0)
,即可分别求出四个解。如下图所示:
老哥看书学的还是视频?