【NLP】文本预处理

目录

一、文本处理的基本方法

1.1 分词

1.2 命名体实体识别

1.3 词性标注 

二、文本张量的表示形式

2.1 one-hot编码

2.2 word2vec 模型

2.2.1 CBOW模式

2.2.2 skipgram模式

2.3 词嵌入word embedding

三、文本数据分析

3.1 标签数量分布

3.2 句子长度分布

3.3 词频统计与关键词词云

四、文本特征处理

4.1 n-gram特征

4.2 文本长度规范

五、文本数据增强


文本语料在输送给模型前一般需要一系列的预处理工作,才能符合模型输入的要求,如:将文本转化成模型需要的张量,规范张量的尺寸等,而且科学的文本预处理环节还将有效指导模型超参数的选择,提升模型的评估指标

一、文本处理的基本方法

1.1 分词

分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,分词过程就是找到这样分界符的过程

无线电法国别研究
['无线电法', '国别', '研究']

词作为语言语义理解的最小单元,是人类理解文本语言的基础。因此也是AI解决NLP领域高阶任务,如自动问答、机器翻译、文本生成的重要基础环节

  • 精确模式分词:试图将句子最精确地切开,适合文本分析
  • 全模式分词:把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能消除歧义
  • 搜索引擎模式分词:在精确模式基础上,对长词再次切分,提高召回率,适合搜索引擎分词
import jieba# 精确模式
def test01():text = '无线电法国别研究'# cut_all默认为Falseobj = jieba.cut(text, cut_all=False)print(obj)# <generator object Tokenizer.cut at 0x0000019CB8CDC148># lcut直接返回分词列表内容words = jieba.lcut(text, cut_all=False)print(words)# ['无线电', '法国', '别', '研究']# 全模式分词
def test02():text = '无线电法国别研究'obj = jieba.cut(text, cut_all=True)print(obj)# <generator object Tokenizer.cut at 0x000001E6304AC148>words = jieba.lcut(text, cut_all=True)print(words)# ['无线', '无线电', '法国', '国别', '研究']# 搜索引擎模式分词
def test03():text = '无线电法国别研究'obj = jieba.cut_for_search(text)print(obj)# <generator object Tokenizer.cut_for_search at 0x000001CCE75DA748>words = jieba.lcut_for_search(text)print(words)# ['无线', '无线电', '法国', '别', '研究']if __name__ == '__main__':# test01()# test02()test03()

使用用户自定义词典

  • 添加自定义词典后,jieba能够准确识别词典中出现的词汇,提升整体的识别准确率
  • 词典格式:一行分三部分,词语、词频(可略)、词性(可略),空格隔开,顺序不可颠倒
云计算 5 n
李小福 2 nr
easy_install 3 eng
好用 300
韩玉赏鉴 3 nz
八一双鹿 3 nz
import jiebadef main():text = "八一双鹿更名为八一南昌篮球队!"# 精确模式words = jieba.lcut(text)print(words)# ['八', '一双', '鹿', '更名', '为', '八一', '南昌', '篮球队', '!']# 自定义词表jieba.load_userdict("./data/userdict.txt")words = jieba.lcut(text)print(words)# ['八一双鹿', '更名', '为', '八一', '南昌', '篮球队', '!']if __name__ == '__main__':main()

1.2 命名体实体识别

  1. 命名实体:通常将人名、地名、机构名等专有名词统称命名实体.。如:周杰伦、黑山县、孔子学院、24辊方钢矫直机
  2. 命名实体识别(Named Entity Recognition,简称NER)就是识别出一段文本中可能存在的命名实体
鲁迅, 浙江绍兴人, 五四新文化运动的重要参与者, 代表作朝花夕拾.
==>
鲁迅(人名) / 浙江绍兴(地名)人 / 五四新文化运动(专有名词) / 重要参与者 / 代表作 / 朝花夕拾(专有名词)

同词汇一样,命名实体也是人类理解文本的基础单元,是AI解决NLP领域高阶任务的重要基础环节

1.3 词性标注 

  • 语言中对词的一种分类方法,以语法特征为主要依据、兼顾词汇意义对词进行划分的结果,常见的词性有14种,如:名词、动词、形容词等
  • 词性标注(Part-Of-Speech tagging,简称POS)就是标注出一段文本中每个词汇的词性
我爱自然语言处理
==>
我/rr, 爱/v, 自然语言/n, 处理/vnrr: 人称代词
v: 动词
n: 名词
vn: 动名词

词性标注以分词为基础,是对文本语言的另一个角度的理解,因此也常常成为AI解决NLP领域高阶任务的重要基础环节

