Python----NLP自然语言处理(FastText)

一、FastText

1.1、介绍

        FastText 是由 Facebook AI Research(FAIR)团队开发的一个快速、高效的词向量和文本分类工具。它是基于Word2Vec的扩展和优化,支持生成词向量和执行文本分类任务,具有简单、高效、易用的特点。FastText 的实现经过优化,在大型语料上训练速度比传统方法快数倍,且内存占用更低。

1.2、子词机制

        子词机制(Subword Mechanism) 是FastText的核心创新,这一机制通过将单词拆分为子词(subwords)来生成词向量。它解决了传统词向量模型(如 Word2Vec)的一些局限性,例如无法处理未登录词和对形态学信息的忽略。

        在 FastText 中,每个单词会被分解成多个子词。模型不仅为整个单词创建向量,还为其子词创建向量,并将它们组合起来表示这个单词。

        FastText和Word2Vec中的模型很相似,也支持CBOW和Skip-gram,我们以CBOW举例:CBOW读取句子,预测中心词;FastText读取单词,预测子词。

子词机制的优点 

捕捉形态信息

        英文中,FastText 可以捕捉词缀和前缀的语义。例如 "playing" 和 "played" 会共享子词 "play"。中文中,单个汉字常带有丰富的语义。例如 "质量" 和 "量化" 都包含 "量",会共享部分语义信息。

处理未登录词 

        即使一个单词没有出现在训练语料中,只要它的子词在语料中出现过,就可以通过子词生成词向量。 例如:生僻词 "高质感" 可以通过子词 "高", "质", "感" 得到表示。

更好的泛化能力

        传统的 Word2Vec 会为每个单词生成独立的向量,而 FastText 可以通过子词共享信息,增强对罕见词的理解能力。对于存在大量新词或生僻词的任务(如社交媒体分析),FastText 的子词机制具有显著优势。

子词增加了额外的存储需求,但提升了泛化能力。

1.3、子词机制的工作原理

子词分解

在子词分解中,有两个参数minn 和 maxn,用于定义子词的最小和最大长度。例如分解英文单词playing,设置minn=3maxn=4,则会分解为:

  • 3-grams: ["pla", "lay", "ayi", "yin", "ing"]
  • 4-grams: ["play", "layi", "ayin", "ying"]

如果分解的是中文单词高富帅,设置minn=1maxn=2,则会分解为:

  • 1-grams: ["高", "富","帅"]
  • 2-grams: ["高富","富帅"]

推荐设置:

  • 中文:minn=1maxn=3
  • 英文:minn=3maxn=6

子词向量

每个子词都有一个独立的向量,FastText 将这些子词的向量加和作为单词的表示。

假设:

  • 子词 "质" 的向量是 v1
  • 子词 "量" 的向量是 v2
  • 子词 "高" 的向量是 v3

那么单词 "高质量" 的最终表示为:v高质量=v3+v1+v2

未登录词处理

  • 如果某个单词未出现在训练语料中,FastText 会通过其子词来生成表示。
  • 例如,假设单词 "高质量" 不在训练词表中,但其子词 "高","质量" 存在,FastText 会通过这些子词的向量组合生成 "高质量" 的表示。

二、案例

安装工具包

pip install jieba=0.42.1
pip install gensim==4.3.1

导入模块包 

from gensim.models import FastText
import jieba # jieba分词器
import re # 正则表达式

分词 

f = open("sanguo.txt", 'r',encoding='utf-8') #读入文本
lines = []
for line in f: #分别对每段分词
  temp = jieba.lcut(line) #结巴分词 精确模式
  words = []
  for i in temp:
    #过滤掉所有的标点符号
    i = re.sub("[\s+\.\!\/_,$%^*(+\"\'””《》]+|[+——!,。?、~@#¥%……&*():;‘]+", "", i)
    if len(i) > 0:
      words.append(i)
  if len(words) > 0:
    lines.append(words)
print(lines[0:5])#预览前5行分词结果

模型训练 

