一. 张量

PyTorch里面最基本的操作对象就是Tensor,Tensor是张量的英文,表示的是一个多维的矩阵,比如零维就是一个点,一维就是向量,二维就是一般的矩阵,多维就相当于一个多维的数组,这和numpy是对应的,而且PyTorch的Tensor和numpy的ndarray可以相互转换,唯一不同的是PyTorch可以在GPU上运行,而numpy的ndarray只能在CPU上运行。

我们先介绍一下一些常用的不同数据类型的Tensor,有32位浮点型torch.FloatTensor,64位浮点型torch.DoubleTensor,16位整型torch.ShortTensor,32位整型torch.IntTensor和64位整型torch.LongTensor。

1. 定义一个给定尺寸给定元素的张量

需要注意的是torch.Tensor默认的是torch.FloatTensor的数据类型

# 定义一个三行二列给定元素的矩阵,并且显示出矩阵的元素和大小
a = torch.Tensor([[2, 3], [4, 8], [7, 9]])
print('a is: {}'.format(a))
print("a'size is {}".format(a.size()))

运行结果:

也可以定义自己想要的数据类型:

# 定义一个三行二列给定元素的矩阵,并且显示出矩阵的元素和大小
b = torch.LongTensor([[2, 3], [4, 8], [7, 9]])
print('a is: {}'.format(a))

当然也可以创建一个全0、全1的Tensor或者取一个正态分布作为随机初始值:

# 全零张量
c = torch.zeros((3, 2))
print('zero tensor: {}'.format(c))
# 全一张量
d = torch.ones((3, 2))
print('one tensor: {}'.format(d))
# 随机初始化
e = torch.randn((3, 2))
print('normal randon is: {}'.format(e))

运行结果:

2. 通过索引获取或者改变张量中的值

我们也可以像numpy一样通过索引的方式取得其中的元素,同时也可以改变他的值。

# 将张量a中第一行第二列的元素变为100
a[0, 1] = 100
print('changed a is: {}'.format(a))

运行结果:

3. Tensor与numpy.ndarray之间相互转换

# 将Tensor b转换为ndarray类型
numpy_b = b.numpy()
print('conver to numpy is n {}'.format(numpy_b))# 定义一个ndarray类型的 e
e = np.array([[2, 3], [4, 5]])
# 将e由ndarray类型转换为Tensor类型
torch_e = torch.from_numpy(e)
print('from numpy to torch.Tensor is {}'.format(torch_e))
# 更改tensor的数据类型——由int32到float
f_torch_e = torch_e.float()
print('change data type to float tensor: {}'.format(f_torch_e))

运行结果:

如果你的电脑支持GPU加速,还可以将Tensor放到GPU上。

首先通过torch.cuda.is_available()判断一下是否支持GPU,如果想把tensor a放到GPU上,只需 a.cuda()就能够将tensor a放到GPU上了。

if torch.cuda.is_available():a_cuda = a.cuda()print(a_cuda)

二. 变量

接着要讲的概念就是Variable,也就是变量,这个在numpy里面是没有的,是神经网络计算图里特有的一个概念,就是Variable提供了自动求导的功能,之前如果了解过Tensorflow的人应该清楚神经网络在做运算的时候需要先构造一个计算图谱,然后在里面进行前向传播和反向传播。

Variable和Tensor本质上没有区别,不过Variable会被放入一个计算图中,然后进行前向传播、反向传播。

首先Variable是在torch.autograd.Variable中,要将一个tensor变为Variable也非常简单,比如想让一个tensor a变为Variable,只需要Variable(a)就可以了。我们可以通过下图了解到Variable的属性。

从上图可以看出来Variable有三个重要的组成属性:data,grad和grad_fn。通过data可以取出Variable里面的Tensor值,grad_fn表示的是得到这个Variable的操作,比如通过加减还是乘除得到的,最后grad是这个Variable的反向传播梯度,下面通过例子来具体说明一下:

