这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战
在 PyTorch 的 nn,nn 也就是 neural network 的缩写,在 nn 包中有一个 Module 类这是神经网络模块的基类,我们定义层、块大部分都是 Module 的子类。
- 定义 class 并且继承于 nn.Module
- 在 class 中,定义其属性为 layer
- 实现 class 中 forward 方法
class Network:
def __init__(self):
self.layer = None
def forward(self,t):
t = self.layer(t)
return t
复制代码
然后我们在这个基础上进行小小改造就得到了一个 pytorch ,让 Network 继承于 nn.Module
类,好处是 nn.Module
在背后做了很多工作。
class Network(nn.Module):
def __init__(self):
super(Network,self).__init__()
self.layer = None
def forward(self,t):
t = self.layer(t)
return t
复制代码
class Network(nn.Module):
def __init__(self):
super(Network,self).__init__()
self.conv1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=6,out_channels=12,kernel_size=5)
self.fc1 = nn.Linear(in_features=12*4*4,out_features=120)
self.fc2 = nn.Linear(in_features=120,out_features=60)
self.out = nn.Linear(in_features=60,out_features=10)
def forward(self,t):
return t
复制代码
我们可以通过实例化一个网络,然后通过实例来查看一下网络的结构。
network = Network()
network
复制代码
Network( (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) (conv2): Conv2d(6, 12, kernel_size=(5, 5), stride=(1, 1)) (fc1): Linear(in_features=192, out_features=120, bias=True) (fc2): Linear(in_features=120, out_features=60, bias=True) (out): Linear(in_features=60, out_features=10, bias=True) )
复制代码
class CustomLinear(nn.Module):
def __init__(self,in_features,out_features,bias=True):
super(CustomLinear,self).__init__()
self.in_features = in_features
self.out_features = out_features
self.weight = Parameter(torch.Tensor(out_features,in_features))
if bias:
self.bias = Parameter(torch.Tensor(out_features))
else:
self.register_parameter('bias',None)
self.reset_parameters()
def forward(self,input):
return F.linear(input,self.weight,self.bias)
复制代码
这里 Parameter
是继承于 torch.Tensor
的类,这个 self.weight
是模型在训练过程需要通过学习不断更新的变量。在源码中 self.register_parameter(name,value)
对参数进行注册。
我们经常会遇到 argument 和 parameter 这两个词,他们区别是,当调用一个函数传入参数是 argument,argument 是实实在在数值我们传入到要调用函数的数值。而在函数内部持有变量的是 parameter,也就是 parameter 通用于函数内部,出于此原因我们可以将 parameter 看成一个 placeholder。我们可以用 argument 来更新内部的 parameter。
self.conv1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=6,out_channels=12,kernel_size=5)
self.fc1 = nn.Linear(in_features=12*4*4,out_features=120)
self.fc2 = nn.Linear(in_features=120,out_features=60)
self.out = nn.Linear(in_features=60,out_features=10)
复制代码
- Hyperparameter(超参数)
- Data dependent hyperparameter
在 Conv2d 的参数为 in_channels、out_channels 和 kernel_size 三个参数,而对于 Linear 只有 in_features 和 out_features 两个参数。那么 Hyperparameter 超参数是人为选定的参数,但是并不是随意选择,主要基于验证和误差反馈来选择利于得到好的效果来调整这些参数。在卷积层和全连接层 kernel_size
,out_features
和 out_channels
是人为定义参数。
其中 conv1 的 in_channels 和 out 全连接层 out_features 依赖数据和任务的,所以这些参数是 Data dependent hyperparameter 的参数。