transformers包介绍——nlp界最顶级的包——可以不用 但不能不知道——python包推荐系列
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
背景1
- 现在在AI行业什么最火计算机视觉还是自然语言处理其实不得不说现在nlp很火。
- 还有人记得上个月很多科技爱好者都在玩的chatgpt么那个就是nlp技术的一大应用。
- 现在都在觉得AI赚钱工资高然后很多人都想做一些事情、很多企业都想做一些事情和AI挂钩的。
- 现在AI里面算是比较有活力的就是nlp领域。
背景2
经常能看到一些读者在群里问
- “现在nlp方面的包应该用什么”
- “现在想做一个文本分类的代码而且我还要求是中文的我应该怎么实现呢”
- “现在想做中文的文本搜索想做问答机器人我怎么实现呢”
- “现在想做一些更加高级的东西比如文本纠错、文本摘要等应该怎么实现呢“
- ”我想学习pytorch想要了解python关于AI方面的应用我应该看什么源码呢“
- “我现在想做文本搜图我现在想做让文本写唐诗我应该怎么研究呢”
- …还有更多
so
- 如果我告诉你你的大部分任务可能就几行代码就搞定了你会相信吗
- 如果我告诉你就算是你想训练符合你自己数据的模型也就是简单的导入数据即可。无需调整什么参数。训练完即可直接发布你会相信吗
- 当然如果你像我一样希望可以自己定义模型自己开发模型想要二次创作但是苦于找不到学习案例苦于不知道怎么改那你可真得看看我接下来要推荐的东西了。
总而言之如果你对python、pytorch、机器学习、nlp技术文本挖掘、文本分类、文本生成、文本搜索、问答机器人、搜索等、计算机视觉、语音识别等领域感兴趣或者想做一些类似的工具。
这里需要说明一下
- 如果是python小白、nlp小白的话还是建议看看这个包起码是一个非常重要的包。在未来遇到这个方向的时候起码有解决方案。
- 如果是python、nlp高级开发者可以看看这两个包的源码。他的代码设计还是非常优秀的。可以学到不少知识点。
ok
那么接下来我将分享一个在GitHub上拥有7.8万个star的明星python包————transformers
这个包将会打包你的所有困惑和焦虑带你走上nlp不归路。
正文
多说无益直接秀肌肉
1. 文本分类
大部分人在nlp中遇到的第一个任务就是文本分类。
下面是实用3行代码就调用了一个开源模型并且做到了情感分析本质上就是文本分类只不过是从情感维度分析这句话是消极还是积极
from transformers import pipeline
classifier = pipeline('sentiment-analysis')
classifier('We are very love chinese')
#>>> [{'label': 'POSITIVE', 'score': 0.9997429251670837}]
可以看出就几行代码
- 第一行代码导入一个类也就相当于一个管道。
- 第二行代码是将
pipeline
设置为情感分析模式。 - 把需要分析的文本传递给这个分类器
classifier
然后就输出结论了。
给人的感觉就是即开即用就是这么简单。
可是这个时候就有人问了
- 可以对中文做情感分类么或者叫文本分类
- 这个准确率怎么样效果好么
- 我可以做一个自己的分类器么用自己的数据
当然可以而且也是比较简单的。鉴于篇幅问题这里只是把大纲分享出来并且附上简单的代码
1.1.加载数据
from datasets import load_dataset
imdb = load_dataset("imdb")
1.2.预处理
#load tokenizer
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
def preprocess_function(examples):
return tokenizer(examples["text"], truncation=True)
# process data
tokenized_imdb = imdb.map(preprocess_function, batched=True)
# padding
from transformers import DataCollatorWithPadding
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
1.3.评估器
import evaluate
accuracy = evaluate.load("accuracy")
import numpy as np
def compute_metrics(eval_pred):
predictions, labels = eval_pred
predictions = np.argmax(predictions, axis=1)
return accuracy.compute(predictions=predictions, references=labels)
1.4.开始训练
from transformers import AutoModelForSequenceClassification, TrainingArguments, Trainer
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased", num_labels=2, id2label=id2label, label2id=label2id
)
training_args = TrainingArguments(
output_dir="my_awesome_model",
learning_rate=2e-5,
per_device_train_batch_size=16,
per_device_eval_batch_size=16,
num_train_epochs=2,
weight_decay=0.01,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
push_to_hub=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_imdb["train"],
eval_dataset=tokenized_imdb["test"],
tokenizer=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
trainer.train()
1.5.总结
- 可以看出来整体上非常简单加载数据、设置预处理、处理数据、训练即可。但是这么简单的东西还有人不知道因此我觉得还是很有必要分享出来的。
- 当然我也不是无脑的就是说这个包非常好这个包就一定上手简单那是不可能的。只是说这个包相对于别的包来说更好用。上面的代码虽然简单但是如果你不了解其中的原理和细节很难搞懂也就很难用起来。也就是说我们要用巧劲才能以柔克刚驱动这个大家伙。不然你会感觉这玩意怎么这么难用。
- 因此我会在后面会分享一些详细的、完整的教程可以期待一下关注公众号「统计学人」
2.文本纠错
- 如果你之前见过文本分类那你可能感觉上面的案例没什么意思别急往下看。
- 如果你之前连文本分类都不清楚那你可能会对这个案例感觉更有意思。
给你看个文本👇3秒时间能不能找到错别字
“法国的首都是吧黎。”
3
2
1
找到错别字了么我猜测你肯定找到了吧
这个字错了应该是巴
。
当前我使用简单的几行代码就能找到这个错别字。不信看看我这个这个代码和结果。
前置操作
- 这里把一些需要用到的包导入进来
- 并且设置好具体的数据结构「方便大家可以看的更加清楚」。
- 并且加载一个大模型。
from dataclasses import dataclass
from typing import List
from transformers import pipeline
unmasker = pipeline('fill-mask', model='bert-base-chinese')
@dataclass
class ErrorList:
index: int
error_char: str
correct_char: List[str]
魔法代码
然后巧妙的使用大模型的一个任务fill-mask
。基于这个任务做一些巧妙的设计就可以完成文本纠错的任务。
- 我这里把上面的句子放进来
法国的首都是吧黎。
. - 然后放到函数里面函数会输出句子的每一个错别字、这个错别字在什么位置并且给到应该改为什么字。
my_text = "法国的首都是吧黎。"
def find_error_character(text: str) -> List[ErrorList]:
text_length = len(text)
text_split = list(text)
final_list = list()
for _index in range(text_length):
_list = text_split.copy()
_list[_index] = '[MASK]'
_str = ''.join(_list)
res = unmasker(_str)
parti_list = [i.get('token_str') for i in res]
if text_split[_index] not in parti_list:
_res = ErrorList(
index=_index, error_char=text_split[_index], correct_char=parti_list)
final_list.append(_res)
return final_list
find_error_character(my_text)
# >>>[ErrorList(index=3, error_char='首', correct_char=['人', '大', '', '也', '酒']),
# >>> ErrorList(index=6, error_char='吧', correct_char=['巴', '伦', '法', '波', '洛'])]
结果解释、总结
结果解释 可以看出来上面把两个可能的错别字找到了。一个是首
一个是吧
。并且给到错别字所在的具体位置并且给到正确的字是哪些(可能性越大的字越靠前)。
原理介绍 但是你说我们做了什么好像就是使用了一个大模型bert-base-chinese
的fill-mask
模式然后随便写了段代码就拥有这些魔法这难道不香么
提升效果 当然如果上面的效果你不满意需要在你的数据上再拟合一下其实也是非常简单的。操作起来不复杂而且效果提升会很明显。
3. 文本搜索
如果说上面的那个场景大家见的不多也是理解毕竟现在天天写文档的就不多了更别说体验到文本纠错这个场景。
但是有个场景大家每天都会使用那就是搜索🔍。
- 大家经常在抖音搜索视频输入的是文本。
- 大家经常在百度、csdn、谷歌、stack overflow等搜索问题输入的也是文本。
- 大家经常在小红书、淘宝搜索商品输入的也是文字。
大家有想过这背后的技术是怎么实现的呢相当全面的解释我不也不太懂。这里只是介绍文本搜索方面的东西。
文本向量化
还记得机器学习里面的有一个非常经典的数据集——鸢尾花数据集么。这个数据大概是有150条数据三个品种。每一条数据记录了这个花瓣的宽度、厚度、长度等好像是这3个维度记不清楚了。反正这三个维度大家人眼是可以直观感受到的。
还记得你自己的性别、你自己的年龄、你自己来自哪里、在什么学校里面上学、学的什么专业么这些整理好表格一个个维度贴出来你也很清楚知道这些都是所谓的向量。
我们把思维拓展一下现在有个黑盒子可以把一串文本转换成一大串向量。每一个数值代表一个意义。虽然某数据的值表示的维度到底是什么我们也不清楚。
想象着
- 每一个文本在一个高维度空间中都有着他们自己的位置。
- 如果两个文本在这个高维度空间里面比较近表示他们就是相似的。
- 如果两个文本在这个高维度空间里面比较远表示他们就是不相似的。
在以前其实也是这么处理的。唯一提升的就是现在这个黑盒子
提取的特征更加准确更加优秀击败了之前的黑盒子
。
这里分享一个小的代码就是上面提到的黑盒子
,一起感受一下吧
导入包
from typing import List, Union
import numpy as np
import pandas as pd
import torch as t
from transformers import AutoModel, AutoTokenizer
计算cos距离的函数
def numpy_cos_sim(a: np.ndarray, b: np.ndarray) -> np.ndarray:
if len(a.shape) == 1:
a = a.reshape(1, -1)
if len(b.shape) == 1:
b = b.reshape(1, -1)
a_norm = a / np.linalg.norm(a, ord=2, axis=1).reshape(-1, 1)
b_norm = b / np.linalg.norm(b, ord=2, axis=1).reshape(-1, 1)
return np.matmul(a_norm, b_norm.T)
黑盒子模型
class TextVector:
def __init__(self,
model_name_or_path: str = None,
device: str = "cuda:0") -> None:
# 加载和处理模型, cuda
self.model_name_or_path = model_name_or_path
self.device = device
self.tokenizer = AutoTokenizer.from_pretrained(self.model_name_or_path)
self.batch_size = 100
self.model = AutoModel.from_pretrained(self.model_name_or_path)
self.model.to(self.device)
def encode_fun(self, texts: List[str]) -> np.ndarray:
inputs = self.tokenizer.batch_encode_plus(
texts, padding=True, truncation=True, return_tensors="pt", max_length=64)
inputs.to(device=self.device)
with t.no_grad():
embeddings = self.model(**inputs)
embeddings = embeddings.last_hidden_state[:, 0]
embeddings = embeddings.to('cpu').numpy()
return embeddings
黑盒子模型的使用
在这里我们初始化这个黑盒子
然后把一串文本放入这个黑盒子
里面发现输出了一个(4, 768)
维度的向量。那么这个向量就是这串文本的向量化表示了
textvector = TextVector(model_name_or_path="hfl/chinese-roberta-wwm-ext")
text1 = ['计算机科学', '我爱统计学', '那个音乐真好听', '他唱的歌真的不错']
text1_vector = textvector.encode_fun(text1)
text1_vector.shape
# >>> (4, 768)
把这个向量化打印出来长成这个样子
# >>> array([[-0.01761765, 0.30379066, 0.79640263, ..., -0.35549787,
# >>> -0.42488524, 0.23474628],
# >>> [-0.0502945 , 0.4215444 , 0.18330751, ..., -0.7200883 ,
# >>> -0.44032276, -0.1382378 ],
# >>> [ 0.20864306, 0.6202163 , -0.08560622, ..., -0.06069888,
# >>> -0.18625183, -0.43429998],
# >>> [ 0.11968233, 0.38393256, 0.19664326, ..., 0.1699293 ,
# >>> 0.02434621, -0.411282 ]], dtype=float32)
-
为了强调把4个文本拎出来
['计算机科学', '我爱统计学', '那个音乐真好听', '他唱的歌真的不错']
-
这个时候再计算上面的4个文本两两之间的相关性。
numpy_cos_sim(text1_vector, text1_vector)
# >>> array([[1.0000001 , 0.8569578 , 0.73208493, 0.7412211 ],
# >>> [0.8569578 , 0.99999994, 0.7372216 , 0.7467295 ],
# >>> [0.73208493, 0.7372216 , 0.9999997 , 0.9066033 ],
# >>> [0.7412211 , 0.7467295 , 0.9066033 , 0.99999994]], dtype=float32)
可以发现
'计算机科学'
和'我爱统计学'
相关性有0.85和'那个音乐真好听'
相关性只有0.73.'那个音乐真好听'
和'他唱的歌真的不错'
相关性在0.90左右。
想象一下如果我们把上面的4个文本换成4亿条文本、4000亿条文本在结合一些更加精细的处理。那不就是一个庞大的搜索引擎么
5. 更多
上面也就是transformers包的冰山一角。能做的实在是太多了我这里就复制他自己写的介绍吧
-
🤗 Transformers 提供了数以千计的预训练模型支持 100 多种语言的文本分类、信息抽取、问答、摘要、翻译、文本生成。它的宗旨让最先进的 NLP 技术人人易用。
-
🤗 Transformers 提供了便于快速下载和使用的API让你可以把预训练模型用在给定文本、在你的数据集上微调然后通过 model hub 与社区共享。同时每个定义的 Python 模块均完全独立方便修改和快速研究实验。
-
🤗 Transformers 支持三个最热门的深度学习库 Jax, PyTorch and TensorFlow — 并与之无缝整合。你可以直接使用一个框架训练你的模型然后用另一个加载和推理。
同时你还可以
便于使用的先进模型
- NLU 和 NLG 上表现优越
- 对教学和实践友好且低门槛
- 高级抽象只需了解三个类
- 对所有模型统一的API
更低计算开销更少的碳排放
- 研究人员可以分享已训练的模型而非每次从头开始训练
- 工程师可以减少计算用时和生产环境开销
- 数十种模型架构、两千多个预训练模型、100多种语言支持
对于模型生命周期的每一个部分都面面俱到
- 训练先进的模型只需 3 行代码
- 模型在不同深度学习框架间任意转移随你心意
- 为训练、评估和生产选择最适合的框架衔接无缝
为你的需求轻松定制专属模型和用例
- 我们为每种模型架构提供了多个用例来复现原论文结果
- 模型内部结构保持透明一致
- 模型文件可单独使用方便魔改和快速实验
延伸
-
其实在nlp领域python包千千万万个数不胜数。我们不可能把所有的包都用一遍只要选择一个包认真的去研究即可。这不就像是我们的人生么如果各个东西都只是浅尝辄止那注定是没有收获选择一个东西即可。
-
其实前几年不还是那些分词、词向量等传统模型更火么这几年出现了bert、transformers等大模型让nlp发生翻天覆地的变化。这不就像是我们的生活么过去的2022年变化莫测最不缺的就是变化。
-
各种变化层出不穷但是都离不开概率论、统计、数学、计算机应用技术。这不也是给我们指明了研究道路么要研究本质的东西只有把本质的东西研究透成果才能开出花来。
最后
transformers包就像是pytorch、tensorflow、sklearn等包一样内容相当庞大功能丰富。
我这里也只能介绍他的一点点内容如果对这个包感兴趣可以查看他的官网https://github.com/huggingface/transformers
我后面也会介绍更多关于transformers包的使用方法
介绍更多关于NLP的相关知识
我后面也会介绍更多python有趣的包
可以继续关注我「统计学人」