Tensorflow - Numpy Equivalence

Exercises in Refresher_numpy are repeated for tensorflow version

In [1]:
import tensorflow as tf
import numpy as np
In [2]:
sess = tf.Session()
In [4]:
const = tf.constant(10)
sess.run(const)
Out[4]:
10

Generating sequence

In [7]:
arange = tf.range(0,10,1)
print(arange)
print(arange.op)
Tensor("range_2:0", shape=(10,), dtype=int32)
name: "range_2"
op: "Range"
input: "range_2/start"
input: "range_2/limit"
input: "range_2/delta"
attr {
  key: "Tidx"
  value {
    type: DT_INT32
  }
}

In [8]:
sess.run(arange)
Out[8]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)
In [11]:
linspace = tf.linspace(0.,10.,10) #start stop must be float
print(linspace.op)
name: "LinSpace_2"
op: "LinSpace"
input: "LinSpace_2/start"
input: "LinSpace_2/stop"
input: "LinSpace_2/num"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}
attr {
  key: "Tidx"
  value {
    type: DT_INT32
  }
}

In [13]:
sess.run(linspace)
Out[13]:
array([ 0.       ,  1.1111112,  2.2222223,  3.3333335,  4.4444447,
        5.555556 ,  6.666667 ,  7.777778 ,  8.888889 , 10.       ],
      dtype=float32)

Tensor creation

In [14]:
zeros = tf.zeros((3,5)) #or tf.ones
print(zeros.op)
name: "zeros"
op: "Const"
attr {
  key: "dtype"
  value {
    type: DT_FLOAT
  }
}
attr {
  key: "value"
  value {
    tensor {
      dtype: DT_FLOAT
      tensor_shape {
        dim {
          size: 3
        }
        dim {
          size: 5
        }
      }
      float_val: 0.0
    }
  }
}

In [15]:
sess.run(zeros)
Out[15]:
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]], dtype=float32)
In [26]:
fill = tf.fill((3,5),4)
print(fill.op)
sess.run(fill)
name: "Fill_2"
op: "Fill"
input: "Fill_2/dims"
input: "Fill_2/value"
attr {
  key: "T"
  value {
    type: DT_INT32
  }
}
attr {
  key: "index_type"
  value {
    type: DT_INT32
  }
}

Out[26]:
array([[4, 4, 4, 4, 4],
       [4, 4, 4, 4, 4],
       [4, 4, 4, 4, 4]], dtype=int32)
In [27]:
fill_const = tf.constant(4,shape=(3,5))
print(fill_const.op)
sess.run(fill_const)
name: "Const_2"
op: "Const"
attr {
  key: "dtype"
  value {
    type: DT_INT32
  }
}
attr {
  key: "value"
  value {
    tensor {
      dtype: DT_INT32
      tensor_shape {
        dim {
          size: 3
        }
        dim {
          size: 5
        }
      }
      int_val: 4
    }
  }
}

Out[27]:
array([[4, 4, 4, 4, 4],
       [4, 4, 4, 4, 4],
       [4, 4, 4, 4, 4]], dtype=int32)
In [16]:
rnd_normal = tf.random_normal((3,5),1,0.01)
print(rnd_normal.op)
name: "random_normal"
op: "Add"
input: "random_normal/mul"
input: "random_normal/mean"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}

In [17]:
sess.run(rnd_normal)
Out[17]:
array([[0.9995551 , 0.99447954, 0.98896337, 1.0143579 , 1.004673  ],
       [0.9862911 , 1.003186  , 1.0032037 , 0.9918547 , 1.0023279 ],
       [1.0119741 , 1.0049429 , 1.0007715 , 0.99658316, 0.99718565]],
      dtype=float32)

Using random seed

In [89]:
tf.set_random_seed(99)
In [40]:
rnd_int = tf.random_uniform((3,5),0,10,dtype=tf.int32,seed=101)
sess.run(rnd_int)
Out[40]:
array([[3, 5, 1, 3, 3],
       [0, 6, 8, 4, 1],
       [2, 4, 7, 9, 5]], dtype=int32)

Reshaping

