Tensorflow中的数据操作

数据操作

在深度学习中,通常会频繁地对数据进行操作。而在Tensorflow中,tensor是一个类,也是存储和变换数据的主要工具。此外tensor还提供GPU计算和自动求梯度等功能,这使得tensor更加适合深度学习。

1.创建tensor

x = tf.constant(range(12))
print(x.shape)
x

上述代码使用range函数创建了一个行向量,返回结果为一个tensor实例,其中包含了从0开始的12个连续整数。输出结果为:

(12,)
<tf.Tensor: id=0, shape=(12,), dtype=int32, numpy=array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])>

提示:range函数用来创建一个整数数列。
tf.constant(value, dtype=None, shape=None, name='Const', verify_shape=False)函数用来创建一个常量,其中value不可少,可以是一个数值,也可以是一个数列。

使用shape属性获取tensor实例的形状:

x.shape

输出结果:

TensorShape([12])

使用len函数得到tensor实例中元素的总数:

len(x)

输出结果:

12

使用reshape函数将行向量x的形状改为(3,4),即一个3行4列的矩阵,并记做X除了形状改变意外,X中的元素保持不变。

X = tf.reshape(x, (3,4))
X

输出结果:

<tf.Tensor: id=2, shape=(3,4), dtype=int32, numpy=array([[0, 1, 2, 3], 
													
														[4, 5, 6, 7], 													
														
														[8, 9, 10, 11]])

可以注意到X属性中的形状发生了变化。
其中tf.reshape(x, (3,4))也可以写成tf.reshape(x, (-1, 4))tf.reshape(x, (3, -1))。这里x的元素个数是已知的,-1是能够通过其它元素个数和其它维度的大小推断出来的。

创建一个各元素为0,形状为(2, 3, 4)的张量。向量与矩阵都是特殊的张量。

tf.zeros((2,3,4))

类似地,我们可以创建各元素为1的张量。

tf.ones((3,4))

也可以使用python的列表(list)指定需要创建的tensor中每个元素的值。

Y = tf.constant([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])

有些情况下,我们需要随机生成tensor中每个元素的值。下面创建一个形状为(3,4)的tensor。它的每个元素都随机采样于均值为0,标准差为1的正态分布。

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

提示:tf.random.normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None) ,其中shape为输出张量的形状,必选。

2.运算

tensor支持大量的运算符。
+:对应(位置)元素相加
*:对应(位置)元素相乘
/:对应(位置)元素相除
指数运算:

Y = tf.cast(Y, tf.float32)
tf.exp(Y)

tf.cast(x, dtype, name = None)。该函数的作用是执行tensorflow中张量数据类型转换,比如读入的图片如果是int8类型的,一般要在训练前把图像的数据格式转换为float32.
tf.exp(x, name=None)。计算e的x次方。
矩阵乘法:
由上面生成的XY来做矩阵乘法的运算。X是3(行)*4(列)的矩阵,Y也是3(行)*4(列)的矩阵,所以X * Y的转置。
同时也要保证XY的数据类型一致。

Y = tf.cast(Y, tf.int32)
tf.matmul(X, tf.transpose(Y))

将多个tensor连结(concatenate)。

tf.concat([X, Y], axis = 0), tf.concat([X, Y], axis = 1)

输出结果:

(<tf.Tensor: id=28, shape=(6, 4), dtype=int32, numpy=
 array([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11],
        [ 2,  1,  4,  3],
        [ 1,  2,  3,  4],
        [ 4,  3,  2,  1]])>,
 <tf.Tensor: id=30, shape=(3, 8), dtype=int32, numpy=
 array([[ 0,  1,  2,  3,  2,  1,  4,  3],
        [ 4,  5,  6,  7,  1,  2,  3,  4],
        [ 8,  9, 10, 11,  4,  3,  2,  1]])>)

