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

NLP自然语言处理

NLP就是人与机器沟通的“桥梁”。

NLP的基础概念

概念名词

词表/词库(Vocabulary)

文本数据集中出现的所有单词的集合。

语料库(Corpus)

用于NLP任务的文本数据集合。

词嵌入(Word Embedding)

将单词映射到低维连续向量空间的技术,用于捕捉单词的语义和语法信息。

分词(Tokenization)

将文本分割成一个个单词或标记的过程,为后续处理提供基本的单位。

停用词(Stop Words)

在文本处理中被忽略的常见单词,如"a"、"the"、"is"等

词频(Term Frequency)

在给定文档中,某个单词出现的次数。

词性标注(Part-of-Speech Tagging)

为每个词赋予正确的词法标记。

句法分析(Parsing)

分析句子的结构,确定词语间的语法关系。

词干提取(Stemming)与词形还原(Lemmatization)

词干提取:将词转换为词干或原型形式,去除变化或衍生部分。

词形还原:将词还原为词源或词典中的词目形式。

词向量化(Word Vector)

将词语表示为实数向量,以捕捉语言与实数间的关系。

TF-IDF(Term Frequency-Inverse Document Frequency)

一种常用的文本特征表示方法,综合考虑了词频和逆文档频率。

命名实体消歧(Named Entity Disambiguation)与识别(Named Entity Recognition)

命名实体消歧:确定文本中提到的实体的具体含义,如区分同名不同义的实体。

命名实体识别:识别文本中具有特定意义的实体,并分类为人名、机构名、日期等。

序列常见类型

  1. 字符序列

    一个字符串就是一个字符序列,每个字符按顺序排列。                                  例子:"hello" 是一个由 hello 组成的字符序列。
  2. 单词序列

    一句话可以看作是一个单词序列,每个单词按照一定顺序排列。                                例子:"I love NLP" 是一个由 IloveNLP 组成的单词序列。
  3. 时序数据

    在时间序列中,元素是按时间顺序排列的,常用于预测问题。      例子:股票价格数据可以看作是随时间变化的数值序列。
  4. 语音序列

    在语音处理任务中,语音信号可以被分解为按时间顺序排列的帧序列(特征向量序列)。
  5. 其他序列

    序列还可以表示一些更抽象的结构,比如DNA序列(由碱基组成的序列)、事件序列等。

基本流程

1.语料获取

利用已经建好的数据集或第三方语料库

获取网络数据

与第三方合作获取数据,通过购买的方式获取部分需求文本数据

2.语料预处理

去除数据中非文本内容

中文分词  jieba分词软件

词性标注。词性标注指给词语打上词类标签,如名词、动词、形容词等,常用的词性标注方法有基于规则的算法、基于统计的算法等。

去停用词。停用词就是句子中没必要存在的词,去掉停用词后对理解整个句子的语义没有影响。中文文本中存在大量的虚词、代词或者没有特定含义的动词、名词,在文本分析的时候需要去掉。

3.文本向量化(特征工程)

文本数据经过预处理去除数据中非文本内容、中文分词、词性标注和去停用词后,基本上是干净的文本了。但此时还是无法直接将文本用于任务计算,需要通过某些处理手段,预先将文本转化为特征向量。一般可以调用一些模型来对文本进行处理,常用的模型有词袋模型(Bag of Words Model)、独热表示、TF-IDF 表示、n元语法(n-gram)模型和 Word2Vec模型等。

4.模型构建

5.模型训练

6.模型评价

NLP中的特征工程

在自然语言处理(NLP)中,特征工程是指将文本数据转换为适合机器学习模型使用的数值表示的过程

传统NLP中的特征工程

独热编码 one - hot

独热编码(One-Hot Encoding) 是一种常见的特征表示方法,通常用于将离散的类别型数据转换为数值型表示,它的特点是将每个类别表示为一个向量,在该向量中,只有一个元素为1,其余元素全部为0。

