離散的なデータ構造上のガウス過程

Beginner

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

はじめに

ガウス過程は、回帰と分類タスクのための機械学習における人気のあるツールです。ただし、通常、固定長の特徴ベクトル形式のデータが必要であり、特定のアプリケーションでは制限になる場合があります。この実験では、これらの構造に直接作用するカーネル関数を定義することで、ガウス過程を遺伝子配列などの可変長シーケンスにどのように使用できるかを検討します。私たちは、scikit-learn を使用してガウス過程モデルを実装します。

VM のヒント

VM の起動が完了したら、左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebook を使って練習しましょう。

時々、Jupyter Notebook が読み込み終了するまで数秒待つ必要がある場合があります。Jupyter Notebook の制限により、操作の検証は自動化できません。

学習中に問題に遭遇した場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。

SequenceKernel を定義する

scikit-learn のKernelGenericKernelMixinクラスから継承するSequenceKernelクラスを定義します。このカーネルは、可変長のシーケンス間の類似度測定を定義します。それは R-畳み込みを使用してそうします。これには、一対の文字列間のすべての文字のペアに対して 2 値文字単位のカーネルを積分することが含まれます。その後、このカーネルを使用して、シーケンスに対する回帰と分類タスクを実行できます。

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):
    """
    可変長のシーケンスに対する最小限(ただし有効)の畳み込みカーネル。
    """

    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", "numeric", self.baseline_similarity_bounds
        )

    def _f(self, s1, s2):
        """
        一対のシーケンス間のカーネル値
        """
        return sum(
            [1.0 if c1 == c2 else self.baseline_similarity for c1 in s1 for c2 in s2]
        )

    def _g(self, s1, s2):
        """
        一対のシーケンス間のカーネル微分
        """
        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

シーケンス類似度行列を可視化する

SequenceKernelを使って、シーケンス間の類似度行列を計算することができます。この行列をカラーマップを使って描画します。明るい色が高い類似度を示すようになっています。

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("Sequence similarity under the kernel")
plt.show()

シーケンスに対する回帰を行う

SequenceKernelを使って、シーケンスに対する回帰を行うことができます。6 つのシーケンスのデータセットを使い、1 番目、2 番目、4 番目、5 番目のシーケンスを訓練セットとして使って、3 番目と 6 番目のシーケンスに対する予測を行います。

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="prediction")
plt.bar(training_idx, Y[training_idx], width=0.2, color="r", alpha=1, label="training")
plt.xticks(np.arange(len(X)), X)
plt.title("Regression on sequences")
plt.legend()
plt.show()

シーケンスに対する分類を行う

SequenceKernelを使って、シーケンスに対する分類を行うことができます。6 つのシーケンスのデータセットを使い、シーケンスに'A'が含まれているかどうかで訓練します。その後、別の 5 つのシーケンスに対して予測を行います。正解は、シーケンスに少なくとも 1 つの'A'があるかどうかだけです。ここでは、4 つの正しい分類ができ、1 つで失敗します。

X_train = np.array(["AGCT", "CGA", "TAAC", "TCG", "CTTT", "TGCT"])
## シーケンスに'A'が含まれているかどうか
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="training",
)
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="truth",
)
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="prediction",
)
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 on sequences")
plt.legend()
plt.show()

まとめ

この実験では、カスタムカーネル関数を使って、可変長のシーケンスに対してガウス過程をどのように使用するかを示しました。scikit-learn を使って、シーケンスデータに対して回帰と分類タスクをどのように行うかを示しました。