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

论文笔记:RNG-KBQA: Generation Augmented Iterative Ranking for Knowledge Base Question Answering

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

整体架构

Enumeration of Candidates

实体识别和实体链接

Logical Form Ranking

排名器是基于BERT双编码器(以输入问题-候选对作为输入)经过训练,以最大限度地提高基本事实逻辑形式的分数,同时最大限度地减少不正确候选者的分数。

扩展了提出的逻辑形式排序器,保持架构和逻辑相同,用于实体消歧任务,并展示其作为第二阶段实体排序器的有效性。

Target Logical Form Generation

有了候选的排名列表,引入了一个生成模型来组成以问题为条件的最终逻辑形式和我们的排名器返回的前 k 个逻辑形式。 生成器是从 Raffel 等人实例化的基于转换器的 seq-to-seq 模型,因为它在生成相关任务中表现出强大的性能。 如图所示,通过连接问题和由分号分隔的排名器返回的前 k 个候选者(即 [x; ct1; …; ctk])来构建输入。

GRAILQA 是第一个评估零样本泛化的数据集。 具体来说,GRAILQA 总共包含 64,331 个问题,并仔细拆分数据,以评估 KBQA 任务中的三个泛化级别,包括 i.i.d. 设置、构图设置(泛化到看不见的构图)和零镜头设置(泛化到看不见的 KB 模式)。 我们在图中展示了组合泛化( compositional generalization )和零样本泛化( zero-shot generalization)的示例。测试集中每个设置的分数分别为 25%、25% 和 50%。 除了泛化挑战之外,GRAILQA 还存在额外的困难,包括大量涉及的实体/关系、逻辑形式的复杂组合性(最多 4 跳)以及问题中提到的实体的噪声。

论文笔记:Complex Knowledge Base Question Answering: A Survey

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

这篇论文是复杂KBQA方面的一篇综述。介绍了复杂 KBQA 的两大主流方法,即基于语义解析( semantic parsing-based, SP-based)的方法和基于信息检索(information retrieval-based, IR-based)的方法。从这两个类别的角度回顾了先进的方法并解释了对典型挑战的解决方案。

论文动机

Who is the first wife of TV producer that was nominated for The Jeff Probst Show?

  1. 在知识图谱中做多跳推理 (multi-hop reasoning)
  2. 考虑题目中给的限制词 (constrained relations)
  3. 考虑数字运算的情况 (numerical operations)

知识图谱问答系统思路

  1. 实体连接 (entity linking),识别问题q的主题实体eq,其目的是将问题链接到知识库中的相关实体。在这一步中,进行命名实体识别、消歧和链接。通常使用一些现成的实体链接工具来完成,例如 S-MART、DBpediaSpotlight和 AIDA;
  2. 利用答案预测模块来预测答案 Aq。可以采用以下两种方法进行预测:
      1. 基于语义解析 (SP-based) 方法:将问题解析为逻辑形式,并针对知识库执行以找到答案;
    • 基于信息检索 (IR-based) 方法:检索特定于问题的图并应用一些Rank算法从顶部位置选择实体。
  3. 最后,将 KBQA 预测得到的预测答案 Aq 作为系统输出返回给用户

遇到的挑战

直接将传统知识图谱问答模型运用到复杂问题上,不管是基于语义解析的方法还是信息检索的方法都将遇到新的挑战

  1. 传统方法无法支撑问题的复杂逻辑
    • 现有的 SP-based 的方法中使用的解析器难以涵盖各种复杂的查询(例如,多跳推理、约束关系和数值运算)。
    • 以前的 IR-based 的方法可能无法回答复杂的查询,因为它们排名是在没有可追溯推理的情况下对小范围实体进行的。
  2. 复杂问题包含了更多的实体,导致在知识图谱中搜索空间变大:这两种方法都将问题理解视为首要步骤。当问题在语义和句法方面变得复杂时,模型需要具有强大的自然语言理解和泛化能力。
  3. 通常 Complex KBQA 数据集缺少对正确路径的标注:这表明 SP-based 的方法和 IR-based 的方法必须分别在没有正确逻辑形式和推理路径注释的情况下进行训练。这种微弱的监督信号给这两种方法带来了困难。

论文笔记:improving-multi-hop-question-answering-over-knowledge-graphs-using-knowledge-base-embeddings

论文:https://aclanthology.org/2020.acl-main.412.pdf

论文概述

