Replace specific columns in a matrix with a constant column vector - matlab

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

Related

I'm using MATLAB R2015b, How do we generate a rectangular matrix with upper diagonal elements 1?

I am trying to generate a rectangular matrix with 1s on the diagonal above the main diagonal and -1s on the main diagonal. I used "eye" which does not create the diagonal above the main.
Please find my attempt to this below.
N = 5
M1 = -eye([N-1 N])
M2 = eye([N N-1])'
M = M1+M2
I am unable to resolve this issue on my own. Any help or links to relevant documentation would be greatly appreciated.
I don't know of any prebuild function, but you can easily make such a matrix yourself:
N=5;
M=7;
diag=-eye(N,M);
upper_diag=horzcat(zeros(N,1),eye(N,M-1))
final=diag+upper_diag
using the identity matrix and some concatenation to shift the diagonal around. This example assumes you are looking for a square matrix.
The result looks like:
final =
-1 1 0 0 0 0 0
0 -1 1 0 0 0 0
0 0 -1 1 0 0 0
0 0 0 -1 1 0 0
0 0 0 0 -1 1 0
Just create eye and diag matrices as per normal, add them together, then chop away the rows you do not need:
nCol = 7;
nRow = 5;
M = -eye(nCol) + diag(ones(nCol - 1, 1), 1);
M = M(1:nRow, 1:nCol)
produces
M =
-1 1 0 0 0 0 0
0 -1 1 0 0 0 0
0 0 -1 1 0 0 0
0 0 0 -1 1 0 0
0 0 0 0 -1 1 0
The four-input version of spdiags does just that, producing a sparse matrix. You may need to convert to full then.
M = 5; %// number of rows
N = 7; %// number of columns
d = [0 1]; %// specify main diagonal and the one above
v = [-1 1]; %// values in those diagonals
result = full(spdiags(ones(M,1)*v, d, M, N));
This gives
result =
-1 1 0 0 0 0 0
0 -1 1 0 0 0 0
0 0 -1 1 0 0 0
0 0 0 -1 1 0 0
0 0 0 0 -1 1 0

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

Matlab Generating a Matrix with random elements

How can I generate a Matrix with Boolean elements, but the sum of each row is equal to a certain constant number.
Is each row the same one number?
k = 5;
m = 10;
n = 10;
[~, I] = sort(rand(m,n), 2)
M = I <= k
If you don't want the same number of 1s in each row, but rather have a vector that specifies per row how many 1s you want then you need to use bsxfun as well:
K = (1:10)'; %//'
m = 10;
n = 10;
[~, I] = sort(rand(m,n), 2)
M = bsxfun(#ge, K,I)
Lets say you want to have 20 columns (n=20) and your vector a contains the number of ones you want in each row:
n=20;
a= [5 6 1 9 4];
X= zeros(numel(a),n);
for k=1:numel(a)
rand_order=randperm(n);
row_entries=[ones(1,a(k)),zeros(1,n-a(k))];
row_entries=row_entries(rand_order);
X(k,:)=row_entries;
end
X=boolean(X);
What I do is generate me a random ordered index array rand_order then getting an array which contains the wanted number of ones filled with zero. Reorder those elements according to rand_order saving it and converting it to logical. And because of the use of a for loop rand_order is all the time computed again, so giving you different locations for your output:
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0
0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
1 0 0 1 0 1 1 0 1 0 0 1 1 0 0 0 1 1 0 0
1 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0

Drawing a line of ones on a matrix

I have a matrix m = zeros(1000, 1000). Within this matrix I want to draw an estimate of the line which passes through 2 points from my matrix. Let's say x = [122 455]; and y = [500 500];.
How can I do this in Matlab? Are there any predefined functions to do this? I am using Matlab 2012b.
I'll denote the two endpoints as p1 and p2 because I'm planning to use x and y for something else. I'm also assuming that the first coordinate of p1 and p2 is x and the second is y. So here's a rather simple way to do it:
Obtain the equation of the line y = ax + b. In MATLAB, this can be done by:
x = p1(1):p2(1)
dx = p2(1) - p1(1);
dy = p2(2) - p1(2);
y = round((x - p1(1)) * dy / dx + p1(2));
Convert the values of x and y to indices of elements in the matrix, and set those elements to 1.
idx = sub2ind(size(m), y, x);
m(idx) = 1;
Example
Here's an example for a small 10-by-10 matrix:
%// This is our initial conditon
m = zeros(10);
p1 = [1, 4];
p2 = [5, 7];
%// Ensure the new x-dimension has the largest displacement
[max_delta, ix] = max(abs(p2 - p1));
iy = length(p1) - ix + 1;
%// Draw a line from p1 to p2 on matrix m
x = p1(ix):p2(ix);
y = round((x - p1(ix)) * (p2(iy) - p1(iy)) / (p2(ix) - p1(ix)) + p1(iy));
m(sub2ind(size(m), y, x)) = 1;
m = shiftdim(m, ix > iy); %// Transpose result if necessary
The result is:
m =
0 0 0 0 0 0 0 0 0 0
0 0 0 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
0 1 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Update: I have patched this algorithm to work when dy > dx by treating the dimension with the largest displacement as if it were the x-dimension, and then transposing the result if necessary.
Neither of the provided answers work for displacements in y greater than in x (dy > dx).
As pointed out, Bresenham's line algorithm is exactly meant for that.
The matlab file provided here works similarly than the examples provided in the other answers but covers all the use-cases.
To relate to the previously provided example, the script can be used like this:
% initial conditions
m = zeros(10);
p1 = [1, 4];
p2 = [5, 10];% note dy > dx
% use file provided on file exchange
[x y] = bresenham(p1(1),p1(2),p2(1),p2(2));
% replace entries in matrix m
m(sub2ind(size(m), y, x)) = 1;
result looks like this:
m =
0 0 0 0 0 0 0 0 0 0
0 0 0 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
0 1 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
0 0 0 1 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
For me (matlab R2013b) following line did not work, when p1(1)>p2(2) (":" can not count backwards):
x = p1(1):p2(1);
E.G.:
1:10
1 2 3 4 5 6 7 8 9 10
10:1
Empty matrix: 1-by-0
But it worked when I used linspac instead:
x = linspace(p1(1), p2(1), abs(p2(1)-p1(1))+1);

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