NLP自然语言处理 01 文本预处理

发布于:2025-07-01 ⋅ 阅读:(26) ⋅ 点赞:(0)

文本预处理

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

文本处理的基本方法

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

文本张量表示方法

  • one-hot编码
  • Word2vec
  • Word Embedding

文本语料的数据分析

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

已有数据时,优先进行数据分析

文本特征处理

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

数据增强方法

  • 回译数据增强法

文本处理的基本方法

        分词

        分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。

        分词的原因:在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符。

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

        jieba:流行的分词模块

        注意:jieba的cut返回的是一个生成器,lcut返回的是一个列表

        不同模式的选择参数是通用的,只是返回的东西不一样

import jieba
content = "今天下午三点我在咖啡厅等了你整整两小时,但最终你并没有出现。"
# 精准模式,试图将句子最精确地切开,适合文本分析.
jieba.cut(content, cut_all=False)
print(jieba.lcut(content, cut_all=False))
# 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能消除歧义。
print(jieba.lcut(content, cut_all=True))
# 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
print(jieba.lcut_for_search(content))
# 自定义词典
jieba.load_userdict("dict.txt")
'''
添加自定义词典后, jieba能够准确识别词典中出现的词汇,提升整体的识别准确率。
词典格式: 每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。
词典内容为 
今天下午 
整整两小时
'''
print(jieba.lcut(content))

运行结果 

命名实体识别(了解)

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

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

        通常使用训练好的模型来识别

词性标注

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

        词性标注(Part-Of-Speech tagging, 简称POS)就是标注出一段文本中每个词汇的词性.

词性标注作用:对文本语言的另一个角度的理解,ai解决nlp领域高阶任务的重要基础环节

        使用jieba进行词性标注:

import jieba.posseg as pseg # (Part-Of-Speech tagging, 简称POS)
def dm04_jieba_pos():
    sentence = '我爱北京天安门'
    mydata = pseg.lcut(sentence)
    print('mydata-->', mydata)
    # 返回结果 1:pair元组的列表 2:每个pair元组由词汇和词性组成
     # mydata --> [pair('我', 'r'), pair('爱', 'v'), pair('北京', 'ns'), pair('天安门', 'ns')]
if __name__ == '__main__':
    dm04_jieba_pos()

文本的张量化表示

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

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

==>

# 每个词对应矩阵中的一个向量
[[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

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 jieba
# 导入keras中的词汇映射器Tokenizer
from tensorflow.keras.preprocessing.text import Tokenizer
# 导入用于对象保存与加载的joblib
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)
if __name__ == '__main__':
    dm_onehot_gen()
Tokenizer()是把词变为类似字典的形式,值为词和索引的键值对,因为字典对字符没有顺序,所以每次onehot编码顺序可能不同
  • 输出效果 

陈奕迅 的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: '吴亦凡'}
 

word2vec模型     

是一种将 单词 转换为 词向量 的自然语言处理技术
是利用 深度学习网络 来探索 单词和单词之间的语义关系 ,用深度学习的 网络权重参数 表示词向量
是在 无监督的语料 上构建了一个 有监督的任务

Word2Vec主要包含两种模型架构:

  1. ​CBOW(Continuous Bag-of-Words)​

    • ​原理​​:通过上下文词预测中心词。例如,给定句子“the cat sits on the”,模型会利用上下文词(“the”“cat”“sits”“on”)预测中心词“mat”
    • ​特点​​:计算效率高,适合大规模数据集和高频词,但对低频词效果较弱
  2. ​Skip-gram​

    • ​原理​​:通过中心词预测上下文词。例如,给定中心词“fox”,模型预测其周围的词(如“quick”“brown”“jumps”“over”)
    • ​特点​​:更适合处理低频词和捕捉细粒度语义关系,但计算复杂度较高

CBOW(Continuous bag of words)模式:

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

CBOW模式下的word2vec过程说明:

  • 假设我们给定的训练语料只有一句话: 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模式:

  • 假设我们给定的训练语料只有一句话: 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张量表示.
词向量的检索获取
  • 神经网络训练完毕后,如何检索某1个单词的向量呢?以CBOW方式举例说明如何检索a单词的词向量。
  • 如下图所示:a的onehot编码[10000],用参数矩阵[3,5] * a的onehot编码[10000],可以把参数矩阵的第1列参数给取出来,这个[3,1]的值就是a的词向量。