import torch
from torch.autograd import Variable
# create Variable
x = Variable(torch.Tensor([1]), requires_grad=True)
w = Variable(torch.Tensor([2]), requires_grad=True)
b = Variable(torch.Tensor([3]), requires_grad=True)# Build a computational graph
y = w * x + b# 查看变量x里面的三个组成属性,此时还未自动求导,所以x.grad_fn,x_grad都为None
print(x.data, x.grad_fn, x.grad)  # x.data = 1, x.grad_fn = None, x.grad = None# Compute gradients
y.backward() # same as y.backward(torch.Tensor([1]))
# print out the gradients
print(x.grad, x.grad_fn, x.data)  # x.grad = 2, x.grad_fn = None, x.data = 1
print(y.grad, y.grad_fn, y.data)  # y.grad = None, y.grad_fn = <AddBackward0 object at 0x0000022B482E4978>, y.data = 5

构建Variable,要注意得传入一个参数requires_grad=True,这个参数表示是否对这个变量求梯度,默认的是False,即不对这个变量求梯度,这里我们希望得到这些变量的梯度,所以需要传入这个参数。

从上面的代码可以看出,y.backward()这一行代码就是所谓的自动求导,这其实等价于y.backward(torch.FloatTensor([1])),只不过对于标量求导里面的参数就可以不写了,自动求导不需要你再去写明哪个函数对哪个函数求导,直接通过这行代码就能对所有的需要梯度的变量进行求导,得到它们的梯度,然后通过x.grad可以得到x的梯度。

上面是对标量的求导,同时也可以对矩阵求导,比如:

x = torch.randn(3)
x = Variable(x, requires_grad=True)
print(x)   # x = tensor([0.4149, 0.2224, 1.5925], requires_grad=True)
y = x * 2
print(y)   # y = tensor([0.8297, 0.4447, 3.1851], grad_fn=<MulBackward0>)
y.backward(torch.FloatTensor([1, 0.1, 0.01]))
print(x.grad)  # x.grad = tensor([2.0000, 0.2000, 0.0200])

这相当于给出了一个三维向量去做运算,这时候得到的y的结果就是一个向量,这里对这个向量求导就不能直接写成y.backward(),这样程序是会报错的。这个时候需要传入参数声明,比如 y.backward(torch.Tensor([1, 1, 1])),这样得到的结果就是它们每个分量的梯度,或者可以传入 y.backward(torch.Tensor([1, 0.1, 0.01])),这样得到的梯度就是它们原本的梯度分别乘上1,0.1,0.01。

三. 数据集的读取

在处理任何机器学习问题之前都需要数据读取,并进行预处理。PyTorch提供了很多工具使得数据的读取和预处理变得很容易。

torch.utils.data.Dataset是代表这一数据的抽象类,你可以定义自己的数据类继承和重写这个抽象类,非常简单,只需要定义__len__和__getitem__这两个函数:

import torch
from torch.utils.data import Dataset,DataLoader
import pandas as pd
class myDataset(Dataset):def __init__(self, csv_file, txt_file, root_dir, other_file):self.csv_data = pd.read_csv(csv_file)with open(txt_file, 'r') as f:data_list = f.readlines()self.txt_data = data_listself.root_dir = root_dirdef __len__(self):return len(self.csv_data)def __getitem__(self, idx):data = (self.csv_data[idx], self.txt_data[idx])return data

通过上面的方式,可以定义我们的数据类,可以通过迭代的方式来取得每一个数据,但是这样很难实现取batch、shuffle或者多线程去读取数据,所以PyTorch中提供了一个简单的方法来做这个事情,通过torch.utils.data.DataLoader()来定义一个新的迭代器,如下:

dataiter = DataLoader(myDataset, batch_size=32, shuffle=True, collate_fn=default_collate)

里面的参数都比较清楚,只有collate_fn是表示如何取样本的,我们可以定义自己的函数来准确地实现想要的功能,默认的函数在一般情况下都是可以使用的。

另外在torchvision这个包中还有一个更高级的有关于计算机视觉的数据读类:ImageFolder,主要功能是处理图片,且要求图片是下面这种存放格式:

1 root/dog/xxx.png

2 root/dog/xxy.png

3 root/dog/xxz.png

4

5 root/cat/123.png

6 root/cat/asd.png

之后这样来调用这个类:

dset = ImageFolder(root='root_path', transform=None, loader=default_loader)

其中的root是根目录,在这个目录下几个文件夹,每个文件夹表示一个类别:transform和target_transform是图片增强,之后会详细讲;loader是图片读取的方法,因为我们读取的图片的名字,然后通过loader讲图片转换成我们需要的图片类型进入神经网络。

