面对有时候需要对数据维度进行扩充,例如低维数据向转高维度或者不规则张量 ragged Tensor的填充,这时候就需要expand_dims登场、同时还有 tf.tile 和 preprocessing.sequence.pad_sequences 帮忙。
tf.expand_dims 可以扩充数组维度,参数包括:
array:需要扩充的数组,这里 tensor,np.array 或者 python.list 都可以
axis:需要扩充的维度,这里假设 n 维数据,则只能扩充至 n+1 维,否则会报错
index = np.array([
[71, 1331, 4231, 0, 0, 0],
[73, 8, 3215, 55, 927, 0],
[83, 91, 1, 645, 1253, 927],
])
# expand_dim 扩充维度 3 x 6 -> 3 x 6 x 1
expand = tf.expand_dims(index, axis=-1)
print(expand)
原始数据维度 3x6,扩充后变为 3x6x1 ,如果设置axis=0,则扩充为 1x3x6,同理 axis=1,扩充至 3x1x6,axis=2 作用与 axis=-1一致,都是在最后追加一维。
tf.Tensor(
[[[ 71]
[1331]
[4231]
[ 0]
[ 0]
[ 0]]
[[ 73]
[ 8]
[3215]
[ 55]
[ 927]
[ 0]]
[[ 83]
[ 91]
[ 1]
[ 645]
[1253]
[ 927]]], shape=(3, 6, 1), dtype=int64)
前面的expand_dims是在当前维度增加新的维度,tf.tile不会增加新的维度,只是扩充当前 shape,参数包括:
array:需要扩充的数组,这里 tensor,np.array 或者 python.list 都可以
list:各维度元素扩充倍数,这里需要与原始 shape 维度一致,原始 m x n,list参数 k x j => tile后维度 (m*k) x (n*j)
# tile 扩展维度
# Easy 2x2 3x4 => 6x8
index = [
[1,2],
[3,4],
]
print(tf.tile(index,[3,4]))
2x2 3x4 对应位置相乘得到 6x8,实际上就是将对应数据在相应维度上复制对应次数,[1,2] 和 [3,4]先在axis=0维度复制三次变成 6x2 ,然后再在axis=1维度上复制4次,由6x2变为6x8
tf.Tensor(
[[1 2 1 2 1 2 1 2]
[3 4 3 4 3 4 3 4]
[1 2 1 2 1 2 1 2]
[3 4 3 4 3 4 3 4]
[1 2 1 2 1 2 1 2]
[3 4 3 4 3 4 3 4]], shape=(6, 8), dtype=int32)
在处理序列数据时,各个样本常常具有不同长度,就是常说的不规则向量 ragged Tensor,这里需要给对应向量填充至维度统一,才能进行后续训练等,就像one-hot一样,包含如下参数:
array:需要扩充的数组,这里 tensor,np.array 或者 python.list 都可以
padding:填充方式,post是在后面补0,pre则是在前面补0,可以根据自己需求选择
# Hard 3x6 => 3x6x1 => 3x6x10
raw_inputs = [
[711, 632, 71],
[73, 8, 3215, 55, 927],
[83, 91, 1, 645, 1253, 927],
]
padded_inputs = tf.keras.preprocessing.sequence.pad_sequences(
raw_inputs, padding="post"
)
由于深度学习模型的输入数据必须为单一张量(batch_size, 6, vocab_size)
,短于最长条目的样本需要用占位符值进行填充(或者,也可以在填充短样本前截断长样本)。这里长度分别为3,5,6,所以以6为基准进行填充。
[[ 711 632 71 0 0 0]
[ 73 8 3215 55 927 0]
[ 83 91 1 645 1253 927]]
结合前两个方法继续扩充该向量,先追加一维:
print(tf.expand_dims(padded_inputs, axis=-1)
tf.Tensor(
[[[ 711]
[ 632]
[ 71]
[ 0]
[ 0]
[ 0]]
[[ 73]
[ 8]
[3215]
[ 55]
[ 927]
[ 0]]
[[ 83]
[ 91]
[ 1]
[ 645]
[1253]
[ 927]]], shape=(3, 6, 1), dtype=int32)
再把最后一维增加10倍:
print(tf.tile(tf.expand_dims(padded_inputs, axis=-1), [1, 1, 10]))
刚才是2维所以后面扩充的list是2维,这里数据是三维,所以对应list也是三维,当某一维度数字为1时,代表不进行扩充。
tf.Tensor(
[[[ 711 711 711 711 711 711 711 711 711 711]
[ 632 632 632 632 632 632 632 632 632 632]
[ 71 71 71 71 71 71 71 71 71 71]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]]
[[ 73 73 73 73 73 73 73 73 73 73]
[ 8 8 8 8 8 8 8 8 8 8]
[3215 3215 3215 3215 3215 3215 3215 3215 3215 3215]
[ 55 55 55 55 55 55 55 55 55 55]
[ 927 927 927 927 927 927 927 927 927 927]
[ 0 0 0 0 0 0 0 0 0 0]]
[[ 83 83 83 83 83 83 83 83 83 83]
[ 91 91 91 91 91 91 91 91 91 91]
[ 1 1 1 1 1 1 1 1 1 1]
[ 645 645 645 645 645 645 645 645 645 645]
[1253 1253 1253 1253 1253 1253 1253 1253 1253 1253]
[ 927 927 927 927 927 927 927 927 927 927]]], shape=(3, 6, 10), dtype=int32)
更多推荐算法相关深度学习:深度学习导读专栏