import jieba.posseg as psegdef main():text = '我爱北京天安门'words = pseg.lcut(text)print(words)# [pair('我', 'r'), pair('爱', 'v'), pair('北京', 'ns'), pair('天安门', 'ns')]if __name__ == '__main__':main()

二、文本张量的表示形式

将一段文本使用张量进行表示,其中一般将词汇为表示成向量,称作词向量,再由各个词向量按顺序组成矩阵形成文本表示

["人生", "该", "如何", "起头"]
==>
# 每个词对应矩阵中的一个向量
[[1.32, 4,32, 0,32, 5.2],[3.1, 5.43, 0.34, 3.2],[3.21, 5.32, 2, 4.32],[2.54, 7.32, 5.12, 9.54]]

将文本表示成张量(矩阵)形式,能够使语言文本可以作为计算机处理程序的输入,进行接下来一系列的解析工作

2.1 one-hot编码

独热编码,将每个词表示成具有n个元素的向量,这个词向量中只有一个元素是1,其他元素都是0,不同词汇元素为0的位置不同,其中n的大小是整个语料中不同词汇的总数

["改变", "要", "如何", "起手"]
==>
[[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]

onehot 编码实现: 

import joblib
from keras.preprocessing.text import Tokenizervocab = {"周杰伦", "陈奕迅", "王力宏", "李宗盛", "吴亦凡", "鹿晗"}
# 实例化一个词汇映射器对象
tokenizer = Tokenizer(num_words=None, char_level=False)
# 使用映射器拟合现有文本数据
tokenizer.fit_on_texts(vocab)for token in vocab:zero_list = [0] * len(vocab)# 使用映射器转化现有文本数据, 每个词汇对应从1开始的自然数# 返回样式如: [[2]], 取出其中的数字需要使用[0][0]index = tokenizer.texts_to_sequences([token])[0][0] - 1zero_list[index] = 1print(token, '的one-hot编码是:', zero_list)# 使用joblib工具保存映射器, 以便之后使用
tokenizer_path = "./data/Tokenizer"
joblib.dump(tokenizer, tokenizer_path)# 李宗盛 的one-hot编码是: [1, 0, 0, 0, 0, 0]
# 周杰伦 的one-hot编码是: [0, 1, 0, 0, 0, 0]
# 王力宏 的one-hot编码是: [0, 0, 1, 0, 0, 0]
# 陈奕迅 的one-hot编码是: [0, 0, 0, 1, 0, 0]
# 吴亦凡 的one-hot编码是: [0, 0, 0, 0, 1, 0]
# 鹿晗 的one-hot编码是: [0, 0, 0, 0, 0, 1]

one-hot 编码器的使用:

import joblibvocab = {"周杰伦", "陈奕迅", "王力宏", "李宗盛", "吴亦凡", "鹿晗"}
tokenizer_path = "./data/Tokenizer"
tokenizer = joblib.load(tokenizer_path)token = '李宗盛'
# 使用 token 获取 token_index
index = tokenizer.texts_to_sequences([token])[0][0] - 1
# 得到 one-hot 编码
zero_list = [0] * len(vocab)
zero_list[index] = 1
print(token, '的one-hot编码是:', zero_list)
# 李宗盛 的one-hot编码是: [1, 0, 0, 0, 0, 0]

one-hot 编码的优劣势:

  • 优势:操作简单,容易理解
  • 劣势:完全割裂了词与词之间的联系,在大语料集下,每个向量的长度过大,占据大量内存
  • 因为one-hot编码明显的劣势,这种编码方式被应用的地方越来越少,取而代之的是稠密向量的表示方法 word2vec 和 word embedding

2.2 word2vec 模型

word2vec 是一种流行的将词汇表示成向量的无监督训练方法,该过程将构建神经网络模型,将网络参数作为词汇的向量表示,包含 CBOW 和 skipgram 两种训练模式

2.2.1 CBOW模式

Continuous bag of words

给定一段文本语料,再选定某段长度(窗口)作为研究对象,使用上下文词汇预测目标词汇

上图中窗口大小为9,使用前后4个词汇对目标词汇进行预测

过程详解

假设给定的训练语料只有一句话:Hope can set you free (愿你自由成长),窗口大小为3,因此模型的第一个训练样本来自Hope can set,因为是CBOW模式,所以将使用Hope和set作为输入,can作为输出。在模型训练时, Hope,can,set 等词汇都使用其 one-hot 编码。输入数据的每个 one-hot 编码(5*1)与各自的变换矩阵(即参数矩阵3*5,这里的 3 是指最后得到的词向量维度)相乘之后再相加,得到上下文表示矩阵(3*1)

将上下文表示矩阵与变换矩阵(参数矩阵 5*3,所有的变换矩阵共享参数)相乘,得到 5*1 的结果矩阵,结果矩阵与目标矩阵即 can 的 one-hot 编码矩阵 (5*1) 进行损失的计算,然后更新网络参数完成一次模型迭代

2.2.2 skipgram模式

给定一段用于训练的文本语料,再选定某段长度(窗口)作为研究对象,使用目标词汇预测上下文词汇

图中窗口大小为9,使用目标词汇对前后四个词汇进行预测

过程详解

假设给定的训练语料只有一句话:Hope can set you free (愿你自由成长),窗口大小为3,因此模型的第一个训练样本来自Hope can set。因为是skipgram模式,所以将使用can作为输入 ,Hope和set作为输出,在模型训练时 Hope,can,set 等词汇都使用其 one-hot 编码。将 can 的 one-hot 编码与变换矩阵(即参数矩阵3*5,3是指最后得到的词向量维度)相乘,得到目标词汇表示矩阵(3*1)

将目标词汇表示矩阵与多个变换矩阵(参数矩阵5*3)相乘,得到多个 5*1 的结果矩阵,将与 Hope 和 set 对应的 one-hot 编码矩阵(5*1)进行损失计算, 然后更新网络参数完成一次模型迭代

最后窗口按序向后移动,重新更新参数,直到所有语料被遍历完成,得到最终的变换矩阵即参数矩阵(3*5),这个变换矩阵与每个词汇的one-hot编码(5*1)相乘,得到的3x1的矩阵就是该词汇的 word2vec 张量表示

2.3 词嵌入word embedding

  • 通过一定的方式将词汇映射到指定维度(一般是更高维度)的空间
  • 广义的 word embedding 包括所有密集词汇向量的表示方法,如之前学习的 word2vec 可认为是 word embedding 的一种
  • 狭义的 word embedding 是指在神经网络中加入的 embedding 层,对整个网络进行训练的同时产生的 embedding 矩阵(embedding层的参数),这个 embedding 矩阵就是训练过程中所有输入词汇的向量表示组成的矩阵

词嵌入层会根据输入的词的数量构建一个词向量矩阵。如:有 100 个词,每个词希望转换成 128 维度的向量,那么构建的矩阵形状即为100 * 128,输入的每个词都对应了矩阵中的一个向量

在 PyTorch 中,可以使用 nn.Embedding 词嵌入层来实现输入词的向量化

  • 先将语料进行分词,构建词与索引的映射,可以将这个映射称为词表,词表中每个词都对应了一个唯一的索引
  • 然后使用 nn.Embedding 构建词嵌入矩阵,词索引对应的向量即为该词对应的数值化后的向量表示

nn.Embedding 对象构建时,最主要有两个参数:

  • num_embeddings 表示词的数量
  • embedding_dim 表示用多少维的向量来表示每个词
import torch
import torch.nn as nn
import jiebadef main():text = '北京冬奥的进度条已经过半,不少外国运动员在完成自己的比赛后踏上归途。'# 1. 分词words = jieba.lcut(text)print('words:', words)# 2. 构建词表index_to_word = {}word_to_index = {}# 分词去重unique_words = list(set(words))for idx, word in enumerate(unique_words):index_to_word[idx] = wordword_to_index[word] = idx# 3.构建词嵌入层# num_embeddings为词的数量,embedding_dim为词嵌入的维度embedding = nn.Embedding(num_embeddings=len(index_to_word), embedding_dim=4)# 4.文本转为词向量表示for word in words:idx = word_to_index[word]word_vector = embedding(torch.tensor(idx))print('%3s\t' % word, word_vector)if __name__ == "__main__":main()
words: ['北京', '冬奥', '的', '进度条', '已经', '过半', ',', '不少', '外国', '运动员', '在', '完成', '自己', '的', '比赛', '后', '踏上', '归途', '。']北京    tensor([1.1339, 1.1262, 0.6638, 1.5691], grad_fn=<EmbeddingBackward0>)冬奥    tensor([0.2753, 0.3262, 1.7691, 1.2225], grad_fn=<EmbeddingBackward0>)的     tensor([-0.7507,  1.8850,  1.4340, -0.8074], grad_fn=<EmbeddingBackward0>)
进度条   tensor([ 0.5693, -0.0951, -0.4607,  0.0555], grad_fn=<EmbeddingBackward0>)已经    tensor([-0.5726,  0.0812,  1.1051, -0.0020], grad_fn=<EmbeddingBackward0>)过半    tensor([0.0691, 0.1430, 1.9346, 1.4653], grad_fn=<EmbeddingBackward0>),     tensor([-1.1009,  0.7833, -0.9021,  1.8811], grad_fn=<EmbeddingBackward0>)不少    tensor([ 0.7913,  0.0890, -0.7459,  1.1473], grad_fn=<EmbeddingBackward0>)外国    tensor([-0.6079,  0.2563,  0.8344, -0.5977], grad_fn=<EmbeddingBackward0>)
运动员   tensor([-1.9587,  0.0995, -1.0728, -0.2779], grad_fn=<EmbeddingBackward0>)在     tensor([-1.6571, -1.2508, -0.8138, -2.6821], grad_fn=<EmbeddingBackward0>)完成    tensor([-1.4124, -0.5624,  1.2548,  0.1708], grad_fn=<EmbeddingBackward0>)自己    tensor([-2.5485, -0.1839, -0.0079,  0.1326], grad_fn=<EmbeddingBackward0>)的     tensor([-0.7507,  1.8850,  1.4340, -0.8074], grad_fn=<EmbeddingBackward0>)比赛    tensor([ 0.3826, -1.8883,  0.5677,  0.1951], grad_fn=<EmbeddingBackward0>)后     tensor([ 0.2585, -1.2181,  1.0165, -0.4775], grad_fn=<EmbeddingBackward0>)踏上    tensor([-1.6933,  1.2826,  0.9993, -0.2306], grad_fn=<EmbeddingBackward0>)归途    tensor([ 3.8709,  0.5133,  0.1683, -0.9699], grad_fn=<EmbeddingBackward0>)。     tensor([-0.9352, -1.2663, -1.5860, -0.2301], grad_fn=<EmbeddingBackward0>)

词嵌入层默认使用的是均值为 0,标准差为 1 的正态分布进行初始化,也可以理解为是随机初始化。这个用来表示词的文本真的能够表达出词的含义吗?

nn.Embedding 中对每个词的向量表示都是随机生成的,当一个词输入进来后,会使用随机产生的向量来表示该词。该词向量参与到下游任务的计算,下游任务计算后,会和目标结果进行对比产生损失。接下来,通过反向传播更新所有的网络参数,就包括了 nn.Embedding 中的词向量表示。这样通过反复的前向计算、反向传播、参数更新,最终每个词的向量表示就会变得更合理

三、文本数据分析

文本数据分析能够有效帮助理解数据语料,快速检查出语料可能存在的问题,并指导之后模型训练过程中一些超参数的选择

后续文章中采用中文酒店评论语料来讲解

sentence    label
早餐不好,服务不到位,晚餐无西餐,早餐晚餐相同,房间条件不好,餐厅不分吸烟区.房间不分有无烟房.    0
去的时候 ,酒店大厅和餐厅在装修,感觉大厅有点挤.由于餐厅装修本来该享受的早饭,也没有享受(他们是8点开始每个房间送,但是我时间来不及了)不过前台服务员态度好!    1
有很长时间没有在西藏大厦住了,以前去北京在这里住的较多。这次住进来发现换了液晶电视,但网络不是很好,他们自己说是收费的原因造成的。其它还好。  1
非常好的地理位置,住的是豪华海景房,打开窗户就可以看见栈桥和海景。记得很早以前也住过,现在重新装修了。总的来说比较满意,以后还会住   1
交通很方便,房间小了一点,但是干净整洁,很有香港的特色,性价比较高,推荐一下哦 1
酒店的装修比较陈旧,房间的隔音,主要是卫生间的隔音非常差,只能算是一般的    0
酒店有点旧,房间比较小,但酒店的位子不错,就在海边,可以直接去游泳。8楼的海景打开窗户就是海。如果想住在热闹的地带,这里不是一个很好的选择,不过威海城市真的比较小,打车还是相当便宜的。晚上酒店门口出租车比较少。   1
位置很好,走路到文庙、清凉寺5分钟都用不了,周边公交车很多很方便,就是出租车不太爱去(老城区路窄爱堵车),因为是老宾馆所以设施要陈旧些,    1
酒店设备一般,套房里卧室的不能上网,要到客厅去。    0
...

第一列数据代表具有感情色彩的评论文本,第二列数据 0 或 1,代表每条文本数据是积极或者消极的评论,0代表消极,1代表积极

3.1 标签数量分布

import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt# 设置显示风格
plt.style.use('fivethirtyeight')# 分别读取训练tsv和验证tsv
train_data = pd.read_csv("data/cn_data/train.tsv", sep="\t")
valid_data = pd.read_csv("data/cn_data/dev.tsv", sep="\t")# 获得训练数据标签数量分布
sns.countplot(x="label", data=train_data)
plt.title("train_data")
plt.show()# 获取验证数据标签数量分布
sns.countplot(x="label", data=valid_data)
plt.title("valid_data")
plt.show()

在深度学习模型评估中,一般使用ACC作为评估指标,若想将ACC的基线定义在50%左右(随机猜测的准确率是 50%),则需要正负样本比例维持在1:1左右,否则就要进行必要的数据增强或数据删减。上图中训练和验证集正负样本都稍有不均衡,可以进行一些数据增强

3.2 句子长度分布

import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt# 设置显示风格
plt.style.use('fivethirtyeight')# 分别读取训练tsv和验证tsv
train_data = pd.read_csv("data/cn_data/train.tsv", sep="\t")
valid_data = pd.read_csv("data/cn_data/dev.tsv", sep="\t")# 在训练数据中添加新的句子长度列, 每个元素的值都是对应的句子列的长度
train_data["sentence_length"] = list(map(lambda x: len(x), train_data["sentence"]))
# 在验证数据中添加新的句子长度列, 每个元素的值都是对应的句子列的长度
valid_data["sentence_length"] = list(map(lambda x: len(x), valid_data["sentence"]))# 绘制句子长度列的数量分布图
sns.countplot(x="sentence_length", data=train_data)
# 主要关注count长度分布的纵坐标, 不需要绘制横坐标, 横坐标范围通过dist图进行查看
plt.xticks([])
plt.show()
# 绘制dist长度分布图
sns.distplot(train_data["sentence_length"])
# 主要关注dist长度分布横坐标, 不需要绘制纵坐标
plt.yticks([])
plt.show()# 绘制句子长度列的数量分布图
sns.countplot(x="sentence_length", data=valid_data)
# 主要关注count长度分布的纵坐标, 不需要绘制横坐标, 横坐标范围通过dist图进行查看
plt.xticks([])
plt.show()
# 绘制dist长度分布图
sns.distplot(valid_data["sentence_length"])
# 主要关注dist长度分布横坐标, 不需要绘制纵坐标
plt.yticks([])
plt.show()

 训练集句子长度分布:

验证集句子长度分布:

通过绘制句子长度分布图,可以得知语料中大部分句子长度的分布范围,因为模型的输入要求为固定尺寸的张量,合理的长度范围对之后进行句子截断补齐(规范长度)起到关键的指导作用。上图中大部分句子长度的范围大致为20-250之间

获取正负样本长度散点分布

# 绘制训练集长度分布的散点图
sns.stripplot(y='sentence_length', x='label', data=train_data)
plt.show()# 绘制验证集长度分布的散点图
sns.stripplot(y='sentence_length', x='label', data=valid_data)
plt.show()

训练集上正负样本的长度散点分布:

验证集上正负样本的长度散点分布:

通过查看正负样本长度散点图,可以有效定位异常点的出现位置,能更准确进行人工语料审查。上图中在训练集正样本中出现了异常点,句子长度近3500左右,需要人工审查

3.3 词频统计与关键词词云

不同词汇总数统计

import jieba
import pandas as pd
# 导入chain方法用于扁平化列表
from itertools import chain# 分别读取训练tsv和验证tsv
train_data = pd.read_csv("data/cn_data/train.tsv", sep="\t")
valid_data = pd.read_csv("data/cn_data/dev.tsv", sep="\t")# 进行训练集的句子进行分词, 并统计出不同词汇的总数
train_vocab = set(chain(*map(lambda x: jieba.lcut(x), train_data["sentence"])))
print("训练集共包含不同词汇总数为:", len(train_vocab))# 进行验证集的句子进行分词, 并统计出不同词汇的总数
valid_vocab = set(chain(*map(lambda x: jieba.lcut(x), valid_data["sentence"])))
print("训练集共包含不同词汇总数为:", len(valid_vocab))# 训练集共包含不同词汇总数为: 12162
# 训练集共包含不同词汇总数为: 6857

获取高频形容词词云

import jieba.posseg as pseg
import pandas as pd
import matplotlib.pyplot as plt
# 导入绘制词云的工具包
from wordcloud import WordCloud
# 导入chain方法用于扁平化列表
from itertools import chaindef get_a_list(text):"""用于获取形容词列表"""# 使用jieba的词性标注方法切分文本,获得具有词性属性flag和词汇属性word的对象# 从而判断flag是否为形容词,来返回对应的词汇r = []for g in pseg.lcut(text):if g.flag == "a":r.append(g.word)return rdef get_word_cloud(keywords_list):# 实例化绘制词云的类, 其中参数font_path是字体路径, 为了能够显示中文,# max_words指词云图像最多显示多少个词, background_color为背景颜色wordcloud = WordCloud(font_path="./data/SimHei.ttf", max_words=100, background_color="white")# 将传入的列表转化成词云生成器需要的字符串形式keywords_string = " ".join(keywords_list)# 生成词云wordcloud.generate(keywords_string)# 绘制图像并显示plt.figure()plt.imshow(wordcloud, interpolation="bilinear")plt.axis("off")plt.show()# 分别读取训练tsv和验证tsv
train_data = pd.read_csv("data/cn_data/train.tsv", sep="\t")
valid_data = pd.read_csv("data/cn_data/dev.tsv", sep="\t")# 获得训练集上正样本
p_train_data = train_data[train_data["label"] == 1]["sentence"]
# 获得训练集上负样本
n_train_data = train_data[train_data["label"] == 0]["sentence"]
# 获得验证集上正样本
p_valid_data = valid_data[valid_data["label"] == 1]["sentence"]
# 获得验证集上负样本
n_valid_data = valid_data[valid_data["label"] == 0]["sentence"]# 对训练集正样本的每个句子的形容词
train_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_train_data))
#print(train_p_n_vocab)
# 获取训练集负样本的每个句子的形容词
train_n_a_vocab = chain(*map(lambda x: get_a_list(x), n_train_data))
# 对验证集正样本的每个句子的形容词
valid_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_valid_data))
#print(train_p_n_vocab)
# 获取验证集负样本的每个句子的形容词
valid_n_a_vocab = chain(*map(lambda x: get_a_list(x), n_valid_data))# 调用绘制词云函数
get_word_cloud(train_p_a_vocab)
get_word_cloud(train_n_a_vocab)
get_word_cloud(valid_p_a_vocab)
get_word_cloud(valid_n_a_vocab)

