2015-11-22 10 views
5

Supponiamo di voler calcolare i coefficienti dei minimi quadrati in TensorFlow utilizzando la soluzione di forma chiusa. Normalmente, vorrei farlo in questo modo,Memorizzazione nella cache di un valore calcolato come costante in TensorFlow

beta_hat = tf.matmul(
      tf.matmul(tf.matrix_inverse(tf.matmul(tf.transpose(X), X)), tf.transpose(X)), y 
) 

Dove X e y sono segnaposti tensorflow corrispondenti alle covariate e variabile di destinazione, rispettivamente.

Se dunque io volessi eseguire la previsione, vorrei fare qualcosa di simile,

y_pred = tf.matmul(X, beta_hat) 

Se dovessi eseguire,

sess.run(y_pred, feed_dict={X: data_X}) 

avrei ovviamente ottenere un errore che non mi fornisco un valore necessario per il segnaposto . Mi piacerebbe avere la flessibilità di trattare beta_hat come costante dopo averlo calcolato (in modo da non dover definire un nuovo segnaposto per la nuova matrice di covariate per la previsione). Un modo per raggiungere questo obiettivo è,

# Make it constant. 
beta_hat = sess.run(beta_hat, feed_dict={X: data_X, y: data_y}) 
y_pred = tf.matmul(X, beta_hat) 

mi chiedevo se ci fosse un modo più elegante per trattare il tensore costante in modo che io non bisogno di eseguire la sessione e ottenere una costante né creare un segnaposto separata per l'incoming dati da utilizzare per la previsione.

Ecco alcuni esempi di codice che dimostrano la circostanza che sto descrivendo.

import numpy as np 
import tensorflow as tf 


n, k = 100, 5 
X = tf.placeholder(dtype=tf.float32, shape=[None, k]) 
y = tf.placeholder(dtype=tf.float32, shape=[None, 1]) 

beta = np.random.normal(size=(k,)) 
data_X = np.random.normal(size=(n, k)) 

data_y = data_X.dot(beta) 
data_y += np.random.normal(size=data_y.shape)/3.0 
data_y = np.atleast_2d(data_y).T 

# Convert to 32-bit precision. 
data_X, data_y = np.float32(data_X), np.float32(data_y) 

# Compute the least squares solution. 
beta_hat = tf.matmul(
    tf.matmul(tf.matrix_inverse(tf.matmul(tf.transpose(X), X)), 
       tf.transpose(X)), y 
) 

# Launch the graph 
sess = tf.Session() 
sess.run(tf.initialize_all_variables()) 

print "True beta: {}".format(beta) 
print "Est. beta: {}".format(
    sess.run(beta_hat, feed_dict={X: data_X, y: data_y}).ravel() 
) 

# # This would error. 
# y_pred = tf.matmul(X, beta_hat) 
# print "Predictions:" 
# print sess.run(y_pred, feed_dict={X: data_X}) 

# Make it constant. 
beta_hat = sess.run(beta_hat, feed_dict={X: data_X, y: data_y}) 

# This will no longer error. 
y_pred = tf.matmul(X, beta_hat) 
print "Predictions:" 
print sess.run(y_pred, feed_dict={X: data_X}) 

risposta

1

Forse contro-intuitivo, il modo più semplice per riutilizzare beta_hat come una costante nei passaggi successivi sarebbe quello di assegnarlo a un tf.Variable:

n, k = 100, 5 
X = tf.placeholder(dtype=tf.float32, shape=[None, k]) 
y = tf.placeholder(dtype=tf.float32, shape=[None, 1]) 

beta = np.random.normal(size=(k,)) 
data_X = np.random.normal(size=(n, k)) 

data_y = data_X.dot(beta) 
data_y += np.random.normal(size=data_y.shape)/3.0 
data_y = np.atleast_2d(data_y).T 

# Convert to 32-bit precision. 
data_X, data_y = np.float32(data_X), np.float32(data_y) 

# Compute the least squares solution. 
beta_hat = tf.matmul(
    tf.matmul(tf.matrix_inverse(tf.matmul(tf.transpose(X), X)), 
       tf.transpose(X)), y 
) 

beta_hat_cached = tf.Variable(beta_hat) 

# Launch the graph 
sess = tf.Session() 

print "True beta: {}".format(beta) 
# Run the initializer, which computes `beta_hat` once: 
sess.run(beta_hat_cached.initializer, feed_dict={X: data_X, y: data_y}) 
# To access the value of `beta_hat`, "run" the variable to read its contents. 
print "Est. beta: {}".format(beta_hat_cached.ravel()) 

# Use the cached version to compute predictions. 
y_pred = tf.matmul(X, beta_hat_cached) 
print "Predictions:" 
print sess.run(y_pred, feed_dict={X: data_X}) 
+0

ravel == eval? (Oppure questa funzione è documentata?) –

0

mrry ha infatti presentato una soluzione elegante. Dovresti considerare di contrassegnare la sua risposta come corretta se è davvero ciò che desideri.

