利用大型语言模型构建动态金融知识图谱——FinDKG
摘要
在金融市场中,动态知识图谱(Dynamic Knowledge Graphs,DKGs)是一种表达对象之间随时间变化的多种关系的流行结构。它们可以有效地表示从复杂的非结构化数据源(如文本或图像)中提取的信息。在金融应用中,基于从金融新闻文章中获取的信息,DKGs 可用于检测战略性主题投资的趋势。
本文探讨了大型语言模型(Large Language Models,LLMs)作为动态知识图谱生成器的特性,提出了一种新的开源微调 LLM——集成上下文知识图谱生成器(Integrated Contextual Knowledge Graph Generator,ICKG)。我们利用 ICKG 从金融新闻文章语料库中生成了一个新的开源 DKG,称为 FinDKG,并提出了一种基于注意力机制的图神经网络(Graph Neural Network,GNN)架构来分析它,称为 KGTransformer。
我们在基准数据集和 FinDKG 上测试了所提出模型的性能,展示了其在链接预测任务上的优越性能。此外,我们评估了 KGTransformer 在 FinDKG 上用于主题投资的表现,显示其可以超越现有的主题 ETF。
引言
知识图谱和动态知识图谱
知识图谱(Knowledge Graph,KG)是一种数据结构,用于编码实体及其之间的多种关系。形式上,KG 可以表示为 ,其中 和 分别表示实体集合和关系集合, 表示事实的集合,由实体之间的不同类型的关系组成。三元组 是 KG 的基本构建块,其中 表示源实体, 表示关系, 表示目标实体。
动态知识图谱(Dynamic Knowledge Graph,DKG)扩展了静态 KG,通过引入时间动态性。DKG 中的每个事实都与一个时间戳 相关联,允许模型捕捉事件的时间演化。因此,事件以四元组的形式出现:
其中 是事件发生的时间,满足 对于 。那么,在时间 的 DKG 可以表示为:
动态知识图谱学习
估计从观测数据中得到的 的模型的任务称为动态知识图谱学习。这通常涉及到图神经网络(Graph Neural Network,GNN)的训练,旨在同时建模 KG 的结构和时间动态。
在实际应用中,如金融领域,实体和关系可以进一步分组,通常称为元实体(meta-entities)。例如,考虑实体 “Jeff Bezos”(类型为 “Person”)和实体 “Amazon”(类型为 “Company”)之间的关系 “Founder Of”(可以视为 “Business Action” 类型)。
本文贡献
本文的主要贡献如下:
- 1. KGTransformer:我们提出了一种基于注意力机制的 GNN 架构,用于动态知识图谱学习,包含元实体信息,称为 KGTransformer。该模型结合了现有的 GAT(Graph Attention Networks)和 EvoKG 架构。
- 2. ICKG 模型:我们开发了一种用于动态知识图谱生成的开源 LLM,称为集成上下文知识图谱生成器(ICKG)。
- 3. FinDKG 数据集:我们利用 ICKG 从金融新闻文章中创建了一个开源的动态知识图谱,称为 FinDKG。我们将其用于主题投资,特别是捕捉人工智能(Artificial Intelligence,AI)趋势。
相关工作
图表示学习
图表示学习(Graph Representation Learning)旨在从图结构中提取低维的潜在空间表示,以改进下游任务的性能。这些方法在节点分类、边预测和图分类等任务中表现出显著的能力。
金融知识图谱
金融系统通常具有复杂且动态演化的关系,这些关系可以用 DKG 表示,用于欺诈交易识别、股票收益预测、股票关联发现等应用。然而,金融网络的异质性和动态性对现有的静态 GNN 模型提出了挑战。
LLM 在金融中的应用
大型语言模型(LLMs)在金融任务中得到了广泛应用,如金融情感分析、基于新闻标题的股票市场预测等。然而,LLMs 在动态知识图谱中的应用在文献中仍然有限。

