pytorch 基础
一.张量(Tensor)
PyTorch 的官方介绍是一个拥有强力GPU加速的张量和动态构建网络的库,其主要构件是张量,所以我们可以把 PyTorch 当做 NumPy 来用,PyTorch 的很多操作好 NumPy 都是类似的,但是因为其能够在 GPU 上运行,所以有着比 NumPy 快很多倍的速度。
0维张量/标量 标量是一个数字
1维张量/向量 1维张量称为“向量”。
2维张量 2维张量称为矩阵
3维张量 公用数据存储在张量 时间序列数据 股价 文本数据 彩色图片(RGB)
张量是现代机器学习的基础。它的核心是一个数据容器,多数情况下,它包含数字,有时候它也包含字符串,但这种情况比较少。因此把它想象成一个数字的水桶。
解释的很好的博客:

二.变量(Variable)
tensor 是 PyTorch 中的完美组件,但是构建神经网络还远远不够,我们需要能够构建计算图的 tensor,这就是 Variable。Variable 是对 tensor 的封装,操作和 tensor 是一样的,但是每个 Variabel都有三个属性,Variable 中的 tensor本身.data,对应 tensor 的梯度.grad以及这个 Variable 是通过什么方式得到的.grad_fn(即得到这个Variable的操作)
在numpy中没有,是神经网络计算图里特有的一个概念,variable提供了自动求导的功能,之前如果了解过TensorFlow的应该清楚神经网络在做运算时需要构造一个计算图谱,然后在里面进行前向传播和反向传播。
variable和Tensor本质上没有区别,不过variable会被放入一个计算图中,然后进行前向传播,反向传播,自动求导。

三、自动求导
自动求导是 PyTorch 中非常重要的特性,能够让我们避免手动去计算非常复杂的导数,这能够极大地减少了我们构建模型的时间,这也是其前身 Torch 这个框架所不具备的特性,下面我们通过例子看看 PyTorch 自动求导的独特魅力以及探究自动求导的更多用法。

import torch
 import numpy as np#一、张量Tensor
 #创建一个numpy ndarray
 #randn()取一个正态分布作为随机初始值
 numpy_tensor=np.random.randn(10,20)
 #使用两种方式将numpy和ndarray转换到tensor上
 #直接将NumPy ndarray 的数据类型转换为对应的PyTorch Tensor数据类型
 pytorch_tensor1=torch.Tensor(numpy_tensor)
 pytorch_tensor2=torch.from_numpy(numpy_tensor)#使用下面的方法将pytorch tensor 转换为numpy ndarray
 #如果pytorch Tensor在CPU上
 numpy_tensor =pytorch_tensor1.numpy()
 #如果pytorch Tensor在GPU上
 #GPU上的Tensor不能直接装换为numpy ndarray,需要使用.cup()先将GPU上的Tensor转到CPU上
 numpy_tensor=pytorch_tensor1.cpu().numpy()#pytorch Tensor使用GPU加速
 #使用2种方式将Tensor放到GPU上
 #1.定义cuda数据类型
 dtype=torch.cuda.FloatTensor#定义默认GPU的数据类型
 gpu_tensor=torch.randn(10,20).type(dtype)#2.
 gpu_tensor=torch.randn(10,20).cuda(0)#将Tensor放在第一个GPU上
 #gpu_tensor=torch.randn(10,20).cuda(1)#将Tensor放在第二个GPU上
 #使用第一种方式将 tensor 放到 GPU 上的时候会将数据类型转换成定义的类型,而是用第二种方式能够直接将 tensor 放到 GPU 上,类型跟之前保持一致
 #推荐在定义 tensor 的时候就明确数据类型,然后直接使用第二种方法将 tensor 放到 GPU 上#将 tensor 放回 CPU 的操作非常简单
 cpu_tensor=gpu_tensor.cpu()#访问Tensor的一些属性
 #得到Tensor的大小
 print(pytorch_tensor1.shape)
 print(pytorch_tensor1.size())
 #得到Tensor的数据类型
 print(pytorch_tensor1.type())
 #得到Tensor的维度
 print(pytorch_tensor1.dim())
 #得到tensor的所有元素个数
 print(pytorch_tensor1.numel())x=torch.randn(3,2)
 #torch.DoubleTensor为64位浮点型
 #torch.FloatTensor为32位浮点型
 #torch.ShortTensor为16位整型
 #torch.IntTensor为32位整型
 #torch.LongTensor为64位整型
 #torch.Tensor默认是torch.FloatTensor数据类型
 x=x.type(torch.DoubleTensor)
 #将pytorch tensor 转换为numpy ndarray
 x_array=x.numpy()
 #打印Tensor 的数据类型
 print(x_array.dtype)
 #‘numpy.ndarray’ object has no attribute ‘type’
 #print(x_array.type())#张量的操作
 x=torch.ones(2,2)
 print(x)#这是一个float tensor
 print(x.type())
 #以下两种方式将其转换为整型
 x=x.type(torch.LongTensor)
 print(x)
 print(x.type())
 x=x.long()
 print(x)
 print(x.type())#用以下两种方式再将其转换为float
 #x=x.float()
 x=x.type(torch.FloatTensor)
 print(x)
 print(x.type())x=torch.randn(4,3)
 print(x)#沿着行取最大值
 max_value,max_idx=torch.max(x,dim=1)
 #打印每行最大值
 print(max_value)
 #打印每行最大值的下标
 print(max_idx)#沿着行对x求和
 sum_x=torch.sum(x,dim=1)
 print(sum_x)#增加维度或者减少维度
 print(x.shape)
 x=x.unsqueeze(0)#在第一维增加
 print(x.shape)
 print(x)x=x.unsqueeze(1)#在第一维增加
 print(x.shape)x=x.squeeze(0)#减少第一维
 print(x.shape)x=x.squeeze()#将tensor中所有的一维全部去掉
 print(x.shape)x=torch.randn(3,4,5)
 print(x.shape)#使用permute和transpose进行维度交换
 x=x.permute(1,0,2)#permute可以重新排列tensor的维度
 print(x.shape)
 x=x.transpose(0,2)#transpose交换tensor中的两个维度
 print(x.shape)#使用view对tensor进行reshape
 x=torch.randn(3,4,5)
 print(x.shape)
 x=x.view(-1,5)#-1表示任意大小,5表示第二维变成5
 print(x.shape)
 x=x.view(3,20)
 print(x.shape)#对两个tensor进行求和
 x=torch.randn(3,4)
 print(x)
 y=torch.randn(3,4)
 print(y)
 #z=x+y
 z=torch.add(x,y)
 print(z)#pytorch中大多数的操作都支持 inplace 操作,
 #也就是可以直接对 tensor 进行操作而不需要另外开辟内存空间,
 #方式非常简单,一般都是在操作的符号后面加_x=torch.ones(3,3)
 print(x.shape)
 print(x)
 #unsqueeze 进行inplace
 x.squeeze_(0)
 print(x.shape)
 print(x)
 #transpose 进行inplace
 x.transpose_(1,0)
 print(x.shape)
 print(x)x=torch.ones(3,3)
 y=torch.ones(3,3)
 print(x)
 x.add_(y)
 print(x)#练习
 x=torch.ones(4,4).float()
 x[1:3,1:3]=2#1表示起始下标,3表示结束位置的前一位
 print(x)#二.变量(Variable)
 #通过下面这种方式导入Variable
 from torch.autograd import Variable
 x_tensor=torch.randn(10,5)
 y_tensor=torch.randn(10,5)
 #将tensor变成variable

