确定数据的回归系数 - MATLAB

时间:2015-06-09 18:01:10

标签: matlab matrix regression numerical-methods

我正在做一个涉及科学计算的项目。以下是我在一些实验后得到的三个变量及其值。

Here x,y,z are some variables

还有一个包含三个未知数的等式abc

x=(a+0.98)/y+(b+0.7)/z+c

如何使用上述方法获取a,b,c的值?这在MATLAB中是否可行?

1 个答案:

答案 0 :(得分:2)

这听起来像回归问题。假设测量中无法解释的误差是高斯分布的,您可以通过least squares找到参数。基本上,你必须重写方程,以便你得到ma + nb + oc = p的形式,然后你有6个方程有3个未知数(a, b, c),这些参数可以通过优化至少找到广场。因此,通过一些代数,我们得到:

za + yb + yzc = xyz - 0.98z - 0.7z

因此,m = z, n = y, o = yz, p = xyz - 0.98z - 0.7z。我会把这个留给你作为练习来验证我的代数是正确的。然后,您可以形成矩阵方程:

Ax = d

我们有6个方程,我们想要求x x = [a b c]^{T}。要解决x,您可以使用所谓的pseudoinverse来检索参数,以最大限度地减少真实输出与这些参数生成的输出之间的误差(如果您要使用相同的输入数据。

换句话说:

x = A^{+}d

A^{+}是矩阵A的伪逆,矩阵向量乘以向量d

为了将我们的想法放入代码中,我们将定义输入数据,形成A矩阵和d向量,其中每个行之间共享的行都是一个等式,然后使用伪逆来查找我们的参数。您可以使用ldivide (\)运算符来完成工作:

%// Define x y and z
x = [9.98; 8.3; 8.0; 7; 1; 12.87];
y = [7.9; 7.5; 7.4; 6.09; 0.9; 11.23];
z = [7.1; 5.6; 5.9; 5.8; -1.8; 10.8];

%// Define A matrix
A = [z y y.*z];
%// Define d vector
d = x.*y.*z - 0.98*z - 0.7*z;

%// Find parameters via least-squares
params = A\d;

params存储参数abc,我们得到:

params =

  -37.7383
  -37.4008
   19.5625

如果您想仔细检查值的接近程度,可以在帖子中使用上面的表达式,并与x中的每个值进行比较:

a = params(1); b = params(2); c = params(3);
out = (a+0.98)./y+(b+0.7)./z+c;
disp([x out])

9.9800    9.7404
8.3000    8.1077
8.0000    8.3747
7.0000    7.1989
1.0000   -0.8908
12.8700   12.8910

你可以看到它并不完全接近,但你得到的参数在最小二乘错误意义上是最好的。

奖金 - 与RANSAC配合

您可以看到一些预测值(输出中的右列)比其他值更多。这是因为我们在您的数据中使用所有点来查找相应的模型。一种用于最小化误差并增加模型估计的稳健性的技术是使用称为RANSAC RAN dom SA mple C的东西 onsensus。 RANSAC背后的基本方法是,对于一定数量的迭代,您可以获取数据并随机抽样查找模型所需的最少点数。找到此模型后,如果要使用这些参数来描述数据,则会发现总体错误。你随机选择点,找到你的模型,找到错误和产生最小误差的迭代将是你保持定义整体模型的参数。

如上所示,我们可以定义的一个错误是真实x点与预测x点之间的绝对差值之和。还有许多其他措施,例如平方误差的总和,但现在让我们坚持使用简单的东西。如果你看一下上面的公式,我们需要至少三个方程式来定义abc,对于每一个迭代,我们随机选择三个点无需替换我可能会添加,找到我们的模型,确定错误,并继续迭代并找到误差最小的参数。

因此,您可以像这样编写RANSAC算法:

%// Define cost and number of iterations
cost = Inf;
iterations = 50;

%// Set seed for reproducibility
rng(123);

%// Define x y and z
x = [9.98; 8.3; 8.0; 7; 1; 12.87];
y = [7.9; 7.5; 7.4; 6.09; 0.9; 11.23];
z = [7.1; 5.6; 5.9; 5.8; -1.8; 10.8];

for idx = 1 : iterations
    %// Determine where we would need to sample
    ind = randperm(numel(x), 3);

    xs = x(ind); ys = y(ind); zs = z(ind); %// Sample

    %// Define A matrix
    A = [zs ys ys.*zs];
    %// Define d vector
    d = xs.*ys.*zs - 0.98*zs - 0.7*zs;

    %// Find parameters via least-squares
    params = A\d;

    %// Determine error
    a = params(1); b = params(2); c = params(3);
    out = (a+0.98)./y+(b+0.7)./z+c;
    err = sum(abs(x - out));

    %// If error produced is less than current error
    %// then save parameters
    if err < cost
        cost = err;
        final_params = params;
    end
end

当我运行上面的代码时,我得到了我的参数:

final_params =

  -38.1519
  -39.1988
   19.7472

将此与我们的x相比较,我们得到:

a = final_params(1); b = final_params(2); c = final_params(3);
out = (a+0.98)./y+(b+0.7)./z+c;
disp([x out])

9.9800    9.6196
8.3000    7.9162
8.0000    8.1988
7.0000    7.0057
1.0000   -0.1667
12.8700   12.8725

正如您所看到的,值得到了改善 - 特别是第四和第六点......并将其与之前的版本进行比较:

9.9800    9.7404
8.3000    8.1077
8.0000    8.3747
7.0000    7.1989
1.0000   -0.8908
12.8700   12.8910

您可以看到第二个值比之前版本更差,但其他数字更接近真实值。

玩得开心!