论文笔记:PromptKG: A Prompt Learning Framework for Knowledge Graph Representation Learning and Application

前言

论文:https://arxiv.org/pdf/2210.00305v1.pdf

代码:https://github.com/zjunlp/PromptKG

概述

知识图谱(KGs)通常有两个特征:异构的图结构和文本丰富的实体/关系信息。知识图谱表示学习旨在将关系和实体映射到连续的向量空间中,从而提高知识推理能力,并可应用于问答系统、推荐系统等下游任务。知识图谱表示模型需要考虑图结构和文本语义,但目前没有一个全面的开源框架主要针对知识图谱的信息性文本描述。论文提出了一个用于知识图谱表示学习和应用的开源提示学习框架PromptKG,它装备了前沿的基于文本的方法,集成了一个新的即时学习模型,并支持各种任务(如知识图补全、知识回答、推荐和知识探究)。

一些显著的开源和长期维护的知识体系表示工具包已经开发出来,如OpenKE, LibKGE, PyKEEN, CogKGE。然而,在不使用任何辅助信息的情况下,这些基于嵌入的方法在浅层网络架构的表达能力方面受到限制。

相比之下,基于文本的方法结合可用文本进行知识表示学习。随着提示学习(prompt learning)的快速发展,大量基于文本的模型被提出,这些模型可以通过预训练语言模型获得良好的性能。

阅读更多:论文笔记:PromptKG: A Prompt Learning Framework for Knowledge Graph Representation Learning and Application

基于文本的知识图谱表示

基于判别方法(Discrimination-based methods)

基于判别方法有两种模型:

一种(如KG- bert 和PKGC)利用单个编码器对带有文本描述的知识图谱三元组进行编码;

另一种(如StAR和SimKGC)利用孪生编码器(双塔模型)和预训练语言模型分别对实体和关系进行编码。

基于生成方法(Generation-based methods)

给定一个缺失尾实体的三元组(h, r, ?),给模型输入<?h, ?r>,输出?t。在训练过程中,生成模型最大化条件概率:

为了保证知识图谱中解码序列模式和tokens的一致性,GenKGC提出了一个实体感知的分层解码器来约束??。此外,受提示学习的启发,GenKGC采用与样例相同关系的三元组隐式编码结构化知识。此外,KGT5提出用文本描述对知识图谱表示进行预训练。

基于提示学习的知识表示学习

普通的预训练语言模型中有两个模块:一个用于将token id嵌入到语义空间的词嵌入层(a word embedding layer),另一个用于生成上下文感知嵌入的编码器(encoder)。该方法与普通的判别式方法共享相同的架构。论文采用掩码语言模型,在词嵌入层将实体和关系视为特殊标记。如图所示,该模型利用头部实体和关系及其描述的序列预测出正确的尾部实体。对于实体/关系嵌入,冻结编码器层(encoder),只微调实体嵌入层(entity embedding),以优化损失函数:

其中Θ表示模型的参数,?? 和 ?? 是实体?的描述和嵌入。

基于提示学的的知识图谱表示学习方法

PromptKG整体结构

PromptKG的设计原则

1)统一的知识图谱编码器:PromptKG利用统一的编码器封装图结构和文本语义;

2)模型枢纽:PromptKG集成了许多前沿的基于文本的KG表示模型;

3)灵活的下游任务:PromptKG将KG表示学习和下游任务进行了解耦

统一的知识图谱编码(Unified KG Encode)

一个统一的知识图谱编码器表示图结构和文本语义,支持不同类型的基于文本的知识图谱表示方法。

对于基于判别的方法,输入是建立在纯文本描述上的:

对于基于生成的模型,利用 ? 和 ?? 中的来优化带有标签 ?? 的模型。当预测头实体时,在输入序列中添加一个特殊的token( [reverse])以进行反向推理。用特殊的tokens表示知识图谱中的实体和关系,并得到如下输入:

其中,[Entity h]表示头实体的特殊token。为编码图结构,对1跳邻居实体进行采样,并将它们连接起来作为隐式结构信息的输入。

通过统一的知识图谱编码器,PromptKG可以编码异构的图结构和丰富的文本语义信息。

模型中心(Model Hub)

