Torch tensors swapping dimensions - lua

I came across these two lines (back-to-back) of code in a torch project:
im4[{1,{},{}}] = im3[{3,{},{}}]
im4[{3,{},{}}] = im3[{1,{},{}}]
What do these two lines do? I assumed they did some sort of swapping.

This is covered in indexing in the Torch Tensor Documentation
Indexing using the empty table {} is shorthand for all indices in that dimension. Below is a demo which uses {} to copy an entire row from one matrix to another:
> a = torch.Tensor(3, 3):fill(0)
0 0 0
0 0 0
0 0 0
> b = torch.Tensor(3, 3)
> for i=1,3 do for j=1,3 do b[i][j] = (i - 1) * 3 + j end end
> b
1 2 3
4 5 6
7 8 9
> a[{1, {}}] = b[{3, {}}]
> a
7 8 9
0 0 0
0 0 0
This assignment is equivalent to: a[1] = b[3].
Your example is similar:
im4[{1,{},{}}] = im3[{3,{},{}}]
im4[{3,{},{}}] = im3[{1,{},{}}]
which is more clearly stated as:
im4[1] = im3[3]
im4[3] = im3[1]
The first line assigns the values from im3's third row (a 2D sub-matrix) to im4's first row and the second line assigns the first row of im3 to the third row of im4.
Note that this is not a swap, as im3 is never written and im4 is never read from.

Related

Torch: Concatenating tensors of different dimensions

I have a x_at_i = torch.Tensor(1,i) that grows at every iteration where i = 0 to n. I would like to concatenate all tensors of different sizes into a matrix and fill the remaining cells with zeroes. What is the most idiomatic way to this. For example:
x_at_1 = 1
x_at_2 = 1 2
x_at_3 = 1 2 3
x_at_4 = 1 2 3 4
X = torch.cat(x_at_1, x_at_2, x_at_3, x_at_4)
X = [ 1 0 0 0
1 2 0 0
1 2 3 0
1 2 3 4 ]
If you know n and assuming you have access to your x_at_i easily at each iteration I would try something like
X = torch.Tensor(n, n):zero()
for i = 1, n do
X[i]:narrow(1, 1, i):copy(x_at[i])
end

How to count the number of repetitions for every single number?