Tuttavia, penso che questo sia un buon posto per chiarire ciò che percepisco come fonte di confusione per i segnaposto ... Questo non è necessariamente diretto alla persona che ha posto la domanda, ma credo che sarà rilevante per molti principianti che inciampano su questa domanda ...


I segnaposto devono essere considerati come input di funzione. Quindi, prima, vediamo come funziona in Python, e poi vi mostrerò la forma equivalente in tensorflow ...

Se voglio avere una funzione che calcola la potenza indicata vari input x e y, quindi ho potuto fare in questo modo ...

def f(x,y): 
    # For example... 
    return x * y 

in particolare, posso chiamare questa funzione con diversi valori per x e y:

f(1,3) = 3 
f(1,4) = 4 
f(2,3) = 6 
f(2,4) = 8 

Tuttavia, nel mio caso particolare, io possa avere un valore fisso di . Quindi, nel mio caso, non ha senso passare y come argomento. Invece, voglio infornare il mio valore di y nella funzione, e solo variare x.Per fare questo, posso semplicemente catturare il valore esterno del y:

y = 3 
def g(x): 
    return x * y 

Ora ogni volta che chiamo g, y avrà il valore fisso di 3:

g(1) = 3 
g(2) = 6 

Allo stesso modo, se so anche che x è fisso, ho potuto cogliere il valore esterno del x:

x = 2 
def h(): 
    return g(x) 

Ora, quando chiamo h, sto implicitamente chiamando h()=g(2)=f(2,3).

Questo è ottimo, ma il problema è che ogni volta che chiamo h, si ripeterà la moltiplicazione perché equivale a chiamare f(2,3). Così per migliorare le prestazioni, posso valutare l'espressione, e quindi avere una funzione che restituisce solo questo valore precalcolate:

val = h() 
def h23(): 
    return val 

Non importa quante volte io chiamo h23, la moltiplicazione viene eseguita solo una volta (sulla linea val = h()).

Tensorflow ha concetti analoghi.

Se si vuole avere una funzione in cui è possibile variare entrambi gli ingressi, allora si dovrebbe fare oggetti segnaposto per entrambe le istanze, e passare i valori alla funzione in un dizionario di alimentazione durante l'esecuzione in una sessione:

dtype = tf.float64 
shape =() 
x = tf.placeholder(dtype, shape) 
y = tf.placeholder(dtype, shape) 
fxy = f(x,y) 
with tf.Session() as sess: 
    print(sess.run(fxy, {x:1,y:3})) 
    print(sess.run(fxy, {x:1,y:4})) 
    print(sess.run(fxy, {x:2,y:3})) 
    print(sess.run(fxy, {x:2,y:4})) 

Tuttavia, se uno dei miei valori non cambia, allora io possibile inizializzare direttamente come una costante e creare una nuova funzione con questo valore "cotto in esso":

y = tf.constant(3) 
gx = f(x, y) 
with tf.Session() as sess: 
    print(sess.run(gx, {x:1})) 
    print(sess.run(gx, {x:2})) 

Il punto chiave è che ora mi non è necessario passare un valore per y nel mio dizionario dei feed. È costante e catturato nell'espressione gx.
Allo stesso modo, se x è anche una costante, allora dovrei dichiaro così:

x = tf.constant(2) 
h = f(x,y) 
with tf.Session() as sess: 
    print(sess.run(h)) 

Come si può vedere, dal momento che tutte le mie variabili sono costanti, non ho bisogno di un dizionario di alimentazione a tutti. Questo è l'equivalente di Tensorflow di chiamare una funzione senza argomenti, come h().

Tuttavia, proprio come in precedenza, quando chiamo h, potrebbe essere necessario rivalutare il grafico ogni volta. Quindi ho due opzioni.

  1. Sono in grado di calcolare il risultato in numpy, quindi avvolgere quel valore con una costante di tensorflow.
  2. È possibile calcolare l'output in tensorflow, eseguirlo in una sessione per ottenere il valore di numpy e quindi avvolgerlo in una costante.

Nella prima opzione, vorrei fare qualcosa di simile

fxy = tf.constant(f(2,3)) 

Ora ho precalcolate il valore della funzione al di fuori di tensorflow, e poi avvolto tale valore come una costante in modo che posso usare in altre funzioni di tensorflow.

Al contrario, si potrebbe prendere in considerazione solo l'opzione 2 se la funzione usa alcune complicate intrinseci tensorflow, o se la vostra funzione impiega davvero tanto tempo a correre e si pensa che sarà più veloce al computer nella tensorflow:

with tf.Session() as sess: 
    fxy = tf.constant(sess.run(h)) 

Per Capisco cosa sta succedendo qui, ricorda che

h = f(tf.constant(1), tf.constant(3)) 

Quindi non ho bisogno di passare un feed dict. Lo snippet sess.run(h) esegue quella moltiplicazione all'interno di tensorflow e lo restituisce come una matrice Numpy. Quindi, infine, avvolgo quel valore con un file tf.constant in modo da poterlo utilizzare in altre funzioni di Tensorflow.

Problemi correlati