torch.nn是专门为神经网络设计的模块化接口
torch.nn构建与autograd之上,可以用来定义和运行神经网络
介绍一下四大库:torch.nn.modules、torch.nn.functional、torch.nn.parameter、torch.nn.Sequential
torch.nn.modules
************torch.nn.modules*************
torch.nn.MSELoss
torch.nn.CrossEntropyLoss
torch.nn.Conv2d # 封装的是卷积神经网络层
torch.nn.Embedding
torch.nn.LSTM
torch.nn.Linear
torch.nn.dropout
torch.nn.LeakyReLU
封装的每一层就是一个模块
// An highlighted block
var foo = 'bar';
// An highlighted block
var foo = 'bar';
torch.nn.functional
************torch.nn.functional************
torch.nn.functional.conv2d
torch.nn.functional.embedding
torch.nn.functional.bilinear
torch.nn.functional & torch.nn.modules有什么区别?
torch.nn.functional & torch.nn.modules有什么区别?
1) 类型不同:torch.nn.functional是函数,torch.nn.modules是类
函数:只是进行简单的 数学运算而已。functional中的函数是一个确定的不变的运算公式,输入数据产生输出就ok,
类:会自动提取可学习的参数 深度学习中会有很多权重是在不断更新的,不可能每进行一次forward就用新的权重重新来定义一遍函数来进行计算,
所以说就会采用类的方式,以确保能在参数发生变化时仍能使用我们之前定好的运算步骤。
2) 如果模型有可学习的参数,最好使用nn.Module对应的相关layer,否则二者都可以使用,没有什么区别:
比如此例中的Relu其实没有可学习的参数,只是进行一个运算而已,所以使用的就是functional中的relu函数, 而卷积层和全连接层都有可学习的参数,
所以用的是nn.Module中的类。 不具备可学习参数的层,将它们用函数代替,这样可以不用放在构造函数中进行初始化。
3) nn.functional.xxx 需要自己定义 weight,每次调用时都需要手动传入 weight,而 nn.xxx 则不用,举例如下
示例:
import torch
import torch.nn as nn
import torch.nn.functional as F
# torch.nn 定义的CNN
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv_1 = nn.Conv2d(1, 16, krenel_size=5, padding=0)
self.relu_1 = nn.ReLU(inplace=True)
self.maxpool_1 = nn.MaxPool2d(kernel_size=2)
self.conv_2 = nn.Conv2d(16, 32, krenel_size=5, padding=0)
self.relu_2 = nn.ReLU(inplace=True)
self.maxpool_2 = nn.MaxPool2d(kernel_size=2)
self.linear = nn.Linear(4*4*32, 10)
def forward(self, x):
x = x.view(x.size(0), -1)
out = self.maxpool_1(self.relu_1(self.conv_1(x)))
out = self.maxpool_2(self.relu_2(self.conv_2(out)))
out = self.linear(out.view(x.size(0), -1))
return out
# torch.nn.functional 定义一个相同的CNN
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv_1_weight = nn.Parameter(torch.randn(16, 1, 5, 5))
self.bias_1_weight = nn.Parameter(torch.randn(16))
self.conv_2_weight = nn.Parameter(torch.randn(32, 16, 5, 5))
self.bias_2_weight = nn.Parameter(torch.randn(32))
self.linear_weight = nn.Parameter(torch.randn(4 * 4 * 32, 10))
self.bias_weight = nn.Parameter(torch.randn(10))
def forward(self, x):
x = x.view(x.size(0), -1)
out = F.conv2d(x, self.conv_1_weight, self.bias_1_weight)
out = F.conv2d(out, self.conv_2_weight, self.bias_2_weight)
out = F.linear(out.view(x.size(0), -1), self.linear_weight, self.bias_weight)
torch.nn.parameter
************torch.nn.parameter************
------定义可训练的参数
一般情况下为什么需要设置torch.nn.parameter?
依然有些模型的参数需要去不断的更新,属于tensor,但是不属于这个模型的偏置和权重,所以为了方便,用torch.nn.parameter将参数指定一下
tensor与Parmeter有什么区别?
paramter属于一个tensor
示例:
class NN_Network(nn.Module):
def __init__(self,in_dim,hid,out_dim):
super(NN_Network, self).__init__()
self.linear1 = nn.Linear(in_dim,hid)
self.linear2 = nn.Linear(hid,out_dim)
self.linear1.weight = torch.nn.Parameter(torch.zeros(in_dim,hid))
self.linear1.bias = torch.nn.Parameter(torch.ones(hid))
self.linear2.weight = torch.nn.Parameter(torch.zeros(in_dim,hid))
self.linear2.bias = torch.nn.Parameter(torch.ones(hid))
def forward(self, input_array):
h = self.linear1(input_array)
y_pred = self.linear2(h)
return y_pred
in_d = 5
hidn = 2
out_d = 3
net = NN_Network(in_d, hidn, out_d)
# 读取parameters,因为net.parameters是个生成器,所以需要去遍历输出
for param in net.parameters():
print(param.size())
#一次定义多个parameter
torch.nn.ParameterList
torch.nn.ParameterDict
params = torch.nn.ParameterList([torch.nn.Parameter(torch.randn(5, 10)) for i in range(5)])
torch.nn.ParameterDict
params = torch.nn.ParameterDict({
'left': nn.Parameter(torch.randn(5, 10)),
'right': nn.Parameter(torch.randn(5, 10))
})
params
torch.nn.Sequential
************torch.nn.Sequential************
-------顺序容器
#写法一:
net = nn.Sequential(
nn.Conv2d(1, 20, 5)
)
#写法二:
net = nn.Sequential()
net.add_module('conv2d', nn.Conv2d(1, 20, 5))
#写法三:
from collections import OrderedDict
net = nn.Sequential(OrderedDict([
('conv2d', nn.Conv2d(1, 20, 5))
#.....
]))
示例:
class NN_Network(nn.Module):
def __init__(self,in_dim,hid,out_dim):
super(NN_Network, self).__init__()
self.linear1 = nn.Linear(in_dim,hid)
self.linear2 = nn.Linear(hid,out_dim)
def forward(self, input_array):
h = self.linear1(input_array)
y_pred = self.linear2(h)
return y_pred
# 下面利用torch.nn.Sequential来封装:
class Net(nn.Module):
def __init__(self,in_dim,hid,out_dim):
super(Net, self).__init__()
self.layer = torch.nn.Sequential(
nn.Conv2d(1, 20, 5),
nn.ReLU(),
nn.Conv2d(10, 20, 5),
nn.ReLU(),
)
def forward(self, x):
ouput = self.layer(x)
return ouput