Octave matrix to be filled based on condition [duplicate] - matlab

I want to convert an integer i to a logical vector with an i-th non-zero element. That can de done with 1:10 == 2, which returns
0 1 0 0 0 0 0 0 0 0
Now, I want to vectorize this process for each row. Writing repmat(1:10, 2, 1) == [2 5]' I expect to get
0 1 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
But instead, this error occurs:
Error using ==
Matrix dimensions must agree.
Can I vectorize this process, or is a for loop the only option?

You can use bsxfun:
>> bsxfun(#eq, 1:10, [2 5].')
ans =
0 1 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
Note the transpose .' on the second vector; it's important.

Another way is to use eye and create a logical matrix that is n x n long, then use the indices to index into the rows of this matrix:
n = 10;
ind = [2 5];
E = eye(n,n) == 1;
out = E(ind, :);
We get:
>> out
out =
0 1 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0

Just another possibility using indexing:
n = 10;
ind = [2 5];
x=zeros(numel(ind),n);
x(sub2ind([numel(ind),n],1:numel(ind),ind))=1;

Related

Creating MATLAB neural network target array from class labels [duplicate]

For neural networking, I would like to represent a column vector y = [1;2;3] in a matrix like so:
y = [1 0 0;
0 1 0;
0 0 1]
My vector y is very large, and so hardcoding is not an option. Also, I would like to avoid using for-loops.
What I did so far:
y1 =[y; zeros(1,length(y)) ;zeros(1,length(y))] % add two rows with zeros in orde to give y the right format
idx = find(y1(1,:) == 2); % find all the columns containing a 2
y1(:,idx(1):idx(end)) = y1(:,[0;1;0]); % this does not work because now I am comparing a matrix with a vector
I also tried this:
y1( y1 == [2;0;0] )=[0;1;0]; % This of course does not work
Is there a way to specify I want to compare columns in y1 == [2;0;0], or is there another way to solve this?
From the context of your question, you wish to find a matrix where each column is an identity vector. For an identity vector, each column in this matrix is a non-zero vector where 1 is set in the position of the vector denoted by each position of y and 0 otherwise. Therefore, let's say we had the following example:
y = [1 5 4 3]
You would have y_out as the final matrix, which is:
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
There are several ways to do this. The easiest one would be to declare the identity matrix with eye, then let y pick out those columns that you want from this matrix and place them as columns into your final matrix. If y had all unique values, then we would simply be rearranging the columns of this identity matrix based on y. As such:
y_out = eye(max(y));
y_out = y_out(:,y)
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
Another way would be to declare a sparse matrix, where each row index is simply those elements from y and each column index is increasing from 1 up to as many elements as we have y:
y_out = sparse(y, 1:numel(y), 1, max(y), numel(y));
y_out = full(y_out)
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
One more way would be to use sub2ind to find linear indices into your matrix, then access those elements and set them to 1. Therefore:
ind = sub2ind([max(y) numel(y)], y, 1:numel(y));
y_out = zeros(max(y), numel(y));
y_out(ind) = 1
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
This works even if y has "missing" values:
n = numel(y);
y_matrix = zeros(n, max(y));
y_matrix((1:n) + (y-1)*n) = 1;
Example:
y = [1 5 3 2];
gives
y_matrix =
1 0 0 0 0
0 0 0 0 1
0 0 1 0 0
0 1 0 0 0
You can use bsxfun:
y_out = bsxfun(#eq, (1:max(y)).', y);
Not as efficient as the #rayryeng's answer but this might also help,
Also if there are repeated values in y this code works fine.
a = [1 2 3 2 5 7 6 8];
[X,Y] = meshgrid(a,1 : length(a));
A = X == Y;
A =
1 0 0 0 0 0 0 0
0 1 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1

Replace specific columns in a matrix with a constant column vector

For neural networking, I would like to represent a column vector y = [1;2;3] in a matrix like so:
y = [1 0 0;
0 1 0;
0 0 1]
My vector y is very large, and so hardcoding is not an option. Also, I would like to avoid using for-loops.
What I did so far:
y1 =[y; zeros(1,length(y)) ;zeros(1,length(y))] % add two rows with zeros in orde to give y the right format
idx = find(y1(1,:) == 2); % find all the columns containing a 2
y1(:,idx(1):idx(end)) = y1(:,[0;1;0]); % this does not work because now I am comparing a matrix with a vector
I also tried this:
y1( y1 == [2;0;0] )=[0;1;0]; % This of course does not work
Is there a way to specify I want to compare columns in y1 == [2;0;0], or is there another way to solve this?
From the context of your question, you wish to find a matrix where each column is an identity vector. For an identity vector, each column in this matrix is a non-zero vector where 1 is set in the position of the vector denoted by each position of y and 0 otherwise. Therefore, let's say we had the following example:
y = [1 5 4 3]
You would have y_out as the final matrix, which is:
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
There are several ways to do this. The easiest one would be to declare the identity matrix with eye, then let y pick out those columns that you want from this matrix and place them as columns into your final matrix. If y had all unique values, then we would simply be rearranging the columns of this identity matrix based on y. As such:
y_out = eye(max(y));
y_out = y_out(:,y)
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
Another way would be to declare a sparse matrix, where each row index is simply those elements from y and each column index is increasing from 1 up to as many elements as we have y:
y_out = sparse(y, 1:numel(y), 1, max(y), numel(y));
y_out = full(y_out)
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
One more way would be to use sub2ind to find linear indices into your matrix, then access those elements and set them to 1. Therefore:
ind = sub2ind([max(y) numel(y)], y, 1:numel(y));
y_out = zeros(max(y), numel(y));
y_out(ind) = 1
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
This works even if y has "missing" values:
n = numel(y);
y_matrix = zeros(n, max(y));
y_matrix((1:n) + (y-1)*n) = 1;
Example:
y = [1 5 3 2];
gives
y_matrix =
1 0 0 0 0
0 0 0 0 1
0 0 1 0 0
0 1 0 0 0
You can use bsxfun:
y_out = bsxfun(#eq, (1:max(y)).', y);
Not as efficient as the #rayryeng's answer but this might also help,
Also if there are repeated values in y this code works fine.
a = [1 2 3 2 5 7 6 8];
[X,Y] = meshgrid(a,1 : length(a));
A = X == Y;
A =
1 0 0 0 0 0 0 0
0 1 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1

In matlab, increment different column element for every row in without using a loop

Assume you have an 4x4 matrix A of zeros:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
And an 4x1 vector B that represents column indices for matrix A (so values [1:4])
4
2
3
1
Now I want to increment those columnpositions in matrix A on the index on every row from vector B.
I have tried a couple of constructions myself but can't quite manage to do this.
For example I tried:
A(:, B) = A(:, B)+1
Which just increment every element in A.
This is how I want the operation to act:
>> A(somethting(B)) = A(somethting(B)) + 1
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0
You can do this by using the linear index to each of the elements you want to address. Compute this using sub2ind:
>> A = zeros(4)
A =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
>> B = [4 2 3 1]
B =
4 2 3 1
>> i=sub2ind(size(A),B,1:4)
i =
4 6 11 13
>> A(i) = A(i)+1
A =
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0
Well just in case you want a looped version :p
A = zeros(4,4);
B = [4, 2, 3, 1];
for i = 1:length(B)
A(i, B(i) ) = A(i, B(i) ) + 1;
end
A = zeros(4);
B = [4 2 3 1];
A(repmat([1:4]',1,4) == repmat(B,4,1)) = 1
A =
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0

Insert an identity matrix into a larger dimension of null matrix

Suppose i have an identity matrix .
I=eye(3)
which will produce
I = [1 0 0
0 1 0
0 0 1]
Now i want to insert I into a (5X5) null matrix such that my result will be
N = [0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1]
How could i achieve this efficiently .Thanks in advace
With the Image processing toolbox, this could be done using padarray like this:
padarray(eye(3), [2 2], 'pre');
padarray pads an array with zeros. The [2 2] part says how many zeros to pad it with, in this case 2 rows and 2 columns. pre means you want it in front of the matrix, not after it (post).
Without it, you need to tweak it a bit more. One option could be to create an identity matrix of the full size, then make the first elements zero:
m = 5; %// size of matrix
n = 3; %// size of identity matrix
a = eye(m);
a(1:m-n,1:m-n) = 0;
a =
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
... or:
a = zeros(m);
a(m-n+1:m,m-n+1:m) = eye(n)
... or using sparse:
full(sparse(m-n+1:m,m-n+1:m,1))
Alternatively,
m = 5;
n = 3;
a = diag( [zeros(1, m-n), ones(1,n)] );

Matlab/Octave 1-of-K representation

I have a y of size 5000,1 (matrix), which contains integers between 1 and 10. I want to expand those indices into a 1-of-10 vector. I.e., y contains 1,2,3... and I want it to "expand" to:
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
What is the best way to do that?
I tried:
Y = zeros(5000,10); Y(y) = 1;
but it didn't work.
It works for vectors though:
if y = [2 5 7], and Y = zeros(1,10), then Y(y) = [0 1 0 0 1 0 1 0 0 0].
Consider the following:
y = randi([1 10],[5 1]); %# vector of 5 numbers in the range [1,10]
yy = bsxfun(#eq, y, 1:10)'; %# 1-of-10 encoding
Example:
>> y'
ans =
8 8 4 7 2
>> yy
yy =
0 0 0 0 0
0 0 0 0 1
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 0 0
0 0 0 0 0
0 0 0 0 0
n=5
Y = ceil(10*rand(n,1))
Yexp = zeros(n,10);
Yexp(sub2ind(size(Yexp),1:n,Y')) = 1
Also, consider using sparse, as in: Creating Indicator Matrix.
While sparse may be faster and save memory, an answer involving eye() would be more elegant as it is faster than a loop and it was introduced during the octave lecture of that class
Here is an example for 1 to 4
V = [3;2;1;4];
I = eye(4);
Vk = I(V, :);
You can try cellfun operations:
function vector = onehot(vector,decimal)
vector(decimal)=1;
end
aa=zeros(10,2);
dec=[5,6];
%split into columns
C=num2cell(aa,1);
D=num2cell(dec,1);
onehotmat=cellfun("onehot",C,D,"UniformOutput",false);
output=cell2mat(onehotmat);
I think you mean:
y = [2 5 7];
Y = zeros(5000,10);
Y(:,y) = 1;
After the question edit, it should be this instead:
y = [2,5,7,9,1,4,5,7,8,9....]; //(size (1,5000))
for i = 1:5000
Y(i,y(i)) = 1;
end