scalib.modeling.LdaAcc#

class scalib.modeling.LdaAcc(nc, pois)[source]#

Models the leakage \(\mathbf{l}\) with \(n_s\) dimensions using the linear discriminant analysis classifier (LDA) with integrated dimensionality reduction.

Based on the training data, linear discriminant analysis build a linear dimentionality reduction to \(p\) dimensions that maximizes class separation, for each target variable. Then, for each variable, a multivariate gaussian template is fitted for each class (using the same covariance matrix for all the classes) in the reduced dimensionality space to predict leakage likelihood [1].

Let \(\mathbf{W}\) be the dimensionality reduction matrix of size (\(p\), \(n_s\)). The likelihood is

\[\mathsf{\hat{f}}(\mathbf{l} | x) = \frac{1}{\sqrt{(2\pi)^{p} \cdot |\mathbf{\Sigma} |}} \cdot \exp^{\frac{1}{2} (\mathbf{W} \cdot \mathbf{l} - \mathbf{\mu}_x) \mathbf{\Sigma} ( \mathbf{W} \cdot \mathbf{l}-\mathbf{\mu}_x)'}\]

where \(\mathbf{\mu}_x\) is the mean of the leakage for class \(x\) in the projected space (\(\mu_x = \mathbb{E}(\mathbf{W}\mathbf{l}_x)\), where \(\mathbf{l}_x\) denotes the leakage traces of class \(x\)) and \(\mathbf{\Sigma}\) its covariance (\(\mathbf{\Sigma} = \mathbb{Cov}(\mathbf{W}\mathbf{l}_x - \mathbf{\mu}_x)\)).

This class is aimed to be used together with Lda. In particular, LdaAcc only perform the fitting step, from which a fitted Lda instance can be created for an arbitrary \(p\). The solved Lda instance provides the probability of each class with predict_proba() thanks to Bayes’ law such that

\[\hat{\mathsf{pr}}(x|\mathbf{l}) = \frac{\hat{\mathsf{f}}(\mathbf{l}|x)} {\sum_{x^*=0}^{n_c-1} \hat{\mathsf{f}}(\mathbf{l}|x^*)}.\]

Example

>>> from scalib.modeling import Lda, LdaAcc
>>> import numpy as np
>>> # 1000 traces of length 10, with value between 0 and 4091
>>> traces = np.random.randint(0, 4092, (1000, 10), dtype=np.int16)
>>> # classes between 0 and 15 (2 variables)
>>> x = np.random.randint(0, 16, (1000, 2), dtype=np.uint16)
>>> lda_acc = LdaAcc(nc=16, pois=[list(range(5)), list(range(4, 10))])
>>> lda_acc.fit_u(traces, x)
>>> lda = Lda(lda_acc, p=3) # Projection to 3 dimensions.
>>> # predict classes for new traces
>>> new_traces = np.random.randint(0, 256, (20,10), dtype=np.int16)
>>> predicted_proba = lda.predict_proba(new_traces)

Notes

This should have similar behavior as scikit-learn’s LDA, but it has better performance and numerical properties (at the cost of flexibility).

References

Parameters:
  • nc (int) – Number of possible classes (e.g., 256 for 8-bit target). nc must be smaller than \(2^{16}\).

  • pois (list of array_like, int) – Indices of the POIs in the traces for each variable. That is, for variable i, and training trace t, t[pois[i]] is the input datapoints for the LDA.

Methods

fit_u(traces, x)

Update the LDA estimates with new training data.

get_mus()

Return means matrix (classes means) as a list of length nv, where the i-th element is the matrix of shape: (nc, len(pois[i])) associated to the i-th variable.

get_sb()

Return \(S_{B}\) matrix (between-class scatter).

get_sw()

Return \(S_{W}\) matrix (within-class scatter).

fit_u(traces, x)[source]#

Update the LDA estimates with new training data.

Parameters:
  • traces (array_like, int16) – Array that contains the traces. The array must be of dimension (n,ns) and its type must be int16.

  • x (array_like, uint16) – Labels for each trace. Must be of shape (n, nv) and must be uint16.

get_sw()[source]#

Return \(S_{W}\) matrix (within-class scatter).

get_sb()[source]#

Return \(S_{B}\) matrix (between-class scatter).

get_mus()[source]#

Return means matrix (classes means) as a list of length nv, where the i-th element is the matrix of shape: (nc, len(pois[i])) associated to the i-th variable.