[Tensorflow2.0] Tensor structure operation

Tensor operations mainly include tensor structure operations and tensor mathematical operations.

Tensor structure operations such as: tensor creation, index slicing, dimension transformation, merge and segmentation.

Tensor mathematical operations mainly include: scalar operations, vector operations, and matrix operations. In addition, we will introduce the broadcast mechanism of tensor computing.

In this article we introduce the structure operation of tensors.

One, create a tensor

Many methods for creating tensors are very similar to the methods for creating arrays in numpy.

import tensorflow as tf
import numpy as np 
a = tf.constant([1,2,3],dtype = tf.float32)
tf.print(a)
[1 2 3]
b = tf.range(1,10,delta = 2)
tf.print(b)
[1 3 5 7 9]
c = tf.linspace(0.0,2*3.14,100)
tf.print(c)
[0 0.0634343475 0.126868695 ... 6.15313148 6.21656609 6.28]
d = tf.zeros([3,3])
tf.print(d)
[[0 0 0]
 [0 0 0]
 [0 0 0]]
a = tf.ones([3,3])
b = tf.zeros_like(a,dtype= tf.float32)
tf.print(a)
tf.print(b)
[[1 1 1]
 [1 1 1]
 [1 1 1]]
[[0 0 0]
 [0 0 0]
 [0 0 0]]
b = tf.fill([3,2],5)
tf.print(b)
[[5 5]
 [5 5]
 [5 5]]
# Uniformly distributed random 
tf.random.set_seed (1.0 ) 
A = tf.random.uniform ([. 5], MINVAL = 0, 10 = MAXVAL ) 
TF. Print (A)
[1.65130854 9.01481247 6.30974197 4.34546089 2.9193902]
# Normal random 
B = tf.random.normal ([3,3], Mean = 0.0, STDDEV = 1.0 ) 
TF. Print (B)
[[0.403087884 -1.0880208 -0.0630953535]
 [1.33655667 0.711760104 -0.489286453]
 [-0.764221311 -1.03724861 -1.25193381]]
# Normal random, removing data other than 2-fold variance regenerate 
C = tf.random.truncated_normal ((5, 5), Mean = 0.0, STDDEV = 1.0, DTYPE = tf.float32) 
TF. Print (C)
[[-0.457012236 -0.406867266 0.728577733 -0.892977774 -0.369404584]
 [0.323488563 1.19383323 0.888299048 1.25985599 -1.95951891]
 [-0.202244401 0.294496894 -0.468728036 1.29494202 1.48142183]
 [0.0810953453 1.63843894 0.556645 0.977199793 -1.17777884]
 [1.67368948 0.0647980496 -0.705142677 -0.281972528 0.126546144]]
# Special matrix 
the I tf.eye = (3,3) # matrix 
tf. Print (the I) 
tf. Print ( "  " ) 
T = tf.linalg.diag ([l, 2,3]) # diagonal matrix 
tf . print (t)
[[1 0 0]
 [0 1 0]
 [0 0 1]]
 
[[1 0 0]
 [0 2 0]
 [0 0 3]]

Second, the index slice

Tensor index slicing is almost the same as numpy. Support default parameters and ellipses when slicing.

For tf.Variable, some elements can be modified by indexing and slicing.

For continuous sub-regions of tensor extraction, tf.slice can also be used.

In addition, for irregular slice extraction, tf.gather, tf.gather_nd, tf.boolean_mask can be used.

tf.boolean_mask is the most powerful, it can realize the functions of tf.gather, tf.gather_nd, and tf.boolean_mask can also realize Boolean index.

If you want to get a new tensor by modifying some elements of the tensor, you can use tf.where, tf.scatter_nd.

tf.random.set_seed(3)
t = tf.random.uniform([5,5],minval=0,maxval=10,dtype=tf.int32)
tf.print(t)
[[4 7 4 2 9]
 [9 1 2 4 7]
 [7 2 7 4 0]
 [9 6 9 7 2]
 [3 7 0 0 3]]
