1.背景介绍
概述
RPA(Robotic Process Automation,机器人流程自动化)
在过去几年里,由于技术的飞速发展,智能手机的普及,以及互联网的高速发展,人们越来越多地使用智能手机进行日常生活中重复性的事务处理工作。例如拍照、发送短信、接电话、办公等等。然而,面对繁杂的业务流程及其复杂的交互逻辑,传统的人工操作仍然是一个不可或缺的环节。为了更加有效地管理复杂的业务流程,从而减少人力成本并提升产品ivity,业务流程自动化(Business Process Automation, BPA)应运而生。
机器人流程自动化(RPA)也是基于现代信息技术和计算技术的业务流程自动化解决方案。它将人类的智慧注入到自动化的流程中,可以使整个流程从繁重的手工操作中解放出来,提高工作效率。基于RPA,企业可以实现全方位的业务流程自动化,包括人员流转、数据处理、合同管理、金融交易、物料采购等多个方面。RPA可用于各种规模的企业,包括小微企业、初创企业、中型企业、以及大型企业。
BPA业务流程自动化系统的核心功能主要包括以下五个模块:
- 模板匹配:通过分析和识别企业内部常用的业务流程模式,根据模板建立起一套标准化的工作流;
- 数据提取:自动从各类数据库、文件等获取数据,进一步提升数据的准确性、完整性、及时性;
- 数据转换:对获取的数据进行清洗、转换、拆分、整理,进一步完善企业内部数据的价值,降低数据管理难度;
- 规则引擎:利用规则语言,对数据进行流转控制、分配审批、数据记录、报告生成等操作;
- 自动化测试:模拟实际场景进行测试,验证系统运行是否符合预期效果,提升系统的稳定性。
当前,业界对于BPA的应用仍处于蓬勃发展阶段。据调研显示,全球超过90%的企业认为BPA能够显著提升生产效率、降低企业成本、改善客户体验。
GPT-3
另一种提升BPA能力的方法是采用AI技术。GPT-3(Generative Pre-trained Transformer-based Language Model),是一种基于Transformer编码器的大型、通用、深层次语言模型。目前已经证明其性能优于当今最先进的基于RNN、BERT的语言模型。GPT-3预训练得到的模型可以理解文本、推断文本、描述图像和音频、生成图像和音频,是一种具有广泛应用前景的AI模型。
基于GPT-3的BPA系统可以提供如下优点:
- 通过学习已有的业务流程模式,自动生成符合规范的标准工作流,极大地缩短了人工制作工作流的时间;
- 提供自动化数据提取、转换、清洗功能,通过机器学习算法,对数据进行高效率的分类、处理和存储;
- 在不依赖人工参与的情况下,完成复杂的自动化流程,不需要担心数据质量、准确性的问题;
- 有利于提升人力资源的利用率,通过利用计算机代替人工,可以大幅提升工作效率。
需求背景
业务流程自动化(BPA)解决的是复杂业务流程管理中的一个重要问题——复杂且易错的手动流程无法有效地提升工作效率。随着数字化进程的普及、全新的服务方式逐渐取代传统的方式,企业也在向数字化方向迈进。
传统的业务流程是由很多人的协同完成,每个人都需要按照固定顺序,依次处理相关文档,做出判断,甚至要输入命令。但随着业务的复杂度增加,工作流会变得越来越长,每个人的操作之间可能出现冲突,导致效率低下。因此,需要引入人工智能(AI)来帮助流程自动化的实施者来实现自动化。
当前,企业可以通过BPA系统来提升工作效率。但是,要想实现好的用户体验,还需要考虑以下几个方面:
- 用户使用习惯:用户从事不同岗位的角色,在使用流程自动化系统时,他们会有不同的使用习惯。不同角色的人会有不同的学习曲线,需要教授给予适合的知识和技能,才能正确的使用系统。同时,如果用户使用不当或者错误,可能会造成损失。因此,需要针对不同角色设计不同的系统界面。
- 帮助文档:如果企业没有自己的用户手册、帮助文档,那么用户只能靠自己摸索系统的用法,费时费力。需要制作一份系统使用的指南、使用教程、操作手册等,让用户快速上手,使用系统顺畅自如。
- 反馈机制:用户在使用过程中,如果遇到任何问题,都可以向系统反馈,系统会通过日志和报错等形式记录下来,便于问题追踪定位和排查。同时,系统可以及时响应用户的意见建议,提升用户体验。
- 数据安全:企业的数据安全尤为重要。对于保密数据,应该设置访问权限限制,只有授权人员才可以使用系统。另外,还要设定数据备份策略,确保数据的安全性。
本文将通过实践案例来展示如何通过GPT-3及其相关技术,提升BPA的用户体验。
2.核心概念与联系
工作流自动化
在RPA系统中,流程的自动化分为三个阶段:规则识别、实体识别、触发条件识别。
规则识别
在规则识别阶段,系统通过分析模板,找寻关键词、结构和语义等特征,对业务流程的结构进行抽象,形成一套规则集。如图所示,一条“销售”流程可能包含“创建订单”、“确认收货”、“支付款项”等子流程。而这条流程的结构往往是一致的,因此只需定义一次规则即可。这些规则可以被持久化保存,后续的自动化任务均可以直接引用该规则。
实体识别
在实体识别阶段,系统通过分析数据,发现企业内部存在的业务对象(实体)。如:产品、库存、经营者、销售订单、付款订单等。这些实体可以作为工作流的输入,即支持自动流转。
触发条件识别
在触发条件识别阶段,系统会识别到流转的触发条件。如:“新建订单”、“商品出库”、“申请支付”等事件发生时,系统应当触发相应的流程任务。
实例:
假设一家公司希望通过RPA系统,完成产品采购、订单结算、发票打印、运输配送等一系列复杂的业务流程,其中有些流程还涉及到财务部门的审批和风险控制。管理员需要设计出一套标准化的工作流,并且定义一些触发条件和实体。
规则识别:
- “产品采购”:采购申请。
- “订单结算”:填写付款单,确认订单金额。
- “发票打印”:打印发票,上传发票至服务器。
- “运输配送”:选择快递公司,提交物流单。
- “审批”:审批财务总账单、利润表。
- “风险控制”:评估投资组合的风险级别。
实体识别:
- 产品、库存、经营者、销售订单、付款订单、财务数据。
触发条件识别:
- 当订单状态为“新建”,触发“产品采购”流程。
- 当付款状态为“等待支付”,触发“订单结算”流程。
- 当物流状态为“准备发货”,触发“运输配送”流程。
- 当订单状态为“已付款”,触发“审批”流程。
- 当审批结果为“通过”,触发“发票打印”流程。
- 当投资组合的风险级别超过阀值,触发“风险控制”流程。
以上规则和实体以及触发条件组成了一个标准化的工作流。
3.核心算法原理和具体操作步骤以及数学模型公式详细讲解
AI模型简介
GPT-3模型结构非常复杂,包括17亿参数和8千万个神经元。GPT-3由两个部分组成:模型架构和训练策略。
GPT-3模型架构:GPT-3模型结构非常复杂,包括Transformer编码器(Encoder)、Feed Forward Neural Network(FFNN)、Language Model Head、Output Layer。
-
Transformer编码器:GPT-3的编码器是由12个self-attention layers(self-attn)、12个Feedforward layers(ff)组成的 transformer encoder 。每一层的输入输出维度都是512,并采用了残差连接(Residual Connections)。
-
Feed Forward Neural Network:FFNN 是一种两层神经网络,每一层都包含 2048 个隐藏单元。GPT-3 的 FFNN 将 Transformer Encoder 中的信息传递给模型进行进一步处理。
-
Language Model Head:LMH(Language Model Head)负责预测序列的下一个 token。LMH 根据模型预测出的 token 序列,可以生成新文本。LMH 将 LM 优化目标视为生成新的文本,而不是像普通的语言模型那样预测下一个 token。
-
Output Layer:GPT-3的最后一层称为输出层,用于预测 token 的概率分布。GPT-3 的最终预测结果是一个连续分布,而不是离散的结果。
GPT-3训练策略:GPT-3的训练策略包含两种方法:pre-training和fine-tuning。
-
pre-training:pre-training是对 GPT-3 模型的参数进行迭代更新,以便在特定任务上获得最佳性能。pre-training的目的是通过大量的无监督学习和对抗训练来对 GPT-3 模型进行知识增强。
-
fine-tuning:fine-tuning是在已训练好的GPT-3模型上微调模型参数,以满足特定任务的需求。fine-tuning可以在更高的准确率水平上进行训练,并且可以应用于不同的任务。fine-tuning的过程类似于其他机器学习模型的训练过程,但其结果不仅能对原始的任务有所改进,而且还能用于其他任务。
GPT-3训练策略能够通过无监督学习和对抗训练的方法,对模型参数进行不断迭代,从而获得最佳性能。GPT-3训练策略的核心是使用了一种新的优化目标,即对抗训练(Adversarial Training)。对抗训练通过加入噪声扰乱模型参数,强制模型以更具策略性的方式进行预测,从而使模型逼近真实情况。
操作步骤
下面,我将以产品采购、订单结算、发票打印、运输配送、审批、风险控制流程为例,介绍RPA系统的操作步骤。
产品采购
- 采购申请。
- 审核。审阅采购计划书,确定是否符合采购要求。如:价格、数量、质量、时间等。
- 确认。如:生产商、品牌名称、物料规格、发货地址等。
- 报价。如:按件、按重量、按体积计算价钱。
- 支付申请。如:支付宝、微信等。
- 发票打印。
- 上架商品。如:出厂、上传仓库等。
- 生成采购订单。
订单结算
- 查看订单。检查订单状态,查看是否已付款。如:等待支付、已支付等。
- 创建付款单。如:填写付款单,确认订单金额。
- 提交付款申请。如:支付宝、微信等。
- 查看付款状态。如:等待支付、已支付等。
发票打印
- 查看发票。如:是否打印,是否上传。
- 打印发票。
- 上传发票至服务器。
运输配送
- 选择快递公司。
- 提交物流单。
- 查看物流状态。如:已发货、运输中、运输完成等。
- 修改物流信息。如:查看物流单号。
- 签收确认。如:确认物流单号是否正确。
审批
- 审批财务总账单、利润表。
- 查看审批结果。如:通过、不通过。
风险控制
- 评估投资组合的风险级别。
- 根据风险级别决定是否冻结资产。
- 推荐资产组合调整方案。
数学模型公式详细讲解
GPT-3模型是一种深度学习模型,其输入输出都是文本数据。因此,将文本输入到GPT-3模型中,就会得到模型的预测结果,即模型的输出。GPT-3模型的输出结果是一个连续分布,通常情况下,输出值的范围为[0,1]。
接下来,我们将详细了解GPT-3模型输出的数学模型公式。GPT-3的语言模型和任务训练目标与Seq2seq模型相似。
Seq2seq模型
Seq2seq模型是一种比较基础的模型,输入文本长度任意,输出文本长度也任意。它的基本思路是把输入序列和输出序列分别作为输入,训练一个模型能够实现翻译、问答等功能。
Seq2seq模型的数学公式如下:
Pθ(y1:m∣x1:n)=exp{hθ⋅y1T}∑k=1Kexp{hθ⋅ykT}+1−softmax(zi)KP_{theta}(y_{1:m}|x_{1:n})=frac{exp{boldsymbol{h}_{theta} cdot y_1^{T}}}{sum_{k=1}^{K}exp{h_{theta} cdot y_k^{T}}}+frac{1-text{softmax}(z_i)}{K}
其中,KK表示输出空间大小,θtheta表示模型的参数,x1:nx_{1:n}表示输入序列,y1:my_{1:m}表示输出序列,hθboldsymbol{h}_{theta}表示隐层的权重。
Pθ(y1:m∣x1:n)=∏t=1mP(yt∣y<t,x1:n;θ)P_{theta}(y_{1:m}|x_{1:n})=prod_{t=1}^m P(y_t|y_{<t},x_{1:n};theta)
上式表示Seq2seq模型的概率计算公式,公式左边表示输出序列的条件概率。其中,y<ty_{<t}表示从tt时刻之前的输出序列。
L(θ)=1N∑i=1N∑j=1liL(y^ij∣y^i,<j,xi;θ)L(theta)=frac{1}{N}sum_{i=1}^N sum_{j=1}^{l_i} mathcal{L}(hat{y}_{ij}|hat{y}_{i,<j},x_i;theta)
其中,lil_i表示输入序列xix_i的长度,yi:<jy_{i:<j}表示第ii个输入序列的前j−1j-1个元素,y^ijhat{y}_{ij}表示第ii个输入序列的第jj个元素的预测标签,Lmathcal{L}表示损失函数,y^i,<jhat{y}_{i,<j}表示第ii个输入序列的前jj个元素的真实标签。
GPT-3模型
GPT-3模型和Seq2seq模型的区别主要在于:
- GPT-3模型的输入文本长度为1024或512,输出文本长度不固定。
- GPT-3模型采用了transformer模型作为编码器,能够捕获序列的全局信息。
- GPT-3模型输出的文本的最后一项为结束符号,可以作为判别句子结束的标志。
- GPT-3模型在预测时,采用softmax函数,并采用多个随机采样函数,从而获取样本中可能性最大的输出。
GPT-3模型的概率计算公式如下:
Pθ(y1:m∣x1:n)=ehθ⊤y1∑k=1Kehθ⊤yk+1−softmax(zi)KP_{theta}(y_{1:m}|x_{1:n})=frac{e^{bf{h}_{theta}^top y_1 }}{sum_{k=1}^{K} e^{bf{h}_{theta}^top y_k }}+frac{1-operatorname{softmax}(z_i)}{K}
其中,K=2K=2, zi∈[0,1]z_iin [0,1],θ=(Wa,Wb,wp)theta=(W^a, W^b, w_p),Wa∈RE×dW^ain R^{Etimes d}, Wb∈R(L+1)×EW^bin R^{(L+1)times E}, wp∈Rd×Vw_pin R^{dtimes V}, hθ=[h1:L],∈Rdbf{h}_{theta}=[bf{h}_{{1:L}}], in R^{d}.
其中,VV表示输出空间大小,EE表示embedding size,LL表示transformer encoder的层数,dd表示hidden size。
GPT-3模型的损失函数如下:
L(θ)=1N∑i=1N∑j=1li−logpθ(yj∣yj−1:j−L,xi)+(1−zi)(−∑u=1Lsparseu(−logzu))+λ∥θ∥22L(theta)=frac{1}{N}sum_{i=1}^N sum_{j=1}^{l_i} -log p_theta(y_{j}|y_{j-1:j-L},x_i) + (1-z_i)left(-sum_{u=1}^{L}text{sparse}_{u}(-log z_u)right)+ lambda|theta|_2^2
其中,−logpθ(yj∣yj−1:j−L,xi)-log p_theta(y_{j}|y_{j-1:j-L},x_i) 表示log likelihood,ziz_i表示标签为yiy_i的概率,λlambda表示正则化系数。
其中,lil_i表示输入序列xix_i的长度,−logpθ(yj∣yj−1:j−L,xi)-log p_theta(y_{j}|y_{j-1:j-L},x_i) 表示第ii个输入序列的第jj个元素的log likelihood。
GPT-3模型的训练策略主要有三种:pre-training、fine-tuning和distillation。
- pre-training:pre-training主要是在大量无监督数据上训练模型。通过对抗训练的方法,模仿模型生成的数据来增强模型的表达能力,提高模型的鲁棒性。pre-training分为两种方法,即GPT-2和GPT-NEO。
- fine-tuning:fine-tuning是在已有模型上的微调过程。fine-tuning可以使模型在特定任务上取得更好的性能。
- distillation:distillation是一种模型蒸馏方法。蒸馏过程可以使得模型的复杂度保持较低,而模型的参数却达到了与预训练模型相同的效果。
4.具体代码实例和详细解释说明
Python实现案例
安装环境
首先安装pytorch和transformers库。
!pip install torch==1.6.0 transformers==3.0.2
导入必要的包。
import os
import random
from typing import List
import numpy as np
import pandas as pd
import torch
from sklearn.model_selection import train_test_split
from transformers import AdamW, get_linear_schedule_with_warmup, GPT2Tokenizer, GPT2LMHeadModel
数据预处理
读取数据,处理异常值,对文本进行切分。
data = pd.read_csv('order_info.csv')
data['order_date'] = data['order_date'].apply(str) # 转换日期类型
def split_text(text):
return text.strip().split()
def clean_text(text):
"""处理异常值"""
words = []
for word in text:
if word == 'nan':
continue
elif len(word) <= 1 or not any(c.isalnum() for c in word):
continue
else:
words.append(word)
return words
def process_text(text: str)->List[str]:
"""对文本进行切分"""
words = split_text(text)
cleaned_words = clean_text(words)
return [' '.join(cleaned_words)]
processed_texts = data[['product', 'customer', 'order_date']].applymap(process_text).values.flatten().tolist()
print(len(processed_texts))
定义Tokenizer。
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
special_tokens = {'pad_token': '<|padding|>'}
num_added_toks = tokenizer.add_special_tokens(special_tokens)
assert num_added_toks == 1
定义train、val、test数据集。
random.shuffle(processed_texts)
train_text, test_text = processed_texts[:int(len(processed_texts)*0.8)], processed_texts[int(len(processed_texts)*0.8):]
train_df, val_df = train_test_split(pd.DataFrame({'text': train_text}), test_size=0.2, random_state=42)
train_dataset = Dataset(train_df, tokenizer)
val_dataset = Dataset(val_df, tokenizer)
test_dataset = Dataset(pd.DataFrame({'text': test_text}), tokenizer)
模型搭建
定义模型,加载预训练权重。
class Dataset:
def __init__(self, df: pd.DataFrame, tokenizer: GPT2Tokenizer):
self.df = df
self.tokenizer = tokenizer
def __getitem__(self, index: int):
item = self.df.iloc[index]['text'][0]
tokens = self.tokenizer.encode(item, return_tensors='pt').squeeze()
label = tokens[1:]
input_ids = tokens[:-1]
mask = ~(input_ids == tokenizer.pad_token_id).bool()
return {
"input_ids": input_ids,
"labels": label,
"mask": mask
}
def __len__(self):
return len(self.df)
class GPTEmbedding(torch.nn.Embedding):
def forward(self, inputs):
inputs = super().forward(inputs)
position_ids = torch.arange(inputs.shape[-1], dtype=torch.long, device=inputs.device)
position_embeddings = self.weight[position_ids, :]
embeddings = inputs + position_embeddings
return embeddings
class GPTConfig:
def __init__(self, vocab_size: int, max_position_embeddings: int, hidden_size: int, n_layers: int,
n_heads: int, dropout: float):
self.vocab_size = vocab_size
self.max_position_embeddings = max_position_embeddings
self.hidden_size = hidden_size
self.n_layers = n_layers
self.n_heads = n_heads
self.dropout = dropout
class GPTModel(torch.nn.Module):
def __init__(self, config: GPTConfig, embedding: GPTEmbedding):
super().__init__()
self.config = config
self.embedding = embedding
self.encoder = torch.nn.TransformerEncoder(encoder_layer=torch.nn.TransformerEncoderLayer(d_model=config.hidden_size,
nhead=config.n_heads),
num_layers=config.n_layers,
norm=torch.nn.LayerNorm(normalized_shape=config.hidden_size))
self.lm_head = torch.nn.Linear(config.hidden_size, config.vocab_size, bias=False)
def forward(self, inputs, labels=None, attention_mask=None):
batch_size, seq_length = inputs.shape
inputs = self.embedding(inputs)
outputs = self.encoder(inputs, src_key_padding_mask=~attention_mask)
logits = self.lm_head(outputs)[:, :-1, :].contiguous()
loss = None
if labels is not None:
shift_logits = logits[..., :-1, :].contiguous()
shift_labels = labels[..., 1:].contiguous()
loss_fct = torch.nn.CrossEntropyLoss(ignore_index=-100)
loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)),
shift_labels.view(-1))
return loss, logits
checkpoint_path = '/content/drive/MyDrive/gpt2-medium/'
config = GPTConfig(vocab_size=tokenizer.vocab_size,
max_position_embeddings=1024,
hidden_size=1024,
n_layers=24,
n_heads=16,
dropout=0.1)
embedding = GPTEmbedding(num_embeddings=config.vocab_size,
embedding_dim=config.hidden_size)
model = GPTModel(config=config,
embedding=embedding)
model.load_state_dict(torch.load(os.path.join(checkpoint_path, f'pytorch_model.{checkpoint_path}.bin')))
model.eval()
if torch.cuda.is_available():
model = model.cuda()
else:
print("Using CPU")
模型训练
定义训练函数。
def train_epoch(loader, optimizer, scheduler, model, device):
total_loss = 0
model.train()
for step, batch in enumerate(loader):
inputs = batch["input_ids"].to(device)
labels = batch["labels"].to(device)
attention_mask = batch["mask"].to(device)
optimizer.zero_grad()
loss, _ = model(inputs, labels=labels, attention_mask=attention_mask)
loss.backward()
optimizer.step()
scheduler.step()
total_loss += loss.item()
return total_loss / len(loader)
定义验证函数。
@torch.no_grad()
def evaluate(loader, model, device):
total_loss = 0
model.eval()
for step, batch in enumerate(loader):
inputs = batch["input_ids"].to(device)
labels = batch["labels"].to(device)
attention_mask = batch["mask"].to(device)
_, output_logits = model(inputs, labels=labels, attention_mask=attention_mask)
shift_logits = output_logits[..., :-1, :].contiguous()
shift_labels = labels[..., 1:].contiguous()
loss_fct = torch.nn.CrossEntropyLoss(ignore_index=-100)
loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)),
shift_labels.view(-1))
total_loss += loss.item()
return total_loss / len(loader)
定义超参数,启动训练。
BATCH_SIZE = 16
LR = 5e-5
WARMUP_STEPS = 1000
MAX_LEN = 1024
DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'
train_loader = DataLoader(train_dataset,
batch_size=BATCH_SIZE,
shuffle=True,
collate_fn=lambda x: pad_sequence([xx['input_ids'] for xx in x], batch_first=True, padding_value=tokenizer.pad_token_id))
valid_loader = DataLoader(val_dataset,
batch_size=BATCH_SIZE,
shuffle=False,
collate_fn=lambda x: pad_sequence([xx['input_ids'] for xx in x], batch_first=True, padding_value=tokenizer.pad_token_id))
optimizer = AdamW(params=model.parameters(), lr=LR, correct_bias=False)
scheduler = get_linear_schedule_with_warmup(optimizer,
num_warmup_steps=WARMUP_STEPS,
num_training_steps=len(train_loader)*EPOCHS)
for epoch in range(EPOCHS):
train_loss = train_epoch(train_loader, optimizer, scheduler, model, DEVICE)
valid_loss = evaluate(valid_loader, model, DEVICE)
print(f"Epoch: {epoch+1}/{EPOCHS}, Train Loss: {train_loss:.5f}, Valid Loss: {valid_loss:.5f}")
5.未来发展趋势与挑战
实用化
随着BPA技术的发展,企业可以越来越精细化地自动化各个流程。但现状是,仍存在很大的进步空间。具体来说,以下几个方面是需要持续努力的。
- 流程映射自动化。将现有流程通过系统映射工具转换为标准工作流。
- 服务优化。服务流程自动化之后,企业将拥有更多的自助服务能力,因此需要进一步优化企业内部服务系统,提升用户体验。
- 大数据支撑。GPT-3模型的能力受限于数据的量和规模,因此需要借助大数据平台对模型进行训练和超参数调优。
- 安全防护。BPA作为人机协同的工具,其安全性和隐私问题依旧需要关注。
- 数据治理。企业内部数据需要被高度管控,包括法律法规、政策要求等。如何对数据产生的价值进行评估、可视化、跟踪,以及如何进行风险控制等,都是未来的工作方向。
深度学习技术
随着BPA技术的深入落地,有关深度学习技术的应用也逐渐成为热门话题。深度学习的最新技术革命,结合了强大的计算能力、巨大的海量数据量、以及对大量标签数据的需求,激发了BPA领域的创新潮。
目前,在文本生成领域,包括BART、T5等模型,这些模型既能很好地完成文本的自动摘要、文本的翻译、对话系统的生成、评论文本的分类、图像的生成等任务,也能够充分利用大规模的无监督数据进行预训练,提升生成效果。
相比之下,在图像生成领域,包括StyleGAN、BigGAN等模型,这些模型能够利用有限的无标签图像数据进行学习,从而可以生成符合某种风格的高清图片。此外,还有在医疗影像领域的GAN模型,能够生成合理的影像诊断报告。
BPA在深度学习技术上展开新的探索,将有助于提升模型的学习能力、生成图像的质量、以及利用无监督数据提升模型的泛化能力。