训练集正样本形容词词云:

训练集负样本形容词词云:

验证集正样本形容词词云:

验证集负样本形容词词云:

根据高频形容词词云显示,可以对当前语料质量进行简单评估,同时对违反语料标签含义的词汇进行人工审查和修正,来保证绝大多数语料符合训练标准。上图中的正样本大多数是褒义词,而负样本大多数是贬义词,但是负样本词云中也存在"好"这样的褒义词,因此可以人工进行审查

四、文本特征处理

文本特征处理包括为语料添加具有普适性的文本特征,如:n-gram特征,以及对加入特征之后的文本语料进行必要的处理,如:长度规范。这些特征处理工作能够有效的将重要的文本特征加入模型训练中,增强模型评估指标

4.1 n-gram特征

给定一段文本序列,其中n个词或字的相邻共现特征即 n-gram 特征,常用的 n-gram 特征是 bi-gram 和 tri-gram 特征,分别对应n为2和3

假设给定分词列表: ["是谁", "敲动", "我心"]对应的数值映射列表为: [1, 34, 21]可以认为数值映射列表中的每个数字是词汇特征除此之外, 还可以把"是谁"和"敲动"两个词共同出现且相邻也作为一种特征加入到序列列表中假设1000就代表"是谁"和"敲动"共同出现且相邻此时数值映射列表就变成了包含 2-gram 特征的特征列表: [1, 34, 21, 1000]这里的"是谁"和"敲动"共同出现且相邻就是bi-gram特征中的一个"敲动"和"我心"也是共现且相邻的两个词汇, 因此也是 bi-gram 特征假设1001代表"敲动"和"我心"共同出现且相邻那么, 最后原始的数值映射列表 [1, 34, 21] 添加了bi-gram特征之后就变成了 [1, 34, 21, 1000, 1001]

