首页 > 编程语言 >python实战(三)——文本向量化/文本表示

python实战(三)——文本向量化/文本表示

时间:2024-10-26 17:16:04浏览次数:9  
标签:实战 python 模型 词汇表 单词 texts 文本 向量

一、概念

        文本向量化是自然语言处理领域的重要环节,也是现在大语言模型开发重要基础。计算机程序无法理解文字信息(实际上非数值类型的信息都无法理解),因此我们需要将文字信息转换成计算机程序可理解的数值类型。通俗来说就是我们的算法模型是一系列函数和公式的组合推导,那么变量自然得是数值类型的才能参与计算。因此,这么将文本转换成数值类型的向量的过程就是文本向量化,而转换得到的这个向量又称文本表示。

二、分词

        分词是文本向量化之前的必备步骤,为了让得到的文本表示不会损失太多的语义信息,我们需要有一个良好的分词结果。常见的中文分词库有jieba英文分词库有nltk,这些分词库的原理都是内置一个词典,通过词匹配的方式将词语分隔出来。实际上,英文由于有空格分隔各个单词,分词的步骤较为简单(前提是划分单词而非词组),但由于中文是连续的字符,不依赖词典是无法得到有效的分词结果的(除非按“字”的粒度进行分隔,例如命名实体识别任务)。以中文分词为例:

import jieba

# 示例中文文本
text = "我喜欢学习自然语言处理。"

# 使用jieba进行分词
seg_list = jieba.cut(text)

# 将分词结果转换为列表并打印
print("分词结果:", "/ ".join(seg_list))

        结果如下:

fd002a60796a409ab3bfa7fed3557a83.png

        内置词典的分词器有个弊端就是无法及时更新词典,从而导致对于新词的划分力度不足,例如如今我们倾向于将“大语言模型”作为一个词组,但是直接使用jieba分词的结果可能并不如我们所想:

a08f2226913a4d1c8ca8d238ccc7550c.png

        这时候,我们可以通过手动添加词典的方式进行词库的更新。

jieba.add_word('大语言模型')

4947ac90d0fc42e093103479529fa457.png

三、文本向量化常见方式

1、词袋模型

        词袋模型(Bag-of-Words,BOW)是一种自然语言处理中常用的文本表示方法,它的基本思想是将文本看作一个装着单词的“袋子”,不考虑单词的顺序和语法结构,只关注单词的出现频率。词袋模型的构建过程包括以下几个步骤:

  • 分词:将文本分割成单词或词汇单元。
  • 构建词汇表:从所有文档中提取唯一的单词,形成一个词汇表(这个过程也包括了去停用词等操作)。
  • 特征向量化:对于每个文档,统计出现在词汇表中的每个单词的出现频率,并形成一个特征向量。向量的每个维度对应词汇表中的一个单词,其值表示该单词在文档中的出现次数,未出现则为0(所以是一个及其稀疏的向量)。
  • 模型训练与预测:使用特征向量作为输入,训练机器学习模型,并进行预测。

(1)中文示例

import jieba
from sklearn.feature_extraction.text import CountVectorizer

# 示例中文文本数据
texts = [
    '苹果和梨子是很常见的水果。',
    '我喜欢吃芒果和百香果。',
    '苹果今年推出了新的手机。',
    '华为的新手机拍照性能非常好。'
]

# 使用jieba进行分词
texts_cut = [" ".join(jieba.cut(text)) for text in texts]

# 初始化CountVectorizer对象
vectorizer = CountVectorizer()

# 使用分词后的文本数据训练Vectorizer,即构建词汇表,并返回文档-词汇矩阵
X = vectorizer.fit_transform(texts_cut)

# 获取词汇表
vocabulary = vectorizer.get_feature_names_out()

# 打印词汇表
print("Vocabulary:", vocabulary)

# 打印文档-词汇矩阵
print("Document-term matrix:")
print(X.toarray())

        下面可以看到打印出来的词汇表和向量矩阵,可以发现构建词表的过程中默认会去掉常见的停用词,例如“的”、“和”。同时,文本向量中可以清晰得出词汇表对应词语的出现频次。例如第一句话“苹果和梨子是很常见的水果”对应向量中,第四位“常见”出现了1次,第十位“梨子”和十一位“水果”各出现1次,倒数第二位“苹果”出现了1次。

