This library provides differentiable computation in PyTorch for the signature-PDE-kernel both on CPU and GPU. Automatic differentiation is done efficiently by solving a second "adjoint" PDE so without backpropagating through the PDE solver.
This allows to build state-of-the-art kernel-methods such as Support Vector Machines or Gaussian Processes for high-dimensional, irregularly-sampled, multivariate time series.
pip install git+https://github.com/crispitagorico/sigkernel.git
Requires PyTorch >=1.6.0, Numba >= 0.50 and Cython >= 0.29.
The library automatically detects and uses available GPU acceleration:
Automatically detected when PyTorch with CUDA is installed. Supports paths up to 1024 points per dimension.
Automatically detected on M1/M2/M3 Macs with PyTorch >= 1.12. No size limits. Move tensors to MPS device:
X = X.to('mps') Y = Y.to('mps')
The library automatically selects: CUDA (fastest for large paths) > MPS (good performance on Apple Silicon) > CPU (fallback via Cython).
import torch import sigkernel # Specify the static kernel (for linear kernel use sigkernel.LinearKernel()) static_kernel = sigkernel.RBFKernel(sigma=0.5) # Specify dyadic order for PDE solver (int > 0, default 0, the higher the more accurate but slower) dyadic_order = 1 # Specify maximum batch size of computation; if memory is a concern try reducing max_batch, default=100 max_batch = 100 # Initialize the corresponding signature kernel signature_kernel = sigkernel.SigKernel(static_kernel, dyadic_order) # Synthetic data batch, len_x, len_y, dim = 5, 10, 20, 2 # Use 'cuda', 'mps', or 'cpu' depending on available hardware device = 'cuda' if torch.cuda.is_available() else ('mps' if torch.backends.mps.is_available() else 'cpu') X = torch.rand((batch,len_x,dim), dtype=torch.float64, device=device) # shape (batch,len_x,dim) Y = torch.rand((batch,len_y,dim), dtype=torch.float64, device=device) # shape (batch,len_y,dim) Z = torch.rand((batch,len_x,dim), dtype=torch.float64, device=device) # shape (batch,len_y,dim) # Compute signature kernel "batch-wise" (i.e. k(x_1,y_1),...,k(x_batch, y_batch)) K = signature_kernel.compute_kernel(X,Y,max_batch) # Compute signature kernel Gram matrix (i.e. k(x_i,y_j) for i,j=1,...,batch), also works for different batch_x != batch_y) G = signature_kernel.compute_Gram(X,Y,sym=False,max_batch) # Compute MMD distance between samples x ~ X and samples y ~ Y, where X,Y are two distributions on path space... mmd = signature_kernel.compute_mmd(X,Y,max_batch) # ... and to backpropagate through the MMD distance simply call .backward(), like any other PyTorch loss function mmd.backward() # Compute scoring rule between X and a sample path y, i.e. S_sig(X,y) = E[k(X,X)] - 2E[k(X,y] ... y = Y[0] sr = signature_kernel.compute_scoring_rule(X,y,max_batch) # ... and expected scoring rule between X and Y, i.e. S(X,Y) = E_Y[S_sig(X,y)] esr = signature_kernel.compute_expected_scoring_rule(X,Y,max_batch) # Sig CHSIC: XY|Z sigchsic = signature_kernel.SigCHSIC(X, Y, Z, static_kernel, dyadic_order=1, eps=0.1)
Examples for paper The signature kernel is the solution of a Goursat PDE
To run the specific examples navigate to folder ./examples and install the requirements with
pip install -r requirements.txt
To train all models and all datasets run (takes ~8 hours)
python3 time_series_classification.py --train
To test all models and all datasets run
python3 time_series_classification.py --test
To print results final results run
python3 time_series_classification.py --print
Jupyter notebook bitcoin_predictions.ipynb.
Jupyetr notebook recombination.ipynb.
@article{salvi2020computing, title={The Signature Kernel is the solution of a Goursat PDE}, author={Salvi, Cristopher and Cass, Thomas and Foster, James and Lyons, Terry and Yang, Weixin}, journal={arXiv preprint arXiv:2006.14794}, year={2020} }