当前位置: 首页 > news >正文

自然语言处理——02 文本预处理(上)

1 认识文本预处理

  • 概念:

    • 文本语料在输送给模型前一般需要一系列的预处理工作,才能符合模型输入的要求;
    • 比如:将文本转化成模型需要的张量、规范张量的尺寸;
    • 比如:
      • 关于数据X:数据有没有脏数据、数据长度分布情况等;
      • 关于标签Y:分类问题查看标签是否均匀;
  • 作用:

    • 指导模型超参数的选择 、提升模型的评估指标;
    • 大白话:文本预处理的工作,就是准备出模型需要的x、y,然后送给模型;
  • 主要环节:

    1. 文本处理的基本方法(先拆分、标注文本)

      • 分词:把长句子切成词语(比如“我喜欢自然语言处理”→“我/喜欢/自然语言/处理”);
      • 词性标注:给词语贴标签(动词、名词等,比如“喜欢”是动词);
      • 命名实体识别:找出人名、地名、机构名(比如“北京有个清华大学”→识别出“北京”是地名,“清华大学”是机构名);
    2. 文本张量表示方法(把文本转成模型能计算的数字)

      • one-hot编码:用0和1表示词语,简单但容易“词多爆内存”;
      • Word2vec/Word Embedding:让意思相近的词数字更像(比如“猫”和“狗”的向量比“猫”和“桌子”更接近),能抓语义关系;
    3. 文本语料的数据分析(检查数据质量、找规律)

      • 统计标签数量、句子长度,画出词云(比如发现“垃圾邮件”标签太多/太少,或者句子太长模型难处理),帮你判断数据合不合理,需不需要调整;
    4. 文本特征处理(给模型加“额外信息”)

      • 添加n-gram特征:不只看单个词,还看词语搭配(比如“机器学习”一起出现,比单独“机器”+“学习”信息更多);
      • 规范文本长度:把句子统一成差不多长度(太短补一补,太长砍一砍),方便模型处理;
    5. 数据增强方法(数据不够?“造”点新数据)

      • 回忆数据增强法(比如同义替换、回译):没太多数据时,把句子换种说法(“我很开心”→“我非常高兴”),让模型见更多样的表达,避免学偏。

2 文本处理的基本方法

2.1 分词

2.1.1 概述

  • 分词:将连续的字序列按照一定的规范重新组合成词序列的过程;

  • 作用:

    • 词作为语言语义理解的最小单元,是人类理解文本语言的基础;
    • 是AI解决NLP领域高阶任务,如自动问答、机器翻译、文本生成的重要基础环节;
  • 英文是不需要分词的,因为英文中的空格是天然的分解符,而中文没有明显的分解符。

  • 例:

    腾讯是一家上市公司,旗下有微信、QQ等产品,我们平时主要通过微信联系。
    腾讯/是/一家/上市公司/,/旗下/有/微信/、/QQ/等/产品/,/我们/平时/主要/通过/微信/联系/。
    

