当前位置:   article > 正文

pytorch学习(一)_torch.empty

torch.empty

1.torch

Torch是一个与Numpy类似的张量(Tensor)操作库,与Numpy不同的是Torch对GPU支持的很好,Lua是Torch的上层包装。

PyTorch和Torch使用包含所有相同性能的C库:TH, THC, THNN, THCUNN,并且它们将继续共享这些库。

这样的回答就很明确了,其实PyTorch和Torch都使用的是相同的底层,只是使用了不同的上层包装语言。

注:LUA虽然快,但是太小众了,所以才会有PyTorch的出现。

PyTorch是一个基于Torch的Python开源机器学习库,用于自然语言处理等应用程序。 它主要由Facebook的人工智能研究小组开发。Uber的"Pyro"也是使用的这个库。

PyTorch是一个Python包,提供两个高级功能:

  • 具有强大的GPU加速的张量计算(如NumPy)
  • 包含自动求导系统的的深度神经网络

2.PyTorch 深度学习:60分钟快速入门 (官方)

torch — PyTorch 1.11.0 documentation

pytorch api

2.1张量

1.from __future__ import print_function

该句语句是python2的概念,那么python3对于python2就是future了,也就是说,在python2的环境下,超前使用python3的print函数。

 所以以后看到这个句子的时候,不用害怕,只是把下一个新版本的特性导入到当前版本!

2.x = torch.empty(5, 3)  创建一个 5x3 矩阵, 但是未初始化:

 根据现有的张量创建张量。 这些方法将重用输入张量的属性,例如, dtype,除非设置新的值进行覆盖

x = x.new_ones(5, 3, dtype=torch.double) # new_* 方法来创建对象

print(x)

x = torch.randn_like(x, dtype=torch.float) # 覆盖 dtype!

print(x)

3. 使用size方法与Numpy的shape属性返回的相同,张量也支持shape属性

4.在python中,tuple元组这种数据结构同列表类似,都可以描述一组数据的集合,它们都是容器,是一系列组合的对象,不同的地方在于,元组里的元素是不能更改的,它们之间的差异性我们用一个例子来说明一下:

列表:

>>>find_files("*.txt")

["file1.txt","file2.txt","file3.txt","file4.txt"]

元组:

>>> student=(1,"tom","2008-05-06",10,135.7)

>>> print(student[1]) #输出 tom

从上面的比较例子可以看出,列表一般用于不确定个数的数据的集合中,例如上面,并不知道能找到多少个txt文件,所以用列表来表示,而元组一般用于描述一个东西的特性,例如上面的例子,描述了一个学生的学号、姓名、出生年月、年龄和身高,下面我们具体来学习元组这种数据类型;

5.加法运算

法一:y = torch.rand(5, 3)         

          print(x + y)

法二:print(torch.add(x, y))

法三:提供输出tensor作为参数

           result = torch.empty(5, 3)

           torch.add(x, y, out=result)

           print(result)

法四:y.add_(x)

           print(y)

任何 以``_`` 结尾的操作都会用结果替换原变量. 例如: ``x.copy_(y)``, ``x.t_()``, 都会改变 ``x``.

6.torch.view: 可以改变张量的维度和大小,与Numpy的reshape类似

x = torch.randn(4, 4)

y = x.view(16)#变一维数组

z = x.view(-1, 8) # size -1 从其他维度推断,这里变为8列(8,-1)变为8行

print(x.size(), y.size(), z.size())

torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

7.如果你有只有一个元素的张量,使用.item()来得到Python数据类型的数值

 8.Torch Tensor和NumPy数组转换

Torch Tensor与NumPy数组共享底层内存地址,修改一个会导致另一个的变化。

(1)将一个Torch Tensor转换为NumPy数组

b = a.numpy()

print(b)

[1. 1. 1. 1. 1.]

a.add_(1)

print(a) print(b)

 (2)NumPy Array 转化成 Torch Tensor,使用from_numpy自动转化

b = torch.from_numpy(a)

np.add(a, 1, out=a)

print(a) print(b)

9.所有的 Tensor 类型默认都是基于CPU, CharTensor 类型不支持到 NumPy 的转换. CUDA 张量

