PyThorch的自然语言处理学习(一)

监督学习范式

机器学习中的监督,或者简单的监督学习,是指将目标(被预测的内容)的ground truth用于观察(输入)的情况。
在这里插入图片描述

  • observations:观察是想要预测的东西,用x表示观察值,观察值也叫做输入。
  • targets:目标是和观察相对应的标签,通常是要被预测的事情,用y表示,也被称为ground truth。
  • model:模型是一个数学表达式或者函数,受到一个观察值x,并预测其目标标签的值。
  • parameters:表示权重,参数模型,用符号w表示。
  • predictions:预测,也叫做估计,是模型在给定观测值的情况下所猜测的目标的值。
  • loss function:损失函数,预测和训练数据里的观测目标之间的距离。给定一个目标及其预测,损失函数将分配一个损失的标量实值,损失值越低则预测效果越好。2
    在这里插入图片描述

样本和目标编码

用数字表示观测值(文本),以便与机器学习算法一起使用。
在这里插入图片描述
表示文本的一种简单的方法是用数字向量进行表示。 有无数种方法可以执行这种映射/表示。

独热表示

one-hot表示是从一个零向量开始,如果单词出现在句子或文档里,则将向量里的相应条目设置为1。

对句子进行标记,忽略标点符号,并将所有的单词都用小写字母表示,就会得到一个大小为8的词汇表:{time, fruit, flies, like, a, an, arrow, banana}。所以,我们可以用一个八维的one-hot向量来表示每个单词。

短语“like a banana”的one-hot表示将是一个3×8矩阵,其中的列是8维的one-hot向量。通常还会看到“折叠”或二进制编码,其中文本/短语由词汇表长度的向量表示,用0和1表示单词的缺失或存在。“like a banana”的二进制编码是:[0,0,0,1,1,0,0,1]。

在这里插入图片描述

TF 词频表示

在这里插入图片描述

sklearn生成折叠的单热或者二进制表示

from sklearn.feature_extraction.text import CountVectorizer
import seaborn as sns

corpus =['Time flies flies like an arrow.',
'Fruit flies like a banana.']
one_hot_vectorizer =CountVectorizer(binary=True)
#binary=True则CountVectorizer不再使用术语/令牌的计数。如果文档中存在令牌,则令牌为1(如果不存在),则与令牌0的出现频率无关。因此,您将只处理二进制值。
#默认为False,一个关键词在一篇文档中可能出现n次,如果binary=True,非零的n将全部置为1,这对需要布尔值输入的离散概率模型的有用的
one_hot = one_hot_vectorizer.fit_transform(corpus).toarray()
#CountVectorizer是通过fit_transform函数将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在第i个文本下的词频。即各个词语出现的次数
x = ['a','arroe','banana','files','fruit','like','time']
sns.heatmap(one_hot, annot=True,
            cbar=False, xticklabels=True,
            yticklabels=['Sentence 1','Sentence 2'])

在这里插入图片描述

IDF

考虑一组专利文件。您可能希望它们中的大多数都有诸如claim、system、method、procedure等单词,并且经常重复多次。TF表示对更频繁的单词进行加权。然而,像“claim”这样的常用词并不能增加我们对具体专利的理解。
相反,如果“tetrafluoroethylene”这样罕见的词出现的频率较低,但很可能表明专利文件的性质,我们希望在我们的表述中赋予它更大的权重。

在这里插入图片描述

TF-IDF

TF-IDF = TF*IDF
TF−IDF公式表达来一次词的出现频率,并且在一定程度上降低了某些高频词的影响。

如果一个单词在所有文档里都出现,那这个单词IDF=0,则TF-IDF=0,从而可以忽略它的重要性。如果一个词在文档里出现的很少,那么其IDF值将会是最大值logN。

from sklearn.feature_extraction.text import TfidfVectorizer
import seaborn as sns
tfidf_vectorizer = TfidfVectorizer()
tfidf = tfidf_vectorizer.fit_transform(corpus).toarray()
#计算文档里的词的TF-IDF并矩阵表示
x2 = ['a','arroe','banana','files','fruit','like','time']
sns.heatmap(tfidf,annot=True,
            cbar=False,xticklabels=x2,
           yticklabels=['Sentence 1','Sentence 2'])

在这里插入图片描述

计算图

计算图的数据结构可以方便的实现数据流
**计算图是对数学表达式建模的抽象。**在深度学习的上下文中,计算图的实现(如Theano、TensorFlow和PyTorch)进行了额外的记录(bookkeeping),以实现在监督学习范式中训练期间获取参数梯度所需的自动微分。我们将在“PyTorch基础知识”中进一步探讨这一点。推理(或预测)就是简单的表达式求值(计算图上的正向流)。让我们看看计算图如何建模表达式。考虑表达式:y=wx+b

