Linear Algebra using Torch


Linear Algebra using Torch

Here is a list of linear algrebra functions provided by pytorch. The order of the concepts in this notebook is based on deep learning book (by Goodfellow et. al) chapter 2.

Tensors

A tensor is an array of numbers, that may have,

  • zero dimensions, and be a scalar ,
  • one dimension, and be a vector
  • two dimensions, and be a matrix
  • or more dimensions.

importing torch

In [ ]:
import torch

Scalars

A scalar is a number (Integers, real numbers, rational numbers) usually denoted by italic font

In [9]:
x = 12
x
Out[9]:
12

Vectors

A vector is a 1-D array of numbers $$ \textbf{x} = \left[ \begin{array}{c} x_1 \\ x_2 \\ x_3 \\ ... \\ x_n \\ \end{array} \right] $$

In [88]:
x = torch.Tensor(5)  # construct a vector lenght 5, uninitialized
x
Out[88]:
 6.3918e-38
 1.4013e-45
 6.3918e-38
 1.4013e-45
 7.0141e-33
[torch.FloatTensor of size 5]
In [10]:
y = torch.randn(5) # construct a vector lenght 5 with random values
y
Out[10]:
 1.4088
-1.7949
-0.3008
 1.3035
-1.1991
[torch.FloatTensor of size 5]
In [21]:
# make a vector from a range
torch.range(1, 5)
Out[21]:
 1
 2
 3
 4
 5
[torch.FloatTensor of size 5]
In [8]:
x.size() # get the size of a vector
Out[8]:
torch.Size([5])
In [89]:
z = x + y # sum of two vectors (they should have same size)
z
Out[89]:
 1.4088
-1.7949
-0.3008
 1.3035
-1.1991
[torch.FloatTensor of size 5]

Distance between two vectors

Returns the p-norm of (input - other)

In [108]:
dist1 = torch.dist(x,y)
dist2 = torch.dist(x,y,3)
print(dist1, dist2)
2.90408080169 2.32354512733

Matrix

A matrix is a 2-D array of numbers(Integers, real numbers, rational numbers) usually denoted by captial letters $$ \textbf{A} = \left[ \begin{array}{c} x_{11} & x_{12} & x_{13} & ... & x_{1n} \\ x_{21} & x_{22} & x_{23} & ... & x_{2n} \\ x_{31} & x_{32} & x_{33} & ... & x_{3n} \\ ... & ... & ... & ... & ...\\ x_{m1} & x_{m2} & x_{m3} & ... & x_{mn} \\ \end{array} \right] $$

In [94]:
# construct a matrix with 5 rows and 3 columns 
A = torch.Tensor(2, 3)
print('A = ',A)

# construct a matrix with 2 rows and 3 columns with random values
B = torch.randn(2, 3) 
print('B = ',B)

# converting a list of lists into a squared torch matrix
C = torch.Tensor([[6.80, -2.11,  5.66],
                  [-6.05, -3.30,  5.36],
                  [-0.45,  2.58, -2.70]]).t()
print('C = ', C)

# change vector to matrix
D = torch.range(1, 6).view(3, 2)
print('D = ', D)
A =  
 6.3918e-38  1.4013e-45  6.3918e-38
 1.4013e-45  7.0309e-33  1.4013e-45
[torch.FloatTensor of size 2x3]

B =  
 0.6157 -0.5688 -0.1571
 1.2626 -0.8603  1.3070
[torch.FloatTensor of size 2x3]

C =  
 6.8000 -6.0500 -0.4500
-2.1100 -3.3000  2.5800
 5.6600  5.3600 -2.7000
[torch.FloatTensor of size 3x3]

D =  
 1  2
 3  4
 5  6
[torch.FloatTensor of size 3x2]

Identity Matrix

A 2-D tensor with ones on the diagonal and zeros elsewhere

In [93]:
# create an identity matrix with lenght of 3
I3 = torch.eye(3)
I3
Out[93]:
 1  0  0
 0  1  0
 0  0  1
[torch.FloatTensor of size 3x3]

Matrix Addition

$$ E = A + B $$
In [96]:
E = A + B
E
Out[96]:
 0.6157 -0.5688 -0.1571
 1.2626 -0.8603  1.3070
[torch.FloatTensor of size 2x3]

Matrix (Dot) Product

If matrix A is a n x m Tensor, matrix B is a m x p Tensor, out will be a n x p Tensor.

