NLP文本预处理

认识文本预处理

1 文本预处理及其作用

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

2 文本预处理中包含的主要环节

  • 文本处理的基本方法
  • 文本张量表示方法
  • 文本语料的数据分析
  • 文本特征处理
  • 数据增强方法

2.1 文本处理的基本方法

  • 分词
  • 词性标注
  • 命名实体识别

2.2 文本张量表示方法

  • one-hot编码
  • Word2vec
  • Word Embedding

2.3 文本语料的数据分析

  • 标签数量分布
  • 句子长度分布
  • 词频统计与关键词词云

2.4 文本特征处理

  • 添加n-gram特征
  • 文本长度规范

2.5 数据增强方法

  • 回译数据增强法

2.6 重要说明

  • 在实际生产应用中, 我们最常使用的两种语言是中文和英文,因此文本预处理部分的内容都将针对这两种语言进行讲解。

文本处理的基本方法

1 什么是分词

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

  • 举个例子:

    大壮是一只肥猫,它看起来像一台卡车,而且时常伸长身体,使它看起来像在打斯诺克

    ['大壮', '是', '一只', '肥猫', ',', '它', '看起来', '像', '一台', '卡车', ',', '而且', '时常', '伸长', '身体', ',', '使', '它', '看起来', '像', '在', '打', '斯诺克']

  • 分词的作用:

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

    • 愿景: "结巴"中文分词, 做最好的 Python 中文分词组件。
  • jieba的特性:

    • 支持多种分词模式
      • 精确模式
      • 全模式
      • 搜索引擎模式
    • 支持中文繁体分词
    • 支持用户自定义词典
  • jieba的安装:

    pip install jieba

  • jieba的使用:

  • 精确模式分词:
  • 试图将句子最精确地切开,适合文本分析。
python 复制代码
import jieba
content = "大壮是一只肥猫,它看起来像一台卡车,而且时常伸长身体,使它看起来像在打斯诺克"
# 精确模型:试图将句子最精确地切开,适合文本分析。也属于默认模式
jieba.cut(content, cut_all=False)  # cut_all默认为False

# 将返回一个生成器对象
<generator object Tokenizer.cut at 0x7f8d9053e650>

# 若需直接返回列表内容, 使用jieba.lcut即可
jieba.lcut(content, cut_all=False)
['大壮', '是', '一只', '肥猫', ',', '它', '看起来', '像', '一台', '卡车', ',', '而且', '时常', '伸长', '身体', ',', '使', '它', '看起来', '像', '在', '打', '斯诺克']
  • 全模式分词:
  • 把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能消除歧义。
复制代码
# 若需直接返回列表内容, 使用jieba.lcut即可
jieba.lcut(content, cut_all=True)

['大', '壮', '是', '一只', '肥猫', ',', '它', '看起', '看起来', '起来', '像', '一台', '台卡', '卡车', ',', '而且', '时常', '伸长', '身体', ',', '使', '它', '看起', '看起来', '起来', '像', '在', '打', '斯诺', '斯诺克', '诺克']


# 注意1:一台卡车全模型分成三个词
# 注意2:逗号和句号也给分成了词
  • 搜索引擎模式分词:
  • 在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
复制代码
import jieba
content = "大壮是一只肥猫,它看起来像一台卡车,而且时常伸长身体,使它看起来像在打斯诺克"
jieba.cut_for_search(content)

# 将返回一个生成器对象
<generator object Tokenizer.cut_for_search at 0x7f8d90e5a550>

# 若需直接返回列表内容, 使用jieba.lcut_for_search即可
jieba.lcut_for_search(content)
['大壮', '是', '一只', '肥猫', ',', '它', '看起', '起来', '看起来', '像', '一台', '卡车', ',', '而且', '时常', '伸长', '身体', ',', '使', '它', '看起', '起来', '看起来', '像', '在', '打', '斯诺', '诺克', '斯诺克']

# 对'斯诺克'等较长词汇都进行了再次分词.
  • 中文繁体分词:
  • 针对中国香港, 台湾地区的繁体文本进行分词。
复制代码
import jieba
content = "煩惱即是菩提,我暫且不提"
jieba.lcut(content)
['煩惱', '即', '是', '菩提', ',', '我', '暫且', '不', '提']
  • 使用用户自定义词典:
  • 添加自定义词典后, jieba能够准确识别词典中出现的词汇,提升整体的识别准确率。
  • 词典格式: 每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。
  • 词典样式如下, 具体词性含义请参照jieba词性对照表 将该词典存为userdict.txt, 方便之后加载使用。
复制代码
# 格式:word freq word_type
大壮 5
肥猫 6
卡车 7
伸长 3
看起来 3
斯诺克
python 复制代码
import jieba

sentence = '大壮是一只肥猫,它看起来像一台卡车,而且时常伸长身体,使它看起来像在打斯诺克'
# 1 没有使用用户自定义词典
mydata = jieba.lcut(sentence, cut_all=False)
print('mydata-->', mydata)

# 2 使用用户自定义词典
jieba.load_userdict("./userdict.txt")
mydata2 = jieba.lcut(sentence, cut_all=False)
print('mydata2-->', mydata2)

# 没有使用用户自定义词典的分词效果
mydata--> ['大壮', '是', '一只', '肥猫', ',', '它', '看起来', '像', '一台', '卡车', ',', '而且', '时常', '伸长', '身体', ',', '使', '它', '看起来', '像', '在', '打', '斯诺克']

