2016-05-05 45 views
6

So che questa domanda è stata posta in varie forme, ma non riesco a trovare alcuna risposta che riesca a capire e utilizzare. Quindi, mi perdoni se questa è una domanda fondamentale, perche' sono un novizio di questi strumenti (Theano/keras)Come monitorare i valori del tensore in Theano/Keras?

problema da risolvere

Supervisione delle variabili nel Reti Neurali (ad esempio ingresso/dimenticare/valori porta di uscita in LSTM)

Quello che sto attualmente ricevendo

non importa in quale fase sto ottenendo quei valori, sto ottenendo qualcosa di simile:

Elemwise{mul,no_inplace}.0 
Elemwise{mul,no_inplace}.0 
[for{cpu,scan_fn}.2, Subtensor{int64::}.0, Subtensor{int64::}.0] 
[for{cpu,scan_fn}.2, Subtensor{int64::}.0, Subtensor{int64::}.0] 
Subtensor{int64}.0 
Subtensor{int64}.0 

C'è un modo che non posso monitorare (ad es. stampare su stdout, scrivere su un file, ecc.)?

Possibile soluzione

Sembra come callback in Keras può fare il lavoro, ma non funziona neanche per me. Sto diventando stessa cosa come sopra

mia ipotesi

sembra che io sto facendo errori molto semplici.

Grazie mille in anticipo, a tutti.


AGGIUNTO

In particolare, sto cercando di monitorare input/dimenticare valori gating/uscita in LSTM. ho scoperto che LSTM.step() è per calcolare questi valori:

def step(self, x, states): 
    h_tm1 = states[0] # hidden state of the previous time step 
    c_tm1 = states[1] # cell state from the previous time step 
    B_U = states[2]  # dropout matrices for recurrent units? 
    B_W = states[3]  # dropout matrices for input units? 

    if self.consume_less == 'cpu':        # just cut x into 4 pieces in columns 
     x_i = x[:, :self.output_dim] 
     x_f = x[:, self.output_dim: 2 * self.output_dim] 
     x_c = x[:, 2 * self.output_dim: 3 * self.output_dim] 
     x_o = x[:, 3 * self.output_dim:] 
    else: 
     x_i = K.dot(x * B_W[0], self.W_i) + self.b_i 
     x_f = K.dot(x * B_W[1], self.W_f) + self.b_f 
     x_c = K.dot(x * B_W[2], self.W_c) + self.b_c 
     x_o = K.dot(x * B_W[3], self.W_o) + self.b_o 

    i = self.inner_activation(x_i + K.dot(h_tm1 * B_U[0], self.U_i)) 
    f = self.inner_activation(x_f + K.dot(h_tm1 * B_U[1], self.U_f)) 
    c = f * c_tm1 + i * self.activation(x_c + K.dot(h_tm1 * B_U[2], self.U_c)) 
    o = self.inner_activation(x_o + K.dot(h_tm1 * B_U[3], self.U_o)) 

    with open("test_visualization.txt", "a") as myfile: 
     myfile.write(str(i)+"\n") 

    h = o * self.activation(c) 
    return h, [h, c] 

E come è nel codice di cui sopra, ho tentato di scrivere il valore di i in un file, ma ha dato solo a me valori come:

Elemwise{mul,no_inplace}.0 
[for{cpu,scan_fn}.2, Subtensor{int64::}.0, Subtensor{int64::}.0] 
Subtensor{int64}.0 

Così ho provato i.eval() o i.get_value(), ma entrambi non sono riusciti a darmi valori.

.eval() mi ha dato questo:

theano.gof.fg.MissingInputError: An input of the graph, used to compute Subtensor{::, :int64:}(<TensorType(float32, matrix)>, Constant{10}), was not provided and not given a value.Use the Theano flag exception_verbosity='high',for more information on this error. 

e .get_value() mi ha dato questo:

AttributeError: 'TensorVariable' object has no attribute 'get_value' 

Così ho fatto marcia indietro quelle catene (che le chiamate di linea che funzioni ..) e ho cercato di ottenere valori ad ogni passo che ho trovato, ma invano.

Mi sento come se fossi in alcune insidie ​​di base.

+0

Come si ottengono i valori? Includi il tuo codice, sembra che tu stia stampando le variabili simboliche e non i loro valori. –

+0

Grazie mille per la tua risposta veloce @MatiasValdenegro. Ho aggiornato la mia domanda sopra con codici e messaggi di errore. – totuta

risposta

1

Io uso la soluzione descritta nella FAQ Keras:

http://keras.io/getting-started/faq/#how-can-i-visualize-the-output-of-an-intermediate-layer

In dettaglio:

from keras import backend as K 

intermediate_tensor_function = K.function([model.layers[0].input],[model.layers[layer_of_interest].output]) 
intermediate_tensor = intermediate_tensor_function([thisInput])[0] 

rendimenti:

array([[ 3., 17.]], dtype=float32) 

Tuttavia mi piacerebbe utilizzare la API funzionale ma non riesco a ottenere il tensore reale, solo il simbolico rappresentativo ionico. Per esempio:

model.layers[1].output 

rendimenti:

<tf.Tensor 'add:0' shape=(?, 2) dtype=float32> 

mi manca qualcosa circa l'interazione di Keras e tensorflow qui, ma non sono sicuro che cosa. Qualche idea molto apprezzata.

1

