My question might be trivial. I have a large 3D matrix (m by n by k elements) in MatLab and want to extract all diagonal slices and store them in another 3D array. For a better representation, I have attached a picture. the dashed lines are the diagonal slices I am looking for.
Given a m x n x k array a use the following method to extract the slices into a cell array:
idx = repmat(reshape((0 : k - 1), 1, 1,[])+(1 : n), [m, 1, 1]);
result = accumarray(idx(:), a(:), [], #(x){reshape(x, m, 1,[])});
The slices have dimensions [m x 1 x y] where y ranges from 1 to min(n,k).
For old MATLAB versions use the following (bsxfun instead of implicit expansion):
idx = repmat(bsxfun(#plus, reshape((0 : k - 1), 1, 1,[]), (1 : n)), [m, 1, 1]);
result = accumarray(idx(:), a(:), [], #(x){reshape(x, m, 1,[])});
Related
I have a 3D matrix sized (x,y,N) and a 2D matrix sized (N,N).
I would like to manipulate the two in a way that each column in the 2D matrix has the coefficients for a linear combination of the 2D sized- (x, y) slices in the 3D matrix. And I would like to do this for all N columns in the 2D matrix.
Schematically,
Currently the code looks like:
A = zeros(numel(x_axis), numel(y_axis), N);
B = zeros(numel(x_axis), numel(y_axis), N);
C = zeros(N, N)
for i = 1 : N
for j = 1 : N
A(:,:,i) = A(:,:,i) + B(:,:,j) * C(j,i);
end
end
But it is quite slow. Is there any way to speed up the MATLAB code by vectorizing?
If I understand your problem well, then this should work:
[p,q,N] = size(B);
A = reshape( reshape(B, [p*q, N]) * C, [p, q, N]);
edit: Cleaner version suggested by Suever:
A = reshape(reshape(B, [], size(B, 3)) * C, size(B))
Generalization to the R-D case:
A = reshape(reshape(B, [], size(B, ndims(B))) * C, size(B))
You can use bsxfun which will calculate this very quickly for you. We have to use permute to re-arrange C a little bit to ensure that it has conformant dimensions for using bsxfun and then we perform the summation along the third dimension of the resulting output and apply squeeze to remove the singleton third dimension.
A = squeeze(sum(bsxfun(#times, B, permute(C, [3 4 1 2])), 3))
I'm wondering if it is possible to perform a multidimensional matrix multiplication without resorting to a for-loop. Given the N-by-P matrix A and the N-by-M-by-P matrix B, I want to compute the M-dimensional vector y, defined element-wise as
y(j) = sum_(i = 1,...,N) sum_(k = 1,...,P) A(i,k)*B(i,j,k)
You can linearize A into a row vector, then reshape and permute the array B as a matrix, so that the desired result is just matrix multiplication:
M = 5;
N = 6;
P = 8;
A = rand(N,P);
B = rand(N,M,P);
result = A(:).'*reshape(permute(B, [1 3 2]), [], M);
Or reshape matrix A so that its dimensions are aligned with those of B, use bsxfun to multiply with singleton-expansion, and sum over the two desired dimensions:
result = sum(sum(bsxfun(#times, reshape(A, N, 1, P), B), 1), 3);
I had to convert an n x n matrix to n^2 x 1 column vector for ease of some operations. Now, that the operations are done, how do I return to the n x n form from the n^2 x 1 vector.
It is supposed to be opposite of this: concatenation
Thanks!
You can use the reshape() function:
//M is your n^2 x 1 column vector, A is your nxn matrix that you want to recover
A = reshape(M, [n n])
If your n x n matrix is 3x3, then:
A = reshape(M, [3 3])
For more info: http://www.mathworks.com/help/matlab/ref/reshape.html
I have an a-by-b cell array, C. In each element, there is a float array.
I now want to create a new symmetric matrix M. Each element (i, j) in M is to be set to the sum of the Euclidean distances of all the respective float arrays in C.
For example, to find M(i,j), I would take the set of b float arrays in C along row i, and the set of b float arrays in C along row j, find the Euclidean distance between each array across the two sets, and then sum up the b x b values. C{i,j} is a column vector. All columns are the same length.
Below is my "brute force" implementation of this:
for i=1:a
for j=1:a
dist_sum = 0;
for k=1:b
for l=1:b
dist = sqrt(sum((C{i, k} - C{j, l}) .^ 2));
dist_sum = dist_sum + dist;
end
end
M(j, i) = dist_sum;
M(i, j) = dist_sum;
end
end
My question: Is there a more efficient way of doing this using matrix operations, without having to explicitly compute each Euclidean distance in turn?
It would be better to use a 3D array, instead of a 2D cell array of equal-size column vectors.
If you have a cell array: first convert into a 3D array (D in my code); then it's easy to compute distances with bsxfun; and finally apply sum:
D = permute(C, [3 1 2]);
D = reshape(cat(2, D{:}), [], size(C,1), size(C,2)); %// 3D array
dist = sqrt(sum(bsxfun(#minus, D, permute(D, [1 4 5 2 3])).^2)); %// distances
M = squeeze(sum(sum(dist, 3), 5)); %// sum of distances
Example: with
>> C = {[1; 2], [30; 40], [0; 1]; [5; 7] [19; 17] [4; 5]}; %// a is 2, b is 3
the result of both your code and mine is
M =
196.8391 182.8791
182.8791 77.3002
Before Calculating Euclidean Distance:
Can convert the cell array to matrix by using cell2mat... then u can use following methods..
Method 1:
G = rand(1, 72);
G2 = rand(1, 72);
D = sqrt(sum((G - G2) .^ 2));
Method 2:
V = G - G2;
D = sqrt(V * V');
Method 3:
D = norm(G - G2);
Method 4:
D = pdist2(G,G2);
I would suggest converting the matrix elements to a vector using (:) and then using distance2curve.m function file from Matlab File Exchange to find the minimum/Euclidean distance between the two arrays.
Let's say the two cell arrays are A and B with matrices containing the row and column indices for each cell array denoted as 'indA' and 'indB', where each row in 'indA' and 'indB' contains the row element and column elements of 'A' and 'B', respectively. Now use the above function as:
[M, distance, t] = distance2curve(indA(:, :), indB(:, :))
The output variable M should contain the minimum/Euclidean distance between the two arrays that you are looking for.
Given 100x100 matrix where each element represents a function value in space, I would like to find parameter values A, B, C, D, E for a function f(x, y) = A + Bx + Cy + DX^2+Ey^2 that fits the best the given matrix values, where x represents a row number and y represents a column number
To illustrate the aim on a smaller example, let's say we have a 3x3 matrix T:
T = [0.1 0.2 0.1; 0.8, 0.6, 0.5; 0.1, 0, 1]
in this case f(1,1) = 0.1 and f(3,2)= 0.
Concretely the matrix values for which I would like to find a fitting function (surface) are displayed in the image below:
I would be very thankful if anyone suggested a way to find the 3D function that fits (best) the given matrix.
Edit
Is it possible to find a fit directly or is it neccesary (or better) fo first represent the data as matrix [X, Y, f(X,Y)]:
vals = []
for(i = 1: 100)
for j = 1 : 100
if(T(i,j) ~= 0)
vals = [vals;i, j, T(i,j)];
end;
end;
end;
These guys seemed to have done it in one line:
http://www.mathworks.com/matlabcentral/newsreader/view_thread/134076
x = % vector of x values
y = % vector of y values
z = % f(x,y)
V = [1 x y x.^2 x.*y y.^2];
a = V \ z ;
From the help page:
If A is a rectangular m-by-n matrix with m ~= n, and B is a column vector with m elements or a matrix with m rows, then A\B returns a least-squares solution to the system of equations A*x= B.