例:在nlp中,构成词库{time, fruit, flies, like, a, an, arrow, banana},banana的one-hot表示就是:[0,0,0,0,0,0,0,1],"like a banana” 的one-hot表示就是:[0,0,0,1,1,0,0,1]。

词频-逆文档频率(TF-IDF)

词频

在计算词频(TF)时,分母是文档中的总词数 ,不考虑重复

例:“Fruit flies like time flies a fruit” ,TF("files")=2/7

逆文档频率(Inverse Document Frequency, IDF)

逆文档频率用来衡量一个词在整个文档集合(语料库)中的重要性。它的目的是降低那些在很多文档中频繁出现的词的权重,例如“the”、“is”这种常见词,或者低频罕见词tetrafluoroethylene(四氟乙烯)。

D表示文档集合,t是要计算的词。+1 是为了避免分母为 0 的情况。

math在文章中出现5次,文章有200个词,则IDF=log[200/(5+1)]

TF-IDF 计算

TF-IDF 是 TF 和 IDF 相乘

一个词在特定文档中出现的频率越高(TF高),并且在整个语料库中出现得越少(IDF高),它的 TF-IDF 值就越高。可以找出在文章中重点但不常见的词,比如一些专业名词等。

n-grams

n-grams 是特征工程中的一种技术,它通过将文本中的连续 n 个词(或字符)组合起来,形成一个短语来捕捉文本中的局部上下文信息。n 可以为 1、2、3 等,具体取决于希望捕捉的上下文范围。

  • 1-gram(Unigram):每个单独的词作为一个单位。例如,"I love NLP" 的 1-gram 是 ["I", "love", "NLP"]

  • 2-grams(Bigram):相邻的两个词组合成一个短语。例如,"I love NLP" 的 2-grams 是 ["I love", "love NLP"]

  • 3-grams(Trigram):相邻的三个词组合成一个短语。例如,"I love NLP" 的 3-grams 是 ["I love NLP"]

深度学习中NLP的特征输入

稠密编码(特征嵌入)

稠密编码(Dense Encoding)

通常指的是将离散或高维稀疏数据转化为低维的连续、密集向量表示。

特征嵌入(Feature Embedding)

特征嵌入,也成为词嵌入,是稠密编码的一种表现形式,目的是将离散的类别、对象或其他类型的特征映射到一个连续的向量空间。

特点:

  • 低维度:相比稀疏表示(如独热编码),稠密编码的维度更低,能够减少计算和存储成本。

  • 语义相似性:嵌入向量之间的距离(如欧氏距离或余弦相似度)可以表示这些对象之间的语义相似性。

  • 可微学习:嵌入表示通常通过神经网络进行学习,并且通过反向传播算法进行优化。

词嵌入算法

Embedding Layer

API

nn.Embedding(num_embeddings=10, embedding_dim=4)

  1. num_embeddings 表示词的数量

  2. embedding_dim 表示用多少维的向量来表示每个词

代码示例

