# Converting a model to SymPy

by: Kevin Broløs & Meera Machado

(Feyn version 2.0 or newer)

Feyn models are, in truth, mathematical expressions represented as directed graphs. We can use `SymPy`

to convert these graph representations to symbolic mathematical expressions. Specifically, models can be converted to `SymPy`

objects for further manipulation or processing: executing them as equations, printing them in `LaTeX`

, or just implementing them in any environment following the equation.

The only limitation is that we don't currently support exporting categorical registers to an executable function, so for models with categories, you'll only have an expression for understanding purposes.

## Let's first generate a dataset and initialize a QLattice

```
import feyn
import numpy as np
import pandas as pd
# Generate a dataset and put it into a dataframe
np.random.seed(42)
X = np.random.normal(size=100)
y = np.exp(X)
data = pd.DataFrame(X, columns=['X'])
data['y'] = y
# Initialize and reset QLattice
ql = feyn.connect_qlattice()
ql.reset(random_seed=666)
```

## Sample and fit models real quick

We run the `QLattice`

for just 2 epochs, and convert the best model to a mathematical expression.

```
models = ql.auto_run(data, 'y', kind='regression', n_epochs=2)
# Take the best model
model = models[0]
model
```

The model maps the input $X$ to the output $y$ through an exponential function, just like the generated data.

## Convert to SymPy

Let's see how the `SymPy`

expression looks converted to `LaTeX`

:

```
sympy_model = model.sympify(signif=3)
sympy_model.as_expr()
```

$\displaystyle 1.0e^{1.0X} - 0.00306$

The parameter **signif** specifies the number of significant digits in the expression's coefficients.

## Let's try it for classification

For the sake of simplicity, we create a classification task by setting a boundary on the $y$ values.

```
# Boundary at the median
data['y'] = np.where(data['y'] > 0.88, 1, 0)
# Reset QLattice
ql.reset(random_seed=666)
# Run QLattice for classification
models = ql.auto_run(data, 'y', kind='classification', n_epochs=2)
# Best model
model = models[0]
model
```

Let's see how the `SymPy`

expression looks converted to `LaTeX`

:

```
sympy_model = model.sympify(symbolic_lr=True, include_weights=False)
sympy_model.as_expr()
```

$\displaystyle \frac{1}{1 + e^{-\tanh{(X + e^X)}}}$

In a classification problem, the mathematical expression in wrapped in a logistic function, as clearly seen above. Setting the parameter **symbolic_lr** to **True** makes the logistic function explicit. In addition, by setting **include_weights** to **False** the coefficients are not displayed, which can make the mathematical expression cleaner.

## What to do with the SymPy object

You can check out their documentation on how to use it if you don't already know how. It works automatically by pretty printing in unicode terminals and `IPython`

environments.

You can also use this for portability of final `Feyn`

graphs, as you don't need the `Python`

runtime to execute a simple mathematical equation. So you can take the output of these functions and port to `R`

, `STATA`

, `JavaScript`

, or even `Excel`

if you want to.