2.1.2 jieba分词器

  • jieba——目前流行的中文分词工具

    import jieba
    
    • 支持三种分词模式(分词粒度):

      • 精确模式:默认分词模式,试图将文本精确切分,减少冗余和歧义,适用于文本分析、文本挖掘等需要精准词语划分的任务,调用方法为jieba.cut(text, cut_all=False)

        cut_all=False:关闭全模式,开启精确模式;

      • 全模式:会扫描出句子中所有可能成词的词语,分词速度快,但无法解决分词歧义问题,适用于需要尽可能多地提取词语,对准确性要求不高的场景 ,调用方法为jieba.cut(text, cut_all=True)

      • 搜索引擎模式:在精确模式基础上,对长词再次进行切分,增加分词的粒度,提高召回率,适合用于搜索引擎构建索引、处理用户查询等场景,调用方法为jieba.cut_for_search(text)

    • 支持中文繁体分词,支持用户自定义词典;

  • jieba.cut VS jieba.lcut

    • jieba.cut
      • 返回的是一个生成器对象。生成器是一种特殊的迭代器,它并不会一次性将所有分词结果加载到内存中,而是在迭代过程中按需生成。这样在处理大量文本时,能显著减少内存占用,提升程序运行效率;
      • 适合处理文本量非常大的情况,比如处理大规模的文本语料库、流式读取文件中的文本并进行分词等,通过迭代方式逐个获取分词结果,能有效控制内存使用;
    • jieba.lcut
      • 返回的是一个列表,即一次性将所有分词结果以列表形式存储在内存中。在处理小量文本时,使用列表便于直接进行后续操作,如统计词频、筛选特定词语等;但处理大量文本时,若内存不足,可能导致程序崩溃;
      • 适用于文本量较小,需要立即对所有分词结果进行统一操作的场景,如对一篇短文章进行分词后,马上统计词频、进行词性标注等操作,因为可以直接通过索引等方式访问列表中的元素;
  • 用户自定义词典时,遵循以下格式:

    词语  词频  词性
    
    • 词语:希望 jieba 优先识别的自定义词汇(比如专业术语、新造词等)
    • 词频:数字表示 “建议的分词优先级”(数值越小,越优先被识别),主要用于调整分词权重
    • 词性:可选的词性标注(如 n 名词、nz 其他专名),jieba 支持自定义词性,也可忽略(但格式上需保留空格占位)
  • jieba词性对照表

    a 形容词ad 副词ag 形容词性语素an 名形词
    b 区别词
    c 连词
    d 副词dfdg 副语素
    e 叹词
    f 方位词
    g 语素
    h 前接成分
    i 成语
    j 简称略称
    k 后接成分
    l 习用语
    m 数词mgmq 数量词
    n 名词ng 名词性语素nr 人名nrfgnrtns 地名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
    

2.1.3 例

  • 例:三种分词模式

    content = "腾讯是一家上市公司,旗下有微信、QQ等产品,我们平时主要通过微信联系。"
    
    # 精确模式
    myobj1 = jieba.cut(sentence=content, cut_all= False)
    print('myobj1-->', myobj1)
    mydata1 = jieba.lcut(sentence=content, cut_all=False)
    print('mydata1-->', mydata1)
    # 全模式
    myobj2 = jieba.cut(sentence=content, cut_all=True)
    print('myobj2-->', myobj2)
    mydata2 = jieba.lcut(sentence=content, cut_all=True)
    print('mydata2-->', mydata2)
    # 搜索引擎模式
    myobj3 = jieba.cut_for_search(sentence=content)
    print('myobj3-->', myobj3)
    mydata3 = jieba.lcut_for_search(sentence=content)
    print('mydata3-->', mydata3)
    

    在这里插入图片描述

  • 例:支持繁体分词

    # 支持繁体分词
    content = "煩惱即是菩提,我暫且不提"
    mydata = jieba.lcut(content)
    print('mydata-->', mydata)
    

    在这里插入图片描述

  • 例:支持用户自定义词典

    # 支持用户自定义词典
    # 不使用用户字典
    content = "腾讯是一家上市公司,旗下有王者荣耀、和平精英等游戏,但还是要少玩游戏"
    mydata1 = jieba.lcut(sentence=content, cut_all=False)
    print('mydata1-->', mydata1)# 使用用户字典
    """
    上市
    王者荣耀 1 n
    和平精英 2 n
    """
    jieba.load_userdict('data/userdict.txt')
    mydata2 = jieba.lcut(sentence=content, cut_all=False)
    print('mydata2-->', mydata2)
    

    在这里插入图片描述

2.2 命名实体识别

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

  • 命名实体识别(Named Entity Recognition,简称NER),识别出一段文本中可能存在的命名实体;

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

  • 例:

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

2.3 词性标注

  • 词性:语言中对词的一种分类方法,以语法特征为主要依据、兼顾词汇意义对词进行划分的结果;

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

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

  • 例:

    我爱自然语言处理
    我/rr,爱/v,自然语言/n,处理/vnrr:人称代词
    v:动词
    n:名词
    vn:动名词
    
  • 例:

    # 词性标注
    import jieba.posseg as pseg
    mydata1 = pseg.lcut("我爱北京天安门")
    print('mydata1-->', mydata1)
    

    在这里插入图片描述

3 文本张量的表示方式

3.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]]
    
  • NLP中文本词向量表示的常用方法:

    • One-Hot编码
    • Word2vec
    • Word Embedding

