Подробное руководство по графу знаний, включающему обучение и оценку

Прежде чем вы начнете читать эту статью, я предполагаю, что у вас есть краткое представление о вложениях графов знаний. Если нет, я предлагаю вам ознакомиться со следующей статьей, которая дает вам хорошее представление об этой концепции:



Теперь, когда это не так, в этой статье я покажу, как вы можете создавать вложения графов знаний, интерпретировать их, а также оценивать их производительность в задачах на основе графов.

Граф знаний

Рассмотрим граф знаний страны. На этом графике у нас есть названия стран и регионов как объектов. Отношения представлены двумя свойствами, а именно сосед и расположен в.

График представляет собой встроенный набор данных библиотеки PyKEEN Python.

Посмотрите на следующий снимок экрана с тройками графа знаний, показанными в виде фрейма данных:

Тройки имеют вид (croatia, neighbor, serbia) и (denmark, locatedin, europe). Ниже приведена полная визуализация графика с использованием библиотеки NetworkX Python:

График большой, поэтому визуализация не слишком четкая. Давайте проверим подграф этого графа знаний.

Подграф выше ясно иллюстрирует триплеты, показывая как сущности, так и отношения.

Теперь у нас есть граф знаний. Давайте разберемся, как генерировать вложения графа знаний с помощью библиотеки Python PyKEEN.

Встраивание графа знаний

Выше показано визуализация вложений графа знаний, обученных с использованием алгоритма TransR. Обратите внимание, как страны сгруппированы вместе. В верхней части визуализации мы видим Боснию, Черногорию и Албанию близко друг к другу. Это указывает на то, что алгоритм встраивания смог объединить страны с похожими свойствами вместе.

Визуализация выполнена с использованием PCA, где размер встраивания 128 уменьшен до размера 2-х измерений. Это может повлиять на точность группировки стран. Кроме того, алгоритм встраивания можно настроить для повышения производительности.

Вот код для создания вложений:

Предпосылки

pip install pykeen -q # install PyKEEN library

Прочитать данные

from pykeen.datasets import Countries
import pandas as pd

# read data from pykeen dataset method
df = pd.DataFrame(Countries().training.triples)
df.columns = ['h', 'r', 't']
df.sample(10)

Создание вложений

from pykeen.triples import TriplesFactory
from pykeen.pipeline import pipeline

# Generate triples from the graph data
tf = TriplesFactory.from_labeled_triples(df.values)

# split triples into train and test
training, testing = tf.split([0.8, 0.2], random_state=42)

# generate embeddings using PyKEEN's pipeline method
result = pipeline(
        training=training,
        testing=testing,
        model = "TransR",
        model_kwargs=dict(embedding_dim=128),
        training_kwargs=dict(num_epochs=200),
        random_seed=42)

В приведенном выше коде класс TriplesFactory обеспечивает стандартизированное представление троек в графе знаний. В PyKEEN есть разные методы для чтения троек и управления ими. Кроме того, чтобы разделить данные на обучающие, проверочные и тестовые наборы. Здесь я просто разделяю данные на обучающие и тестовые наборы, так как не выполняю настройку гиперпараметров.

Я выбрал модель TransR и установил размер внедрения на 128 и эпохи на 200.

График Loss vs. Epochs выглядит следующим образом:

Потери уменьшаются до 100 эпох, а затем остаются почти постоянными. 100 эпох было бы достаточно для этого тренировочного процесса. Ну что ж!

Получить вложения

Процесс обучения завершен, и теперь мы можем получить вложения из объекта result функции pipeline() PyKEEN. Мы изучаем вложения как для сущностей, так и для отношений. Эти вложения можно визуализировать с помощью любых методов уменьшения размерности, таких как PCA или t-SNE (такие же, как визуализация, показанная в разделе выше).

Ниже приведен код для получения вложений после завершения процесса обучения:

Вложения сущностей

# get entity labels from training set
entity_labels = training.entity_labeling.all_labels()
# convert entities to ids
entity_ids = torch.as_tensor(training.entities_to_ids(entity_labels))
# retrieve the embeddings using entity ids
entity_embeddings = result.model.entity_representations[0](indices=entity_ids)
# create a dictionary of entity labels and embeddings
entity_embeddings_dict = dict(zip(entity_labels, entity_embeddings.detach().numpy()))

Вложения отношений

