Tensorflow 神经网络中lambda层的输出形状不正确。如何改变它?

Tensorflow 神经网络中lambda层的输出形状不正确。如何改变它?,tensorflow,keras,nlp,Tensorflow,Keras,Nlp,这是我关于Stackoverflow的第一个问题,如果我遗漏了什么,请向我指出。 使用keras和tensorflow 1时,我的Lambda层有问题。在这个Lambda层中,我将一个100维手套向量作为输入,并计算与其他8个向量的余弦相似性(我之前转换为张量)。作为输出,我希望得到八个余弦相似性作为张量(我认为这在tensorflow中是必要的?) 我现在的问题是,结果张量的形状显然是(8,1),但实际上我认为我需要输出形状(无,8)。否则,它将不匹配我的网络中的后续层,即输出层,并应输出六类

这是我关于Stackoverflow的第一个问题,如果我遗漏了什么,请向我指出。 使用keras和tensorflow 1时,我的Lambda层有问题。在这个Lambda层中,我将一个100维手套向量作为输入,并计算与其他8个向量的余弦相似性(我之前转换为张量)。作为输出,我希望得到八个余弦相似性作为张量(我认为这在tensorflow中是必要的?)

我现在的问题是,结果张量的形状显然是(8,1),但实际上我认为我需要输出形状(无,8)。否则,它将不匹配我的网络中的后续层,即输出层,并应输出六类概率

这是我输入Lambda层的自定义函数的代码,取自:

此处输出,打印测试结果时,转换后的张量为:

Tensor("packed_53:0", shape=(8,), dtype=float32)
[0.5166239  0.2958691  0.317714   0.44583628 0.39608976 0.4195615 0.6432581  0.2618766 ]
结果如我所愿,但我的NN中的输出形状不正确。这些是最后几层,其各自的输出形状如下:

hidden = Dense(vector_dimension, activation='relu')(attention)

distance = Lambda(cosine_distance)(hidden)

out = Dense(6, activation='softmax')(distance)


dense_41 (Dense)             (None, 100)               20100     
_________________________________________________________________
lambda_26 (Lambda)           (8, 1)                    0         
_________________________________________________________________
dense_42 (Dense)             (8, 6)                    12        
dense_41 (Dense)             (None, 100)               20100     
_________________________________________________________________
lambda_26 (Lambda)           (None, 8)                    0         
_________________________________________________________________
dense_42 (Dense)             (None, 6)                    12        
最后我想要的是:

hidden = Dense(vector_dimension, activation='relu')(attention)

distance = Lambda(cosine_distance)(hidden)

out = Dense(6, activation='softmax')(distance)


dense_41 (Dense)             (None, 100)               20100     
_________________________________________________________________
lambda_26 (Lambda)           (8, 1)                    0         
_________________________________________________________________
dense_42 (Dense)             (8, 6)                    12        
dense_41 (Dense)             (None, 100)               20100     
_________________________________________________________________
lambda_26 (Lambda)           (None, 8)                    0         
_________________________________________________________________
dense_42 (Dense)             (None, 6)                    12        
我已经试过K变换张量并尝试输出形状函数,但没有达到预期效果。 任何帮助都将不胜感激


我希望我能澄清我的问题,并提前向您表示感谢。

只需将余弦计算更改为矢量化运算

def cosine_dist(inp):
  # I decided to have this as a variable within the function. 
  # But you can also define this outside and pass it as an input to the function.
  emo_vectors = tf.ones(shape=(8,100))
  def normalize(x):
    return x / K.sum(x**2, axis=1, keepdims=True)

  inp = normalize(inp)
  emo_vectors = normalize(emo_vectors)  
  cdist = K.dot(inp, K.transpose(emo_vectors))

  return cdist
这是一个正在使用的示例

inp = layers.Input(shape=(100))
hidden = layers.Lambda(lambda x: cosine_dist(x))(inp)
model = models.Model(inputs=inp, outputs=hidden)
model.summary()
这就给了,

Model: "model_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_8 (InputLayer)         [(None, 100)]             0         
_________________________________________________________________
lambda_7 (Lambda)            (None, 8)                 0         
=================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
_________________________________________________________________

如您所见,lambda层的输出现在是
(无,8)

只需将余弦计算更改为矢量化操作

def cosine_dist(inp):
  # I decided to have this as a variable within the function. 
  # But you can also define this outside and pass it as an input to the function.
  emo_vectors = tf.ones(shape=(8,100))
  def normalize(x):
    return x / K.sum(x**2, axis=1, keepdims=True)

  inp = normalize(inp)
  emo_vectors = normalize(emo_vectors)  
  cdist = K.dot(inp, K.transpose(emo_vectors))

  return cdist
这是一个正在使用的示例

inp = layers.Input(shape=(100))
hidden = layers.Lambda(lambda x: cosine_dist(x))(inp)
model = models.Model(inputs=inp, outputs=hidden)
model.summary()
这就给了,

Model: "model_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_8 (InputLayer)         [(None, 100)]             0         
_________________________________________________________________
lambda_7 (Lambda)            (None, 8)                 0         
=================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
_________________________________________________________________

如您所见,lambda层的输出现在是
(无,8)

一个接一个,而我也能够找到第二个解决方案。诀窍是考虑灵活的批量大小。下面是修改后的余弦函数代码:

from keras import backend as K

def cosine_distance(ref_vector):
    global emo_vec_array
    ref_vector = K.l2_normalize(ref_vector, axis=-1)

    cos_sim_list = []
    for emo_vector in emo_vec_array:
      emo_vector = K.l2_normalize(emo_vector, axis=-1)
      emo_vector = tf.reshape(emo_vector, [emo_vector.shape[0], 1])
      cos_sim = K.dot(ref_vector, emo_vector)
      cos_sim_list.append(cos_sim)

    result = tf.convert_to_tensor(cos_sim_list)
    result = tf.reshape(result, [len(emo_vec_array), -1])
    result = tf.transpose(result)
    return result


过了一段时间,我也找到了第二个解决方案。诀窍是考虑灵活的批量大小。下面是修改后的余弦函数代码:

from keras import backend as K

def cosine_distance(ref_vector):
    global emo_vec_array
    ref_vector = K.l2_normalize(ref_vector, axis=-1)

    cos_sim_list = []
    for emo_vector in emo_vec_array:
      emo_vector = K.l2_normalize(emo_vector, axis=-1)
      emo_vector = tf.reshape(emo_vector, [emo_vector.shape[0], 1])
      cos_sim = K.dot(ref_vector, emo_vector)
      cos_sim_list.append(cos_sim)

    result = tf.convert_to_tensor(cos_sim_list)
    result = tf.reshape(result, [len(emo_vec_array), -1])
    result = tf.transpose(result)
    return result