3.2 One-Hot编码

  • One-Hot编码(One-Hot Encoding),也叫稀疏词向量表示

    • One-Hot编码是将分类变量转换为数字格式的常用方法,通常用于AI任务中处理分类标签y数据
    • 在One-Hot编码中,对于一个具有n个不同类别的分类变量,将其表示为一个n维的向量。其中只有一个维度的值为1(代表该样本属于这个类别),其他维度的值均为0;
  • 例:

    ["红色""绿色""蓝色"]
    [[1, 0, 0],
    [0, 1, 0],
    [0, 0, 1]]["人生", "该", "如何", "起头"]
    [[1, 0, 0, 0], 
    [0, 1, 0, 0], 
    [0, 0, 1, 0], 
    [0, 0, 0, 1]]
    
  • 例:One-Hot编码的生成

    import jieba
    from tensorflow.keras.preprocessing.text import Tokenizer
    import joblib
    

    pip install tensorflow

    # One-Hot编码的生成
    # 定义词汇表
    vocabs = ["周杰伦", "陈奕迅", "王力宏", "李宗盛", "吴亦凡", "鹿晗"]# 创建Tokenizer对象,用于文本处理和编码转换
    # Tokenizer是Keras中用于文本预处理的工具,能将文本转换为整数序列或one-hot编码
    mytokenizer = Tokenizer()
    print('mytokenizer-->', mytokenizer)# 使用词汇表训练Tokenizer,构建词汇索引
    # fit_on_texts()方法会遍历输入的文本列表,统计词频并生成词汇表
    mytokenizer.fit_on_texts(vocabs)
    # 打印index_word属性:键是整数索引,值是对应的词语(索引从1开始)
    print('mytokenizer.index_word-->', mytokenizer.index_word)
    # 打印word_index属性:键是词语,值是对应的整数索引(与index_word互为反向映射)
    print('mytokenizer.word_index-->', mytokenizer.word_index)# 遍历词汇表中的每个词语,手动生成One-Hot编码
    for vorcab in vocabs:# 创建一个全为0的列表,长度等于词汇表大小(即6个元素)zero_list = [0] * len(mytokenizer.index_word)# 获取当前词语在word_index中的索引,减1是为了对应列表的0开始索引idx = mytokenizer.word_index[vorcab] - 1# 将对应位置设为1,形成One-Hot编码(只有一个位置为1,其余为0)print(vorcab, '的Ont-Hot编码是:', zero_list)# 使用joblib保存训练好的Tokenizer对象到指定路径
    # 保存后可在其他地方通过joblib.load()加载复用,避免重复训练
    joblib.dump(value=mytokenizer, filename='data/mytokenizer' )
    print('保存mytokenizer END')
    

    在这里插入图片描述

  • 例:One-Hot编码的使用

    mytokenizer = joblib.load('data/mytokenizer')
    # 定义要进行One-Hot编码的目标词语
    token1 = "李宗盛"
    # 创建一个全为0的列表,长度与词汇表(vocabs)的元素数量一致
    zero_list1 = [0] * len(vocabs)
    # 检查词汇是否在Tokenizer的词汇表中
    if token1 in mytokenizer.word_index:  # 通过加载好的Tokenizer,获取目标词语对应的索引,再减1转换为列表的0起始下标# mytokenizer.word_index 是一个字典,键是词语,值是该词语在Tokenizer中的索引(从1开始)idx1 = mytokenizer.word_index[token1] - 1# 将对应下标的位置置为1,完成One-Hot编码(只有对应位置为1,其余为0)zero_list1[idx1] = 1print(token1, '的One-Hot编码是:', zero_list1)
    else:print(f"{token1}不在词汇表中")token2 = "狗蛋儿"
    zero_list2 = [0] * len(vocabs)
    if token2 in mytokenizer.word_index:  idx2 = mytokenizer.word_index[token2] - 1zero_list2[idx2] = 1print(token2, '的One-Hot编码是:', zero_list2)
    else:print(f"{token2}不在词汇表中")
    

    在这里插入图片描述

  • 优点:操作简单,容易理解;

  • 缺点:完全割裂了词与词之间的联系;如果在大语料集下,每个向量的长度过大,会占据大量内存;属于稀疏词向量表示;

  • 正因为One-Hot编码隔离了词和词的联系,又易浪费内存空间,所以出现了稠密向量的表示方法

    • Word2vec
    • Word Embedding