# 使用用户自定义词典的分词效果
mydata2--> ['大壮', '是', '一只', '肥猫', ',', '它', '看', '起来', '像', '一台', '卡车', ',', '而且', '时常', '伸长', '身体', ',', '使', '它', '看', '起来', '像', '在', '打', '斯诺克']

2 什么是命名实体识别

  • 命名实体: 通常我们将人名, 地名, 机构名等专有名词统称命名实体. 如: 周杰伦, 黑山县, 孔子学院, 24辊方钢矫直机。

  • 顾名思义, 命名实体识别(Named Entity Recognition,简称NER)就是识别出一段文本中可能存在的命名实体。

  • 举个例子:

    鲁迅, 浙江绍兴人, 五四新文化运动的重要参与者, 代表作朝花夕拾.

    ==>

    鲁迅(人名) / 浙江绍兴(地名)人 / 五四新文化运动(专有名词) / 重要参与者 / 代表作 / 朝花夕拾(专有名词)

  • 命名实体识别的作用:

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

3 什么是词性标注

  • 词性: 语言中对词的一种分类方法,以语法特征为主要依据、兼顾词汇意义对词进行划分的结果, 常见的词性有14种, 如: 名词, 动词, 形容词等。

  • 顾名思义, 词性标注(Part-Of-Speech tagging, 简称POS)就是标注出一段文本中每个词汇的词性。

  • 举个例子:

    我爱自然语言处理

    ==>

    我/rr, 爱/v, 自然语言/n, 处理/vn

    rr: 人称代词
    v: 动词
    n: 名词
    vn: 动名词

  • 词性标注的作用:

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

python 复制代码
import jieba.posseg as pseg
pseg.lcut("我爱北京天安门") 
[pair('我', 'r'), pair('爱', 'v'), pair('北京', 'ns'), pair('天安门', 'ns')]

# 结果返回一个装有pair元组的列表, 每个pair元组中分别是词汇及其对应的词性, 具体词性含义请参照[附录: jieba词性对照表]()

文本张量表示方法

1 文本张量表示

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

  • 举个例子:

    ["人生", "该", "如何", "起头"]

    ==>

    每个词对应矩阵中的一个向量

    [[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]]

  • 文本张量表示的作用:

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

    • one-hot编码
    • Word2vec
    • Word Embedding

2 one-hot词向量表示

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

举个例子:

