2016-02-29 84 views
1

我想做這個「手工」,而不是使用曲面擬合工具,因爲根據我有的數據,曲面擬合可能會有所不同。所以,我首先讀取Excel表格中的數據,然後初始化一些係數,計算一個3D表面(f(x,y)),然後計算總最小平方和,我希望將其最小化。每次我運行該腳本時,它都會告訴我我處於本地最小值,即使我更改了初始值。改變容差也不會影響結果。從最基本的原則最小二乘曲面擬合

這是代碼:

% flow function in a separate .m file (approximation, it’s a negative paraboloid, maybe if required, this function may vary): 

function Q = flow(P1,P2,a,b,c,d,e,f) 
Q1 = a-b.*P1-c.*P1.^2; 
Q2 = d-e.*P2-f.*P2.^2; 
Q = Q1 + Q2; 

% Variable read, I use a xlsread instead 
p1a = [-5, -5, -5, -5, -5, -5, -5, -5, -5, -5]; 
p2a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 
qa = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; 

p1b = [-6, -6, -6, -6, -6, -6, -6, -6, -6, -6]; 
p2b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 
qb = [12, 11, 10, 9, 8, 7, 6, 5, 4, 3]; 

% Variable initialization 
coef = [50, 1, 1, 10, 1, 1]; 

% Function calculation 
q1a = flow(p1a,p2a,coef(1),coef(2),coef(3),coef(4),coef(5),coef(6)); 
q1b = flow(p1b,p2b,coef(1),coef(2),coef(3),coef(4),coef(5),coef(6)); 

% Least squares 
LQa = (qa-q1a).^2; 
LQb = (qb-q1b).^2; 
Sa = sum(LQa); 
Sb = sum(LQb); 
St = Sa+Sb; 

% Optimization (minimize the least squares sum) 
func = @(coef)(St); 
init = coef; 
opt = optimoptions('fminunc', 'Algorithm', 'quasi-newton', 'Display', 'iter','TolX', 1e-35, 'TolFun', 1e-30); 
[coefmin, Stmin] = fminunc(func, init, opt); 

如果你運行它,你應該得到的​​結果爲Stmin,但如果你改變的係數,你會得到另一種結果,而這也將是視爲當地最低標準。

我在做什麼錯?

+1

所以你說當你改變初始值時你正在碰到不同的局部最小值?這聽起來很正常......一種解決方法是用一些不同的初始值向量播種,然後選擇性能最佳的播放器(多啓動策略) – Dan

+0

感謝您的回答。對我知道那個。問題是,第一次迭代顯示我最低限度,這不正確。而且我也知道,在6個自由度中,我可以有一組無窮的結果(局部最小值),以及另一個無限的全局最小值結果集。我不在乎每個係數的值是什麼(我沒有限制),我只需要一個全局最優(一個),這將允許我(和任何想要使用此代碼的人)更好地適合我的實驗點多項式二次表達式。 – Lifehaxor

+0

好吧,我現在看到了,你的問題並不清楚。問題在於你如何定義'func'。我發佈了一個答案,顯示它應該如何。 – Dan

回答

1

問題是您的func只是一個常數。它只是返回預先計算的值,St,無論您傳遞給func的輸入如何,該值都是常數。嘗試使用各種不同的輸入呼叫func來測試。

您的目標函數需要包含將您帶到St的所有計算。因此,我建議你保存在一個M文件的函數看起來像這樣替換你func

function St = objectiveFunction(coef, p1a, p2a, p1b, p2b, qa, qb, q1a, q1b) 

    % Function calculation 
    q1a = flow(p1a,p2a,coef(1),coef(2),coef(3),coef(4),coef(5),coef(6)); 
    q1b = flow(p1b,p2b,coef(1),coef(2),coef(3),coef(4),coef(5),coef(6)); 

    % Least squares 
    LQa = (qa-q1a).^2; 
    LQb = (qb-q1b).^2; 
    Sa = sum(LQa); 
    Sb = sum(LQb); 
    St = Sa+Sb; 

end 

然後在你的腳本調用objectiveFunction利用這樣的匿名函數:

[coefmin, Stmin] = fminunc(@(coef)(objectiveFunction(coef, p1a, p2a, p1b, p2b, qa, qb, q1a, q1b)), init, opt); 

的的想法是創建一個匿名函數,只需要一個參數coef,這是fminunc將會寵愛並轉回到您的目標函數的變量。您的objectiveFunction需要的其他參數(即p1a, p2a, p1b,...)現在被認爲是由您的匿名功能預先計算的,因此也被fminunc預先計算。

其餘的代碼可以保持不變。

+0

非常感謝丹。我希望這段代碼能夠爲社區其他人帶來一些想法。問候。 – Lifehaxor