Word2Vec的一些不足
在上一篇文章中,了解了如何使用word2vec进行文本相似度识别。然而,在实践中发现,word2vec的表现并不尽如人意,原因有很多:
一方面,word2vec的处理单位是单词,碰到短语时的核心处理逻辑还是进行分词后求平均,这样子的做法虽然高效,但在碰到较长的文本时,识别效果下降得非常快。
另一方面,在使用Google预训练的词向量模型时,出现了词汇表缺失的情况。很多常用词一旦变换了不太常见的形态,就因为出现频率下降而被优化掉了,这种情况在英文文本中受单词多态的影响极为明显。
虽然也有尝试各种方法,比如词干提取,迁移学习等来改善这些问题,但总感觉达不到满意的识别率。网上搜到的一些教程也都是比较老的了。跟ai方向的同学交流了下,他们说现在大家都是用GPT来处理文本了,于是自己也去了解了一下如何使用这些前沿的NLP技术。
尝试BERT
看了几篇介绍预训练语义模型的文章后,最终是把目标锁定在了「无监督预训练+下游任务微调」的BERT上。试着用BERT处理现在面临的认证相关文本识别问题。BERT是基于Transformer架构的预训练语言模型,可以用于各种NLP任务,如文本分类、命名实体识别等。
在本文中,将介绍如何使用BERT进行文本分类。具体来说,将使用BERT预训练模型bert-base-chinese,并在最后增加一个分类器,用于输入文本的分类。
与上篇文章中提到的gensim库不同,将使用transformer库。在PyTorch中安装transformer库非常简单,只需要输入以下命令:
1
| pip3 install transformers
|
文本分类
目标任务是对输入文本进行分类,判断其是否与认证相关,将使用bert-base-chinese模型进行分类。
由于目前只有一个包含100多个认证关键词的字典,多分类的精度肯定指望不上,因此尝试先做一个二分类的问题,即输入文本究竟是否认证相关,后续再进行划分。
但最后发现由于训练样本实在太小,内部种类差异大,且相当于只有正样本等多重原因,在经过反复的训练后,分类器模型的表现还是很差,不管碰到什么文本,都倾向于将其判断为认证相关。
代码实现
下面是使用BERT进行文本分类的代码实现,其中使用了transformer库和PyTorch框架:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| import torch from transformers import BertTokenizer, BertForSequenceClassification, BertConfig
class AuthClassifier: def __init__(self, lang='en', model_path=None): self.lang = lang if self.lang == 'en': self.tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') config = BertConfig.from_pretrained('bert-base-uncased', num_labels=2) self.model = BertForSequenceClassification(config) keyword_file = "en/keyword.txt" elif self.lang == 'zh': self.tokenizer = BertTokenizer.from_pretrained('bert-base-chinese') config = BertConfig.from_pretrained('bert-base-chinese', num_labels=2) self.model = BertForSequenceClassification(config) keyword_file = "zh/keyword.txt" else: raise ValueError("Unsupported language: %s" % self.lang)
with open(keyword_file, 'r', encoding='utf-8') as f: self.keywords = set([line.strip() for line in f])
if model_path is not None: self.model = BertForSequenceClassification.from_pretrained(model_path)
def predict(self, text): tokens = self.tokenizer.encode_plus(text, max_length=128, truncation=True, padding='max_length', add_special_tokens=True, return_attention_mask=True, return_tensors='pt')
with torch.no_grad(): outputs = self.model(tokens['input_ids'], attention_mask=tokens['attention_mask']) logits = outputs[0]
_, predicted = torch.max(logits, dim=1)
contains_keyword = any(keyword in text.lower() for keyword in self.keywords)
if predicted.item() == 1 or contains_keyword: return True else: return False
|
在以上代码中,首先使用from_pretrained方法加载了bert-base-chinese模型和tokenizer。然后,对输入文本进行分词,并将其转换为BERT输入格式。最后,进行包含关系的判断,并打印出预测结果。
总结
本文介绍了如何使用最新的NLP技术BERT进行文本分类。通过使用BERT预训练模型和transformer库,可以轻松地对输入文本进行分类。但由于训练样本较少,分类器的表现还有待改进。下一篇文章中将计划以聚类的方法解决这个问题。
参考资料:
通俗理解BERT:https://blog.csdn.net/v_JULY_v/article/details/127411638
Github项目主页:https://github.com/huggingface/transformers
文本分类任务实例:https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/text_classification.ipynb#scrollTo=5o4rUteaIrI_