Matlab寻找合适的系数

Matlab寻找合适的系数,matlab,regression,Matlab,Regression,我有如下所述的x向量和y向量: x = [0 5 8 15 18 25 30 38 42 45 50]; y = [81.94 75.94 70.06 60.94 57.00 50.83 46.83 42.83 40.94 39.00 38.06]; 有了这些值,我如何才能找到系数y=a*(b^x) 我尝试过这段代码,但它在y=a*e^(b*x) 我知道插值技术,但我无法将其应用到我的解决方案中 非常感谢 因为y=a*b^x与log(y)=log(a)+x log(b)相同,所以您可以 >

我有如下所述的x向量和y向量:

x = [0 5 8 15 18 25 30 38 42 45 50];
y = [81.94 75.94 70.06 60.94 57.00 50.83 46.83 42.83 40.94 39.00 38.06];
有了这些值,我如何才能找到系数
y=a*(b^x)

我尝试过这段代码,但它在
y=a*e^(b*x)

我知道插值技术,但我无法将其应用到我的解决方案中

非常感谢

因为y=a*b^x与log(y)=log(a)+x log(b)相同,所以您可以

>> y = y(:);
>> x = x(:);
>> logy = log(y);
>> beta = regress(logy, [ones(size(x)), x]);
>> loga = beta(1);
>> logb = beta(2);
>> a = exp(loga);
>> b = exp(logb);
所以a和b的值是

绘制拟合曲线

>> plot(x, y, '.', x, a * b .^ x, '-') 
给你这个-

注意
回归
函数来自统计工具箱,但是您可以定义一个非常简单的版本,它可以满足您的需要

function beta = regress(y, x)
    beta = (x' * x) \ (x' * y);
end
因为y=a*b^x与log(y)=log(a)+x log(b)相同,所以您可以

>> y = y(:);
>> x = x(:);
>> logy = log(y);
>> beta = regress(logy, [ones(size(x)), x]);
>> loga = beta(1);
>> logb = beta(2);
>> a = exp(loga);
>> b = exp(logb);
所以a和b的值是

绘制拟合曲线

>> plot(x, y, '.', x, a * b .^ x, '-') 
给你这个-

注意
回归
函数来自统计工具箱,但是您可以定义一个非常简单的版本,它可以满足您的需要

function beta = regress(y, x)
    beta = (x' * x) \ (x' * y);
end

作为Chris Taylor给出的答案的扩展,该答案在对数变换域中提供了最佳线性拟合,您可以通过直接解决非线性问题,在原始域中找到更好的拟合,例如

例如,使用Chris给出的解决方案作为起点:

x = [0 5 8 15 18 25 30 38 42 45 50];
y = [81.94 75.94 70.06 60.94 57.00 50.83 46.83 42.83 40.94 39.00 38.06];

regress = @(y, x) (x' * x) \ (x' * y);

y = y(:);
x = x(:);
logy = log(y);
beta = regress(logy, [ones(size(x)), x]);
loga = beta(1);
logb = beta(2);
a = exp(loga)
b = exp(logb)
error = sum((a*b.^x - y).^2)
其中:

>> a, b, error
a =
  78.862758878038164
b =
   0.984328823937827
error =
  42.275290442577422
您可以进一步迭代以找到更好的解决方案

beta = [a; b];
iter = 20
for k = 1:iter
    fi = beta(1)*beta(2).^x;
    ri = y - fi;
    J = [ beta(2).^x, beta(1)*beta(2).^(x-1).*x ]';
    JJ = J * J';
    Jr = J * ri;
    delta = JJ \ Jr;
    beta = beta + delta;
end

a = beta(1)
b = beta(2)
error = sum((a*b.^x - y).^2)
给予:

>> a, b, error

a =
  80.332725222265623
b =
   0.983480686478288
error =
   35.978195088265906

作为Chris Taylor给出的答案的扩展,该答案在对数变换域中提供了最佳线性拟合,您可以通过直接解决非线性问题,在原始域中找到更好的拟合,例如

例如,使用Chris给出的解决方案作为起点:

x = [0 5 8 15 18 25 30 38 42 45 50];
y = [81.94 75.94 70.06 60.94 57.00 50.83 46.83 42.83 40.94 39.00 38.06];

regress = @(y, x) (x' * x) \ (x' * y);

y = y(:);
x = x(:);
logy = log(y);
beta = regress(logy, [ones(size(x)), x]);
loga = beta(1);
logb = beta(2);
a = exp(loga)
b = exp(logb)
error = sum((a*b.^x - y).^2)
其中:

>> a, b, error
a =
  78.862758878038164
b =
   0.984328823937827
error =
  42.275290442577422
您可以进一步迭代以找到更好的解决方案

beta = [a; b];
iter = 20
for k = 1:iter
    fi = beta(1)*beta(2).^x;
    ri = y - fi;
    J = [ beta(2).^x, beta(1)*beta(2).^(x-1).*x ]';
    JJ = J * J';
    Jr = J * ri;
    delta = JJ \ Jr;
    beta = beta + delta;
end

a = beta(1)
b = beta(2)
error = sum((a*b.^x - y).^2)
给予:

>> a, b, error

a =
  80.332725222265623
b =
   0.983480686478288
error =
   35.978195088265906

另一个选择是使用MATLAB,它允许您以交互方式生成拟合,还可以发出运行拟合所需的MATLAB代码


另一个选择是使用MATLAB,它可以让您以交互方式生成拟合,还可以发出运行拟合所需的MATLAB代码


我喜欢这一点,虽然这实际上是一个数学问题,而不是一个编程问题,但它很快就解决了。我要说我是一个数学家,而不是一个程序员,所以这个问题显然非常适合我!为什么我不能像你提到的那样实现log(y)=log(a)+x log(b)?如果没有回归或测试版,可能我正在使用这段代码,但实际上我没有得到解决方案。你能再描述一下吗?@Hayra我不明白你的问题是什么-你能再说一遍你的问题吗?我喜欢这样,虽然这实际上是一个数学问题,而不是一个编程问题,但它很快就解决了。我要说我是一个数学家,而不是一个程序员,所以这个问题显然非常适合我!为什么我不能像你提到的那样实现log(y)=log(a)+x log(b)?如果没有回归或测试版,可能我正在使用这段代码,但实际上我没有得到解决方案。你能再描述一下吗?@Hayra我不明白你的问题是什么-你能再说一遍你的问题吗?谢谢。看起来你的循环做了20次梯度下降迭代-对吗?这是高斯-牛顿的例子。它具有更快的收敛速度,并且不需要hessian函数。我们可以实现梯度下降,甚至是纯牛顿,因为海森函数很容易计算。谢谢。看起来你的循环做了20次梯度下降迭代-对吗?这是高斯-牛顿的例子。它具有更快的收敛速度,并且不需要hessian函数。我们可以实现梯度下降,甚至是纯牛顿,因为海森函数很容易计算。