首先,我要感谢参与这个宏伟项目的每个人,Math.NET救了我的命! 关于线性和非线性回归我几乎没有问题,我是土木工程师,当我攻读硕士学位时,我需要开发一个C#应用程序,根据从测试中获得的数据计算混凝土的流变参数。 其中一个描述混凝土流变行为的模型是“Herschel-Bulkley模型”,它具有以下公式:
y = T + K*x^n
x(剪切速率),y(剪切应力)是从测试中获得的值,而T,K和N是我需要确定的参数。 我知道“T”的值介于0和Ymin之间(Ymin是测试中的最小数据点),所以这就是我所做的: 由于它是非线性方程,我必须使它成为线性的,如下所示: ln(y-T)= ln(K)+ n * ln(x)
创建一个可能的T值数组,从0到Ymin,并尝试等式中的每个值, 然后通过线性回归我找到K和N的值, 然后计算SSD,并将结果存储在一个数组中, 在我完成T的所有可能值之后,我看到哪个具有最小的SSD,并使用它来找到最佳的K和N. 这个方法有效,但我觉得它不像应该的那样聪明或优雅,必须有更好的方法来做到这一点,我希望在这里找到它,它也很慢。 这是我使用的代码:
public static double HerschelBulkley(double shearRate, double tau0, double k, double n)
{
var t = tau0 + k * Math.Pow(shearRate, n);
return t;
}
public static (double Tau0, double K, double N, double DeltaMin, double RSquared) HerschelBulkleyModel(double[] shear, double[] shearRate, double step = 1000.0)
{
// Calculate the number values from 0.0 to Shear.Min;
var sm = (int) Math.Floor(shear.Min() * step);
// Populate the Array of Tau0 with the values from 0 to sm
var tau0Array = Enumerable.Range(0, sm).Select(t => t / step).ToArray();
var kArray = new double[sm];
var nArray = new double[sm];
var deltaArray = new double[sm];
var rSquaredArray = new double[sm];
var shearRateLn = shearRate.Select(s => Math.Log(s)).ToArray();
for (var i = 0; i < sm; i++)
{
var shearLn = shear.Select(s => Math.Log(s - tau0Array[i])).ToArray();
var param = Fit.Line(shearRateLn, shearLn);
kArray[i] = Math.Exp(param.Item1);
nArray[i] = param.Item2;
var shearHerschel = shearRate.Select(sr => HerschelBulkley(sr, tau0Array[i], kArray[i], nArray[i])).ToArray();
deltaArray[i] = Distance.SSD(shearHerschel, shear);
rSquaredArray[i] = GoodnessOfFit.RSquared(shearHerschel, shear);
}
var deltaMin = deltaArray.Min();
var index = Array.IndexOf(deltaArray, deltaMin);
var tau0 = tau0Array[index];
var k = kArray[index];
var n = nArray[index];
var rSquared = rSquaredArray[index];
return (tau0, k, n, deltaMin, rSquared);
}