【问题标题】:passing Tensor as input to Keras api functional model将张量作为输入传递给 Keras api 功能模型
【发布时间】:2019-11-17 18:04:14
【问题描述】:

我有一个 api 函数模型,它可以很好地使用 numpy 数组作为输入。我的模型的简化版本如下。

inputLayerU = Input(shape=(10,))
denseLayerU = Dense(10, activation='relu')(inputLayerU)

inputLayerM = Input(shape=(10,))    
denseLayerM = Dense(10, activation='relu')(inputLayerM)

concatLayerUM = concatenate([denseLayerU, denseLayerM], axis = 1)
outputLayer = Dense(1,activation='linear')(concatLayerUM)

model = Model(inputs=[inputLayerUM, inputLayerMU], outputs=outputLayer)

model.fit_generator(dataGenerator(train, matA, matB, matC, batchSize,1),
    epochs=3,
    steps_per_epoch=10)

我使用了一个非常大的数据集,不适合我的记忆,所以我使用了一个生成器,如下所示:

def dataGenerator(data, matA, matB, matC, batchSize):

    sampleIndex = range(len(data))    
    batchNumber = int(len(data)/batchSize)  #count of batches

    counter=0
    while 1:
        U = np.zeros((batchSize,N))
        M = np.zeros((batchSize,N))
        outY = np.zeros((batchSize))

        for i in range(0,batchSize):
            ind = sampleIndex[i+counter*batchSize]
            U[i,:] = matA[ind,:]
            M[i,:] = matB[ind,:]
            outY[i] = data.iloc[ind]['y']

        matU = np.dot(U,matC)            
        matM = np.dot(M,matC)

        yield ([matU, matM], outY)

        #increase counter and restart it to yeild data in the next epoch as well
        counter += 1    
        if counter >= batchNumber:
            counter = 0  

如您所见,我在dataGenerator 函数中使用了两个二维数组的dot 乘积。我在 GPU 上运行我的代码并使其更快,我想用matmaul 替换点积,它以张量格式提供相同的结果。所以它会是这样的:

matU = tf.matmul(U,matB)        
matM = tf.matmul(M,matB)

但是,它提供了这个错误:

InvalidArgumentError: Requested tensor connection from unknown node: "input_4:0".

input_4:0 是模型中的第一个 inputLayerU 节点。所以看来我无法将张量传递给 InputLayer。那我应该怎么通过呢?

另外,我尝试将张量 matU 和 matM 转换为 numpy 数组,然后再将它们传递给输入层

matU = tf.Session().run(tf.matmul(U,matB))       
matM = tf.Session().run(tf.matmul(M,matB))

但它比最初使用点积要慢 10 倍。

我检查了this post,但是,它是针对顺序模型的,在开始训练模型之前我没有张量。

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:

    您可以将 U 和 M 作为输入传递,然后在模型中应用 Lambda:

    Lambda(lambda x: tf.matmul(x, tf.constant(constant_matrix)))
    

    假设 constant_matrix 在您的模型中是一个常数。

    使用函数式 API:

    import numpy as np
    from tensorflow import keras
    from tensorflow.keras.layers import *
    from tensorflow.keras.models import Model
    from tensorflow.keras import backend as K
    
    const_matrix = np.random.rand(10, 20)
    
    def apply_const_matrix(x):
      """
          x: shape=(batch_size, input_dims)
          const_matrix: shape=(input_dims, output_dims)
          output: (batch_size, output_dims)
      """
      return K.dot(x, K.constant(const_matrix))
    
    def make_model():
      inp_M = Input(shape=(10,))
      inp_U = Input(shape=(10,))
      Mp = Lambda(apply_const_matrix)(inp_M)
      Up = Lambda(apply_const_matrix)(inp_U)
      join = Concatenate(axis=1)([Mp, Up])
      h1 = Dense(32, activation='relu')(join)
      out = Dense(1, activation='sigmoid')(h1)
      model = Model([inp_M, inp_U], out)
      model.compile('adam', 'mse')
      return model
    
    model = make_model()
    model.summary()
    

    这里假设模型的输入是matmul运算之前的M、U向量,并且变换是用一个常数矩阵。

    【讨论】:

    • 谢谢,第二个 matB 输入错误,我已修复。我不明白,我从生成器中批量获取 U 和 M,那么我应该如何定义 inputLayer?像这样的东西? inputLayerU = Input(shape=(BatchSize,)), inputLambdaU = Lambda(lambda inputLayerU: tf.matmul(inputLayerU, tf.constant(matC)))
    • @Taher 编辑了答案,以举例说明如何应用该操作。
    • 你的代码和我的 dataGeneartor 一样。我使用它并应用了 tf.matmul 而不是 K.dot。但是,它比我在自己的实现中使用的方式使用点积要慢。
    猜你喜欢
    • 2020-03-13
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2021-06-12
    • 2022-11-11
    • 2017-10-24
    • 2021-06-24
    • 1970-01-01
    相关资源
    最近更新 更多