《动手学习深度学习》- Tensorflow数据操作

《动手学习深度学习》- Tensorflow数据操作

Scroll Down
import tensorflow as tf
tf.__version__
'2.3.0'

1. 创建 tensor

  • tensor 是存储和变换数据的主要工具, tensor 和 Numpy 的多维数组比较类似, 但是 tensor 可以提供 GPU 计算和自动求梯度等功能
# 创建行向量

x = tf.constant(range(12))
x
<tf.Tensor: shape=(12,), dtype=int32, numpy=array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])>
print(x.shape)
print(len(x)) # 获取向量中元素的个数
(12,)
12
# 使用reshape函数把行向量x的形状改为(3, 4)
x = tf.reshape(x,(3,4))
x
<tf.Tensor: shape=(3, 4), dtype=int32, numpy=
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])>
  • 注意X属性中的形状发生了变化。上面x.reshape((3, 4))也可写成x.reshape((-1, 4))或x.reshape((3, -1))。由于x的元素个数是已知的,这里的-1是能够通过元素个数和其他维度的大小推断出来的。

2. 创建指定形状的张量

tf.zeros((2,3,4))
<tf.Tensor: shape=(2, 3, 4), dtype=float32, numpy=
array([[[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]],

       [[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]]], dtype=float32)>
tf.ones((3,4))
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]], dtype=float32)>
  • 通过 Python 列表指定 tensor 中每个元素的值
y = tf.constant([[1,2,3,4],[4,5,6,7],[7,8,9,10]])
y
<tf.Tensor: shape=(3, 4), dtype=int32, numpy=
array([[ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10]])>
  • 随机生成tensor中每个元素的值。下面我们创建一个形状为(3, 4)的tensor。它的每个元素都随机采样于均值为0、标准差为1的正态分布。

  • tf.random.normal(shape=(3,4), mean=0, stddev=1)

    1. mean 均值
    2. 正态分布的标准差
tf.random.normal(shape=(3,4), mean=0, stddev=1)
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[ 0.2814369 ,  1.1456217 ,  1.1553345 ,  0.91973084],
       [-0.24770287, -0.8750045 , -0.04902882, -0.02854874],
       [ 1.4356786 ,  2.6822388 , -0.58117944,  1.7481779 ]],
      dtype=float32)>

3. Tensor 运算

print("x => ", x.shape)
print("y => ", x.shape)

print(x)
print(y)
x =>  (3, 4)
y =>  (3, 4)
tf.Tensor(
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]], shape=(3, 4), dtype=int32)
tf.Tensor(
[[ 1  2  3  4]
 [ 4  5  6  7]
 [ 7  8  9 10]], shape=(3, 4), dtype=int32)

3.1 按元素加法:

  • 按对应元素相加
  • x,y 都是 (3,4),做按元素加法, 结果形状不变
res01 = x + y 
res01
<tf.Tensor: shape=(3, 4), dtype=int32, numpy=
array([[ 1,  3,  5,  7],
       [ 8, 10, 12, 14],
       [15, 17, 19, 21]])>

3.2 按元素乘法:

  • 对应元素相乘, 注意不是矩阵的点乘
res02 = x * y
res02
<tf.Tensor: shape=(3, 4), dtype=int32, numpy=
array([[  0,   2,   6,  12],
       [ 16,  25,  36,  49],
       [ 56,  72,  90, 110]])>

3.3 按元素除法:

res03 = x / y
res03
<tf.Tensor: shape=(3, 4), dtype=float64, numpy=
array([[0.        , 0.5       , 0.66666667, 0.75      ],
       [1.        , 1.        , 1.        , 1.        ],
       [1.14285714, 1.125     , 1.11111111, 1.1       ]])>

3.4 按元素做指数运算:

  • 类型转换 tf.cast(y, tf.float32)
  • 指数运算 tf.exp(Y)
    1. 类型为bfloat16,half,float32,float64,complex64或complex128的张量。
    2. exp(y) = e^y
y = tf.cast(y, tf.float32) # 将y的类型转换为 float32
tf.exp(y) # 指数运算
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[2.7182817e+00, 7.3890562e+00, 2.0085537e+01, 5.4598148e+01],
       [5.4598148e+01, 1.4841316e+02, 4.0342880e+02, 1.0966332e+03],
       [1.0966332e+03, 2.9809580e+03, 8.1030840e+03, 2.2026467e+04]],
      dtype=float32)>

3.5 矩阵乘法

  • 矩阵乘法要求两边行列对应: (3,4) <==> (4,3)
  • 两边数据类型对应 int32 <==> int32
  • tf.matmul(x,y)
    1. 矩阵乘法
  • tf.transpose(y)
    1. 作用 : 转置
    2. (3,4) => (4,3)
y = tf.cast(y,tf.int32)
tf.matmul(x, tf.transpose(y))
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
array([[ 20,  38,  56],
       [ 60, 126, 192],
       [100, 214, 328]])>

