Int [1]: import tensorflow as tf
Int [2]: tf.constant(1) # 创建一个整型张量
Out [2]:
Int [3]: tf.constant(1.) # 创建一个浮点型张量
Out [3]:
Int [4]: tf.constant(2., dtype=tf.double) # 创建的同时指定数据类型
Out [4]:
Int [5]: tf.constant([[1.,2.,3.],[4.,5.,6.]]) # 通过传入一个list参数创建
Out [5]:
如果输入的数据与指定的数据类型不相符,会产生以下异常:
TypeError: Cannot convert provided value to EagerTensor. Provided value: 2.1 Requested dtype: int32
Int[9]: import numpy as np
Int[10]: tf.convert_to_tensor(np.ones([2, 3]))
Out[10]:
Int[11]: tf.convert_to_tensor(np.ones([2, 3]))
Out[11]:
Int[12]: tf.convert_to_tensor([[2.,3.],[3., 4.]])
Out[12]:
如果你熟悉numpy创建数组的方法,你一定见过zeros()、ones()等方法,TensorFlow中也有这些方法。
In [3]: a = tf.zeros([2, 3, 3]) # 创建一个元素全为0,形状为[2, 3, 3]的tensor
In [4]: a
Out[4]:
In [5]: b = tf.ones([2, 3]) # 创建一个元素全为1,形状为[2, 3]的tensor
In [6]: b
Out[6]:
In [7]: tf.zeros_like(b) # 仿照b的shape创建一个全为0的tensor
Out[7]:
In [8]: tf.ones_like(a) # 仿照b的shape创建一个全为1的tensor
Out[8]:
In [9]: tf.fill([2,3],5) # 创建元素全为5,形状为[2,3]的tensor
Out[9]:
在实际应用中,经常需要随机初始化元素服从某种分布的tensor,TensorFlow中也提供了这种功能。
(1)从指定正态分布中随机取值:tf.random.normal()。例如,随机初始化一个元素服从均值为1,方差为1的正态分布且形状为[2, 3]的tensor:
In [10]: tf.random.normal([2, 3], mean=1, stddev=1)
Out[10]:
(2)从指定的截断正态分布中随机取值:truncated_normal()。意思是从指定的正太分布中取值,但是取值范围在两个标准差范围内,也就是:[ mean - 2 stddev, mean + 2 stddev ]
In [11]: tf.random.truncated_normal([2, 3], mean=1, stddev=1)
Out[11]:
(3)从指定均匀分布中随机取值:tf.random.uniform()。
In [12]: tf.random.uniform([2, 3], minval=1, maxval=2) # 在1~2之间均匀分布
Out[12]:
In [14]: import numpy as np
In [15]: import tensorflow as tf
In [16]: a = tf.convert_to_tensor(np.arange(80).reshape(2,2,4,5))
In [17]: a
Out[17]:
TensorFlow支持Python原生的基础索引方式,即多个方括号逐步索引取值:[idx][idx][idx],每个方括号对应一个维度。
In [18]: a[0] # 取第一个维度
Out[18]:
In [19]: a[0][1] # 同时筛选两个维度
Out[19]:
In [20]: a[0][1][3][3] # 同时对4个维度进行筛选
Out[20]:
这种索引数据的方法简单,易于理解,但是可读性差,只能按维度依次索引数据,也不能索引列。
TensorFlow也继承了numpy中的部分索引方式
(1)[idx1, idx2, idx3]
这种索引方式是在一个方括号内写下所有的索引,每个索引序号之间用逗号隔开。
In [21]: a[1] # 筛选第一维度,这跟基础索引一样
Out[21]:
In [22]: a[1,1, 3] # 同时帅选3个维度
Out[22]:
(2)冒号切片与步长:[start?step]
这种索引方式在Python原生的list类型中也是常见的,而且使用方法也是一样的。
In [23]: a[1,:,0:2] # 对第1维度选第二块数据,对第二维度选所有数据,对第三维度选前两行
Out[23]:
In [24]: a[1,:,0:2,0:4] # 继续上面的例子,对第4维度筛选去前4列
Out[24]:
In [25]: a[1,:,0:2,0:4:2] # 对第4维度加上步长,每隔一个数据取一次
Out[25]:
也可以使用负值步长表示逆序索引,但要注意,负数步长时,原本的[start : end : step]也要跟着编程[end : start : step]:
In [26]: a[1,:,0:2,4:0:-1]
Out[26]:
In [27]: a[1,:,0:2,4:0:-2]
Out[27]:
在numpy和TensorFlow中还有“…"(三个英文句号)的使用,“…"用于表示连续多个维度全选:
In [28]: a[1,...,0:4] # 等同于a[1, : , : ,0:4]
Out[28]:
In [29]: a[0,0,...] # 等同于a[0,0,:,:]
Out[29]:
gather与gather_nd是指TensorFlow通过gather()方法和gather_nd()方法提供的两种索引方式。在numpy中,可以通过嵌套list的方式来指定无规则的索引:
In [30]: b = np.arange(20).reshape(4,5)
In [31]: b[1, [0,3,4]] # 选取第2行的第1列、第4列、第5列
Out[31]: array([5, 8, 9])
但是在TensorFlow中,这种索引方式并没有从numpy中继承下来,所以如果在Tensor中使用这种方式,会抛出以下异常:
TypeError: Only integers, slices ( : ), ellipsis (…), tf.newaxis (None) and scalar tf.int32/tf.int64 tensors are valid indices, got [0, 3, 4]
还好的是,在TensorFlow中通过gather()方法和gather_nd()方法提供了这种索引方法。
(1)gather()方法
In [32]: tf.gather(b, axis=0, indices=[0, 2, 3]) # 选取第1行,第3行,第4行
Out[32]:
In [33]: tf.gather(b, axis=1, indices=[0, 2, 3]) # 选取第1列,第3列,第4列
Out[33]:
仔细观察上面gather()方法例子,可以发现,第一个参数时数据源,还有两个参数中,axis指的是将要的维度,indices指的是需要选取的序号。
(2)gather_nd()
gather()方法一次只能对一个维度进行索引,gather_nd()方法可以同时对多个维度进行索引。
In [34]: tf.gather_nd(b, [[0, 2],[3, 3]]) # 选取第1行第3列的那个数据,和第4行第4列的数据
Out[34]:
可以结合一些简单的逻辑运算符进行索引取值:
In [1]: import tensorflow as tf
In [2]: a = tf.random.uniform([3,3],minval=-10,maxval=10,dtype=tf.int32)^M
...: a
2019-10-23 11:03:13.189763: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
Out[2]:
In [3]: mask = a < 0^M
...: mask
Out[3]:
可以看到,返回的是一个shape与a相同的tensor,在a小于零的位置是True,大于零的位置为False。进一步地,我们可以用boolwan_mask()方法直接取出符合条件的元素:
In [4]: tf.boolean_mask(a,mask)
Out[4]:
可以结合where()方法取出符合条件元素的索引:
In [5]: m_index = tf.where(mask)^M
...: m_index
Out[5]:
再使用之前说过的gather_nd()方法取值:
In [6]: tf.gather_nd(a,m_index)
Out[6]:
where()方法还有第二种用法——从两个tensor中取出符合条件的值,这时候where()方法必须接受3个参数:
In [7]: condition = tf.random.uniform([3,3],minval=0,maxval=2,dtype=tf.int32)^M
...: condition = tf.cast(condition, tf.bool)^M
...: condition
Out[7]:
In [8]: a = tf.range(1,10)^M
...: a = tf.reshape(a,[3,3])^M
...: a
Out[8]:
In [9]: b = tf.range(-9,0)^M
...: b = tf.reshape(b,[3,3])^M
...: b
Out[9]:
In [10]: tf.where(condition, a, b)
Out[10]:
上面where()方法返回的结果在True的位置取值是a中对应位置元素的值,在False位置是b中对应元素的值。