import torch
import torch.nn as nn
import jiebatest="今天天气真好,好久没有这么好的天了"#文本分词
words=jieba.lcut(test)# print(words)
# 输出:
# ['今天天气', '真', '好', ',', '好久', '没有', '这么', '好', '的', '天', '了']#构建词典
index_to_word={}
word_to_index={}
for i,word in enumerate(set(words)):if word not in word_to_index:index_to_word[i]=wordword_to_index[word]=i
# print(word_to_index)
# print(index_to_word)
#输出:
"""
{'今天天气': 0, '真': 1, '好': 2, ',': 3, '好久': 4, '没有': 5, '这么': 6, '
的': 8, '天': 9, '了': 10}
{0: '今天天气', 1: '真', 2: '好', 3: ',', 4: '好久', 5: '没有', 6: '这么', 8: '的', 9: '天', 10: '了'}
"""#词嵌入层
#第一个参数:词表单词总数 第二个:词嵌入维度
embed=nn.Embedding(len(word_to_index),2)#将文本转成词向量表示
print("-"*30)
for word in words:i=word_to_index[word]# 获取词向量word_vector=embed(torch.tensor([i]))print("%3s\t" % word_vector)"""
------------------------------
tensor([[0.4638, 1.4010]], grad_fn=<EmbeddingBackward0>)
tensor([[0.2467, 0.5415]], grad_fn=<EmbeddingBackward0>)
tensor([[ 0.1601, -0.2102]], grad_fn=<EmbeddingBackward0>)
tensor([[-0.6121, -1.8269]], grad_fn=<EmbeddingBackward0>)
tensor([[ 0.4472, -0.0368]], grad_fn=<EmbeddingBackward0>)
tensor([[-1.0996,  0.1180]], grad_fn=<EmbeddingBackward0>)
tensor([[-1.0891, -0.2760]], grad_fn=<EmbeddingBackward0>)
tensor([[ 0.1601, -0.2102]], grad_fn=<EmbeddingBackward0>)
tensor([[ 0.3143, -0.9363]], grad_fn=<EmbeddingBackward0>)
tensor([[-0.2251,  0.9102]], grad_fn=<EmbeddingBackward0>)
tensor([[-0.5780, -0.8060]], grad_fn=<EmbeddingBackward0>)
"""
"""
假设现在有语料库sentences = ["i like dog", "i love coffee", "i hate milk", "i love milk"] 通过词嵌入层算法和NNLM模型得到以下结果[['i', 'like'], ['i', 'love'], ['i', 'hate'], ['i', 'love']] -> ['dog', 'coffee', 'milk', 'milk']
"""import torch
import torch.nn as nn
import numpy
import torch.optim as optimsentences= ["i like dog", "i love coffee", "i hate milk","i love milk"]
#创建词表和对应的映射关系
word_list = " ".join(sentences).split()
# print(word_list)
"""
['i', 'like', 'dog', 'i', 'love', 'coffee', 'i', 'hate', 'milk','i', 'love', 'milk']
"""word_list= list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict)#词表大小#设置模型超参数
m_dim=2#嵌入向量的维度
n_hidden=2#神经元数量
n_step=2#输入步长数#创建输入的样本和目标值
def make_batch(sentences):input_batch = []target_batch = []for sen in sentences:word = sen.split()# print(word)input = [word_dict[n] for n in word[:-1]]target = word_dict[word[-1]]input_batch.append(input)target_batch.append(target)return input_batch,target_batch#创建模型
class NNLM(nn.Module):def __init__(self,n_step,n_class,m_dim,n_hidden):super (NNLM,self).__init__()#定义嵌入层,单词索引映射为嵌入向量self.embed=nn.Embedding(n_class,m_dim)#第一层隐藏层self.linear1=nn.Linear(m_dim*n_step,n_hidden)#分类类别数就是词表大小self.linear2=nn.Linear(n_hidden,n_class)def forward(self,x):x=self.embed(x)#通过嵌入层得到的形状是(batch_size,n_step,m_dim) ->(batch_size,n_step*m_dim)x=x.view(-1,n_step*m_dim)#拉平为二维数据h=torch.tanh(self.linear1(x))output=self.linear2(h)return output#初始化模型
model=NNLM(n_step,n_class,m_dim,n_hidden)#创建损失函数和优化器
criterion=nn.CrossEntropyLoss()#损失函数 交叉熵
optimizer=optim.Adam(model.parameters(),lr=0.001)#优化器 学习率#准备输入和目标数据
input_batch,target_batch=make_batch(sentences)
input_batch=torch.LongTensor(input_batch)
target_batch=torch.LongTensor(target_batch)for epoch in range(5000):optimizer.zero_grad()#梯度清零    output=model(input_batch)loss=criterion(output,target_batch)if (epoch+1)%1000==0:print(f'Epoch:, %04d % (epoch+1), cost=, {loss:.6f}.format(loss)')loss.backward()#反向传播optimizer.step()#更新参数#使用训练好的模型进行预测
predict=model(input_batch).max(1,keepdim=True)[1]#输出预测结果
print([sen.split()[:2] for sen in sentences],'->',[number_dict[n.item()] for n in predict.squeeze()])    """
Epoch:, %04d % (epoch+1), cost=, 0.601257.format(loss)
Epoch:, %04d % (epoch+1), cost=, 0.511757.format(loss)
Epoch:, %04d % (epoch+1), cost=, 0.452694.format(loss)
Epoch:, %04d % (epoch+1), cost=, 0.412047.format(loss)
Epoch:, %04d % (epoch+1), cost=, 0.389134.format(loss)
[['i', 'like'], ['i', 'love'], ['i', 'hate'], ['i', 'love']] -> ['dog', 'milk', 'milk', 'milk']

