Codage sparse avec dictionnaire pré-calculé

Beginner

This tutorial is from open-source community. Access the source code

Introduction

Dans ce laboratoire, nous allons apprendre à transformer un signal en une combinaison sparse d'ondelettes de Ricker en utilisant des méthodes de codage sparse. Le Ricker (également connu sous le nom de chapeau mexicain ou la seconde dérivée d'un Gaussien) n'est pas un noyau particulièrement adapté pour représenter des signaux piecewise constants comme celui-ci. On peut donc voir combien l'ajout d'atomes de différentes largeurs compte et cela justifie donc l'apprentissage du dictionnaire pour adapter le mieux possible votre type de signaux.

Nous comparerons visuellement différentes méthodes de codage sparse en utilisant l'estimateur SparseCoder. Le dictionnaire plus riche à droite n'est pas plus grand en taille, une sous-échantillonnage plus important est effectué pour rester dans le même ordre de grandeur.

Conseils sur la VM

Une fois le démarrage de la VM terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Notebook pour accéder à Jupyter Notebook pour la pratique.

Parfois, vous devrez peut-être attendre quelques secondes pour que Jupyter Notebook ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limitations de Jupyter Notebook.

Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez votre feedback après la session et nous résoudrons rapidement le problème pour vous.

Importation des bibliothèques

Nous allons commencer par importer les bibliothèques nécessaires.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import SparseCoder

Définition des fonctions d'ondelettes de Ricker

Nous allons définir des fonctions pour générer une ondelette de Ricker et un dictionnaire d'ondelettes de Ricker.

def ricker_function(resolution, center, width):
    """Ondelette de Ricker (chapeau mexicain) sous-échantillonnée discrètement"""
    x = np.linspace(0, resolution - 1, resolution)
    x = (
        (2 / (np.sqrt(3 * width) * np.pi**0.25))
        * (1 - (x - center) ** 2 / width**2)
        * np.exp(-((x - center) ** 2) / (2 * width**2))
    )
    return x


def ricker_matrix(width, resolution, n_components):
    """Dictionnaire d'ondelettes de Ricker (chapeau mexicain)"""
    centers = np.linspace(0, resolution - 1, n_components)
    D = np.empty((n_components, resolution))
    for i, center in enumerate(centers):
        D[i] = ricker_function(resolution, center, width)
    D /= np.sqrt(np.sum(D**2, axis=1))[:, np.newaxis]
    return D

Générer un signal

Nous allons générer un signal et le visualiser à l'aide de Matplotlib.

resolution = 1024
subsampling = 3  ## facteur de sous-échantillonnage
width = 100
n_components = resolution // subsampling

## Générer un signal
y = np.linspace(0, resolution - 1, resolution)
first_quarter = y < resolution / 4
y[first_quarter] = 3.0
y[np.logical_not(first_quarter)] = -1.0

## Visualiser le signal
plt.figure()
plt.plot(y)
plt.title("Signal original")
plt.show()

Calculer un dictionnaire d'ondelettes

Nous allons calculer un dictionnaire d'ondelettes et le visualiser à l'aide de Matplotlib.

## Calculer un dictionnaire d'ondelettes
D_fixed = ricker_matrix(width=width, resolution=resolution, n_components=n_components)
D_multi = np.r_[
    tuple(
        ricker_matrix(width=w, resolution=resolution, n_components=n_components // 5)
        for w in (10, 50, 100, 500, 1000)
    )
]

## Visualiser le dictionnaire d'ondelettes
plt.figure(figsize=(10, 5))
for i, D in enumerate((D_fixed, D_multi)):
    plt.subplot(1, 2, i + 1)
    plt.imshow(D, cmap=plt.cm.gray, interpolation="nearest")
    plt.title("Dictionnaire d'ondelettes (%s)" % ("largeur fixe" si i == 0 else "plusieurs largeurs"))
    plt.axis("off")
plt.show()

Codage sparse

Nous allons effectuer un codage sparse sur le signal en utilisant différentes méthodes et visualiser les résultats.

## Liste les différentes méthodes de codage sparse dans le format suivant :
## (titre, transform_algorithm, transform_alpha,
##  transform_n_nozero_coefs, couleur)
estimators = [
    ("OMP", "omp", None, 15, "navy"),
    ("Lasso", "lasso_lars", 2, None, "turquoise"),
]
lw = 2

plt.figure(figsize=(13, 6))
for subplot, (D, titre) in enumerate(
    zip((D_fixed, D_multi), ("largeur fixe", "plusieurs largeurs"))
):
    plt.subplot(1, 2, subplot + 1)
    plt.title("Codage sparse contre le dictionnaire %s" % titre)
    plt.plot(y, lw=lw, linestyle="--", label="Signal original")
    ## Effectuez une approximation d'ondelette
    for titre, algo, alpha, n_nonzero, couleur in estimators:
        coder = SparseCoder(
            dictionary=D,
            transform_n_nonzero_coefs=n_nonzero,
            transform_alpha=alpha,
            transform_algorithm=algo,
        )
        x = coder.transform(y.reshape(1, -1))
        densité = len(np.flatnonzero(x))
        x = np.ravel(np.dot(x, D))
        erreur_carrée = np.sum((y - x) ** 2)
        plt.plot(
            x,
            color=couleur,
            lw=lw,
            label="%s : %s coefficients non nuls,\n%.2f d'erreur" % (titre, densité, erreur_carrée),
        )

    ## Désajustement par seuillage doux
    coder = SparseCoder(
        dictionary=D, transform_algorithm="threshold", transform_alpha=20
    )
    x = coder.transform(y.reshape(1, -1))
    _, idx = np.where(x!= 0)
    x[0, idx], _, _, _ = np.linalg.lstsq(D[idx, :].T, y, rcond=None)
    x = np.ravel(np.dot(x, D))
    erreur_carrée = np.sum((y - x) ** 2)
    plt.plot(
        x,
        color="darkorange",
        lw=lw,
        label="Seuillage avec désajustement :\n%d coefficients non nuls, %.2f d'erreur"
        % (len(idx), erreur_carrée),
    )
    plt.axis("tight")
    plt.legend(shadow=False, loc="best")
plt.subplots_adjust(0.04, 0.07, 0.97, 0.90, 0.09, 0.2)
plt.show()

Sommaire

Dans ce laboratoire, nous avons appris à transformer un signal en une combinaison sparse d'ondelettes de Ricker à l'aide de méthodes de codage sparse et de l'estimateur SparseCoder. Nous avons également comparé différentes méthodes de codage sparse et visualisé les résultats.