IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 词嵌入(Word Embedding)原理详解 -> 正文阅读

[人工智能]词嵌入(Word Embedding)原理详解

? 词嵌入模型是自然语言处理(NLP)中语言模型与表征学习技术的统称。在自然语言处理过程中,我们需要将单词(word)映射到对应的向量,从而能够用于模型训练。通常情况下可以使用one-hot向量来表示单词,但是one-hot向量长度为单词表所有单词的个数,数量过于庞大,并且各个单词之间相似度为0,这与我们日常生活是很不符的(不同的单词之间可能会比较相近,在文本中经常在一起出现;也可能不相近,在文本距离较远)。所以选择新的方法来表示单词便显得尤为重要。

? 对于上述问题,可以用词嵌入的方法来解决。使用词嵌入的基本思路是:先用one-hot编码等方法来标记单词,然后构建一个包含embedding层的神经网络,模型的输入和输出一般为在文本中位置相近的单词one-hot向量。训练完成中,将单词one-hot向量输入到embedding中,embedding的输出向量即为该单词的新的嵌入表示。这些向量一般情况下远远小于one-hot向量长度,并且可以用于度量各个单词之间的相似与类比关系。

一:基本原理

? 兔兔先以下面的一个文本为例:

“rabbit?are very lovely animals, and we should not hurt them? ”

? 对于这样的文本,它包含11种单词,所以把单词按一定顺序排列,则每个单词可以由长度为11的向量表示。

? 若单词表:[rabbit,are,very,lovely,animals,and,we,should,not,hurt,them],此时rabbit的one-hot表示为[1,0,0,0,0,0,0,0,0,0,0]

? 之后,我们需要构造一个模型,以文本中相邻的单词为模型输入与输出来进行训练。然而,模型的输入与输出需要固定个数。在这里,兔兔引入Word2vec中常用的两种模型:跳词模型与连续词袋模型。

1.跳词模型

? 跳词模型,它是通过文本中某个单词来推测前后几个单词。例如,根据‘rabbit’来推断前后的单词可能为‘a’,'is','eating','carrot'。在训练模型时我们在文本中选取若干连续的固定长度的单词序列,把前后的一些单词作为输出,中间的某个位置的单词作为输入。

2.连续词袋模型

? 连续词袋模型与跳词模型恰好相反,它是根据文本序列中周围单词来预测中心词。在训练模型时,把序列中周围单词作为输入,中心词作为输出。

? 对于词嵌入,emdedding层是模型的核心部分,它一般在整个网络第一层。在Pytorch中有专门的nn.embedding层来实现该部分,但实际上,embedding层的结构可以非常多样,最简单的使用仅仅一层全连接层也是可行的,embedding层理论上也可以是一个层数很多的网络。训练结束后,把某个单词的one-hots输入到embedding,embedding的输出为该单词嵌入表示。(embedding在训练时输入单词数固定,但是预测时可以输入一个单词,也可以接受多个单词输入,这也说明embedding结构较为特殊,在后面兔兔会详细讲述)

二:方法实现

? 兔兔在下面案例中使用连续词袋模型,每次从文本中选取序列长度为9,输入单词数为,8,输出单词数为1,中心词位于序列中间位置。并且采用pytorch中的emdedding和自己设计embedding两种方法,词嵌入维度为50。文本节选自《The Tale Of Peter Rabbit》(彼得兔的故事),本文词总数:793,词汇数:401,需要的同学可以在资源中下载。

? 对于文本数据,我们不考虑文本中标点符号,为了避免同一单词大小写不同的差异,一律将单词转成小写。

文本数据处理部分:

import torch
import re
import numpy as np

txt=[] #文本数据
with open('peter_rabbit.txt',encoding='utf-8') as f:
    for line in f.readlines():
        l=line.strip()
        spilted_sentence=re.split(" |;|-|,|!|\'",l)
        for w in spilted_sentence:
            if w !='':
                txt.append(w.lower())
vol=list(set(txt)) #单词表
n=len(vol) #单词表单词数
vol_dict=dict(zip(vol,np.arange(n))) #单词索引

data=[]
label=[]

for i in range(784):
    in_words=txt[i:i+4]
    in_words.extend(txt[i+6:i+10])
    out_word=txt[i+5]
    in_one_hot=np.zeros((8,n))
    out_one_hot=np.zeros((1,n))
    out_one_hot[0,vol_dict[out_word]]=1
    for j in range(8):
        in_one_hot[j,vol_dict[in_words[j]]]=1
    data.append(in_one_hot)
    label.append(out_one_hot)

