Repository: lisa-lab/pylearn2

Issue:
Unable to load using monitor.push_monitor existing model with Softmax
```
      1 from pylearn2.config import yaml_parse
      2 train = yaml_parse.load(train_str)
----> 3 train.main_loop()

/home/ubuntu/git/pylearn2/pylearn2/train.pyc in main_loop(self, time_budget)
    140         """
    141         t0 = datetime.now()
--> 142         self.setup()
    143         if self.algorithm is None:
    144             self.run_callbacks_and_monitoring()

/home/ubuntu/git/pylearn2/pylearn2/train.pyc in setup(self)
    120         self.model.monitor.time_budget_exceeded = False
    121         if self.algorithm is not None:
--> 122             self.algorithm.setup(model=self.model, dataset=self.dataset)
    123         self.setup_extensions()
    124 

/home/ubuntu/git/pylearn2/pylearn2/training_algorithms/sgd.pyc in setup(self, model, dataset)
    293 
    294         cost_value = self.cost.expr(model, nested_args,
--> 295                                     ** fixed_var_descr.fixed_vars)
    296 
    297         if cost_value is not None and cost_value.name is None:

/home/ubuntu/git/pylearn2/pylearn2/costs/mlp/dropout.pyc in expr(self, model, data, **kwargs)
     87             per_example=self.per_example
     88         )
---> 89         return model.cost(Y, Y_hat)

/home/ubuntu/git/pylearn2/pylearn2/models/mlp.pyc in cost(self, Y, Y_hat)
   1082     def cost(self, Y, Y_hat):
   1083 
-> 1084         return self.layers[-1].cost(Y, Y_hat)
   1085 
   1086     @wraps(Layer.cost_matrix)

/home/ubuntu/git/pylearn2/pylearn2/models/mlp.pyc in cost(self, Y, Y_hat)
   1497     def cost(self, Y, Y_hat):
   1498 
-> 1499         log_prob_of = self._cost(Y, Y_hat).sum(axis=1)
   1500         assert log_prob_of.ndim == 1
   1501 

/home/ubuntu/git/pylearn2/pylearn2/models/mlp.pyc in _cost(self, Y, Y_hat)
   1478         # we use sum and not mean because this is really one variable per row
   1479 
-> 1480         if self._has_binary_target:
   1481             # The following code is the equivalent of accessing log_prob by the
   1482             # indices in Y, but it is written such that the computation can

AttributeError: 'Softmax' object has no attribute '_has_binary_target'
```

YAML:

```
train_str = """!obj:pylearn2.train.Train {
    dataset: &train !import '__main__ .train_set',
    model: !obj:pylearn2.monitor.push_monitor {
        model: !pkl: "fit.pkl",
        name: "old_monitor"
    },
    algorithm: !obj:pylearn2.training_algorithms.sgd.SGD {
        batch_size: 25,
        learning_rate: .01,
        learning_rule: !obj:pylearn2.training_algorithms.learning_rule.Momentum {
            init_momentum: 0.4
        },
        cost: !obj:pylearn2.costs.mlp.dropout.Dropout {
             input_include_probs: { 'h0' : .8 },
             input_scales: { 'h0' : 1.25 }
        },  
        monitor_iteration_mode : "even_shuffled_sequential",
        train_iteration_mode : "even_shuffled_sequential",
        monitoring_dataset:
            {
                'valid' : !import '__main__ .valid',
                'test'  : !import '__main__ .test',
                'train' : *train
            },
        termination_criterion: !obj:pylearn2.termination_criteria.And {
            criteria: [
                !obj:pylearn2.termination_criteria.MonitorBased {
                    channel_name: "valid_y_misclass",
                    prop_decrease: 0.20,
                    N: 10
                },
                !obj:pylearn2.termination_criteria.EpochCounter {
                    max_epochs: 10
                },
            ]
        },
    },
    extensions: [ 
        !obj:pylearn2.train_extensions.best_params.MonitorBasedSaveBest {
             channel_name: 'valid_y_misclass',
             save_path: "./fit_cont_best.pkl"
        },!obj:pylearn2.training_algorithms.learning_rule.MomentumAdjustor {
            start: 1,
            saturate: 30,
            final_momentum: 0.90
        },
    ],
    save_path: "fit_cont.pkl",
    save_freq: 1
}"""
```



Discussion:
Right, the `self._has_binary_target` attribute has been added recently, and is not present in the older model you are loading.
The easiest way to fix it is to add the following just before using it:

```
# support old pickle files
if not hasattr(self, '_has_binary_target'):
    self._has_binary_target = False
```

A better way would be to put that statement (and the other similar ones in mlp.py) in a `__setstate__` method, so these things are fixed right when the model is unpickled.

Can you check if this work, and submit a PR?
Thanks,


Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -72,7 +72,8 @@ def run(self):
     description='A machine learning library built on top of Theano.',
     license='BSD 3-clause license',
     long_description=open('README.rst').read(),
-    install_requires=['numpy>=1.5', 'theano', 'pyyaml', 'argparse'],
+    dependency_links=['git+http://github.com/Theano/Theano.git#egg=Theano'],
+    install_requires=['numpy>=1.5', 'pyyaml', 'argparse', "Theano"],
     package_data={
         '': ['*.cu', '*.cuh', '*.h'],
     },


Test patch: