确定数据的回归系数 - MATLAB
Determining regression coefficients for data - MATLAB
我正在做一个涉及科学计算的项目。以下是我经过一些实验得到的三个变量及其值。
还有一个包含三个未知数的方程式,a
、b
和 c
:
x=(a+0.98)/y+(b+0.7)/z+c
如何使用上面的方法获取 a,b,c
的值?这在 MATLAB 中可行吗?
这听起来像是一个回归问题。假设测量中无法解释的误差服从高斯分布,您可以通过 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
存储参数a
、b
和c
,我们得到:
params =
-37.7383
-37.4008
19.5625
如果您想仔细检查这些值的接近程度,您可以简单地在 post 中使用上面的表达式并与 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
你可以看到它并不完全接近,但是你得到的参数在最小二乘误差意义上是最好的。
奖金 - 适合 运行SAC
您可以看到一些预测值(输出中的右列)比其他预测值更偏。这是因为我们使用了您数据中的所有点来找到合适的模型。一种用于最小化误差并提高模型估计稳健性的技术是使用称为 RANSAC 或 运行dom SAmple C共识。 运行SAC 背后的基本方法是,对于一定数量的迭代,您获取数据并 运行dom 仅对找到模型所需的最少点进行采样。找到此模型后,如果使用这些参数来描述数据,就会发现总体错误。您保持 运行dom 只选择点,找到您的模型,并找到错误和产生最少错误量的迭代将是您定义整体模型的参数。
正如您在上面看到的,我们可以定义的一个错误是真实 x
点与预测 x
点之间的绝对差之和。还有许多其他度量,例如误差平方和,但现在让我们坚持使用一些简单的方法。如果您看一下上面的公式,我们至少需要 三个方程 才能定义 a
、b
和 c
,以及所以对于每次迭代,我们运行dom只有select三个点没有替换我可能会添加,找到我们的模型,确定错误,并不断迭代并找到误差最少的参数。
因此,您可以像这样编写 运行SAC 算法:
%// 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
你可以看到第二个值比上一个版本更差,但其他数字更接近真实值。
玩得开心!
我正在做一个涉及科学计算的项目。以下是我经过一些实验得到的三个变量及其值。
还有一个包含三个未知数的方程式,a
、b
和 c
:
x=(a+0.98)/y+(b+0.7)/z+c
如何使用上面的方法获取 a,b,c
的值?这在 MATLAB 中可行吗?
这听起来像是一个回归问题。假设测量中无法解释的误差服从高斯分布,您可以通过 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
存储参数a
、b
和c
,我们得到:
params =
-37.7383
-37.4008
19.5625
如果您想仔细检查这些值的接近程度,您可以简单地在 post 中使用上面的表达式并与 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
你可以看到它并不完全接近,但是你得到的参数在最小二乘误差意义上是最好的。
奖金 - 适合 运行SAC
您可以看到一些预测值(输出中的右列)比其他预测值更偏。这是因为我们使用了您数据中的所有点来找到合适的模型。一种用于最小化误差并提高模型估计稳健性的技术是使用称为 RANSAC 或 运行dom SAmple C共识。 运行SAC 背后的基本方法是,对于一定数量的迭代,您获取数据并 运行dom 仅对找到模型所需的最少点进行采样。找到此模型后,如果使用这些参数来描述数据,就会发现总体错误。您保持 运行dom 只选择点,找到您的模型,并找到错误和产生最少错误量的迭代将是您定义整体模型的参数。
正如您在上面看到的,我们可以定义的一个错误是真实 x
点与预测 x
点之间的绝对差之和。还有许多其他度量,例如误差平方和,但现在让我们坚持使用一些简单的方法。如果您看一下上面的公式,我们至少需要 三个方程 才能定义 a
、b
和 c
,以及所以对于每次迭代,我们运行dom只有select三个点没有替换我可能会添加,找到我们的模型,确定错误,并不断迭代并找到误差最少的参数。
因此,您可以像这样编写 运行SAC 算法:
%// 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
你可以看到第二个值比上一个版本更差,但其他数字更接近真实值。
玩得开心!