При использовании keras Lambda, как мне обработать «TypeError: Объектные массивы в настоящее время не поддерживаются»? - PullRequest
0 голосов
/ 05 ноября 2018

Я использую Keras, и я хочу сделать слой, который принимает [a0, a1], [b0, b1, b2] в качестве входных данных и дает [a0*b0, a0*b1, a0*b2, a1*b0, a1*b1, a1*b2] в качестве выходных данных. Я пытался использовать Lambda, но не смог добиться успеха. Вот мой код:

import numpy as np
from keras.models import Input
from keras.layers import Lambda

def mix(A):
    reshaped = [np.reshape(A[m], (1,np.size(A[m]))) for m in range(len(A))]
    mixed = reshaped[-1]

    for i in range(len(A)-1):
        mixed = np.matmul(np.transpose(reshaped[-i-2]), mixed)
        mixed = np.reshape(mixed, (1,np.size(mixed)))

    return np.reshape(mixed, np.size(mixed))

a = Input(shape=(2,))
b = Input(shape=(3,))
c = Lambda(mix)([a, b])

Вот ошибка, которую я получил:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-32-07bbf930b48b> in <module>()
      1 a = Input(shape=(2,))
      2 b = Input(shape=(3,))
----> 3 c = Lambda(mix)([a, b])

~\Anaconda3\envs\mind\lib\site-packages\keras\engine\base_layer.py in __call__(self, inputs, **kwargs)
    455             # Actually call the layer,
    456             # collecting output(s), mask(s), and shape(s).
--> 457             output = self.call(inputs, **kwargs)
    458             output_mask = self.compute_mask(inputs, previous_mask)
    459 

~\Anaconda3\envs\mind\lib\site-packages\keras\layers\core.py in call(self, inputs, mask)
    685         if has_arg(self.function, 'mask'):
    686             arguments['mask'] = mask
--> 687         return self.function(inputs, **arguments)
    688 
    689     def compute_mask(self, inputs, mask=None):

<ipython-input-31-bbc21320d8af> in mix(A)
      4 
      5     for i in range(len(A)-1):
----> 6         mixed = np.matmul(np.transpose(reshaped[-i-2]), mixed)
      7         mixed = np.reshape(mixed, (1,np.size(mixed)))
      8 

TypeError: Object arrays are not currently supported

Но если я поставлю:

a = np.array([1,2])
b = np.array([3,4,5])
print(mix([a,b]))

тогда я получаю:

[ 3  4  5  6  8 10]

это именно то, что я и хотел. Но я не знаю, как правильно поместить это в Lambda.

Может кто-нибудь сказать мне, как справиться с этим? Я новичок в Keras, поэтому я не знаю внутреннюю структуру Lambda, Input или других вещей.


После комментария Абхиджита я изменил код следующим образом:

import numpy as np
import tensorflow as tf
from keras.models import Input
from keras.layers import Lambda

def mix(A):
    reshaped = [tf.reshape(A[m], (1,tf.size(A[m]))) for m in range(len(A))]
    mixed = reshaped[-1]

    for i in range(len(A)-1):
        mixed = tf.matmul(tf.transpose(reshaped[-i-2]), mixed)
        mixed = tf.reshape(mixed, (1,tf.size(mixed)))

    return tf.reshape(mixed, [tf.size(mixed)])

a = Input(shape=(2,))
b = Input(shape=(3,))
c = Lambda(mix)([a, b])

Теперь я не получаю никаких ошибок, но я не думаю, что получил правильную нейронную сеть. Потому что выполнение:

model = Model(inputs=[a,b], outputs=c)
print(model.summary())

Я получаю:

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_22 (InputLayer)           (None, 2)            0                                            
__________________________________________________________________________________________________
input_23 (InputLayer)           (None, 3)            0                                            
__________________________________________________________________________________________________
lambda_3 (Lambda)               (None,)              0           input_22[0][0]                   
                                                                 input_23[0][0]                   
==================================================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
__________________________________________________________________________________________________

Но посмотрите на слой lambda_3. Разве выходная форма не должна быть (None, 6)?

1 Ответ

0 голосов
/ 05 ноября 2018

Помимо того, что вам нужно использовать бэкэнд-функции Keras (например, keras.backend.*) или использовать бэкэнд-функции напрямую (например, tf.* или th.*), я думаю, что вы делаете определение mix излишне сложным , Это можно сделать намного проще, как это:

from keras import backend as K

def mix(ts):
    t0 = K.expand_dims(ts[0], axis=-1)
    t1 = K.expand_dims(ts[1], axis=1)
    return K.batch_flatten(t0 * t1)

a = Input(shape=(2,))
b = Input(shape=(3,))
c = Lambda(mix)([a, b])

model = Model(inputs=[a,b], outputs=c)

Вот тест:

# the reshapes are necessary to make them a batch
a = np.array([1,2]).reshape(1,2)
b = np.array([3,4,5]).reshape(1,3)
print(model.predict([a, b]))

# output
[[ 3.  4.  5.  6.  8. 10.]]

Кроме того, иногда слой Lambda может автоматически выводить форму вывода. Однако, если вы хотите, вы можете явно установить его форму вывода:

c = Lambda(mix, output_shape=(6,))([a, b])

Краткое описание модели:

Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_9 (InputLayer)            (None, 2)            0                                            
__________________________________________________________________________________________________
input_10 (InputLayer)           (None, 3)            0                                            
__________________________________________________________________________________________________
lambda_5 (Lambda)               (None, 6)            0           input_9[0][0]                    
                                                                 input_10[0][0]                   
==================================================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
__________________________________________________________________________________________________
...