3.3 Word2vec模型

3.3.1 概述

  • Word2vec模型是一种将单词转换为词向量的自然语言处理技术;

    • 是利用深度学习网络挖掘单词间语义关系,用网络里的权重参数表示词向量(比如“苹果”和“水果”的向量,在语义空间里距离近);
    • 是在无监督的语料(互联网大量文本,没人手动标标签)上构建了一个有监督的任务(预测单词这种带目标的事情),底成本利用海量数据;
  • Word2Vec有两种训练词向量方式:

    • **CBOW(Continuous Bag of Words)**方式训练词向量
      • 试图根据上下文中的周围单词来预测当前单词,即用周围词预测中间词
      • 它将周围单词的词向量求和或取平均作为上下文的表示,然后通过一个神经网络进行预测
    • Skip-Gram方式训练词向量
      • 试图根据当前单词来预测上下文中的周围单词,即用中间词预测周围词
      • 它将当前单词的词向量作为输入,然后通过一个神经网络来预测周围单词

3.3.2 CBOW方式

  • 已知数据:有5个字母构成的文本序列“abcdeaaeddccbadae …”,其中a、b、c、d、e的One-Hot表示为见下表

    字母One-Hot表示
    a1 0 0 0 0
    b0 1 0 0 0
    c0 0 1 0 0
    d0 0 0 1 0
    e0 0 0 0 1
  • 需求

    • 构建神经网络,输入层数据要求5个特征,隐藏层有3个神经元,输出层5个神经元;
    • 使用已知数据训练这个神经网络;
    • 用隐藏层的权重参数充当 a、b、c、d、 e 这5个单词的词向量;
  • 需求分析

    • 两个问题:

      • 已知文本序列,如何构建神经网络,来探索 a、b、c、d、 e 这5个单词之间的语义关系?
      • a、b、c、d、 e 这5个单词之间的语义关系,又如何保存到神经网络中?
    • 思路:

      在这里插入图片描述

      • 数据流:输入数据5个特征,经过隐藏层变成3个特征,经过输出层变成5个特征;
      • 数据形状:m*5 >> m*3 >> m*5(m是样本数量),即降维又升维;
      • 隐藏层参数矩阵w为:5*3(5是输入维度,3是隐藏层维度)、输出层参数矩阵w':3*5(3是隐藏层维度,5是输出维度);
      • 训练过程:数据经过前向传播得到预测值ŷ,预测值ŷ与真实值y比较得到损失,通过反向传播可以更新权重矩阵ww'参数;
  • CBOW 核心是用周围单词预测中间单词,过程如下:

    • 构建样本
      • 引入滑动窗口(此处规定滑动窗口大小为3)切分文本序列,构建样本。比如:
        • 样本1:x(a, c),y (b)。中间词是 b ,周围词就是 a 和 c
        • 样本2:x(b, d),y ©。中间词是 c ,周围词就是 b 和 d
        • ……
      • 将x中的两个字母的One-Hot编码拼在一起(或求和平均)当作输入,将y的One-Hot编码当作真实值;
    • 神经网络前向传播(降维+升维)
      • 降维(参数矩阵w):
        • 输入 x(a 和 c 的One-Hot编码拼在一起或者通过求和平均后得到的值)维度是 5 ,通过参数矩阵 w(5*3维度,5是输入维度,3是隐藏层维度) ,把 5 维 “拍扁” 成 3 维隐藏层输出;
        • 这一步叫 “降维”,把高维、语义孤立的One-Hot,转成低维、带语义关联的向量(隐藏层输出就是 “词向量雏形”);
      • 升维(参数矩阵w'):
        • 隐藏层 3 维输出,再通过参数矩阵 w’(3*5,3是隐藏层维度,5是输出维度) ,升回 5 维,得到预测值ŷ
        • 这一步是 “升维”,让模型能输出和真实值同维度的预测结果,方便计算误差;
    • 计算损失(Loss):拿预测值ŷ(模型猜的b^)和真实值y(实际的b)比,用损失函数算差距。差距越大,Loss 越高,模型越 “差”;
    • 反向传播(更新ww':根据 Loss 反向调整参数矩阵 ww' 的数值,让下次预测更准;
  • 训练结束后,参数矩阵 w 就存着单词的词向量

    • 此处 w 是5*3维度(5是输入维度,3是隐藏层维度),每一列对应一个单词的词向量;

    • 比如对于字母 a 的词向量:

      • 因为 a 的One-Hot是 [1,0,0,0,0],所以w 的 “第 0 列”。假设w矩阵长这样

        [w11, w12, w13]
        [w21, w22, w23]
        [w31, w32, w33]
        [w41, w42, w43]
        [w51, w52, w53]
        
      • 那么 a 的词向量是 [w11, w21, w31, w41, w51]

    • 这样,原本孤立的One-Hot,就通过训练,在 w 里变成了“语义相关”的低维向量。

3.3.3 Skip-Gram方式

  • CBOW 核心是用中间单词预测周围单词,过程如下:

    • 构建样本

      • 引入滑动窗口(此处规定滑动窗口大小为3)切分文本序列,构建样本。比如:
        • 样本1:x(b),y (a, c)。中间词是 b ,周围词就是 a 和 c
        • 样本2:x(c),y (b, d)。中间词是 c ,周围词就是 b 和 d
        • ……
      • 将x中的字母的One-Hot编码当作输入,将y的One-Hot编码当作真实值;
    • 神经网络前向传播(降维+升维)

      • 降维(参数矩阵w):
        • 输入 x(b 的 One-hot)维度是 5 ,通过参数矩阵 w(5*3维度,5是输入维度,3是隐藏层维度) ,把 5 维 “拍扁” 成 3 维隐藏层输出;
        • 这一步提取 b 的“语义特征”;
      • 升维(参数矩阵w'):
        • 隐藏层 3 维输出,再通过参数矩阵 w’(3*5,3是隐藏层维度,5是输出维度) ,升回 5 维,得到预测值ŷ
        • 这一步让模型能输出和真实值同维度的结果,方便算误差;
    • 计算损失(Loss):拿预测值ŷ(模型猜的a^和c^)和真实值y(实际的a和c)比,用损失函数算差距。差距越大,Loss 越高,模型越 “差”;

    • 反向传播(更新ww':根据 Loss 反向调整参数矩阵 ww' 的数值,让下次预测更准;

  • 训练结束后,参数矩阵 w 就存着单词的词向量

    • 此处 w 是5*3维度(5是输入维度,3是隐藏层维度),每一行对应一个单词的词向量;

    • 比如对于字母 b 的词向量:

      • 因为 b 的One-Hot是 [0,1,0,0,0],所以w 的 “第 1 行”。假设w矩阵长这样

        [w11, w12, w13]
        [w21, w22, w23]
        [w31, w32, w33]
        [w41, w42, w43]
        [w51, w52, w53]
        
      • 那么 b 的词向量是 [w21, w22, w23]

    • 这样,原本孤立的One-Hot,就通过训练,在 w 里变成了“语义相关”的低维向量。

3.3.4 Word2vec模型的训练和使用

3.3.4.1 概述
  • FastText 工具包

    • 背景:Facebook(现 Meta)开源的 NLP 工具;

    • 功能:文本分类、训练词向量;

  • Tomas Mikolov 是 Word2Vec 作者,后来又搞了 FastText ,相当于**“Word2Vec 升级版/拓展版”**:

    • Word2Vec 主要聚焦“单词级”词向量训练;

    • FastText 加入“字符级”信息(比如把“apple”拆成“app”“ppl”“ple” ),对小语种、生僻词更适配,功能也更丰富(文本分类 + 词向量)。

  • 不管用 Word2Vec 还是 FastText ,训练词向量都绕不开这些步骤:

    • 获取训练数据
    • 词向量的训练、保存、加载、查看
    • 模型效果检验
    • 模型超参数设定
3.3.4.2 获取训练数据
  • 数据来源:http://mattmahoney.net/dc/enwik9.zip,这是英语维基百科的部分网页信息,大小在300M左右(解压后1个G);

  • 原始数据中包含 XML/HTML 格式的内容,这些内容并不是我们需要的,所以接下来对原始数据做一些处理;

  • 编写wikifil.py脚本,用于清洗enwik9文件:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-"""
    Python版Wikipedia XML清洗脚本功能与原Perl脚本(wikifil.pl)完全相同:
    1. 只保留<text>...</text>之间的内容
    2. 移除#REDIRECT页面
    3. 清除所有XML/HTML标签
    4. 转换URL编码字符
    5. 移除参考文献、外部链接、图片标记等
    6. 保留图像说明文字
    7. 将链接转换为普通文本
    8. 将数字拼写出来(如1→one)
    9. 最终只保留小写字母和空格(无连续空格)
    """import re
    import sysdef clean_wiki_text():text_mode = Falsewith open("enwik9", "r", encoding="utf-8") as f:for line in f:# 检测是否进入<text>标签if "<text " in line:text_mode = True# 忽略#REDIRECT页面if "#redirect" in line.lower():text_mode = Falseif text_mode:# 检测是否离开<text>标签if "</text>" in line:text_mode = Falsecontinue# 移除XML标签line = re.sub(r'<.*?>', '', line)# 解码URL编码字符line = line.replace('&amp;', '&')line = line.replace('&lt;', '<')line = line.replace('&gt;', '>')# 移除参考文献 <ref...>...</ref>line = re.sub(r'<ref[^<]*<\/ref>', '', line)# 移除XHTML标签line = re.sub(r'<[^>]*>', '', line)# 处理URL链接,保留可见文本line = re.sub(r'\[http:[^] ]*', '[', line)# 移除图片链接标记,保留说明文字line = re.sub(r'\|thumb', '', line, flags=re.IGNORECASE)line = re.sub(r'\|left', '', line, flags=re.IGNORECASE)line = re.sub(r'\|right', '', line, flags=re.IGNORECASE)line = re.sub(r'\|\d+px', '', line, flags=re.IGNORECASE)line = re.sub(r'\[\[image:[^\[\]]*\|', '', line, flags=re.IGNORECASE)# 简化分类标记line = re.sub(r'\[\[category:([^|\]]*)[^]]*\]\]', '[[\\1]]', line, flags=re.IGNORECASE)# 移除其他语言链接line = re.sub(r'\[\[[a-z\-]*:[^\]]*\]\]', '', line, flags=re.IGNORECASE)# 移除wiki URL,保留可见文本line = re.sub(r'\[\[[^\|\]]*\|', '[[', line)# 移除{{icons}}和{tables}line = re.sub(r'\{\{[^\}]*\}\}', '', line)line = re.sub(r'\{[^\}]*\}', '', line)# 移除方括号line = line.replace('[', '').replace(']', '')# 移除其他URL编码字符line = re.sub(r'&[^;]*;', ' ', line)# 转换为小写line = line.lower()# 将数字拼写出来line = line.replace('0', ' zero ')line = line.replace('1', ' one ')line = line.replace('2', ' two ')line = line.replace('3', ' three ')line = line.replace('4', ' four ')line = line.replace('5', ' five ')line = line.replace('6', ' six ')line = line.replace('7', ' seven ')line = line.replace('8', ' eight ')line = line.replace('9', ' nine ')# 移除非字母字符,合并连续空格line = re.sub(r'[^a-z]', ' ', line)line = re.sub(r' +', ' ', line).strip()if line:print(line)if __name__ == "__main__":clean_wiki_text()
    
  • 将下面这两个文件放在同一个目录下:

    在这里插入图片描述

  • 打开 CMD 命令行,执行:

    python wikifil.py > fil9
    
  • 可以查看生成的fil9文件中的前 20 行内容:

    Get-Content fil9 -Head 20
    

    在这里插入图片描述

3.3.4.3 词向量的训练、保存、加载、查看
  • 安装 fasttext:安装的方式具体还是见GitHub - facebookresearch/fastText: Library for fast text representation and classification.;

    • 可能涉及到C++17的编译、由于Python版本过高不支持安装等问题,下面只给出示例代码;
    pip install fasttext
    
  • 训练、保存、加载

    def fasttext_train_save_load():# 训练词向量mymodel = fasttext.train_unsupervised('data/fil9', epoch=1)# 保存词向量mymodel.save_model("data/mymodel.bin")# 加载词向量mymodel = fasttext.load_model("data/mymodel.bin")
    
  • 查看

    # 查看词向量
    def fasttext_get_word_vector():# 加载已经训练好的词向量模型mymodel = fasttext.load_model("data/mymodel.bin")# 查看词向量themyvector = mymodel.get_word_vector('the')print('myvector--->', type(myvector), myvector.shape, myvector)
    
3.3.4.4 模型效果检验
  • 检查单词向量质量的一种简单方法就是查看其邻近单词,然后主观来判断这些邻近单词是否与目标单词相关,进而来粗略评定模型效果的好坏;

  • 查看临近词:

    # 查看临近词
    def fasttext_get_nearest_neighbors():# 加载已经训练好的词向量模型mymodel = fasttext.load_model("data/mymodel.bin")# 查看词向量dog的临近词result = mymodel.get_nearest_neighbors('dog')print('result--->', result)
    
3.3.4.5 模型超参数设定
# 模型参数设定
def fasttext_parm():''' unsupervised_default = {'model': "skipgram",    # 1 选择词向量的训练方式'lr': 0.05,             # 2 学习率'dim': 100,             # 3 词向量特征数'ws': 5,'epoch': 5,             # 4 训练轮次'minCount': 5,'minCountLabel': 0,'minn': 3,'maxn': 6,'neg': 5,'wordNgrams': 1,'loss': "ns",'bucket': 2000000,'thread': multiprocessing.cpu_count() - 1,  # 5 线程数'lrUpdateRate': 100,'t': 1e-4,'label': "__label__",'verbose': 2,'pretrainedVectors': "",'seed': 0,'autotuneValidationFile': "",'autotuneMetric': "f1",'autotunePredictions': 1,'autotuneDuration': 60 * 5,  # 5 minutes'autotuneModelSize': ""}'''mymodel = fasttext.train_unsupervised('./data/fil9', epoch=1, model='cbow', lr=0.1, dim=300, thread=8)

3.3.5 CBOW VS Skip-Gram

  • 原理:CBOW用周围单词预测当前单词;Skip - Gram凭当前单词预测周围单;
  • 计算效率:CBOW因对多个上下文单词向量求和平均,计算高效;Skip - Gram要为每个单词生成上下文,训练速度慢、效率低;
  • 数据需求:CBOW需更多训练数据汇总整体信息;Skip - Gram在大规模数据中处理低频词更优,能生成丰富上下文信息;
  • 适用场景:CBOW适合训练数据大、高频词情况;Skip - Gram对低频词、复杂语义关系场景表现好,像大规模数据集中处理低频词。

3.4 Word Embedding

  • Word Embedding(词嵌入),通过一定的方式将词汇映射到指定维度(一般是更高维度)的空间;

    • 广义:只要是将单词用向量来表示的方法,都算(比如 Word2Vec、GloVe 这些),不管用不用深度学习;
    • 狭义:在深度神经网络里,专门加一个 “嵌入层”(比如 PyTorch 的nn.Embedding),用网络训练出向量;
  • Word2Vec方式产生词向量和Word Embedding(nn. Embedding)方式有何异同?

    • 相同点:都是将单词用向量来表示,让计算机能处理文本;
    • 不同点
      • Word2Vec产生词向量后,某一个词向量比如单词“the”的词向量就固定下来了,是静态的
      • nn.Embedding层产生词向量后,词嵌入层作为整体神经网络的一部分,权重参数会参与更新,是动态的
      • Word2Vec使用起来一般需要两步:输入单词"the"拿到词向量 >> 再送给神经网络进行使用;
      • nn.Embedding层使用起来只有一步:直接嵌入到神经网络中。

4 使用tenserboard可视化嵌入的词向量

  • 需求:

    • 有下面两句话

      腾讯是一家上市公司,旗下有王者荣耀、和平精英等游戏,但还是要少玩游戏
      我爱自然语言处理
      
    • 对这两句话分词,并完成文本数值化、数值张量化

    • 然后对词向量进行可视化

import torch
from tensorflow.keras.preprocessing.text import Tokenizer
from torch.utils.tensorboard import SummaryWriter
import jieba
import torch.nn as nn
import tensorflow as tf
import tensorboard as tb
tf.io.gfile = tb.compat.tensorflow_stub.io.gfile
# 1 对句子分词,构建词列表word_list
# 定义两个示例句子
sentence1 = '腾讯是一家上市公司,旗下有王者荣耀、和平精英等游戏,但还是要少玩游戏'
sentence2 = '我爱自然语言处理'
sentences = [sentence1, sentence2]
word_list = []
# 用jieba对每个句子分词,结果存入word_list
for s in sentences:word_list.append(jieba.lcut(s))
print('word_list--->', word_list)
# 2 对句子分词列表word_list做词表构建,得到每个词的索引映射
mytokenizer = Tokenizer()
mytokenizer.fit_on_texts(word_list)
print('mytokenizer.index_word--->', mytokenizer.index_word)
print('mytokenizer.word_index--->', mytokenizer.word_index)
my_token_list = list(mytokenizer.index_word.values())  # 获取词列表,用于后续可视化
print('my_token_list--->', my_token_list)
# 3 创建nn.Embedding层,实现词嵌入
# num_embeddings是词表大小(不同词的数量),embedding_dim是词向量维度
embed = nn.Embedding(num_embeddings=len(mytokenizer.index_word), embedding_dim=8)
print('词嵌入层embed--->', embed)
# 设置打印精度,方便查看张量值
torch.set_printoptions(precision=4, sci_mode=False)
print('词嵌入层的矩阵参数(每个单词的词向量)embed--->', embed.weight.data)
# 4 创建SummaryWriter对象,可视化词向量
# 用于把词嵌入矩阵和词列表写入TensorBoard,方便可视化查看
summarywriter = SummaryWriter()  
summarywriter.add_embedding(embed.weight.data, my_token_list)
summarywriter.close()
# 5 通过索引获取词向量
# 遍历词表索引,获取对应词向量并打印
for idx in range(len(mytokenizer.index_word)):tmp_vec = embed(torch.tensor([idx]))print('tmp_vec--->', tmp_vec.detach().numpy())
  • 在程序的当前目录下运行:tensorboard --logdir=runs --host 0.0.0.0,再通过http://127.0.0.1:6006访问。
http://www.dtcms.com/a/334926.html

相关文章:

  • B*算法深度解析:动态避障路径规划的革命性方法
  • AI安全增强核心技术:提示词防火墙、置信度过滤与知识蒸馏防御
  • 2-3〔O҉S҉C҉P҉ ◈ 研记〕❘ 漏洞扫描▸AppScan(WEB扫描)
  • XC6SLX45T-2FGG484C Xilinx AMD Spartan-6 FPGA
  • 16-集合的Stream编程
  • 基于STM32的智能书房系统设计与实现
  • BitLocker解密
  • docker compose安装mysql8
  • UE5多人MOBA+GAS 46、制作龙卷风技能
  • C/单片机内存管理,仿真keii
  • 第5问 对于数据分析领域,统计学要学到什么程度?
  • 第6问 数据分析领域主要的岗位有哪些?
  • 《从混乱到有序:AI 如何一步步梳理数据质量难题》文章提纲
  • 基于Python的课程作业管理系统 Python+Django+Vue.js
  • Python-深度学习.pytorch(二)——自动微分、认识深度学习
  • C++STL标准模板库详解
  • 【渗透实战】无下载器环境(curl/wget)下玩转 Metasploit 自动利用
  • ES操作手册
  • 一、内核初始化中与内存管理相关的函数
  • C语言:文件操作详解
  • 微软Wasm学习-创建一个最简单的c#WebAssembly测试工程
  • 【项目实战】利用AI生成式编程生成控制镜头变倍,变焦,光圈的Shell脚本(一)
  • 如何在FastAPI中玩转APScheduler,实现动态定时任务的魔法?
  • Redis7学习--详解 主从复制
  • 利用cursor+MCP实现浏览器自动化释放双手
  • 自动驾驶中的传感器技术24.1——Camera(16)
  • 企业级Java项目金融应用领域——银行系统(补充)
  • python线程学习
  • 一文了解金融合规
  • 什么是模型预测控制?