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)