word2vec

Word2vec是一个用来产生词向量的模型。是一个将单词转换成向量形式的工具。

word2vec一般分为CBOW(Continuous Bag-of-Words)与 Skip-Gram 两种模型:

1.CBOW

根据中心词周围的词来预测中心词,有negative sample和Huffman两种加速算法,

CBOW对小型数据库比较合适。

连续词袋模型(CBOW)是一种根据上下文单词来预测目标单词的模型。具体来说,给定一个窗口大小为 n 的上下文单词序列,连续词袋模型的任务是预测中间的目标单词。

import torch
import torch.nn as nn
import torch.optim as optim 
import numpy as np
import matplotlib.pyplot as plt#定义数据类型为浮点数
dtype=torch.FloatTensor# 语料库,包含训练模型的句子
sentences = ["i like dog", "i like cat", "i like animal","dog cat animal", "apple cat dog like", "cat like fish","dog like meat", "i like apple", "i hate apple","i like movie book music apple", "dog like bark", "dog friend cat"]# 建立词表
word_sentences = " ".join(sentences).split()
word_list = list(set(word_sentences))# 去重
word_index = {w: i for i, w in enumerate(word_list)}#创建CBOW的训练数据集
cbow_inputs=[]
for i in range(1,len(word_sentences)-1):context=[word_index[word_sentences[i-1]],word_index[word_sentences[i+1]]]target=word_index[word_sentences[i]]cbow_inputs.append([context, target])  # 上下文和目标加入训练集#词嵌入维度
emb_dim=2
#词表大小
vocab_size=len(word_index)
#训练批次
batch_size=2#定义CBOW模型
class CBOW(nn.Module):def __init__(self):super(CBOW,self).__init__()#映射矩阵self.embed=nn.Embedding(vocab_size,emb_dim)self.linear=nn.Linear(emb_dim,vocab_size)#输出矩阵#前向传播def forward(self,x):embeds=self.embed(x)#映射矩阵avg_embeds=torch.mean(embeds,dim=1)#上下文词向量取平均,dim是指在n_stepps维度上取平均output=self.linear(avg_embeds)return output #初始化模型
model=CBOW()#创建损失函数和优化器
criterion=nn.CrossEntropyLoss()#损失函数 交叉熵
optimizer=optim.Adam(model.parameters(),lr=0.001)#优化器 学习率#定义随机批量生成函数
def random_batch(data,size):random_inputs=[]random_labels=[]random_index=np.random.choice(range(len(data)),size,replace=False)#根据随机索引生成输入和目标数据for i in random_index:#目标词one_hot编码random_inputs.append(data[i][0])#上下文词的索引作为标签random_labels.append(data[i][1])return random_inputs,random_labels#训练模型
for epoch in range(10000):inputs,labels=random_batch(cbow_inputs,batch_size)# print(inputs)# print(labels)#转为张量input_batch=torch.LongTensor(inputs)label_batch=torch.LongTensor(labels)optimizer.zero_grad()#梯度清零    output=model(input_batch)loss=criterion(output,label_batch)if (epoch+1)%1000==0:print("Epoch:",epoch+1,"loss:",loss.item())loss.backward()#反向传播optimizer.step()#更新参数#可视化词嵌入
for i,label in enumerate(word_list):W=model.embed.weight.data.numpy()#获取参数x,y=float(W[i][0]),float(W[i][1])plt.scatter(x,y)plt.annotate(label,xy=(x,y),xytext=(5,2),textcoords='offset points',ha='right',va='bottom')plt.show()
"""
Epoch: 1000 loss: 1.9663656949996948
Epoch: 2000 loss: 2.3870277404785156
Epoch: 3000 loss: 1.9677610397338867
Epoch: 4000 loss: 1.111128330230713
Epoch: 5000 loss: 0.8203855752944946
Epoch: 6000 loss: 2.0697202682495117
Epoch: 7000 loss: 1.6513001918792725
Epoch: 8000 loss: 1.0836256742477417
Epoch: 9000 loss: 0.2905329167842865
Epoch: 10000 loss: 1.4150944948196411
"""