$$ C = AB $$$$ C_{i,j} = \sum_{k} A_{i,k}B_{k,j} $$
In [98]:
# Matrix (Dot) Product
A = torch.randn(2, 3)
B = torch.randn(3, 3)
C = torch.mm(mat1, mat2)
C
Out[98]:
-1.8093 -0.5059  3.2282
-0.4125 -0.9633  1.2989
[torch.FloatTensor of size 2x3]

Matrix-vector Product

Performs a matrix-vector product of the matrix mat and the vector vec.

$$ C = vA $$$$ C_{i,j} = \sum_{k} A_{i,k}v_{k} $$
In [99]:
mat = torch.randn(2, 3)
vec = torch.randn(3)
torch.mv(mat, vec)
Out[99]:
 1.2666
 0.8673
[torch.FloatTensor of size 2]

Slicing

In [44]:
B[:,1] # get second row
Out[44]:
 0.8536
-0.8088
-0.7905
 1.6649
-0.2254
[torch.FloatTensor of size 5]
In [50]:
B[2,:] # get third column
Out[50]:
 1.4403
-0.7905
-0.2565
[torch.FloatTensor of size 3]

Trace

$$ Tr(A) = \sum_{i} A_{i,i} $$
In [59]:
# Trace Sum_{i} A_{i,i}
torch.trace(B)
Out[59]:
-1.7913550734519958

Matrix Transpose

$$ (A^T)_{i,j} = A_{j,i}$$
In [58]:
torch.transpose(B, 0, 1) # for matrix transpose you should always use 0 and 1
Out[58]:
-0.7260  0.7709  1.4403  0.6289 -0.1382
 0.8536 -0.8088 -0.7905  1.6649 -0.2254
 0.1086  0.2285 -0.2565  0.7119 -1.5903
[torch.FloatTensor of size 3x5]

Matrix Inversion

In [79]:
X = torch.rand(4, 4)
print ('X = ',X)
X_inv = torch.inverse(X)
print ('X_inv = ',X_inv)

print ('X.X_inv = ', torch.mm(X, X_inv))
X =  
 0.3917  0.7439  0.9247  0.3545
 0.7052  0.4397  0.4108  0.2657
 0.9407  0.3193  0.3513  0.7634
 0.4330  0.9092  0.3423  0.1048
[torch.FloatTensor of size 4x4]

X_inv =  
-0.9226  2.9167 -0.5220 -0.4724
-0.1413 -1.4749  0.3301  1.8129
 1.3689  1.3265 -0.8989 -1.4458
 0.5659 -3.5877  2.2289  0.4893
[torch.FloatTensor of size 4x4]

X.X_inv =  
 1.0000  0.0000  0.0000 -0.0000
 0.0000  1.0000  0.0000 -0.0000
 0.0000  0.0000  1.0000 -0.0000
 0.0000  0.0000  0.0000  1.0000
[torch.FloatTensor of size 4x4]

Special Matrices

Symmetric Matrix $$ A = A^T $$

In [67]:
A = torch.Tensor([[1, 2,  3],
                  [2, 4,  5],
                  [3,  5, 6]]).t()
print ('A= ', A)
AT = torch.transpose(A, 0, 1)
print ('AT= ',AT)
A=  
 1  2  3
 2  4  5
 3  5  6
[torch.FloatTensor of size 3x3]

AT=  
 1  2  3
 2  4  5
 3  5  6
[torch.FloatTensor of size 3x3]

Orthogonal matrix $$ A^T A = A A^T = I $$ $$ A^{-1} = A^{T} $$

In [69]:
A = torch.Tensor([[0, -0.8,  -0.6],
                  [0.8, -0.36,  0.48],
                  [0.6,  0.48, -0.64]]).t()
print ('A= ', A)
AT = torch.transpose(A, 0, 1)
print ('AT.A = ',torch.mm(AT,A))
A=  
 0.0000  0.8000  0.6000
-0.8000 -0.3600  0.4800
-0.6000  0.4800 -0.6400
[torch.FloatTensor of size 3x3]

AT.A =  
 1.0000  0.0000  0.0000
 0.0000  1.0000  0.0000
 0.0000  0.0000  1.0000
[torch.FloatTensor of size 3x3]

Systems of Equations

$$ Ax = b $$

X, LU = torch.gesv(B, A) returns the solution to the system of linear equations represented by AX=BAX=B LU contains L and U factors for LU factorization of A.

In [102]:
A = torch.Tensor([[6.80, -2.11,  5.66,  5.97,  8.23],
                  [-6.05, -3.30,  5.36, -4.44,  1.08],
                  [-0.45,  2.58, -2.70,  0.27,  9.04],
                  [8.32,  2.71,  4.35,  -7.17,  2.14],
                  [-9.67, -5.14, -7.26,  6.08, -6.87]]).t()