209d710123a6404182ce3945a6e4e54d.png

(2)英文示例

        由于英文有空格划分单词,因此单词粒度的词汇表构建过程中不需要进行分词即可直接使用词袋模型。

from sklearn.feature_extraction.text import CountVectorizer

# 示例文本数据
texts = [
    "Apple and pear are very common fruits.",
    "I like to eat mango and passion fruit.",
    "Apple has launched a new phone this year.",
    "HuaWei's new phone has excellent camera performance."
]

# 初始化CountVectorizer对象
vectorizer = CountVectorizer()

# 使用文本数据训练Vectorizer,即构建词汇表,并返回文档-词汇矩阵
X = vectorizer.fit_transform(texts)

# 获取词汇表
vocabulary = vectorizer.get_feature_names_out()

# 打印词汇表
print("Vocabulary:", vocabulary)

# 打印文档-词汇矩阵
print("Document-term matrix:")
print(X.toarray())

7fbc2d8cdb854a14a8c8ede21cd720cc.png

        由此可知,词袋模型的缺陷非常明显:首先,它并没有任何语义信息;其次,词汇表的长度决定了词袋向量的长度,如果词汇表有上百万个词语,那么每一个样本的词袋向量也有上百万维,这是不可容忍的。

2、Word2Vec

        Word2Vec由Google在2013年开发,用于生成词嵌入(词语的文本表示)。Word2Vec通过学习单词的上下文关系来生成每个单词的数值向量表示,这些向量能够捕捉单词的语义信息和句法信息,并将单词的语义相似性转化为向量空间中的几何关系。Word2Vec模型的核心思想是:在文本中经常一起出现的单词在向量空间中也会彼此接近。Word2Vec的训练过程如下:

  • 初始化词嵌入:为每个单词分配一个随机向量(向量维度由我们根据任务需要定义)。
  • 构建词汇表:创建一个包含所有单词的词汇表(实际应用中单词数量可选,如仅使用出现频率Top N的单词)。
  • 训练模型:使用文本数据训练模型,通过优化算法(如梯度下降)调整词嵌入向量,以最小化预测误差。
  • 生成词嵌入:训练完成后,每个单词都会有一个固定长度的向量表示。

        此外,Word2Vec有两种学习模式:

(1)CBOW(Continuous Bag of Words)

        CBOW模型的输入是单词的上下文,输出是中心词的预测,即使用周围的单词来预测中间的单词。CBOW模型的目标是最大化给定上下文词时目标词的条件概率,这等价于最小化交叉熵损失。对于CBOW模型,目标函数可以表示为:

eq?L%20%3D%20-%5Csum_%7Bt%3D1%7D%5E%7BT%7D%5Csum_%7Bk%3D1%7D%5E%7BV%7Dt_%7Bt%2Ck%7Dlog%5Chat%7Bp%7D%28w_%7Bk%7D%7Cw_%7Bt-c%7D%2C...%2Cw_%7Bt-1%7D%2Cw_%7Bt+1%7D%2C...%2Cw_%7Bt+c%7D%29

        其中,T是训练集中样本的总数,V是词汇表的大小,eq?w_%7Bk%7D是目标词,eq?w_%7Bt-c%7D%2C...%2Cw_%7Bt-1%7D%2Cw_%7Bt+1%7D%2C...%2Cw_%7Bt+c%7D是上下文词,eq?%5Chat%7Bp%7D%28w_%7Bk%7D%7Cw_%7Bt-c%7D%2C...%2Cw_%7Bt-1%7D%2Cw_%7Bt+1%7D%2C...%2Cw_%7Bt+c%7D%29是在给定上下文的情况下目标词的条件概率。

(2)Skip-Gram

        Skip-Gram模型的输入是中心词,输出是上下文单词的预测,即它使用一个单词来预测周围的单词。Skip-Gram模型的数学公式可以表示为最大化给定目标词的条件下上下文词的出现概率,即最大化下面的目标函数:

eq?L%20%3D%20-%5Csum_%7Bt%3D1%7D%5E%7BT%7D%5Csum_%7B-c%5Cleqslant%20j%5Cleqslant%20c%2Cj%5Cneq%200%7Dlog%5Chat%7Bp%7D%28w_%7Bt+j%7D%7Cw_%7Bt%7D%29

        其中,T是训练集中的样本总数,c是上下文窗口大小,eq?w_%7Bt%7D是目标词,eq?w_%7Bt+j%7D是上下文词,条件概率eq?%5Chat%7Bp%7D%28w_%7Bt+j%7D%7Cw_%7Bt%7D%29可以用softmax函数计算:

eq?%5Chat%7Bp%7D%28w_%7BO%7D%7Cw_%7BI%7D%29%20%3D%20%5Cfrac%7Bexp%28%7Bv%7D%27%5E%7BT%7D_%7Bw_%7Bo%7D%7Dv_%7Bw_%7BI%7D%7D%29%7D%7B%5Csum_%7Bw%3D1%7D%5E%7BW%7Dexp%28%7Bv%7D%27%5E%7BT%7D_%7Bw%7Dv_%7Bw_%7BI%7D%7D%29%7D

        这里,eq?v_%7Bw_%7BI%7D%7Deq?%7Bv%7D%27_%7Bw_%7BO%7D%7D分别是输入词eq?w_%7BI%7D和输出词eq?w_%7BO%7D的向量表示,W是词汇表的大小。

(1)中文示例

import jieba
from gensim.models import Word2Vec

# 示例中文文本数据
texts = [
    '苹果和梨子是很常见的水果。',
    '我喜欢吃芒果和百香果。',
    '苹果今年推出了新的手机。',
    '华为的新手机拍照性能非常好。'
]

# 使用jieba进行分词
texts_cut = [list(jieba.cut(text)) for text in texts]

# 训练Word2Vec模型
# 指定生成的词嵌入维度为30,学习的上下文窗口指定为5,用于构建词汇表的单词出现频次不低于min_count
model = Word2Vec(sentences=texts_cut, vector_size=30, window=5, min_count=1)

# 使用模型
vector = model.wv['梨子']  # 获取单词的向量表示
similar_words = model.wv.most_similar('梨子')  # 找到最相似的词汇

# 打印结果
print("向量表示:", vector)
print("与'梨子'最相似的词汇:", similar_words[:3])

        结果如下,我们指定了向量维度30,并查找模型学习到的词汇语义相似度知识(由于数据量较少模型学习效果欠佳):

8e6818f977da412aa32ba01f62b7ebc9.png

(2)英文示例

import jieba
from gensim.models import Word2Vec

# 示例中文文本数据
texts = [
    "Apple and pear are very common fruits.",
    "I like to eat mango and passion fruit.",
    "Apple has launched a new phone this year.",
    "HuaWei's new phone has excellent camera performance."
]

# 将文本数据分割成单词列表
texts_split = [text.split() for text in texts]

# 训练Word2Vec模型
# 指定生成的词嵌入维度为30,学习的上下文窗口指定为3,用于构建词汇表的单词出现频次不低于min_count
model = Word2Vec(sentences=texts_split, vector_size=30, window=3, min_count=1, epochs=20)

# 使用模型
vector = model.wv['pear']  # 获取单词的向量表示
similar_words = model.wv.most_similar('pear')  # 找到最相似的词汇

# 打印结果
print("向量表示:", vector)
print("与'pear'最相似的词汇:", similar_words[:3])

8b6bcce4f4a24b2289e7c68d1488ecad.png        这里需要注意几个参数:

  • sg:取值为0表示使用CBOW模式,为1表示使用skip-gram模式,默认为0。
  • vector_size:单词向量的维度数,默认100。
  • window:词嵌入训练过程中,句子中当前单词与预测单词的最大距离不能超过该值,默认5。
  • min_count:词汇表构建过程中,忽略总频率低于该值的所有单词,默认5。
  • epochs:迭代次数,默认5。