Everything works same as numpy

In [43]:
const = tf.range(0,15,1)
sess.run(const)
Out[43]:
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14],
      dtype=int32)
In [46]:
reshape = tf.reshape(const,(3,5)) 
print(reshape)
sess.run(reshape)
Tensor("Reshape_7:0", shape=(3, 5), dtype=int32)
Out[46]:
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]], dtype=int32)
In [47]:
reshape = tf.reshape(reshape,(-1,)) #dont miss the comma
print(reshape)
sess.run(reshape)
Tensor("Reshape_8:0", shape=(15,), dtype=int32)
Out[47]:
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14],
      dtype=int32)
In [48]:
reshape = tf.reshape(reshape,(5,-1))
print(reshape)
sess.run(reshape)
Tensor("Reshape_9:0", shape=(5, 3), dtype=int32)
Out[48]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]], dtype=int32)

Reshape leaving the batch axis

In [4]:
ones = tf.ones((5,5,5))
print(ones)
reshape = tf.reshape(ones,(-1,25))
print(reshape)
Tensor("ones_1:0", shape=(5, 5, 5), dtype=float32)
Tensor("Reshape:0", shape=(5, 25), dtype=float32)

Tensor operations

In [52]:
max_v = tf.reduce_max(const)
sess.run(max_v)
Out[52]:
14
In [53]:
min_v = tf.reduce_min(const)
sess.run(min_v)
Out[53]:
0
In [54]:
mean_v = tf.reduce_mean(const)
sess.run(mean_v)
Out[54]:
7
In [56]:
#Index location of max value
argmax_v = tf.argmax(const)
sess.run(argmax_v)
Out[56]:
14

Slicing

Everything including syntax works same as numpy

To grab specific columns or rows, use tf.nn.embedding_lookup

In [24]:
mat = tf.reshape(tf.range(0,100,1),(10,10))
sess.run(mat)
Out[24]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
       [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
       [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]], dtype=int32)
