Cross-correlation in tensorflow? - arrays

I'm new to tensorflow, I'm trying to get a cross-correlation of two 1D array. The function tfp.stats.correlation doesn't give me the desired output and it required both the array to be the same size. For the multiplication, It appear that it need the same dimension.
I'm basically just simply converting the numpy to tensorflow. The code below work when both the array are the same size, and it doesnt work when they are not. How can I make it work for both??
def xcorr(a, b):
fa = tf.signal.fft(a)
fb = tf.signal.fft(b)
xx = tf.math.multiply(fa,tf.math.conj(fb))
xcc = tf.signal.fftshift(tf.signal.ifft(xx))
aa = tf.math.multiply(fa,tf.math.conj(fa))
xaa = tf.signal.fftshift(tf.signal.ifft(aa))
bb = tf.math.multiply(fb,tf.math.conj(fb))
xbb = tf.signal.fftshift(tf.signal.ifft(bb))
xcc = tf.math.divide(xcc,tf.math.sqrt(tf.math.multiply(xaa[len(a)-1],xbb[len(b)-1])))
return tf.math.real(xcc)

Related

Pytorch: Test each row of the first 2D tensor also exist in the second tensor?

Given two tensors t1 and t2:
t1=torch.tensor([[1,2],[3,4],[5,6]])
t2=torch.tensor([[1,2],[5,6]])
If the row elements of t1 is exist in t2, return True, otherwise return False. The ideal result is
[Ture, False, True].
I tried torch.isin(t1, t2), but its return the results by elements not by rows. By the way, if they are numpy arrays, it can be completed by
np.in1d(t1.view('i,i').reshape(-1), t2.view('i,i').reshape(-1))
I wonder how to get the similar result in tensor?
def rowwise_in(a,b):
"""
a - tensor of size a0,c
b - tensor of size b0,c
returns - tensor of size a1 with 1 for each row of a in b, 0 otherwise
"""
# dimensions
a0 = a.shape[0]
b0 = b.shape[0]
c = a.shape[1]
assert c == b.shape[1] , "Tensors must have same number of columns"
a_expand = a.unsqueeze(1).expand(a0,b0,c)
b_expand = b.unsqueeze(0).expand(a0,b0,c)
# element-wise equality
equal = a_expand == b_expand
# sum along dim 2 (all elements along this dimension must be true for the summed dimension to be True)
row_equal = torch.prod(equal,dim = 2)
row_in_b = torch.max(row_equal, dim = 1)[0]
return row_in_b
In addition to the greate solution of DerekG this small change seems more fast and robust
a,b = torch.tensor([[1,2,3],[3,4,5],[5,6,7]],device=torch.device(0)), torch.tensor([[1,2,3],[5,6,7]],device=torch.device(0))
# dimensions
shape1 = a.shape[0]
shape2 = b.shape[0]
c = a.shape[1]
assert c == b.shape[1] , "Tensors must have same number of columns"
a_expand = a.unsqueeze(1).expand(-1,shape2,c)
b_expand = b.unsqueeze(0).expand(shape1,-1,c)
# element-wise equality
mask = (a_expand == b_expand).all(-1).any(-1)
I tried that for tensors with 10 000 rows, it works pretty fast and without memory wasting

Reshaping nested struct arrays to cell array having elements with different sizes

