Part 8: Symbolic Regression#
import numpy as np
import sympy
import matplotlib.pyplot as plt
import hls4ml
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.metrics import roc_curve, auc, accuracy_score
from tensorflow.keras.utils import to_categorical
from sklearn.datasets import fetch_openml
QKeras installation not found, installing one...
Collecting qkeras@ git+https://github.com/fastmachinelearning/qkeras.git
Cloning https://github.com/fastmachinelearning/qkeras.git to /tmp/pip-install-odfvs9n7/qkeras_24a4b8709e744a8ea621c1a70c786954
Running command git clone --filter=blob:none --quiet https://github.com/fastmachinelearning/qkeras.git /tmp/pip-install-odfvs9n7/qkeras_24a4b8709e744a8ea621c1a70c786954
Resolved https://github.com/fastmachinelearning/qkeras.git to commit 14907441ec67a5fda2cfa3bc5e3319a7a108f9f6
Preparing metadata (setup.py): started
Preparing metadata (setup.py): finished with status 'done'
Requirement already satisfied: numpy>=1.16.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.26.4)
Requirement already satisfied: scipy>=1.4.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.15.0)
Collecting pyparser
Downloading pyparser-1.0.tar.gz (4.0 kB)
Preparing metadata (setup.py): started
Preparing metadata (setup.py): finished with status 'done'
Requirement already satisfied: setuptools>=41.0.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (75.8.0)
Requirement already satisfied: tensorflow-model-optimization>=0.2.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.7.5)
Collecting networkx>=2.1
Downloading networkx-3.4.2-py3-none-any.whl (1.7 MB)
?25l ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/1.7 MB ? eta -:--:--
━━━━━━━━━━━━━━━╸━━━━━━━━━━━━━━━━━━━━━━━━ 0.7/1.7 MB 20.0 MB/s eta 0:00:01
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.7/1.7 MB 29.2 MB/s eta 0:00:00
?25hRequirement already satisfied: keras-tuner>=1.0.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.1.3)
Requirement already satisfied: scikit-learn>=0.23.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.2.2)
Requirement already satisfied: tqdm>=4.48.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (4.67.1)
Requirement already satisfied: packaging in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (24.2)
Requirement already satisfied: tensorboard in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (2.14.1)
Requirement already satisfied: kt-legacy in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.0.5)
Requirement already satisfied: ipython in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (8.31.0)
Requirement already satisfied: requests in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (2.32.3)
Requirement already satisfied: threadpoolctl>=2.0.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from scikit-learn>=0.23.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.5.0)
Requirement already satisfied: joblib>=1.1.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from scikit-learn>=0.23.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.4.2)
Requirement already satisfied: six~=1.14 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorflow-model-optimization>=0.2.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.17.0)
Requirement already satisfied: dm-tree~=0.1.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorflow-model-optimization>=0.2.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.1.8)
Requirement already satisfied: absl-py~=1.2 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorflow-model-optimization>=0.2.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.4.0)
Collecting parse==1.6.5
Downloading parse-1.6.5.tar.gz (24 kB)
Preparing metadata (setup.py): started
Preparing metadata (setup.py): finished with status 'done'
Requirement already satisfied: pygments>=2.4.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (2.19.1)
Requirement already satisfied: jedi>=0.16 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.19.2)
Requirement already satisfied: traitlets>=5.13.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (5.14.3)
Requirement already satisfied: decorator in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (5.1.1)
Requirement already satisfied: pexpect>4.3 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (4.9.0)
Requirement already satisfied: stack_data in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.6.3)
Requirement already satisfied: typing_extensions>=4.6 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (4.12.2)
Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.0.48)
Requirement already satisfied: matplotlib-inline in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.1.7)
Requirement already satisfied: exceptiongroup in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.2.2)
Requirement already satisfied: idna<4,>=2.5 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from requests->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.10)
Requirement already satisfied: charset_normalizer<4,>=2 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from requests->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.4.1)
Requirement already satisfied: urllib3<3,>=1.21.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from requests->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (2.3.0)
Requirement already satisfied: certifi>=2017.4.17 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from requests->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (2024.12.14)
Requirement already satisfied: markdown>=2.6.8 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.6)
Requirement already satisfied: google-auth-oauthlib<1.1,>=0.5 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.0.0)
Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.7.0)
Requirement already satisfied: werkzeug>=1.0.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.1.3)
Requirement already satisfied: grpcio>=1.48.2 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (1.54.3)
Requirement already satisfied: google-auth<3,>=1.6.3 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (2.37.0)
Requirement already satisfied: protobuf in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (4.21.12)
Requirement already satisfied: pyasn1-modules>=0.2.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from google-auth<3,>=1.6.3->tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.4.1)
Requirement already satisfied: rsa<5,>=3.1.4 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from google-auth<3,>=1.6.3->tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (4.9)
Requirement already satisfied: cachetools<6.0,>=2.0.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from google-auth<3,>=1.6.3->tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (5.5.0)
Requirement already satisfied: requests-oauthlib>=0.7.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from google-auth-oauthlib<1.1,>=0.5->tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (2.0.0)
Requirement already satisfied: parso<0.9.0,>=0.8.4 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from jedi>=0.16->ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.8.4)
Requirement already satisfied: ptyprocess>=0.5 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from pexpect>4.3->ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.7.0)
Requirement already satisfied: wcwidth in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.2.13)
Requirement already satisfied: MarkupSafe>=2.1.1 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from werkzeug>=1.0.1->tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.0.2)
Requirement already satisfied: asttokens>=2.1.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from stack_data->ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.0.0)
Requirement already satisfied: pure_eval in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from stack_data->ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.2.3)
Requirement already satisfied: executing>=1.2.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from stack_data->ipython->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (2.1.0)
Requirement already satisfied: pyasn1<0.7.0,>=0.4.6 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (0.6.1)
Requirement already satisfied: oauthlib>=3.0.0 in /home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<1.1,>=0.5->tensorboard->keras-tuner>=1.0.1->qkeras@ git+https://github.com/fastmachinelearning/qkeras.git) (3.2.2)
Building wheels for collected packages: qkeras, pyparser, parse
Building wheel for qkeras (setup.py): started
Building wheel for qkeras (setup.py): finished with status 'done'
Created wheel for qkeras: filename=QKeras-0.9.0-py3-none-any.whl size=179031 sha256=d236d38dd5d9a94395dc49f98f389258bdb615a49c451353230679967c2c6c76
Stored in directory: /tmp/pip-ephem-wheel-cache-_j_1apn1/wheels/da/9e/6d/912922d9ef166e85149fc7add252aed3f4f8ae73095ce08a9d
Building wheel for pyparser (setup.py): started
Building wheel for pyparser (setup.py): finished with status 'done'
Created wheel for pyparser: filename=pyparser-1.0-py3-none-any.whl size=4950 sha256=f3d7170f009d6f1a0a08f581b30bfd1be69e95ac5880a8a915e29506439ff40d
Stored in directory: /home/runner/.cache/pip/wheels/25/87/78/ff95e8a747dc534fbd199fb3ea06d80935bc87e44567bbdb31
Building wheel for parse (setup.py): started
Building wheel for parse (setup.py): finished with status 'done'
Created wheel for parse: filename=parse-1.6.5-py3-none-any.whl size=18193 sha256=ce83427854af6811e10b6a53d536d2892ff1093be2ff2862b688f3df6529042b
Stored in directory: /home/runner/.cache/pip/wheels/3f/10/c8/5023ea72290855ee33e7bc403e1048ae238b9c2fdb549a9f51
Successfully built qkeras pyparser parse
Installing collected packages: parse, pyparser, networkx, qkeras
Successfully installed networkx-3.4.2 parse-1.6.5 pyparser-1.0 qkeras-0.9.0
QKeras installed.
2025-01-10 14:13:22.931599: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: SSE4.1 SSE4.2 AVX AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
WARNING: Failed to import handlers from recurrent.py: No module named 'torch'.
WARNING: Failed to import handlers from pooling.py: No module named 'torch'.
WARNING: Failed to import handlers from merge.py: No module named 'torch'.
WARNING: Failed to import handlers from convolution.py: No module named 'torch'.
WARNING: Failed to import handlers from reshape.py: No module named 'torch'.
WARNING: Failed to import handlers from core.py: No module named 'torch'.
/home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages/hls4ml/converters/__init__.py:28: UserWarning: WARNING: Pytorch converter is not enabled!
warnings.warn("WARNING: Pytorch converter is not enabled!", stacklevel=1)
Load the LHC jet tagging dataset#
data = fetch_openml('hls4ml_lhc_jets_hlf')
X, Y = data['data'].to_numpy(), data['target'].to_numpy()
print(data['feature_names'])
print(X.shape, Y.shape)
print(Y[:10])
LE = LabelEncoder()
Y = LE.fit_transform(Y)
Y = to_categorical(Y, 5)
Y = 2 * Y - 1
print(Y[:10])
/home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages/sklearn/datasets/_openml.py:968: FutureWarning: The default value of `parser` will change from `'liac-arff'` to `'auto'` in 1.4. You can set `parser='auto'` to silence this warning. Therefore, an `ImportError` will be raised from 1.4 if the dataset is dense and pandas is not installed. Note that the pandas parser may return different data types. See the Notes Section in fetch_openml's API doc for details.
warn(
['zlogz', 'c1_b0_mmdt', 'c1_b1_mmdt', 'c1_b2_mmdt', 'c2_b1_mmdt', 'c2_b2_mmdt', 'd2_b1_mmdt', 'd2_b2_mmdt', 'd2_a1_b1_mmdt', 'd2_a1_b2_mmdt', 'm2_b1_mmdt', 'm2_b2_mmdt', 'n2_b1_mmdt', 'n2_b2_mmdt', 'mass_mmdt', 'multiplicity']
(830000, 16) (830000,)
['g' 'w' 't' 'z' 'w' 'w' 't' 'g' 'z' 'g']
[[ 1. -1. -1. -1. -1.]
[-1. -1. -1. 1. -1.]
[-1. -1. 1. -1. -1.]
[-1. -1. -1. -1. 1.]
[-1. -1. -1. 1. -1.]
[-1. -1. -1. 1. -1.]
[-1. -1. 1. -1. -1.]
[ 1. -1. -1. -1. -1.]
[-1. -1. -1. -1. 1.]
[ 1. -1. -1. -1. -1.]]
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.5, random_state=123)
scaler = StandardScaler().fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
# PySR (or any genetic programming based SR) not happy with too many training data
X_train = X_train[:8000]
Y_train = Y_train[:8000]
print('X_train.shape: ' + str(X_train.shape))
print('Y_train.shape: ' + str(Y_train.shape))
print('X_test.shape: ' + str(X_test.shape))
print('Y_test.shape: ' + str(Y_test.shape))
X_train.shape: (8000, 16)
Y_train.shape: (8000, 5)
X_test.shape: (415000, 16)
Y_test.shape: (415000, 5)
Perform SR with PySR (if installed)#
If you want to run PySR
(a genetic programming-based symbolic regression software), please see MilesCranmer/PySR for installation and intructions.
Below is an example configuration script to run training in PySR
, where one can specify the allowed primitive functions unary_operators
binary_operators
(e.g. +
, *
, sin
) and constraints complexity_of_operators
constraints
nested_constraints
in the equation seacrhing. The training results will be stored in a .pkl
file that contains the final equations selected by the training strategy model_selection
.
We also provide an already trained PySR model sr/example.pkl
in the following sections for demonstrating the HLS implementation.
from pysr import PySRRegressor
!export JULIA_NUM_THREADS=32
model_pysr = PySRRegressor(
model_selection='accuracy',
niterations=40,
timeout_in_seconds=60 * 60 * 1,
maxsize=40,
select_k_features=6,
binary_operators=['+', '-', '*'],
unary_operators=['sin', 'sc(x)=sin(x)*cos(x)'],
complexity_of_operators={'+': 1, '-': 1, '*': 1, 'sin': 1, 'sc': 1},
constraints={'sin': 20, 'sc': 20},
nested_constraints={'sin': {'sin': 0, 'sc': 0}, 'sc': {'sin': 0, 'sc': 0}},
extra_sympy_mappings={'sc': lambda x: sympy.sin(x) * sympy.cos(x)},
loss='L2MarginLoss()', # (1 - y*y')^2
)
model_pysr.fit(X_train, Y_train)
/home/runner/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages/pysr/sr.py:1346: UserWarning: Note: it looks like you are running in Jupyter. The progress bar will be turned off.
warnings.warn(
Using features ['x2' 'x3' 'x4' 'x11' 'x14' 'x15']
Compiling Julia backend...
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
Cell In[5], line 1
----> 1 model_pysr.fit(X_train, Y_train)
File ~/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages/pysr/sr.py:1970, in PySRRegressor.fit(self, X, y, Xresampled, weights, variable_names, X_units, y_units)
1967 self._checkpoint()
1969 # Perform the search:
-> 1970 self._run(X, y, mutated_params, weights=weights, seed=seed)
1972 # Then, after fit, we save again, so the pickle file contains
1973 # the equations:
1974 if not self.temp_equation_file:
File ~/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages/pysr/sr.py:1625, in PySRRegressor._run(self, X, y, mutated_params, weights, seed)
1622 if not already_ran and update_verbosity != 0:
1623 print("Compiling Julia backend...")
-> 1625 Main = init_julia(self.julia_project, julia_kwargs=julia_kwargs)
1627 if cluster_manager is not None:
1628 cluster_manager = _load_cluster_manager(Main, cluster_manager)
File ~/miniconda3/envs/hls4ml-tutorial/lib/python3.10/site-packages/pysr/julia_helpers.py:198, in init_julia(julia_project, quiet, julia_kwargs, return_aux)
193 raise FileNotFoundError(
194 f"Julia is not installed in your PATH. Please install Julia and add it to your PATH.\n\nCurrent PATH: {env_path}",
195 )
197 if not info.is_pycall_built():
--> 198 raise ImportError(_import_error())
200 from julia.core import Julia
202 try:
ImportError:
Required dependencies are not installed or built. Run the following command in your terminal:
python3 -m pysr install
Prepare symbolic expressions in strings first#
We provide a trained model for the HLS demonstration.
If you have PySR
installed, you can directly load the trained expressions from the output file sr/example.pkl
.
PySR
allows custom functions to be defined, such as sc(x):=sin(x)*cos(x) in this example, they need to be re-defined through extra_sympy_mappings
and a new sympy
class when retrieving the equations for evaluation.
from pysr import PySRRegressor
model_pysr = PySRRegressor.from_file('sr/example.pkl')
with sympy.evaluate(True):
for i in range(5):
print('Tagger {} = '.format(i) + str(model_pysr.sympy()[i]) + '\n------------------------------------------')
# Re-write custom operator defined from PySR config: sc(x) = sin(x)*cos(x)
model_pysr.set_params(extra_sympy_mappings={"sc": lambda x: sympy.sin(x) * sympy.cos(x)})
model_pysr.refresh()
class sc(sympy.Function):
pass
There are two options for evaluating math functions in hls4ml
, one is using the standard HLS math library (func
), another one is using approximation with user-defined lookup tables (func_lut
) for resources saving. We will define the lookup tables (table range and size) for func_lut
later.
We have the equations in the sympy
format, now convert them into strings: expr
for using the standard functions and expr_lut
for using the approximation with lookup tables. We will re-parse expr
and expr_lut
from strings in sympy
format for the hls4ml
converter.
expr = []
expr_lut = []
for i in range(5):
expr.append(str(model_pysr.sympy()[i]))
expr_lut.append(expr[i].replace("sin", "sin_lut").replace("cos", "cos_lut"))
If you don’t have PySR installed, you can also write your expressions directly in strings and parse in sympy
format, which can then be fed to hls4ml
converter. Here again, expr
for using standard math library, expr_lut
for using approximation with lookup tables.
# Expressions from 'sr/example.pkl'
# Expressions that will use Vivado math library
expr = [
'-0.1630426*(sin(-0.75052315)*cos(-0.75052315) - 0.84283006)*sin(2*x14 - 1.03665108)*cos(2*x14 - 1.03665108) - sin(x14 - (0.9237657 - 0.11933863*x3)*(-x15 + 2*x2 - 0.3817056) + 1.761264957)',
'(-(0.5822144*sin(0.83811*x14)*cos(0.83811*x14) - 0.5324657)*(sin(0.3923645*x2)*cos(0.3923645*x2) - 0.63548696) + sin(x14 - 0.3923645*x15 + x3 + 0.51168373)*cos(x14 - 0.3923645*x15 + x3 + 0.51168373))*(0.561041303633489*sin(x15) - 0.47277835) - 0.84055585',
'0.49239117*(sin(x3)*cos(x3) + sin(x15 + 0.76784414*x3)*cos(x15 + 0.76784414*x3))*(sin(-0.13417026)*cos(-0.13417026) + sin(0.5180547)*cos(0.5180547) + sin(x2)*cos(x2)) - sin(x14 + 0.25715914*x15*x3 - x2 - x3 + 0.66443527)',
'0.41071504*(0.9298677 - sin(0.59376544*x15))*(sin(x14)*cos(x14) + 5.2546763*sin(0.71913457 - x3)*cos(0.71913457 - x3))*(-sin(2*x3)*cos(2*x3) + sin(5.2546763*x14 + x3 + 0.77032656)*cos(5.2546763*x14 + x3 + 0.77032656) + 0.32492808) - 0.863786752431664',
'(1.0745832 - sin(-x14 - 0.4094719)*cos(-x14 - 0.4094719))*(-0.15737492*x15 - sin(x14 - 4.2594776)*cos(x14 - 4.2594776) + sin(3*x14 - x3*(x14 - 4.1772995) - x3 + 3.087878)*cos(3*x14 - x3*(x14 - 4.1772995) - x3 + 3.087878) - 0.690204005690814)',
]
# Expressions that will use look-up table approximated math functions
expr_lut = []
for i in range(len(expr)):
expr_lut.append(expr[i].replace("sin", "sin_lut").replace("cos", "cos_lut"))
Then parse the strings to sympy expressions#
Define the lookup tables for approximating math functions. The table range and size can be customized for each function to be approximated, they depend on how much precision can be compromised to save more resources.
from hls4ml.utils.symbolic_utils import init_pysr_lut_functions
# For functions approximated with look-up table, define the table range and size
function_definitions = [
'sin_lut(x) = math_lut(sin, x, N=256, range_start=-8, range_end=8)',
'cos_lut(x) = math_lut(cos, x, N=256, range_start=-8, range_end=8)',
]
init_pysr_lut_functions(init_defaults=True, function_definitions=function_definitions)
lut_functions = {
'sin_lut': {'math_func': 'sin', 'range_start': -8, 'range_end': 8, 'table_size': 256},
'cos_lut': {'math_func': 'cos', 'range_start': -8, 'range_end': 8, 'table_size': 256},
}
Parse expr
and expr_lut
to sympy expressions.
# Use sympy to parse strings into sympy expressions
for i in range(len(expr)):
print('expr =\n' + expr[i])
print("----------------------------------------")
print('expr_LUT =\n' + expr_lut[i])
print("========================================")
expr[i] = sympy.parsing.sympy_parser.parse_expr(expr[i])
expr_lut[i] = sympy.parsing.sympy_parser.parse_expr(expr_lut[i])
Use hls4ml.converters.convert_from_symbolic_expression
to convert sympy expressions and compile.
# Use hls4ml to convert sympy expressions into HLS model
hls_model = hls4ml.converters.convert_from_symbolic_expression(
expr, n_symbols=16, output_dir='my-hls-test', precision='ap_fixed<16,6>', part='xcvu9p-flga2577-2-e'
)
hls_model.write()
hls_model.compile()
hls_model_lut = hls4ml.converters.convert_from_symbolic_expression(
expr_lut,
n_symbols=16,
output_dir='my-hls-test-lut',
precision='ap_fixed<16,6>',
part='xcvu9p-flga2577-2-e',
lut_functions=lut_functions,
)
hls_model_lut.write()
hls_model_lut.compile()
Compare outputs: PySR vs HLS vs HLS(LUT)#
test_vector = np.random.rand(1, 16) * 4 - 2
# print(model_pysr.predict(test_vector))
print(hls_model.predict(test_vector))
print(hls_model_lut.predict(test_vector))
Compare performance on the dataset#
# Y_pysr = model_pysr.predict(X_test)
Y_hls = hls_model.predict(X_test)
Y_hls_lut = hls_model_lut.predict(X_test)
# auc_pysr=[]
auc_hls = []
auc_hls_lut = []
for x, label in enumerate(LE.classes_):
# fpr_pysr, tpr_pysr, _ = roc_curve(Y_test[:, x], Y_pysr[:, x])
fpr_hls, tpr_hls, _ = roc_curve(Y_test[:, x], Y_hls[:, x])
fpr_hls_lut, tpr_hls_lut, _ = roc_curve(Y_test[:, x], Y_hls_lut[:, x])
# auc_pysr.append(auc(fpr_pysr, tpr_pysr))
auc_hls.append(auc(fpr_hls, tpr_hls))
auc_hls_lut.append(auc(fpr_hls_lut, tpr_hls_lut))
# print('PySR acc = {0:.3f}'.format(accuracy_score(np.argmax(Y_test, axis=1), np.argmax(Y_pysr, axis=1))))
# print('PySR auc = {0:.3f},{1:.3f},{2:.3f},{3:.3f},{4:.3f}'.format(auc_pysr[0],auc_pysr[1],auc_pysr[2],auc_pysr[3],auc_pysr[4]))
print('HLS acc = {0:.3f}'.format(accuracy_score(np.argmax(Y_test, axis=1), np.argmax(Y_hls, axis=1))))
print(
'HLS auc = {0:.3f},{1:.3f},{2:.3f},{3:.3f},{4:.3f}'.format(
auc_hls[0], auc_hls[1], auc_hls[2], auc_hls[3], auc_hls[4]
)
)
print('HLS_LUT acc = {0:.3f}'.format(accuracy_score(np.argmax(Y_test, axis=1), np.argmax(Y_hls_lut, axis=1))))
print(
'HLS_LUT auc = {0:.3f},{1:.3f},{2:.3f},{3:.3f},{4:.3f}'.format(
auc_hls_lut[0], auc_hls_lut[1], auc_hls_lut[2], auc_hls_lut[3], auc_hls_lut[4]
)
)
def plot_roc(y_test, y_pred, labels, model):
color = ['blue', 'orange', 'green', 'red', 'purple']
for x, label in enumerate(labels):
fpr, tpr, _ = roc_curve(y_test[:, x], y_pred[:, x])
if model == 'pysr':
plt.plot(
tpr,
fpr,
label='{0}, PySR, AUC = {1:.1f}'.format(label, auc(fpr, tpr) * 100.0),
linestyle='solid',
color=color[x],
lw=1.5,
)
if model == 'hls':
plt.plot(
tpr,
fpr,
label='{0}, HLS, AUC = {1:.1f}'.format(label, auc(fpr, tpr) * 100.0),
linestyle='dotted',
color=color[x],
lw=1.5,
)
if model == 'hls_lut':
plt.plot(
tpr,
fpr,
label='{0}, HLS LUT, AUC = {1:.1f}'.format(label, auc(fpr, tpr) * 100.0),
linestyle='None',
color=color[x],
lw=1,
marker='o',
ms=1,
)
plt.semilogy()
plt.xlabel('True positive rate', size=15, loc='right')
plt.ylabel('False positive rate', size=15, loc='top')
plt.tick_params(axis='both', which='major', direction='in', length=6, width=1.2, labelsize=12, right=True, top=True)
plt.tick_params(axis='both', which='minor', direction='in', length=2, width=1, labelsize=12, right=True, top=True)
plt.xlim(0, 1)
plt.ylim(0.001, 1)
plt.grid(True)
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5), fontsize=12)
plt.figure(figsize=(15, 15))
axes = plt.subplot(2, 2, 1)
# plot_roc(Y_test, Y_pysr, LE.classes_, 'pysr')
plot_roc(Y_test, Y_hls, LE.classes_, 'hls')
plot_roc(Y_test, Y_hls_lut, LE.classes_, 'hls_lut')
Run synthesis from command line#
!source ${XILINX_VITIS}/settings64.sh
!vitis_hls -f build_prj.tcl "reset=1 synth=1 csim=0 cosim=0 validation=0 export=0 vsynth=0"
!cat my-hls-test/myproject_prj/solution1/syn/report/myproject_csynth.rpt