In [25]:
sess.run(mat[0,:])#First row
Out[25]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)
In [27]:
sess.run(tf.nn.embedding_lookup(mat,[0,2]))  #First and third row
Out[27]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]], dtype=int32)
In [59]:
sess.run(mat[:,0])#First column
Out[59]:
array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90], dtype=int32)
In [30]:
sess.run(tf.nn.embedding_lookup(tf.transpose(mat),[0,2]))  #First and third column
Out[30]:
array([[ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
       [ 2, 12, 22, 32, 42, 52, 62, 72, 82, 92]], dtype=int32)
In [60]:
sess.run(mat[:2,:3]) #slice first 2 rows and 3 columns
Out[60]:
array([[ 0,  1,  2],
       [10, 11, 12]], dtype=int32)
In [62]:
sess.run(mat[2:4,5:-2]) #slice from 2nd until 4th row, from 5th until last second column
Out[62]:
array([[25, 26, 27],
       [35, 36, 37]], dtype=int32)
In [63]:
sess.run(mat[:5:2,:5:2]) #slice every 2nd element from first 5 rows and column 
Out[63]:
array([[ 0,  2,  4],
       [20, 22, 24],
       [40, 42, 44]], dtype=int32)
In [65]:
sess.run(mat[::2,::2])#slice every 2nd element in whole matrix
Out[65]:
array([[ 0,  2,  4,  6,  8],
       [20, 22, 24, 26, 28],
       [40, 42, 44, 46, 48],
       [60, 62, 64, 66, 68],
       [80, 82, 84, 86, 88]], dtype=int32)
In [66]:
sess.run(mat[2::2,3::2]) #every 2nd element starting from index 2 of row and index 3 of column
Out[66]:
array([[23, 25, 27, 29],
       [43, 45, 47, 49],
       [63, 65, 67, 69],
       [83, 85, 87, 89]], dtype=int32)
In [67]:
sess.run(mat[::-1,::-1]) #reverse the entire matrix
Out[67]:
array([[99, 98, 97, 96, 95, 94, 93, 92, 91, 90],
       [89, 88, 87, 86, 85, 84, 83, 82, 81, 80],
       [79, 78, 77, 76, 75, 74, 73, 72, 71, 70],
       [69, 68, 67, 66, 65, 64, 63, 62, 61, 60],
       [59, 58, 57, 56, 55, 54, 53, 52, 51, 50],
       [49, 48, 47, 46, 45, 44, 43, 42, 41, 40],
       [39, 38, 37, 36, 35, 34, 33, 32, 31, 30],
       [29, 28, 27, 26, 25, 24, 23, 22, 21, 20],
       [19, 18, 17, 16, 15, 14, 13, 12, 11, 10],
       [ 9,  8,  7,  6,  5,  4,  3,  2,  1,  0]], dtype=int32)
In [68]:
sess.run(mat[3::-1,3::-1]) #pick up the first 3 rows and column and reverse them
Out[68]:
array([[33, 32, 31, 30],
       [23, 22, 21, 20],
       [13, 12, 11, 10],
       [ 3,  2,  1,  0]], dtype=int32)

Masking

tf.boolean_mask should be used

In [70]:
my_filter = mat > 50
print(my_filter)
sess.run(my_filter)
Tensor("Greater_1:0", shape=(10, 10), dtype=bool)
Out[70]:
array([[False, False, False, False, False, False, False, False, False,
        False],
       [False, False, False, False, False, False, False, False, False,
        False],
       [False, False, False, False, False, False, False, False, False,
        False],
       [False, False, False, False, False, False, False, False, False,
        False],
       [False, False, False, False, False, False, False, False, False,
        False],
       [False,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True]])
In [75]:
sess.run(tf.boolean_mask(mat,mat>50)) #Equivalent to mat[mat>50] ==> mat[my_filter]
Out[75]:
array([51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
       68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
       85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99],
      dtype=int32)

Apply operations to elements that satisfy certain condition

Reassignment to same tensor does not work in tensorflow

In [73]:
sess.run(tf.where(mat>50,mat*-10,mat)) #prefer tf.less instead of <
#sess.run(tf.where(mat>50,-10,mat)) #Does not work. Both results should confirm to tensor dim. use mat*0-10
Out[73]:
array([[   0,    1,    2,    3,    4,    5,    6,    7,    8,    9],
       [  10,   11,   12,   13,   14,   15,   16,   17,   18,   19],
       [  20,   21,   22,   23,   24,   25,   26,   27,   28,   29],
       [  30,   31,   32,   33,   34,   35,   36,   37,   38,   39],
       [  40,   41,   42,   43,   44,   45,   46,   47,   48,   49],
       [  50, -510, -520, -530, -540, -550, -560, -570, -580, -590],
       [-600, -610, -620, -630, -640, -650, -660, -670, -680, -690],
       [-700, -710, -720, -730, -740, -750, -760, -770, -780, -790],
       [-800, -810, -820, -830, -840, -850, -860, -870, -880, -890],
       [-900, -910, -920, -930, -940, -950, -960, -970, -980, -990]],
      dtype=int32)

Get indices of masked elements

In [106]:
sess.run(tf.where(tf.equal(mat%2,0)))
#sess.run(tf.where(mat%2 == 0)) #does not work
Out[106]:
array([[0, 0],
       [0, 2],
       [0, 4],
       [0, 6],
       [0, 8],
       [1, 0],
       [1, 2],
       [1, 4],
       [1, 6],
       [1, 8],
       [2, 0],
       [2, 2],
       [2, 4],
       [2, 6],
       [2, 8],
       [3, 0],
       [3, 2],
       [3, 4],
       [3, 6],
       [3, 8],
       [4, 0],
       [4, 2],
       [4, 4],
       [4, 6],
       [4, 8],
       [5, 0],
       [5, 2],
       [5, 4],
       [5, 6],
       [5, 8],
       [6, 0],
       [6, 2],
       [6, 4],
       [6, 6],
       [6, 8],
       [7, 0],
       [7, 2],
       [7, 4],
       [7, 6],
       [7, 8],
       [8, 0],
       [8, 2],
       [8, 4],
       [8, 6],
       [8, 8],
       [9, 0],
       [9, 2],
       [9, 4],
       [9, 6],
       [9, 8]])

To get elements corresponding to indices, flatten the tensor and use tf.nn.embedding_lookup

In [117]:
mat_flat = tf.reshape(mat,(-1,))
idx = tf.where(tf.equal(mat_flat%2,0))
elx = tf.nn.embedding_lookup(mat_flat,idx)
sess.run(elx)
Out[117]:
array([[ 0],
       [ 2],
       [ 4],
       [ 6],
       [ 8],
       [10],
       [12],
       [14],
       [16],
       [18],
       [20],
       [22],
       [24],
       [26],
       [28],
       [30],
       [32],
       [34],
       [36],
       [38],
       [40],
       [42],
       [44],
       [46],
       [48],
       [50],
       [52],
       [54],
       [56],
       [58],
       [60],
       [62],
       [64],
       [66],
       [68],
       [70],
       [72],
       [74],
       [76],
       [78],
       [80],
       [82],
       [84],
       [86],
       [88],
       [90],
       [92],
       [94],
       [96],
       [98]], dtype=int32)

Applying operation/function to specific indices

This is done using tf.scatter. See Sampling section for examples

Applying function

This cannot be done in the numpy way as reassignment to tensors is not allowed.

We cant use

mat[idx] = func(mat[idx])

We can manipulate whole column or rows as follows

In [83]:
a = tf.reshape(tf.range(0,15),(5,3))
sess.run(a)
Out[83]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]], dtype=int32)