使用.to 方法 可以将Tensor移动到任何设备中

  1. # is_available 函数判断是否有cuda可以使用
  2. # ``torch.device``将张量移动到指定的设备中
  3. if torch.cuda.is_available():
  4. device = torch.device("cuda") # a CUDA 设备对象
  5. y = torch.ones_like(x, device=device) # 直接从GPU创建张量
  6. x = x.to(device) # 或者直接使用``.to("cuda")``将张量移动到cuda中
  7. z = x + y
  8. print(z)
  9. print(z.to("cpu", torch.double)) # ``.to`` 也会对变量的类型做更改
tensor([0.7632], device='cuda:0')
tensor([0.7632], dtype=torch.float64)

2.2Autograd: 自动求导机制

PyTorch 中所有神经网络的核心是 autograd 包。torch.Tensor是这个包的核心类。

如果设置 .requires_grad 为 True,那么将会追踪所有对于该张量的操作。 当完成计算后通过调用 .backward()自动计算所有的梯度, 这个张量的所有梯度将会自动积累到 .grad 属性

阻止张量跟踪历史记录,可以调用.detach()方法将其与计算历史记录分离,并禁止跟踪它将来的计算记录。

为了防止跟踪历史记录(和使用内存),可以将代码块包装在with torch.no_grad():中。 在评估模型时特别有用,因为模型可能具有requires_grad = True的可训练参数,但是我们不需要梯度计算

在自动梯度计算中还有另外一个重要的类Function.

Tensor 和 Function互相连接并生成一个非循环图,它表示和存储了完整的计算历史每个张量都有一个.grad_fn属性,这个属性引用了一个创建了TensorFunction(除非这个张量是用户手动创建的,即,这个张量的 grad_fn 是 None)。

如果需要计算导数,你可以在Tensor上调用.backward()。 如果Tensor是一个标量(即它包含一个元素数据)则不需要为backward()指定任何参数, 但是如果它有更多的元素,你需要指定一个gradient 参数来匹配张量的形状

1.创建一个张量并设置 requires_grad=True 用来追踪他的计算历史

对张量进行操作:

结果y已经被计算出来了,所以,grad_fn已经被自动生成了。

 

 

 .requires_grad_( ... ) 可以改变现有张量的 requires_grad属性。 如果没有指定的话,默认输入的flag是 False

2.梯度

反向传播 因为 out是一个标量(scalar),out.backward() 等于out.backward(torch.tensor(1))

 

 一般来说,torch.autograd就是用来计算vector-Jacobian product的工具。

来看一个vector-Jacobian product的例子

 在这个情形中,y不再是个标量。torch.autograd无法直接计算出完整的雅可比行列,但是如果我们只想要vector-Jacobian product,只需将向量作为参数传入backward

..........................

2.3神经网络

神经网络的典型训练过程如下:

  1. 定义包含一些可学习的参数(或者叫权重)神经网络模型;
  2. 在数据集上迭代;
  3. 通过神经网络处理输入;
  4. 计算损失(输出结果和正确值的差值大小);
  5. 将梯度反向传播回网络的参数;
  6. 更新网络的参数,主要使用如下简单的更新原则: weight = weight - learning_rate * gradient

在模型中必须要定义 forward 函数,backward 函数(用来计算梯度)会被autograd自动创建。 可以在 forward 函数中使用任何针对 Tensor 的操作。

3.基础

torch.nn是专门为神经网络设计的模块化接口。nn构建于 Autograd之上,可用来定义和运行神经网络。

nn.functional,这个包中包含了神经网络中使用的一些常用函数,这些函数的特点是,不具有可学习的参数(如ReLU,pool,DropOut等),这些函数可以放在构造函数中,也可以不放,但是这里建议不放。

3.1定义一个网络

PyTorch中已经为我们准备好了现成的网络模型,只要继承nn.Module,并实现它的forward方法,PyTorch会根据autograd,自动实现backward函数,在forward函数中可使用任何tensor支持的函数,还可以使用if、for循环、print、log等Python语法,写法和标准的Python写法一致。

class Net(nn.Module):
    def __init__(self):
        # nn.Module子类的函数必须在构造函数中执行父类的构造函数
        super(Net, self).__init__()

       # 卷积层 '1'表示输入图片为单通道, '6'表示输出通道数,'3'表示卷积核为3*3
        self.conv1 = nn.Conv2d(1, 6, 3)

       #线性层,输入1350个特征,输出10个特征
        self.fc1   = nn.Linear(1350, 10)  #这里的1350是如何计算的呢?这就要看后面的forward函数

         #正向传播

def forward(self, x): 
        print(x.size()) # 结果:[1, 1, 32, 32]
       
