打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
pytorch深度学习和自然语言处理入门

之前也提过,pytorch之于tensorflow,优雅不是一星半点。

pytorch学习是轻松愉快了。本期文章写pytorch在nlp上的应用。(paul allen的allennlp也由tensorflow迁移到了pytorch平台,可见一斑)

导入模块:

import torch

import torch.autograd as autograd

import torch.nn as nn

import torch.nn.functional as F

import torch.optim as optim

torch.manual_seed(1)

一、线性模块,这里需要注意是y =  xw+b。不是我们数学上习惯的y=wx+b(矩阵是不满足乘法交换率的)

定义一个全连接层,也就是线性仿射变换。W=(5,3),b=(3)

lin =  nn.Linear(5,3)

这里需要特别注意,输入变量是n*5,输出为n*3

data = autograd.Variable(torch.randn(2,5))

lin(data)

运算得到结果如下:

Variable containing:
-0.2889  0.3574  0.6554
-0.9682  0.0289  0.4426
[torch.FloatTensor of size 2x3]

二、非线性激活函数

常用的Relu和tanh。sigmoid因为梯度消失的问题,反而不常用。从理论上讲,非线性的激活函数可以无穷多,为什么选这两个?这是工程上的问题,因为它们的导数形式便于计算

我们用随机正态分布,初始化2*2的矩阵。

data = autograd.Variable(torch.randn(2,2))

Variable containing:
-0.6331  0.8795
-0.6842  0.4533
[torch.FloatTensor of size 2x2]

把变量经由relu计算(Rectified Linear Unit,修正线性单元),relu的公式很简单=max(0,x),就是如果x>0,就取x,否则取0,就是把负的信号给屏蔽了。

F.relu(data)

Variable containing:
 0.0000  0.8795
 0.0000  0.4533
[torch.FloatTensor of size 2x2]
下图的蓝线是relu

对比sigmoid类函数主要变化是:

1)单侧抑制

 2)相对宽阔的兴奋边界 

3)稀疏激活性。

这与人的神经皮层的工作原理接近。

另外一个很重要的激活函数就是softmax。

data = autograd.Variable(torch.randn(2,2))

Variable containing:
-0.3968 -0.6571
-1.6428  0.9803
[torch.FloatTensor of size 2x2]

F.softmax(data,dim=0),dim=0,按第0维softmax,就是概率化。这个函数在输出层很有用,比如mnist要分成10类,那softmax就是这10类对应的概率。概率最大者就是对应的分类。(概率思维也在这里体现了)

Variable containing:
 0.7766  0.1628
 0.2234  0.8372
[torch.FloatTensor of size 2x2]

还有一个类似的函数F.log_softmax()也是工程上的考虑,因为最小二乘损失函数求导要会带来计算量的问题,所以考虑交叉熵损失。与之配合的就是这个对数softmax

三、目标函数。也就是反身传播要优化的目标。也称为成本函数或损失函数。

四,词袋模型(Bag-Of-Words=BOW),应该算最简单的语言模型,不考虑词的位置,就是数数。比如词汇表如果就两个词,hello,world。那么"hello hello hello hello" = [4,0],'hello world hello world'=[2,2],即所谓语言模型,就是对一个字符串,或文章内容,如何进行编码,转为计算机和pytorch可以处理的向量或矩阵类型。这里的数字就是表达词的出现次数

用这个最简单的BOW,来对西班牙语和英语做分类。

先定义最简单的训练语料和测试语料。

data = [ ("me gusta comer en la cafeteria".split(), "SPANISH"),
         ("Give it to me".split(), "ENGLISH"),
         ("No creo que sea una buena idea".split(), "SPANISH"),
         ("No it is not a good idea to get lost at sea".split(), "ENGLISH") ]

test_data = [ ("Yo creo que si".split(), "SPANISH"), ("it is lost on me".split(), "ENGLISH")]

把词下标化,计算机其实不会真的去管这个词是什么东西,有什么语义。现代统计语言模型或深度学习,确实没有管单词本身具有什么意思,而是“统计”它们出现的位置,频率,前后关系等。就已经解决了很多问题。(语义的环境,应该得交由知识图谱)

首选把词汇表单词下标算出来。

word_2_idx = {}

for sent,_ in data + test_data:

    print(sent)

    for word in sent:

        if word not in word_2_idx:

        #这里用的是这个word首次出现的位置,比如me就是第1个出现的,下标为0

            word_2_idx[word] =  len(word_2_idx)

有了词汇表,就可以算词汇表的长度,以及我们需要把句子分成两类。

VOCAB_SIZE = len(word_2_idx)

NUM_LABELS = 2

神经网络模型:

class BoWClassifier(nn.Module): # 从nn.Module继承bow分类器

    def __init__(self, num_labels, vocab_size):

        #父类初始化

        super(BoWClassifier, self).__init__()

        self.linear = nn.Linear(vocab_size, num_labels)

    def forward(self, bow_vec):

        #bow_vec是词的bow向量

        return F.log_softmax(self.linear(bow_vec))

把句子变成向量:

就是用句子里的词,去词汇表里查下标,在向量对应的位置加1

def make_bow_vector(sentence, word_to_ix):

    vec = torch.zeros(len(word_to_ix))

    for word in sentence:

        vec[word_to_ix[word]] += 1

    #vec本来是个向量,变形成1*N的矩阵

    return vec.view(1, -1)

make_bow_vector("Give it to me".split(),word_2_idx)

在用户手动定义Variable时,参数requires_grad默认值是False。而在Module中的层在定义时,相关Variable的requires_grad参数默认是True。 
在计算图中,如果有一个输入的requires_grad是True,那么输出的requires_grad也是True。只有在所有输入的requires_grad都为False时,输出的requires_grad才为False。

关于作者:魏佳斌,互联网产品/技术总监,北京大学光华管理学院(MBA),特许金融分析师(CFA),资深产品经理/码农。偏爱python,深度关注互联网趋势,人工智能,AI金融量化。致力于使用最前沿的认知技术去理解这个复杂的世界。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
PyTorch专栏(十七): 使用PyTorch进行深度学习
四天速成!香港科技大学 PyTorch 课件分享
给训练踩踩油门:编写高效的PyTorch代码技巧
Pytorch中交叉熵Loss趣解
Pytorch 常用损失函数拆解
深度学习之PyTorch实战(2)——神经网络模型搭建和参数优化
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服