在下面的代码中:
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import keras.backend as kb
ip1 = keras.Input((20,), name='ip1')
ip2 = keras.Input((20,), name='ip2')
ip3 = keras.Input((20,), name='ip3')
ip4 = keras.Input((20,), name='ip4')
ip5 = keras.Input((20,), name='ip5')
ip6 = keras.Input((20,), name='ip6')
ip7 = keras.Input((20,), name='ip7')
ip8 = keras.Input((20,), name='ip8')
ip9 = keras.Input((20,), name='ip9')
ip_concat = kb.stack([ip1, ip2, ip3, ip4, ip5, ip6, ip7, ip8, ip9], axis=1)
rel_features = layers.Dense(128, input_shape=(9, 20))(ip_concat)
f1_enc = layers.Dense(64, activation='tanh', input_shape=(9, 128))(rel_features)
这里,f1_enc
具有9x64的形状。现在,我需要做的可以从下面的例子中理解。为了简单起见,我将初始张量保持为3x3:,而不是9x64张量
[[a, b, c],
[d, e, f],
[g, h, i]]
需要转换为3x3x6张量,如下所示:
[[[a, b, c, a, b, c],
[a, b, c, d, e, f],
[a, b, c, g, h, i]],
[[d, e, f, a, b, c],
[d, e, f, d, e, f],
[d, e, f, g, h, i]],
[[g, h, i, a, b, c],
[g, h, i, d, e, f],
[g, h, i, g, h, i]]]
我知道张量在张量流中是不可变的,所以在张量上循环并将值重新分配给新的张量是行不通的。
此外,我还试着处理急切的执行,因为张量到numpy矩阵的转换不起作用。根据我现在的理解,将张量转换为numpy矩阵的策略不起作用,因为我们使用的是keras层。
虽然代码将需要反向传播到ip_concat
,但它将而不需要通过新的张量反向传播。稍后将有一个从ip_concat
到另一个keras层的连接。
这可能不是最有效的方法,但:
import numpy as np
import tensorflow as tf
tensor = tf.constant([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(tensor)
# tf.Tensor(
# [[1 2 3]
# [4 5 6]
# [7 8 9]], shape=(3, 3), dtype=int32)
x = tensor.numpy()
tensor = tf.constant([[np.concatenate((j, i)) for i in x] for j in x])
print(tensor)
# tf.Tensor(
# [[[1 2 3 1 2 3]
# [1 2 3 4 5 6]
# [1 2 3 7 8 9]]
# [[4 5 6 1 2 3]
# [4 5 6 4 5 6]
# [4 5 6 7 8 9]]
# [[7 8 9 1 2 3]
# [7 8 9 4 5 6]
# [7 8 9 7 8 9]]], shape=(3, 3, 6), dtype=int32)
使用tf.unstack
、tf.tile
、tf.reshape
和tf.concat
的组合。我们的初始张量A
:
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]], dtype=int32)>
首先,展开行:
A1, A2, A3 = tf.unstack(A, axis=0)
输出:
(<tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 2, 3], dtype=int32)>,
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([4, 5, 6], dtype=int32)>,
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([7, 8, 9], dtype=int32)>)
然后tile
和reshape
:
L1, L2, L3 = [tf.reshape(tf.tile(X, [3]), (3,3)) for X in [A1, A2, A3]]
输出:
(<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]], dtype=int32)>,
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
array([[4, 5, 6],
[4, 5, 6],
[4, 5, 6]], dtype=int32)>,
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
array([[7, 8, 9],
[7, 8, 9],
[7, 8, 9]], dtype=int32)>)
然后与初始张量连接:
R1, R2, R3 = [tf.concat([X, A], axis=1) for X in [L1, L2, L3]]
输出:
(<tf.Tensor: shape=(3, 6), dtype=int32, numpy=
array([[1, 2, 3, 1, 2, 3],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 7, 8, 9]], dtype=int32)>,
<tf.Tensor: shape=(3, 6), dtype=int32, numpy=
array([[4, 5, 6, 1, 2, 3],
[4, 5, 6, 4, 5, 6],
[4, 5, 6, 7, 8, 9]], dtype=int32)>,
<tf.Tensor: shape=(3, 6), dtype=int32, numpy=
array([[7, 8, 9, 1, 2, 3],
[7, 8, 9, 4, 5, 6],
[7, 8, 9, 7, 8, 9]], dtype=int32)>)