Skip to content

Theano - A Trivial Theano Expression

Let’s start with the most fundamental task in Theano: defining and evaluating a simple mathematical expression. We’ll add two scalar numbers, c = a + b.

In standard Python, c = a + b would immediately compute the sum if a and b have values. In Theano, the process is different because we first define the computation symbolically and then compile it for execution.

First, import the necessary Theano modules. It’s conventional to import theano.tensor with an alias like tt.

import theano
import theano.tensor as tt
import numpy as np # We'll need numpy for input data later

Declare symbolic variables a and b. These are placeholders that represent the type of data (e.g., scalar, vector, matrix) and its data type (e.g., float64, int32) but don’t hold actual values yet. We use tt.dscalar() for double-precision floating-point scalars.

# Declare 'a' as a symbolic scalar (double precision float)
a = tt.dscalar('a') # 'a' is an optional name for debugging
# Declare 'b' as another symbolic scalar
b = tt.dscalar('b')
# Check their types
print(f"Type of 'a': {type(a)}")
print(f"Theano type of 'a': {a.type}")
# Output will show they are Theano TensorVariables of type float64 scalar

At this stage, a and b are just nodes in a future computational graph.

Now, define the expression using the symbolic variables. This builds the computational graph.

# Define 'c' as the symbolic sum of 'a' and 'b'
c = a + b
# 'c' is now also a symbolic variable representing the addition operation
print(f"\nType of 'c': {type(c)}")
print(f"Theano type of 'c': {c.type}")
# Output will show 'c' is also a TensorVariable resulting from the addition

Crucially, no addition is performed yet. We have only defined the relationship c = a + b symbolically.

To actually compute the sum, we need to compile this symbolic graph into an executable function using theano.function. This function takes symbolic inputs and returns symbolic outputs.

# Compile the function
# inputs: A list of symbolic variables that are inputs to the expression ([a, b])
# outputs: A list of symbolic variables that are the results ([c])
add_scalars = theano.function(inputs=[a, b], outputs=c)
print(f"\nCompiled function type: {type(add_scalars)}")
# Output: <class 'theano.compile.function_module.Function'>

Theano performs optimizations during this compilation step.

5. Invoke the Function with Concrete Values

Section titled “5. Invoke the Function with Concrete Values”

Now we can call the compiled function add_scalars with actual numerical values for a and b. Theano functions typically accept standard Python numbers or NumPy arrays.

# Call the function with concrete values for 'a' and 'b'
result = add_scalars(3.5, 5.5)
# The function executes the compiled graph and returns the numerical result
print(f"\nResult of 3.5 + 5.5: {result}")
print(f"Type of result: {type(result)}")
# You can call it again with different values
result2 = add_scalars(10.0, -2.0)
print(f"Result of 10.0 + (-2.0): {result2}")

The output result will be 9.0. Note that Theano functions often return NumPy types (like numpy.ndarray even for scalars) by default.

import theano
import theano.tensor as tt
import numpy as np
# 1. Declare symbolic variables (placeholders)
a = tt.dscalar('a') # double precision scalar
b = tt.dscalar('b') # double precision scalar
# 2. Define the symbolic expression (build the graph)
c = a + b
# 3. Compile the expression into an executable function
# Specify inputs [a, b] and output [c]
add_scalars = theano.function(inputs=[a, b], outputs=c)
# 4. Invoke the compiled function with concrete numerical data
value1 = 3.5
value2 = 5.5
result = add_scalars(value1, value2)
# 5. Print the result
print(f"Symbolic expression defined: c = a + b")
print(f"Compiled function: {add_scalars}")
print(f"Executing with a={value1}, b={value2}")
print(f"Result (c): {result}")
print(f"Result type: {type(result)}")
# Example with different values
result2 = add_scalars(100, 200)
print(f"\nExecuting with a=100, b=200")
print(f"Result (c): {result2}")

This simple example illustrates the core workflow of Theano: define symbolically -> compile -> execute with data. This separation allows Theano to perform significant optimizations before running any calculations.