提取n-gram特征

n_gram_range = 2def create_n_gram_set(input_list):"""description: 从数值列表中提取所有的 n-gram 特征:param input_list: 输入的数值列表, 可以看作是词汇映射后的列表,里面每个数字的取值范围为[1, 25000]:return: n-gram特征组成的集合>>> create_ngram_set([1, 4, 9, 4, 1, 4]){(4, 9), (4, 1), (1, 4), (9, 4)}"""return set(zip(*[input_list[i:] for i in range(n_gram_range)]))input_list = [1, 3, 2, 1, 5, 3]
result = create_n_gram_set(input_list)
print(result)
# {(3, 2), (1, 3), (2, 1), (1, 5), (5, 3)}

4.2 文本长度规范

一般模型的输入需要等尺寸大小的矩阵,因此在进入模型前需要对每条文本数值映射后的长度进行规范,此时将根据句子长度分布分析出覆盖绝大多数文本的合理长度,对超长文本进行截断, 对不足文本进行补齐(一般使用数字0),这个过程就是文本长度规范

from keras.utils import pad_sequences
text_length = 10def padding_cut(data):"""description: 对输入文本张量进行长度规范:param x_train: 文本的张量表示, 形如: [[1, 32, 32, 61], [2, 54, 21, 7, 19]]:return: 进行截断补齐后的文本张量表示"""# 使用pad_sequences即可完成return pad_sequences(data, text_length)data = [[1, 23, 5, 32, 55, 63, 2, 21, 78, 32, 23, 1], [2, 32, 1, 23, 1]]
res = padding_cut(data)
print(res)
# [[ 5 32 55 63  2 21 78 32 23  1]
#  [ 0  0  0  0  0  2 32  1 23  1]]