默认 Variable 是不需要求梯度的,所以我们用这个方式申明需要对其进行求梯度

x=Variable(x_tensor,requires_grad=True)
 #print(x)
 y=Variable(y_tensor,requires_grad=True)
 #print(y)
 z=torch.sum(x+y)
 print(z.data)
 print(z.grad_fn)#求x和y的梯度
 z.backward()
 #print(x.grad)
 #print(y.grad)#练习构建一个函数x的二次方,然后求x=2的导数
 import matplotlib.pyplot as plt
 x=np.arange(-3,3.01,0.1)
 y=x**2
 plt.plot(x,y)
 plt.plot(2,4,‘ro’)
 plt.show()#求解导数
 x=Variable(torch.FloatTensor([2]),requires_grad=True)
 print(x)
 y=x**2
 y.backward()
 print(x.grad)#自动求导
 x=Variable(torch.Tensor([2]),requires_grad=True)
 print(x)
 y=x+2
 z=y**2+3
 print(z)
 z.backward()
 print(x.grad)x=Variable(torch.randn(10,20),requires_grad=True)
 y=Variable(torch.randn(10,5),requires_grad=True)
 w=Variable(torch.randn(20,5),requires_grad=True)
 out=torch.mean(y-torch.matmul(x,w))#torch.matmul是做矩阵乘法
 out.backward()#自动求导
 print(x.grad)#得到x的梯度
 print(y.grad)#得到y的梯度
 print(w.grad)#得到w的梯度#复杂情况的自动求导
 #对多维数组的自动求导机制
 #构建一个1*2的矩阵,矩阵元素为2和3
 m=Variable(torch.FloatTensor([[2,3]]),requires_grad=True)
 print(m)
 n=Variable(torch.zeros(1,2))
 print(n)
 n[0,0]=m[0,0]**4
 n[0,1]=m[0,1]**3
 print(n)n.backward(torch.ones_like(n))#将 (w0, w1) 取成 (1, 1)
 print(torch.ones_like(n))
 print(m.grad)#多次自动求导
 x=Variable(torch.FloatTensor([3]),requires_grad=True)
 print(x)
 y=x*2+x**2+3
 print(y)y.backward(retain_graph=True)#设置retain_graph为True来保留计算图
 print(x.grad)
 y.backward()
 print(x.grad)#练习
 x=Variable(torch.FloatTensor([2,3]),requires_grad=True)
 k=Variable(torch.zeros(2))
 k[0]=x[0]**2+3x[1]
 k[1]=x[1]**2+2x[0]
 print(k)j=torch.zeros(2,2)
 k.backward(torch.FloatTensor([1,0]),retain_graph=True)#第一个参数是求导的权重w0,w1
 j[0]=x.grad.data
 x.grad.data.zero_()#归零之前求得的梯度
 k.backward(torch.FloatTensor([0,1]))#第一个参数是求导的权重w0,w1
 j[1]=x.grad.data
 print(j)