C语言实现多维函数梯度(偏导数)计算问题求助


我尝试实现梯度计算算法,但无法判断程序是否运行正确,因为我甚至不知道如何手动计算梯度。
我附上了参考实现的相关资料,若有人能给出输入数据示例和对应的预期输出结果,我将十分感激,我很想弄懂相关原理。同时我也想知道我的程序编写存在哪些错误。
提前感谢大家的帮助,我真的卡在这个问题上毫无进展。
初始版本代码
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <locale.h> double f(double x) { return (x * x ); } int main(int argc, char** argv) { double del = 0.1; int n; scanf_s("%d", &n); double* x; x = (double*)malloc(n * sizeof(double)); double* y; y = (double*)malloc(n * sizeof(double)); double* fx; fx = (double*)malloc(n * sizeof(double)); double* fy; fy = (double*)malloc(n * sizeof(double)); double* grad; grad = (double*)malloc(n * sizeof(double)); int i = 0; for (i = 0; i < n; i++) { printf("x[%d] = ", i); scanf_s("%lf", &x[i]); y[i] = x[i]; fx[i] = f(x[i]); } double a = 1 / del; for (i = 0; i < n; i++) { y[i] = y[i] + del; fy[i] = f(y[i]); grad[i] = a * (fy[i] - fx[i]); y[i] = x[i]; } for (i = 0; i < n; i++) { printf("%lf ", grad[i]); } }
更新版本代码
double f(double arr[], int size) { int a = sizeof(arr); for (int i = 0; i < size; i++) { arr[i] = arr[i] * arr[i]; } return *arr; } int main(int argc, char** argv) { double del = 0.1; int n; scanf_s("%d", &n); double* x; x = (double*)malloc(n * sizeof(double)); double* y; y = (double*)malloc(n * sizeof(double)); double* fx; fx = (double*)malloc(n * sizeof(double)); double* fy; fy = (double*)malloc(n * sizeof(double)); double* grad; grad = (double*)malloc(n * sizeof(double)); int i = 0; for (i = 0; i < n; i++) { printf("x[%d] = ", i); scanf_s("%lf", &x[i]); y[i] = x[i]; fx[i] = f(x,n); } double a = 1 / del; for (i = 0; i < n; i++) { y[i] = y[i] + del; fy[i] = f(y,n); grad[i] = a * (fy[i] - fx[i]); y[i] = x[i]; } for (i = 0; i < n; i++) { printf("%lf ", grad[i]); } }
解答
梯度计算基础逻辑
你使用的前向差分法数值梯度计算公式为:梯度分量 ≈ (f(x+Δ) - f(x))/Δ,你设置的Δ为0.1。如果测试函数为f(x)=x²,精确梯度为2x,前向差分计算的近似值为2x+0.1。
初始版本问题与测试用例
初始版本实现的是多个独立单变量函数的导数计算,逻辑可运行,但不属于多元函数梯度计算。
测试输入:
2 1 2
预期输出:2.100000 4.100000
更新版本错误与修正
更新后的版本存在3处核心错误:
- 函数f直接修改了传入的原数组,每次调用后原数组所有元素都会被平方,后续计算全部错误
sizeof(arr)获取的是指针的字节长度,不是数组元素长度,该写法无效- 函数仅返回数组第一个元素的平方值,不符合多元函数梯度计算要求,常规测试用多元函数为所有输入变量的平方和
修正后的函数示例:
// 计算多元函数f = sum(x_i²),不修改原数组 double f(double arr[], int size) { double sum = 0; for (int i = 0; i < size; i++) { sum += arr[i] * arr[i]; } return sum; }
修正后测试输入:
2 1 2
计算过程:
- 原函数值:
1² + 2² = 5 - 第一个变量加0.1后的函数值:
1.1² + 2² = 5.21,对应梯度分量为(5.21-5)/0.1 = 2.1 - 第二个变量加0.1后的函数值:
1² + 2.1² = 5.41,对应梯度分量为(5.41-5)/0.1 = 4.1
预期输出:2.100000 4.100000
内容的提问来源于stack exchange,提问作者user14554338
相关产品推荐
相关产品推荐