PromptKG由一个模型中心组成,支持许多基于文本的知识图谱表示模型。例如,KG-BERT使用BERT对三元组及其描述进行评分。但KG-BERT具有较高的时间复杂度,StAR和SimKGC都引入了一种基于塔的方法( a tower-based method)来预计算实体嵌入并高效地检索top-?实体。此外,GenKGC和KGT5将知识图谱补全视为序列到序列(seq2seq)的生成方法。此外,?NN-KGE是一种通过k近邻线性插值其实体分布的知识图谱表示模型。

模型支持的下游任务

应用到下游任务(Applying to Downstream Task)

以基于提示学的知识图谱表示学习为例,如下图所示:

  • 对于知识图谱补全,向模型输入头实体和关系的文本信息⟨?,??⟩,然后通过掩码token预测获得目标尾实体。
  • 对于问答,向模型输入用自然语言编写的问题,并将其与[MASK] token连接起来,以获得目标答案(实体)的特殊token。
  • 在推荐方面,将用户的交互历史作为实体嵌入的顺序输入,然后利用掩码token预测来获得推荐项目。
  • 对于知识探测任务,采用实体嵌入作为额外的知识,以帮助模型更好地通过句子进行推理,并预掩码位置的token,遵循PELT。
知识图谱表示学习应用于不同的下游任务

Entity_t指不同任务的目标尾实体、答案实体、推荐项目和目标尾实体,它遵循预训练(获得嵌入)和微调范式(特定任务调优)。

实验结果

1)基于文本信息的知识图谱补全(链接预测)是知识图谱表示的直接下游任务;
2)问答是一种直观的知识密集型任务;
3)推荐涉及与真实世界知识图谱中的实体对齐,因此可以从知识图谱表示中受益;
4)知识探究(LAMA)利用完形问句分析语言模型中包含的事实知识和常识知识。

知识补全(Knowledge Graph Completion)

针对知识图谱补全任务,论文在数据集WN18RRFB15k-237上进行了链接预测实验,并在PromptKG上使用hits1和MRR指标对模型进行了评估。从表中,基于判别的方法SimKGC比其他基线模型取得了更高的性能。KGT5和GenKGC等基于生成的模型也产生了可比较的结果,并显示了知识图谱表示的潜在能力。?NN-KGE可以从知识存储中通过计算最近邻居实体嵌入空间的距离和两步训练策略的来获得最佳hits1分数。

知识问答(Question Answering)

将PromptKG应用于问答系统,并在MetaQA数据集上进行实验。由于计算资源的限制,论文只评估了1跳推断性能。从表中可以看出,PromptKG中的KGT5具有最佳性能。

知识推荐(Recommendation)

对于推荐任务,在一个完善的版本ML-20m上进行了实验。利用ML-20m与KB4Rec提供的Freebase的链接,获取ML-20m中电影的文本描述。在这些描述上预训练电影嵌入后,按照BERT4Rec的设置在顺序推荐任务上进行了实验。与BERT4Rec相比,PromptKG被证实是有效的推荐。

知识探索(Knowledge Probing)

知识探索检查语言模型(BERT、RoBERTa等)召回事实的能力。使用预训练BERT (BERT -base-uncase)和RoBERTa (RoBERTa -base)模型在LAMA上进行实验。为证明由知识图谱增强的实体嵌入有助于语言模型从预训练中获取更多事实知识,训练了一个遵循PELT的可插拔实体嵌入模块。
如表所示,当使用实体嵌入模块时,性能有所提高。由于Squad中没有标注的主题实体,Concept Net中也没有对应主题实体的URI进行实体对齐,因此只对LAMA中的剩余数据进行实体嵌入。

结论

论文提出PromptKG,一种知识图谱表示学习和应用的提示学习框架。PromptKG建立了一个统一工具包,该工具包具有定义明确的模块和易于使用的接口,以支持在知识图谱上使用PLMs的研究。PromptKG为研究人员和开发人员提供有效和高效的训练代码,并支持下游任务。

PMP-十五至尊图

项目是为创造独特的产品、服务或成果而进行的临时性工作

知识领域启动过程组规划过程组执行过程组监控过程组收尾过程组
项目整合管理1. 制定项目章程2. 制定项目管理计划3. 指导与管理项目工作
4. 管理项目知识
5. 监控项目工作
6. 实施整体变更控制
7. 结束项目或阶段
项目范围管理1. 规划范围管理
2. 收集需求
3. 定义范围
4. 创建WBS
5. 确认范围
6. 控制范围