这篇文章结合知识补全的思想来改善知识库问答。通过自然语言理解这个问句并从知识库中寻找正确答案实体。多跳的问答则需要对关系路径进行推理。由于知识库不充分原因,现有的工作引入额外的文本弥补知识库稀疏问题。另外也有工作是通过目标实体从知识库中抽取多跳范围内的子图,在该子图内进行答案的检索。作者认为这是一种启发式的划定答案所在的领域。

稀疏和不完整 KG 中多跳 QA over Knowledge Graphs (KGQA) 的挑战:当寻找对应的答案时,由于知识库不充分,“Louis Mellis”与答案“Crime”没有直接的边相连,则需要经过较长的路径推理。而启发式的设定跳数为3时(灰色区域),使得答案不在这个领域内,促使无法寻找到答案。

本文的贡献点在于:

(1)首次将知识库表征引入知识库问答任务;

(2)不需要启发式地设定具体的领域范围;

整体架构

KG Embedding Module

作者使用ComplEx算法对整个知识库中的实体和边嵌入到固定大小的向量,作者之所以选择ComplEx算法,是因为该算法采用的是张量分解法,更能够捕捉更全面的特征。但在具体实验中,只获取实部的参数。

Question Embedding Module

对于问句 q, 作者使用 RoBERTa 预训练语言模型获得768维度的向量,并通过4层全连接层(激活函数为ReLU)映射到与知识表示相同维度的空间。在微调过程中,作者将问句替换到得分函数中的关系,这是一个比较巧妙的创新点,其借助ComplEx(或者说是知识表示学习的方法)的得分函数 ϕ 和排序损失函数训练的机制,促使目标实体 h和答案 t 之间的语义关系是问句q在复数空间中的表示。因为在有的知识库比较大,候选关系非常多,因此作者使用标签平滑方法。

Answer Selection Module

这一部分是核心,在已知知识图谱表征、每个三元组的得分以及问句的表征后,需要对候选答案进行筛选。对于知识库不大的可以按照上述的方法计算,但对于知识库较大的,则需要对候选的答案集合进行缩减(pruning),作者借鉴了PullNet算法,提出一种简单的缩减方法(Relation Matching)。

PyTorch训练模型转ONNX

方法一

加载Pipeline

从transformers库中加载FeatureExtractionPipeline。如果知道要使用的模型的所有输入形状和配置,则可以不需要此步骤。使用 convert_graph_to_onnx 中的相应函数可以显着简化自定义模型的创建。生成的变量将用于torch导出调用。

from transformers import FeatureExtractionPipeline, AutoModel, AutoTokenizer, convert_graph_to_onnx

model_access = "my_model_dir"
model_pipeline = FeatureExtractionPipeline(
        model=AutoModel.from_pretrained(model_access),
        tokenizer=AutoTokenizer.from_pretrained(model_access, use_fast=True),
        framework="pt",
        device=-1)

config = model_pipeline.model.config
tokenizer = model_pipeline.tokenizer

with torch.no_grad():
    input_names, output_names, dynamic_axes, tokens = convert_graph_to_onnx.infer_shapes(model_pipeline, "pt")
    ordered_input_names, model_args = convert_graph_to_onnx.ensure_valid_input(
            model_pipeline.model, tokens, input_names)

# 如果想添加更多的输出,则必须相应地修改dynamic_axes和output_names。
del dynamic_axes["output_0"]  # Delete unused output
del dynamic_axes["output_1"]  # Delete unused output

output_names = ["output"]
dynamic_axes["output"] = {0: 'batch'}

# 导出模型到ONNX
model = torch.load("best_model.pth")
output = "best_model.onnx"
torch.onnx.export(
        model,
        model_args,
        f=output,
        input_names=input_names,
        output_names=output_names,
        dynamic_axes=dynamic_axes,
        do_constant_folding=True,
        use_external_data_format=False,
        enable_onnx_checker=True,
        opset_version=11)

# 检查 onnx model
onnx_model = onnx.load(output)
onnx.checker.check_model(onnx_model)
print('The model is checked!')

加载onnx模型进行推理

import numpy as np
from transformers import AutoTokenizer
import onnxruntime as rt
import time

onnx_model_path = "best_model.onnx"
model_path = "best-checkpoint"  # my_model_dir
tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False)
span = "输入"  # 输入的文本