# 第 0 行 
tf. Print (t [0])
[4 7 4 2 9]
# Reciprocal of the first line 
TF. Print (T [-1])
[3 7 0 0 3]
# 第 1 行 第 3 列 
tf. Print (t [1,3 ]) 
tf. Print (t [1] [3])
4
4
# Line 1 to line 3 
TF. Print (T [1:. 4 ,:]) 
. TF Print (tf.slice (T, [1,0], [3,5])) # tf.slice (INPUT , begin_vector, size_vector)
[[9 1 2 4 7]
 [7 2 7 4 0]
 [9 6 9 7 2]]
[[9 1 2 4 7]
 [7 2 7 4 0]
 [9 6 9 7 2]]
#Line 1 to the last line, column 0 to the last column Take a column every two columns 
tf. Print (t [1: 4 ,: 4: 2])
[[9 2]
 [7 7]
 [9 9]]
# Variables, the index can also be used to modify some elements and slice 
X = tf.Variable ([[1,2], [3,4-]], DTYPE = tf.float32) 
X [ . 1,:] ASSIGN (. tf.constant ([0.0,0.0 ])) 
tf. print (x)
[[1 2]
 [0 0]]
a = tf.random.uniform([3,3,3],minval=0,maxval=10,dtype=tf.int32)
tf.print(a)
[[[7 3 9]
  [9 0 7]
  [9 6 7]]
 
 [[1 3 3]
  [0 8 1]
  [3 1 0]]
 
 [[4 0 6]
  [6 2 2]
  [7 9 5]]]
# Ellipses may represent multiple colon 
TF. Print (A [...,. 1])
[[3 0 6]
 [3 8 1]
 [0 2 9]]

The above slicing methods are relatively regular. For irregular slice extraction, you can use tf.gather, tf.gather_nd, tf.boolean_mask.

Consider the class gradebook example, there are 4 classes, 10 students in each class, and 7 subjects in each class. It can be represented by a 4  10  7 tensor.

scores = tf.random.uniform((4,10,7),minval=0,maxval=100,dtype=tf.int32)
tf.print(scores)
[[[52 82 66 ... 17 86 14]
  [8 36 94 ... 13 78 41]
  [77 53 51 ... 22 91 56]
  ...
  [11 19 26 ... 89 86 68]
  [60 72 0 ... 11 26 15]
  [24 99 38 ... 97 44 74]]
 
 [[79 73 73 ... 35 3 81]
  [83 36 31 ... 75 38 85]
  [54 26 67 ... 60 68 98]
  ...
  [20 5 18 ... 32 45 3]
  [72 52 81 ... 88 41 20]
  [0 21 89 ... 53 10 90]]
 
 [[52 80 22 ... 29 25 60]
  [78 71 54 ... 43 98 81]
  [21 66 53 ... 97 75 77]
  ...
  [6 74 3 ... 53 65 43]
  [98 36 72 ... 33 36 81]
  [61 78 70 ... 7 59 21]]
 
 [[56 57 45 ... 23 15 3]
  [35 8 82 ... 11 59 97]
  [44 6 99 ... 81 60 27]
  ...
  [76 26 35 ... 51 8 17]
  [33 52 53 ... 78 37 31]
  [71 27 44 ... 0 52 16]]]
# Extracting each class 0 students, student fifth, ninth grade students all 
P = tf.gather (Scores, [0,5,9], Axis =. 1 ) 
TF. Print (P)
[[[52 82 66 ... 17 86 14]
  [24 80 70 ... 72 63 96]
  [24 99 38 ... 97 44 74]]
 
 [[79 73 73 ... 35 3 81]
  [46 10 94 ... 23 18 92]
  [0 21 89 ... 53 10 90]]
 
 [[52 80 22 ... 29 25 60]
  [19 12 23 ... 87 86 25]
  [61 78 70 ... 7 59 21]]
 
 [[56 57 45 ... 23 15 3]
  [6 41 79 ... 97 43 13]
  [71 27 44 ... 0 52 16]]]