word2vec的训练和使用 

获取训练数据

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

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

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

import fasttext

"""
需求:基于 ./data/fil9 数据集, 进行词向量的训练,并检验效果
思路步骤:
1. 准备语料库 ./data/fil9
2. 使用无监督训练api ,训练模型
3. 验证模型的效果, 查看模型的向量
4. 模型的近邻单词的表现
5. 保存模型
6. 加载模型,查看是否可以正常加载
"""


def fasttext_demo():
    # 1. 准备语料库 ./data/fil9
    path = './data/fil9'
    # 2. 使用无监督训练api ,训练模型
    # train_unsupervised: 给word2vec使用,训练的是词向量。 注意:不要调用错了
    # train_supervised: 给文本分类使用的,训练的是分类模型
    # model = fasttext.train_unsupervised(path)
    # 为了节省时间,直接加载已经训练好的模型
    model_path = './data/fil9.bin'
    model = fasttext.load_model(model_path)

    print(f'单词数量:{len(model.words)}')
    print(f'模型维度:{model.get_dimension()}')
    # 3. 验证模型的效果, 查看模型的向量
    vector = model.get_word_vector('apple')
    print(vector)
    # 4. 模型的近邻单词的表现
    # get_nearest_neighbors: 基于词向量之间的距离(如:欧氏距离),计算最相似的单词
    print(model.get_nearest_neighbors('sports'))
    print(model.get_nearest_neighbors('apple'))
    # 5. 保存模型
    # 保存模型的时候,对模型的后缀名是没有要求的。但是保存的文件只能通过fasttext进行读取
    model.save_model('./data/fil9.bin.1')
    # 6. 加载模型,查看是否可以正常加载

    model1 = fasttext.load_model('./data/fil9.bin.1')

    vector2 = model1.get_word_vector('apple')

    # 判断两个模型对一个单词的预测结果是否完全一致
    print(vector == vector2)

# TODO:fasttext 训练word2vec 默认参数
# unsupervised_default = {
#     "model": "skipgram",
#     "lr": 0.05,
#     "dim": 100,
#     "epoch": 5,
#     "thread": multiprocessing.cpu_count() - 1
# }
#

# 在训练词向量过程中, 我们可以设定很多常用超参数来调节我们的模型效果, 如:
# TODO:无监督训练模式: 'skipgram' 或者 'cbow', 默认为'skipgram', 在实践中,skipgram模式在利用子词方面比cbow更好.
# TODO: 词嵌入维度dim: 默认为100, 但随着语料库的增大, 词嵌入的维度往往也要更大.
# 数据循环次数epoch: 默认为5, 但当你的数据集足够大, 可能不需要那么多次.
# 学习率lr: 默认为0.05, 根据经验, 建议选择[0.01,1]范围内.
# 使用的线程数thread: 默认为:cpu数-1, 一般建议和你的cpu核数相同.
def fasttext_tuning_demo():
    # 1. 准备语料库 ./data/fil9
    path = './data/fil9'
    # 2. 使用无监督训练api ,训练模型
    # TODO:对模型进行调参
    model = fasttext.train_unsupervised(path, "cbow", dim=300, epoch=1, lr=0.1, thread=8)
    # 3. 验证模型的效果, 查看模型某个单词的向量
    vector = model.get_word_vector('apple')
    print(f'单词:apple, 对应的向量:{vector}')
    # 4. 模型的近邻单词的表现
    sports_neighbor = model.get_nearest_neighbors('sports')
    music_neighbor = model.get_nearest_neighbors('music')
    print(f'sports_neighbor :{sports_neighbor}')
    print(f'music_neighbor :{music_neighbor}')

    # 5. 保存模型
    model.save_model('./data/fil9.bin.tuning')


if __name__ == '__main__':
    # fasttext_demo()
    fasttext_tuning_demo()

词嵌入word embedding

