2015-11-22 3 views
5

Angenommen, ich möchte die Koeffizienten der kleinsten Quadrate in TensorFlow mithilfe der Lösung in geschlossener Form berechnen. Normalerweise würde ich dies tun, wie so,Caching eines berechneten Werts als Konstante in TensorFlow

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

Wo X und y TensorFlow Platzhalter sind für die Kovariaten und Zielgröße entsprechen.

Wenn ich dann Vorhersage ausführen wollte, würde ich so etwas tun,

y_pred = tf.matmul(X, beta_hat) 

Wenn ich auszuführen waren,

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

ich natürlich einen Fehler bekommen würde, dass ich nicht vorsah ein notwendiger Wert für den Platzhalter y. Ich hätte gerne die Flexibilität, beta_hat als Konstante zu behandeln, nachdem ich es berechnet habe (so dass ich keinen neuen Platzhalter für die neue Kovariatenmatrix für die Vorhersage definieren müsste). Eine Möglichkeit, dies zu erreichen ist,

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

ich mich gefragt, ob es eine elegantere Art und Weise war die Tensor als konstant zu behandeln, so dass ich weder brauche die Sitzung auszuführen und eine Konstante erhält noch einen separaten Platzhalter für eingehende erstellen Daten, die für die Vorhersage verwendet werden.

Hier ist ein Beispielcode, der die Umstände, die ich beschreibe, zeigt.

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}) 

Antwort

1

Vielleicht Gegen intuitiv, der einfachste Weg, wieder zu verwenden beta_hat als Konstante in den nachfolgenden Schritten, es zu einem tf.Variable zuzuordnen wäre:

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? (Oder ist diese Funktion dokumentiert?) –

0

mrry in der Tat eine elegante Lösung vorgelegt hat. Sie sollten in Erwägung ziehen, seine Antwort als richtig zu markieren, wenn dies tatsächlich das ist, was Sie wollen.

Ich denke jedoch, dass dies ein guter Platz ist, um zu klären, was ich als Quelle der Verwirrung über Platzhalter wahrnehme ... Dies richtet sich nicht unbedingt an die Person, die die Frage stellte, aber ich glaube, dass es sein wird relevant für viele Anfänger, die auf diese Frage stolpern ...


Platzhalter sollten wie Funktionseingaben gedacht werden. Also lassen Sie uns zuerst prüfen, wie das in Python funktioniert, und dann werde ich die entsprechende Form in Tensorflow zeigen ...

Wenn ich eine Funktion haben wollen, der die Ausgabe verschiedene Eingänge x und y gegeben berechnet, dann könnte ich tun es wie folgt ...

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

insbesondere kann ich diese Funktion mit verschiedenen Werten rufen für x und y:

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

jedoch in meinem Fall, ich kann ein fester Wert von y. In meinem Fall ist es also nicht sinnvoll, y als Argument zu übergeben. Stattdessen möchte ich meinen Wert von y in die Funktion einbauen und nur x variieren.Um das zu tun, kann ich einfach den äußeren Wert von y erfassen:

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

Nun, wenn ich g nennen, haben y den festen Wert von 3:

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

Und falls ich weiß auch, dass x ist fest, ich konnte den äußeren Wert von x erfassen:

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

Nun, wenn ichanrufen, ich rufe implizit h()=g(2)=f(2,3).

Das ist toll, aber das Problem ist, dass jedes Mal, wenn ich h aufrufen, wird es die Multiplikation wiederholen, weil es gleichbedeutend mit dem Aufruf f(2,3) ist. Damit die Leistung zu verbessern, kann ich den Ausdruck, bewerten und dann eine Funktion haben, die gerade diese vorberechneten Wert zurückgibt:

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

Egal, wie oft ich h23 nennen, die Multiplikation nur einmal (auf der Linie durchgeführt wird val = h()).

Tensorflow hat analoge Konzepte.

Wenn Sie eine Funktion haben, wo Sie beiden Eingänge variieren können, dann sollten Sie Platzhalter-Objekte für beiden Instanzen machen, und die Werte für die Funktion in einem Feed-Wörterbuch übergeben, wenn in einer Sitzung ausgeführt wird:

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})) 

wenn jedoch einer meiner Werte nicht ändert, dann kann ich es als eine konstante initialisieren direkt und eine neue Funktion mit diesem Wert „eingebacken“ erstellen:

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})) 

der entscheidende Punkt ist, ich, dass jetzt muss keinen Wert fürübergeben 10 in meinem Feed-Wörterbuch. Es ist konstant und wird in dem Ausdruck gx festgehalten.
Und falls x auch eine Konstante ist, dann sollte ich es so erklären:

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

Wie Sie sehen können, da alle meine Variablen konstant sind, ich überhaupt einen Feed-Wörterbuch nicht benötigen. Dies ist die Tensorflow Äquivalent eine Funktion ohne Argumente aufrufen, wie h().

jedoch nach wie vor, wenn ich h nennen, kann es brauchen die grafische Darstellung jedes Mal neu zu bewerten. Also habe ich zwei Möglichkeiten.

  1. Ich kann das Ergebnis in numpy berechnen, dann wickeln Sie diesen Wert mit einer Tensorflow-Konstante.
  2. kann ich die Ausgabe in tensorflow berechnen, ist es in einer Sitzung führen Sie den numpy Wert zu erhalten, und es dann in einer konstanten wickeln.

In der ersten Option, würde ich so etwas wie diese

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

tut Jetzt habe ich den Wert der Funktion außerhalb von Tensorflow vorberechnet, und dann diesen Wert als Konstante gewickelt, so dass ich verwenden können, es in anderen Tensorflow-Funktionen.

Im Gegensatz dazu würden Sie nur betrachten Option 2, wenn Ihre Funktion einig kompliziert Tensorflow intrinsics verwendet, oder wenn Ihre Funktion wirklich lange dauert, zu laufen und denken Sie sie schneller in Tensorflow zu Computer sein:

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

zu verstehen, was hier vor sich geht, daran erinnern, dass

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

Also brauche ich kein Futter dict passieren. Das Snippet sess.run(h) führt diese Multiplikation innerhalb von Tensorflow aus und gibt es als Numpy-Array zurück. Dann schließe ich diesen Wert schließlich mit einer tf.constant, so dass ich es in anderen Tensorflow-Funktionen verwenden kann.

Verwandte Themen