这可以写成两个子表达式z = wx和y = z + b,然后我们可以用一个有向无环图(DAG)表示原始表达式,其中的节点是乘法和加法等数学运算。操作的输入是节点的传入边,操作的输出是传出边。因此,对于表达式y = wx + b,计算图如图1-6所示。在下一节中,我们将看到PyTorch如何让我们以一种直观的方式创建计算图形,以及它如何让我们计算梯度,而无需考虑任何记录(bookkeeping)。

在这里插入图片描述

PyThorch基础

PyTorch是一个开源、社区驱动的深度学习框架。PyTorch实现了一种“tape-based automatic differentiation”方法,允许我们动态定义和执行计算图形。动态计算图在建模NLP任务的时候特别有用,每个输入可能导致不同的图结构。

PyTorch是一个优化的张量操作库,它提供了一系列用于深度学习的包。这个库的核心是张量,它是一个包含一些多维数据的数学对象。 0阶张量就是一个数字,或者标量。一阶张量(一阶张量)是一个数字数组,或者说是一个向量。二阶张量是一个向量数组,或者说是一个矩阵。因此,张量可以推广为标量的n维数组。

1、创建张量
def describe(x):
    print("Type: {}".format(x.type()))
    print("Shape/size: {}".format(x.shape))
    print("Values: \n{}".format(x))
import torch
describe(torch.Tensor(2,3))#通过制定一个随机张量的维数来初始化
#Type: torch.FloatTensor
#Shape/size: torch.Size([2, 3])
#Values: 
#tensor([[2.7553e+12, 7.5338e+28, 1.3556e-19],
#        [6.4600e+19, 2.8175e+20, 1.8490e+20]])

describe(torch.rand(2,3)) #利用均与分布随机初始化张量
describe(torch.randn(2,3))#利用标准正太分布随机初始化向量

创建张量,所有张量都用相同的标量填充。对于创建0或1张量,我们有内置函数,对于填充特定值。
在这里插入图片描述
从列表里进行初始化张量


x2 = torch.Tensor([[1,2,3],[4,5,6]])
describe(x2)
x2 = torch.Tensor([[1,2,3],[4,5,6]])
describe(x2)
#Type: torch.FloatTensor
#Shape/size: torch.Size([2, 3])
#Values: 
#tensor([[1., 2., 3.],
#        [4., 5., 6.]])

numpy创建张量

import torch 
import numpy as np
npy = np.random.rand(2,3)
describe(torch.from_numpy(npy))
2、张量类型和大小

使用torch.Tensor构造函数的时候默认张量的类型是torch.FloatTensor,在初始化之后可以使用强制类型转换。两种方法可以实现初始化类型:

  1. 直接通过构造函数制定张量类型(如FloatTensor()或LongTensor())
  2. 使用特殊方法torch.tensor()的dtype
x = torch.FloatTensor([[1,2,3],[4,5,6]])
describe(x)
#Type: torch.FloatTensor
xx = x.long()
describe(xx)
#Type: torch.LongTensor
x3 = torch.tensor([[1,2,3],[4,5,6]],dtype = torch.int64)
describe(x3)
#Type: torch.LongTensor
3、张量操作

利用函数、符号操作符等处理张量

x4 = torch.Tensor(2,3)
describe(torch.add(x,x))
describe(x+x)

行列操作

x5 = torch.arange(6)
x6 = x5.view(2,3)
describe(x6)
describe(torch.sum(x6,dim=0))
#Type: torch.LongTensor
#Shape/size: torch.Size([3])
#Values: 
#tensor([3, 5, 7])
describe(torch.sum(x6,dim=1))
#Type: torch.LongTensor
#Shape/size: torch.Size([2])
#Values: 
#tensor([ 3, 12])
describe(torch.transpose(x6,0,1))
#Type: torch.LongTensor
#Shape/size: torch.Size([3, 2])
#Values: 
#tensor([[0, 3],
#        [1, 4],
#        [2, 5]])
4、索引、切片、连接

切片即索引一个张量

x7  = torch.arange(6).view(2,3)
describe(x7[:1,:2])
#Type: torch.LongTensor
#Shape/size: torch.Size([1, 2])
#Values: 
#tensor([[0, 1]])
describe(x7[0,1])
#Type: torch.LongTensor
#Shape/size: torch.Size([])
#Values: 1

复杂索引:张量的非连续索引

torch.index_select(input, dim, index, out=None)
函数返回的是沿着输入张量的指定维度的指定索引号进行索引的张量子集,其中输入张量、指定维度和指定索引号就是
torch.index_select(input, dim, index, out=None) 函数的三个关键参数,函数参数有:

