Como monitorar valores de tensores nos Theano / Keras?

votos
7

Eu sei que esta pergunta foi feita de várias formas, mas eu realmente não posso encontrar qualquer resposta que eu possa entender e usar. Então, perdoe-me se esta é uma questão fundamental, porque eu sou um novato para essas ferramentas (Theano / keras)

Problema para resolver

Monitorizar variáveis ​​em Redes Neuronais (por exemplo, / / ​​esquecem valores de porta de entrada e saída em LSTM)

O que eu estou recebendo atualmente

não importa em que estágio que estou recebendo esses valores, estou ficando algo como:

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

Existe alguma maneira eu não posso controlar (por exemplo, impressão na saída padrão, gravar em um arquivo, etc) eles?

Solução possível

Parece que retornos de chamada em Keras podem fazer o trabalho, mas não quer trabalhar para mim. Estou ficando mesma coisa como acima

Meu palpite

Parece que eu estou fazendo erros muito simples.

Muito obrigado antecipadamente, todos.


ADICIONADO

Especificamente, eu estou tentando monitorar entrada / esquecer valores gating / saída em LSTM. Descobri que LSTM.step () é para calcular esses valores:

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 como é no código acima, eu tentei escrever o valor de i em um arquivo, mas ele só me deu valores como:

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

Então, eu tentei i.eval () ou i.get_value (), mas ambos não conseguiram me dar valores.

.eval () me deu esta:

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 () me deu esta:

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

Então eu recuou aquelas correntes (que linha chama que funciona ..) e tentou obter valores de todos os passos que eu encontrei, mas em vão.

Parece que estou em algumas armadilhas básicas.

Publicado 05/05/2016 em 21:51
fonte usuário
Em outras línguas...                            


3 respostas

votos
2

Eu uso a solução descrita no FAQ Keras:

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

Em detalhe:

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]

rendimentos:

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

No entanto, eu gostaria de usar a API funcional, mas eu não consigo obter o tensor real, apenas a representação simbólica. Por exemplo:

model.layers[1].output

rendimentos:

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

Eu estou faltando alguma coisa sobre a interação de Keras e Tensorflow aqui, mas eu não tenho certeza do que. Qualquer visão muito apreciada.

Respondeu 07/05/2016 em 12:32
fonte usuário

votos
1

Uma solução é criar uma versão de sua rede que é truncado na camada LSTM dos quais você deseja monitorar os valores de porta e, em seguida, substituir a camada original com uma camada de costume em que o stepfunction é modificado para retornar não apenas a camada escondida valores, mas também os valores de porta.

Por exemplo, digamos que você quiser acessar o acesso dos valores portão de uma GRU. Criar um GRU2 camada personalizada que herda tudo, desde a classe GRU, mas se adaptar a função etapa de tal forma que ele retorna uma concatenação do estados que deseja monitorar e, em seguida, leva apenas a parte que contém as ativações camada escondida anteriores ao computar os próximos ativações. ou seja:

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]

(Note-se que as únicas linhas que são adicionados no início e no fim da função).

Se você, em seguida, executar a sua rede com GRU2 com a última camada em vez de GRU (com return_sequences = true para a camada GRU2), você pode simplesmente chamar prever na sua rede, isso vai lhe dar todos os valores da camada e portões ocultos.

A mesma coisa deve funcionar para LSTM, embora você pode ter que decifrar um pouco para descobrir como armazenar todas as saídas que você quer em um vetor e recuperá-los novamente depois.

Espero que ajude!

Respondeu 23/06/2016 em 08:48
fonte usuário

votos
0

Você pode usar de Teano impressão módulo para impressão durante a execução (e não durante a definição, que é o que você está fazendo e a razão pela qual você não está recebendo valores, mas a sua definição abstrata).

Impressão

Basta usar a Printfunção. Não se esqueça de usar a saída de Printcontinuar o seu gráfico , caso contrário, a saída será desligado e impressão provavelmente será removido durante a otimização. E você vai ver nada.

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

Enredo

Um pequeno bônus que você pode desfrutar.

A classe de impressão tem um global_fnparâmetro, para substituir a chamada de retorno padrão para imprimir. Você pode fornecer sua própria função e aceder directamente aos dados, para construir um enredo por exemplo.

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 a cadeia que passou a imprimir ( '...') é armazenado no objeto de impressão em nome da propriedade message(ver função myPlottingFn). Isso é útil para a construção de multi-curvas trama automaticamente

Respondeu 06/09/2017 em 11:42
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more