# get relation labels from training set
relation_labels = training.relation_labeling.all_labels()
# convert relations to ids
relation_ids = torch.as_tensor(training.relations_to_ids(relation_labels))
# retrieve the embeddings using relation ids
relation_embeddings = result.model.relation_representations[0](indices=relation_ids)
# create a dictionary of relation labels and embeddings
relation_embeddings_dict = dict(zip(relation_labels, relation_embeddings.detach().numpy()))

Оценка вложений

Мы видели генерацию вложений, а также то, как их извлекать. Теперь давайте проверим их производительность при прогнозировании ссылок. Прогнозирование ссылок — это задача на основе графа, которая включает прогнозирование отсутствующих или будущих связей между узлами в графе.

Посмотрите мою статью, в которой подробно описываются задачи на основе графа, такие как предсказание ссылок и классификация узлов.

PyKEEN предоставляет простой способ выполнить оценку задачи прогнозирования ссылок.

Я создам фрейм данных для обучающих и тестовых наборов, чтобы было легче понять процесс оценки.

# create a train df
df_train = pd.DataFrame(training.triples)
df_train.columns = ['h','r','t']
# create a test df
df_test = pd.DataFrame(testing.triples)
df_test.columns = ['h','r','t']

Я буду использовать оценку на основе скоринга для выполнения задачи предсказания хвоста (вариант предсказания ссылки). Модель должна предсказать хвостовую сущность из тестового набора. Я рассматриваю 3 случая, чтобы продемонстрировать работу этого процесса оценки.

Случай 1: Мексика

На изображении выше мы видим, что модель обучена трем тройкам, включающим Mexico в качестве головного объекта. Тестовый набор имеет один экземпляр с отношением neighbor. Наша цель — правильно предсказать хвостовую сущность тестового набора, т. е. предсказать united_states из тройки (mexico, neighbor, united_states).

from pykeen import predict

# tail prediction
predict.predict_target(model=result.model,
                       head="mexico",
                       relation="neighbor",
                       triples_factory=result.training).df.head(20)

Приведенный выше кодовый блок выполняет предсказание хвоста для «отсутствующей» тройки (mexico, neighbor, ?)..

В приведенном выше выводе мы видим, что модель оценивает belize, guatemala и united_states как лучшие прогнозы на основе метода оценки. belize и guatemala уже присутствовали в тренировочном наборе, и модель правильно предсказала united_states. Обратите внимание, как прогнозы с самым высоким рейтингом имеют лучший результат.

Это один из вариантов использования задачи предсказания ссылок.

Случай 2: Сенегал

Здесь мы предсказываем хвост тестовой тройки (senegal, locatedin, ?). В тестовом наборе есть только один экземпляр. Прогноз следующий:

Случай 3: Бутан

Здесь есть два экземпляра в тестовом наборе. Посмотрим прогнозы:

Модель правильно оценивает первый экземпляр предсказания хвоста (india), но не может оценить второй экземпляр (china) в верхних рядах. Он успешно предсказывает хвостовую метку, но с низкой достоверностью.

Это связано с тем, что модель не смогла точно отразить сетевые отношения во вложениях. Помните, что я не выполнял оптимизацию гиперпараметров при обучении модели, что могло снизить производительность.

Метрики оценки

В предыдущем разделе я показал базовый процесс оценки. У нас есть методы оценки на основе рангов, которые количественно определяют производительность модели. Ранговые методы имеют несколько метрик, и одной из важных метрик является средний ранг.

Средний ранг — это средний ранг правильного предсказания по всем тройкам тестов. В приведенных выше 3 случаях средний ранг можно рассчитать следующим образом:

Случай 1: Ранг = 4

Случай 2: Ранг = 2

Случай 3: Ранг = 2 (первый случай)

Случай 3: Ранг = 13 (второй случай)

Следовательно, средний ранг равен (4+2+2+13)/4 = 5,25.

Средний ранг для всего набора тестов выглядит следующим образом:

rank_metrics = result.metric_results.to_df()
rank_metrics[rank_metrics.Metric=='arithmetic_mean_rank']

Мы выполнили предсказание хвоста в вышеупомянутых 3 случаях. Для всего набора тестов средний ранг предсказания хвоста составляет около 7,2, что не так уж и плохо.

Мы обучили достойную модель встраивания графа знаний!

Спасибо за чтение, и ура!

Хотите присоединиться?
Свяжитесь со мной в LinkedIn, Twitter, GitHub или Website!