class dataset:
    def __init__(self):
        self.n=784 #训练样本数
    def __len__(self):
        return self.n
    def __getitem__(self, item):
        traindata=torch.tensor(np.array(data),dtype=torch.float32) #运行model1此处用long,model2用float32.
        trainlabel=torch.tensor(np.array(label),dtype=torch.float32)
        return traindata[item],trainlabel[item]

? 这部分代码兔兔保存在dataset.py文件下,它将原始文本进行拆分并以一定顺序拆成需要训练的输入数据(data)与输出数据(label),并以one-hot表示。

1.使用nn.Embedding构建模型

? 对于nn.Embedding(),至少需要两个参数:num_embeddings与embedding_dim,表示词汇表大小与词嵌入维度。在这里参数为(401,50)。

? 理论上说,nn.Embedding应该类似于一个输入维度为词汇表长度、输出为词嵌入维度的全连接层。我们可以通过以下方法验证。

embed=nn.Embedding(401,200)
print(list(embed.parameters())[0].data)
print(list(embed.parameters())[0].data.shape)

? 最终的参数的确表明它是一个单层的全连接网络。与普通全连接网络不同的是:它的每个神经元输入是一个词向量而不是数,这样它的输入维度可以是[batch_size,num_input_word,one_hot_dim]。所以它更像是共享相同参数的num_word个平行的全连接层,类似于卷积神经网络中的通道channel。所以embedding层输出的维度[batch,num_input_word,embed_dim]。将这个输入下一个全连接层时,需要改变embedding输出数据维度。该部分代码保存在model1.py中。

import torch
from torch import nn
from torch.utils.data import DataLoader
from dataset import dataset

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.embed=nn.Embedding(401,50)
        self.fc1=nn.Linear(160400,100)
        self.act1=nn.ReLU()
        self.fc2=nn.Linear(100,401*1)
        self.act2=nn.Sigmoid()
    def forward(self,input):
        b,_,_=input.shape
        out=self.embed(input).view(b,1,-1)
        out=self.fc1(out)
        out=self.act1(out)
        out=self.fc2(out)
        out=self.act2(out)
        return out
if __name__=='__main__':
    model=model()
    optim=torch.optim.Adam(params=model.parameters())
    Loss=nn.MSELoss()
    traindata=DataLoader(dataset(),batch_size=5,shuffle=True)
    for i in range(100):
        print('the {} epoch'.format(i))
        for d in traindata:
            yp=model(d[0])
            loss=Loss(yp,d[1])
            optim.zero_grad()
            loss.backward()
            optim.step()
    torch.save(model,'model_1.pkl')

2.自己构造embedding

? 兔兔这里定义了一个含有层数为2的全连接层为embedding层,方法与前面embedding的效果相近。该部分代码保存在model2.py中。

import torch
from torch import nn
from torch.utils.data import DataLoader
from dataset import dataset
import numpy as np
class embedding(nn.Module):
    def __init__(self,in_dim,embed_dim):
        super().__init__()
        self.embed=nn.Sequential(nn.Linear(in_dim,200),
                                 nn.ReLU(),
                                 nn.Linear(200,embed_dim),
                                 nn.Sigmoid())
    def forward(self,input):
        b,c,_=input.shape
        output=[]
        for i in range(c):
            out=self.embed(input[:,i])
            output.append(out.detach().numpy())
        return torch.tensor(np.array(output),dtype=torch.float32).permute(1,0,2)


class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.embed=embedding(401,50)
        self.fc1=nn.Linear(400,4000)
        self.act1=nn.ReLU()
        self.fc2=nn.Linear(4000,401*1)
        self.act2=nn.Sigmoid()
    def forward(self,input):
        b,_,_=input.shape
        out=self.embed (input).reshape(b,-1)
        out=self.fc1 (out)
        out=self.act1(out)
        out=self.fc2(out)
        out=self.act2(out)
        out=out.view(b,1,-1)
        return out
if __name__=='__main__':
    model=model()
    optim=torch.optim.Adam(params=model.parameters())
    Loss=nn.MSELoss()
    traindata=DataLoader(dataset(),batch_size=5,shuffle=True)
    for i in range(100):
        print('the {} epoch'.format(i))
        for d in traindata:
            yp=model(d[0])
            loss=Loss(yp,d[1])
            optim.zero_grad()
            loss.backward()
            optim.step()
    torch.save(model,'model_2.pkl')

三:总结

? 词嵌入模型作为自然语言处理的一种方法,其种类广泛,并且不局限于兔兔本文讲述的方法。而这些词嵌入方法的思想基本大致相同。从本质上来说,词嵌入与自编码器有诸多相似之处,它都是将数据维度降低,并且通常以更加合理的方式来表示数据,在实际应用总,这类方法对于深度学习模型的训练及优化具有重要意义。

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 20:57:15  更:2022-09-24 20:57:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:49:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码