So I have a for loop that loops 100 times and each time it generates a random number from 1 to 100. For some statistics, I need to count how many times each number repeats. I have no idea how to make it other than manually.
One = 0
Two = 0
Three = 0
Four = 0
Five = 0
for i=1, 100 do
number = GetRandomNumber(1, 5, 1.5)
if number == 1 then
One = One + 1
elseif number == 2 then
Two = Two + 1
elseif number == 3 then
Three = Three + 1
elseif number == 4 then
Four = Four + 1
elseif number == 5 then
Five = Five + 1
end
end
This is how I currently count, but I don't want to manually type for every number. How can I make this simpler?
I do it as such:
number_counter, number = {}, 0
for i = 1, 100 do
number = GetRandomNumber(1, 5, 1.5)
if number_counter[number] then
number_counter[number] = number_counter[number] + 1
else
number_counter[number] = 1
end
end
This is, of course, assuming there are no half points (not sure what the 1.5 is for). Then you can just call number_counter[#] to see what its value is.

Batch processing in Torch with ClassNLLCriterion

I'm trying to implement a simple NN in Torch to learn more about it. I created a very simple dataset: binary numbers from 0 to 15 and my goal is to classify the numbers into two classes - class 1 are numbers 0-3 and 12-15, class 2 are the remaining ones. The following code is what i have now (i have removed the data loading routine only):
require 'torch'
require 'nn'
data = torch.Tensor( 16, 4 )
class = torch.Tensor( 16, 1 )
network = nn.Sequential()
network:add( nn.Linear( 4, 8 ) )
network:add( nn.ReLU() )
network:add( nn.Linear( 8, 2 ) )
network:add( nn.LogSoftMax() )
criterion = nn.ClassNLLCriterion()
for i = 1, 300 do
prediction = network:forward( data )
--print( "prediction: " .. tostring( prediction ) )
--print( "class: " .. tostring( class ) )
loss = criterion:forward( prediction, class )
network:zeroGradParameters()
grad = criterion:backward( prediction, class )
network:backward( data, grad )
network:updateParameters( 0.1 )
end
This is how the data and class Tensors look like:
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1
[torch.DoubleTensor of size 16x4]
2
2
2
2
1
1
1
1
1
1
1
1
2
2
2
2
[torch.DoubleTensor of size 16x1]
Which is what I expect it to be. However when running this code, i get the following error on line loss = criterion:forward( prediction, class ):
torch/install/share/lua/5.1/nn/ClassNLLCriterion.lua:69: attempt to
perform arithmetic on a nil value
When i modify the training routine like this (processing a single data point at a time instead of all 16 in a batch) it works and the network successfully learns to recognize the two classes:
for k = 1, 300 do
for i = 1, 16 do
prediction = network:forward( data[i] )
--print( "prediction: " .. tostring( prediction ) )
--print( "class: " .. tostring( class ) )
loss = criterion:forward( prediction, class[i] )
network:zeroGradParameters()
grad = criterion:backward( prediction, class[i] )
network:backward( data[i], grad )
network:updateParameters( 0.1 )
end
end
I'm not sure what might be wrong with the "batch processing" i'm trying to do. A brief look at the ClassNLLCriterion didn't help, it seems i'm giving it the expected input (see below), but it still fails. The input it receives (prediction and class Tensors) looks like this:
-0.9008 -0.5213
-0.8591 -0.5508
-0.9107 -0.5146
-0.8002 -0.5965
-0.9244 -0.5055
-0.8581 -0.5516
-0.9174 -0.5101
-0.8040 -0.5934
-0.9509 -0.4884
-0.8409 -0.5644
-0.8922 -0.5272
-0.7737 -0.6186
-0.9422 -0.4939
-0.8405 -0.5648
-0.9012 -0.5210
-0.7820 -0.6116
[torch.DoubleTensor of size 16x2]
2
2
2
2
1
1
1
1
1
1
1
1
2
2
2
2
[torch.DoubleTensor of size 16x1]
Can someone help me out here? Thanks.
Experience has shown that nn.ClassNLLCriterion expects target to be a 1D tensor of size batch_size or a scalar. Your class is a 2D one (batch_size x 1) but class[i] is 1D, that's why your non-batch version works.
So, this will solve your problem:
class = class:view(-1)
Alternatively, you can replace
network:add( nn.LogSoftMax() )
criterion = nn.ClassNLLCriterion()
with the equivalent:
criterion = nn.CrossEntropyCriterion()
The interesting thing is that nn.CrossEntropyCriterion is also able to take a 2D tensor. Why is nn.ClassNLLCriterion not?

KMP Preprocessing Function

this is the pseudo code I've see in ItoA:
1 m = P.length
2 let pi[1...m] be a new array
3 pi[1] = 0
4 k=0
5 for q=2 to m
6 while k > 0 and P[k+1] != P[q]
7 k = pi[k]
8 if P[k+1] == P[q]
9 k = k+1
10 pi[q] = k
11 return pi
my doubt is why on line 6 we do k = pi[k] instead of k-- which seems to me that should be the way of checking a preffix of length k (because if P[k+1] != P[q] it means that a preffix of lenght k+1 that's also suffix cannot be achieved) which can be also suffix, that is comparing with P[q], I also think that if we do it, the running time will stay the same.
The recursive call k = pi[k] searches for the smaller border of p[1..q]; because the pi[k], which is the largest border of P[0..k], is smaller border of p[1..q] than pi[q]. It will search until it finds a border of p[1..q] where the next character p[k+1] is not equal to P[q+1].
You can find more details here: http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm

Opencv: how to create new matrix from existing matrix with some changes?

in OpenCV, I have a matrix like this: [3 4 2; 5 2 1; 6 7 9], that is with 3x3 size. Now I want to change it into 3x1 size, and be like this:
[3 4 2 5 2 1 6 7 9]. But this is not exactly what I want, my actual goal is to put zero before and after each value, at the same time repeat each value three times. So my goal matrix should be like this: [ 0 3 3 3 0 0 4 4 4 0 0 2 2 2 0 0 5 5 5 0 0 2 2 2 0 0 1 1 1 0 0 6 6 6 0 0 7 7 7 0 0 9 9 9 0 ]. I wrote the following code for this:
for ( int i = 0; i < 3; i ++ )
{
for ( int j = 0; j < 3; j ++ )
{
for ( int m = k + 1; m < m + 3; m ++ )
{
dstMat.col (m) = srcMat.at <int> ( i, j );
}
k = k + 5 ;
}
}
Is there any better way for doing is? Especially without "for" loop, it is really time confusing. Many thanks in advance.
You can use Mat::reshape to convert your 3x3 matrix to 3x1. This way you'll need one for loop instead of two, and it's an O(1) operation.
you can omit the next for loop by using ROI:
srcMat.reshape(0,1);
for (int i =0; i < 9; i++)
dstMat(cv::Range::all(), cv::Range(i*5+1, i*5+4)).setTo(srcMat.at<int>(i));
and that would be all.
You could start by calling reshape on your matrix to flatten it to one row/column. That would save you one of the for loops and make it slightly clearer.

Resources