I have a similar question to my previous one. This time the form of the nested structure looks like this:
Sizes = [2, 5, 8, 6, 3];
cells = 5;
for i = 1:cells
for j = 1:Sizes(i)
a(i).b.c(j).d = rand(1,1);
end
a(i).b.Size = Sizes(i);
end
Again I would like to put all the d values of a(:).b.c(:) into a single cell array that contains 1 x cells cells.
Here is my solution using cellfun but I would like to avoid this function:
ab = [a.b];
abc = {ab.c};
abcd = cellfun(#(x) [x.d], abc, 'UniformOutput', false);
Using the previous solution for abc:
abc = [ab.c];
creates a 1x24 struct array with field d. I thought of using the Size field to reshape this result into a cell array but I don't know how or if it is possible. Do you have a better appraoch without using loops and without cellfun?
You can do this using mat2cell as follows:
ab = [a.b];
abc = [ab.c];
abcd = mat2cell([abc.d], 1, [ab.Size]);

Create a 2D list with variable length [torch]

I want to create a 2D list that can have elements of variable lengths inside, for example, if I have a 10x10 list in MATLAB, I can
define it with:
z = cell(10,10)
and start assigning some elements by doing this:
z{2}{3} = ones(3,1)
z{1}{1} = zeros(100,1)
z{1}{2} = []
z{1}{3} = randn(20,1)
...
What is the optimal way to define such empty 2D list in torch? Moreover, is there a way to exploit the tensor structure to do this?
In python, I can do something along this to define an empty 10x10 2D list:
z = [[None for j in range(10)] for i in range(10)]
My best guess for torch is doing something like
z = torch.Tensor(10,10)
for i=1,10 do
for j=1,10 do
z[{{i},{j}}] = torch.Tensor()
end
end
but, this does not work, and defining a tensor inside a tensor seems like a bad idea ...
This is a follow up to the question asked here (however in the link it is asked in python): Create 2D lists in python with variable length indexed vectors
From the documentation I've read, tensors only support primitive numeric data types. You won't be able to use tensor for your intended usage. Leverage tables.
local function makeMatrix(initialVal, ...)
local isfunc = type(initialVal) == "function"
local dimtable = {...}
local function helper(depth)
if depth == 0 then
return isfunc and initialVal() or initialVal
else
local plane = {}
for i = 1, dimtable[depth] do
plane[i] = helper(depth-1)
end
return plane
end
end
return helper(#dimtable)
end
p = makeMatrix(0, 2, 3, 5) -- makes 3D matrix of size 2x3x5 with all elements initialized to 0
makeMatrix(torch.Tensor, m ,n)
Answer from Torch's Google Group forums. Agreeing that tables is the solution:
z = {}
for i=1,10 do
z[i] = {}
for j=1,10 do
z[i][j] = torch.Tensor()
end
end

The use of Cell array of strings in a program

Suppose I have the following code
mc = {[2 5],[2 5],[8 9 2],[33 77 4],[102 6],[110 99],[2 5]}
(Identifying uniques in a cell array:Jonas Answer):
%# convert to strings
mcs = cellfun(#(x)(mat2str(x)),mc,'uniformoutput',false);
%# run unique
[uniqueCells,idxOfUnique,idxYouWant] = unique(mcs);
fileName = ['C:\Users\MATLAB\matrice_Result.mat'];
save(fileName,'uniqueCells');
to load the result and use it as a cell, Can I do that ?:
load('C:\Users\MATLAB\matrice_Result.mat');
A = uniqueCells;
B = [5 77 41 66 7];
(Finding the vectors of the cell A that contain at least one element of the vector B: Divakar Answer)
R = A(arrayfun(#(n) any(ismember(B,A{n})),1:numel(A)));
I have the impression that the second code does not recognize A !!!
Just use str2num(A{n}) to convert each cell of A back into numeric form:
R = A(arrayfun(#(n) any(ismember(B,str2num(A{n}))),1:numel(A)));
The above gives the result in string form, because A{n} is converted to numbers within ismember but A is left in string form. If you want the result in numeric form, first convert A and then apply your (Divakar's) original line to the converted A:
A_num = cellfun(#str2num, A, 'uniformoutput', 0);
R = A_num(arrayfun(#(n) any(ismember(B,A_num{n})),1:numel(A)));

How to concatenate arrays from cell arrays in Matlab

I am new to Matlab and was trying to concatenate array from cell arrays. I have done it as shown below.
S = load('input_file.mat');
c = struct2cell(S);
v = cell2mat(c(1,1));
temp = v(1:500,1:600);
v = cell2mat(c(3,1));
temp1 = v(1:500,1:600);
v = cell2mat(c(2,1));
temp2 = v(1:500,1:600);
v = cell2mat(c(4,1));
temp3 = v(1:500,1:600);
array1 = vertcat(temp,temp1);
array2 = vertcat(temp2,temp3);
But i guess there should be a better way or a direct function call which can get me the same result as i am getting from the code shown?
This is a very specific task, not very general, unless I'm missing the pattern. Starting after struct2cell:
C3 = cellfun(#(x)x(1:500,1:600),c,'uni',0);
array1 = vertcat(C3{[1 3]});
array2 = vertcat(C3{[2 4]});
Although, you could probably get rid of your initial structfun if you replace cellfun above with structfun, taking s as an input. It simply operates on each field.

Resources