opt = rt.SessionOptions()
sess = rt.InferenceSession(onnx_model_path)  # Loads the model
t0 = time.perf_counter()
model_input = tokenizer.encode_plus(span)
model_input = {name: np.atleast_2d(value) for name, value in model_input.items()}
onnx_result = sess.run(None, model_input)
onnx_result = onnx_result[0]
onnx_result = np.argmax(onnx_result, axis=-1)
print(time.perf_counter() - t0)

方法二

pt2onnx

import os
import torch
from transformers import BertTokenizer, get_linear_schedule_with_warmup,BertForSequenceClassification, AdamW
import onnx

def pt2onnx_bert():
    pretrained_model = '../model/bert-base-chinese'
    onnx_path = 'api/onnx/bert-base-chinese-cls.onnx'
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    tokenizer = BertTokenizer.from_pretrained(pretrained_model)
    model = BertForSequenceClassification.from_pretrained(pretrained_model)
    model.eval()
    model.to(device)

    input_names = ['input_ids', 'attention_mask', 'token_type_ids']
    outputs_names = ['output']
    # 构造输入
    inputs = '输入'
    encode_dict = tokenizer.encode_plus(text=inputs,
                                        max_length=512,
                                        pad_to_max_length=True,
                                        return_tensors='pt',
                                        return_token_type_ids=True,
                                        return_attention_mask=True)

    input_ids = encode_dict['input_ids']
    attention_mask = encode_dict['attention_mask']
    token_type_ids = encode_dict['token_type_ids']

    dummy_input = {
        'input_ids': input_ids,
        'attention_mask': attention_mask,
        'token_type_ids': token_type_ids
    }
    with torch.no_grad():
        torch.onnx.export(model=model,
                          args=tuple(dummy_input.values()),
                          f=onnx_path,
                          opset_version=11,
                          input_names=input_names,
                          output_names=outputs_names,
                          dynamic_axes={'input_ids': {0: 'batch_size'},
                                        'attention_mask': {0: 'batch_size'},
                                        'token_type_ids': {0: 'batch_size'},
                                        'output': {0: 'batch_size'}}
                          )
    # 验证
    print(onnx.checker.check_model(onnx_path))

推理

from onnxruntime import GraphOptimizationLevel, InferenceSession, SessionOptions, get_all_providers

def create_model_for_provider(model_path: str, provider: str) -> InferenceSession:
    assert provider in get_all_providers(), f"provider {provider} not found, {get_all_providers()}"

    options = SessionOptions()
    #控制线程数
    options.intra_op_num_threads = 0
    options.graph_optimization_level = GraphOptimizationLevel.ORT_ENABLE_ALL
    session = InferenceSession(model_path, options, providers=[provider])
    return session

def onnx_inference(x):
    #CPUExecutionProvider
    ort_session = create_model_for_provider(onnx_model_path, 'CUDAExecutionProvider')
    encode_dict = tokenizer.batch_encode_plus(batch_text_or_text_pairs=x,
                                              max_length=MAX_SEQ_LEN,
                                              pad_to_max_length=True,
                                              return_tensors='pt',
                                              return_token_type_ids=False,
                                              return_attention_mask=True)

    inputs = {k: v.numpy() for k, v in encode_dict.items()}
    outputs = ort_session.run(None, inputs)
    # 不同的模型对应不同的以下代码
    outputs = outputs[0]
    outputs = np.argmax(outputs, axis=-1)
    result = []
    for out in outputs:
        result.append(id2label[out])
    return result

Cython编译python

from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension

extensions = [
    Extension(name='name1',
              sources=['source file'],
              include_dirs=['head files'],
              libraries=['library names'],
              library_dirs=['library directories']),
    Extension(name='name2',
              sources=['source file'],
              include_dirs=['head files'],
              libraries=['library names'],
              library_dirs=['library directories'])
]
# setup.py 放在 sources同目录
# 按照上述方式配置,会生成两个so,name1.so和name2.so
# 命令:python setup.pu build_ext,同时生成c文件和so
setup(
    name='name',
    # language_level=3指定python3
    ext_modules=cythonize(extensions, language_level=3)
)

参考

https://github.com/oborchers/sentence-transformers/blob/72da7293186700bff4fed8e81adcfe40a03be1d2/examples/onnx_inference/onnx_inference.ipynb

https://zhuanlan.zhihu.com/p/422290231

服务器后台远程复制文件scp

正常执行scp命令

从一台服务器复制文件夹到另一台服务器

scp -r origin_dir ip:target_dir

输入Ctrl+z暂停任务

