Matlab 迭代求模型的最优值

Matlab 迭代求模型的最优值,matlab,Matlab,假设我有一个模型,可以表示为: y = a + b*st + c*d2 其中st是某些数据的平滑版本,a、b和c是未知的模型客户。应使用迭代过程来找到a、b和c的最佳值以及附加值alpha,如下所示 在这里,我使用我拥有的一些数据展示了一个示例。我在这里只展示一小部分数据,以了解我拥有的信息: 17.1003710350253 16.7250000000000 681.521316544969 17.0325989276234 18.0540000000000 676.

假设我有一个模型,可以表示为:

y = a + b*st + c*d2
其中st是某些数据的平滑版本,a、b和c是未知的模型客户。应使用迭代过程来找到a、b和c的最佳值以及附加值alpha,如下所示

在这里,我使用我拥有的一些数据展示了一个示例。我在这里只展示一小部分数据,以了解我拥有的信息:

17.1003710350253    16.7250000000000    681.521316544969
17.0325989276234    18.0540000000000    676.656460644882
17.0113862864815    16.2460000000000    671.738125420192
16.8744356336601    15.1580000000000    666.767363772145
16.5537077980594    12.8830000000000    661.739644621949
16.0646524243248    10.4710000000000    656.656219934146
15.5904357723302    9.35000000000000    651.523986525985
15.2894427136087    12.4580000000000    646.344231349275
15.1181450512182    9.68700000000000    641.118300709434
15.0074128442766    10.4080000000000    635.847600747838
14.9330905954828    11.5330000000000    630.533597865332
14.8201069920058    10.6830000000000    625.177819082427
16.3126863409751    15.9610000000000    619.781852331734
16.2700386755872    16.3580000000000    614.347346678083
15.8072873786912    10.8300000000000    608.876012461843
15.3788908036751    7.55000000000000    603.369621360944
15.0694302370038    13.1960000000000    597.830006367160
14.6313314652840    8.36200000000000    592.259061672302
14.2479738025295    9.03000000000000    586.658742460043
13.8147156115234    5.29100000000000    581.031064599264
13.5384821473624    7.22100000000000    575.378104234926
13.3603543306796    8.22900000000000    569.701997272687
13.2469020140965    9.07300000000000    564.004938753678
13.2064193251406    12.0920000000000    558.289182116093
13.1513460035983    12.2040000000000    552.557038340513
12.8747853506079    4.46200000000000    546.810874976187
12.5948999131388    4.61200000000000    541.053115045791
12.3969691298003    6.83300000000000    535.286235826545
12.1145822760120    2.43800000000000    529.512767505944
11.9541188991626    2.46700000000000    523.735291710730
11.7457790927936    4.15000000000000    517.956439908176
11.5202981254529    4.47000000000000    512.178891679167
11.2824263926694    2.62100000000000    506.405372863054
11.0981930749608    2.50000000000000    500.638653574697
10.8686514170776    1.66300000000000    494.881546094641
10.7122053911554    1.68800000000000    489.136902633882
10.6255883267131    2.48800000000000    483.407612975178
10.4979083986908    4.65800000000000    477.696601993434
10.3598092538338    4.81700000000000    472.006827058220
10.1929490084608    2.46700000000000    466.341275322034
10.1367069580204    2.36700000000000    460.702960898512
10.0194072271384    4.87800000000000    455.094921935306
9.88627023967911    3.53700000000000    449.520217586971
9.69091601129389    0.417000000000000   443.981924893704
9.48684595125235    -0.567000000000000  438.483135572389
9.30742664359900    0.892000000000000   433.026952726910
9.18283037670750    1.50000000000000    427.616487485241
9.02385722622626    1.75800000000000    422.254855571341
8.90355705229410    2.46700000000000    416.945173820367
8.76138912769045    1.99200000000000    411.690556646207
8.61299614111510    0.463000000000000   406.494112470755
8.56293606861698    6.55000000000000    401.358940124780
8.47831879772002    4.65000000000000    396.288125230599
8.42736865902327    6.45000000000000    391.284736577104
8.26325535934842    -1.37900000000000   386.351822497948
8.14547793724500    1.37900000000000    381.492407263967
8.00075641792910    -1.03700000000000   376.709487501030
7.83932517791044    -1.66700000000000   372.006028644665
7.68389447250257    -4.12900000000000   367.384961442799
7.63402151555169    -2.57900000000000   362.849178517935
接下来的结果可能没有意义,因为需要完整的数据,但这是一个例子。使用这些数据,我试图通过迭代的方式来求解

    y = d(:,1);
    d1 = d(:,2);
    d2 = d(:,3);

    alpha_o = linspace(0.01,1,10);
    a = linspace(0.01,1,10);
    b = linspace(0.01,1,10);
    c = linspace(0.01,1,10);
定义a、b和c的不同值以及模型中使用的另一个术语alpha,现在我将找到这些参数的每个可能组合,并查看哪个组合最适合数据:

% every possible combination of values
xx = combvec(alpha_o,a,b,c);

