我的任务是使用梯度下降在c++中实现逻辑回归。任务的一部分是当梯度的大小低于10e-07时停止梯度下降。
我必须最小化: //chart.googleapis.com/chart?cht=tx&chl=L(w)%20%3D%20%5Cfrac%7B1%7D%7BN%7D%5Csum%20log(1%20%2B%20exp(-y_%7Bi%7Dw%5E%7BT%7Dx_%7Bi%7D))
然而,由于超过了最大迭代次数,我的梯度下降一直在停止。我尝试了不同的最大迭代阈值,它们都是最大的。我认为我的代码有问题,因为logistic回归由于其成本函数的凹性而被认为是梯度下降的一项容易的任务,梯度下降应该很容易找到最小值。
我正在使用armadillo库来处理矩阵和向量。
#include "armadillo.hpp"
using namespace arma;
double Log_Likelihood(Mat<double>& x, Mat<int>& y, Mat<double>& w)
{
Mat<double> L;
double L_sum = 0;
for (int i = 0; i < x.n_rows; i++)
{
L = log(1 + exp(-y[i] * w * x.row(i).t() ));
L_sum += as_scalar(L);
}
return L_sum / x.n_rows;
}
Mat<double> Gradient(Mat<double>& x, Mat<int>& y, Mat<double>& w)
{
Mat<double> grad(1, x.n_cols);
for (int i = 0; i < x.n_rows; i++)
{
grad = grad + (y[i] * (1 / (1 + exp(y[i] * w * x.row(i).t()))) * x.row(i));
}
return -grad / x.n_rows;
}
void fit(Mat<double>& x, Mat<int>& y, double alpha = 0.05, double threshold = pow(10, -7), int maxiter = 10000)
{
w.set_size(1, x.n_cols);
w = x.row(0);
int iter = 0;
double log_like = 0;
while (true)
{
log_like = Log_Likelihood(x, y, w);
if (iter % 1000 == 0)
{
std::cout << "Iter: " << iter << " -Log likelihood = " << log_like << " ||dL/dw|| = " << norm( Gradient(x, y, w), 2) << std::endl;
}
iter++;
if ( norm( Gradient(x, y, w), 2) < threshold)
{
std::cout << "Magnitude of gradient below threshold." << std::endl;
break;
}
if (iter == maxiter)
{
std::cout << "Max iterations surpassed." << std::endl;
break;
}
w = w - (alpha * Gradient(x, y, w));
}
}我希望梯度下降停止,因为梯度的幅度低于10e-07。
我的标签是{1,-1}。
发布于 2019-08-09 02:16:52
通过记录或绘制每次迭代的值来验证您的对数似然率是否正在朝着收敛方向增加,并检查梯度的范数是否正趋于0。你应该做梯度上升,所以增加梯度而不是减去它。如果梯度的范数一直在增加,这意味着你没有朝着最优的方向前进。另一方面,如果梯度的范数“跳来跳去”,但没有达到0,那么你应该减小步长/学习率alpha,然后再试一次。
绘制和分析这些值将有助于调试和分析您的算法。
https://stackoverflow.com/questions/57417620
复制相似问题