集成上下文知识图谱生成器(ICKG)
大型语言模型在知识图谱生成中的应用
大型语言模型(LLMs) 在自然语言处理领域取得了巨大成功,但其在知识图谱生成中的应用仍然有限。本文提出了ICKG,一种基于 LLM 的知识图谱生成器,通过监督微调(Supervised Fine-tuning) 来适应金融领域的特殊需求。
ICKG 的训练流程
- 1. 数据集构建:从开源的金融新闻文章中收集 5,000 篇文章,利用 GPT-4 API 生成知识图谱提取的训练数据。
- 2. 数据质量过滤:对生成的知识图谱数据进行质量过滤,确保符合预期的格式和内容。
- 3. 模型微调:使用收集的高质量数据,对开源的 Mistral 7B 模型进行微调,得到最终的 ICKG 模型。
ICKG 模型代码示例
以下是用于训练 ICKG 模型的代码示例:
备注:完整代码论文复现请加入知识星球获取。
# 导入必要的库
from transformers import AutoTokenizer, AutoModelForCausalLM
# 加载预训练的 Mistral 7B 模型和 tokenizer
tokenizer = AutoTokenizer.from_pretrained('mistral-7b')
model = AutoModelForCausalLM.from_pretrained('mistral-7b')
# 定义知识图谱提取的提示模板
prompt_template = """
请从以下金融新闻文章中提取实体及其关系,生成五元组 (s, r, o, t, c),其中 s 和 o 是实体,r 是关系,t 是时间戳,c 是实体类别。
文章内容:
{article_content}
"""
# 定义微调函数
def fine_tune_ickg(model, tokenizer, articles):
# 遍历文章进行微调
for article in articles:
......
# 优化器步骤
optimizer.step()
optimizer.zero_grad()
return model
金融动态知识图谱(FinDKG)数据集
数据集构建
我们收集了大约 40 万篇来自《华尔街日报》的金融新闻文章,时间跨度从 1999 年到 2023 年。我们使用 ICKG 从每篇文章中提取五元组,关系类型限制在 15 种,与金融新闻相关(如表 1 所示)。实体被标记为特定类别(如表 2 所示)。
实体和关系示例
关系类型示例:
关系 | 定义 | 示例 |
Has | 表示所有权或持有关系 | Google Has Android |
Announce | 表示正式宣布某个事件或产品 | Apple Announces iPhone 13 |
实体类别示例:
类别 | 定义 | 示例 |
ORG | 非政府组织 | Imperial College London |
COMP | 公司 | Apple Inc. |
PERSON | 个人 | Jerome Powell |
FinDKG 的可视化
通过对 FinDKG 进行可视化,我们可以看到特定时间段内最相关的实体和它们之间的关系。例如,在 2023 年 1 月,图谱中显示了美国和中国之间的地缘政治紧张关系,以及高通胀对全球经济的影响。
通过 KG Transformer 进行图学习
模型概述
KGTransformer 是一种基于注意力机制的图神经网络(GNN)模型,专为动态知识图谱的学习而设计。它结合了图注意力网络(Graph Attention Networks, GAT) 和异构图 Transformer(Heterogeneous Graph Transformer, HGT) 的特点。
元实体的引入
在金融知识图谱中,实体和关系可以进一步分类,这些类别称为元实体(Meta-entities)。注意力得分的计算考虑了元实体信息,引入了一个映射函数 ,将每个实体映射到一个实体类型。KGTransformer 通过引入元实体的信息,能够更好地捕捉实体之间的复杂关系。
模型细节
多头注意力机制
KGTransformer 利用多头注意力机制,将每一层的输入特征表示为多个子空间的组合:
其中, 是注意力头的数量, 是第 层的特征维度。
注意力计算
在 KGTransformer 中,图的表示为 ,其中 。在第 层,模型生成实体的嵌入表示 ,初始输入为 。
每一层的更新函数为:
- ? :激活函数,如 Leaky-ReLU
- ? :注意力权重,表示源实体 对目标实体 的影响程度
- ? :消息向量,包含源实体的信息
元实体的注意力计算
引入元实体后,注意力权重的计算考虑了实体的类别:
- ? :源实体的键向量
- ? :目标实体的查询向量
- ? :关系特定的可训练权重矩阵
- ? :元实体之间的关系矩阵