项目进度管理
1. 规划进度管理
2. 定义活动
3. 排序活动
4. 顺序估算活动持续时间
5. 制定进度计划
5. 控制进度
项目成本管理1. 规划成本管理
2. 估算成本
3. 制定预算
4. 控制成本
项目质量管理1. 规划质量管理2. 管理质量3. 控制质量
项目资源管理1. 规划资源管理
2. 估算活动资源
3. 获取资源
4. 建设团队
5. 管理团队
6. 控制资源
项目沟通管理1. 规划沟通管理2. 管理沟通3. 监督沟通
项目风险管理1. 规划风险管理
2. 识别风险
3. 实施定性风险分析
4. 实施定量风险分析
5. 规划风险应对
6. 实施风险应对7. 监督风险
项目采购管理1. 规划采购管理2. 实施采购3. 控制采购
项目相关方管理1. 识别相关方2. 规划相关方参与3. 管理相关方参与4. 监督相关方参与
十五至尊图
项目数据、信息和报告流向

论文笔记:Semantics Driven Embedding Learning for Effective Entity Alignment

论文:https://github.com/zhongziyue/SDEA/tree/main/paper

代码:https://github.com/zhongziyue/SDEA

SDEA一种语义驱动的实体嵌入方法,用于实体对齐。SDEA由属性嵌入和关系嵌入两个模块组成。属性嵌入通过预训练的基于transformer的语言模型从属性值中捕获语义信息。关系嵌入使用带有注意力机制的GRU模型选择性地聚合邻居节点的语义信息。属性嵌入和关系嵌入都以语义为驱动,在实体之间建立桥梁。

为了更好地捕捉实体内在的语义(主要体现在长文本属性值中),并有效识别邻居实体在对齐过程中的贡献,提出了一种语义驱动的实体嵌入方法SDEA。该文采用两个嵌入模块,即属性嵌入和关系嵌入。在属性嵌入模块中,使用基于transformer的预训练语言模型来获得每个实体的初始嵌入。最重要的是,该模块捕获了细粒度语义和实体的直接关联。进一步,关系嵌入模块通过注意力机制从属性嵌入的细粒度语义中学习邻近实体的贡献,并选择性地聚合来自邻近实体的信息。此外,从属性嵌入(保留实体的语义)和关系嵌入(聚合邻居实体的语义)进行联合表示学习,以发现实体之间的间接关联。

SDEA框架

属性嵌入模块(Attribute Embedding Module)

属性嵌入模块旨在从实体的属性值中捕获实体之间的语义关联。属性值不仅包括短文本和数字,还包括长句子。从属性值中捕获语义信息一直是一个挑战。为了解决这个问题,使用Transformer,该模型在捕获文本语义信息方面达到了最先进的性能,以处理文本中的异构性。此外,为了处理不同KG模式的异构性,通过将实体的所有属性值组合为一个整体来捕获细粒度语义,然后捕获两个实体之间的语义关联。将属性嵌入形式化为BERT的下游任务,即对预训练的BERT进行微调,将实体ei的属性值编码为属性嵌入Ha(ei)在以下两个阶段。

1)数据预处理:此阶段旨在将实体ei的属性值转换为序列,即一系列tokens,然后可以将其输入到BERT模型中。算法1描述了该步骤的总体过程。

例如,下图说明了算法1中的过程。

2)属性编码:此阶段将前一步生成的序列作为输入,目的是通过BERT模型将序列转换为嵌入。使用预训练的BERT模型和MLP (Multi-Layer Perceptron)层,通过对实体ei的属性序列S(ei)进行编码,得到属性嵌入向量Ha(ei)。

关系嵌入模块(Relation Embedding Module)

在关系嵌入模块中,使用基于GRU的注意机制来建模邻居的贡献,并选择性地聚合这些信息。直观地说,给定一个实体ei,它的邻居ej的贡献将取决于ei的其他邻居。替代方法包括平均邻居的嵌入、池化和直接使用注意机制。相比之下,Bidirectional GRU (BiGRU)模型能够捕捉ei不同邻居之间的相关性,从而可以根据上下文信息(周围邻居)对不同实体的同一邻居的不同贡献进行建模。