# Extract the 0th student, 5th student, 9th student's 1st course, 3rd course, 6th course score 
q = tf.gather (tf.gather (scores, [0, 5,9], axis = 1), [1,3,6], axis = 2 ) 
tf. Print (q)
[[[82 55 14]
  [80 46 96]
  [99 58 74]]
 
 [[73 48 81]
  [10 38 92]
  [21 86 90]]
 
 [[80 57 60]
  [12 34 25]
  [78 71 21]]
 
 [[57 75 3]
  [41 47 13]
  [27 96 16]]]
# Extraction of classes 0 0 students, all four students achievement of the second class, students of the sixth three classes 
# length of the sample indices for the number of samples of each element for the sampling position The coordinates of 
s = tf.gather_nd (scores, indices = [(0,0), (2,4), (3,6)])
<tf.Tensor: shape=(3, 7), dtype=int32, numpy=
array([[52, 82, 66, 55, 17, 86, 14],
       [99, 94, 46, 70,  1, 63, 41],
       [46, 83, 70, 80, 90, 85, 17]], dtype=int32)>

The above functions of tf.gather and tf.gather_nd can also be implemented with tf.boolean_mask.

# Extract each class of student 0, 5 students, the 9th student achievement of all 
the p-= tf.boolean_mask (Scores, [True, False, False, False, False, 
                            True, False, False, False, True ], axis = 1 ) 
tf. print (p)
[[[52 82 66 ... 17 86 14]
  [24 80 70 ... 72 63 96]
  [24 99 38 ... 97 44 74]]
 
 [[79 73 73 ... 35 3 81]
  [46 10 94 ... 23 18 92]
  [0 21 89 ... 53 10 90]]
 
 [[52 80 22 ... 29 25 60]
  [19 12 23 ... 87 86 25]
  [61 78 70 ... 7 59 21]]
 
 [[56 57 45 ... 23 15 3]
  [6 41 79 ... 97 43 13]
  [71 27 44 ... 0 52 16]]]
# Extraction of classes 0 0 students, the second four classes of students, student sixth of all three classes of scores 
S = tf.boolean_mask (Scores, 
    [[True, 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, False, False , False, False, False], 
     [False, False, False, False, False, False, True, False, False, False]]) 
tf. Print (s)
[[52 82 66 ... 17 86 14]
 [99 94 46 ... 1 63 41]
 [46 83 70 ... 90 85 17]]
# Using boolean index may be implemented tf.boolean_mask 
 
# find elements in the matrix is less than 0 
c = tf.constant ([[- 1,1 , -1], [2,2, -2], [3, -3,3 ]], dtype = tf.float32) 
tf. print (c, " \ n " ) 
 
tf. print (tf.boolean_mask (c, c <0), " \ n " ) 
tf. print (c [c <0] ) # Boolean index for syntactic sugar in the form of boolean_mask
[[-1 1 -1]
 [2 2 -2]
 [3 -3 3]] 
 
[-1 -1 -2 -3] 
 
[-1 -1 -2 -3]

The above methods can only extract some element values ​​of tensors, but cannot change some element values ​​of tensors to get new tensors.

If you want to get a new tensor by modifying some element values ​​of the tensor, you can use tf.where and tf.scatter_nd.

tf.where can be understood as a tensor version of if, in addition it can also be used to find the position coordinates of all elements that satisfy the condition.

The effect of tf.scatter_nd is somewhat opposite to tf.gather_nd, tf.gather_nd is used to collect elements of a given position of a tensor,

And tf.scatter_nd can insert certain values ​​into the specified position of a tensor of all 0s of a given shape.

# Find tensor element is less than 0, it is replaced by new tensor obtained np.nan 
# similar tf.where np.where action and, as will be appreciated if the tensor version 
 