使用bg命令将其放入后台

bg %1

使用jobs查看状态,已经在后台运行了

disown -h 将这个作业忽略HUP信号

查看运行状态和父进程号

ps -ef | grep scp

测试会话中断,任务继续运行不受影响

首先退出

exit

然后再查看状态

ps -ef | grep scp

参考

https://blog.csdn.net/sraing/article/details/85121543

论文笔记:Few-Shot Learning with Siamese Networks and Label Tuning

前言

论文:https://arxiv.org/pdf/2203.14655v2.pdf

代码:https://github.com/symanto-research/few-shot-learning-label-tuning

摘要

在训练数据很少或没有训练数据的情况下构建文本分类器的问题,通常称为零样本和小样本文本分类。近年来,一种基于神经文本蕴涵模型的方法已被发现在不同的任务范围内提供强大的结果。在这项工作中表明,通过适当的预训练,嵌入文本和标签的Siamese网络提供了一个有竞争力的替代方案。这些模型大大降低推理成本:标签数量恒定,而不是线性。此外,还引入了标签调优,是一种简单且计算效率高的方法,它允许通过仅更改标签嵌入来在少量设置中适应模型。虽然提供比模型微调更低的性能,但这种方法具有体系结构上的优势,即单个编码器可以由多个不同的任务共享。

动机

  • 对于文本数据,任务的标签通常是通过文本形式来实现的,可以是标签的名称,也可以是简明的文本描述。
  • Cross Attention(CA)和Siamese Networks(SNs)还通过对小样本的模型进行微调来支持小样本学习。这通常是通过更新模型的所有参数来完成的,导致不能在不同任务之间共享模型。
  • 作者提出Label Tuning(LT)作为完全微调的替代方案,它允许对许多任务使用相同的模型,从而极大地增加了方法的可伸缩性。

模型

图1 Overview of training and inference with Label Tuning (LT)

在训练时,输入和标签文本由编码器处理。然后Label Tuning(LT)使用交叉熵(CE)损失调优标签。在推理时,输入文本通过相同的编码器。然后使用调优的标签嵌入和相似度函数对每个标签进行评分。编码器保持不变,可以在多个任务之间共享。

方法

Fine-Tuning

在小样本学习的情况下,需要在小样本的基础上对模型进行调整。在基于梯度的小样本学习中,尝试提高带有标签的小样本的相似度分数。从概念上讲,希望增加每个文本及其正确标签之间的相似度,并减少每个其他标签之间的相似度。使用batch softmax作为目标:

其中B是batch size,S(x, y) = f(x)·f(y)是当前模型f下输入x与标签文本y的相似度。在batch中,所有其他元素都作为负样本。为此,使每个batch中只包含每个标签的一个样本。这类似于典型的softmax分类目标。唯一的区别是f(yi)是在前向传播中计算的,而不是作为一个简单的参数查找。

Label Tuning

定期微调的缺点是需要更新整个网络的权重。这导致每个新任务都需要较慢的训练和较大的内存需求,这反过来又增加了大规模部署新模型的挑战。作为一种替代方案,引入标签调优,它不改变编码器的权重。主要思想是首先预先计算每个类的标签嵌入,然后使用小样本对它们进行调优。有一个包含N对输入文本xi及其参考标签索引zi的训练集。预先计算输入文本的矩阵表示和标签的矩阵表示,X∈RN×d,Y∈RK×d,d为embedding的维数,K为标签集的大小。每个输入和标签组合的相似度分数定义为S = X × YT(S∈RN×K),并利用交叉熵进行调优。

为了避免过拟合,使用范数添加了一个正则化,惩罚偏离初始标签嵌入太远的位置。另外,还通过在标签embedding中每个梯度步上mask一些项实现dropout。通过在小样本上4折交叉验证进行微调。要为每个调优模型存储的唯一信息是d维标签嵌入。

Knowledge Distillation

标签微调产生的模型比实际的微调精确度低。可以通过知识蒸馏来补偿。首先训练一个标准的微调模型,并使用该模型为未标注的样本生成标签分布。之后,将该数据集用于训练未调优模型的新标签embedding。这增加了该方法的训练成本,并增加了对未标注数据的额外要求,但保留了在推断时可以跨多个任务共享一个模型的优点。

结论

论文证明了Cross Attention(CA)和Siamese Networks(SN)在不同的任务集和多种语言中提供了类似的结果。SNs的推理成本很低,因为标签embedding可以预先计算,而且与CA相比,SNs不随标签数量的增加而扩展。