四. nn.Mudule(模组)

在PyTorch里面编写神经网络,所有的层结构和损失函数都来自于torch.nn,所有的模型构建都是从这个基类nn.Module继承的,于是有了下面这个模板。

from torch import nn
class net_name(nn.Module):def __init__(self, other_arguments):super(net_name, self).__init__()self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size)# other network layerdef forward(self, x):x = self.conv1(x)return x

这样就建立了一个计算图,并且这个结构可以复用多次,每次调用就相当于用该计算图定义的相同参数做一个前向传播,这得益于PyTorch的自动求导功能,所以我们不需要自己编写反向传播,而所有的网络层都由nn这个包得到,比如线性层nn.Linear,等之后使用的时候我们可以详细地介绍每一种每一种网络对应的结构,以及如何调用。

定义完模型之后,我们需要通过nn这个包来定义损失函数。常简的损失函数都已经定义在了nn中,比如均方误差、多分类的交叉熵,以及二分类的交叉熵,等等,调用这些已经定义好的损失函数也很简单:

# 定义交叉熵损失函数
loss = nn.CrossEntropyLoss(output, target)

这样就能求得我们的输出和真实目标之间的损失函数了。

五. 优化

在机器学习或者深度学习中,我们需要通过修改参数使得损失函数最小化(或最大化),优化算法就是一种调整模型参数更新的策略。

优化算法分为两大类:

1. 一阶优化算法

这种算法使用各个参数的梯度值来更新参数,最常用的一阶优化算法是梯度下降。所谓的梯度就是导数的多变量表达式,函数的梯度形成了一个向量场,同时也是一个方向,这个方向上方向导数最大,且等于梯度。梯度下降的功能是通过寻找最小值,控制方差,更新模型参数,最终使模型收敛,网络的参数更新公式是:$theta =theta -eta times frac{partial J(theta )}{partial theta }$,其中$eta$是学习率,$frac{partial J(theta )}{partial theta }$是函数梯度。

2. 二阶优化算法

二阶优化算法使用了二阶导数(也叫做Hessian方法)来最小化或最大化损失函数,主要基于牛顿法,但由于二阶导数的计算成本很高,所以这种方法并没有广泛使用。torch.optim是一个实现各种优化算法的包,大多数常见的算法都能够直接通过这个包来调用,比如随机梯度下降,以及添加动量的随机梯度下降,自适应学习率等。在调用的时候将需要优化的参数传入,这些参数都必须是Variable,然后传入一些基本的设定,比如学习率和动量等。

下面举一个例子:

from torch import optim
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

这样我们就将模型的参数作为需要更新的参数传入优化器,设定学习率为0.0.1,动量为0.9的随机梯度下降,在优化之前需要先将梯度归零,即optimizer.zeros(),然后再通过loss.backward()反向传播,自动求导得到每个参数的梯度,最后只需要optimizer.step()就可以通过梯度做进一步参数更新。

六. 模型的保存和加载

在PyTorch里面使用torch.save()来保存模型的结构和参数有两种保存方式:

1. 保存整个模型的结构信息和参数信息,保存的对象是模型model;

2. 保存模型的参数,保存的对象是模型的状态 model.state_dict();

可以这样保存,save的第一个参数是保存对象,第二个参数是保存路径及名称:

torch.save(model, './model.pth')
torch.save(model.state_dict(), './model_state.pth')

加载模型有两种方式分别对应于保存模型的方式:

1. 加载完整的模型结构和参数信息,使用 load_model = torch.load('model.pth'),在网络较大的时候加载的时间比较长,同时存储空间也比较大;

2. 加载模型参数信息,需要先导入模型的结构,然后通过 model.load_state_dict(torch.load('model_state.pth'))来导入;

以上内容皆为廖星宇编著的《深度学习入门之PyTorch》这本书上的内容。

