我尝试使用梯度下降来找到函数的局部最小值,Im使用具有动量的梯度下降,但是它只会收敛到我期望的局部最小值附近的点。这是我的梯度下降函数:
Point gradient_descent(double dx, double dy, double error, double gamma, unsigned int max_iters, double moment) {
double cur_error_x = error;
double cur_error_y = error;
double cur_error_moment_x = 0;
double cur_error_moment_y = 0;
unsigned int iters = 0;
double p_error_dx;
double p_error_dy;
double v_x = 0, v_y = 0;
double v_x_pre = 0, v_y_pre = 0;
std::string savePath = "D:\\GradientDescent.csv";
std::ofstream writeFile(savePath);
writeFile << "dx,dy,E(dx;dy)\n";
double dxMin = 1000, dyMin = 1000;
do {
p_error_dx = dx;
p_error_dy = dy;
//NAG
v_x = moment * v_x_pre + gamma * dfx(p_error_dx - moment * v_x_pre , p_error_dy - moment * v_x_pre);
v_y = moment * v_y_pre + gamma * dfy(p_error_dx - moment * v_x_pre , p_error_dy - moment * v_x_pre);
dx -= v_x;
dy -= v_y;
cur_error_moment_x = (p_error_dx - dx);
cur_error_moment_y = (p_error_dy - dy);
cur_error_x = abs_val(p_error_dx - dx);
cur_error_y = abs_val(p_error_dy - dy);
printf("\ni= %i \n", iters);
printf("\nc_error x= %f\n", cur_error_x);
printf("\nc_error y= %f\n", cur_error_y);
printf("\n==================================\n");
printf("\ndx = %f , dy= %f \n", dx, dy);
printf("\n E(dx,dy)= %f\n", cost_func(dx, dy));
printf("\n==================================\n");
writeFile << dx << "," << dy << "," << cost_func(dx, dy) << std::endl;
iters++;
v_x_pre = v_x;
v_y_pre = v_y;
if (cost_func(dx, dy) < cost_func(dxMin, dyMin)) {
dxMin = dx;
dyMin = dy;
}
} while ((error < cur_error_x || error < cur_error_y) && iters < max_iters);
v_x = 0; v_y = 0;
v_x_pre = 0; v_y_pre = 0;
writeFile.close();
return Point(dxMin, dyMin);
}
这是我在云中绘制的结果比较: the function converge near the minimum