2017-10-16 10 views
4

je dois mettre en œuvre une couche personnalisée comme ceci:Comment mettre en œuvre la couche personnalisée avec entrées multiples dans Keras

class MaskedDenseLayer(Layer): 
    def __init__(self, output_dim, activation, **kwargs): 
     self.output_dim = output_dim 
     super(MaskedDenseLayer, self).__init__(**kwargs) 
     self._activation = activations.get(activation) 
    def build(self, input_shape): 

     # Create a trainable weight variable for this layer. 
     self.kernel = self.add_weight(name='kernel', 
            shape=(input_shape[0][1], self.output_dim), 
            initializer='glorot_uniform', 
            trainable=True) 
     super(MaskedDenseLayer, self).build(input_shape) 

    def call(self, l): 
     self.x = l[0] 
     self._mask = l[1][1] 
     print('kernel:', self.kernel) 
     masked = Multiply()([self.kernel, self._mask]) 
     self._output = K.dot(self.x, masked) 
     return self._activation(self._output) 


    def compute_output_shape(self, input_shape): 
    return (input_shape[0][0], self.output_dim) 

Ceci est tout comme la façon de mettre en œuvre Keras API introduit des couches personnalisées. et je dois donner deux entrées à cette couche comme ceci:

def main(): 
    with np.load('datasets/simple_tree.npz') as dataset: 
     inputsize = dataset['inputsize'] 
     train_length = dataset['train_length'] 
     train_data = dataset['train_data'] 
     valid_length = dataset['valid_length'] 
     valid_data = dataset['valid_data'] 
     test_length = dataset['test_length'] 
     test_data = dataset['test_data'] 
     params = dataset['params'] 

    num_of_all_masks = 20 
    num_of_hlayer = 6 
    hlayer_size = 5 
    graph_size = 4 

    all_masks = generate_all_masks(num_of_all_masks, num_of_hlayer, hlayer_size, graph_size) 

    input_layer = Input(shape=(4,)) 

    mask_1 = Input(shape = (graph_size , hlayer_size)) 
    mask_2 = Input(shape = (hlayer_size , hlayer_size)) 
    mask_3 = Input(shape = (hlayer_size , hlayer_size)) 
    mask_4 = Input(shape = (hlayer_size , hlayer_size)) 
    mask_5 = Input(shape = (hlayer_size , hlayer_size)) 
    mask_6 = Input(shape = (hlayer_size , hlayer_size)) 
    mask_7 = Input(shape = (hlayer_size , graph_size)) 


    hlayer1 = MaskedDenseLayer(hlayer_size, 'relu')([input_layer, mask_1]) 
    hlayer2 = MaskedDenseLayer(hlayer_size, 'relu')([hlayer1, mask_2]) 
    hlayer3 = MaskedDenseLayer(hlayer_size, 'relu')([hlayer2, mask_3]) 
    hlayer4 = MaskedDenseLayer(hlayer_size, 'relu')([hlayer3, mask_4]) 
    hlayer5 = MaskedDenseLayer(hlayer_size, 'relu')([hlayer4, mask_5]) 
    hlayer6 = MaskedDenseLayer(hlayer_size, 'relu')([hlayer5, mask_6]) 
    output_layer = MaskedDenseLayer(graph_size, 'sigmoid')([hlayer6, mask_7]) 

    autoencoder = Model(inputs=[input_layer, mask_1, mask_2, mask_3, 
        mask_4, mask_5, mask_6, mask_7], outputs=[output_layer]) 

    autoencoder.compile(optimizer='adam', loss='binary_crossentropy') 
    #reassign_mask = ReassignMask() 

    for i in range(0, num_of_all_masks): 
     state = np.random.randint(0,20) 
     autoencoder.fit(x=[train_data, 
         np.tile(all_masks[state][0], [300, 1, 1]), 
         np.tile(all_masks[state][1], [300, 1, 1]), 
         np.tile(all_masks[state][2], [300, 1, 1]), 
         np.tile(all_masks[state][3], [300, 1, 1]), 
         np.tile(all_masks[state][4], [300, 1, 1]), 
         np.tile(all_masks[state][5], [300, 1, 1]), 
         np.tile(all_masks[state][6], [300, 1, 1])], 
        y=[train_data], 
        epochs=1, 
        batch_size=20, 
        shuffle=True, 
        #validation_data=(valid_data, valid_data), 
        #callbacks=[reassign_mask], 
        verbose=1) 

Malheureusement, quand je lance ce code je reçois l'erreur suivante:

TypeError: can only concatenate tuple (not "int") to tuple 