词嵌入(Word Embedding)是自然语言处理(NLP)中的核心技术,旨在将离散的词语映射为低维稠密的连续向量,从而捕捉词语之间的语义和语法关系。

  1. ​定义​
    词嵌入通过将词汇表中的单词或短语转换为固定长度的实数向量,使得语义相近的词在向量空间中距离更近。例如,“猫”和“狗”的向量相似度高于“猫”和“汽车”

  2. ​核心思想​

    • ​分布式假设​​:上下文相似的词具有相似含义。模型通过大量文本数据学习词的共现关系,生成向量表示
    • ​降维与稠密性​​:相比高维稀疏的One-Hot编码(如10000维),词嵌入通常使用50-300维的稠密向量,提升计算效率并保留语义信息
  • 广义的word embedding包括所有密集词汇向量的表示方法,如之前学习的word2vec, 即可认为是word embedding的一种.
  • 狭义的word embedding是指在神经网络中加入的embedding层, 对整个网络进行训练的同时产生的embedding矩阵(embedding层的参数), 这个embedding矩阵就是训练过程中所有输入词汇的向量表示组成的矩阵.

文本数据分析

  • 文本数据分析的作用:

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

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

数据集说明

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

  • 中文酒店评论语料:

    • 属于二分类的中文情感分析语料, 该语料存放在"./cn_data"目录下.
    • 其中train.tsv代表训练集, dev.tsv代表验证集, 二者数据样式相同.
  • train.tsv数据样式:

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

import torch
from tensorflow.keras.preprocessing.text import Tokenizer
from torch.utils.tensorboard import SummaryWriter
import jieba
import torch.nn as nn

# ---------------------这一部分是为了解决SummaryWriter报错问题--------------------- #

# 注意:
# fs = tf.io.gfile.get_filesystem(save_path)
# AttributeError: module 'tensorflow._api.v2.io.gfile' has no attribute 'get_filesystem'
# 错误原因分析:
#  1 from tensorboard.compat import tf 使用了tf 如果安装tensorflow,默认会调用它tf的api函数
import tensorflow as tf
import tensorboard as tb

# tf.io.gfile = tb.compat.tensorflow_stub.io.gfile
import os
import tensorboard.compat.tensorflow_stub.io.gfile as gfile

gfile.join = os.path.join

# ---------------------这一部分是为了解决SummaryWriter报错问题--------------------- #


"""
需求:使用nn.Embedding层构建词嵌入层,并对词向量可视化分析
1 对句子分词 word_list
2 对句子word2id求my_token_list,对句子文本数值化sentence2id
3 创建nn.Embedding层,查看每个token的词向量数据
4 创建SummaryWriter对象, 可视化词向量
  词向量矩阵embd.weight.data 和 词向量单词列表my_token_list添加到SummaryWriter对象中
   summarywriter.add_embedding(embd.weight.data, my_token_list)
 5 通过tensorboard观察词向量相似性
 6 也可通过程序,从nn.Embedding层中根据idx拿词向量
"""


def word_embedding_demo():
    # 1 对句子分词 word_list
    sentence1 = '传智教育是一家上市公司,旗下有黑马程序员品牌。我是在黑马这里学习人工智能'
    sentence2 = "我爱自然语言处理"
    # 把两个句子放在一个列表里面,方便后续分词
    sentences = [sentence1, sentence2]
    word_list = []
    # 循环遍历两个句子,并分词。
    for sentence in sentences:
        # TODO:把分词后的结果放到word_list中,word_list包含所有的单词
        word_list.append(jieba.lcut(sentence))
    print(f'word_list: {word_list}')
    # 2 对句子word2id求my_token_list,对句子文本数值化sentence2id
    tokenizer = Tokenizer()
    # TODO: 对句子中所有出现过的单词进行拟合
    tokenizer.fit_on_texts(word_list)

    # TODO : 获取词表大小
    # my_token_list里面包含所有的不重复单词
    my_token_list = tokenizer.index_word.values()
    nums_embedding = len(my_token_list)
    print(f'my_token_list: {my_token_list}')
    print(f'nums_embedding: {nums_embedding}')

    # TODO: 把句子中所有的单词转换成索引 ['黑马'] -> [1]
    sentence2id = tokenizer.texts_to_sequences(word_list)
    print(f'sentence2id: {sentence2id}')

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

    # 3 创建nn.Embedding层,查看每个token的词向量数据
    # TODO:完成模型的定义,以及内部神经网络参数的初始化
    embd = nn.Embedding(num_embeddings=nums_embedding, embedding_dim=8)

    # 4 创建SummaryWriter对象, 可视化词向量 . (这里不需要记忆,实现的时候复制即可)
    # SummaryWriter中logdir参数可以指定日志存放的目录
    summary_writer = SummaryWriter()
    # add_embedding 是专门针对词嵌入场景写日志的api,需要两个参数:
    # 参数1:embedding层中的网络参数。 参数2: 词表(包含所有去重单词的列表)
    # 为了方便演示,节省时间,这里直接把模型初始化的参数放进来了
    summary_writer.add_embedding(embd.weight.data, my_token_list)
    summary_writer.close()

    #  5 通过tensorboard观察词向量相似性
    # 在命令行执行: tensorboard --logdir=runs --host=0.0.0.0
    # 需要注意:执行命令时所在的目录

    #  6 也可通过程序,从nn.Embedding层中根据idx拿词向量
    #  构造index, 0 ~ 19
    for index in range(nums_embedding):
        # 6.1 把索引转化成张量
        input = torch.tensor(index)
        # 6.2 TODO: 输入embd,进行前向传播
        word_vector = embd(input)
        # 6.3 打印结果
        print(f'单词:{tokenizer.index_word[index + 1]} ,索引:{index}, 词向量:{word_vector.detach().numpy()} ')


