Repository: GPflow/GPflow

Issue:
Changing parameter to fixed requires model recompilation prior to prediction 
Error is: ValueError: Cannot feed value of shape (4,) for Tensor u'Variable:0', which has shape '(5,)'
Error happens in predict_f  - full error trace below.

Minimal working example below.
Issue on master branch as of April 24, 2016.
### Code MWE - based on simple_regression.py

```
import GPflow
import tensorflow as tf
import os
import numpy as np
def getData():
    rng = np.random.RandomState( 1 )
    N = 30
    X = rng.rand(N,1)
    Y = np.sin(12*X) + 0.66*np.cos(25*X) + rng.randn(N,1)*0.1 + 3
    return X,Y
if __name__ == '__main__':
    X,Y = getData()
    k = GPflow.kernels.Matern52(1)
    meanf = GPflow.mean_functions.Linear(1,0)
    m = GPflow.gpr.GPR(X, Y, k, meanf)
    m.likelihood.variance = 0.01
    m._compile()
    print "Here are the parameters before optimization"
    print m
    m.kern.variance.fixed = True
    #m._compile() # If we compile again the code below works
    [mu,var] = m.predict_f(X)
    print mu
    print 'done'
```
### Trace:

```
Traceback (most recent call last):
  File "/Users/mqbssaby/PrivateProjects/BranchedGP/runfile.py", line 29, in <module>
    [mu,var] = m.predict_f(X)
  File "/Users/mqbssaby/pythonlibs/GPflow/GPflow/model.py", line 82, in runnable
    return instance._session.run(graph, feed_dict=feed_dict)
  File "/Users/mqbssaby/anaconda/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 340, in run
    run_metadata_ptr)
  File "/Users/mqbssaby/anaconda/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 553, in _run
    % (np_val.shape, subfeed_t.name, str(subfeed_t.get_shape())))
ValueError: Cannot feed value of shape (4,) for Tensor u'Variable:0', which has shape '(5,)'
```



Discussion:

Resolving patch:
diff --git a/GPflow/model.py b/GPflow/model.py
--- a/GPflow/model.py
+++ b/GPflow/model.py
@@ -83,7 +83,8 @@ def __call__(self, tf_method):
         def runnable(instance, *np_args):
             graph_name = '_' + tf_method.__name__ + '_graph'
             if not hasattr(instance, graph_name):
-                instance._compile()
+                if instance._needs_recompile:
+                    instance._compile()  # ensures free_vars is up-to-date.
                 self.tf_args = [tf.placeholder(*a) for a in self.tf_arg_tuples]
                 with instance.tf_mode():
                     graph = tf_method(instance, *self.tf_args)


Test patch:
diff --git a/testing/test_autoflow.py b/testing/test_autoflow.py
--- a/testing/test_autoflow.py
+++ b/testing/test_autoflow.py
@@ -54,7 +54,9 @@ def setUp(self):
         tf.reset_default_graph()
         rng = np.random.RandomState(0)
         X, Y = rng.randn(2, 10, 1)
-        self.m = GPflow.svgp.SVGP(X, Y, kern=GPflow.kernels.Matern32(1), likelihood=GPflow.likelihoods.StudentT(), Z=X[::2].copy())
+        self.m = GPflow.svgp.SVGP(X, Y, kern=GPflow.kernels.Matern32(1),
+                                  likelihood=GPflow.likelihoods.StudentT(),
+                                  Z=X[::2].copy())
         self.Xtest = np.random.randn(100, 1)
         self.Ytest = np.random.randn(100, 1)
 
@@ -82,5 +84,26 @@ def test(self):
         mu1, var1 = self.m.predict_f(self.Xnew)
 
 
+class TestFixAndPredict(unittest.TestCase):
+    """
+    Bug #54 says that if a model parameter is fixed  between calls to predict
+    (an autoflow fn) then the second call fails. This test ensures replicates
+    that and ensures that the bugfix remains in furure.
+    """
+    def setUp(self):
+        rng = np.random.RandomState(0)
+        X, Y = rng.randn(2, 10, 1)
+        self.m = GPflow.svgp.SVGP(X, Y, kern=GPflow.kernels.Matern32(1),
+                                  likelihood=GPflow.likelihoods.StudentT(),
+                                  Z=X[::2].copy())
+        self.Xtest = np.random.randn(100, 1)
+        self.Ytest = np.random.randn(100, 1)
+
+    def test(self):
+        self.m._compile()
+        self.m.kern.variance.fixed = True
+        _, _ = self.m.predict_f(self.m.X)
+
+
 if __name__ == "__main__":
     unittest.main()