用BiGRU捕获邻居间的相关性,直观地,将实体ei的所有邻居作为BiGRU模型的输入序列。注意机制使模型能够利用每个邻居的重要性,从邻居中提取最相关的信息。

联合实体表示(Joint Entity Representation)

给定一个实体ei,属性嵌入模块和关系嵌入模块分别计算其属性嵌入Ha(ei)和关系嵌入Hr(ei),分别从属性和邻居中获取信息。为了联合建模来自属性和邻居的信息,计算了一个联合表示Hm(ei),通过一个MLP层将Ha(ei)和Hr(ei)结合在一起。

因此,三个嵌入Ha(ei)、Hr(ei)和Hm(ei),分别捕获属性信息、邻居信息以及联合属性和邻居信息。最后的实体嵌入内容(ei)是这些嵌入的连接,它捕获信息的所有三个方面。

论文笔记:SelfKG: Self-Supervised Entity Alignment in Knowledge Graphs

前言

论文:https://arxiv.org/pdf/2203.01044.pdf

代码:https://github.com/THUDM/SelfKG

摘要

实体对齐是构建网络规模知识图谱的一个基本问题,旨在识别不同知识图谱中的等价实体。在其发展过程中,标签监督被认为是准确对齐的必要条件。受自监督学习最近进展的启发,探讨了在实体对齐中可以在多大程度上摆脱监督。通常,标签信息(正实体对)用于监督将每个正实体对中的对齐实体拉得更近的过程。然而,论文的理论分析表明,在实际实体对齐的学习中,将未标记的负对推远比将标记的正对拉近受益更多。利用这一发现,为实体对齐制定了自监督学习目标。论文提出SelfKG的有效策略来优化这一目标,以对齐没有标签监督的实体。在基准数据集上的广泛实验表明,无监督的SelfKG可以与最先进的有监督基线相匹配或取得相当的结果。SelfKG的性能表明,自监督学习为知识图谱中的实体对齐提供了巨大的潜力。

挑战

基于表示学习的对齐方法以其优越的灵活性和准确性成为实体对齐的主流解决方案。然而,它们的成功在很大程度上依赖于人工标注提供的监督信息,而对于网络规模的知识图谱来说,这可能是有偏差的,而且获取起来成本非常高。鉴于这一基本挑战,本文旨在探索在没有标签监督的情况下,跨知识图谱对齐实体的潜力。

继续阅读论文笔记:SelfKG: Self-Supervised Entity Alignment in Knowledge Graphs

论文笔记:Supporting Clustering with Contrastive Learning

论文:https://arxiv.org/pdf/2103.12953.pdf

代码:https://github.com/amazon-science/sccl

概述

无监督聚类的目的是根据在表示空间中测量的一定距离发现数据的语义类别。然而,在学习过程的开始阶段,不同的类别往往在表示空间中相互重叠,这对基于距离的聚类在实现不同类别之间的良好分离提出了重大挑战。为此,论文提出了用对比学习支持聚类(SCCL)——一个利用对比学习促进更好分离的新框架。论文实验证明SCCL在利用自底向上实例识别和自顶向下聚类的优势方面的有效性,在使用真实聚类标签进行评估时,可以获得更好的簇内和簇间距离。

即使使用深度神经网络,在聚类开始之前,数据在不同类别之间仍然存在显著重叠。因此,通过优化各种基于距离或相似度的聚类目标学习到的聚类纯度较低。

实例对比学习(Instance-CL)通常在通过数据增强获得的辅助集上进行优化。顾名思义,对比损失用于将原始数据集中同一实例的增强样本拉到一起,而将不同实例的增强样本推开。Instance-CL将不同的实例分散开来,同时在某种程度上隐式地将相似的实例聚集在一起。通过将重叠的类别分散开来,可以利用这种有益的属性来支持聚类。然后进行聚类,从而更好地分离不同的簇,同时通过明确地将该簇中的样本集中在一起,使每个簇更紧密。如图所示:

继续阅读论文笔记:Supporting Clustering with Contrastive Learning

知识补全和问答方法调研

Pipeline方法

知识补全链接预测

SQUIRE: A Sequence-to-sequence Framework for Multi-hop Knowledge Graph Reasoning

数据集知识库比较小