3、预训练模型

        这里我们使用BERT(Bidirectional Encoder Representations from Transformers)作为示例。Bert是基于Transformer架构的预训练语言模型,它通过预训练的方式学习语言的表示和理解,在多种自然语言处理任务中取得了显著的效果。Bert通过两个主要的任务进行预训练:

  • Masked Language Model(MLM):在MLM任务中,模型需要预测被遮盖(masked)的token,这个任务使得模型去学习token之间的关系以及上下文信息,类似于完形填空。MLM过程中,有15%的token会被随机掩盖,其中80%用[MASK]这个token来代替,10%用一个随机token来替换,10%保持原token不变。
  • Next Sentence Prediction(NSP):在NSP任务中,模型需要判断两句话是否为连续的上下文句子,这个任务让模型能够理解句子之间的逻辑关系(虽然后面的研究发现这个任务对于Bert性能的提升并无太大作用,更多还是MLM给它带来的能力)。

(1)中文示例

from transformers import BertTokenizer, BertModel
import torch

# 这是一个基础版本的bert中文模型,如果需要更强大的、在特定任务中微调过的模型,可以去HuggingFace查找
# 预训练模型同样依赖自身的词典进行分词,而在bert-base-chinese这个模型中,对中文的分词粒度是字,也就是按照字的粒度划分中文文本,有一些模型是按照词粒度进行中文分词的,这个同样可以到HF上去查找
model_name = 'bert-base-chinese'
# 初始化分词器
tokenizer = BertTokenizer.from_pretrained(model_name)
# 加载模型
model = BertModel.from_pretrained(model_name)

texts = ['苹果和梨子是很常见的水果。', '我喜欢吃芒果和百香果。', '苹果今年推出了新的手机。', '华为的新手机拍照性能非常好。']

# 分词器生成Bert模型必要的输入格式
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")
# 禁用梯度,打开预测模式
with torch.no_grad():
    # 预测输出
    outputs = model(**inputs)

# 取最后一层的token平均向量
print('向量维度:')
print(sentence_embeddings.shape)
sentence_embeddings = outputs.pooler_output
print(sentence_embeddings)

63432db94ce44e98b2b63adb38598106.png

(2)英文示例

from transformers import BertTokenizer, BertModel
import torch

# 同样,可以去HuggingFace找更强大的模型
model_name = 'bert-base-uncased'

# 初始化分词器
tokenizer = BertTokenizer.from_pretrained(model_name)
# 加载模型
model = BertModel.from_pretrained(model_name)

texts = ["Apple and pear are very common fruits.", "I like to eat mango and passion fruit.", "Apple has launched a new phone this year.", "HuaWei's new phone has excellent camera performance."]

# 分词器生成Bert必要的输出格式
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")
# 禁用梯度,打开预测模式
with torch.no_grad():
    # 预测输出
    outputs = model(**inputs)

# 取最后一层的token平均向量
sentence_embeddings = outputs.pooler_output
print('向量维度:')
print(sentence_embeddings.shape)
print('文本向量:')
print(sentence_embeddings)

376a5070328b429e966f53a4ae21619c.png

        可见,Bert生成的向量维度默认为768维。

四、总结

        目前,对于文本向量化的任务,基本都会使用大型预训练模型了,这是由于它们最大程度保留了文本的原始语义,在诸多任务中表现良好。此外,传统的模型如Word2Vec对同一个单词的向量化表示是相同的,但我们知道同一个词在不同语境下应当有不同的含义。预训练模型结合了上下文进行文本表示,从而使得同一个词在不同语境下有不同的表征,这就是最明显的优势。例如,下面是第一句话中表示水果的Apple和第三句话中表示手机品牌的Apple的Bert文本表示截取,二者之间有着明显区别:

(1)水果“Apple”的向量:

b58f482680c241a6ac17b27c728761f1.png

(2)手机“Apple”的向量

2927fb54db0041ab8ae65ccde95203b9.png

        关于预训练模型的内容笔者后续会逐一详解。

 

标签:实战,python,模型,词汇表,单词,texts,文本,向量
From: https://blog.csdn.net/ChaneMo/article/details/143116615

