一、神经网络基本样子
1、构建神经网络需要继承nn.Module类。
简单看看nn.Module类
class Module(object):
def __init__(self):
def forward(self, *input):
def add_module(self, name, module):
def cuda(self, device=None):
def cpu(self):
def __call__(self, *input, **kwargs):
def parameters(self, recurse=True):
def named_parameters(self, prefix='', recurse=True):
def children(self):
def named_children(self):
def modules(self):
def named_modules(self, memo=None, prefix=''):
def train(self, mode=True):
def eval(self):
def zero_grad(self):
def __repr__(self):
def __dir__(self):
2、提取必须有的框架
import torch
from torch import nn
class Tudui(nn.Module):
def __init__(self):
super().__init__()
def forward(self,input):
(1)在定义一个神经网络类时,我们必须重新定义的就是 init(self)和 def forward(self,input)。
(2)在定义带学习参数的函数的时候一定定义在 init(self)内部,而定义不带学习参数的函数时候也最好定义在 init(self)内部,但是也可以放入到forward(self,input)内部。
用两个函数解释:
class MyNet(torch.nn.Module):
def __init__(self):
super(MyNet, self).__init__() # 第一句话,调用父类的构造函数
self.conv1 = torch.nn.Conv2d(3, 32, 3, 1, 1)
self.relu1=torch.nn.ReLU()
self.max_pooling1=torch.nn.MaxPool2d(2,1)
self.conv2 = torch.nn.Conv2d(3, 32, 3, 1, 1)
self.relu2=torch.nn.ReLU()
self.max_pooling2=torch.nn.MaxPool2d(2,1)
self.dense1 = torch.nn.Linear(32 * 3 * 3, 128)
self.dense2 = torch.nn.Linear(128, 10)
def forward(self, x):
x = self.conv1(x)
x = self.relu1(x)
x = self.max_pooling1(x)
x = self.conv2(x)
x = self.relu2(x)
x = self.max_pooling2(x)
x = self.dense1(x)
x = self.dense2(x)
return x
model = MyNet()
print(model)
import torch
import torch.nn.functional as F
class MyNet(torch.nn.Module):
def __init__(self):
super(MyNet, self).__init__() # 第一句话,调用父类的构造函数
self.conv1 = torch.nn.Conv2d(3, 32, 3, 1, 1)
self.conv2 = torch.nn.Conv2d(3, 32, 3, 1, 1)
self.dense1 = torch.nn.Linear(32 * 3 * 3, 128)
self.dense2 = torch.nn.Linear(128, 10)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = F.max_pool2d(x)
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x)
x = self.dense1(x)
x = self.dense2(x)
return x
model = MyNet()
print(model)
结论:书写在初始化内部更加方便下面forward函数的调用,因为__init__(self)里面的self将声明过的函数“公有化”了。在下面直接使用,如果没有在__init__(self)内部声明。在forward(self, x)内使用需要nn.functional来引入那些无参的函数。(例子中引入了import torch.nn.functional as F,所以直接F.函数了)
二、搭建的具体细节
1、万能的搭建方式
import torch
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
from torch import nn
class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.conv1 = Conv2d(3,32,5,padding=2)
self.maxpool1=MaxPool2d(2)
self.conv2=Conv2d(32,32,5,padding=2)#输入输出的channel到底是什么意思
self.maxpool2=MaxPool2d(2)
self.conv3 = Conv2d(32,64,5,padding=2)
self.maxpool3=MaxPool2d(2)
self.flatten=Flatten()
self.linear1 =Linear(1024,64)
self.linear2=Linear(64,10)
def forward(self,x):
x=self.conv1(x)
x=self.maxpool1(x)
x=self.conv2(x)
x=self.maxpool2(x)
x=self.conv3(x)
x=self.maxpool3(x)
x=self.flatten(x)
x=self.linear1(x)
x=self.linear2(x)
return x
2、通过Sequential来包装层
就是将各个层封装成为一个数组,之后只可以通过下标进行索引(哪怕你给他们起名字)
(1) 最简单的序贯模型
import torch.nn as nn
model = nn.Sequential(
nn.Conv2d(1,20,5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU()
)
print(model)
print(model[2]) # 通过索引获取第几个层
'''
import torch
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch import nn
from torch.utils.tensorboard import SummaryWriter
class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.model1=Sequential(
Conv2d(3,32,5,padding=2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self,x):
x=self.model1(x)
return x
对比:
self.conv1 = Conv2d(3,32,5,padding=2)和Conv2d(3,32,5,padding=2):省略了self.conv1这一步。
x=self.model1(x),直接将这一序列的函数一次性全部执行。
不过这种普通的方法有一个缺陷:只能通过model[i]来获得这个序列里面的特定函数,就相当于使用Sequential,将各个层封装成数组。
(2)给每层添加一个数组
import torch.nn as nn
from collections import OrderedDict
model = nn.Sequential(OrderedDict([
('conv1', nn.Conv2d(1,20,5)),
('relu1', nn.ReLU()),
('conv2', nn.Conv2d(20,64,5)),
('relu2', nn.ReLU())
]))
print(model)
从上面的结果中可以看出,这个时候每一个层都有了自己的名称,但是此时需要注意,我并不能够通过名称直接获取层,依然只能通过索引index,即
model[2] 是正确的
model[“conv2”] 是错误的
(3)使用add_module()来实现
import torch.nn as nn
from collections import OrderedDict
model = nn.Sequential()
model.add_module("conv1",nn.Conv2d(1,20,5))
model.add_module('relu1', nn.ReLU())
model.add_module('conv2', nn.Conv2d(20,64,5))
model.add_module('relu2', nn.ReLU())
print(model)
print(model[2])
nn.Sequential()建立之后就可以使用model.add_module(‘relu2’, nn.ReLU()),来追加层数,不过需要注意依旧只可以通过下标索引。