五、文本数据增强

回译数据增强目前是文本数据增强方面效果较好的增强方法,一般基于google翻译接口,将文本数据翻译成另外一种语言(一般选择小语种),之后再翻译回原语言,即可认为得到与与原语料同标签的新语料,新语料加入到原数据集中即可认为是对原数据集数据增强

  • 操作简便, 获得新语料质量高.
  • 在短文本回译过程中,新语料与原语料可能存在很高重复率,并不能有效增大样本的特征空间

高重复率解决办法:

进行连续的多语言翻译,如:中文→韩文→日语→英文→中文。根据经验,最多只采用3次连续翻译,更多的翻译次数将产生效率低下,语义失真等问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/19176.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1-16 tortoiseGit分支与Git操作

1-1 创建分支 什么时候需要开分支&#xff1f; - 隔离线上版本和开发版本 - 大功能开发&#xff0c;不想影响到其他人&#xff0c;自己独立开个分支去开发 SVN经典目录结构&#xff1a; - trunk-------------------------开发中的文件 - bran…

4090单卡挑战DeepSeek r1 671b:尝试量化后的心得的分享

引言&#xff1a; 最近&#xff0c;DeepSeek-R1在完全开源的背景下&#xff0c;与OpenAI的O1推理模型展开了激烈竞争&#xff0c;引发了广泛关注。为了让更多本地用户能够运行DeepSeek&#xff0c;我们成功将R1 671B参数模型从720GB压缩至131GB&#xff0c;减少了80%&#xff…