KGTransformer 模型代码示例
以下是用于训练 KGTransformer 模型的代码示例:
备注:完整代码论文复现请加入知识星球获取。
# 导入必要的库
import torch
import os
import sys
import pprint
from copy import deepcopy
from functools import partial
from collections import defaultdict
from datetime import datetime
# 获取当前脚本的绝对路径
current_path = os.path.abspath(__file__)
parent_parent_path = os.path.dirname(os.path.dirname(current_path))
sys.path.append(parent_parent_path)
# 导入 DKG 库
import DKG
from DKG.utils.log_utils import add_logger_file_handler, get_log_root_path, logger
from DKG.utils.model_utils import get_embedding
from DKG.utils.train_utils import setup_cuda, EarlyStopping
from DKG.model import (
DynamicGraphModel, DKG_DEFAULT_CONFIG, EmbeddingUpdater,
Combiner, EdgeModel, InterEventTimeModel, MultiAspectEmbedding
)
from DKG.model.time_interval_transform import TimeIntervalTransform
from DKG.train import compute_loss
from DKG.eval import evaluate
# 配置模型参数
args = deepcopy(DKG_DEFAULT_CONFIG)
args.seed = 41
args.cuda = args.gpu >= 0 and torch.cuda.is_available()
args.device = torch.device("cuda:{}".format(args.gpu) if args.cuda else "cpu")
args.graph = "FinDKG"
args.version = "KGTransformer"
......
# 设置随机种子
import numpy as np
np.random.seed(args.seed)
torch.manual_seed(args.seed)
if args.cuda:
torch.cuda.manual_seed_all(args.seed)
# 加载数据
from torch.utils.data import DataLoader
G = DKG.data.load_temporal_knowledge_graph(args.graph, data_root='./data')
collate_fn = partial(DKG.utils.collate_fn, G=G)
......
# 构建模型
embedding_updater = EmbeddingUpdater(
num_nodes=G.number_of_nodes(),
static_entity_embed_dim=args.static_entity_embed_dim,
structural_dynamic_entity_embed_dim=args.structural_dynamic_entity_embed_dim,
temporal_dynamic_entity_embed_dim=args.temporal_dynamic_entity_embed_dim,
node_latest_event_time=torch.zeros(
G.number_of_nodes(), G.number_of_nodes() + 1, 2, dtype=torch.float32
),
num_relations=G.num_relations,
rel_embed_dim=args.rel_embed_dim,
num_node_types=G.num_node_types,
num_heads=args.num_attn_heads,
......
combiner = Combiner(
......
).to(args.device)
edge_model = EdgeModel(
num_nodes=G.number_of_nodes(),
num_relations=G.num_relations,
rel_embed_dim=args.rel_embed_dim,
combiner=combiner,
dropout=args.dropout
).to(args.device)
inter_event_time_model = InterEventTimeModel(
dynamic_entity_embed_dim=args.temporal_dynamic_entity_embed_dim,
static_entity_embed_dim=args.static_entity_embed_dim,
num_rels=G.num_relations,
......
inter_event_time_mode=args.inter_event_time_mode,
dropout=args.dropout
)
model = DynamicGraphModel(
embedding_updater=embedding_updater,
......
node_latest_event_time=torch.zeros(
G.number_of_nodes(), G.number_of_nodes() + 1, 2, dtype=torch.float32
)
).to(args.device)
# 初始化嵌入
......
# 设置优化器
params = list(model.parameters()) + [
......
time_optimizer = torch.optim.AdamW(params, lr=args.lr, weight_decay=args.weight_decay)
# 训练模型
for epoch in range(args.epochs):
model.train()
for batch_i, (prior_G, batch_G, cumul_G, batch_times) in enumerate(train_data_loader):
# 计算损失
batch_train_loss_dict = compute_loss(
model, args.optimize, batch_G, static_entity_embeds,
init_dynamic_entity_embeds, init_dynamic_relation_embeds, args
)
# 反向传播和优化
loss = sum(batch_train_loss_dict.values())
loss.backward()
edge_optimizer.step()
edge_optimizer.zero_grad()
time_optimizer.step()
time_optimizer.zero_grad()
备注:完整代码论文复现请加入知识星球获取。
时间演化的更新
为了在动态环境中使用 KGTransformer,我们需要将时间信息引入模型。我们使用一个循环神经网络(Recurrent Neural Network,RNN)来建模嵌入的时间演化:
其中, 是时间 的时间嵌入(temporal embeddings)。
时间演化代码示例
备注:完整代码论文复现请加入知识星球获取。
class TemporalKGTransformer(nn.Module):
def __init__(self, ...):
super(TemporalKGTransformer, self).__init__()
......
def forward(self, x, edge_index, edge_type, node_type, h_prev):
x = self.kg_transformer(x, edge_index, edge_type, node_type)
h_t = self.rnn(x, h_prev)
return h_t
动态知识图谱学习
时间维度的引入
为了捕捉知识图谱随时间的变化,KGTransformer 使用了循环神经网络(Recurrent Neural Network, RNN)来更新实体和关系的时间嵌入(Temporal Embeddings)和结构嵌入(Structural Embeddings)。
概率建模
为了对动态知识图谱进行学习,定义了事件发生的概率模型:
其中, 表示在时间 发生的新事件集合。
利用 EvoKG 框架,将条件概率分解为结构和时间两部分:
损失函数
为了训练模型,定义了包含时间和结构信息的损失函数:
实验与应用
在真实世界 DKG 上的链接预测
数据集
我们在多个真实世界的知识图谱数据集上评估了 KGTransformer 的性能,包括 YAGO、WIKI、ICEWS14 和我们构建的 FinDKG。KGTransformer 在包含元实体信息的数据集上表现出色,尤其是在 FinDKG 上,与其他基线模型相比,性能提升了约 10%。
实验结果
在基准数据集上,KGTransformer 在链接预测任务上表现优异,特别是在包含实体类型信息的 FinDKG 数据集上,KGTransformer 的性能显著超过了其他模型。
实验代码示例
备注:完整代码论文复现请加入知识星球获取。
# 定义早停机制
stopper = EarlyStopping(
args.graph, args.patience,
result_root=log_root_path,
run_best_checkpoint_prefix=run_best_checkpoint_prefix,
overall_best_checkpoint_prefix=overall_best_checkpoint_prefix,
eval=args.eval
)
# 开始训练
for epoch in range(args.epochs):
model.train()
for batch_i, (prior_G, batch_G, cumul_G, batch_times) in enumerate(train_data_loader):
# 计算损失
batch_train_loss_dict = compute_loss(
model, args.optimize, batch_G, static_entity_embeds,
init_dynamic_entity_embeds, init_dynamic_relation_embeds, args
)
# 反向传播和优化
......
# 验证模型
val_dict, val_dynamic_entity_emb, val_dynamic_relation_emb, loss_weights = evaluate(
......
# 早停判断
score = val_dict['MRR']
pack_args = (
......
if stopper.step(score, pack_checkpoint(*pack_args)):
logger.info(f"[Epoch-{epoch}] Early stop!")
break
# 测试模型
run_best_checkpoint = stopper.load_checkpoint()
model, edge_optimizer, time_optimizer, val_static_entity_emb,
init_dynamic_entity_embeds, val_dynamic_entity_emb,
init_dynamic_relation_embeds, val_dynamic_relation_emb,
node_latest_event_time_post_valid, loss_weights, _ =
unpack_checkpoint(run_best_checkpoint, model, edge_optimizer, time_optimizer)
evaluate(
model, test_data_loader, G, val_static_entity_emb, val_dynamic_entity_emb,
val_dynamic_relation_emb, G.num_relations, args,
"Test", args.full_link_pred_test, args.time_pred_eval, loss_weights=loss_weights
)
备注:完整代码论文复现请加入知识星球获取。
金融新闻中的趋势识别
通过分析 FinDKG,我们可以动态跟踪全球金融网络。例如,我们可以观察到 COVID-19 实体的中心性指标随着时间的变化,捕捉到疫情在不同时间点对全球经济的影响。


趋势识别代码示例
备注:完整代码论文复现请加入知识星球获取。
# 计算节点中心性指标
def compute_centrality(graph):
......
# 其他中心性指标
return degree_centrality, betweenness_centrality
# 绘制中心性指标随时间的变化
def plot_centrality_over_time(centrality_data):
# 绘图逻辑省略
plt.show()
基于 FinDKG 的主题投资
我们利用 KGTransformer 对 FinDKG 进行训练,预测与人工智能(AI)相关的公司。通过构建一个 AI 主题的投资组合,我们发现该投资策略在评估期间的表现优于市场基准和其他 AI 主题的 ETF。

投资组合构建代码示例
备注:完整代码论文复现请加入知识星球获取。
# 根据模型预测构建投资组合
def construct_portfolio(model, fin_dkg, theme='AI'):
predicted_entities = model.predict_entities(theme)
portfolio = allocate_weights(predicted_entities)
return portfolio
# 模拟投资组合表现
......
# 绘制投资组合表现
def plot_portfolio_performance(returns):
plt.plot(returns)
plt.xlabel('Time')
plt.ylabel('Returns')
plt.title('Portfolio Performance')
plt.show()
结论

本文提出了一种利用大型语言模型生成动态知识图谱的新方法,并开发了一个用于金融领域的开源数据集 FinDKG。我们还提出了 KGTransformer 模型,展示了其在链接预测任务上的优越性能。我们的研究为在金融市场中利用 DKGs 和 LLMs 提供了新的思路和工具。