# 【tensorflow2.0】张量的结构操作

### 一，创建张量

```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]]```
```# 均匀分布随机
tf.random.set_seed(1.0)
a = tf.random.uniform([5],minval=0,maxval=10)
tf.print(a)```
`[1.65130854 9.01481247 6.30974197 4.34546089 2.9193902]`
```# 正态分布随机
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]]```
```# 正态分布随机，剔除2倍方差以外数据重新生成
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]]```
```# 特殊矩阵
I = tf.eye(3,3) #单位矩阵
tf.print(I)
tf.print(" ")
t = tf.linalg.diag([1,2,3]) #对角阵
tf.print(t)```
```[[1 0 0]
[0 1 0]
[0 0 1]]

[[1 0 0]
[0 2 0]
[0 0 3]]```

### 二，索引切片

```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]`
```# 倒数第一行
tf.print(t[-1])```
`[3 7 0 0 3]`
```# 第1行第3列
tf.print(t[1,3])
tf.print(t[1][3])```
```4
4```
```# 第1行至第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]]```
```# 第1行至最后一行，第0列到最后一列每隔两列取一列
tf.print(t[1:4,:4:2])```
```[[9 2]
[7 7]
[9 9]]```
```# 对变量来说，还可以使用索引和切片修改部分元素
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]]]```
```# 省略号可以表示多个冒号
tf.print(a[...,1])```
```[[3 0 6]
[3 8 1]
[0 2 9]]```

```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]]]```
```# 抽取每个班级第0个学生，第5个学生，第9个学生的全部成绩
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]]]```
```# 抽取每个班级第0个学生，第5个学生，第9个学生的第1门课程，第3门课程，第6门课程成绩
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]]]```
```# 抽取第0个班级第0个学生，第2个班级的第4个学生，第3个班级的第6个学生的全部成绩
# indices的长度为采样样本的个数，每个元素为采样位置的坐标
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)>```

```# 抽取每个班级第0个学生，第5个学生，第9个学生的全部成绩
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]]]```
```# 抽取第0个班级第0个学生，第2个班级的第4个学生，第3个班级的第6个学生的全部成绩
[[True,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]]```
```# 利用tf.boolean_mask可以实现布尔索引

# 找到矩阵中小于0的元素
c = tf.constant([[-1,1,-1],[2,2,-2],[3,-3,3]],dtype=tf.float32)
tf.print(c,"\n")

```[[-1 1 -1]
[2 2 -2]
[3 -3 3]]

[-1 -1 -2 -3]

[-1 -1 -2 -3]```

tf.where可以理解为if的张量版本，此外它还可以用于找到满足条件的所有元素的位置坐标。

tf.scatter_nd的作用和tf.gather_nd有些相反，tf.gather_nd用于收集张量的给定位置的元素，

```# 找到张量中小于0的元素,将其换成np.nan得到新的张量
# tf.where和np.where作用类似，可以理解为if的张量版本

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)>```
```# 如果where只有一个参数，将返回所有满足条件的位置坐标
indices = tf.where(c<0)
indices```
```<tf.Tensor: shape=(4, 2), dtype=int64, numpy=
array([[0, 0],
[0, 2],
[1, 2],
[2, 1]])>```
```# 将张量的第[0,0]和[2,1]两个位置元素替换为0得到新的张量
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)>```
```# scatter_nd的作用和gather_nd有些相反
# 可以将某些值插入到一个给定shape的全0的张量的指定位置处。
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)>```

### 三，维度变换

tf.reshape 可以改变张量的形状。

tf.squeeze 可以减少维度。

tf.expand_dims 可以增加维度。

tf.transpose 可以交换维度。

tf.reshape可以改变张量的形状，但是其本质上不会改变张量元素的存储顺序，所以，该操作实际上非常迅速，并且是可逆的。

```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]]]]```
```# 改成 （3,6）形状的张量
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]]```
```# 改回成 [1,3,3,2] 形状的张量
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]]]]```

```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]]]```
`d = tf.expand_dims(s,axis=0) #在第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可以交换张量的维度，与tf.reshape不同，它会改变张量元素的存储顺序。

tf.transpose常用于图片存储格式的变换上。

```# 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])```

### 四，合并分割

tf.concat和tf.stack有略微的区别，tf.concat是连接，不会增加维度，而tf.stack是堆叠，会增加维度。

```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是tf.concat的逆运算，可以指定分割份数平均分割，也可以通过指定每份的记录数量进行分割。

```# tf.split(value,num_or_size_splits,axis)
tf.split(c,3,axis = 0)  #指定分割份数，平均分割```
```[<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) #指定每份的记录数量`
```[<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)>]```

GitHub 项目地址：https://github.com/lyhue1991/eat_tensorflow2_in_30_days

0 条评论

• ### 【tensorflow2.0】中阶api--模型、损失函数、优化器、数据管道、特征列等

TensorFlow的中阶API主要包括各种模型层，损失函数，优化器，数据管道，特征列等等。

• ### 【tensorflow2.0】自动微分机制

神经网络通常依赖反向传播求梯度来更新网络参数，求梯度过程通常是一件非常复杂而容易出错的事情。

• ### 【tensorflow2.0】AutoGraph的使用规范

而Autograph机制可以将动态图转换成静态计算图，兼收执行效率和编码效率之利。

• ### TensorFlow2.X学习笔记(1)--TensorFlow核心概念

TensorFlow™ 是一个采用 数据流图（data flow graphs），用于数值计算的开源软件库。节点（Nodes）在图中表示数学操作，图中的线（e...

• ### TensorFlow2.X学习笔记(3)--TensorFlow低阶API之张量

TensorFlow提供的方法比numpy更全面，运算速度更快，如果需要的话，还可以使用GPU进行加速。

• ### TensorFlow2.X学习笔记(4)--TensorFlow低阶API之AutoGraph相关研究

而Autograph机制可以将动态图转换成静态计算图，兼收执行效率和编码效率之利。

• ### win10 tensorflow笔记2 MNIST机器学习入门

这里跟官方有两处不同 1：第1行代码原文是import input_data这里的input_data是无法直接导入的。需要给出具体路径from tensor...

• ### 【tensorflow2.0】中阶api--模型、损失函数、优化器、数据管道、特征列等

TensorFlow的中阶API主要包括各种模型层，损失函数，优化器，数据管道，特征列等等。