Codificación esparsa con diccionario precomputado

Machine LearningMachine LearningBeginner
Practicar Ahora

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

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, aprenderemos cómo transformar una señal como una combinación esparsa de ondas de Ricker utilizando métodos de codificación esparsa. El Ricker (también conocido como sombrero mexicano o la segunda derivada de una función Gaussiana) no es un kernel particularmente bueno para representar señales piecewise constantes como esta. Por lo tanto, se puede ver cuánto importa agregar átomos de diferentes anchos y, por lo tanto, se justifica aprender el diccionario para ajustarse mejor al tipo de señales que se tienen.

Visualizaremos diferentes métodos de codificación esparsa utilizando el estimador SparseCoder. El diccionario más rico de la derecha no es más grande en tamaño, se realiza una submuestreo más agresivo para mantenerse en el mismo orden de magnitud.

Consejos sobre la VM

Una vez que se haya iniciado la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.

A veces, es posible que tenga que esperar unos segundos para que Jupyter Notebook termine de cargarse. La validación de las operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.

Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje comentarios después de la sesión y resolveremos el problema inmediatamente para usted.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup(["Advanced Data Analysis and Dimensionality Reduction"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup -.-> sklearn/decomposition("Matrix Decomposition") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/decomposition -.-> lab-49294{{"Codificación esparsa con diccionario precomputado"}} ml/sklearn -.-> lab-49294{{"Codificación esparsa con diccionario precomputado"}} end

Importar bibliotecas

Comenzaremos importando las bibliotecas necesarias.

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

Definir funciones de ondas de Ricker

Definiremos funciones para generar una onda de Ricker y un diccionario de ondas de Ricker.

def ricker_function(resolution, center, width):
    """Onda de Ricker (sombrero mexicano) submuestreada discretamente"""
    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):
    """Diccionario de ondas de Ricker (sombrero mexicano)"""
    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

Generar una señal

Generaremos una señal y la visualizaremos utilizando Matplotlib.

resolution = 1024
subsampling = 3  ## factor de submuestreo
width = 100
n_components = resolution // subsampling

## Generar una señal
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

## Visualizar la señal
plt.figure()
plt.plot(y)
plt.title("Señal original")
plt.show()

Calcular un diccionario de ondas

Calculemos un diccionario de ondas y visualicémoslo utilizando Matplotlib.

## Calcular un diccionario de ondas
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)
    )
]

## Visualizar el diccionario de ondas
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("Diccionario de ondas (%s)" % ("ancho fijo" si i == 0 else "varios anchos"))
    plt.axis("off")
plt.show()

Codificación esparsa

Realizaremos la codificación esparsa en la señal utilizando diferentes métodos y visualizaremos los resultados.

## Liste los diferentes métodos de codificación esparsa en el siguiente formato:
## (título, algoritmo de transformación, alfa de transformación,
##  número de coeficientes no nulos de transformación, color)
estimadores = [
    ("OMP", "omp", None, 15, "azul marino"),
    ("Lasso", "lasso_lars", 2, None, "turquesa"),
]
lw = 2

plt.figure(figsize=(13, 6))
for subplot, (D, título) in enumerate(
    zip((D_fixed, D_multi), ("ancho fijo", "varios anchos"))
):
    plt.subplot(1, 2, subplot + 1)
    plt.title("Codificación esparsa contra el diccionario %s" % título)
    plt.plot(y, lw=lw, linestyle="--", label="Señal original")
    ## Haga una aproximación de ondas
    for título, algo, alfa, n_no_nulos, color in estimadores:
        codificador = SparseCoder(
            dictionary=D,
            transform_n_nonzero_coefs=n_no_nulos,
            transform_alpha=alfa,
            transform_algorithm=algo,
        )
        x = codificador.transform(y.reshape(1, -1))
        densidad = len(np.flatnonzero(x))
        x = np.ravel(np.dot(x, D))
        error_cuadrado = np.sum((y - x) ** 2)
        plt.plot(
            x,
            color=color,
            lw=lw,
            label="%s: %s coeficientes no nulos,\n%.2f error" % (título, densidad, error_cuadrado),
        )

    ## Desviación de umbral suave
    codificador = SparseCoder(
        dictionary=D, transform_algorithm="umbral", transform_alpha=20
    )
    x = codificador.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))
    error_cuadrado = np.sum((y - x) ** 2)
    plt.plot(
        x,
        color="naranja oscura",
        lw=lw,
        label="Umbralización con desviación:\n%d coeficientes no nulos, %.2f error"
        % (len(idx), error_cuadrado),
    )
    plt.axis("tight")
    plt.legend(shadow=False, loc="mejor")
plt.subplots_adjust(0.04, 0.07, 0.97, 0.90, 0.09, 0.2)
plt.show()

Resumen

En este laboratorio, aprendimos cómo transformar una señal como una combinación esparsa de ondas de Ricker utilizando métodos de codificación esparsa y el estimador SparseCoder. También comparamos diferentes métodos de codificación esparsa y visualizamos los resultados.