Here’s how to look inside Theano tensors — I start with a wrong way (dir()) and end with the correct way ([row for row in theano.function(, data)]).
Theano is this really pretty package for Python — it operates on top of Numpy to provide short hand and functionality useful for machine learning algorithms. I bumped into this when I was running some demo code available at deeplearning.net. The demo data used by this code is actually a Python Pickled +Gzipped version of the MNIST handwritten digit database. In this scenario, all I wanted to do was print the MNIST data after it had been already been loaded by Theano into the demo script. The data is accessible via instances of the theano.TensorVariable class.
The first attempt worked for the rows of data corresponding to the images stored as 2D arrays since Theano tensors of type matrix have a convenience method that lets one grab the data as a familiar 2D Numpy array using an undocumented get_value() method (it doesn’t appear in the API for theano.TensorVariable, but is mentioned briefly elsewhere). This convenience method disappears for the 1D arrays, since these were not constructed with a shared reference to an underlying Numpy array.
After spending a solid amount of time working away with Python’s dir(), searching for a way to coerce Theano into showing me its innards, I finally came to my senses and realized I should probably see what canonical solutions are. Completely new to Theano, and only having recently read about them — I simply wasn’t well versed enough with the notion of compiling a Theano function. Finally, peering into the loaded MNIST data came down to this …
datasets = load_data(dataset) train_set_x, train_set_y = datasets valid_set_x, valid_set_y = datasets test_set_x , test_set_y = datasets ##### -- my code begins here ... def print_set(data, name): with open("extract/" + name + ".txt", "w+") as handle: print >>handle, "# type(python)", type(data) print >>handle, "# type(theano)", data.type print >>handle, "# dimensions ", data.ndim if data.ndim == 2: print >>handle, "# rows(numpy) ", len(data.get_value()) print >>handle, "# cols(numpy) ", len(data.get_value()) for row in theano.function(, data)(): for val in row: print >>handle, "%0.3f" % val, print >>handle elif data.ndim == 1: for row in theano.function(, data)(): print >>handle, "%d" % row else: return print_set(train_set_x, "train_set_x") print_set(train_set_y, "train_set_y") print_set(valid_set_x, "valid_set_x") print_set(valid_set_y, "valid_set_y") print_set(test_set_x, "test_set_x" ) print_set(test_set_y, "test_set_y" ) return
Here, the magic is in the constructor theano.function(, data) (– Thanks: Olivier Delalleau) The great thing about working through this problem is that I should be able to extend this solution to building actual functions in Theano. The stumbling around did force me to understand more about Theano’s tensors and Theano’s compiled function graphs.