Normalizing all columns

In [104]:
def normalize(a): #can be any function
    #see broadcasting to understand this computation
    b = (a - tf.reduce_min(a))/(tf.reduce_max(a)-tf.reduce_min(a))
    return b

l = []
for i in range(a.shape[1]):
    b = tf.expand_dims(normalize(a[:,i]),axis=1) #concat requires more than 1D
    l.append(b)
c = tf.concat(l,axis=1)
    
sess.run(c)
Out[104]:
array([[0.  , 0.  , 0.  ],
       [0.25, 0.25, 0.25],
       [0.5 , 0.5 , 0.5 ],
       [0.75, 0.75, 0.75],
       [1.  , 1.  , 1.  ]])

Normalizing all rows

In [105]:
l = []
for i in range(a.shape[0]):
    b = tf.expand_dims(normalize(a[i,:]),axis=0) #concat requires more than 1D
    l.append(b)
c = tf.concat(l,axis=0)
    
sess.run(c)
Out[105]:
array([[0. , 0.5, 1. ],
       [0. , 0.5, 1. ],
       [0. , 0.5, 1. ],
       [0. , 0.5, 1. ],
       [0. , 0.5, 1. ]])

Broadcasting

Works same as numpy

In [76]:
arr = tf.ones((5,4))
sess.run(arr)
Out[76]:
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]], dtype=float32)
In [77]:
sess.run(arr + 1) #(5,4) + (1,)
Out[77]:
array([[2., 2., 2., 2.],
       [2., 2., 2., 2.],
       [2., 2., 2., 2.],
       [2., 2., 2., 2.],
       [2., 2., 2., 2.]], dtype=float32)
In [78]:
sess.run(arr + [1,2,3,4]) #(5,4) + (4,)
Out[78]:
array([[2., 3., 4., 5.],
       [2., 3., 4., 5.],
       [2., 3., 4., 5.],
       [2., 3., 4., 5.],
       [2., 3., 4., 5.]], dtype=float32)
In [82]:
sess.run(arr + tf.reshape(tf.constant([1.,2.,3.,4.,5.]),(5,1)))#(5,4) + (5,1)
Out[82]:
array([[2., 2., 2., 2.],
       [3., 3., 3., 3.],
       [4., 4., 4., 4.],
       [5., 5., 5., 5.],
       [6., 6., 6., 6.]], dtype=float32)

Concatenation

In [86]:
features = tf.random_uniform((10,3),0,101,dtype=tf.int32)
labels = tf.random_uniform((10,1),0,2,dtype=tf.int32)
print(features)
print(labels)
Tensor("random_uniform_10:0", shape=(10, 3), dtype=int32)
Tensor("random_uniform_11:0", shape=(10, 1), dtype=int32)
In [87]:
sess.run(tf.concat([features,labels],axis=1)) #same syntax as numpy
Out[87]:
array([[ 0, 35, 82,  0],
       [65, 26,  5,  0],
       [51, 19, 87,  0],
       [94, 75, 41,  1],
       [ 4, 18, 60,  0],
       [82, 16, 14,  0],
       [97, 51, 67,  0],
       [11, 82, 85,  1],
       [ 4, 30, 76,  0],
       [16, 86, 82,  1]], dtype=int32)

Sampling

In [4]:
x = tf.lin_space(0.,10.,1000)
print(x)
Tensor("LinSpace_1:0", shape=(1000,), dtype=float32)
In [22]:
sample_size = 10
rand_ind = tf.random_uniform((sample_size,),0,x.shape[0],dtype=tf.int32)
sess.run(rand_ind)
Out[22]:
array([315, 240, 544, 521, 391, 751, 741, 146, 206, 216], dtype=int32)
In [20]:
sample_x = tf.nn.embedding_lookup(x,rand_ind)
print(sample_x)
Tensor("embedding_lookup_1/Identity:0", shape=(10,), dtype=float32)
In [23]:
sess.run(sample_x)
Out[23]:
array([3.4934933, 1.6016016, 3.093093 , 8.698698 , 9.469469 , 2.9929929,
       2.7227225, 5.175175 , 5.7457457, 8.788789 ], dtype=float32)

Another example

Add a delta to the sampled points

tf.scatter_add illustration

In [43]:
x = tf.range(50,75,dtype=tf.float32)
sess.run(x)
Out[43]:
array([50., 51., 52., 53., 54., 55., 56., 57., 58., 59., 60., 61., 62.,
       63., 64., 65., 66., 67., 68., 69., 70., 71., 72., 73., 74.],
      dtype=float32)
In [44]:
sample_size = 5
rand_ind = tf.random_uniform((sample_size,),0,x.shape[0],dtype=tf.int32)
sess.run(rand_ind)
Out[44]:
array([ 9,  6,  0,  4, 11], dtype=int32)
In [62]:
#tf.scatter needs a variable
x_var = tf.Variable(x)
#Update should be of size 1 or of size rand_ind
x_delta = tf.scatter_add(x_var,rand_ind,0.33)
#x_delta = tf.scatter_add(x_var,rand_ind,tf.constant([1.3,2.3,3.3,4.3,5.3]))
In [63]:
sess.run(tf.global_variables_initializer())
sess.run(x_delta)
Out[63]:
array([50.  , 51.  , 52.33, 53.  , 54.33, 55.33, 56.  , 57.  , 58.  ,
       59.  , 60.  , 61.  , 62.33, 63.  , 64.  , 65.  , 66.  , 67.  ,
       68.  , 69.  , 70.  , 71.33, 72.  , 73.  , 74.  ], dtype=float32)

Apply arbitary function to the sampled points

tf.scatter_update illustration

In [66]:
#Makes the elements 33% of its original value
def func(X,ind):
    t = tf.nn.embedding_lookup(X,ind)
    t = t*0.33 
    return t
    
x_var = tf.Variable(x)
t = func(x,rand_ind)
x_delta = tf.scatter_update(x_var,rand_ind,func(x,rand_ind))
In [67]:
sess.run(tf.global_variables_initializer())
sess.run([x_delta,rand_ind,t])
Out[67]:
[array([50.      , 51.      , 52.      , 53.      , 54.      , 55.      ,
        56.      , 18.810001, 58.      , 19.470001, 60.      , 61.      ,
        62.      , 63.      , 64.      , 65.      , 66.      , 67.      ,
        68.      , 22.77    , 23.1     , 23.43    , 72.      , 73.      ,
        74.      ], dtype=float32),
 array([ 7, 20,  9, 19, 21], dtype=int32),
 array([18.810001, 23.1     , 19.470001, 22.77    , 23.43    ],
       dtype=float32)]
In [68]:
sess.close()