input(Tensor) - 需要进行索引操作的输入张量; dim(int) - 需要对输入张量进行索引的维度;
index(LongTensor) - 包含索引号的 1D 张量; out(Tensor, optional) - 指定输出的张量。比如执行
torch.zeros([2, 2], out = tensor_a),相当于执行 tensor_a = torch.zeros([2,
2]);


# 创建1D张量
a = torch.arange(0, 9)
print(a)
# 获取1D张量的第1个维度且索引号为2和3的张量子集
print(torch.index_select(a, dim = 0, index = torch.tensor([2, 3])))# 创建2D张量
b = torch.arange(0, 9).view([3, 3])
print(b)
# 获取2D张量的第2个维度且索引号为0和1的张量子集(第一列和第二列)
print(torch.index_select(b, dim = 1, index = torch.tensor([0, 1])))# 创建3D张量
c = torch.arange(0, 9).view([1, 3, 3])
print(c)
# 获取3D张量的第1个维度且索引号为0的张量子集
print(torch.index_select(c, dim = 0, index = torch.tensor([0])))'''
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])
tensor([2, 3])
tensor([[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]])
tensor([[0, 1],
        [3, 4],
        [6, 7]])
tensor([[[0, 1, 2],
         [3, 4, 5],
         [6, 7, 8]]])
tensor([[[0, 1, 2],
         [3, 4, 5],
         [6, 7, 8]]])
'''

连接张量

x8 = torch.arange(6).view(2,3)
describe(torch.cat([x8,x8],dim=0))
describe(torch.cat([x8,x8].dim=1))
#Values: 
#tensor([[1., 2., 3.],
#        [4., 5., 6.],
#        [1., 2., 3.],
#        [4., 5., 6.]])
describe(torch.stack([x8,x8]))
#Type: torch.FloatTensor
#Shape/size: torch.Size([2, 2, 3])
#Values: 
#tensor([[[1., 2., 3.],
#         [4., 5., 6.]],

#        [[1., 2., 3.],
#         [4., 5., 6.]]])
5、张量的线性代数

张量可以做线性代数运算,乘法、逆、迹运算等。

xx = torch.ones(3,2)
xx[:,1] += 1
xx
#tensor([[1., 2.],
#        [1., 2.],
#        [1., 2.]])
describe(torch.mm(x,xx))
#Type: torch.FloatTensor
#Shape/size: torch.Size([2, 2])
#Values: tensor([[ 6., 12.],[15., 30.]])
6、张量和计算梯度

当张量的requires_grad布尔值被设置为真,可以追踪梯度张量以及梯度函数。
利用requires_grad=True创建张量时,需要PyTorch来管理计算梯度的bookkeeping信息。首先,PyTorch将跟踪向前传递的值。然后,在计算结束时,使用单个标量来计算向后传递。反向传递是通过对一个张量使用backward()方法来初始化的,这个张量是由一个损失函数的求值得到的。向后传递为参与向前传递的张量对象计算梯度值。

x9 = torch.ones(2,2,requires_grad = True)
print(x.grad is None) #True
y = (x+2)*(x+5)+3
describe(y)
#Type: torch.FloatTensor
#Shape/size: torch.Size([2, 3])
#Values: 
#tensor([[21., 31., 43.],[57., 73., 91.]])
z = y.mean()
describe(z)
#Type: torch.FloatTensor
#Shape/size: torch.Size([])
#Values: 52.66666793823242
z.backword()

GPU访问

要利用GPU,首先需要分配GPU内存上的张量。对gpu的访问是通过一个名为CUDA的专门API进行的。CUDA API是由NVIDIA创建的,并且仅限于在NVIDIA gpu上使用。PyTorch提供的CUDA张量对象在使用中与常规cpu绑定张量没有区别,除了内部分配的方式不同。

PyTorch使创建这些CUDA张量变得非常容易(示例1-16),它将张量从CPU传输到GPU,同时维护其底层类型。

PyTorch中的首选方法是与设备无关,并编写在GPU或CPU上都能工作的代码。在下面的代码片段中,我们首先使用torch.cuda.is_available()检查GPU是否可用,然后使用torch.device检索设备名。然后,将实例化所有未来的张量,并使用.to(device)方法将其移动到目标设备。

import torch
print(torch.cuda.is_available())#True
device = torch.device("cuda"if torch.cuda.is_available()else"cpu")
print(device)#cuda
xc = torch.rand(3,3).to(device)
describe(xc)
#Type: torch.cuda.FloatTensor
#Shape/size: torch.Size([3, 3])
#Values: 
#tensor([[0.1233, 0.5033, 0.4846],
#        [0.4023, 0.8022, 0.6756],
#        [0.9225, 0.3256, 0.1320]], #device='cuda:0')

要对CUDA和非CUDA对象进行操作,我们需要确保它们在同一设备上。如果我们不这样做,计算就会中断。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值