# 训练 FastText 模型
model = FastText(
  sentences=lines,   # 预处理后的语料
  vector_size=20,    # 词向量的维度
  window=5,       # 窗口大小
  min_count=3,     # 最低词频,低于此值的词将被忽略
  sg=1,         # Skip-gram 模型 (1 表示 Skip-gram, 0 表示 CBOW)
  epochs=10,      # 训练轮次
  workers=4,      # 并行线程数
  min_n=2,       # 子词的最小长度
  max_n=4        # 子词的最大长度
)

检测模型效果

# 输出词向量
print("主公的词向量:\n",model.wv.get_vector("主公"))


# 输出与特定词语相关度比较高的词
print("和主公相关性最高词语:")
print(model.wv.most_similar("主公"))


print("和荆州相关性最高词语:")
print(model.wv.most_similar("荆州"))

完整代码

# 导入所需库
from gensim.models import FastText  # FastText词向量模型
import jieba  # 中文分词库
import re  # 正则表达式库

# 读取文本文件
f = open("sanguo.txt", 'r', encoding='utf-8')  # 以utf-8编码打开三国演义文本

# 初始化存储分词结果的列表
lines = []

# 逐行处理文本
for line in f:  # 遍历文件的每一行
    # 使用jieba进行精确模式分词
    temp = jieba.lcut(line)  # 返回分词后的列表
    
    # 初始化存储过滤后词语的列表
    words = []
    
    # 过滤每个词语
    for i in temp:
        # 使用正则表达式去除标点符号和特殊字符
        # 匹配各种中文/英文标点符号和特殊字符
        i = re.sub("[\s+\.\!\/_,$%^*(+\"\'””《》]+|[+——!,。?、~@#¥%……&*():;‘]+", "", i)
        
        # 只保留长度大于0的非空词语
        if len(i) > 0:
            words.append(i)
    
    # 只添加非空的行
    if len(words) > 0:
        lines.append(words)

# 打印前5行分词结果(用于检查预处理效果)
print("前5行分词结果:")
print(lines[0:5])

# 训练FastText模型
model = FastText(
    sentences=lines,   # 预处理后的分词语料
    vector_size=20,    # 词向量维度(通常50-300,这里设为20演示用)
    window=5,         # 上下文窗口大小(考虑前后5个词)
    min_count=3,      # 词语最小出现次数(低于3次会被忽略)
    sg=1,            # 训练算法:1=skip-gram(更适合小数据), 0=CBOW
    epochs=10,       # 训练迭代次数
    workers=4,       # 并行线程数(提高训练速度)
    min_n=2,         # 字符级n-gram最小长度(用于处理未登录词)
    max_n=4          # 字符级n-gram最大长度
)

# 获取并打印"主公"的词向量(20维)
print("\n'主公'的词向量:")
print(model.wv.get_vector("主公"))

# 查找与"主公"最相似的词语
print("\n与'主公'最相似的词语:")
print(model.wv.most_similar("主公", topn=5))  # 默认返回10个,这里显示5个

# 查找与"荆州"最相似的词语
print("\n与'荆州'最相似的词语:")
print(model.wv.most_similar("荆州", topn=5))
主公的词向量:
 [ 0.1157713  -1.0269296  -0.29581293  0.2543293   0.3448897   0.24345848
 -0.51907265  0.7143039  -0.22339359  0.5440311   0.7463962  -0.23664966
  0.7180554  -0.02237542  0.4524613   0.54626554  0.31623515 -0.38442203
 -0.49574775 -0.7358438 ]
和主公相关性最高词语:
[('成事', 0.9346866607666016), ('烦', 0.9330105185508728), ('机会', 0.9306012988090515), ('主上', 0.9269402623176575), ('今事', 0.9214110374450684), ('有何不可', 0.9199930429458618), ('切不可', 0.9187008142471313), ('蒙', 0.9183181524276733), ('良策', 0.9159600138664246), ('臣料', 0.9139387607574463)]
和荆州相关性最高词语:
[('徐州', 0.9036551117897034), ('东川', 0.9007480144500732), ('江夏', 0.8960878849029541), ('西川', 0.8957638740539551), ('取川', 0.8716447949409485), ('襄阳', 0.8640182018280029), ('川', 0.8624700903892517), ('公安', 0.8566825985908508), ('袁绍处', 0.8560354113578796), ('屯小沛', 0.8489747047424316)]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值