SMORE: KNOWLEDGE GRAPH COMPLETION AND MULTI-HOP REASONING IN MASSIVE KNOWLEDGE GRAPHS

算法SMORE适用于较大知识库

知识问答

Subgraph Retrieval Enhanced Model for Multi-hop Knowledge Base Question Answering

子图检索和推理过程是解耦的,基于embedding-based KBQA的SOTA方法。子图检索和推理过程是pipline的。

基于pipeline方法总结

1、知识补全两篇论文中只做了链接预测相关的实验,没有给出下游问答的任务

联合训练

Sequence-to-Sequence Knowledge Graph Completion and Question

KGT5算法:链接预测和问答联合训练

该算法的局限

KGT5在归纳不可见的事实方面表现较好,但在记忆事实方面表现较差。如果需要,可以使用KGT5与常规链路预测或KGQA系统的集成来缓解这个问题。

作者不建议使用KGT5作为独立的KGQA方法,只应在查询解析不能产生良好结果的情况下使用它。

知识表示学习方法调研

NeuralKG

https://github.com/zjukg/NeuralKG

NeuralKG: An Open Source Library for Diverse Representation Learning of Knowledge Graphs

ComponentsModels
KGEModelTransE(2013), TransH(2014), TransR(2015), ComplEx(2016), DistMult(2014), RotatE(2019), ConvE(2018), BoxE(2020), CrossE(2019), SimplE(2018)
GNNModelRGCN(2017), KBAT(2019), CompGCN(2020), XTransE(2020)
RuleModelComplEx-NNE+AER(2018), RUGE(2018), IterE(2019)

知识表示学习常用的方法

来自第四范式技术分享

https://yeu.h5.xeknow.com/sl/3BzAvx

https://github.com/AutoML-Research

Triplet-based models

Translational Distance Model(TDM)

2013,TransE

2014,TransH

2019,TotatE

Neural Network Model(NNM)

2014,MLP

2018,ConvE

2020,RSN

BiLinear Model(BLM)

2011,RESCAL,关系为方阵

2014,DistMult,关系为对角矩阵

2016,CompIEx,

2017,Analogy

2018,SimpIE

2019,QuatE

2020,AutoSF,BLMs – unified form

2021,AutoSF+,An AutoML approach to design bilinear scoring functions

Bilinear models are the best choice in triplet-based models

Relational path

2015,PTransE

2019,RSN,Models long-term information well, but is limited in modeling short-term information

2020,Insterstellar,A NAS approach to recurrently process the relational paths

The relational paths contain richer information than triplets

GCN-variants

2017,R-GCN

2020,CompGCN

2020,GraIL,Enclosing subgraph -> Entity labeling – > GNN scoring

2021,KE-GCN

2022,RED-GNN

论文笔记:HAO Unity: A Graph-based System for Unifying Heterogeneous Data

HAO Unity系统架构

基于图的异构数据集成系统HAO Unity,HAO Unity系统整体框架如下图所示,主要组件包括:物理统一组件、语义统一组件、数据探索组件。物理统一组件负责通过属性图交换不同格式的数据。语义统一组件则从两方面来统一属性图中的异构数据:schema和instance。数据探索组件提供一个查询元数据、实体和关系信息的接口,方面用户了解集成后的数据,并进一步构建下游应用。

继续阅读论文笔记:HAO Unity: A Graph-based System for Unifying Heterogeneous Data

D2R调研

RDB2RDF

官方 RDB2RDF 标准,W3C 的 RDB2RDF 工作小组制定的两个标准,用于将关系型数据库的数据转换为RDF格式的数据。

1、Direct Mapping of Relational Data to RDF

The Direct Mapping is an automatic mapping of a relational database to RDF.

ps:不可自定义的默认映射。当关系数据很好地规范化,有主键,外键等时,直接映射是合适的。缺点:不能把数据库的数据映射到自己定义的本体上。

2、R2RML: RDB to RDF Mapping Language

R2RML is a customizable language to map a relational database to RDF.

ps:可自定义的映射。

RDB2RDF工具

Ontop

Ontop is a Virtual Knowledge Graph system. It exposes the content of arbitrary relational databases as knowledge graphs. These graphs are virtual, which means that data remains in the data sources instead of being moved to another database.

Ontop translates SPARQL queries expressed over the knowledge graphs into SQL queries executed by the relational data sources. It relies on R2RML mappings and can take advantage of lightweight ontologies.