C = tf.constant ([[- 1,1, -1], [2,2, -2], [3, -3,3 ]], dtype = tf.float32) 
d = tf.where (c <0, tf.fill (c.shape , np.nan), c)
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[nan,  1., nan],
       [ 2.,  2., nan],
       [ 3., nan,  3.]], dtype=float32)>
# If where only one parameter, returns all satisfy the conditions of the position coordinates of 
indices tf.where = (C < 0) 
indices
<tf.Tensor: shape=(4, 2), dtype=int64, numpy=
array([[0, 0],
       [0, 2],
       [1, 2],
       [2, 1]])>
# The tensor first [0,0] and [2,1] position of the element with the two new 0 to obtain the tensor 
d = c - tf.scatter_nd ([[ 0,0], [2,1]] , [c [0,0], c [2,1 ]], c.shape)
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[ 0.,  1., -1.],
       [ 2.,  2., -2.],
       [ 3.,  0.,  3.]], dtype=float32)>
# The role of scatter_nd is somewhat opposite to gather_nd 
# You can insert certain values ​​at a specified position in a tensor of all 0s of a given shape. 
indices = tf.where (c < 0) 
tf.scatter_nd (indices, tf.gather_nd (c, indices), c.shape)
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[-1.,  0., -1.],
       [ 0.,  0., -2.],
       [ 0., -3.,  0.]], dtype=float32)>

Three, dimensional transformation

Dimension transformation related functions mainly include tf.reshape, tf.squeeze, tf.expand_dims, tf.transpose.

tf.reshape can change the shape of a tensor.

tf.squeeze can reduce the dimension.

tf.expand_dims can increase the dimension.

tf.transpose can exchange dimensions.

tf.reshape can change the shape of a tensor, but it does not essentially change the storage order of tensor elements, so this operation is actually very fast and reversible.

a = tf.random.uniform(shape=[1,3,3,2],
                      minval=0,maxval=255,dtype=tf.int32)
tf.print(a.shape)
tf.print(a)
TensorShape([1, 3, 3, 2])
[[[[135 178]
   [26 116]
   [29 224]]
 
  [[179 219]
   [153 209]
   [111 215]]
 
  [[39 7]
   [138 129]
   [59 205]]]]
# Changed to (3,6) shape tensor 
B = tf.reshape (A, [3,6 ]) 
TF. Print (b.shape) 
TF. Print (B)
TensorShape([3, 6])
[[135 178 26 116 29 224]
 [179 219 153 209 111 215]
 [39 7 138 129 59 205]]
# Change back into [1,3,3,2] shape tensor 
C = tf.reshape (B, [1,3,3,2 ]) 
TF. Print (C)
[[[[135 178]
   [26 116]
   [29 224]]
 
  [[179 219]
   [153 209]
   [111 215]]
 
  [[39 7]
   [138 129]
   [59 205]]]]

If a tensor has only one element in a certain dimension, tf.squeeze can eliminate this dimension.

Similar to tf.reshape, it does not essentially change the storage order of tensor elements.

Each element of a tensor is stored linearly in memory. The general rule is that the physical addresses of adjacent elements in the same level are also adjacent.

s = tf.squeeze(a)
tf.print(s.shape)
tf.print(s)
TensorShape([3, 3, 2])
[[[135 178]
  [26 116]
  [29 224]]
 
 [[179 219]
  [153 209]
  [111 215]]
 
 [[39 7]
  [138 129]
  [59 205]]]
tf.expand_dims = D (S, Axis = 0) # a dimension of the insertion length of dimension 0 1
<tf.Tensor: shape=(1, 3, 3, 2), dtype=int32, numpy=
array([[[[135, 178],
         [ 26, 116],
         [ 29, 224]],
 
        [[179, 219],
         [153, 209],
         [111, 215]],
 
        [[ 39,   7],
         [138, 129],
         [ 59, 205]]]], dtype=int32)>

tf.transpose can exchange the dimensions of a tensor. Unlike tf.reshape, it changes the storage order of tensor elements.