3.6 矩阵拼接

  • tf.concat([x,y],axis = 0)
    1. axis 表示维度 : 0 表示行, 1 表示列
  • 分别在行上(维度0,即形状中的最左边元素)和列上(维度1,即形状中左起第二个元素)连结两个矩阵
  • 在行上拼接两个矩阵,相当于将矩阵上下叠加 => shape = (6,4)
  • 在列上拼接两个矩阵,相当于将矩阵左右叠加 => shape = (3,8)
print(x)
print(y)
tf.Tensor(
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]], shape=(3, 4), dtype=int32)
tf.Tensor(
[[ 1  2  3  4]
 [ 4  5  6  7]
 [ 7  8  9 10]], shape=(3, 4), dtype=int32)
tf.concat([x,y],axis = 0)
<tf.Tensor: shape=(6, 4), dtype=int32, numpy=
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10]])>
tf.concat([x,y],axis = 1)
<tf.Tensor: shape=(3, 8), dtype=int32, numpy=
array([[ 0,  1,  2,  3,  1,  2,  3,  4],
       [ 4,  5,  6,  7,  4,  5,  6,  7],
       [ 8,  9, 10, 11,  7,  8,  9, 10]])>

3.7 矩阵比较

  • 对应位置的元素进行比较
tf.equal(x,y)
<tf.Tensor: shape=(3, 4), dtype=bool, numpy=
array([[False, False, False, False],
       [ True,  True,  True,  True],
       [False, False, False, False]])>

3.8 元素求和

  • tf.reduce_sum(x) 对x中所有元素求和
  • tf.norm(x) 计算x向量的范数
tf.reduce_sum(x) # numpy=66 结果
<tf.Tensor: shape=(), dtype=int32, numpy=66>
x = tf.cast(x, tf.float32)
tf.norm(x)
<tf.Tensor: shape=(), dtype=float32, numpy=22.494444>

4. 广播机制

  • 当对两个形状不同的tensor按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个tensor形状相同后再按元素运算
  • A: (3,1) B: (1,2)
  • 由于A和B分别是3行1列和1行2列的矩阵,如果要计算A + B,那么A中第一列的3个元素被广播(复制)到了第二列,而B中第一行的2个元素被广播(复制)到了第二行和第三行。如此,就可以对2个3行2列的矩阵按元素相加。
A = tf.reshape(tf.constant(range(3)), (3,1))
B = tf.reshape(tf.constant(range(2)), (1,2))

A,B
(<tf.Tensor: shape=(3, 1), dtype=int32, numpy=
 array([[0],
        [1],
        [2]])>,
 <tf.Tensor: shape=(1, 2), dtype=int32, numpy=array([[0, 1]])>)
# 触发广播机制, A 中元素把第一列复制到第二列 => (3,2)
# B 中元素把第一行复制到第二行和第三行 => (3,2)
A + B 
<tf.Tensor: shape=(3, 2), dtype=int32, numpy=
array([[0, 1],
       [1, 2],
       [2, 3]])>

5. 索引

  • 在tensor中,索引(index)代表了元素的位置。tensor的索引从0开始逐一递增。例如,一个3行2列的矩阵的行索引分别为0、1和2,列索引分别为0和1。

5.1 获取指定范围的索引

  • x[0:3] # 取索引为 0, 1, 2的三行
x[0:3] # 取索引为 0, 1, 2的三行
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[ 0.,  1.,  2.,  3.],
       [ 4.,  5.,  6.,  7.],
       [ 8.,  9., 10., 11.]], dtype=float32)>

5.2 为指定元素赋值

  • tf.Variable 在修改Tensor值时, 必须转换成 Variable
    1. 变量通过 tf.Variable 类进行创建和跟踪。tf.Variable 表示张量,对它执行运算可以改变其值
    2. X[1,2].assign(9) : 为索引为 1,2 的元素赋值
x = tf.Variable(x)
x
<tf.Variable 'Variable:0' shape=(3, 4) dtype=float32, numpy=
array([[ 0.,  1.,  2.,  3.],
       [ 4.,  5.,  6.,  7.],
       [ 8.,  9., 10., 11.]], dtype=float32)>
x[1,2].assign(9)
<tf.Variable 'UnreadVariable' shape=(3, 4) dtype=float32, numpy=
array([[ 0.,  1.,  2.,  3.],
       [ 4.,  5.,  9.,  7.],
       [ 8.,  9., 10., 11.]], dtype=float32)>

5.3 为指定列赋值

x = tf.Variable(x)
x[1:2,:].assign(tf.ones(x[1:2,:].shape, dtype=tf.float32) * 3)
<tf.Variable 'UnreadVariable' shape=(3, 4) dtype=float32, numpy=
array([[ 0.,  1.,  2.,  3.],
       [ 3.,  3.,  3.,  3.],
       [ 8.,  9., 10., 11.]], dtype=float32)>

6. tensor 和 numpy 的相互转换

  • 通过array函数和asnumpy函数令数据在NDArray和NumPy格式之间相互变换。下面将NumPy实例变换成tensor实例
  • numpy => tensor : tf.constant(P)
  • tensor => numpy : np.array(T)
import numpy as np
P = np.ones((3,4))
T = tf.constant(P)
T
<tf.Tensor: shape=(3, 4), dtype=float64, numpy=
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])>
np.array(T)
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])