# 卷积 -> 激活 -> 池化 
        x = self.conv1(x) #根据卷积的尺寸计算公式,计算结果是30,具体计算公式后面第二章第四节 卷积神经网络 有详细介绍。
        x = F.relu(x)
        print(x.size()) # 结果:[1, 6, 30, 30]
        x = F.max_pool2d(x, (2, 2))
#我们使用池化层,计算结果是15
        x = F.relu(x)
        print(x.size()) # 结果:[1, 6, 15, 15]
        # reshape,‘-1’表示自适应
     
  #这里做的就是压扁的操作 就是把后面的[1, 6, 15, 15]压扁,变为 [1, 1350]
        x = x.view(x.size()[0], -1) 
        print(x.size()) # 这里就是fc1层的的输入1350 
        x = self.fc1(x)        
        return x

net = Net()
print(net)

网络的可学习参数通过net.parameters()返回

for parameters in net.parameters():
    print(parameters)

net.named_parameters可同时返回可学习的参数及名称。

for name,parameters in net.named_parameters():
    print(name,':',parameters.size())

forward函数的输入和输出都是Tensor

input = torch.randn(1, 1, 32, 32) # 这里的对应前面fforward的输入是32
out = net(input)
out.size()

 input.size()

 在反向传播前,先要将所有参数的梯度清零

net.zero_grad() 
out.backward(torch.ones(1,10)) # 反向传播的实现是PyTorch自动实现的,我们只要调用这个函数即可

3.2损失函数

y = torch.arange(0,10).view(1,10).float()
criterion = nn.MSELoss()
loss = criterion(out, y)

#loss是个scalar,我们可以直接用item获取到他的python类型的数值
print(loss.item()) 

3.3优化器

在反向传播计算完所有参数的梯度后,还需要使用优化方法来更新网络的权重和参数,例如随机梯度下降法(SGD)的更新策略如下:

weight = weight - learning_rate * gradient

在torch.optim中实现大多数的优化方法,例如RMSProp、Adam、SGD等,下面我们使用SGD做个简单的样例

out = net(input) # 这里调用的时候会打印出我们在forword函数中打印的x的大小
criterion = nn.MSELoss()
loss = criterion(out, y)
#新建一个优化器,SGD只需要要调整的参数和学习率
optimizer = torch.optim.SGD(net.parameters(), lr = 0.01)
# 先梯度清零(与net.zero_grad()效果一样)
optimizer.zero_grad() 
loss.backward()

#更新参数
optimizer.step()

4.数据的加载和预处理

PyTorch通过torch.utils.data对一般常用的数据加载进行了封装,可以很容易地实现多线程数据预读和批量加载。 并且torchvision已经预先实现了常用图像数据集,包括前面使用过的CIFAR-10,ImageNet、COCO、MNIST、LSUN等数据集,可通过torchvision.datasets方便的调用

Dataset

Dataset是一个抽象类,为了能够方便的读取,需要将要使用的数据包装为Dataset类。 自定义的Dataset需要继承它并且实现两个成员方法:

  1. __getitem__() 该方法定义用索引(0 到 len(self))获取一条数据或一个样本
  2. __len__() 该方法返回数据集的总长度

#引用
from torch.utils.data import Dataset
import pandas as pd

  1. #定义一个数据集
  2. class BulldozerDataset(Dataset):
  3. """ 数据集演示 """
  4. def __init__(self, csv_file):
  5. """实现初始化方法,在初始化的时候将数据读载入"""
  6. self.df=pd.read_csv(csv_file)
  7. def __len__(self):
  8. '''
  9. 返回df的长度
  10. '''
  11. return len(self.df)
  12. def __getitem__(self, idx):
  13. '''
  14. 根据 idx 返回一行数据
  15. '''
  16. return self.df.iloc[idx].SalePrice

至此,我们的数据集已经定义完成了,我们可以实例化一个对象访问它

ds_demo= BulldozerDataset('median_benchmark.csv')

我们可以直接使用如下命令查看数据集数据

  1. #实现了 __len__ 方法所以可以直接使用len获取数据总数
  2. len(ds_demo)

  1. #用索引可以直接访问对应的数据,对应 __getitem__ 方法
  2. ds_demo[0]

 

 自定义的数据集已经创建好了,下面我们使用官方提供的数据载入器,读取数据

Dataloader

DataLoader为我们提供了对Dataset的读取操作,常用参数有:batch_size(每个batch的大小)、 shuffle(是否进行shuffle操作)、 num_workers(加载数据的时候使用几个子进程)。下面做一个简单的操作

