Like the title says, I have several matrices that I would like to stack in the 3rd dimension. I currently have a solution for stacking unequal vectors horizontally, which reads like so:
A = [1;2;3;4];
B = [1;2];
[i1,j1] = ndgrid(1:size(A,1),1:size(A,2));
[i2,j2] = ndgrid(1:size(B,1),(1:size(B,2))+size(A,2));
plane_stats = accumarray([i1(:),j1(:);i2(:),j2(:)],[A(:);B(:)]);
for any two vectors A and B of unequal size (caveat: I have only tested this for column vectors, stacked horizontally). Wherever there would be a gap, this adds zeros as padding, so the result looks as follows:
1 1
2 2
3 0
4 0
However, I would like to generalize this to 3D so I can stack a third (also unequal) matrix C behind the combination of A and B, like so:
C = [1 2;3 4;5 6]
%some modification of existing ndgrid code
combo(:,:,1) =
1 1
2 2
3 0
4 0
combo(:,:,2) =
1 2
3 4
5 6
0 0
However I am not sure how to extend the solution I currently have. Any and all help/insight is appreciated
I would suggest something like this:
Given unequal sized 2D matrices A, B, C,
A = [1;2;3];
B = [1 2 3];
C = [1 2;3 4;5 6;7 8];
Solution 1
To stack at the 3rd dimension, we can simply do this:
n_rows = max([size(A,1),size(B,1),size(C,1)]);
n_cols = max([size(A,2),size(B,2),size(C,2)]);
combo = zeros(n_rows, n_cols, 3);
combo(1:size(A,1),1:size(A,2),1) = A
combo(1:size(B,1),1:size(B,2),2) = B
combo(1:size(C,1),1:size(C,2),3) = C
Solution 2
In additionally, to stack matrices incrementally in a loop:
matrices = {A,B,C};
for i = 1:numel(matrices)
mat = matrices{i};
combo(1:size(mat,1),1:size(mat,2),i) = mat;
end
Matlab will automatically padding zeros for you.
Solution 3
Another version without warning:
matrices = {A,B,C};
n_rows = 0; n_cols = 0;
for i = 1:numel(matrices)
mat = matrices{i};
n_rows = max(n_rows, size(mat,1));
n_cols = max(n_cols, size(mat,2));
end
combo = zeros(n_rows, n_cols, numel(matrices));
for i = 1:numel(matrices)
combo(1:size(matrices{i},1),1:size(matrices{i},2),i) = matrices{i};
end
Result
All above 3 solutions resulting the same:
>> combo
combo(:,:,1) =
1 0 0
2 0 0
3 0 0
0 0 0
combo(:,:,2) =
1 2 3
0 0 0
0 0 0
0 0 0
combo(:,:,3) =
1 2 0
3 4 0
5 6 0
7 8 0
Your approach for merging A and B is totally fine, it doesn't require any improvement and you can keep on using it:
A = [1;2;3;4];
B = [1;2];
[i1,j1] = ndgrid(1:size(A,1),1:size(A,2));
[i2,j2] = ndgrid(1:size(B,1),(1:size(B,2))+size(A,2));
plane_stats = accumarray([i1(:),j1(:);i2(:),j2(:)],[A(:);B(:)]);
Now... what's great about Matlab is that matrices are automatically expanded (and zero-padded) whenever the code requires it. Hence, for a given matrix C, all you have to do is:
combo = plane_stats;
[C_m,C_n] = size(C);
combo(1:C_m,1:C_n,2) = C;
A few examples:
combo = plane_stats;
C = [1 2; 3 4; 5 6];
[C_m,C_n] = size(C);
combo(1:C_m,1:C_n,2) = C
combo(:,:,1) =
1 1
2 2
3 0
4 0
combo(:,:,2) =
1 2
3 4
5 6
0 0
combo = plane_stats;
C = [1 2; 3 4; 5 6; 7 8; 9 10];
[C_m,C_n] = size(C);
combo(1:C_m,1:C_n,2) = C
combo(:,:,1) =
1 1
2 2
3 0
4 0
0 0
combo(:,:,2) =
1 2
3 4
5 6
7 8
9 10
combo = plane_stats;
C = [1 2 3; 3 4 5; 5 6 7; 7 8 9; 10 11 12; 13 14 15];
[C_m,C_n] = size(C);
combo(1:C_m,1:C_n,2) = C
combo(:,:,1) =
1 1 0
2 2 0
3 0 0
4 0 0
0 0 0
0 0 0
combo(:,:,2) =
1 2 3
3 4 5
5 6 7
7 8 9
10 11 12
13 14 15
combo = plane_stats;
C = [1; 2];
[C_m,C_n] = size(C);
combo(1:C_m,1:C_n,2) = C
combo(:,:,1) =
1 1
2 2
3 0
4 0
combo(:,:,2) =
1 0
2 0
0 0
0 0
I am trying to solve the problem http://postimg.org/image/4bmfha8m7/
I am having trouble in implementing the weight matrix for the 36 inputs.
I have a 3 neuron hidden layer.
I use the backpropagation algorithm to learn.
What I have tried so far is:
% Sigmoid Function Definition
function [result] = sigmoid(x)
result = 1.0 ./ (1.0 + exp(-x));
end
% Inputs
input = [1 1 0 1 1 1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0;
0 0 0 0 1 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1;
0 0 0 0 0 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0 0 0 0;
0 0 0 0 1 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1];
% Desired outputs
output = [1;1;1;1];
% Initializing the bias (Bias or threshold are the same thing, essential for learning, to translate the curve)
% Also, the first column of the weight matrix is the weight of the bias values
bias = [-1 -1 -1 -1];
% Learning coefficient
coeff = 1.0;
% Number of learning iterations
iterations = 100;
disp('No. Of Learning Iterations = ');
disp(iterations);
% Initial weights
weights = ones(36,36);
% Main Algorithm Begins
for i = 1:iterations
out = zeros(4,1);
numIn = length (input(:,1));
for j = 1:numIn
% 1st neuron in the hidden layer
H1 = bias(1,1)*weights(1,1) + input(j,1)*weights(1,2) + input(j,2)*weights(1,3) + input(j,3)*weights(1,4)+ input(j,4)*weights(1,5) + input(j,5)*weights(1,6) + input(j,6)*weights(1,7)
+ input(j,7)*weights(1,8) + input(j,8)*weights(1,9) + input(j,9)*weights(1,10)+ input(j,10)*weights(1,11) + input(j,11)*weights(1,12) + input(j,12)*weights(1,13)
+ input(j,13)*weights(1,14) + input(j,14)*weights(1,15) + input(j,15)*weights(1,16)+ input(j,16)*weights(1,17) + input(j,17)*weights(1,18) + input(j,18)*weights(1,19)
+ input(j,19)*weights(1,20) + input(j,20)*weights(1,21) + input(j,21)*weights(1,22)+ input(j,22)*weights(1,23) + input(j,23)*weights(1,24) + input(j,24)*weights(1,25)
+ input(j,25)*weights(1,26) + input(j,26)*weights(1,27) + input(j,27)*weights(1,28)+ input(j,28)*weights(1,29) + input(j,29)*weights(1,30) + input(j,30)*weights(1,31)
+ input(j,31)*weights(1,32) + input(j,32)*weights(1,33) + input(j,33)*weights(1,34)+ input(j,34)*weights(1,35) + input(j,35)*weights(1,36)
x2(1) = sigmoid(H1);
% 2nd neuron in the hidden layer
H2 = bias(1,2)*weights(2,1) + input(j,1)*weights(2,2) + input(j,2)*weights(2,3) + input(j,3)*weights(2,4)+ input(j,4)*weights(2,5) + input(j,5)*weights(2,6) + input(j,6)*weights(2,7)
+ input(j,7)*weights(2,8) + input(j,8)*weights(2,9) + input(j,9)*weights(2,10)+ input(j,10)*weights(2,11) + input(j,11)*weights(2,12) + input(j,12)*weights(2,13)
+ input(j,13)*weights(2,14) + input(j,14)*weights(2,15) + input(j,15)*weights(2,16)+ input(j,16)*weights(2,17) + input(j,17)*weights(2,18) + input(j,18)*weights(2,19)
+ input(j,19)*weights(2,20) + input(j,20)*weights(2,21) + input(j,21)*weights(2,22)+ input(j,22)*weights(2,23) + input(j,23)*weights(2,24) + input(j,24)*weights(2,25)
+ input(j,25)*weights(2,26) + input(j,26)*weights(2,27) + input(j,27)*weights(2,28)+ input(j,28)*weights(2,29) + input(j,29)*weights(2,30) + input(j,30)*weights(2,31)
+ input(j,31)*weights(2,32) + input(j,32)*weights(2,33) + input(j,33)*weights(2,34)+ input(j,34)*weights(2,35) + input(j,35)*weights(2,36)
x2(2) = sigmoid(H2);
% 3rd neuron in the hidden layer
H3 = bias(1,3)*weights(3,1) + input(j,1)*weights(3,2) + input(j,2)*weights(3,3) + input(j,3)*weights(3,4)+ input(j,4)*weights(3,5) + input(j,5)*weights(3,6) + input(j,6)*weights(3,7)
+ input(j,7)*weights(3,8) + input(j,8)*weights(3,9) + input(j,9)*weights(3,10)+ input(j,10)*weights(3,11) + input(j,11)*weights(3,12) + input(j,12)*weights(3,13)
+ input(j,13)*weights(3,14) + input(j,14)*weights(3,15) + input(j,15)*weights(3,16)+ input(j,16)*weights(3,17) + input(j,17)*weights(3,18) + input(j,18)*weights(3,19)
+ input(j,19)*weights(3,20) + input(j,20)*weights(3,21) + input(j,21)*weights(3,22)+ input(j,22)*weights(3,23) + input(j,23)*weights(3,24) + input(j,24)*weights(3,25)
+ input(j,25)*weights(3,26) + input(j,26)*weights(3,27) + input(j,27)*weights(3,28)+ input(j,28)*weights(3,29) + input(j,29)*weights(3,30) + input(j,30)*weights(3,31)
+ input(j,31)*weights(3,32) + input(j,32)*weights(3,33) + input(j,33)*weights(3,34)+ input(j,34)*weights(3,35) + input(j,35)*weights(3,36)
x2(3) = sigmoid(H3);
% Output layer
x3_1 = bias(1,4)*weights(4,1) + x2(1)*weights(4,2) + x2(2)*weights(4,3) + x2(3)*weights(4,4);
out(j) = sigmoid(x3_1);
% Adjust delta values of weights
% For output layer: delta(wi) = xi*delta,
% delta = (1-actual output)*(desired output - actual output)
delta3_1 = out(j)*(1-out(j))*(output(j)-out(j));
% Propagate the delta backwards into hidden layers
delta2_1 = x2(1)*(1-x2(1))*weights(3,2)*delta3_1;
delta2_2 = x2(2)*(1-x2(2))*weights(3,3)*delta3_1;
delta2_3 = x2(3)*(1-x2(3))*weights(3,4)*delta3_1;
% Add weight changes to original weights and then use the new weights.
% delta weight = coeff*x*delta
for k = 1:4
if k == 1 % Bias cases
weights(1,k) = weights(1,k) + coeff*bias(1,1)*delta2_1;
weights(2,k) = weights(2,k) + coeff*bias(1,2)*delta2_2;
weights(3,k) = weights(3,k) + coeff*bias(1,3)*delta2_3;
weights(4,k) = weights(4,k) + coeff*bias(1,4)*delta3_1;
else % When k=2 or 3 input cases to neurons
weights(1,k) = weights(1,k) + coeff*input(j,1)*delta2_1;
weights(2,k) = weights(2,k) + coeff*input(j,2)*delta2_2;
weights(3,k) = weights(3,k) + coeff*input(j,3)*delta2_3;
weights(4,k) = weights(4,k) + coeff*x2(k-1)*delta3_1;
end
end
end
end
disp('For the Input');
disp(input);
disp('Output Is');
disp(out);
disp('Test Case: For the Input');
input = [1 1 0 1 1 1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0];
For me the problem is the labeling, I can't see where do you have the output
Output (1,1,1,1)? What do you mean. Perhaps I miss something but for me there are two ways of labeling a multiclass clasification one is with a label directly (0 for A, 1 for B, 3 for C...) and expanding it after or directly expanded like A=1,0,0,0 = [1,0,0,0;0,1,0,0;0,0,1,0;0,0,0,1]
The way that you make operations is very easy to make a mistakes, take a look to matlab/octave matrix operations, it's very powerful and could simplify everything a lot.
I have the following code that includes 3 iterated for loops in order to create an upper diagonal matrix, I plan on performing on large data set many times and want to make as computationally efficient as possible.
data = magic(3);
n = size(data,1);
W = zeros(n,n);
for i = 1:n
for j = i:n
if i==j
W(i,j)=0;
else
for k = 1:n
temp(1,k) = (data(i,k)-data(j,k))^2;
sumTemp = sumTemp + temp(1,k);
end
W(i,j)=sqrt(sumTemp);
end
temp = 0;
sumTemp = 0;
end
end
Answer should look like:
[0 6.4807 9.7980
0 0 6.4807
0 0 0]
I am working it hard right now, but figure I would throw it out there in case anyone has any suggestions that would save me hours of fiddling around.
This is hat I have at the moment:
data = magic(3);
n = size(data,1);
W = zeros(n,n);
for i = 1:n
for j = i+1:n
W(i,j)= norm(data(i,:)-data(j,:))
%W(i,j)= sqrt(sum((data(i,:)-data(j,:)).^2));
end
end
What I did:
vecorized the inner loop
removed www, which is unused
changed 2nd loop, start at i+1 because nothing is done for i=j
Replaced sqrt((a-b).^2) with norm(a-b)
And now the "full" vectorization:
data = magic(3);
n = size(data,1);
W = zeros(n,n);
tri=triu(ones(n,n),1)>0;
[i,j]=find(tri);
W(tri)=arrayfun(#(i,j)norm(data(i,:)-data(j,:)),i,j)
Here is a straightforward solution with bsxfun:
Wfull = sqrt(squeeze(sum(bsxfun(#minus,data,permute(data,[3 2 1])).^2,2)))
W = triu(Wfull)
Use this where data is N-by-D, where N is the number of points and D is dimensions. For example,
>> data = magic(3);
>> triu(sqrt(squeeze(sum(bsxfun(#minus,data,permute(data,[3 2 1])).^2,2))))
ans =
0 6.4807 9.7980
0 0 6.4807
0 0 0
>> data = magic(5); data(:,end-1:end)=[]
data =
17 24 1
23 5 7
4 6 13
10 12 19
11 18 25
>> triu(sqrt(squeeze(sum(bsxfun(#minus,data,permute(data,[3 2 1])).^2,2))))
ans =
0 20.8087 25.2389 22.7376 25.4558
0 0 19.9499 19.0263 25.2389
0 0 0 10.3923 18.3576
0 0 0 0 8.5440
0 0 0 0 0
>>
I have a correlation matrix X of five elements(C1,C2,C3,C4,C5)
C1 C2 C3 C4 C5
C1 * 1 0 1 0
C2 1 * 0 0 1
C3 0 0 * 1 1
C4 1 0 1 * 0
C5 0 1 1 0 *
I want to use MatLab to move as many as non-zero cells close to diagonal, while keep the diagonal cells are "*".
For example, you may notice that the columns and rows is shifting in the following matrix, while the diagonal cells are "*".
C1 C4 C2 C5 C3
C1 * 1 1 0 0
C4 1 * 0 0 1
C2 1 0 * 1 0
C5 0 0 1 * 1
C3 0 1 0 1 *
Because I want to do clustering, so I want as many as non-zero cells get close to diagonal after shifting. It's an NP-hard problem.
Anyone know what functions in MatLab can realize this?
What you're looking for is probably the reverse Cuthill-McKee algorithm (RCM), which pretty much does what you want: for a given matrix it finds a permutation that tends to have its non-zero elements closer to the diagonal. There's a built-in function symrcm in MATLAB that does just that.
So assuming that X is your matrix, you can do the following:
p = symrcm(X);
Xnew = X(p, p);
Xnew is the new reordered matrix, and p is the new row/column order.
Example
Let's create a matrix first:
X = [10 0 0 7 0; 3 20 0 0 11; 0 0 30 0 29; 12 7 0 40 0; 0 33 0 0 50]
Now let's reorder it:
p = symrcm(X);
Xnew = X(p, p)
The result is:
Xnew =
40 12 7 0 0
7 10 0 0 0
0 3 20 11 0
0 0 33 50 0
0 0 0 29 30
Seems right.
A = [1 0 0 1 0;
0 1 0 0 1;
0 0 1 0 1;
1 1 0 1 0;
0 1 0 0 1];
N = length(A);
switched = false;
%%
% Calculate initial Global Energy
disp(A);
global_energy = 0;
for l = 1:N
for m = 1:N
if(A(l,m))
global_energy = global_energy + (l-m)^2/2;
end
end
end
disp(global_energy);
counter = 0;
counter_cutoff = 10000000000;
while(true)
switched = false;
counter = counter + 1;
for i = 1:N
for j = i+1:N
current_metric = 0; % Calculate metric of row i and j with columns i and j
permuted_metric = 0; % Calculate metric if they were permuted
% Row i
for k = 1:N
if(k ~= i && k ~= j && A(i,k))
current_metric = current_metric + (i-k)^2/2;
permuted_metric = permuted_metric + (j-k)^2/2;
end
end
% Row j
for k = 1:N
if(k ~= i && k ~= j && A(j,k))
current_metric = current_metric + (j-k)^2/2;
permuted_metric = permuted_metric + (i-k)^2/2;
end
end
% Col i
for k = 1:N
if(k ~= i && k ~= j && A(k,i))
current_metric = current_metric + (i-k)^2/2;
permuted_metric = permuted_metric + (j-k)^2/2;
end
end
% Col j
for k = 1:N
if(k ~= i && k ~= j && A(k,j))
current_metric = current_metric + (j-k)^2/2;
permuted_metric = permuted_metric + (i-k)^2/2;
end
end
% If permuted metric is less, swap columns and rows - set switched to true
if(permuted_metric < current_metric)
switched = true; % there was at least one switch
% Now switch rows and columns
% Switch columns first
A(:,[i j]) = A(:,[j i]);
% Now switch rows
A([i j],:) = A([j i],:);
end
end
end
if(~switched || counter > counter_cutoff)
% All permutations did not lead to a switching of rows and columns
break;
end
end
% Calculate final Global Energy
disp(A);
global_energy = 0;
for l = 1:N
for m = 1:N
if(A(l,m))
global_energy = global_energy + (l-m)^2/2;
end
end
end
disp(global_energy);
Terminal:
1 0 0 1 0
0 1 0 0 1
0 0 1 0 1
1 1 0 1 0
0 1 0 0 1
22
1 1 0 0 0
1 1 1 0 0
0 0 1 1 0
0 0 1 1 0
0 0 0 1 1
3