tf.range
创建一串数字序列:
tf.range(limit, delta=1, dtype=None, name='range')
tf.range(start, limit, delta=1, dtype=None, name='range')
创建一系列从start开始,到limit结束但是不包括limit的数字序列,序列的间隔为delta;
返回的tensor类型由dtype参数指定,如果没有明确指定,tensor类型由start或者limit的类型推测而来;
用法和python的内置函数range相同,start的默认值为0,所以 range(n)和 range(0,n)返回相同的数列。
For Example:
start = 3
limit = 18
delta = 3
tf.range(start, limit, delta) # [3, 6, 9, 12, 15]
start = 3
limit = 1
delta = -0.5
tf.range(start, limit, delta) # [3, 2.5, 2, 1.5]
limit = 5
tf.range(limit) # [0, 1, 2, 3, 4]
对应numpy的arange函数。
tf.transpose
对矩阵进行转置操作:
tf.transpose(
a,
perm=None,
name='transpose',
conjugate=False
)
根据参数perm置换a的维度并返回新的Tensor,如果perm为None,则根据perm = (n-1, ... , 0)进行操作,n为a的秩,如果conjugate为true,并且a.dtype为complex64或者complex32,则返回a的转置共轭。
For Example:
x = tf.constant([[1, 2, 3], [4, 5, 6]])
tf.transpose(x) # [[1, 4]
# [2, 5]
# [3, 6]]
# Equivalently
tf.transpose(x, perm=[1, 0]) # [[1, 4]
# [2, 5]
# [3, 6]]
# If x is complex, setting conjugate=True gives the conjugate transpose
x = tf.constant([[1 + 1j, 2 + 2j, 3 + 3j],
[4 + 4j, 5 + 5j, 6 + 6j]])
tf.transpose(x, conjugate=True) # [[1 - 1j, 4 - 4j],
# [2 - 2j, 5 - 5j],
# [3 - 3j, 6 - 6j]]
# 'perm' is more useful for n-dimensional tensors, for n > 2
x = tf.constant([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
# Take the transpose of the matrices in dimension-0
# (this common operation has a shorthand `linalg.matrix_transpose`)
tf.transpose(x, perm=[0, 2, 1]) # [[[1, 4],
# [2, 5],
# [3, 6]],
# [[7, 10],
# [8, 11],
# [9, 12]]]
tf的transpose和numpy的transpose有所不同,numpy的transpose操作是内存高效且在常数时间复杂度完成的操作,不会涉及到数据的拷贝。 TensorFlow返回的是一个转置之后新的Tensor。
tf.transpose可用于进行TensorFlow的数据格式转化,tensorflow的很多函数都有参数指定data_format,默认值为'NHWC',但是还有一种格式为'NCHW',N:批次中的图像数量,C:图像的通道数量, H:图像的高度, W:图像的宽度。
NHWC 的访存局部性更好(每三个输入像素即可得到一个输出像素),NCHW 则必须等所有通道输入准备好才能得到最终输出结果,需要占用较大的临时空间。
在 CNN 中常常见到 1x1 卷积(例如:用于移动和嵌入式视觉应用的 MobileNets),也是每个输入 channel 乘一个权值,然后将所有 channel 结果累加得到一个输出 channel。如果使用 NHWC 数据格式,可以将卷积计算简化为矩阵乘计算,即 1x1 卷积核实现了每个输入像素组到每个输出像素组的线性变换。
TensorFlow 为什么选择 NHWC 格式作为默认格式?因为早期开发都是基于 CPU,使用 NHWC 比 NCHW 稍快一些(不难理解,NHWC 局部性更好,cache 利用率高)。
NCHW 则是 Nvidia cuDNN 默认格式,使用 GPU 加速时用 NCHW 格式速度会更快(也有个别情况例外)。
最佳实践:设计网络时充分考虑两种格式,最好能灵活切换,在 GPU 上训练时使用 NCHW 格式,在 CPU 上做预测时使用 NHWC 格式。
NHWC到NCHW
perm[0] = 0 # output dimension 0 will be 'N', which was dimension 0 in the input
perm[1] = 3 # output dimension 1 will be 'C', which was dimension 3 in the input
perm[2] = 1 # output dimension 2 will be 'H', which was dimension 1 in the input
perm[3] = 2 # output dimension 3 will be 'W', which was dimension 2 in the input
images_nhwc = tf.placeholder(tf.float32, [None, 200, 300, 3]) # input batch
out = tf.transpose(x, [0, 3, 1, 2])
print(out.get_shape()) # the shape of out is [None, 3, 200, 300]
从NCHW到NHWC
perm[0] = 0 # output dimension 0 will be 'N', which was dimension 0 in the input
perm[1] = 2 # output dimension 1 will be 'H', which was dimension 2 in the input
perm[2] = 3 # output dimension 2 will be 'W', which was dimension 3 in the input
perm[3] = 1 # output dimension 3 will be 'C', which was dimension 1 in the input
images_nchw = tf.placeholder(tf.float32, [None, 3, 200, 300]) # input batch
out = tf.transpose(x, [0, 2, 3, 1])
print(out.get_shape()) # the shape of out is [None, 200, 300, 3]