How Pytorch do row normalization for each matrix in a 3D Tensor(Variable)? - torch

If I have a 3D Tensor (Variable) with size [a,b,c].
consider it as a b*c matrix, and I hope that all these a matrix got row normalized.

You can use the normalize function.
import torch.nn.functional as f
f.normalize(input, p=2, dim=2)
The dim=2 argument tells along which dimension to normalize (divide each row vector by its p-norm.

The following should work.
import torch
import torch.nn.functional as f
a, b, c = 10, 20, 30
t = torch.rand(a, b, c)
g = f.normalize(t.view(t.size(0), t.size(1) * t.size(2)), p=1, dim=1)
print(g.sum(1)) # it confirms the normalization
g = g.view(*t.size())
print(g) # get the normalized output vector of shape axbxc

To normalize a matrix in such a way that the sum of each row is 1, simply divide by the sum of each row:
import torch
a, b, c = 10, 20, 30
t = torch.rand(a, b, c)
t = t / (torch.sum(t, 2).unsqueeze(-1))
print(t.sum(2))

Related

How to initialize an m*n matrix in R with specific row and column names

I am trying to find a way to initialize a m*n matrix in R.
Let's say I have a seq of variable names c(a, b, c, d), and I would like to create a 4*10 matrix with c(a, b, c, d) being the vertical variable, and seq(1:10) to be horizontal variable, so I can check the matrix with the call matrix[a, 1].
Thanks in advance
We can create the matrix as
m1 <- matrix(nrow = 4, ncol = 10, dimnames = list(letters[1:4], NULL))
and use the row names and column index to extract elements
m1['a', 1]
Another base R option using row.names<-
`row.names<-`(matrix(nrow = 4, ncol = 10), head(letters, 4))

Correlation coefficient for three variables in r

For three n-dimensional non-zero-variance variables a, b, and c, n > 2, if
r(ab), r(bc), and r(ac) are Pearson’s correlation coefficients between a and b, between b and c, and between a and c, respectively, then correlation coefficient r(abc) among a, b, and c is defined as:
r^2(abc) = ( r^2(ab) + r^2(bc) + r^2(ac) ) - ( 2 x r(ab) x r(bc) x r(ac) )
I was able to get the code for a manual way of doing it:
a <- c(4, 6, 2, 7)
b <- c(8, 1, 3, 5)
c <- c(6, 3, 1, 9)
al <- data.frame(a, b, c)
al
ab_cor <- cor(al$a, al$b, method = c("pearson"))
bc_cor <- cor(al$b, al$c, method = c("pearson"))
ac_cor <- cor(al$a, al$c, method = c("pearson"))
abc_cor <- sqrt( ( (ab_cor)^2 + (bc_cor)^2 + (ac_cor)^2 ) - ( 2 * ab_cor * bc_cor * ac_cor) )
abc_cor
But I was wondering if this could be done with less lines of code, for example with a for loop. Addittionaly, how would I write it so that I could do it with more than 3 variables as well, for example, r(abcd) i.e. r(ab), r(ac), r(ad), r(bc), r(bd), and r(cd).
The cor function already creates a matrix of the correlations. You just need to pick out the relevant ones and then use some vector operations.
cs <- cor(al, method = "pearson")
cs <- cs[upper.tri(cs)]
#sqrt(sum(cs^2)) - 2*prod(cs)
# apparently it's
sqrt(sum(cs^2) - 2*prod(cs))
This generalizes to your larger case as well assuming that you have all the variables you want in your al data.frame.

Split a tensor in torch

Given an input tensor of size n x 2A x B x C, how to split it into two tensors, each of size n x A x B x C? Essentially, n is the batch size.
You can use torch.split:
torch.split(input_tensor, split_size_or_sections=A, dim=1)
I think you could do something like:
tensor_a = torch.Tensor(n, 2A, B,C)
-- Initialize tensor_a with the data
tensor_b = torch.Tensor(n, A, B, C)
tensor_b = tensor_a[{{},1,{},{}}]
tensor_c = torch.Tensor(n, A, B, C)
tensor_c = tensor_a[{{},2,{},{}}]

Extract rows / columns of a matrix into separate variables

The following question came up in my course yesterday:
Suppose I have a matrix M = rand(3, 10) that comes out of a calculation, e.g. an ODE solver.
In Python, you can do
x, y, z = M
to extract the rows of M into the three variables, e.g. for plotting with matplotlib.
In Julia we could do
M = M' # transpose
x = M[:, 1]
y = M[:, 2]
z = M[:, 3]
Is there a nicer way to do this extraction?
It would be nice to be able to write at least (approaching Python)
x, y, z = columns(M)
or
x, y, z = rows(M)
One way would be
columns(M) = [ M[:,i] for i in 1:size(M, 2) ]
but this will make an expensive copy of all the data.
To avoid this would we need a new iterator type, ColumnIterator, that returns slices? Would this be useful for anything other than using this nice syntax?
columns(M) = [ slice(M,:,i) for i in 1:size(M, 2) ]
and
columns(M) = [ sub(M,:,i) for i in 1:size(M, 2) ]
They both return a view, but slice drops all dimensions indexed with
scalars.
A nice alternative that I have just found if M is a Vector of Vectors (instead of a matrix) is using zip:
julia> M = Vector{Int}[[1,2,3],[4,5,6]]
2-element Array{Array{Int64,1},1}:
[1,2,3]
[4,5,6]
julia> a, b, c = zip(M...)
Base.Zip2{Array{Int64,1},Array{Int64,1}}([1,2,3],[4,5,6])
julia> a, b, c
((1,4),(2,5),(3,6))

dim() Error in outer

I have made the following function I would like to make a 3-dimensional image of using the function "persp", therefore I use the function outer, to get the value of the function for each combination of a and b, but this make an Error.
So my code is:
a<- seq(from=0, to=5,by=0.25)
b<- seq(from=0.1, to=2,by=0.1)
Rab <- function(a,b){
r <- matrix(ncol = 1, nrow = 4)
for (p in seq(from=0, to=4,by=1)){
g <- ifelse(a>=0 & a<1-1/p & p >b, a*p,
ifelse(a>=0 & a<1-1/b & p< b, -1+(a+1/b),
ifelse(a > 1-1/max(p,b),-1+p,NA)))
w <- p
r[w] <- g
}
return(r)
}
q <- outer(a,b,Rab)
And then I get the following Error and warning messages, which I don't understand.
Error in outer(a, b, Rab) :
dims [product 420] do not match the length of object [4]
In addition: Warning messages:
1: In r[w] <- g :
number of items to replace is not a multiple of replacement length
2: In r[w] <- g :
number of items to replace is not a multiple of replacement length
3: In r[w] <- g :
number of items to replace is not a multiple of replacement length
4: In r[w] <- g :
number of items to replace is not a multiple of replacement length
I have tried to read about it, and I think it is because I have constructed the function Rab wrong, but I don't know how to correct it.
Any help is appreciated.
You are right that your Rab function is wrong. The documentation of outer says
X and Y must be suitable arguments for FUN. Each will be extended by rep to length the products of the lengths of X and Y before FUN is called.
FUN is called with these two extended vectors as arguments (plus any arguments in ...). It must be a vectorized function (or the name of one) expecting at least two arguments and returning a value with the same length as the first (and the second).
So in your example a and b are extended to both have length length(a) * length(b), which happens to be 420 in your case. your function Rab should then return a vector of the same length.
In Rab you compute a vector g that has the correct length and would be suitable as a return value. Instead of returning this vector you try to assign it to an entry in the matrix r. Note that this matrix is defined as
r <- matrix(ncol = 1, nrow = 4)
and can't hold vectors of length 420 in either its rows or columns (this is what the warning messages are about). You lose all but the first element of your vector g in the process. You then go on to re-compute g with a slightly different set of parameters, which brings us to the next problem. These computations happen in a loop that is defined like this:
for (p in seq(from=0, to=4,by=1)){
## compute g ...
r[p] <- g
}
You seem to expect this loop to be executed four times but it is actually run five times for values of p equalling 0, 1, 2, 3 and 4. This means that the first g is assigned to r[0], which R silently ignores. Of course when you then try to return r none of this really matters because it only has length 4 (rather than 420) and this triggers an error.
I'm not convinced that I really understand what you are trying to do but the following might be a step in the right direction.
Rab <- function(a, b, p){
ifelse(a>=0 & a<1-1/p & p >b, a*p,
ifelse(a>=0 & a<1-1/b & p< b, -1+(a+1/b),
ifelse(a > 1-1/max(p,b),-1+p,NA)))
}
This will compute the g from your function once for a fixed value of p and return the result. You'd call this like so (for p=0):
q <- outer(a, b, Rab, 0)
If you want to call it for a number of different p you can do something like
q <- lapply(0:3, function(x,y,f, p) outer(x, y, f, p), x=a, y=b, f=Rab)
This would call Rab with p = 0, 1, 2 and 3 (I'm guessing that's what you want, adjust as required).

Categories

Resources