2017-01-21 2 views
0

Ich habe eine Schicht, die den Mittelwert der Zeitschritte berechnet und Maskierung unterstützt. Mein Problem ist, dass die Maske möglicherweise leer ist (keine gepolsterten Zeitschritte), aber ich weiß nicht, wie man beim Arbeiten mit Tensoren nach Nullen sucht.Keras - Theano - Test für Division durch Null

Ich habe ein paar Trainingsbeispiele, für die die Maske leer ist, so dass ich einen NaN-Verlust bekomme und das Programm abstürzt.

Das ist meine Schicht:

class MeanOverTime(Layer): 
    def __init__(self, **kwargs): 
     self.supports_masking = True 
     super(MeanOverTime, self).__init__(**kwargs) 

    def call(self, x, mask=None): 
     if mask is not None: 
      return K.cast(x.sum(axis=1)/mask.sum(axis=1, keepdims=True), K.floatx()) # this may result to division by zero 
     else: 
      return K.mean(x, axis=1) 

    def get_output_shape_for(self, input_shape): 
     return input_shape[0], input_shape[-1] 

    def compute_mask(self, input, input_mask=None): 
     return None 

Diese mask.sum(axis=1, keepdims=True) Null wird. Um dies zu umgehen, habe ich die input_length so erhöht, dass sie alle meine Trainingsbeispiele abdeckt, aber das ist keine Lösung. Ich habe auch versucht, einen Versuch/Ausnahme, aber das hat auch nicht funktioniert.

Antwort

0

try/except funktionieren nicht, weil all dieses Stück Code den symbolischen Tensorgraphen erstellt, der keine Ausnahme hat .. die Auswertung daher die Division durch 0 geschieht in der Funktion fit/evaluate/predict. Sie müssen die Logik/Entscheidung in den symbolischen Graphen einbeziehen.

können Sie switch(condition, then_expression, else_expression) verwenden, wenn und anderes enthalten:

def call(self, x, mask=None): 
    if mask is not None: 
     sum = mask.sum(axis=1, keepdims=True) 
     cond = K.equal(sum,0) 
     _the_other_tensor_ = .... 
     div = K.switch(cond, _the_other_tensor_ ,sum) 
     return K.cast(x.sum(axis=1)/div, K.floatx()) # this may result to division by zero 
    else: 
     return K.mean(x, axis=1) 

Oder nur clip(x, min_value, max_value) verwenden mit einer sehr kleinen Zahl epsilon Clip die Division numerisch stabil zu machen.

def call(self, x, mask=None): 
    if mask is not None: 
     sum = mask.sum(axis=1, keepdims=True) 
     div = K.clip(sum, K.epsilon, 1) 
     return K.cast(x.sum(axis=1)/div, K.floatx()) # this may result to division by zero 
    else: 
     return K.mean(x, axis=1)