C语言逻辑回归截距梯度计算异常:printf影响结果
C语言逻辑回归截距梯度计算异常:printf语句影响结果的原因与修复
问题现象
用C语言实现逻辑回归时,计算截距(b)的梯度出现诡异问题:在gradient_i()函数的循环中,不添加printf("h_%d, %lf\n", j, y_hat_j);语句时,截距梯度结果为错误的0.1176;添加该语句后,结果变为正确的0.86。原以为sigmoid_j()和log_odds_pred()函数运行正常,实际问题藏在后者中。
根本原因
问题出在log_odds_pred()函数里的未初始化变量:
double log_odds_pred(double *theta, double *b, float x[2][2], int ex_number){ double result; // 这里未初始化,值是随机垃圾值 for(int i=0; i<n;i++){ result += (*(theta+i)) * (x[i][ex_number]); } result += *b; return result; }
result声明后没有赋值初始值,它会持有栈内存里的随机垃圾值。当你不添加printf时,这个随机值会参与后续的累加计算,导致y_hat_j完全错误,最终梯度结果异常;而添加printf后,栈内存的布局被改变,result恰好被覆盖为0(或其他不影响正确计算的值),所以得到了正确结果。这种行为属于未定义行为,完全依赖编译器和运行时的内存状态。
修复方案
给log_odds_pred()里的result初始化一个初始值0即可:
double log_odds_pred(double *theta, double *b, float x[2][2], int ex_number){ double result = 0; // 初始化result为0 for(int i=0; i<n;i++){ result += (*(theta+i)) * (x[i][ex_number]); } result += *b; return result; }
修复后,无论是否添加printf语句,log_odds_pred()都会正确计算对数几率,y_hat_j的值稳定,最终截距梯度会固定为正确的0.86。
额外建议
- 养成变量声明时立即初始化的习惯,尤其是局部变量,避免未定义行为。
- 调试此类问题时,可以用编译器的警告功能(比如GCC的
-Wall参数),编译器会直接提示未初始化变量的问题:warning: 'result' is used uninitialized in this function。
内容的提问来源于stack exchange,提问作者dkristof04
相关产品推荐
相关产品推荐

