这个算法也叫盲人下山(参考了机械最优设计技术,孟兆明 常德功编著),下面是c#代码实现:
namespace 梯度下降//求函数minF(X)=x0^2+x1^2-x0*x1-15*x0+75
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int 维数N = 2;
double 收敛精度E = 0.01;
double[] X ;
private void Form1_Load(object sender, EventArgs e)
{
X = new double[维数N];
for (int n = 0; n < 维数N; n++)
{
X[n] = 0;
// X[1] = 0;
}
迭代(X[0], X[1]);
}
private void 迭代(double a0,double a1)
{
double[] X的偏导数P = new double[维数N];
//X的偏导数P[0] = 2 * X[0] - X[1] - 15;//x0^2+x1^2-x0*x1-15*x0+75=f
//X的偏导数P[1] = 2 * X[1] - X[0];
X的偏导数P[0] = 2 * a0 - a1 - 15;//x0^2+x1^2-x0*x1-15*x0+75=f
X的偏导数P[1] = 2 * a1 - a0;
//求梯度幅值
double G = 0;
for (int i = 0; i < 维数N; i++)
{
G += X的偏导数P[i] * X的偏导数P[i];
}
G = Math.Sqrt(G);
double f = a0 * a0 + a1* a1 - a0 * a1 - 15 * a0 + 75;//每迭代一次,f值都在下降
//求黑塞矩阵,此处已经求出
int H00 = 2;
int H01 = -1;
int H10 = -1;
int H11 = 2;
if (G > 收敛精度E)//继续迭代
{
//计算步长
//第一步,计算分子,内积
double 分子 = X的偏导数P[0] * X的偏导数P[0] + X的偏导数P[1] * X的偏导数P[1];
//第二步,计算分母,内*H*积
double 分母1 = X的偏导数P[0] * H00 + X的偏导数P[1] * H10;//x
double 分母2 = X的偏导数P[0] * H01 + X的偏导数P[1] * H11;//y
double 分母 = 分母1 * X的偏导数P[0] + 分母2 * X的偏导数P[1];
//第三部,步长=分子/分母
double 步长 = 分子 / 分母;
//计算第二次迭代的X1=X-步长*第一次的梯度
a0 = a0 - 步长 * X的偏导数P[0];
a1 = a1 - 步长 * X的偏导数P[1];
//继续回过头执行
迭代(a0, a1);
}
}
}
}
编译执行,迭代12次,函数方程f(x)=x0^2+x1^2-x0*x1-15*x0+75达到最小值,满足收敛精度,(x0,x1)=(9.99,4.99)。
参考如下(机械最优设计技术,孟兆明 常德功编著):