只调优标签embeddings(LT)是可以替代微调(FT)方法的。当训练样本数量较少并且结合知识蒸馏时,即在小样本学习场景下,LT的性能接近FT。这与生产场景相关,因为它允许在任务之间共享相同的模型。LT是快速和可扩展的小样本学习下的一个选择。

论文笔记:Exploiting Cloze Questions for Few Shot Text Classification and Natural Language Inference

前言

论文:https://arxiv.org/pdf/2001.07676.pdf%EF%BC%89

代码:https://github.com/timoschick/pet

摘要

一些NLP任务通过使用预先训练好的带有“任务描述”的语言模型,可以以完全无监督的方式解决。虽然这种方法的性能不如监督方法,但本篇工作中表明,这两种思想可以结合起来:作者引入了Pattern-Exploiting Training(PET),一种半监督的训练过程,它将输入示例重新定义为完形句式短语,以帮助语言模型理解给定的任务。然后使用这些短语为大量无标签的样本分配软标签。最后,对得到的训练集进行标准监督训练。对于一些任务和语言,PET在低资源环境下的表现远远优于监督训练和强半监督方法。

模型架构

图1 PET for sentiment classification

PET的工作过程分为三个步骤:

首先,针对每个模式,在小训练集T上对单独的PLM进行微调。

然后,使用所有模型的集合对一个大型的无标签数据集D进行软标签标注。

最后,在软标记数据集上训练标准分类器。

作者还设计了iPET,这是PET的迭代变体,该过程随着训练集规模的增加而重复。

Pattern-Exploiting Training

参数概况

M为预训练语言模型,词表为V,mask token包含在V中,任务A的标签集合L,输入序列x包含k个短语或句子。

定义一个模型函数(pattern)P,将x作为输入,输出包含一个mask token的短语或句子P(x),输出可以看作是一个完形填空。

定义一个映射函数(verbalizer)v,L—>V将每个标签映射到M的词汇表中的一个单词。

将(P, v)称为pattern-verbalizer pair(PVP)。

PVP Training and Inference

给定某个输入x,我们定义标签l∈L的分数为:

并使用softmax获得标签上的概率分布:

使用交叉熵作为微调的损失。

Auxiliary Language Modeling

只使用少量样本进行训练,可能发生灾难性遗忘。对于基于PVP的PLM微调,核心仍然是一个语言模型,我们通过使用语言建模作为辅助任务来解决这个问题。LCE表示交叉熵损失,LMLM表示语言建模损失,计算最终损失为:

LMLM通常比LCE大得多,令α = 10−4

Combining PVPs

该方法面临的一个关键挑战是,在缺乏大型验证集的情况下,很难确定哪个PVPs表现良好。为了解决这个问题,使用了类似于知识蒸馏的策略。定义一个PVPs的集合P,直观地理解给定任务A的意义,按如下方法使用这些PVPs:

  1. 为每个p∈P微调一个单独的语言模型Mp
  1. 使用经过优化的模型的集合M = {Mp | p∈P}来标注集合D(未标注数据集合)。将每个样本x∈D的非归一化类分数合并为:

使用softmax将上述分数转换为概率分布q。使用T = 2得到适当的软分布。所有(x, q)对收集在一个(软标记的)训练集TC中。

  1. 在TC上,使用PLM微调得到模型C。经过优化的模型C作为对A的分类器。
图2 Schematic representation of PET (1-3) and iPET (a-c)

Iterative PET (iPET)

将所有单个模型的知识蒸馏到单个分类器中——意味着它们不能相互学习。由于有些模式的性能可能比其他模式差得多,因此最终模型的训练集TC可能包含许多标签错误的示例。为了弥补这个缺点,设计了iPET,它是PET的迭代变体。iPET的核心思想是在不断增大的数据集上训练几代模型。过程如图2所示。

  1. 对于每个模型,其他模型的一个随机子集通过标注D中的样本生成一个新的训练集。
  1. 使用更大的、特定于模型的数据集训练一组新的PET模型。
  1. 前两个步骤重复k次,每次都将生成的训练集的大小增加d倍。

经过训练k代PET模型,我们使用Mk创建TC和训练模型C在基本的PET。

结论