% loop through each possible combination of values
for j = 1:size(xx,2);
    alpha_o = xx(1,j);
    a_o = xx(2,j);
    b_o = xx(3,j);
    c_o = xx(4,j);

    st = d1(1);
    for i = 2:length(d1);
        st(i) = alpha_o.*d1(i) + (1-alpha_o).*st(i-1);
    end
    st = st(:);

    y_pred = a_o + (b_o*st) + (c_o*d2);
    mae(j) = nanmean(abs(y - y_pred));
end
然后,我可以使用以下最佳值重新运行模型:

[id1,id2] = min(mae);
alpha_opt = xx(:,id2);
st = d1(1);
for i = 2:length(d1);
    st(i) = alpha_opt(1).*d1(i) + (1-alpha_opt(1)).*st(i-1);
end
st = st(:);

y_pred = alpha_opt(2) + (alpha_opt(3)*st) + (alpha_opt(4)*d2);
mae_final = nanmean(abs(y - y_pred));

然而,为了得到最终答案,我需要将每个变量的初始猜测次数增加到10次以上。这将需要很长时间才能运行。因此,我想知道是否有一个更好的方法,我在这里尝试做什么?任何建议都将不胜感激

这里有一些想法:如果你能减少每个for循环中的计算量,你就有可能加快它。一种可能的方法是查找每个循环之间的公共因子,并将其移到循环外部:

如果您查看迭代,您将看到

st1=d11

st2=a*d12+1-a*st1=a*d12+1-a*d11

st3=a*d13+1-a*st2=a*d13+a*1-a*d12+1-a^2*d11

stn=a*d1n+a*1-a*d1n-1+a*1-a^2*d1n-2++1-a^n-1*d11

这意味着可以通过将这两个矩阵相乘来计算st,例如,我使用n=4来说明第一维的概念和总和:

temp1 = [  0      0       0          a     ;
           0      0       a       a(1-a)   ;
           0      a     a(1-a)    a(1-a)^2 ;
           1     (1-a)   (1-a)^2   (1-a)^3 ;]

temp2 = [  0      0        0       d1(4) ;
           0      0      d1(3)     d1(3) ;
           0     d1(2)   d1(2)     d1(2) ;
          d1(1)  d1(1)   d1(1)     d1(1) ;]

st = sum(temp1.*temp2,1)
下面是利用这个概念的代码:计算已经移出了内部for循环,只剩下赋值

 alpha_o = linspace(0.01,1,10);
 xx = nchoosek(alpha_o, 4);
 n = size(d1,1);
 matrix_d1 = zeros(n, n);
 d2 = d2';  % To make the dimension of d2 and st the same.

 for ii = 1:n 
     matrix_d1(n-ii+1:n, ii) = d1(1:ii);
 end

 st = zeros(size(d1)');  % Pre-allocation of matrix will improve speed. 
 mae = zeros(1,size(xx,1));
 matrix_alpha = zeros(n, n);

 for j = 1 : size(xx,1)
    alpha_o = xx(j,1);
    temp = (power(1-alpha_o, [0:n-1])*alpha_o)';
    matrix_alpha(n,:) = power(1-alpha_o, [0:n-1]);
    for ii = 2:n
        matrix_alpha(n-ii+1:n-1, ii) = temp(1:ii-1);
    end
    st = sum(matrix_d1.*matrix_alpha, 1);
    y_pred = xx(j,2) + xx(j,3)*st + xx(j,4)*d2;
    mae(j) = nanmean(abs(y - y_pred));
end
然后:

idx = find(min(mae));
alpha_opt = xx(idx,:);
st = zeros(size(d1)');
temp = (power(1-alpha_opt(1), [0:n-1])*alpha_opt(1))';
matrix_alpha = zeros(n, n);
matrix_alpha(n,:) = power(1-alpha_opt(1), [0:n-1]);;
for ii = 2:n
    matrix_alpha(n-ii+1:n-1, ii) = temp(1:ii-1);
end
st = sum(matrix_d1.*matrix_alpha, 1);   
y_pred = alpha_opt(2) + (alpha_opt(3)*st) + (alpha_opt(4)*d2);
mae_final = nanmean(abs(y - y_pred));

让我知道这是否有帮助

建议:不要去迭代,去最小二乘法,见。可能比迭代更快更好,但这不会限制所选值的范围。我认为我需要这样做,以便让这些值有意义。你所说的限制所选值的范围是什么意思?lscov只是使用所有点来寻找最佳拟合方程的常规最小二乘法。如果不知道要包含哪些点,请首先使用异常值检测之类的方法。例如,在应用指数过滤器的代码部分中使用了一个参数alpha,因此它必须介于0和1之间。我认为你建议的方法会找到最好的价值,在这种情况下可能不准确。如果可能,请提供一个示例。您仍然可以在y=a+b*st+c*d2部分使用最小二乘法。此外,您可以使用野蛮的武力策略或其他非线性优化器来计算alpha。这种二次优化会在每个循环中进行最小二乘计算,但最小二乘法非常快。矢量化正确吗?原文中出现了一个迭代术语sti-1。@JJM Driessen感谢您向我指出这一点!我已经更新了我的答案。