tf.transpose is often used to transform image storage formats.

# Batch,Height,Width,Channel
a = tf.random.uniform(shape=[100,600,600,4],minval=0,maxval=255,dtype=tf.int32)
tf.print(a.shape)
 
# 转换成 Channel,Height,Width,Batch
s= tf.transpose(a,perm=[3,1,2,0])
tf.print(s.shape)
TensorShape([100, 600, 600, 4])
TensorShape([4, 600, 600, 100])

Four, merge and split

Similar to numpy, you can use the tf.concat and tf.stack methods to merge multiple tensors. You can use the tf.split method to split a tensor into multiple tensors.

There is a slight difference between tf.concat and tf.stack. tf.concat is a connection and will not increase the dimension, while tf.stack is a stack and will increase the dimension.

a = tf.constant([[1.0,2.0],[3.0,4.0]])
b = tf.constant([[5.0,6.0],[7.0,8.0]])
c = tf.constant([[9.0,10.0],[11.0,12.0]])
 
tf.concat([a,b,c],axis = 0)
<tf.Tensor: shape=(6, 2), dtype=float32, numpy=
array([[ 1.,  2.],
       [ 3.,  4.],
       [ 5.,  6.],
       [ 7.,  8.],
       [ 9., 10.],
       [11., 12.]], dtype=float32)>
tf.concat([a,b,c],axis = 1)
<tf.Tensor: shape=(2, 6), dtype=float32, numpy=
array([[ 1.,  2.,  5.,  6.,  9., 10.],
       [ 3.,  4.,  7.,  8., 11., 12.]], dtype=float32)>
tf.stack([a,b,c])
<tf.Tensor: shape=(3, 2, 2), dtype=float32, numpy=
array([[[ 1.,  2.],
        [ 3.,  4.]],
 
       [[ 5.,  6.],
        [ 7.,  8.]],
 
       [[ 9., 10.],
        [11., 12.]]], dtype=float32)>
tf.stack([a,b,c],axis=1)
<tf.Tensor: shape=(2, 3, 2), dtype=float32, numpy=
array([[[ 1.,  2.],
        [ 5.,  6.],
        [ 9., 10.]],
 
       [[ 3.,  4.],
        [ 7.,  8.],
        [11., 12.]]], dtype=float32)>
a = tf.constant([[1.0,2.0],[3.0,4.0]])
b = tf.constant([[5.0,6.0],[7.0,8.0]])
c = tf.constant([[9.0,10.0],[11.0,12.0]])
 
c = tf.concat([a,b,c],axis = 0)

tf.split is the inverse operation of tf.concat, you can specify the average number of splits, or you can split by specifying the number of records per copy.

# Tf.split (value, num_or_size_splits, Axis) 
tf.split (C,. 3, Axis = 0)   # specify the split parts, divided equally
[<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
 array([[1., 2.],
        [3., 4.]], dtype=float32)>,
 <tf.Tensor: shape=(2, 2), dtype=float32, numpy=
 array([[5., 6.],
        [7., 8.]], dtype=float32)>,
 <tf.Tensor: shape=(2, 2), dtype=float32, numpy=
 array([[ 9., 10.],
        [11., 12.]], dtype=float32)>]
tf.split (C, [2.2.2], Axis = 0) # specified number of records per
[<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
 array([[1., 2.],
        [3., 4.]], dtype=float32)>,
 <tf.Tensor: shape=(2, 2), dtype=float32, numpy=
 array([[5., 6.],
        [7., 8.]], dtype=float32)>,
 <tf.Tensor: shape=(2, 2), dtype=float32, numpy=
 array([[ 9., 10.],
        [11., 12.]], dtype=float32)>]

reference:

Open source e-book address: https://lyhue1991.github.io/eat_tensorflow2_in_30_days/

GitHub project address: https://github.com/lyhue1991/eat_tensorflow2_in_30_days

Guess you like

Origin www.cnblogs.com/xiximayou/p/12673953.html