2017-06-15 2 views
1

J'ai créé une fonction personnalisée appelée CustomFunc, après l'explication ici: https://www.cntk.ai/pythondocs/extend.htmlComment composer fonction personnalisée CNTK

Si je l'utilise comme suggéré par l'article, cela fonctionne:

model = cntk.user_function(CustomFunc(prev_node)) 

fonctionne ce Bien, le modèle fonctionne sans aucun problème. Mon problème est que je veux utiliser cette fonction dans un appel cntk.layers.Sequential, et dans un appel cntk.layers.Recurrence. Pour ce faire, j'ai d'une manière ou d'une autre besoin de construire la composition de ma fonction avec un autre, puis de la mettre dans l'appel Séquentiel ou Récurrence. En ce moment ce que j'utilise un certain espace réservé, ce que je fais est:

customFunToUse = cntk.user_function(CustomFunc(cntk.placeholder(), otherInputs)) 
model = cntk.layers.Sequential([cntk.layers.Dense(100), 
           customFunToUse, 
           cntk.layers.Recurrence(
           customFunToUse >> cntk.layers.LSTM(100))]) 

Mais cela ne fonctionne pas et soulève toutes sortes d'erreurs: il est parfois une erreur de segmentation, dans un autre modèle similaire est un

"ValueError: Cannot create an NDArrayView using a view shape '[? x 10]' that has unknown dimensions for any of its axes." 

d'autres fois est plutôt un

Evaluate: All nodes inside a recurrent loop must have a layout that is identical; mismatch found for nodes ... 

Notez aussi que ma fonction personnalisée ne modifie pas les dimensions d'entrée: étant donné une quantité de paramters, il retournera la même quantité et le type. Le code est le suivant:

class CustomFun(UserFunction): 
    def __init__(self, *args, otherStuff, name='CustomFun'): 
     super(CustomFun, self).__init__(list(args), name=name) 
     self.otherStuff = otherStuff 

    def forward(self, arguments, outputs=None, keep_for_backward=None, device=None, as_numpy=True): 
     return None,[x/2 for x in arguments] 

    def backward(self, state, root_gradients, variables=None, as_numpy=True): 
     #it's not important right now, just a test... 
     return root_gradient 

    def infer_outputs(self): 
     #shape, type and dynamic axes of inputs are not changed by this function 

     outputVar = [output_variable(self.inputs[idx].shape, self.inputs[idx].dtype, 
      self.inputs[idx].dynamic_axes, name='out_quantLayer') for idx in range(len(self.inputs))] 
     return outputVar 

    def serialize(self): 
     return {'otherStuff': self.otherStuff} 

    @staticmethod 
    def deserialize(inputs, name, state): 
     return CustomFun(inputs, otherStuff=state['otherStuff'], name=name) 

Répondre

1

La bonne façon serait d'écrire quelque chose comme ça def my_layer(x): @C.Function def apply(x): return cntk.user_function(CustomFunc(x)) return apply Malheureusement, cela semble être la cause de mon interpréteur Python crash. J'ai ouvert github issue 2132 à ce sujet. Je vais essayer de mettre à jour cette réponse lorsque le problème sera résolu.

Mise à jour: Il y avait une petite faute de frappe que nous n'avons pas interceptée. Il y a une résolution à la page de problème de github.