为预训练的语言模型提供任务描述可以与标准的监督训练相结合。PET方法包括定义成对的完形填空问题模式(patterns)和语言表达器(verbalizers),这有助于利用预训练的语言模型中包含的知识来完成下游任务。对所有模式-语言化器对的模型进行微调,并使用它们创建大型的带注释的数据集,标准分类器可以在这些数据集上进行训练。当初始训练数据量有限时,PET比标准监督训练和强半监督方法有很大的改进。

Git入门篇

git常用命令

请使用status命令确认工作树和索引的状态。

$ git status

将文件加入到索引,要使用add命令。在<file>指定加入索引的文件。用空格分割可以指定多个文件。

$ git add <file>..

指定参数「.」,可以把所有的文件加入到索引。

$ git add .

请执行如下显示的commit命令。

$ git commit -m “”

执行commit命令之后确认状态。

$ git commit -m “first commit”

$ git status

# On branch master

nothing to commit (working directory clean)

从status响应我们可以看到没有新的变更要提交。

使用log命令,我们可以在数据库的提交记录看到新的提交。

$ git log

可以将远程数据库命名为“origin”。

请使用remote指令添加远程数据库。在<name>处输入远程数据库名称,在<url>处指定远程数据库的URL。

$ git remote add <name> <url>

git remote add origin <git的http地址>

执行推送或者拉取的时候,如果省略了远程数据库的名称,则默认使用名为”origin“的远程数据库。因此一般都会把远程数据库命名为origin。

使用push命令向数据库推送更改内容。<repository>处输入目标地址,<refspec>处指定推送的分支。我们将在高级篇详细地对分支进行说明。

$ git push <repository> <refspec>…

运行以下命令便可向远程数据库‘origin’进行推送。当执行命令时,如果您指定了-u选项,那么下一次推送时就可以省略分支名称了。但是,首次运行指令向空的远程数据库推送时,必须指定远程数据库名称和分支名称。

$ git push -u origin master

使用clone指令可以复制数据库,在<repository>指定远程数据库的URL,在<directory>指定新目录的名称。

$ git clone <repository> <directory>

执行以下指令后,会在目录(test2) 复制远程数据库。

$ git clone <git的http地址> test2

test2进行的操作

然后,推送此次变更,更新远程数据库。

当在克隆的数据库目录执行推送时,您可以省略数据库和分支名称。

$ git push

从“test2”推送到远程数据库的内容拉取到数据库目录“test

使用pull指令进行拉取操作。省略数据库名称的话,会在名为origin的数据库进行pull。

$ git pull <repository> <refspec>…

test进行的操作

请执行以下指令。

$ git pull origin master

使用log指令来确认历史记录是否已更新。

$ git log

git远程分支覆盖本地分支

有时候同一个分支,远程的和本地的都被修改的面目全非了,如果想要把本地的替换成远程的,用下面的命令

git fetch –all

git reset –hard origin/master (这里master要修改为对应的分支名)

git pull

Git 全局设置

  • Git的设定被存放在用户本地目录的.gitconfig档案里。虽然可以直接编辑配置文件,但在这个教程里我们使用config命令。

git config –global user.name “banyungong”

git config –global user.email “banyungong@test.com”

  • 以下命令能让Git以彩色显示。

git config –global color.ui auto

  • 可以为Git命令设定别名。例如:把「checkout」缩略为「co」,然后就使用「co」来执行命令。

git config –global alias.co checkout

创建一个新仓库

git clone <url>

cd test

touch README.md

git add README.md

git commit -m “add README”

git push -u origin master

推到一个存在的文件夹中

cd existing_folder

git init # 然后使用init命令把该existing_folder目录移动到本地Git数据库。

git remote add origin <url>

git add .

git commit -m “Initial commit”

git push -u origin master

推到现有的 Git 仓库

cd existing_repo

git remote rename origin old-origin

git remote add origin <url>

git push -u origin –all

git push -u origin –tags

git管理代码的工作原则

  • 不同版本的代码,在同一个仓库,需要打上不同的tag
  • 开发要在分支上,例如dev分支
  • 使用开发分支上线,上线没有问题之后合入master,方便代码回滚(用master就可以代码回滚)
  • master的代码需和线上代码保持一致
  • 上线之后,给master打上tag,方便以后代码恢复
  • 以上线的版本代码都能有办法恢复
  • 版本迭代更新时,需要从master分支上拉代码到dev,再开始开发

上传代码到dev分支

git status
git add .
git commit -m "更新的功能"
git push origin dev

合并分支到master

git checkout master
git pull origin master
git merge dev
git status
git push origin master