frp与云服务器内网穿透

最近想使用一个便宜的云服务器进行内网穿透&#xff0c;访问到本地电脑 之前使用ssh一直没成功&#xff0c;原因还没分析出来&#xff0c;后来换了一种方法&#xff0c;使用frp来进行内网穿透 frp内网穿透搭建 frp简介 frp 是一个专注于内网穿透的高性能的反向代理应用&…

题海拾贝:英语作文(map)

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞&#xff0c;关注&#xff01; 1、题…

matlab欠驱动船舶模型预测控制

1、内容简介 matlab135-欠驱动船舶模型预测控制 可以交流、咨询、答疑 2、内容说明 略 针对在风 、 浪 、 流时变干扰下欠驱动水面船舶的轨迹跟踪控制问题 &#xff0c; 设计了一种基于模型 预测控制的轨迹跟踪控制器 &#xff0e; 考虑到欠驱动船舶在没有横向驱动力情况下…

2025年-数据库排名

2025年-数据库排名 https://db-engines.com/en/ranking RADB 完整排名 TOP 10 向量 DBMS 的 DB-Engines 排名 关系型 DBMS 的 DB-Engines 排名 搜索引擎的 DB-Engines 排名 键值存储的 DB-Engines 排名 文档存储的 DB-Engines 排名 图形 DBMS 的 DB-Engines 排名 时间序列 DBM…