B = torch.Tensor([[4.02,  6.19, -8.22, -7.57, -3.03],
                  [-1.56,  4.00, -8.67,  1.75,  2.86],
                  [9.81, -4.09, -4.57, -8.61,  8.99]]).t()
X, LU = torch.gesv(B, A)

print ('X = ',X)
print ('LU = ', LU)
torch.dist(B, torch.mm(A, X)) # Checking accuracy
X =  
-0.8007 -0.3896  0.9555
-0.6952 -0.5544  0.2207
 0.5939  0.8422  1.9006
 1.3217 -0.1038  5.3577
 0.5658  0.1057  4.0406
[torch.FloatTensor of size 5x3]

LU =  
  8.2300   1.0800   9.0400   2.1400  -6.8700
  0.8262  -6.9423  -7.9193   6.5518  -3.9937
  0.6877  -0.6651 -14.1840   7.2358  -5.1915
  0.7254   0.7524   0.0232 -13.8198  14.1888
 -0.2564   0.4355  -0.5884  -0.3374  -3.4292
[torch.FloatTensor of size 5x5]

Out[102]:
9.457437262677527e-06

Norm

Functions that measure how “large” a vector is, similar to a distance between zero and the point represented by the vector $$ L^{p} - Norm $$

In [112]:
# L2 norm 
l2_norm = torch.norm(A) 

# L3 norm
l3_norm = torch.norm(A,3)

# L1 norm 
l1_norm = torch.norm(A, 1)

# max norm
max_norm = torch.max(torch.abs(A))

print ('L1 norm = ', l1_norm)
print ('L2 norm = ', l2_norm)
print ('L3 norm = ', l3_norm)
print ('Max norm = ', max_norm)
# Max norm  
L1 norm =  123.749999374
L2 norm =  28.0610742907
L3 norm =  17.7363717639
Max norm =  9.67000007629

Eigendecomposition

Computing the eigenvalues and eigenvectors of a real square matrix.

In [114]:
## Eigenvector and eigenvalue
eigenvector, eigenvalue = torch.eig(A, True) 
print('eigenvector = ', eigenvector)
print('eigenvalue = ', eigenvalue)
eigenvector =  
 7.8266  0.0000
-3.2407  9.6876
-3.2407 -9.6876
-9.7738  0.0000
-4.8114  0.0000
[torch.FloatTensor of size 5x2]

eigenvalue =  
-0.6506 -0.0173  0.3863 -0.4833 -0.1003
 0.1991 -0.0695  0.2021 -0.6204  0.1307
-0.1199  0.2167  0.3939  0.4785 -0.0045
-0.5226  0.2855 -0.3181  0.3591  0.8385
-0.4996  0.6480  0.0000 -0.1535  0.5194
[torch.FloatTensor of size 5x5]

Singular Value Decomposition

$$ A = UDV^{T} $$
In [124]:
a = torch.Tensor([[8.79,  6.11, -9.15,  9.57, -3.49,  9.84],
                  [9.93,  6.91, -7.93,  1.64,  4.02,  0.15],
                  [9.83,  5.04,  4.86,  8.83,  9.80, -8.99],
                  [5.45, -0.27,  4.85,  0.74, 10.00, -6.02],
                  [3.16,  7.98,  3.01,  5.80,  4.27, -5.31]]).t()
u, s, v = torch.svd(a)
print(u,s,v)

# accuracy
print(torch.dist(a, torch.mm(torch.mm(u, torch.diag(s)), v.t())))
-0.5911  0.2632  0.3554  0.3143  0.2299
-0.3976  0.2438 -0.2224 -0.7535 -0.3636
-0.0335 -0.6003 -0.4508  0.2334 -0.3055
-0.4297  0.2362 -0.6859  0.3319  0.1649
-0.4697 -0.3509  0.3874  0.1587 -0.5183
 0.2934  0.5763 -0.0209  0.3791 -0.6526
[torch.FloatTensor of size 6x5]
 
 27.4687
 22.6432
  8.5584
  5.9857
  2.0149
[torch.FloatTensor of size 5]
 
-0.2514  0.8148 -0.2606  0.3967 -0.2180
-0.3968  0.3587  0.7008 -0.4507  0.1402
-0.6922 -0.2489 -0.2208  0.2513  0.5891
-0.3662 -0.3686  0.3859  0.4342 -0.6265
-0.4076 -0.0980 -0.4933 -0.6227 -0.4396
[torch.FloatTensor of size 5x5]

1.03819075292e-05