上次写了关于Pytorch入门基本操作,主要是对数据的操作,这次主要写关于Pytorch在使用时涉及到几个部分的一些入门知识。写博客的目的是方便自己以后复习查找。
学习内容来自于<<深度学习之Pytorch>>这本书,顺便附上上一篇博客链接和书籍链接:
Pytorch入门之基本操作
书籍链接:https://pan.baidu.com/s/150jEc6cKFdlTkksaOmvAmQ
提取码:540i
Tensor (张量)
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.lntTensor
- 64位整型 torch.LongTensor
torch.Tensor 默认的是 torch.FloatTensor 数据类型,也可以定义我们想要的数据类型。
可以在 Tensor和numpy.ndarray 之间相互转换:
a = torch. LongTensor ([[2 , 3], [4 , 8], [7 , 9]])
numpy_a = a.numpy()
b = np.array ([[2 , 3], [4 , 5]])
torch_b = torch.from_numpy(b)
通过简单的 b. numpy (),就能将b转换为numpy数据类型,同时使用 torch.from_num py ()就能将numpy转换为 tensor,如果需要更改tensor的数据类型,只要在转换后的tensor后面加上你需要的类型,比如想将a的类型转换成float,只需 a.float () 就可以了。
如果你的电脑支持 GPU 加速,还可以将 Tensor 放到 GPU上。首先通过 torch.cuda.is_available() 判断一下是否支持GPU,如果想把 tensor放到 GPU 上,只需 a. cuda ()就能够将 tensor a放到 GPU 上了:
if torch.cuda.is_available() :
a cuda = a.cuda()
Variable (变量)
Variable ,也就是变量,这个在 numpy 里面就没有了,是神经网络计算图里特有的一个概念,就是 Variable 提供了自动求导的功能,Variable 和Tensor 本质上没有区别,不过 Variable 会被放入一个汁算图中,然后进行前向传播,反向传播,自动求导。
Variable 有三个比较重要的组成属性: data , grad和 grad_fn。通过data 可以取出 Variable 里面的 tensor 数值, grad_fn 表示的是得到这个 Variable 的操作,比如通过加减还是乘除来得到的,最后 grad 是这个 Variabel 的反向传播梯度。
来看个例子:
# Create Varìable
x= Variable(torch.Tensor ([1]) , requìres_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 #y=2*x + 3
# Compute gradients
y.backward() # same as y.backward(torch.FloatTensor([1])
# print out the gradients
print(x.grad) # x.grad = 2
print(w.grad) # w.grad = 1
print(b.grad) # b .grad =1
构建Variable. 要注意得传入一个参数 requires_grad=True,这个参数表示是否对这个变量求梯度,默认的是 False,也就是不对这个变量求梯度。
y.backward(),这 行代码就是所谓的自动求导,这其实等价于y.backward(torch.FloatTensor([1]),只不过对于标量求导里面的参数就可以不写了,自动求导不需要你再去明确地写明哪个函数对哪个函数求导,直接通过这行代码就能对所有的需要梯度的变量进行求导,得到它们的梯度,然后通过 x.grad 可以得到x的梯度。
Dataset (数据集)
torch.utils.data.Dataset 是代表这一数据的抽象类,你可以自己定义你的数据类继承和重写这个抽象类,非常简单,只需要定义__len__和__getitem__这两个函数:
def __init__ (self, csv file , txt file , r oot 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_list
self.root_dir = root_dir
def __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是表示如何取样本的,我们可以定义自己的函数来准确地实现想要的功能,默认的函数在一般情况下都是可以使用的。
nn.Modul e (模组)
PyTorch 里面编神经网络,所有的层结构和损失函数都来自于 torch.nn,所有的模型构建都是从这个基类nn.Module 继承的,于是有了下面这个模板:
class net name(nn.Module) :
def __init__ (self, other_arguments) :
super(net_name, self). __init__()
self.convl = nn.Conv2d (in channels, out channels, kernel size)
# other network layer
def forward(self, x):
x = self.convl(x)
return x
这样就建立了一个计算图 ,并且这个结构可以复用多次,每次调用就相当于用该计算图定义的相同参数做一次前向传播,这得益于 PyTorch 的自动求导功能,所以我们不需要自己编写反向传播,而所有的网络层都是由 nn 这个包得到的,比如线性nn.Linear。
定义完模型之后,我们需要通过 nn 这个包来定义损失函数。常见的损失函数都已定义在了 nn 中,比如均方误差 、多分类的交叉熵,以及二分类的交叉熵,等等,调用这些已经定义好的损失函数也很简单:
criterion = nn.CrossEntropyLoss()
Loss = criterion(output, target)
torch.optim (优化)
优化 法分为两大类:
1.一阶优化算法
这种算法使用各个参数的梯度值来更新参数,最常用的一阶优化算法是梯度下降法。所谓的梯度就是导数的多变量表达式,函数的梯度形成了一个向量场 ,同时也是一个方向,这个方向上方向导数最大,且等于梯度。梯度下降的功能是通过寻找最小值,控制方差,更新模型参数,最终使模型收敛。
2. 二阶优化算法
二阶优化算法,使用了二阶导数(也叫做 Hessian 方法)来最小化或最大化损失函数,主要基于牛顿法。
torch.optim 是一个实现各种优化算法的包,大多数常见的算法都能够直接通过这个包来调用,比如随机梯度下降,以及添加动量的随机棉度下降,自适应学习率等。在调用的时候将需要优化的参数传入,这些参数都必须是 Variable ,然后传入一些基本的设定,比如学习率和动量等。
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9 )
这样我们就将模型的参数作为需要更新的参数传入优化器,设定学习率是 0.01 ,动量是 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_dic (torch.load(‘model state.pth’)) 来导入。
大概就是这几个部分了:数据类型,训练测试数据集,模型搭建,模型求解,模型保存与加载。入门掌握这几个就大致掌握了框架,细节的话遇到了再具体去学,先从宏观上把握,OK的!