分别在行上和列上连结XY两个矩阵。
可以看到,输出的第一个tensor在维度0的长度(6)为两个输入矩阵在维度0的长度之和(3+3),而输出的第二个tensor在维度1的长度(8)为两个输入矩阵在维度1的长度之和(4+4)。
使用条件判断式可以得到元素为0或1的新的tensor。以X == Y 为例,如果XY在相同位置的条件判断为真(值相等),那么新的tensor在相同的位置为1;反之为0。

tf.equal(X, Y)

输出结果:

<tf.Tensor: id=31, shape=(3, 4), dtype=bool, numpy=
array([[False,  True, False,  True],
       [False, False, False, False],
       [False, False, False, False]])>

tensor中的所有元素求和得到只有一个元素的tensor

tf.reduce_sum(X)

输出结果:

<tf.Tensor: id=33, shape=(), dtype=int32, numpy=66>

计算范数。tf.norm(tensor, ord='euclidean', axis=None, keep_dims=False, name=None)
用来计算向量、矩阵和张量的范数。

X = tf.cast(X, tf.float32)
tf.norm(X)

输出结果:

<tf.Tensor: id=39, shape=(), dtype=float32, numpy=22.494444>

3.广播机制

当对两个形状不同的tensor按元素运算时,可能会出发广播机制(broadcasting)机制;先适当复制元素使这两个tensor形状相同然后再按元素运算。
定义两个tensor

A = tf.reshape(tf.constant(range(3)), (3,1))
B = tf.reshape(tf.constant(range(2)), (1,2))
A, B

输出结果:

(<tf.Tensor: id=42, shape=(3, 1), dtype=int32, numpy=
 array([[0],
        [1],
        [2]])>,
 <tf.Tensor: id=45, shape=(1, 2), dtype=int32, numpy=array([[0, 1]])>)

AB分别是3行1列和1行2列的矩阵,如果要计算A + B,那么A中第1列的3个元素被广播(复制)到了第2列,而B中第1行的2个元素被广播(复制)到了第2行和第3行。如此,就可以对2个3行2列的矩阵按元素相加。

A + B

输出结果:

<tf.Tensor: id=46, shape=(3, 2), dtype=int32, numpy=
array([[0, 1],
       [1, 2],
       [2, 3]])>

4.索引

tensor中,索引(index)代表元素的位置。tensor的索引从0开始逐一递增。例如,一个3行2列的矩阵的行索引分别为0、1和2,列索引分别0和1。
我们可以指定tensor中需要访问的单个元素的位置,如矩阵中行和列的索引,并为该元素重新赋值。

X = tf.Variable(X)
X[1,2].assign(9)

也可以截取一部分元素,并为它们重新赋值。

X[1:2, :].assign(tf.ones(X[1:2, :].shape, dtype=tf.float32)*12)

5.运算的内存开销

在前面的例子中,我们对每个操作新开内存来存储运算结果。举个例子,即使像Y = X + Y这样的运算,也会新开内存,然后将Y指向新内存。
使用Python自带的id函数:如果两个实例的ID一致,那么它们所对应的内存地址相同;反之不同。

X = tf.Variable(X)
Y = tf.cast(Y, dtype=tf.float32)

before = id(Y)
Y = Y + X
id(Y) == before

输出结果:

False

如果想指定结果到特定内存,我们可以使用前面介绍的索引来进行替换操作。

Z = tf.Variable(tf.zeros_like(Y))
before = id(Z)
Z[:].assign(X + Y)
id(Z) == before

输出结果:

True

这里先通过zeros_like创建和Y形状相同且元素为0的tensor,记为Z。接下来将X + Y的结果通过assign函数写进Z对应的内存中。

6.tensor和Numpy相互变换

将Numpy实例变换成tensor实例。

import numpy as np
P = np.ones((2,3))
D = tf.constant(P)
D)

输出结果:

<tf.Tensor: id=115, shape=(2, 3), dtype=float64, numpy=
array([[1., 1., 1.],
       [1., 1., 1.]])>

将NDArray实例变换成Numpy实例。

np.array(D)

输出结果:

array([[1., 1., 1.],
       [1., 1., 1.]])

原文链接

猜你喜欢

转载自blog.csdn.net/qq_45465526/article/details/108446167