Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 386|回复: 0

[默认分类] pytorch 学习笔记(一)

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-6-4 11:02:26 | 显示全部楼层 |阅读模式

    1. pytorch
    复制代码
    是一个动态的建图的工具。不像
    1. Tensorflow
    复制代码
    那样,先建图,然后通过
    1. feed
    复制代码
    1. run
    复制代码
    重复执行建好的图。相对来说,
    1. pytorch
    复制代码
    具有更好的灵活性。
    编写一个深度网络需要关注的地方是:
    1. 网络的参数应该由什么对象保存
    2. 如何构建网络
    3. 如何计算梯度和更新参数
    数据放在什么对象中
    1. pytorch
    复制代码
    中有两种变量类型,一个是
    1. Tensor
    复制代码
    ,一个是
    1. Variable
    复制代码
    (0.4.0版本已经将 Variable 和 Tensor合并,统称为 Tensor)

    1. Tensor
    复制代码
    : 就像
    1. ndarray
    复制代码
    一样,一维
    1. Tensor
    复制代码
    1. Vector
    复制代码
    ,二维
    1. Tensor
    复制代码
    1. Matrix
    复制代码
    ,三维及以上称为
    1. Tensor
    复制代码

    1. Variable
    复制代码
    :是
    1. Tensor
    复制代码
    的一个
    1. wrapper
    复制代码
    ,不仅保存了值,而且保存了这个值的
    1. creator
    复制代码
    ,需要
    1. BP
    复制代码
    的网络都是
    1. Variable
    复制代码
    参与运算
      
    1. [code]import torch
    2. x  = torch.Tensor(2,3,4) # torch.Tensor(shape) 创建出一个未初始化的Tensor,但是还是可以打印出值的,这个应该是这块内存之前的数据
    3. x                        # 这种方式创建出来的Tensor更多是用来接受其他数据的计算值的
    复制代码
    [/code]
    1. [code](0 ,.,.) =
    2. 1.00000e-37 *
    3.    1.5926  0.0000  0.0000  0.0000
    4.    0.0000  0.0000  0.0000  0.0000
    5.    0.0000  0.0000  0.0000  0.0000
    6. (1 ,.,.) =
    7. 1.00000e-37 *
    8.    0.0000  0.0000  0.0000  0.0000
    9.    0.0000  0.0000  0.0000  0.0000
    10.    0.0000  0.0000  0.0000  0.0000
    11. [torch.FloatTensor of size 2x3x4]
    复制代码
    [/code]
    1. [code]x.size()
    复制代码
    [/code]
    1. [code]torch.Size([2, 3, 4])
    复制代码
    [/code]
    1. [code]a = torch.rand(2,3,4)
    2. b = torch.rand(2,3,4)
    3. _=torch.add(a,b, out=x)  # 使用Tensor()方法创建出来的Tensor用来接收计算结果,当然torch.add(..)也会返回计算结果的
    4. x
    复制代码
    [/code]
    1. [code](0 ,.,.) =
    2.   0.9815  0.0833  0.8217  1.1280
    3.   0.7810  1.2586  1.0243  0.7924
    4.   1.0200  1.0463  1.4997  1.0994
    5. (1 ,.,.) =
    6.   0.8031  1.4283  0.6245  0.9617
    7.   1.3551  1.9094  0.9046  0.5543
    8.   1.2838  1.7381  0.6934  0.8727
    9. [torch.FloatTensor of size 2x3x4]
    复制代码
    [/code]
    1. [code]a.add_(b) # 所有带 _ 的operation,都会更改调用对象的值,
    2. #例如 a=1;b=2; a.add_(b); a就是3了,没有 _ 的operation就没有这种效果,只会返回运算结果
    3. torch.cuda.is_available()
    复制代码
    [/code]
    1. [code]True
    复制代码
    [/code]
    自动求导
    1. pytorch
    复制代码
    的自动求导工具包在
    1. torch.autograd
    复制代码

    1. [code]from torch.autograd import Variable
    2. x = torch.rand(5)
    3. x = Variable(x,requires_grad = True)
    4. y = x * 2
    5. grads = torch.FloatTensor([1,2,3,4,5])
    6. y.backward(grads)#如果y是scalar的话,那么直接y.backward(),然后通过x.grad方式,就可以得到var的梯度
    7. x.grad           #如果y不是scalar,那么只能通过传参的方式给x指定梯度
    复制代码
    [/code]
    1. [code]Variable containing:
    2.   2
    3.   4
    4.   6
    5.   8
    6. 10
    7. [torch.FloatTensor of size 5]
    复制代码
    [/code]
    neural networks
    使用
    1. torch.nn
    复制代码
    包中的工具来构建神经网络
    构建一个神经网络需要以下几步:

      定义神经网络的
    1. 权重
    复制代码
    ,搭建网络结构
      遍历整个数据集进行训练

       
        将数据输入神经网络
        计算loss
        计算网络权重的梯度
        更新网络权重

         
          weight = weight + learning_rate * gradient
         
       
      
    1. [code]import torch.nn as nn
    2. import torch.nn.functional as F
    3. class Net(nn.Module):#需要继承这个类
    4.     def __init__(self):
    5.         super(Net, self).__init__()
    6.         #建立了两个卷积层,self.conv1, self.conv2,注意,这些层都是不包含激活函数的
    7.         self.conv1 = nn.Conv2d(1, 6, 5) # 1 input image channel, 6 output channels, 5x5 square convolution kernel
    8.         self.conv2 = nn.Conv2d(6, 16, 5)
    9.         #三个全连接层
    10.         self.fc1   = nn.Linear(16*5*5, 120) # an affine operation: y = Wx + b
    11.         self.fc2   = nn.Linear(120, 84)
    12.         self.fc3   = nn.Linear(84, 10)
    13.     def forward(self, x): #注意,2D卷积层的输入data维数是 batchsize*channel*height*width
    14.         x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) # Max pooling over a (2, 2) window
    15.         x = F.max_pool2d(F.relu(self.conv2(x)), 2) # If the size is a square you can only specify a single number
    16.         x = x.view(-1, self.num_flat_features(x))
    17.         x = F.relu(self.fc1(x))
    18.         x = F.relu(self.fc2(x))
    19.         x = self.fc3(x)
    20.         return x
    21.     def num_flat_features(self, x):
    22.         size = x.size()[1:] # all dimensions except the batch dimension
    23.         num_features = 1
    24.         for s in size:
    25.             num_features *= s
    26.         return num_features
    27. net = Net()
    28. net
    复制代码
    [/code]
    1. [code]Net (
    2.   (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
    3.   (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
    4.   (fc1): Linear (400 -> 120)
    5.   (fc2): Linear (120 -> 84)
    6.   (fc3): Linear (84 -> 10)
    7. )
    复制代码
    [/code]
    1. [code]len(list(net.parameters())) #为什么是10呢? 因为不仅有weights,还有bias, 10=5*2。
    2.                             #list(net.parameters())返回的learnable variables 是按照创建的顺序来的
    3.                             #list(net.parameters())返回 a list of torch.FloatTensor objects
    复制代码
    [/code]
    1. [code]10
    复制代码
    [/code]
    1. [code]input = Variable(torch.randn(1, 1, 32, 32))
    2. out = net(input) #这个地方就神奇了,明明没有定义__call__()函数啊,所以只能猜测是父类实现了,并且里面还调用了forward函数
    3. out              #查看源码之后,果真如此。那么,forward()是必须要声明的了,不然会报错
    4. out.backward(torch.randn(1, 10))
    复制代码
    [/code]
    使用loss criterion 和 optimizer训练网络
    1. torch.nn
    复制代码
    包下有很多loss标准。同时
    1. torch.optimizer
    复制代码
    帮助完成更新权重的工作。这样就不需要手动更新参数了
    1. [code]learning_rate = 0.01
    2. for f in net.parameters():
    3.     f.data.sub_(f.grad.data * learning_rate)  # 有了optimizer就不用写这些了
    复制代码
    [/code]
    1. [code]import torch.optim as optim
    2. # create your optimizer
    3. optimizer = optim.SGD(net.parameters(), lr = 0.01)
    4. # in your training loop:
    5. optimizer.zero_grad() # 如果不置零,Variable 的梯度在每次 backward 的时候都会累加。
    6. output = net(input) # 这里就体现出来动态建图了,你还可以传入其他的参数来改变网络的结构
    7. loss = criterion(output, target)
    8. loss.backward()
    9. optimizer.step() # Does the update
    复制代码
    [/code]
    整体NN结构
    1. [code]import torch.nn as nn
    2. import torch.nn.functional as F
    3. class Net(nn.Module):#需要继承这个类
    4.     def __init__(self):
    5.         super(Net, self).__init__()
    6.         #建立了两个卷积层,self.conv1, self.conv2,注意,这些层都是不包含激活函数的
    7.         self.conv1 = nn.Conv2d(1, 6, 5) # 1 input image channel, 6 output channels, 5x5 square convolution kernel
    8.         self.conv2 = nn.Conv2d(6, 16, 5)
    9.         #三个全连接层
    10.         self.fc1   = nn.Linear(16*5*5, 120) # an affine operation: y = Wx + b
    11.         self.fc2   = nn.Linear(120, 84)
    12.         self.fc3   = nn.Linear(84, 10)
    13.     def forward(self, x): #注意,2D卷积层的输入data维数是 batchsize*channel*height*width
    14.         x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) # Max pooling over a (2, 2) window
    15.         x = F.max_pool2d(F.relu(self.conv2(x)), 2) # If the size is a square you can only specify a single number
    16.         x = x.view(-1, self.num_flat_features(x))
    17.         x = F.relu(self.fc1(x))
    18.         x = F.relu(self.fc2(x))
    19.         x = self.fc3(x)
    20.         return x
    21.     def num_flat_features(self, x):
    22.         size = x.size()[1:] # all dimensions except the batch dimension
    23.         num_features = 1
    24.         for s in size:
    25.             num_features *= s
    26.         return num_features
    27. net = Net()
    28. # create your optimizer
    29. optimizer = optim.SGD(net.parameters(), lr = 0.01)
    30. # in your training loop:
    31. for i in range(num_iteations):
    32.     optimizer.zero_grad() # zero the gradient buffers,如果不归0的话,gradients会累加
    33.     output = net(input) # 这里就体现出来动态建图了,你还可以传入其他的参数来改变网络的结构
    34.     loss = criterion(output, target)
    35.     loss.backward() # 得到grad,i.e.给Variable.grad赋值
    36.     optimizer.step() # Does the update,i.e. Variable.data -= learning_rate*Variable.grad
    复制代码
    [/code]
    其它
      
      关于求梯度,只有我们定义的Variable才会被求梯度,由
    1. creator
    复制代码
    创造的不会去求梯度
      自己定义Variable的时候,记得Variable(Tensor, requires_grad = True),这样才会被求梯度,不然的话,是不会求梯度的
      
    1. [code]# numpy to Tensor
    2. import numpy as np
    3. a = np.ones(5)
    4. b = torch.from_numpy(a)
    5. np.add(a, 1, out=a)
    6. print(a) # 如果a 变的话, b也会跟着变,说明b只是保存了一个地址而已,并没有深拷贝
    7. print(b)# Variable只是保存Tensor的地址,如果Tensor变的话,Variable也会跟着变
    复制代码
    [/code]
    1. [code]a = np.ones(5)
    2. b = torch.from_numpy(a)# ndarray --> Tensor
    3. a_ = b.numpy() # Tensor --> ndarray
    4. np.add(a, 1, out=a)# 这个和 a = np.add(a,1)有什么区别呢?
    5. # a = np.add(a,1) 只是将a中保存的指针指向新计算好的数据上去
    6. # np.add(a, 1, out=a) 改变了a指向的数据
    复制代码
    [/code]
    1. [code]# 将Tensor放到Cuda上
    2. if torch.cuda.is_available():
    3.     x = x.cuda()
    4.     y = y.cuda()
    5.     x + y
    复制代码
    [/code]
    1. [code]# torch.Tensor(1,2,3) 与 torch.Tensor([1,2,3]) 的区别
    2. torch.Tensor(1,2,3) # 生成一个 shape 为 [1,2,3] 的 tensor
    3. torch.Tensor([1,2,3]) # 生成一个值为 [1,2,3] 的 tensor
    复制代码
    [/code]
    1. [code]# tensor 与 numpy
    2. import torch
    3. from torch.autograd import Variable
    4. import numpy as np
    5. n1 = np.array([1., 2.]).astype(np.float32)
    6. # t1 = torch.FloatTensor(n1)
    7. t1 = torch.from_numpy(n1)
    8. n1[0] = 2.
    9. print(t1)
    10. # 可以看出,当使用 无论是使用 FloatTensor 还是 from_numpy 来创建 tensor
    11. # tensor 只是指向了 初始的值而已,而没有自己再开辟空间。
    12. # FloatTensor(2,3,2) 这个不一样,它是开辟了一个 空间。
    复制代码
    [/code]
    如遇无法下载pytorch安装包问题
    [链接:http://pan.baidu.com/s/1c2cSoX6 密码:ckf8]

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-19 16:37 , Processed in 0.428933 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表