sib报错:com.*.xctrunner is not in your device!

1、问题描述 在使用sonic集成IOS设备的时候,我们需要通过sonic-agent服务去识别IOS设备。但是在识别的时候提示如下问题: 本质就是在你这个设备中找不到这个设备也就是找不到WebDriverAgentRunner,但是确实安装了,甚至appium可以正常的调用。 或执行如下命令的时候报错:…

rabbitmq五种模式的总结——附java-se实现(详细)

rabbitmq五种模式的总结 完整项目地址&#xff1a;https://github.com/9lucifer/rabbitmq4j-learning 一、简单模式 &#xff08;一&#xff09;简单模式概述 RabbitMQ 的简单模式是最基础的消息队列模式&#xff0c;包含以下两个角色&#xff1a; 生产者&#xff1a;负责发…

LangChain大模型应用开发:提示词工程应用与实践

介绍 大家好&#xff0c;博主又来给大家分享知识了。今天给大家分享的内容是LangChain提示词工程应用与实践。 在如今火热的大语言模型应用领域里&#xff0c;LangChain可是一个相当强大且实用的工具。而其中的提示词(Prompt)&#xff0c;更是我们与语言模型进行有效沟通的关…

4.buuctf [SWPU2019]Web1及知识点

进入题目页面如下 猜测是二次注入 先注册一个账号 再登录&#xff0c;页面如下 点击申请发布广告 页面如上&#xff0c;存在注入点&#xff0c;尝试 判读是整数型注入还是字符型注入 猜解字段数&#xff0c;尝试发现or,#,空格等被过滤了&#xff0c;只能一个一个试 使用联合…

