one-hot 编码 缺点:
词越多 向量越多 且向量中只有为1起到了训练的作用
传统NLP特征工程的缺点 (使用one-hot)
词典有多长向量就多长 维度高
太稀疏 没有起到训练作用的0太多
语义鸿沟
3. 深度学习中NLP的特征输入
深度学习使用分布式单词表示技术(也称词嵌入表示),通过查看所使用的单词的周围单词(即上下文)
来学习单词表示。这种表示方式将词表示为一个粘稠的序列,在保留词上下文信息同时,避免维度过大
导致的计算困难。
特征嵌入(Feature Embedding) 稠密编码
特征嵌入,也成为词嵌入,是稠密编码的一种表现形式,目的是将离散的类别、对象或其他类型的特
征映射到一个连续的向量空间。通过这种方式,嵌入后的向量可以捕捉不同特征之间的语义关系,并且
便于在后续的机器学习模型中使用。
特点:
低维度:相比稀疏表示(如独热编码),稠密编码的维度更低,能够减少计算和存储成本。
语义相似性:嵌入向量之间的距离(如欧氏距离或余弦相似度)可以表示这些对象之间的语义相似
性。
可微学习:嵌入表示通常通过神经网络进行学习,并且通过反向传播算法进行优化。
清理好的文本 进行one-hot编码 然后 在进行矩阵映射 变成稠密的 然后可以通道映射后的矩阵和映射方式找到原来的one-hot编码
随机一个矩阵 mXn one-hot编码去乘这个矩阵 有多少个词 m就为多少 n是你自己设置的每一个词有多少个特征维度
import jieba
import torch
from torch import nn
from torch import optim
def demo1():
t="这样可以使模型更加的关注那些在某篇文档中特别重要但不常见的词"
l_=jieba.lcut(t)
print(l)
l=set(l_) # 词去重
print(len(l))
构建此表
index_word={}
word_index={}
for index,word in enumerate(l):
index_word[index]=word
word_index[word]=index
print(index_word)
print(word_index)
使用nn建立词嵌入层 传入词的种类数 和 每个词的特征维度
embedding=nn.Embedding(len(word_index),embedding_dim=4)
print(embedding)
向词嵌入层传入下标 它为每一个下标生成一个对应的特征张量
下标必须转为张量
一个个的传
这里传的是没有去重的 词 获得没有去重的词组的下标
for word in l_:
word_f_tensor=embedding(torch.tensor(word_index[word]))
print(word,"---",word_f_tensor)
直接传下标数组
index_list=[]
for word in l_:
index_list.append(word_index[word])
word_f_tensor_list=embedding(torch.tensor(index_list))
print(word_f_tensor_list)
def demo2():
练习
假设现在有语料库sentences = ["i like dog", "i love coffee", "i hate milk", "i do nlp"] 通过词嵌入层算法
和NNLM模型得到以下结果
[['i', 'like'], ['i', 'love'], ['i', 'hate'], ['i', 'do']] -> ['dog', 'coffee', 'milk', 'nlp']
sentences = ["i like dog", "i love coffee", "i hate milk", "i do nlp"]
创建去重后的对词表
word=" ".join(sentences)
word=word.split(" ")
print(word)
word_unique=set(word)
print(word_unique)
index_word={}
word_index={}
for index,word in enumerate(word_unique):
index_word[index]=word
word_index[word]=index
print(index_word)
print(word_index)
创建训练集数据 分为特征和目标 x,y
feature=[]
target=[]
for sentence in sentences:
feature.append(sentence.split(" ")[:-1])
target.append(sentence.split(" ")[-1])
feature_tensor=[]
for el in feature:
feature_tensor.append([word_index[word] for word in el])
feature_tensor=torch.tensor(feature_tensor)
target_tensor=torch.tensor([word_index[el] for el in target])
print(feature_tensor)
print(target_tensor)
创建模型
n_class=len(index_word)
n_step=len(feature[0]) # 一个批次里面有几个词
batch_size=len(feature)
class NNLM(nn.Module):
def init(self,n_class,m,n_step):
super().init()
嵌入层 传入种类数和每个词的特征数\
self.batch_size=batch_size
self.embed=nn.Embedding(n_class,m)
self.liner1=nn.Linear(n_step*m,128)
self.liner2=nn.Linear(128,n_class)
self.action=nn.Tanh()
def forward(self,x):
x=self.embed(x)
x=x.view(x.shape[0],-1)
x=self.liner1(x)
x=self.action(x)
x=self.liner2(x)
return x
模型
model1=NNLM(n_class,3,n_step)
优化器
opt1=optim.Adam(model1.parameters(),lr=0.001)
清梯度
opt1.zero_grad()
损失函数 前向传播
loss_func=nn.CrossEntropyLoss()
y_pre= model1.forward(feature_tensor)
loss=loss_func(y_pre,target_tensor)
反向传播和梯度更新
loss.backward()
opt1.step()
res=model1(feature_tensor[1].unsqueeze(0))
print(torch.max(res,1))
def demo3():
word2vec 是一个用来生成词向量的模型
word2vec一般分为CBOW(Continuous Bag-of-Words)与 Skip-Gram 两种模型:
1、CBOW:根据中心词周围的词来预测中心词,有negative sample和Huffman两种加速算法; 上下文信息 知道周围词找中心词
2、Skip-Gram:根据中心词来预测周围词;
pass
if name=="main":
demo1()
demo2()