2017-04-21 6 views
1

Ich möchte überprüfen, ob ich this Problem mit Tensorflow anstelle von Pymc3 lösen kann. Die experimentelle Idee ist, dass ich ein probibalistisches System definieren werde, das einen Schaltpunkt enthält. Ich kann Sampling als eine Methode der Inferenz verwenden, aber ich begann mich zu fragen, warum ich das nicht einfach mit einem Gradientenabstieg tun konnte.tf.where Ursachen Optimierer im Tensorflow fehlschlagen

Ich entschied mich für die Gradientensuche im Tensorflow, aber es scheint, als ob Tensorflow Schwierigkeiten hat, eine Gradientensuche durchzuführen, wenn tf.where beteiligt ist.

Sie können den folgenden Code finden.

import tensorflow as tf 
import numpy as np 

x1 = np.random.randn(50)+1 
x2 = np.random.randn(50)*2 + 5 
x_all = np.hstack([x1, x2]) 
len_x = len(x_all) 
time_all = np.arange(1, len_x + 1) 

mu1 = tf.Variable(0, name="mu1", dtype=tf.float32) 
mu2 = tf.Variable(5, name = "mu2", dtype=tf.float32) 
sigma1 = tf.Variable(2, name = "sigma1", dtype=tf.float32) 
sigma2 = tf.Variable(2, name = "sigma2", dtype=tf.float32) 
tau = tf.Variable(10, name = "tau", dtype=tf.float32) 

mu = tf.where(time_all < tau, 
       tf.ones(shape=(len_x,), dtype=tf.float32) * mu1, 
       tf.ones(shape=(len_x,), dtype=tf.float32) * mu2) 
sigma = tf.where(time_all < tau, 
       tf.ones(shape=(len_x,), dtype=tf.float32) * sigma1, 
       tf.ones(shape=(len_x,), dtype=tf.float32) * sigma2) 

likelihood_arr = tf.log(tf.sqrt(1/(2*np.pi*tf.pow(sigma, 2)))) -tf.pow(x_all - mu, 2)/(2*tf.pow(sigma, 2)) 
total_likelihood = tf.reduce_sum(likelihood_arr, name="total_likelihood") 

optimizer = tf.train.RMSPropOptimizer(0.01) 
opt_task = optimizer.minimize(-total_likelihood) 
init = tf.global_variables_initializer() 

with tf.Session() as sess: 
    sess.run(init) 
    print("these variables should be trainable: {}".format([_.name for _ in tf.trainable_variables()])) 
    for step in range(10000): 
     _lik, _ = sess.run([total_likelihood, opt_task]) 
     if step % 1000 == 0: 
      variables = {_.name:_.eval() for _ in [mu1, mu2, sigma1, sigma2, tau]} 
      print("step: {}, values: {}".format(str(step).zfill(4), variables)) 

Sie werden bemerken, dass der Tau-Parameter nicht ändert, selbst wenn tensorflow sich der variabel zu sein scheint und es ist Steigung. Irgendwelche Hinweise darauf, was schief läuft? Kann das im Tensorflow berechnet werden oder brauche ich ein anderes Muster?

Antwort

3

tau wird nur im condition-Argument zu where: (tf.where(time_all < tau, ...) verwendet, das ein boolescher Tensor ist. Da die Berechnung von Gradienten nur für kontinuierliche Werte sinnvoll ist, ist der Gradient der Ausgabe in Bezug auf tau Null.

Auch ignorieren tf.where, Sie tau in der Ausdruck time_all < tau, die fast überall konstant ist, so hat eine Steigung von Null.

Aufgrund der Steigung von Null gibt es keine Möglichkeit tau mit Gradientenabstiegsmethoden zu lernen.

Je nach Problem, vielleicht statt einem harten Schalter zwischen zwei Werten, können Sie eine gewichtete Summe anstelle p*val1 + (1-p)*val2, wo p auf tau in kontinuierlicher Weise abhängt.

0

Die zugewiesene Lösung ist die richtige Antwort, aber enthält nicht die Code-Lösung für mein Problem. Das folgende Snippet macht das;

import tensorflow as tf 
import numpy as np 
import os 
import uuid 

TENSORBOARD_PATH = "/tmp/tensorboard-switchpoint" 
# tensorboard --logdir=/tmp/tensorboard-switchpoint 

x1 = np.random.randn(35)-1 
x2 = np.random.randn(35)*2 + 5 
x_all = np.hstack([x1, x2]) 
len_x = len(x_all) 
time_all = np.arange(1, len_x + 1) 

mu1 = tf.Variable(0, name="mu1", dtype=tf.float32) 
mu2 = tf.Variable(0, name = "mu2", dtype=tf.float32) 
sigma1 = tf.Variable(2, name = "sigma1", dtype=tf.float32) 
sigma2 = tf.Variable(2, name = "sigma2", dtype=tf.float32) 
tau = tf.Variable(15, name = "tau", dtype=tf.float32) 
switch = 1./(1+tf.exp(tf.pow(time_all - tau, 1))) 

mu = switch*mu1 + (1-switch)*mu2 
sigma = switch*sigma1 + (1-switch)*sigma2 

likelihood_arr = tf.log(tf.sqrt(1/(2*np.pi*tf.pow(sigma, 2)))) - tf.pow(x_all - mu, 2)/(2*tf.pow(sigma, 2)) 
total_likelihood = tf.reduce_sum(likelihood_arr, name="total_likelihood") 

optimizer = tf.train.AdamOptimizer() 
opt_task = optimizer.minimize(-total_likelihood) 
init = tf.global_variables_initializer() 

tf.summary.scalar("mu1", mu1) 
tf.summary.scalar("mu2", mu2) 
tf.summary.scalar("sigma1", sigma1) 
tf.summary.scalar("sigma2", sigma2) 
tf.summary.scalar("tau", tau) 
tf.summary.scalar("likelihood", total_likelihood) 
merged_summary_op = tf.summary.merge_all() 

with tf.Session() as sess: 
    sess.run(init) 
    print("these variables should be trainable: {}".format([_.name for _ in tf.trainable_variables()])) 
    uniq_id = os.path.join(TENSORBOARD_PATH, "switchpoint-" + uuid.uuid1().__str__()[:4]) 
    summary_writer = tf.summary.FileWriter(uniq_id, graph=tf.get_default_graph()) 
    for step in range(40000): 
     lik, opt, summary = sess.run([total_likelihood, opt_task, merged_summary_op]) 
     if step % 100 == 0: 
      variables = {_.name:_.eval() for _ in [total_likelihood]} 
      summary_writer.add_summary(summary, step) 
      print("i{}: {}".format(str(step).zfill(5), variables)) 
Verwandte Themen