Lua笔记

Lua语法 --注释 #字符串长度、table从1开始连续元素的长度 ..字符串拼接 逻辑运算符 and or not 条件语句 if xxx then elseif yyy then else end 循环语句 for i1,xxx do end xLua AppDomain does not contain a definition for DefineDynamicAssembly&#xff…

开业盛典活动策划方案拆解

道叔来给大家详细剖析咱们方案库里刚收录的这份《蜀大侠火锅店武侠风开业盛典活动策划方案》了&#xff0c;保证让你看完直呼过瘾&#xff0c;收获满满&#xff01; 一、主题创意&#xff1a;武侠风&#xff0c;直击人心 首先&#xff0c;咱们得夸一下这活动的主题——“XXX‘…

三、Unity基础(主要框架)

一、Unity场景概念 如果把游戏运行过程理解成表演&#xff0c;那么场景就是舞台&#xff1b; 场景本质上是一个配置文件&#xff0c;这个配置文件决定了场景中有哪些东西&#xff1b; 二、Scene和Game窗口 1、Scene 滚轮缩放、拖动 单独选中也可以 最下面这个是全能工具…

微软官方出品GPT大模型编排工具:7个开源项目

今天一起盘点下&#xff0c;12月份推荐的7个.Net开源项目&#xff08;点击标题查看详情&#xff09;。 1、一个浏览器自动化操作的.Net开源库 这是一个基于 Google 开源的 Node.js 库 Puppeteer 的 .NET 开源库&#xff0c;方便开发人员使用无头 Web 浏览器抓取 Web、检索 Ja…

C++笔记之类型大小、变量大小,vector与string在栈上内存、堆上内存和总内存的关系

C++笔记之类型大小、变量大小,vector与string在栈上内存、堆上内存和总内存的关系 code review! 文章目录 C++笔记之类型大小、变量大小,vector与string在栈上内存、堆上内存和总内存的关系1.`std::vector<float>` 的内存占用2.`std::vector<float>` 的 `capaci…

华为昇腾920b服务器部署DeepSeek翻车现场

最近到祸一台HUAWEI Kunpeng 920 5250&#xff0c;先看看配置。之前是部署的讯飞大模型&#xff0c;发现资源利用率太低了。把5台减少到3台&#xff0c;就出了他 硬件配置信息 基本硬件信息 按照惯例先来看看配置。一共3块盘&#xff0c;500G的系统盘&#xff0c; 2块3T固态…

【工具变量】ZF引导基金合集(1900-2024年)

政府引导基金是以股权或债权等方式投资于创业风险投资机构或新设的创业风险投资基金&#xff0c;主要用于支持创业企业的发展。根据不同类型的基金&#xff0c;基金出资结构有所不同&#xff0c;可能由政府全额或部分出资&#xff0c;并吸引社会资本和金融机构的参与。 一、政府…

【Java 面试 八股文】常见集合篇

常见集合篇 1. 常见集合有哪些2. ArrayList底层实现的原理是什么&#xff1f;3. ArrayList listnew ArrayList(10)中的list扩容几次4. 如何实现数组和List之间的转换5. ArrayList和LinkedList的区别是什么&#xff1f;6. 说一下HashMap的实现原理&#xff1f;7. HashMap的jdk1.…

使用 DeepSeek 生成商城流程图

步骤 1.下载 mermaid 2.使用 DeepSeek 生成 mermaid 格式 3.复制内容到 4.保存备用。 结束。

STM32 Flash详解教程文章

目录 Flash基本概念理解 Flash编程接口FPEC Flash擦除/写入流程图 Flash选项字节基本概念理解 Flash电子签名 函数读取地址下存放的数据 Flash的数据处理限制部分 编写不易&#xff0c;请勿搬运&#xff0c;感谢理解&#xff01;&#xff01;&#xff01; Flash基本概念…