numpy将所有数据变为0和1_PyTorch 学习笔记(二):张量、变量、数据集的读取、模组、优化、模型的保存和加载...相关推荐

  1. numpy将所有数据变为0和1_Numpy库学习

    之前照着<利用python进行数据分析>学过一边,代码也跟着敲了,但是如果不用的话,印象不深,忘的特别快.所以,现在再过一遍,并且记录一下,加深印象. 一.创建 numpy中的多维数组对象 ...

  2. numpy将所有数据变为0和1_《利用python进行数据分析》1.0——Numpy库

    目录: Tab 键自动完成 %run命令 "Ctri-C" 中断正在执行的代码 忘记输入和输出文本怎么办 创建数组 zero 和ones arange(),生成一定长度的数量 dt ...

  3. PyTorch模型的保存加载以及数据的可视化

    文章目录 PyTorch模型的保存和加载 模块和张量的序列化和反序列化 模块状态字典的保存和载入 PyTorch数据的可视化 TensorBoard的使用 总结 PyTorch模型的保存和加载 在深度 ...

  4. NumPy学习笔记 二

    NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...

  5. 2017-2-15从0开始前端学习笔记(HTML)-图片-表格-表单

    2017-2-15从0开始前端学习笔记-图片-表格-表单 标签 图片 图片<img src="#" alt="文本说明 不能加载图片时显示" title= ...

  6. tensorflow 保存训练loss_tensorflow2.0保存和加载模型 (tensorflow2.0官方教程翻译)

    最新版本:https://www.mashangxue123.com/tensorflow/tf2-tutorials-keras-save_and_restore_models.html 英文版本: ...

  7. Colly 学习笔记(二)——爬虫框架,抓取下载数据(上证A股数据下载)

    Colly 学习笔记(二)--爬虫框架,抓取下载数据(上证A股数据下载) Colly 学习笔记(一)--爬虫框架,抓取中金公司行业市盈率数据 Colly 学习笔记(二)--爬虫框架,抓取下载数据(上证 ...

  8. 【C#8.0 and .NET Core 3.0 高级编程学习笔记】

    @C#8.0 and .NET Core 3.0 高级编程学习笔记 前言 为了能精细地完成对C#语言的学习,我决定选择一本书,精读它,理解它,记录它.我想选择什么书并不是最重要的,最重要的是持之以恒的 ...

  9. 大数据第二阶段Python基础编程学习笔记(待完善)

    大数据第二阶段Python基础编程学习笔记(待完善) 第一章 Python基础语法 3.8 1-1Python概述 python基础部分: ●Python基础语法: 标识符,关键字,变量,判断循环.. ...

最新文章

  1. android+多米音乐+自动播放,android 高仿多米音乐播放器
  2. 分享25个高质量的移动设备wordpress主题(Mobile theme)
  3. 栈的简单介绍以及栈结构的ADT【数据结构】
  4. Windows下运行Redis-网盘链接-简单粗暴-亲测有用
  5. 大多数项目能不能投资,能不能去创业,取决于自己是站在什么高度看问题
  6. 全国计算机一级ms office考试题型,全国计算机等级考试一级MS Office题型剖析
  7. Python操作数据库遇到的问题
  8. IDEA必备插件大全
  9. 学会用CUPS管理打印机
  10. CodeRunner破解
  11. 作为一名投资人,我经常会问创业者 8 个问题
  12. html添加到购物车飞入动画效果,加入购物车的动画效果
  13. 自然数e的故事(转)
  14. 【hadoop权威指南第四版】第三章hadoop分布式文件系统【笔记+代码】
  15. noip题库 —— 4.7反质数
  16. Wireshark抓包实例诊断TCP连接问题
  17. ANSYS中的轴承载荷(BearingLoad)_51CAE_新浪博客
  18. Excel对比Python实现方差分析
  19. 【自学笔记】尚硅谷数据结构与算法Chapter 3 链表
  20. unity初写游戏(四)怪物产生方式

热门文章

  1. 关于K-SVD算法中逐列更新的目标函数的理解,再看不懂就打死我吧
  2. docker容器启动几分钟之后自动退出
  3. Python基础---OS模块 (二)
  4. ZOJ - 3624
  5. C# MD5 加密算法
  6. Redisbook学习笔记(3)数据类型之列表
  7. 《实施Cisco统一通信管理器(CIPT1)》一2.2 CUCM:单站点部署模型
  8. iOS之UI--CAGradientLayer
  9. Ubuntu 下升级git到最新版
  10. 路径空间HDOJ 4514 - 湫湫系列故事——设计风景线 并查集+树型DP