Processus gaussiens sur des structures de données discrètes

Beginner

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

Introduction

Les processus gaussiens sont un outil populaire en apprentissage automatique pour les tâches de régression et de classification. Cependant, ils nécessitent généralement que les données soient sous forme de vecteurs de caractéristiques de longueur fixe, ce qui peut être limitant dans certaines applications. Dans ce laboratoire, nous allons explorer comment les processus gaussiens peuvent être utilisés sur des séquences de longueur variable, telles que les séquences génétiques, en définissant une fonction noyau qui opère directement sur ces structures. Nous utiliserons scikit-learn pour implémenter nos modèles de processus gaussiens.

Conseils sur la VM

Une fois le démarrage de la VM terminé, cliquez dans le coin supérieur gauche pour passer à 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 des commentaires après la session, et nous réglerons rapidement le problème pour vous.

Définir SequenceKernel

Nous définissons une classe SequenceKernel qui hérite des classes Kernel et GenericKernelMixin de scikit-learn. Ce noyau définit une mesure de similarité entre des séquences de longueur variable. Il le fait en utilisant la convolution R, qui consiste à intégrer un noyau binaire par lettre sur toutes les paires de lettres parmi une paire de chaînes. Nous pouvons ensuite utiliser ce noyau pour effectuer des tâches de régression et de classification sur des séquences.

import numpy as np
from sklearn.gaussian_process.kernels import Kernel, Hyperparameter
from sklearn.gaussian_process.kernels import GenericKernelMixin
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.base import clone


class SequenceKernel(GenericKernelMixin, Kernel):
    """
    Un noyau convolutif minimal (mais valide) pour des séquences de longueurs variables.
    """

    def __init__(self, baseline_similarity=0.5, baseline_similarity_bounds=(1e-5, 1)):
        self.baseline_similarity = baseline_similarity
        self.baseline_similarity_bounds = baseline_similarity_bounds

    @property
    def hyperparameter_baseline_similarity(self):
        return Hyperparameter(
            "baseline_similarity", "numérique", self.baseline_similarity_bounds
        )

    def _f(self, s1, s2):
        """
        Valeur du noyau entre une paire de séquences
        """
        return sum(
            [1.0 if c1 == c2 else self.baseline_similarity for c1 in s1 for c2 in s2]
        )

    def _g(self, s1, s2):
        """
        Dérivée du noyau entre une paire de séquences
        """
        return sum([0.0 if c1 == c2 else 1.0 for c1 in s1 for c2 in s2])

    def __call__(self, X, Y=None, eval_gradient=False):
        if Y is None:
            Y = X

        if eval_gradient:
            return (
                np.array([[self._f(x, y) for y in Y] for x in X]),
                np.array([[[self._g(x, y)] for y in Y] for x in X]),
            )
        else:
            return np.array([[self._f(x, y) for y in Y] for x in X])

    def diag(self, X):
        return np.array([self._f(x, x) for x in X])

    def is_stationary(self):
        return False

    def clone_with_theta(self, theta):
        cloned = clone(self)
        cloned.theta = theta
        return cloned

Visualiser la matrice de similarité des séquences

Nous pouvons utiliser notre SequenceKernel pour calculer la matrice de similarité entre les séquences. Nous allons tracer cette matrice à l'aide d'une échelle de couleur, où les couleurs plus claires indiquent une plus grande similarité.

import matplotlib.pyplot as plt

X = np.array(["AGCT", "AGC", "AACT", "TAA", "AAA", "GAACA"])

kernel = SequenceKernel()
K = kernel(X)
D = kernel.diag(X)

plt.figure(figsize=(8, 5))
plt.imshow(np.diag(D**-0.5).dot(K).dot(np.diag(D**-0.5)))
plt.xticks(np.arange(len(X)), X)
plt.yticks(np.arange(len(X)), X)
plt.title("Similarité des séquences sous le noyau")
plt.show()

Effectuer une régression sur des séquences

Nous pouvons utiliser notre SequenceKernel pour effectuer une régression sur des séquences. Nous utiliserons un ensemble de données de 6 séquences et utiliser les 1ère, 2ème, 4ème et 5ème séquences comme ensemble d'entraînement pour effectuer des prédictions sur les 3ème et 6ème séquences.

X = np.array(["AGCT", "AGC", "AACT", "TAA", "AAA", "GAACA"])
Y = np.array([1.0, 1.0, 2.0, 2.0, 3.0, 3.0])

training_idx = [0, 1, 3, 4]
gp = GaussianProcessRegressor(kernel=kernel)
gp.fit(X[training_idx], Y[training_idx])

plt.figure(figsize=(8, 5))
plt.bar(np.arange(len(X)), gp.predict(X), color="b", label="prédiction")
plt.bar(training_idx, Y[training_idx], width=0.2, color="r", alpha=1, label="entraînement")
plt.xticks(np.arange(len(X)), X)
plt.title("Régression sur des séquences")
plt.legend()
plt.show()

Effectuer une classification sur des séquences

Nous pouvons utiliser notre SequenceKernel pour effectuer une classification sur des séquences. Nous utiliserons un ensemble de données de 6 séquences et entraîner sur la question de savoir s'il y a des 'A' dans la séquence. Nous ferons ensuite des prédictions sur 5 autres séquences, où la vérité terrain est simplement de savoir s'il y a au moins un 'A' dans la séquence. Ici, nous effectuons quatre classifications correctes et échouons sur une.

X_train = np.array(["AGCT", "CGA", "TAAC", "TCG", "CTTT", "TGCT"])
## whether there are 'A's in the sequence
Y_train = np.array([True, True, True, False, False, False])

gp = GaussianProcessClassifier(kernel)
gp.fit(X_train, Y_train)

X_test = ["AAA", "ATAG", "CTC", "CT", "C"]
Y_test = [True, True, False, False, False]

plt.figure(figsize=(8, 5))
plt.scatter(
    np.arange(len(X_train)),
    [1.0 if c else -1.0 for c in Y_train],
    s=100,
    marker="o",
    edgecolor="none",
    facecolor=(1, 0.75, 0),
    label="entraînement",
)
plt.scatter(
    len(X_train) + np.arange(len(X_test)),
    [1.0 if c else -1.0 for c in Y_test],
    s=100,
    marker="o",
    edgecolor="none",
    facecolor="r",
    label="vérité",
)
plt.scatter(
    len(X_train) + np.arange(len(X_test)),
    [1.0 if c else -1.0 for c in gp.predict(X_test)],
    s=100,
    marker="x",
    facecolor="b",
    linewidth=2,
    label="prédiction",
)
plt.xticks(np.arange(len(X_train) + len(X_test)), np.concatenate((X_train, X_test)))
plt.yticks([-1, 1], [False, True])
plt.title("Classification sur des séquences")
plt.legend()
plt.show()

Sommaire

Dans ce laboratoire, nous avons démontré comment utiliser des processus gaussiens sur des séquences de longueur variable en utilisant une fonction de noyau personnalisée. Nous avons montré comment effectuer des tâches de régression et de classification sur des données séquentielles à l'aide de scikit-learn.