画像内のすべてのピクセルに対して最小二乗 (または同様の行列ベースの演算) を実行する必要があることに気付きました。すべてのピクセルには一連の数値が関連付けられているため、3D マトリックスとして配置できます。
(この次のビットはスキップできます)
最小二乗推定の意味の簡単な説明:
Y = Ax^2 + Bx + C でモデル化された二次システムがあり、それらの A、B、C 係数を探しているとします。X と対応する Y のいくつかのサンプル (少なくとも 3 つ) を使用して、次のように推定できます。
- (10 としましょう) X サンプルを次のような行列に配置します。
X = [x(:).^2 x(:) ones(10,1)];
- Y サンプルを同様の行列に配置します。
Y = y(:);
- 次を解くことにより、係数 A、B、C を推定します。
coeffs = (X'*X)^(-1)*X'*Y;
必要に応じて、これを自分で試してください。
A = 5; B = 2; C = 1;
x = 1:10;
y = A*x(:).^2 + B*x(:) + C + .25*randn(10,1); % added some noise here
X = [x(:).^2 x(:) ones(10,1)];
Y = y(:);
coeffs = (X'*X)^-1*X'*Y
coeffs =
5.0040
1.9818
0.9241
私があなたをそこに失ったら、もう一度注意を払い始めてください
*大幅な書き直し* 私が抱えている実際の問題にできるだけ近づけるために修正しましたが、それでも最小限の作業例にしています。
問題設定
%// Setup
xdim = 500;
ydim = 500;
ncoils = 8;
nshots = 4;
%// matrix size for each pixel is ncoils x nshots (an overdetermined system)
%// each pixel has a matrix stored in the 3rd and 4rth dimensions
regressor = randn(xdim,ydim, ncoils,nshots);
regressand = randn(xdim, ydim,ncoils);
したがって、私の問題は、画像内のすべてのピクセルに対して (X'*X)^-1*X'*Y (最小二乗または同様の) 操作を実行する必要があることです。それ自体はベクトル化/マトリックス化されていますが、すべてのピクセルに対してそれを行う必要がある唯一の方法は、次のような for ループです。
オリジナルコードスタイル
%// Actual work
tic
estimate = zeros(xdim,ydim);
for col=1:size(regressor,2)
for row=1:size(regressor,1)
X = squeeze(regressor(row,col,:,:));
Y = squeeze(regressand(row,col,:));
B = X\Y;
% B = (X'*X)^(-1)*X'*Y; %// equivalently
estimate(row,col) = B(1);
end
end
toc
Elapsed time = 27.6 seconds
コメントやその他のアイデア
に応じた編集 いくつか試してみました:
1. 長いベクトルに形状を変更し、二重for
ループを削除しました。これにより、時間を節約できました。
2.事前に画像squeeze
を -ing して (およびインライン転置) を削除しましpermute
た。これにより、時間を大幅に節約できます。
現在の例:
%// Actual work
tic
estimate2 = zeros(xdim*ydim,1);
regressor_mod = permute(regressor,[3 4 1 2]);
regressor_mod = reshape(regressor_mod,[ncoils,nshots,xdim*ydim]);
regressand_mod = permute(regressand,[3 1 2]);
regressand_mod = reshape(regressand_mod,[ncoils,xdim*ydim]);
for ind=1:size(regressor_mod,3) % for every pixel
X = regressor_mod(:,:,ind);
Y = regressand_mod(:,ind);
B = X\Y;
estimate2(ind) = B(1);
end
estimate2 = reshape(estimate2,[xdim,ydim]);
toc
Elapsed time = 2.30 seconds (avg of 10)
isequal(estimate2,estimate) == 1;
ロディ・オルデンハウスのやり方
N = xdim*ydim*ncoils; %// number of columns
M = xdim*ydim*nshots; %// number of rows
ii = repmat(reshape(1:N,[ncoils,xdim*ydim]),[nshots 1]); %//column indicies
jj = repmat(1:M,[ncoils 1]); %//row indicies
X = sparse(ii(:),jj(:),regressor_mod(:));
Y = regressand_mod(:);
B = X\Y;
B = reshape(B(1:nshots:end),[xdim ydim]);
Elapsed time = 2.26 seconds (avg of 10)
or 2.18 seconds (if you don't include the definition of N,M,ii,jj)
質問は次のとおりです:
(さらに) 高速な方法はありますか?
(私はそうは思わない。)