Введение
Гауссовы процессы - популярный инструмент в машинном обучении для задач регрессии и классификации. Однако, они обычно требуют, чтобы данные были в виде фиксированной длины вектора признаков, что может ограничивать их использование в некоторых приложениях. В этом лабе мы исследуем, как Гауссовы процессы могут быть использованы для переменной длины последовательностей, таких как генные последовательности, путём определения функции ядра, которая действует непосредственно на этих структурах. Мы будем использовать scikit-learn для реализации наших моделей Гауссовых процессов.
Советы по ВМ
После запуска ВМ нажмите в левом верхнем углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.
Иногда может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится. Валидация операций не может быть автоматизирована из-за ограничений в Jupyter Notebook.
Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.
Определение SequenceKernel
Мы определяем класс SequenceKernel, который наследуется от классов Kernel и GenericKernelMixin из scikit-learn. Этот ядро определяет меру сходства между последовательностями переменной длины. Для этого используется R-конволюция, которая включает интегрирование бинарного ядра по буквам для всех пар букв между парой строк. Затем мы можем использовать это ядро для выполнения задач регрессии и классификации на последовательностях.
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 последовательностях, где истинное значение - просто то, есть ли в последовательности хотя бы одна буква 'A'. Здесь мы делаем четыре правильных классификации и ошибаемся в одном случае.
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="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.