复制代码
["改变", "要", "如何", "起手"]`
==>

[[1, 0, 0, 0],
 [0, 1, 0, 0],
 [0, 0, 1, 0],
 [0, 0, 0, 1]]

one-hot编码的实现:

python 复制代码
import jieba
# 导入keras中的词汇映射器Tokenizer
from tensorflow.keras.preprocessing.text import Tokenizer
# 导入用于对象保存与加载的joblib
from sklearn.externals import joblib

# 思路分析 生成onehot
# 1 准备语料 vocabs
# 2 实例化词汇映射器Tokenizer, 使用映射器拟合现有文本数据 (内部生成 index_word word_index)
# 2-1 注意idx序号-1
# 3 查询单词idx 赋值 zero_list,生成onehot
# 4 使用joblib工具保存映射器 joblib.dump()
def dm_onehot_gen():

    # 1 准备语料 vocabs
    vocabs = {"周杰伦", "陈奕迅", "王力宏", "李宗盛", "吴亦凡", "鹿晗"}

    # 2 实例化词汇映射器Tokenizer, 使用映射器拟合现有文本数据 (内部生成 index_word word_index)
    # 2-1 注意idx序号-1
    mytokenizer = Tokenizer()
    mytokenizer.fit_on_texts(vocabs)

    # 3 查询单词idx 赋值 zero_list,生成onehot
    for vocab in vocabs:
        zero_list = [0] * len(vocabs)
        idx = mytokenizer.word_index[vocab] - 1
        zero_list[idx] = 1
        print(vocab, '的onehot编码是', zero_list)

    # 4 使用joblib工具保存映射器 joblib.dump()
    mypath = './mytokenizer'
    joblib.dump(mytokenizer, mypath)
    print('保存mytokenizer End')

    # 注意5-1 字典没有顺序 onehot编码没有顺序 []-有序 {}-无序 区别
    # 注意5-2 字典有的单词才有idx idx从1开始
    # 注意5-3 查询没有注册的词会有异常 eg: 狗蛋
    print(mytokenizer.word_index)
    print(mytokenizer.index_word)

输出结果:

python 复制代码
陈奕迅 的onehot编码是 [1, 0, 0, 0, 0, 0]
王力宏 的onehot编码是 [0, 1, 0, 0, 0, 0]
鹿晗 的onehot编码是 [0, 0, 1, 0, 0, 0]
周杰伦 的onehot编码是 [0, 0, 0, 1, 0, 0]
李宗盛 的onehot编码是 [0, 0, 0, 0, 1, 0]
吴亦凡 的onehot编码是 [0, 0, 0, 0, 0, 1]

保存mytokenizer End

{'陈奕迅': 1, '王力宏': 2, '鹿晗': 3, '周杰伦': 4, '李宗盛': 5, '吴亦凡': 6}
{1: '陈奕迅', 2: '王力宏', 3: '鹿晗', 4: '周杰伦', 5: '李宗盛', 6: '吴亦凡'}

one-hot编码器的使用:

python 复制代码
# 思路分析
# 1 加载已保存的词汇映射器Tokenizer joblib.load(mypath)
# 2 查询单词idx 赋值zero_list,生成onehot 以token为'李宗盛'
# 3 token = "狗蛋" 会出现异常
def dm_onehot_use():

    vocabs = {"周杰伦", "陈奕迅", "王力宏", "李宗盛", "吴亦凡", "鹿晗"}

    # 1 加载已保存的词汇映射器Tokenizer joblib.load(mypath)
    mypath = './mytokenizer'
    mytokenizer = joblib.load(mypath)

    # 2 编码token为"李宗盛"  查询单词idx 赋值 zero_list,生成onehot
    token = "李宗盛"
    zero_list = [0] * len(vocabs)
    idx = mytokenizer.word_index[token] - 1
    zero_list[idx] = 1
    print(token, '的onehot编码是', zero_list)

输出结果:

python 复制代码
李宗盛 的onehot编码是 [0, 0, 0, 0, 1, 0]
  • one-hot编码的优劣势:

    • 优势:操作简单,容易理解。

    • 劣势:完全割裂了词与词之间的联系,而且在大语料集下,每个向量的长度过大,占据大量内存。

    • 正因为one-hot编码明显的劣势,这种编码方式被应用的地方越来越少,取而代之的是接下来我们要学习的稠密向量的表示方法word2vec和word embedding。

3 word2vec模型

3.1 模型介绍

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

CBOW(Continuous bag of words)模式

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

分析:图中的窗口大小为9,使用前后4各四个词对中间的目标词汇进行预测

CBOW模式下的wordtovec过程说明:

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

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

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

skipgram模式

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

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

skipgram模式下的word2vec过程说明:

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

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

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

词向量的检索获取

神经网络训练完毕后,神经网络的参数矩阵w就我们的想要词向量。如何检索某1个单词的向量呢?以CBOW方式举例说明如何检索a单词的词向量。

如下图所示:a的onehot编码[10000],用参数矩阵[3,5] * a的onehot编码[10000],可以把参数矩阵的第1列参数给取出来,这个[3,1]的值就是a的词向量。

3.2 word2vec的训练和使用

  • 第一步: 获取训练数据
  • 第二步: 训练词向量
  • 第三步: 模型超参数设定
  • 第四步: 模型效果检验
  • 第五步: 模型的保存与重加载
获取训练数据

数据来源:http://mattmahoney.net/dc/enwik9.zip

在这里, 我们将研究英语维基百科的部分网页信息, 它的大小在300M左右。这些语料已经被准备好, 我们可以通过Matt Mahoney的网站下载。

注意:原始数据集已经放在/root/data/enwik9.zip,解压后数据为/root/data/enwik9,预处理后的数据为/root/data/fil9

查看原始数据

html 复制代码
$ head -10 data/enwik9

# 原始数据将输出很多包含XML/HTML格式的内容, 这些内容并不是我们需要的
<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.3/ http://www.mediawiki.org/xml/export-0.3.xsd" version="0.3" xml:lang="en">
  <siteinfo>
    <sitename>Wikipedia</sitename>
    <base>http://en.wikipedia.org/wiki/Main_Page</base>
    <generator>MediaWiki 1.6alpha</generator>
    <case>first-letter</case>
      <namespaces>
      <namespace key="-2">Media</namespace>
      <namespace key="-1">Special</namespace>
      <namespace key="0" />

原始数据处理

html 复制代码
# 使用wikifil.pl文件处理脚本来清除XML/HTML格式的内容
# perl wikifil.pl data/enwik9 > data/fil9 #该命令已经执行

查看预处理后的数据

html 复制代码
# 查看前80个字符
head -c 80 data/fil9

# 输出结果为由空格分割的单词
 anarchism originated as a term of abuse first used against early working class
词向量的训练保存和加载

fasttext 是 facebook 开源的一个词向量与文本分类工具。下面是该工具包的安装方法:

python 复制代码
# 训练词向量工具库的安装
# 方法1 简洁版
pip install fasttext  
# 方法2:源码安装(推荐)
# 以linux安装为例: 目录切换到虚拟开发环境目录下,再执行git clone 操作
git clone https://github.com/facebookresearch/fastText.git
cd fastText
# 使用pip安装python中的fasttext工具包
sudo pip install .
python 复制代码
# 导入fasttext
import fasttext

def dm_fasttext_train_save_load():
    # 1 使用train_unsupervised(无监督训练方法) 训练词向量
    mymodel = fasttext.train_unsupervised('./data/fil9')
    print('训练词向量 ok')

    # 2 save_model()保存已经训练好词向量 
    # 注意,该行代码执行耗时很长 
    mymodel.save_model("./data/fil9.bin")
    print('保存词向量 ok')

    # 3 模型加载
    mymodel = fasttext.load_model('./data/fil9.bin')
    print('加载词向量 ok')


# 步骤1运行效果如下:
有效训练词汇量为124M, 共218316个单词
Read 124M words
Number of words:  218316
Number of labels: 0
Progress: 100.0% words/sec/thread:   53996 lr:  0.000000 loss:  0.734999 ETA:   0h 0m
查看单词对应的词向量
python 复制代码
# 通过get_word_vector方法来获得指定词汇的词向量, 默认词向量训练出来是1个单词100特征
def dm_fasttext_get_word_vector():
    mymodel = fasttext.load_model('./data/fil9.bin')

    myvector = mymodel.get_word_vector('the')
    print('myvector->', type(myvector), myvector.shape, myvector)

# 运行效果如下:
array([-0.03087516,  0.09221972,  0.17660329,  0.17308897,  0.12863874,
        0.13912526, -0.09851588,  0.00739991,  0.37038437, -0.00845221,
        ...
       -0.21184735, -0.05048715, -0.34571868,  0.23765688,  0.23726143],
      dtype=float32)
模型效果检验
python 复制代码
# 检查单词向量质量的一种简单方法就是查看其邻近单词, 通过我们主观来判断这些邻近单词是否与目标单词相关来粗略评定模型效果好坏.

# 查找"运动"的邻近单词, 我们可以发现"体育网", "运动汽车", "运动服"等. 
>>> model.get_nearest_neighbors('sports')

[(0.8414610624313354, 'sportsnet'), (0.8134572505950928, 'sport'), (0.8100415468215942, 'sportscars'), (0.8021156787872314, 'sportsground'), (0.7889881134033203, 'sportswomen'), (0.7863013744354248, 'sportsplex'), (0.7786710262298584, 'sporty'), (0.7696356177330017, 'sportscar'), (0.7619683146476746, 'sportswear'), (0.7600985765457153, 'sportin')]


# 查找"音乐"的邻近单词, 我们可以发现与音乐有关的词汇.
>>> model.get_nearest_neighbors('music')

[(0.8908010125160217, 'emusic'), (0.8464668393135071, 'musicmoz'), (0.8444250822067261, 'musics'), (0.8113634586334229, 'allmusic'), (0.8106718063354492, 'musices'), (0.8049437999725342, 'musicam'), (0.8004694581031799, 'musicom'), (0.7952923774719238, 'muchmusic'), (0.7852965593338013, 'musicweb'), (0.7767147421836853, 'musico')]

# 查找"小狗"的邻近单词, 我们可以发现与小狗有关的词汇.
>>> model.get_nearest_neighbors('dog')

[(0.8456876873970032, 'catdog'), (0.7480780482292175, 'dogcow'), (0.7289096117019653, 'sleddog'), (0.7269964218139648, 'hotdog'), (0.7114801406860352, 'sheepdog'), (0.6947550773620605, 'dogo'), (0.6897546648979187, 'bodog'), (0.6621081829071045, 'maddog'), (0.6605004072189331, 'dogs'), (0.6398137211799622, 'dogpile')]
模型超参数设定
python 复制代码
# 在训练词向量过程中, 我们可以设定很多常用超参数来调节我们的模型效果, 如:
# 无监督训练模式: 'skipgram' 或者 'cbow', 默认为'skipgram', 在实践中,skipgram模式在利用子词方面比cbow更好.
# 词嵌入维度dim: 默认为100, 但随着语料库的增大, 词嵌入的维度往往也要更大.
# 数据循环次数epoch: 默认为5, 但当你的数据集足够大, 可能不需要那么多次.
# 学习率lr: 默认为0.05, 根据经验, 建议选择[0.01,1]范围内.
# 使用的线程数thread: 默认为12个线程, 一般建议和你的cpu核数相同.

>>> model = fasttext.train_unsupervised('data/fil9', "cbow", dim=300, epoch=1, lr=0.1, thread=8)

Read 124M words
Number of words:  218316
Number of labels: 0
Progress: 100.0% words/sec/thread:   49523 lr:  0.000000 avg.loss:  1.777205 ETA:   0h 0m 0s

4 词嵌入word embedding介绍

通过一定的方式将词汇映射到指定维度(一般是更高维度)的空间。

广义的word embedding包括所有密集词汇向量的表示方法,如之前学习的word2vec, 即可认为是word embedding的一种。

狭义的word embedding是指在神经网络中加入的embedding层, 对整个网络进行训练的同时产生的embedding矩阵(embedding层的参数), 这个embedding矩阵就是训练过程中所有输入词汇的向量表示组成的矩阵。

python 复制代码
import torch
import jieba
import torch.nn as nn
from tensorflow.keras.preprocessing.text import Tokenizer

def word_embedding_demo():
    # 1 对句子分词 word_list
    sentence1 = '大壮是一只肥猫,它看起来像一台卡车,而且时常伸长身体,使它看起来像在打斯诺克'
    sentence2 = "我爱自然语言处理"
    sentences = [sentence1, sentence2]
    word_list = []
    for sentence in sentences:
        word_list.append(jieba.lcut(sentence))

    print(f'word_list: {word_list}')

    # 2 对句子word2id求my_token_list,对句子文本数值化sentence2id
    tokenizer = Tokenizer()
    tokenizer.fit_on_texts(word_list)
    my_token_list = tokenizer.index_word.values()
    nums_embedding = len(my_token_list)

    sentence2id = tokenizer.texts_to_sequences(word_list)
    print(f'sentence2id: {sentence2id}')

    print('*' * 20 + '数据预处理部分到此截至' + '*' * 20)

    # 3 创建nn.Embedding层
    embd = nn.Embedding(num_embeddings=nums_embedding, embedding_dim=8)

    # 6 根据idx拿词向量
    for index in range(nums_embedding):
        input = torch.tensor(index)
        word_vector = embd(input)
        print(f'单词:{tokenizer.index_word[index + 1]} ,索引:{index}, 词向量:{word_vector.detach().numpy()} ')

if __name__ == '__main__':
    word_embedding_demo()

程序运行效果:

python 复制代码
word_list: [['大壮', '是', '一只', '肥猫', ',', '它', '看起来', '像', '一台', '卡车', ',', '而且', '时常', '伸长', '身体', ',', '使', '它', '看起来', '像', '在', '打', '斯诺克'], ['我', '爱', '自然语言', '处理']]
my_token_list: dict_values([',', '它', '看起来', '像', '大壮', '是', '一只', '肥猫', '一台', '卡车', '而且', '时常', '伸长', '身体', '使', '在', '打', '斯诺克', '我', '爱', '自然语言', '处理'])
nums_embedding: 22
sentence2id: [[5, 6, 7, 8, 1, 2, 3, 4, 9, 10, 1, 11, 12, 13, 14, 1, 15, 2, 3, 4, 16, 17, 18], [19, 20, 21, 22]]
********************数据预处理部分到此截至********************
单词:, ,索引:0, 词向量:[-1.0019748   2.1034682  -0.6421641   0.18872783  1.3844162   0.4372401
  0.11215194 -1.4044648 ] 
单词:它 ,索引:1, 词向量:[-0.12372922 -0.34016806  0.3133533  -0.39544478  1.1182148   0.4102973
 -0.50041366 -1.7253363 ] 
单词:看起来 ,索引:2, 词向量:[-1.8702623   1.6753458   0.1391657  -1.6196455  -0.07456923 -1.6881874
  1.3985647   0.0982416 ] 
单词:像 ,索引:3, 词向量:[ 0.8195846  -0.75030386 -2.5443625  -1.2438439   0.74480975  1.5852734
  0.20916803 -0.30198157] 
单词:大壮 ,索引:4, 词向量:[-1.4788971   1.504806   -0.10343227  1.4761834  -1.3887477  -0.99142605
  0.27314866  0.81736344] 
单词:是 ,索引:5, 词向量:[-0.19866535 -0.872717    0.70173377  0.660278   -0.02658964  0.43032143
  0.31618974  1.5973266 ] 
单词:一只 ,索引:6, 词向量:[-1.1565173  -0.5613759  -1.0282246   1.0865189   0.67352957 -0.73041946
  1.1537951  -1.9948974 ] 
单词:肥猫 ,索引:7, 词向量:[-0.5390743  -0.19060782  1.8721956  -1.241953   -0.2412651   1.0083534
 -0.936323    1.0242219 ] 
单词:一台 ,索引:8, 词向量:[-1.6025405   1.1727215  -0.72769946  0.08393567 -0.52862906  0.34308353
  0.1818359   1.011255  ] 
单词:卡车 ,索引:9, 词向量:[ 0.9617531  -1.5222783   0.5079899   0.67262715  0.10581371 -1.0521044
 -1.1726444  -1.0906234 ] 
单词:而且 ,索引:10, 词向量:[ 0.20569882 -0.6941174  -0.8476634   0.01048023 -1.2410288   0.25900313
  0.6938502   1.7030785 ] 
单词:时常 ,索引:11, 词向量:[ 1.8215386 -1.0834775 -1.183909   1.1692375  1.046829  -0.9996108
  1.5940698 -1.2441154] 
单词:伸长 ,索引:12, 词向量:[ 0.53214616  0.86160505  0.40506235 -0.19525798 -0.5321762   0.11935219
 -0.23519476 -0.9591835 ] 
单词:身体 ,索引:13, 词向量:[ 0.78559834  0.07251568  2.0843248   1.2136965   1.0807943  -0.60160226
  0.5800502  -0.992616  ] 
单词:使 ,索引:14, 词向量:[ 0.8701581   0.7603921   1.3485266   0.04571709  0.96786326  0.14274526
 -1.5793886   1.1204865 ] 
单词:在 ,索引:15, 词向量:[-0.1748582   0.2117947   0.32797554  0.14593276  1.2658246   0.35309646
 -0.40824893 -0.36999252] 
单词:打 ,索引:16, 词向量:[-0.5509949   0.131074    0.42356685  0.5336856   1.0220431  -3.0073214
  0.59534365 -0.50066555] 
单词:斯诺克 ,索引:17, 词向量:[-1.0875909   0.72114146  3.4376652   0.38434505 -0.9066141  -0.5952264
 -0.7368054   0.29357392] 
单词:我 ,索引:18, 词向量:[ 0.23355238 -0.5395831  -1.3813912  -0.32020932  0.40459493  0.0855441
  0.9421059   0.60523075] 
单词:爱 ,索引:19, 词向量:[-0.2519719   0.514191   -0.11430571 -0.6295364   1.2720859   0.58814436
  1.141736    0.7106812 ] 
单词:自然语言 ,索引:20, 词向量:[-0.49341395  0.39473578  0.60976964 -0.02758557  1.1715553  -0.25975537
  0.01857676 -1.1453928 ] 
单词:处理 ,索引:21, 词向量:[ 0.75272965 -1.2679921  -0.31932047  0.794756   -0.06445816  1.8824439
 -0.3841436   0.28897914] 

文本数据分析

1 文件数据分析介绍

  • 文本数据分析的作用:

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

    • 标签数量分布
    • 句子长度分布
    • 词频统计与关键词词云

2 数据集说明

  • 我们将基于真实的中文酒店评论语料来讲解常用的几种文本数据分析方法.

  • 中文酒店评论语料:

    • 属于二分类的中文情感分析语料。
    • 其中train.tsv代表训练集, dev.tsv代表验证集, 二者数据样式相同。
  • 数据下载:https://pan.baidu.com/s/11y0fUzKDgiEBzK2n_rTndw?pwd=9a4u 提取码: 9a4u

  • train.tsv数据样式:

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

  • train.tsv数据样式说明:

    • train.tsv中的数据内容共分为2列, 第一列数据代表具有感情色彩的评论文本; 第二列数据, 0或1, 代表每条文本数据是积极或者消极的评论, 0代表消极, 1代表积极。

3 获取标签数量分布

python 复制代码
# 导入必备工具包
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt

# 思路分析 : 获取标签数量分布
# 0 什么标签数量分布:求标签0有多少个 标签1有多少个 标签2有多少个
# 1 设置显示风格plt.style.use('fivethirtyeight')
# 2 pd.read_csv(path, sep='\t') 读训练集 验证集数据
# 3 sns.countplot() 统计label标签的0、1分组数量
# 4 画图展示 plt.title() plt.show()
# 注意1:sns.countplot()相当于select * from tab1 group by
def dm_label_sns_countplot():

    # 1 设置显示风格plt.style.use('fivethirtyeight')
    plt.style.use('fivethirtyeight')

    # 2 pd.read_csv 读训练集 验证集数据
    train_data = pd.read_csv(filepath_or_buffer = './cn_data/train.tsv', sep='\t')
    dev_data = pd.read_csv(filepath_or_buffer = './cn_data/dev.tsv', sep='\t')

    # 3 sns.countplot() 统计label标签的0、1分组数量
    sns.countplot(x='label', data = train_data)

    # 4 画图展示 plt.title() plt.show()
    plt.title('train_label')
    plt.show()

    # 验证集上标签的数量分布
    # 3-2 sns.countplot() 统计label标签的0、1分组数量
    sns.countplot(x='label', data = dev_data)

    # 4-2 画图展示 plt.title() plt.show()
    plt.title('dev_label')
    plt.show()
  • 训练集标签数量分布:
  • 验证集标签数量分布:
  • 分析:
    • 在深度学习模型评估中, 我们一般使用ACC作为评估指标, 若想将ACC的基线定义在50%左右, 则需要我们的正负样本比例维持在1:1左右, 否则就要进行必要的数据增强或数据删减. 上图中训练和验证集正负样本都稍有不均衡, 可以进行一些数据增强。

4 获取句子长度分布

python 复制代码
# 思路分析 : 获取句子长度分布 -绘制句子长度分布-柱状图 句子长度分布-密度曲线图
# 0 什么是句子长度分布:求长度为50的有多少个 长度51的有多少个 长度为52的有多少个
# 1 设置显示风格plt.style.use('fivethirtyeight')
# 2 pd.read_csv(path, sep='\t') 读训练集 验证集数据
# 3 新增数据长度列:train_data['sentence_length'] = list(map(lambda x:len(x) , ...))
# 4-1 绘制数据长度分布图-柱状图 sns.countplot(x='sentence_length', data=train_data)
#  画图展示 plt.xticks([]) plt.show()
# 4-2  绘制数据长度分布图-曲线图 sns.displot(x='sentence_length', data=train_data)
# 画图展示 plt.yticks([]) plt.show()

def dm_len_sns_countplot_distplot():
    # 1 设置显示风格plt.style.use('fivethirtyeight')
    plt.style.use('fivethirtyeight')

    # 2 pd.read_csv 读训练集 验证集数据
    train_data = pd.read_csv(filepath_or_buffer='./cn_data/train.tsv', sep='\t')
    dev_data = pd.read_csv(filepath_or_buffer='./cn_data/dev.tsv', sep='\t')

    # 3 求数据长度列 然后求数据长度的分布
    train_data['sentence_length'] =  list( map(lambda x: len(x), train_data['sentence']))

    # 4 绘制数据长度分布图-柱状图
    sns.countplot(x='sentence_length', data=train_data)
    # sns.countplot(x=train_data['sentence_length'])
    plt.xticks([]) # x轴上不要提示信息
    # plt.title('sentence_length countplot')
    plt.show()

    # 5 绘制数据长度分布图-曲线图
    sns.displot(x='sentence_length', data=train_data)
    # sns.displot(x=train_data['sentence_length'])
    plt.yticks([]) # y轴上不要提示信息
    plt.show()

    # 验证集
    # 3 求数据长度列 然后求数据长度的分布
    dev_data['sentence_length'] = list(map(lambda x: len(x), dev_data['sentence']))

    # 4 绘制数据长度分布图-柱状图
    sns.countplot(x='sentence_length', data=dev_data)
    # sns.countplot(x=dev_data['sentence_length'])
    plt.xticks([])  # x轴上不要提示信息
    # plt.title('sentence_length countplot')
    plt.show()

    # 5 绘制数据长度分布图-曲线图
    sns.displot(x='sentence_length', data=dev_data)
    # sns.displot(x=dev_data['sentence_length'])
    plt.yticks([])  # y轴上不要提示信息
    plt.show()
  • 训练集句子长度分布:
  • 验证集句子长度分布:
  • 分析:
    • 通过绘制句子长度分布图, 可以得知我们的语料中大部分句子长度的分布范围, 因为模型的输入要求为固定尺寸的张量,合理的长度范围对之后进行句子截断补齐(规范长度)起到关键的指导作用. 上图中大部分句子长度的范围大致为20-250之间。

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

python 复制代码
# 获取正负样本长度散点分布,也就是按照x正负样本进行分组 再按照y长度进行散点图
# train_data['sentence_length'] = list(map(lambda x: len(x), train_data['sentence']))
#  sns.stripplot(y='sentence_length', x='label', data=train_data)
def dm03_sns_stripplot():
    # 1 设置显示风格plt.style.use('fivethirtyeight')
    plt.style.use('fivethirtyeight')

    # 2 pd.read_csv 读训练集 验证集数据
    train_data = pd.read_csv(filepath_or_buffer='./cn_data/train.tsv', sep='\t')
    dev_data = pd.read_csv(filepath_or_buffer='./cn_data/dev.tsv', sep='\t')

    # 3 求数据长度列 然后求数据长度的分布
    train_data['sentence_length'] = list(map(lambda x: len(x), train_data['sentence']))

    # 4 统计正负样本长度散点图 (对train_data数据,按照label进行分组,统计正样本散点图)
    sns.stripplot(y='sentence_length', x='label', data=train_data)
    plt.show()

    sns.stripplot(y='sentence_length', x='label', data=dev_data)
    plt.show()
  • 训练集上正负样本的长度散点分布:
  • 验证集上正负样本的长度散点分布:
  • 分析:
    • 通过查看正负样本长度散点图, 可以有效定位异常点的出现位置, 帮助我们更准确进行人工语料审查. 上图中在训练集正样本中出现了异常点, 它的句子长度近3500左右, 需要我们人工审查。

6 获取不同词汇总数统计

python 复制代码
# 导入jieba用于分词
# 导入chain方法用于扁平化列表
import jieba
from itertools import chain

# 进行训练集的句子进行分词, 并统计出不同词汇的总数
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))

输出效果:

7 获取训练集高频形容词词云

python 复制代码
# 使用jieba中的词性标注功能
import jieba.posseg as pseg
from wordcloud import WordCloud

# 每句话产生形容词列表
def get_a_list(text):
    r = []

    # 使用jieba的词性标注方法切分文本 找到形容词存入到列表中返回
    for g in pseg.lcut(text):
        if g.flag == "a":
            r.append(g.word)
    return r

# 根据词云列表产生词云
def  get_word_cloud(keywords_list):
    # 实例化词云生成器对象
    wordcloud = WordCloud(font_path="./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()


# 思路分析 训练集正样本词云 训练集负样本词云
# 1 获得训练集上正样本 p_train_data
#   eg: 先使用逻辑==操作检索符合正样本 train_data[train_data['label'] == 1]
# 2 获取正样本的每个句子的形容词 p_a_train_vocab = chain(*map(a,b))
# 3 调用绘制词云函数
def dm_word_cloud():
    # 1 获得训练集上正样本p_train_data
    #   eg: 先使用逻辑==操作检索符合正样本 train_data[train_data['label'] == 1]
    train_data = pd.read_csv(filepath_or_buffer='./cn_data/train.tsv', sep='\t')
    p_train_data = train_data[train_data['label'] == 1 ]['sentence']

    # 2 获取正样本的每个句子的形容词 p_a_train_vocab = chain(*map(a,b))
    p_a_train_vocab = chain(*map(lambda x: get_a_list(x) , p_train_data))
    # print(p_a_train_vocab)
    # print(list(p_a_train_vocab))

    # 3 调用绘制词云函数
    get_word_cloud(p_a_train_vocab)


    print('*' * 60 )
    # 训练集负样本词云
    n_train_data = train_data[train_data['label'] == 0 ]['sentence']

    # 2 获取正样本的每个句子的形容词 p_a_train_vocab = chain(*map(a,b))
    n_a_train_vocab = chain(*map(lambda x: get_a_list(x) , n_train_data)  )
    # print(n_a_dev_vocab)
    # print(list(n_a_dev_vocab))

    # 3 调用绘制词云函数
    get_word_cloud(n_a_train_vocab)
  • 训练集正样本形容词词云:
  • 训练集负样本形容词词云:

8 获取验证集形容词词云

python 复制代码
# 获得验证集上正样本
p_valid_data = valid_data[valid_data["label"]==1]["sentence"]

# 对正样本的每个句子的形容词
valid_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_valid_data))
#print(train_p_n_vocab)

# 获得验证集上负样本
n_valid_data = valid_data[valid_data["label"]==0]["sentence"]

# 获取负样本的每个句子的形容词
valid_n_a_vocab = chain(*map(lambda x: get_a_list(x), n_valid_data))

# 调用绘制词云函数
get_word_cloud(valid_p_a_vocab)
get_word_cloud(valid_n_a_vocab)
  • 验证集正样本形容词词云:
  • 验证集负样本形容词词云:
  • 分析:
    • 根据高频形容词词云显示, 我们可以对当前语料质量进行简单评估, 同时对违反语料标签含义的词汇进行人工审查和修正, 来保证绝大多数语料符合训练标准. 上图中的正样本大多数是褒义词, 而负样本大多数是贬义词, 基本符合要求, 但是负样本词云中也存在"便利"这样的褒义词, 因此可以人工进行审查。

文本特征处理

1 什么是n-gram特征

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

  • 举个例子:

python 复制代码
假设给定分词列表: ["是谁", "敲动", "我心"]

对应的数值映射列表为: [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特征:
python 复制代码
# 一般n-gram中的n取2或者3, 这里取2为例
ngram_range = 2

def create_ngram_set(input_list):
    """
    description: 从数值列表中提取所有的n-gram特征
    :param input_list: 输入的数值列表, 可以看作是词汇映射后的列表, 
                       里面每个数字的取值范围为[1, 25000]
    :return: n-gram特征组成的集合

    eg:
    >>> create_ngram_set([1, 3, 2, 1, 5, 3])
    {(3, 2), (1, 3), (2, 1), (1, 5), (5, 3)}
    """ 
    return set(zip(*[input_list[i:] for i in range(ngram_range)]))
  • 调用:
python 复制代码
input_list = [1, 3, 2, 1, 5, 3]
res = create_ngram_set(input_list)
print(res)
  • 输出效果:
python 复制代码
# 该输入列表的所有bi-gram特征
{(3, 2), (1, 3), (2, 1), (1, 5), (5, 3)}

2 文本长度规范及其作用

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

  • 文本长度规范的实现:

python 复制代码
from tensorflow.keras.preprocessing import sequence

# cutlen根据数据分析中句子长度分布,覆盖90%左右语料的最短长度.
# 这里假定cutlen为10
cutlen = 10

def padding(x_train):
    """
    description: 对输入文本张量进行长度规范
    :param x_train: 文本的张量表示, 形如: [[1, 32, 32, 61], [2, 54, 21, 7, 19]]
    :return: 进行截断补齐后的文本张量表示 
    """
    # 使用sequence.pad_sequences即可完成
    return sequence.pad_sequences(x_train, cutlen)
  • 调用:
python 复制代码
# 假定x_train里面有两条文本, 一条长度大于10, 一天小于10
x_train = [[1, 23, 5, 32, 55, 63, 2, 21, 78, 32, 23, 1],
           [2, 32, 1, 23, 1]]

res = padding(x_train)
print(res)
  • 输出效果:
python 复制代码
[[ 5 32 55 63  2 21 78 32 23  1]
 [ 0  0  0  0  0  2 32  1 23  1]]

文本数据增强

回译数据增强法

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

  • 回译数据增强优势:

    • 操作简便, 获得新语料质量高.
  • 回译数据增强存在的问题:

    • 在短文本回译过程中, 新语料与原语料可能存在很高的重复率, 并不能有效增大样本的特征空间.
  • 高重复率解决办法:

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

词性对照表

  • jieba词性对照表:
python 复制代码
- a 形容词  
    - ad 副形词  
    - ag 形容词性语素  
    - an 名形词  
- b 区别词  
- c 连词  
- d 副词  
    - df   
    - dg 副语素  
- e 叹词  
- f 方位词  
- g 语素  
- h 前接成分  
- i 成语 
- j 简称略称  
- k 后接成分  
- l 习用语  
- m 数词  
    - mg 
    - mq 数量词  
- n 名词  
    - ng 名词性语素  
    - nr 人名  
    - nrfg    
    - nrt  
    - ns 地名  
    - nt 机构团体名  
    - nz 其他专名  
- o 拟声词  
- p 介词  
- q 量词  
- r 代词  
    - rg 代词性语素  
    - rr 人称代词  
    - rz 指示代词  
- s 处所词  
- t 时间词  
    - tg 时语素  
- u 助词  
    - ud 结构助词 得
    - ug 时态助词
    - uj 结构助词 的
    - ul 时态助词 了
    - uv 结构助词 地
    - uz 时态助词 着
- v 动词  
    - vd 副动词
    - vg 动词性语素  
    - vi 不及物动词  
    - vn 名动词  
    - vq 
- x 非语素词  
- y 语气词  
- z 状态词  
    - zg 
  • hanlp词性对照表:
python 复制代码
【Proper Noun------NR,专有名词】

【Temporal Noun------NT,时间名词】

【Localizer------LC,定位词】如"内","左右"

【Pronoun------PN,代词】

【Determiner------DT,限定词】如"这","全体"

【Cardinal Number------CD,量词】

【Ordinal Number------OD,次序词】如"第三十一"

【Measure word------M,单位词】如"杯"

【Verb:VA,VC,VE,VV,动词】

【Adverb:AD,副词】如"近","极大"

【Preposition:P,介词】如"随着"

【Subordinating conjunctions:CS,从属连词】

【Conjuctions:CC,连词】如"和"

【Particle:DEC,DEG,DEV,DER,AS,SP,ETC,MSP,小品词】如"的话"

【Interjections:IJ,感叹词】如"哈"

【onomatopoeia:ON,拟声词】如"哗啦啦"

【Other Noun-modifier:JJ】如"发稿/JJ 时间/NN"

【Punctuation:PU,标点符号】

【Foreign word:FW,外国词语】如"OK

尾声

文本预处理的过程至关重要,友友们可以多多关注把词转换为向量的过程。

最后,专栏的下一篇将介绍rnn循环神经网络及其变体(LSTM、GRU),rnn的基本知识在深度学习专栏已经简单介绍过,这里将更加深入地介绍,值得注意的是,这块儿知识较难理解,友友们可以先看看笔者在深度学习专栏关于循环神经网络的介绍,这里附上链接:

循环神经网络的概念和案例

相关推荐
子燕若水2 小时前
Unreal Engine 5中的AI知识
人工智能
极限实验室3 小时前
Coco AI 实战(一):Coco Server Linux 平台部署
人工智能
杨过过儿3 小时前
【学习笔记】4.1 什么是 LLM
人工智能
巴伦是只猫3 小时前
【机器学习笔记Ⅰ】13 正则化代价函数
人工智能·笔记·机器学习
伍哥的传说3 小时前
React 各颜色转换方法、颜色值换算工具HEX、RGB/RGBA、HSL/HSLA、HSV、CMYK
深度学习·神经网络·react.js
大千AI助手3 小时前
DTW模版匹配:弹性对齐的时间序列相似度度量算法
人工智能·算法·机器学习·数据挖掘·模版匹配·dtw模版匹配
AI生存日记3 小时前
百度文心大模型 4.5 系列全面开源 英特尔同步支持端侧部署
人工智能·百度·开源·open ai大模型
LCG元4 小时前
自动驾驶感知模块的多模态数据融合:时序同步与空间对齐的框架解析
人工智能·机器学习·自动驾驶
why技术4 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端