相关文章

  • 鸿蒙开发融云demo发送文本消息
    鸿蒙开发融云demo发送文本消息融云鸿蒙版是不带UI的,得自己一步步搭建。这次说如何发送文本消息,并且显示文本消息一、思路发送用:IMEngine.getInstance().sendMessage显示文本:Text(ImUtils.dealMyTextContent(this.msg.contentasTextMessage)).l......
  • js逆向实战之某市场监管公告服务平台返回数据解密
    声明:本篇文章仅用于知识交流分享,不用于其他用途练习网站:https://jzsc.mohurd.gov.cn/data/company解密过程分析访问网站,随便选择一个区域,点击查询,看触发哪些数据包。只有一个数据包,且其响应数据一看就是经过加密的。有经验的人就会条件反射是拦截器,全局搜索interceptors。......
  • [python]windows上通过whl文件安装sounddevice教程
    要通过.whl文件安装sounddevice,可以按照以下步骤进行操作:一、准备工作下载.whl文件:从gitee.com/FIRC/pythonlibs_whl_mirror或其他可信任的源下载sounddevice的.whl安装包。确保下载的.whl文件与你的Python版本和系统架构相匹配。安装pip:pip是Python的包管理工具,通常与Python一起安......
  • [python]windows上通过whl文件安装numpy+mkl教程
    在Windows上通过.whl文件安装numpy+mkl,可以按照以下步骤进行:一、准备工作下载numpy+mkl的.whl文件:访问可靠的Python库下载源,如gitee.com/FIRC/pythonlibs_whl_mirror。进去后按Ctrl+F搜索numpy+mkl,找到与你的Python版本和系统架构相匹配的.whl文件。下载该.whl文件到本地计算机。确......
  • 【渗透实战系列】 从SQL注入渗透内网(渗透的本质就是信息搜集)
    前言一个SQL注入可以帮我们的不仅仅是获取数据库表里的数据,还能让我们直接获取到目标服务器的权限,减少我们渗透的时间,本文主要围绕SQL注入如何进内网来写的,不多说兄弟们看文章就完事了。给我一个SQL注入我能干翻你内网朋友们如果有需要全套《网络安全入门+进阶学习......
  • 【黑马python:函数】51-61
    本节目录一、前言二、函数的基础定义语法1.定义形式2.练习案例:查核酸三、函数的传入参数1.语法解析2.案例升级:核酸四、函数的返回值1.语法格式2.返回值的None类型五、函数的说明文档六、函数的嵌套调用七、变量在函数中的作用域1.局部变量与全局变量2.global关键字八......
  • python基础综合案例(数据可视化-动态柱状图)
    1.基础柱状图的构建打开浏览器,你会发现这是一个动态图,会随着时间变化而变化具体效果大家可以看我主页有个动态柱状图视频本质上来说,是和我们构建一个折线统计图差不多的,只是把对象换了一下如果我们需要反转x和y轴,可以输入以下代码#反转x轴和y轴bar.reversal_axis()......
  • 企业数据高效集成:聚水潭与金蝶系统对接实战
    聚水潭盘亏-金蝶其他出库:高效数据集成方案在企业管理系统中,如何实现不同平台间的数据无缝对接一直是一个关键挑战。本文将分享一个具体的技术案例:如何通过轻易云数据集成平台,将聚水潭的盘亏数据高效集成到金蝶云星空的其他出库模块。背景与需求分析在本次集成项目中,我们需要从......
  • Python网络爬虫入门指南
    Python网络爬虫入门指南网络爬虫(WebCrawler),又称为网络蜘蛛(WebSpider),是一种自动化程序,能够遍历互联网上的网页,收集并提取所需的数据。Python作为一种功能强大且易于学习的编程语言,非常适合用于编写网络爬虫。本文将带你了解Python网络爬虫的基本概念、主要库及其使用方法......
  • Python 条件语句详解 if - elif-else
    Python条件语句详解一、引言在编程中,条件语句是一种基本的控制结构,它允许程序根据不同的条件执行不同的代码块。Python提供了丰富的条件语句,包括if、elif(elseif的缩写)和else,这些语句使得程序能够根据特定的条件做出决策,并执行相应的操作。二、条件语句的基本概念(......