ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

線形最小二乗付きヤコビ乗算関数

以下の形式の最小二乗問題で、

minx12Cxd22

lb ≤ x ≤ ub などが条件になり、C が非常に大きく格納できない問題は、ヤコビ乗算関数を用いて解くことができます。この手法に対しては、'trust-region-reflective' アルゴリズムを使用してください。

たとえば、C は循環行列をベースにした 2n 行 n 列の行列とします。これは C の行が行ベクトル v をシフトしたものであることを意味します。この例は、周期的にシフトされ、(–1)k+1/k 形式の要素をもつ行ベクトル v をもちます。

v = [1, –1/2, 1/3, –1/4, ..., –1/n],

周期的にシフト:

C=[11/21/3...1/n1/n11/2...1/(n1)1/(n1)1/n1...1/(n2)1/21/31/4...111/21/3...1/n1/n11/2...1/(n1)1/(n1)1/n1...1/(n2)1/21/31/4...1].

この最小二乗の例は以下の場合の問題とします。

d = [n – 1; n – 2; ...; –n],

制約はi = 1, ..., n に対して –5 ≤ x(i) ≤ 5 です。

n が非常に大きくなると、密行列 C はコンピューターのメモリに収まりません。(n = 10,000 は 1 つのテスト システムに対しては大きすぎます)。

ヤコビ乗算関数の構文は以下になります。

w = jmfcn(Jinfo,Y,flag)

Jinfo は C と同じサイズの行列であり、前提条件子として使用されます。C がメモリに収めるには大きすぎる場合、Jinfo をスパース行列にします。YC*Y または C'*Y が成立するようにサイズ設定されたベクトルまたは行列です。flagjmfcn に以下のような乗算の形式を指定します。

  • flag > 0 ⇒  w = C*Y

  • flag < 0 ⇒  w = C'*Y

  • flag = 0 ⇒  w = C'*C*Y

C はシンプルな構造の行列であるため、ベクトル v のヤコビ乗算関数の記述は容易です。すなわち C を作成する必要はありません。C*Y の各行は v x Y を循環的にシフトされたものの積です。circshift を使用して、v を循環的にシフトします。

C*Y を計算するには、1 番目の行を見つけるために v*Y を計算し、次に v をシフトして 2 番目の行を計算する、というようにします。

C'*Y の計算には同じ計算を実行しますが、temp をシフトしたものを使用します。これは C' の 1 番目の行から形成されます。

temp = [fliplr(v),fliplr(v)];
temp = [circshift(temp,1,2),circshift(temp,1,2)]; % Now temp = C'(1,:)

C'*C*Y を計算するには、v のシフトを使用して単に C*Y を計算します。次に fliplr(v) のシフトを使用してその結果と C' の乗算を計算します。

以下のコードの関数 dolsqJac3 はベクトル v を設定し、ソルバー lsqlin を呼び出します。

function [x,resnorm,residual,exitflag,output] = dolsqJac3(n)
%
r = 1:n-1; % index for making vectors

v(n) = (-1)^(n+1)/n; % allocating the vector v
v(r) =( -1).^(r+1)./r;

% Now C should be a 2n-by-n circulant matrix based on v,
% but that might be too large to fit into memory.

r = 1:2*n;
d(r) = n-r;

Jinfo = [speye(n);speye(n)]; % sparse matrix for preconditioning
% This matrix is a required input for the solver;
% preconditioning is not really being used in this example

% Pass the vector v so that it does not need to be
% computed in the Jacobian multiply function
options = optimoptions('lsqlin','Algorithm','trust-region-reflective',...
    'JacobianMultiplyFcn',@(Jinfo,Y,flag)lsqcirculant3(Jinfo,Y,flag,v));

lb = -5*ones(1,n);
ub = 5*ones(1,n);

[x,resnorm,residual,exitflag,output] = ...
    lsqlin(Jinfo,d,[],[],[],[],lb,ub,[],options);

ヤコビ乗算関数 lsqcirculant3 は以下になります。

function w = lsqcirculant3(Jinfo,Y,flag,v)
% This function computes the Jacobian multiply functions
% for a 2n-by-n circulant matrix example

if flag > 0
    w = Jpositive(Y);
elseif flag < 0
    w = Jnegative(Y);
else
    w = Jnegative(Jpositive(Y));
end

    function a = Jpositive(q)
        % Calculate C*q
        temp = v;

        a = zeros(size(q)); % allocating the matrix a
        a = [a;a]; % the result is twice as tall as the input

        for r = 1:size(a,1)
            a(r,:) = temp*q; % compute the rth row
            temp = circshift(temp,1,2); % shift the circulant
        end
    end

    function a = Jnegative(q)
        % Calculate C'*q
        temp = fliplr(v);
        temp = circshift(temp,1,2); % shift the circulant% the circulant for C'

        len = size(q,1)/2; % the returned vector is half as long
        % as the input vector
        a = zeros(len,size(q,2)); % allocating the matrix a

        for r = 1:len
            a(r,:) = [temp,temp]*q; % compute the rth row
            temp = circshift(temp,1,2); % shift the circulant
        end
    end
end

n = 3000 の場合、C は 18,000,000 要素の密行列です。以下は、x から選択された値での n = 3000 に対する関数 dolsqJac の結果と、output 構造体です。

[x,resnorm,residual,exitflag,output] = dolsqJac3(3000);
Local minimum possible.

lsqlin stopped because the relative change in function value is less than the function tolerance.
x(1)
ans =
    5.0000
x(1500)
ans =
   -0.5201
x(3000)
ans =
   -5.0000
output
output = 

  struct with fields:

       iterations: 16
        algorithm: 'trust-region-reflective'
    firstorderopt: 5.9351e-05
     cgiterations: 36
  constrviolation: []
     linearsolver: []
          message: 'Local minimum possible.↵↵lsqlin stopped because the relative change in function value is less than the function tolerance.'

参考

|

関連するトピック