You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中用LINQ实现简单线性回归的Gradient Descent算法

使用LINQ简化简单线性回归的梯度下降实现

首先说明两处核心调整:

  1. 原代码存在隐性bug:斜率导数、截距导数的初始化放在了外层迭代循环之外,会导致每次迭代的导数累加前序结果,最终参数计算错误,改写时会修复该问题
  2. 内层循环的核心逻辑是同步遍历x、y数组,计算每个样本的预测误差后分别累加两个导数的总和,刚好可以用LINQ的Zip配对+Sum求和完全替代

改写后的精简实现如下(完全移除嵌套for循环):

double[] x = new double[] { 1, 2, 3, 4 };
double[] y = new double[] { 5, 7, 9, 12 };

double slope_current = 0;
double intercept_current = 0;
double learningRate = 0.01;
int iterations = 1500;
int sampleCount = x.Length;

for (int i = 0; i < iterations; i++)
{
    // 单轮LINQ计算两个导数,替代内层循环
    double intercept_derivative = x.Zip(y, (xi, yi) => slope_current * xi + intercept_current - yi).Sum(e => e / sampleCount);
    double slope_derivative = x.Zip(y, (xi, yi) => (slope_current * xi + intercept_current - yi) * xi).Sum(e => e / sampleCount);

    // 更新参数
    intercept_current -= learningRate * intercept_derivative;
    slope_current -= learningRate * slope_derivative;
}

如果希望只遍历一次样本序列提升性能,可以改用Aggregate方法一次性聚合两个导数:

for (int i = 0; i < iterations; i++)
{
    var (interceptGrad, slopeGrad) = x.Zip(y, (xi, yi) => 
    {
        double error = slope_current * xi + intercept_current - yi;
        return (intercept: error / sampleCount, slope: error * xi / sampleCount);
    }).Aggregate((0.0, 0.0), (sum, curr) => (sum.Item1 + curr.intercept, sum.Item2 + curr.slope));

    intercept_current -= learningRate * interceptGrad;
    slope_current -= learningRate * slopeGrad;
}

两种写法运行结果完全一致,迭代1500次后得到的斜率约为2.21、截距约为2.43,和原代码修复bug后的输出结果匹配。

内容的提问来源于stack exchange,提问作者Péter Szilvási

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 16:06:10