Tensorflow : one hot encoding - eval

The following code works fine, but uses eval() which I think would be inefficient. Is there a better way to achieve the same ?
import tensorflow as tf
import numpy as np
sess = tf.Session()
t = tf.constant([[4,5.1,6.3,5,6.5,7.2,9.3,7,1,1.4],[4,5.1,9.3,5,6.5,7.2,1.3,7,1,1.4],[4,3.1,6.3,5,6.5,3.2,5.3,7,1,1.4]])
print t
a = tf.argmax(t,1).eval(session=sess)
z = [ k==np.arange(14) for k in a]
z1 = tf.convert_to_tensor(np.asarray(z).astype('int32'))
print z1
print sess.run(z1)
output
Tensor("Const_25:0", shape=TensorShape([Dimension(3), Dimension(10)]), dtype=float32)
Tensor("Const_26:0", shape=TensorShape([Dimension(3), Dimension(14)]), dtype=int32)
[[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 0]
[0 0 0 0 0 0 0 1 0 0 0 0 0 0]]

One way to achieve it is to compute max on each row and then compare each element to that value. I don't have tensor flow installed on this machine, so can't provide you with the exact code, but it will be along the lines of this:
z1 = tf.equal(t, tf.reduce_max(t, reduction_indices=[1], keep_dims=True))

Related

How to copy and paste a small matrix into a bigger matrix without for-loop

For example, we have a small matrix
B = [5 2,
3 4]
and the bigger one
A = [1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1]
Now I want paste B into A so that A looks like
A = [1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 5 2
0 0 0 3 4]
That means the values of A of the bottom right has been replaced. I would like to do this without using a for-loop. How is that possible?
PS:
A is always an eye(n) matrix (n is a constant).
B is a square matrix and has a variable size but is always less or equal to A
Find the relevant row and column subscripts of A and put B there.
A(end-size(B,1)+1:end, end-size(B,2)+1:end)=B
It works even if B is not a square matrix.

How to create a Boolean Numpy Array using fancy indexing

I have the following dummy array:
>>> arr
[[0 0 1 0 0 1 0 1 1 1 0 0]
[1 1 0 1 1 0 0 0 0 0 1 1]
[1 1 0 1 0 1 0 0 0 0 1 0]
[1 1 0 1 1 0 1 1 0 0 0 1]
[0 1 0 1 0 1 1 1 0 0 0 1]
[1 0 1 1 1 0 0 1 0 0 1 1]]
I also have some "mutations" I would like to incorporate into my array, at the following positions (note these are generated randomly each time, so I cannot just set them manually):
row = [0 4 3]
col = [11 10 7]
I know I can target each (row, col) pair using fancy indexing with arr[row, col] = -3 (for example, set those elements to -3).
However, what I want to do is a bitwise NOT - aka something like this:
arr[row, col] = ~arr
I tried using np.where(), but it won't accept arr[row, col] b/c it doesn't generate a boolean array.
Any suggestions? How can I create a boolean array to use as a where conditional
(also yes, I know I can make an array of all zeros in the same shape as arr and then set those positions to 1's and use that as a mask - I'd love something cleaner tho)
Thanks!

Array block splitting in MATLAB

Say we have a vector containing zeros interspersed blocks of ones of varying length, such as:
0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0
I would like to transform this into a 2D array as follows. Each row contains zeros only and one of the blocks. I.e. the number of rows of the 2D array would be the number of blocks at the end. The above array would transform to:
0 0 0 1 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 1 1 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 1 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 1 1 1 0 0 0
I.e the first block ends up in the first row, the second block in the second row etc.
Question
This exercise is rather trivial using loops. My question is if there is a neat way using MATLAB matrix operations, MATLAB functions and array indexing to do this?
Off the top of my head you could use bwlabel (from the Image Processing Toolbox) to assign each cluster of 1's a unique value. You could then use bsxfun to check equality between the labeled version and the unique labels which will automatically expand it out into a matrix.
a = [0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0];
b = bwlabel(a);
out = bsxfun(#eq, (1:max(b))', b);
Without the image processing toolbox you could do effectively the same thing with:
C = cumsum(~a);
out = bsxfun(#eq, unique(C(logical(a))).', C);
I tried this one
N = 100; % set array size
A = randi(2,N,1)-1; % generate random array filled with 0 and 1
d = diff([0;A]); % if 1 : starting point of block
% if -1 : end point of block
ir = find(A); % Find A==1 which will be row index
ic = cumsum(d(ir)>0); % Set col index
% assemble array
% if you want output as full array
A_new = accumarray([ir,ic],ones(size(ir)),[length(A),ic(end)]);
% if you want output as sparse array
A_new = sparse(ir,ic,ones(size(ir)),length(A),ic(end),length(ir));
% display routine
figure;spy(A,'r');hold on;spy([zeros(size(A)),A_new]);
Turns out it is faster than #Suever 's solution (Compared tic toc time with size 10000, 1000 trial). Also, if you use sparse instead of accumarray, then it is much faster
Suever_time = 7~8 sec
Accumarray = 2~3 sec
Sparse = 0.2~0.3 sec
However, his one is much shorter and neat!

Convert integer to logical array in 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;

Assign sequential number to integer element in array

Good morning/afternoon~
I have an array like this,
A= [12 0 0 0 0 3 0 0 0 66 0 0 0 0 20 0 0 2 0 31 0 0 42 0 32 0 38]
the output should be:
B= [ 1 0 0 0 0 2 0 0 0 3 0 0 0 0 4 0 0 5 0 6 0 0 7 0 8 0 9]
What should I do to replace the non-zero elements in A with sequential number?
This will do it:
A(A ~= 0) = 1:nnz(A)
A(ismember(A,A(A(:) ~=0))) = 1:numel(A(A(:) ~=0))
With the image processing toolbox (will give the same label to adjacent non-zero values, though):
B = bwlabel(A)
B = cumsum(A ~= 0) .* (A ~= 0);

Resources