2.Skip-Gram

根据中心词来预测周围词

Skip-gram 模型是一种根据目标单词来预测上下文单词的模型。具体来说,给定一个中心单词,Skip-gram 模型的任务是预测在它周围窗口大小为 n 内的上下文单词。

import torch
import torch.nn as nn
import torch.optim as optim 
import numpy as np
import matplotlib.pyplot as plt#定义数据类型为浮点数
dtype=torch.FloatTensor# 语料库,包含训练模型的句子
sentences = ["i like dog", "i like cat", "i like animal","dog cat animal", "apple cat dog like", "cat like fish","dog like meat", "i like apple", "i hate apple","i like movie book music apple", "dog like bark", "dog friend cat"]# 建立词表
word_sentences = " ".join(sentences).split()
word_list = list(set(word_sentences))# 去重
word_index = {w: i for i, w in enumerate(word_list)}#创建skip的训练数据集
skip_grams=[]
for i in range(1,len(word_sentences)-1):#当前词对应的idcenter=word_index[word_sentences[i]]#获取当前词的前后两个上下文词对应的idcontext=[word_index[word_sentences[i-1]],word_index[word_sentences[i+1]]]#将当前词和上下文词组合成skip-gram对for w in context:  skip_grams.append([center,w])#定义超参数
#词嵌入维度
emb_dim=2
#词表大小
vocab_size=len(word_list)
#训练批次
batch_size=5#定义skip模型
class Word2Vec(nn.Module):def __init__(self):super(Word2Vec,self).__init__()#词嵌入层self.W=nn.Parameter(torch.rand(vocab_size,emb_dim))#定义输出层矩阵W2self.WT=nn.Parameter(torch.rand(emb_dim,vocab_size))self.logsoftmax=nn.LogSoftmax(dim=1)#前向传播def forward(self,x):#映射层weights=torch.matmul(x,self.W)#输出层out_put=torch.matmul(weights,self.WT)return out_put#初始化模型
model=Word2Vec()#创建损失函数和优化器
criterion=nn.CrossEntropyLoss()#损失函数 交叉熵
optimizer=optim.Adam(model.parameters(),lr=0.001)#优化器 学习率#准备输入和目标数据def random_batch(data,size):random_inputs=[]random_labels=[]#从数据中随机选取size个索引值random_index=np.random.choice(range(len(skip_grams)),size,replace=False)#根据随机索引生成输入和目标数据for i in random_index:#目标词one_hot编码random_inputs.append(np.eye(vocab_size)[data[i][0]])#上下文词的索引作为标签random_labels.append(data[i][1])return random_inputs,random_labels#训练模型
for epoch in range(10000):inputs,labels=random_batch(skip_grams,batch_size)#转为张量input_batch=torch.Tensor(inputs)label_batch=torch.LongTensor(labels)optimizer.zero_grad()#梯度清零    output=model(input_batch)loss=criterion(output,label_batch)if (epoch+1)%1000==0:print("Epoch:",epoch+1,"loss:",loss.item())loss.backward()#反向传播optimizer.step()#更新参数#可视化词嵌入
for i,label in enumerate(word_list):W,WT=model.parameters()#获取参数x,y=float(W[i][0]),float(W[i][1])plt.scatter(x,y)plt.annotate(label,xy=(x,y),xytext=(5,2),textcoords='offset points',ha='right',va='bottom')plt.show()"""input_batch=torch.Tensor(inputs)
Epoch: 1000 loss: 2.0359740257263184
Epoch: 2000 loss: 1.9298549890518188
Epoch: 3000 loss: 2.2617080211639404
Epoch: 4000 loss: 1.4156063795089722
Epoch: 5000 loss: 1.850890874862671
Epoch: 6000 loss: 1.5289673805236816
Epoch: 7000 loss: 1.8529554605484009
Epoch: 8000 loss: 1.8329124450683594
Epoch: 9000 loss: 1.6333214044570923
Epoch: 10000 loss: 1.8766262531280518
"""

3.gensim API调用
import torch
import torch.nn as nn 
import numpy as np
import matplotlib.pyplot as plt
from gensim.models import Word2Vec # 语料库,包含训练模型的句子
sentences = ["i like dog", "i like cat", "i like animal","dog cat animal", "apple cat dog like", "cat like fish","dog like meat", "i like apple", "i hate apple","i like movie book music apple", "dog like bark", "dog friend cat"]# 将语料库转换为列表
token_list=[sentences.split() for sentences in sentences]
print(token_list)
#定义模型
model=Word2Vec(token_list,vector_size=2,window=1,min_count=0,sg=0)#获取词汇表
word_list=list(model.wv.index_to_key)
# print(word_list)#可视化嵌入结果
for i,word in enumerate(word_list):w=model.wv[word]#获取模型参数x,y=float(w[0]),float(w[1])plt.scatter(x,y)plt.annotate(word,xy=(x,y),xytext=(5,2),textcoords='offset points',ha='right',va='bottom')print(model.wv.most_similar("like"))
print(model.wv.similarity("i","cat"))    
plt.show()
"""
[['i', 'like', 'dog'], ['i', 'like', 'cat'], ['i', 'like', 'animal'], ['dog', 'cat', 'animal'], ['apple', 'cat', 'dog', 'like'], ['cat', 'like', 'fish'], ['dog', 'like', 'meat'], ['i', 'like', 'apple'], ['i', 'hate', 'apple'], ['i', 'like', 'movie', 'book', 'music', 'apple'], ['dog', 'like', 'bark'], ['dog', 'friend', 'cat']]
[('friend', 0.846409797668457), ('bark', 0.7237492203712463), ('fish', 0.5371317267417908), ('apple', 0.4996943771839142), ('i', 0.49164748191833496), ('book', 0.31097015738487244), ('dog', -0.11141161620616913), ('cat', -0.21838019788265228), ('movie', -0.5319129824638367), ('music', -0.7415058016777039)]
-0.9571427
"""

 


http://www.mrgr.cn/news/35135.html

相关文章:

  • windows使用JEnv实现一键临时或全局切换java版本
  • 一带一路区块链样题解析(上)
  • 数据结构---顺序表之单链表
  • openEuler普通用户su root时Permission denied
  • 视频生成技术分享
  • 深度学习技术在流体力学中的应用与实操培训【1/3理论课程2/3实操课程】
  • 408算法题leetcode--第14天
  • FastStone Capture屏幕长截图软件注册码
  • Paper 0 | Visual Instruction Tuning
  • 【PyCharm 安装与运用秘籍】Python 和 PyCharm 安装指引,看此篇保证学会(附带优质插件)。
  • 【秋招笔试题】多多排序
  • 基于GPU的Julia集应用程序
  • [产品管理-34]:什么是战略?什么是公司战略?什么是产品战略?什么是创新战略?什么是技术战略?什么是产品创新战略?
  • tauri开发软件中,使用tauri自带的api用浏览器打开指定的url链接
  • Spring Cloud 教程(一) | 认识Spring Cloud
  • iptables添加有线网卡与无线网卡桥接转发规则
  • Java语法-类和对象(上)
  • Ubuntu USB设备绑定
  • project generator 简单使用(二)之 CLion 与 AC6
  • top 使用技巧