Una soluzione è creare una versione della rete che viene troncata nel livello LSTM di cui si desidera monitorare i valori di porta e quindi sostituire il livello originale con un livello personalizzato in cui la funzione di passaggio viene modificata per restituire non solo i valori del livello nascosto, ma anche i valori del gate.

Ad esempio, si supponga di voler accedere all'accesso ai valori di porta di un GRU. Creare un layer personalizzato GRU2 che erediti tutto dalla classe GRU, ma adattare la funzione step in modo tale da restituire una concatenazione degli stati che si desidera monitorare e quindi prendere solo la parte contenente le attivazioni precedenti del layer nascosto quando si calcolano le successive attivazioni. I.e:

def step(self, x, states): 

    # get prev hidden layer from input that is concatenation of 
    # prev hidden layer + reset gate + update gate 
    x = x[:self.output_dim, :] 


    ############################################### 
    # This is the original code from the GRU layer 
    # 

    h_tm1 = states[0] # previous memory 
    B_U = states[1] # dropout matrices for recurrent units 
    B_W = states[2] 

    if self.consume_less == 'gpu': 

     matrix_x = K.dot(x * B_W[0], self.W) + self.b 
     matrix_inner = K.dot(h_tm1 * B_U[0], self.U[:, :2 * self.output_dim]) 

     x_z = matrix_x[:, :self.output_dim] 
     x_r = matrix_x[:, self.output_dim: 2 * self.output_dim] 
     inner_z = matrix_inner[:, :self.output_dim] 
     inner_r = matrix_inner[:, self.output_dim: 2 * self.output_dim] 

     z = self.inner_activation(x_z + inner_z) 
     r = self.inner_activation(x_r + inner_r) 

     x_h = matrix_x[:, 2 * self.output_dim:] 
     inner_h = K.dot(r * h_tm1 * B_U[0], self.U[:, 2 * self.output_dim:]) 
     hh = self.activation(x_h + inner_h) 
    else: 
     if self.consume_less == 'cpu': 
      x_z = x[:, :self.output_dim] 
      x_r = x[:, self.output_dim: 2 * self.output_dim] 
      x_h = x[:, 2 * self.output_dim:] 
     elif self.consume_less == 'mem': 
      x_z = K.dot(x * B_W[0], self.W_z) + self.b_z 
      x_r = K.dot(x * B_W[1], self.W_r) + self.b_r 
      x_h = K.dot(x * B_W[2], self.W_h) + self.b_h 
     else: 
      raise Exception('Unknown `consume_less` mode.') 
     z = self.inner_activation(x_z + K.dot(h_tm1 * B_U[0], self.U_z)) 
     r = self.inner_activation(x_r + K.dot(h_tm1 * B_U[1], self.U_r)) 

     hh = self.activation(x_h + K.dot(r * h_tm1 * B_U[2], self.U_h)) 
    h = z * h_tm1 + (1 - z) * hh 

    # 
    # End of original code 
    ########################################################### 


    # concatenate states you want to monitor, in this case the 
    # hidden layer activations and gates z and r 
    all = K.concatenate([h, z, r]) 

    # return everything 
    return all, [h] 

(notare che le sole righe che ho aggiunto sono all'inizio e alla fine della funzione).

Se si esegue la rete con GRU2 come ultimo livello anziché GRU (con return_sequences = True per il livello GRU2), è possibile chiamare solo predire sulla rete, questo fornirà tutti i valori nascosti di livello e porta.

La stessa cosa dovrebbe funzionare per LSTM, anche se potrebbe essere necessario un po 'di puzzle per capire come memorizzare tutte le uscite desiderate in un vettore e recuperarle di nuovo in seguito.

Spero che questo aiuti!

0

È possibile utilizzare il modulo di Theano printing per la stampa durante l'esecuzione (e non in fase di definizione, che è quello che si sta facendo e il motivo per cui non stai ricevendo i valori, ma la loro definizione astratta).

Stampa

basta usare la funzione di Print. Non dimenticare di utilizzare l'output di Print per continuare il grafico, altrimenti l'output verrà disconnesso e la stampa verrà probabilmente rimossa durante l'ottimizzazione. E non vedrai nulla.

from keras import backend as K 
from theano.printing import Print 

def someLossFunction(x, ref): 
    loss = K.square(x - ref) 
    loss = Print('Loss tensor (before sum)')(loss) 
    loss = K.sum(loss) 
    loss = Print('Loss scalar (after sum)')(loss) 
    return loss 

Trama

Un piccolo bonus si può godere.

La classe Print ha un parametro global_fn, per sovrascrivere il callback predefinito da stampare. È possibile fornire la propria funzione e accedere direttamente ai dati, per esempio per costruire una trama.

from keras import backend as K 
from theano.printing import Print 
import matplotlib.pyplot as plt 

curve = [] 

# the callback function 
def myPlottingFn(printObj, data): 
    global curve 
    # Store scalar data 
    curve.append(data) 

    # Plot it 
    fig, ax = plt.subplots() 
    ax.plot(curve, label=printObj.message) 
    ax.legend(loc='best') 
    plt.show() 

def someLossFunction(x, ref): 
    loss = K.sum(K.square(x - ref)) 
    # Callback is defined line below 
    loss = Print('Loss scalar (after sum)', global_fn=myplottingFn)(loss) 
    return loss 

BTW la stringa passata per la stampa ('...') viene memorizzato nell'oggetto di stampa in nome della proprietà message (vedi funzione myPlottingFn). Questo è utile per la creazione automatica del grafico a più curve

Problemi correlati