SparqlMap

A SPARQL to SQL rewriter based on R2RML specification.

D2RQ

D2RQ 提供了自己的 mapping language(D2RQ Mapping Language),其形式和 R2RML 类似。

Triplify

 Triplify is a small PHP plugin for Web applications, which reveals the semantic structures encoded in relational databases by making database content available as RDF, JSON or Linked Data.

D2RQ

D2RQ的官方介绍是Accessing Relational Databases as Virtual RDF Graphs。http://d2rq.org/

D2RQ 工具,它的主要功能是提供以虚拟的、只读的RDF图形式进入到关系型数据库中。比如通过SPARQL端口查询,输入是SPARQL查询语言,D2RQ通过mapping文件将其转换为SQL语句在关系数据库上查询,因此实际上访问的是关系型数据库。同时也可以使用它从数据库创建 RDF 格式的文件。

D2RQ 由自己的mapping语言,R2RML-kit。它和W3C推荐的R2RML类似。可以通过D2RQ提供的工具来根据数据库自动生成mapping文件。也可以根据自己的需求去修改定制mapping文件。

D2RQ的框架

  • D2RQ主要包括 D2RQ Server, D2RQ Engine 以及 D2RQ Mapping 语言。
  • D2RQ Server是一个HTTP Server,它的主要功能提供对RDF数据的查询访问接口,以供上层的RDF浏览器、SPARQL查询客户端以及传统的HTML浏览器调用。
  • D2RQ Engine的主要功能是使用一个可定制的D2RQ Mapping文件将关系型数据库中的数据换成RDF格式。D2RQ engine并没有将关系型数据库发布成真实的RDF数据,而是使用D2RQ Mapping文件将其映射成虚拟的RDF格式。该文件的作用是在访问关系型数据时将RDF数据的查询语言SPARQL转换为RDB数据的查询语言 SQL,并将SQL查询结果转换为RDF三元组或者SPARQL查询结果。D2RQ Engine是建立在Jena(Jena是一个创建Semantic Web应用的Java平台,它提供了基于RDF,SPARQL等的编程环境)的接口之上。
  • D2RQ Mapping一种用于将关系数据库模式映射到 RDF 词汇表和 OWL 本体的声明性语言。

D2RQ提供的功能

  • 使用 SPARQL 查询非 RDF 数据库
  • 通过 Web 以链接数据的形式访问数据库的内容
  • 以 RDF 格式创建数据库的自定义转储以加载到 RDF 存储中
  • 使用 Apache Jena API 访问非 RDF 数据库中的信息

Ontop和D2RQ比较

R2RML的文档(W3C推荐的映射语言)相比D2RQ mapping的表达能力和文档更清晰,且表达能力更强。D2RQ翻译SPARQL2SQL的过程缺乏query optimization,在大数据情况下性能比较差,经常会出现timeout或OOM(内存消耗比较严重的情况)。此外,他不支持推理。虽然D2RQ可以将KG映射到Jena Model上,通过Jena Reasoner在其上做各种inference,但是效率有很大的问题。而Ontop是支持推理的(backward chaining)。

结论

以虚拟RDF图的方式访问关系数据库是其最主要的一个特性。它的机理就是通过mapping文件,把对RDF的查询等操作翻译成SQL语句,最终在RDB上实现对应操作。当对外提供服务,查询操作比较频繁的情况下,最好是将RDB的数据直接转为RDF,会节省很多SPARQL到SQL的转换时间。

KMeans跑满CPU

问题描述

在调用sklearn.cluster中的KMeans时,cpu占用达100%,比如40核的cpu,最高4000%的cpu占用率

尝试解决方案

scikit-learn版本为0.24.2

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=k, random_state=123)
kmeans.fit(self.embeddings)
cluster_centers = kmeans.cluster_centers_
labels = kmeans.labels_

scikit-learn在0.23版本时会有n_jobs参数可以设置线程数,但是在降低版本之后,设置n_jobs参数依然会跑满cpu。下图是官方文档对n_jobs的解读。

考虑到之后高版本不会再使用n_jobs参数,所以未深究其中原因。

最终解决方案

在启动服务时设置线程数量可以解决该问题,如果设置为4个线程

OMP_NUM_THREADS=4 python run.py