Ce que je besoin est un moyen de mettre en œuvre une coutume couche avec deux entrées contenant la couche précédente et une matrice de masque. Ici, la variable all_mask est une liste contenant des masques pré-générés pour toutes les couches.

Quelqu'un peut-il aider? Quel est le problème ici avec mon code.

Update

Certains paramètres:

données de train: (300, 4)

nombre de couches cachées: 6

unités de couche cachée: 5

masque : (taille de la couche précédente, taille de la couche actuelle)

Et voici mon résumé de modèle:

__________________________________________________________________________________________________ 
Layer (type)     Output Shape   Param #  Connected to      
================================================================================================== 
input_361 (InputLayer)   (None, 4)   0            
__________________________________________________________________________________________________ 
input_362 (InputLayer)   (None, 4, 5)   0            
__________________________________________________________________________________________________ 
masked_dense_layer_281 (MaskedD (None, 5)   20   input_361[0][0]     
                   input_362[0][0]     
__________________________________________________________________________________________________ 
input_363 (InputLayer)   (None, 5, 5)   0            
__________________________________________________________________________________________________ 
masked_dense_layer_282 (MaskedD (None, 5)   25   masked_dense_layer_281[0][0]  
                   input_363[0][0]     
__________________________________________________________________________________________________ 
input_364 (InputLayer)   (None, 5, 5)   0            
__________________________________________________________________________________________________ 
masked_dense_layer_283 (MaskedD (None, 5)   25   masked_dense_layer_282[0][0]  
                   input_364[0][0]     
__________________________________________________________________________________________________ 
input_365 (InputLayer)   (None, 5, 5)   0            
__________________________________________________________________________________________________ 
masked_dense_layer_284 (MaskedD (None, 5)   25   masked_dense_layer_283[0][0]  
                   input_365[0][0]     
__________________________________________________________________________________________________ 
input_366 (InputLayer)   (None, 5, 5)   0            
__________________________________________________________________________________________________ 
masked_dense_layer_285 (MaskedD (None, 5)   25   masked_dense_layer_284[0][0]  
                   input_366[0][0]     
__________________________________________________________________________________________________ 
input_367 (InputLayer)   (None, 5, 5)   0            
__________________________________________________________________________________________________ 
masked_dense_layer_286 (MaskedD (None, 5)   25   masked_dense_layer_285[0][0]  
                   input_367[0][0]     
__________________________________________________________________________________________________ 
input_368 (InputLayer)   (None, 5, 4)   0            
__________________________________________________________________________________________________ 
masked_dense_layer_287 (MaskedD (None, 4)   20   masked_dense_layer_286[0][0]  
                   input_368[0][0]     
================================================================================================== 
Total params: 165 
Trainable params: 165 
Non-trainable params: 0 

Répondre

3

Votre input_shape est une liste de tuples.

input_shape: [(None, 4), (None, 4, 5)] 

Vous ne pouvez pas utiliser simplement input_shape[0] ou input_shape[1]. Si vous voulez utiliser les valeurs réelles, vous devez choisir quel tuple, puis quelle valeur. Exemple:

self.kernel = self.add_weight(name='kernel', 

           #here: 
           shape=(input_shape[0][1], self.output_dim), 


           initializer='glorot_uniform', 
           trainable=True) 

La même chose serait nécessaire (selon vos propres règles de forme) dans la méthode compute_output_shape, où il semble que vous voulez est concaténer tuples:

return input_shape[0] + (self.output_dim,) 

Ne pas oublier décommenter la ligne super(MaskedDenseLayer, self).build(input_shape).

+0

Thx à prendre en compte Daniel, mais le code ne fonctionne toujours pas et l'erreur a changé: Les dimensions doivent être égales, mais sont 5 et 4 pour 'masked_dense_layer_293/MatMul' (op: 'MatMul') avec des formes d'entrée: [? 5], [4,20]. – muradin

+0

Maintenant, l'erreur est plus facile à comprendre. Les formes sont incompatibles pour la multiplication de la matrice. Le problème est dans 'output = K.dot (self.x, masqué)'. Quelles sont exactement les formes que vous attendez pour self.x et pour masqué? Et quel genre de multiplication voulez-vous? –

+0

Il existe deux types de multiplication dans ma fonction d'appel. Premièrement, je devrais multiplier le masque avec le noyau élémentaire et ensuite la matrice multiplier le résultat par l'entrée x. Mes données d'entrée x sont composées de 100 données d'apprentissage avec 4 colonnes. J'ai 20 masques chacun d'eux a 7 couches (même que les couches comptent). Ce sont des matrices de sortie d'entrée * et je veux utiliser un de ces 20 masques dans chaque étape d'ajustement au hasard. – muradin