dl = torch.utils.data.DataLoader(ds_demo, batch_size=10, shuffle=True, num_workers=0)

DataLoader返回的是一个可迭代对象,我们可以使用迭代器分次获取数据

  1. idata=iter(dl)
  2. print(next(idata))

 常见的用法是使用for循环对其进行遍历

  1. for i, data in enumerate(dl):
  2. print(i,data)
  3. # 为了节约空间,这里只循环一遍
  4. break

我们已经可以通过dataset定义数据集,并使用Datalorder载入和遍历数据集,除了这些以外,PyTorch还提供能torcvision的计算机视觉扩展包,里面封装了

torchvision 包

torchvision 是PyTorch中专门用来处理图像的库,PyTorch官网的安装教程中最后的pip install torchvision 就是安装这个包。

torchvision.datasets

torchvision.datasets 可以理解为PyTorch团队自定义的dataset,这些dataset帮我们提前处理好了很多的图片数据集,我们拿来就可以直接使用:

  • MNIST
  • COCO
  • Captions
  • Detection
  • LSUN
  • ImageFolder
  • Imagenet-12
  • CIFAR
  • STL10
  • SVHN
  • PhotoTour 我们可以直接使用,示例如下:
  1. import torchvision.datasets as datasets
  2. trainset = datasets.MNIST(root='./data', # 表示 MNIST 数据的加载的目录
  3. train=True, # 表示是否加载数据库的训练集,false的时候加载测试集
  4. download=True, # 表示是否自动下载 MNIST 数据集
  5. transform=None) # 表示是否需要对数据进行预处理,none为不进行预处理

torchvision.models

torchvision不仅提供了常用图片数据集,还提供了训练好的模型,可以加载之后,直接使用,或者在进行迁移学习 torchvision.models模块的 子模块中包含以下模型结构。

  • AlexNet
  • VGG
  • ResNet
  • SqueezeNet
  • DenseNet
  1. #我们直接可以使用训练好的模型,当然这个与datasets相同,都是需要从服务器下载的
  2. import torchvision.models as models
  3. resnet18 = models.resnet18(pretrained=True)

torchvision.transforms

transforms 模块提供了一般的图像转换操作类,用作数据处理和数据增强

  1. from torchvision import transforms as transforms
  2. transform = transforms.Compose([
  3. transforms.RandomCrop(32, padding=4), #先四周填充0,在把图像随机裁剪成32*32
  4. transforms.RandomHorizontalFlip(), #图像一半的概率翻转,一半的概率不翻转
  5. transforms.RandomRotation((-45,45)), #随机旋转
  6. transforms.ToTensor(),
  7. transforms.Normalize((0.4914, 0.4822, 0.4465), (0.229, 0.224, 0.225)), #R,G,B每层的归一化用到的均值和方差
  8. ])

5.深度学习基础及数学原理

监督学习、无监督学习、半监督学习、强化学习是我们日常接触到的常见的四个机器学习方法:

  • 监督学习:通过已有的训练样本(即已知数据以及其对应的输出)去训练得到一个最优模型(这个模型属于某个函数的集合,最优则表示在某个评价准则下是最佳的),再利用这个模型将所有的输入映射为相应的输出。
  • 无监督学习:它与监督学习的不同之处,在于我们事先没有任何训练样本,而需要直接对数据进行建模
  • 半监督学习 :在训练阶段结合了大量未标记的数据和少量标签数据。与使用所有标签数据的模型相比,使用训练集的训练模型在训练时可以更为准确。
  • 强化学习:我们设定一个回报函数(reward function),通过这个函数来确认否越来越接近目标,类似我们训练宠物,如果做对了就给他奖励,做错了就给予惩罚,最后来达到我们的训练目的。

这里我们只着重介绍监督学习,因为我们后面的绝大部们课程都是使用的监督学习的方法,在训练和验证时输入的数据既包含输入x,又包含x对应的输出y,即学习数据已经事先给出了正确答案。

5.1线性回归

线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。其表达形式为y = w'x+e,e为误差服从均值为0的正态分布。

回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析。

简单的说: 线性回归对于输入x与输出y有一个映射f,y=f(x),而f的形式为aX+b。其中a和b是两个可调的参数,我们训练的时候就是训练a,b这两个参数。

下面我们来用PyTorch的代码来做一个详细的解释

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

下面定义一个线性函数,这里使用 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/356134?site
推荐阅读
相关标签