if __name__ == '__main__':
    word_embedding_demo()

文本特征处理

概念:文本特征处理就是给文本增加特征,类似机器学习中的特征工程,起作用是让模型训练效果更好

常见方法:添加n-gram特征,文本长度规范

n-gram特征

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

代码实现,案例:

现有分词映射列表:[1, 3, 2, 1, 5, 3]

添加2-gram,以及3-gram特征

"""
需求:实现n-gram特征, n可以等于任何数字
思路步骤:
1. 对序列进行切片, 2-gram特征切1次 , 3-gram特征切2次   list[0:] , list[1:] , list[2:]
2. 对列表中的元素从0到len() -1 以此进行遍历, 和切片中对应位置的元素进行组合 (1,3), (3,2) ...
3. 通过set集合进行去重
"""

n = 3


def n_gram(word_list):
    # 1. 对序列进行切片, 2-gram特征切1次    list[0:] , list[1:]
    n_gram_list = []
    # [0,1]
    for index in range(n):
        # 对word_list进行切片,并添加到n_gram_list中。 [ [原始列表],[去掉第一个元素的列表] ... ]
        n_gram_list.append(word_list[index:])

    # 2. 对列表中的元素从0到len() -1 以此进行遍历, 和切片中对应位置的元素进行组合 (1,3), (3,2) ...
    # z = zip(n_gram_list)
    # print(list(z))

    # 使用*对n_gram_list进行拆包
    # print(f'n_gram_list:\n{n_gram_list}')
    # print(f'*n_gram_list:')
    # print(*n_gram_list)

    # 3. 通过set集合进行去重

    # set是无序:对于数字int等它是有序的,其他如str/对象类的它会取hash(并不是完全随机,它的随机有一些规则)
    return set(zip(*n_gram_list))


def zip_demo():
    # zip函数的特点: 一一对应组成元组,如果长度不一致,舍弃匹配不上的
    list1 = [1, 3, 2, 1, 5, 3]
    list2 = [3, 2, 1, 5, 3]

    zipped = zip(list1, list2)

    for item in zipped:
        print(item)


def n_gram_simple(word_list):
    # [word_list[i:] for i in range(n)]
    # 等价于 -----------------------------------------
    #  n_gram_list = []
    #     # [0,1]
    #     for index in range(n):
    #         # 对word_list进行切片,并添加到n_gram_list中。 [ [原始列表],[去掉第一个元素的列表] ... ]
    #         n_gram_list.append(word_list[index:])
    #  ----------------------------------------- ------------------------------------
    return set(zip(*[word_list[i:] for i in range(n)]))


if __name__ == '__main__':
    # zip_demo()
    word_list = [1, 3, 2, 1, 5, 3]

    gram_result = n_gram(word_list)
    gram_simple_result = n_gram_simple(word_list)

    print(f'gram_result:{gram_result}')
    print(f'gram_simple_result:{gram_simple_result}')

运行结果如图 

注意1:*list列表可以对列表进行拆包,如[[],[]]会拆成[][]

注意2:zip(a,b)会将列表a,b中的值一一对应拼接,多余的值忽略掉

文本数据增强

        回译数据增强法:大学生论文降重法

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

  • 回译数据增强优势:

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

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

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


网站公告

今日签到

点亮在社区的每一天
去签到