import torch
from torch import nn
print(torch.__version__)
class MLP(nn.Module):
# 声明模型参数层
def __init__(self, **kwargs):
# 初始化
# **kwargs 表示函数接收可变长度的关键字参数字典
# super() 用来调用父类
super(MLP,self).__init__(**kwargs)
self.hidden = nn.Linear(784,256) # 声明隐藏层
self.act = nn.ReLU() # 添加激活函数
self.output = nn.Linear(256,10) # 添加输出层
# 定义模型向前计算
def forward(self,x):
a = self.act(self.hidden(x))
return self.output(a)
X = torch.rand(2,784)
#随机产生两组样本
net = MLP() # 调用父类
print(net) # 查看MLP结构
# 网络模型为:隐藏层Linear(in_features=784, out_features=256, bias=True)
# 激活函数:ReLU()
# 输出层为:Linear(in_features=256, out_features=10, bias=True)
net(X) # 输出结果,输出2行10列的tensor
Module 的子类
Sequential 类
class MySequential(nn.Module):
from collections import OrderedDict
def __init__(self, *args): # *args表示函数接收可变长度的关键字参数字典
super(MySequential, self).__init__()
if len(args) == 1 and isinstance(args[0], OrderedDict):
# isinstance90 用来判断对象是否为某个类的实例
for key, module in args[0].item():
self.add_module(key, module)
else:
for idx, module in enumerate(args):
self.add_module(str(idx), module) # 添加module
def forward(self, input): # 向前传播
for module in self._modules.values():
input = module(input)
return input
net = MySequential(
nn.Linear(784,256),
nn.ReLU(),
nn.Linear(256,10),
)
print(net)
# 网络模型为:隐藏层Linear(in_features=784, out_features=256, bias=True)
# 激活函数:ReLU()
# 输出层为:Linear(in_features=256, out_features=10, bias=True)
net(X)
# 输出一次向前计算结果,输出2行10列的tensor
ModuleList 类
# 接受列表作为输入
net = nn.ModuleList([nn.Linear(784,256),nn.ReLU()])
net.append(nn.Linear(256,10))
print(net[-1])
# 输出net中最后一个输出层 Linear(in_features=256, out_features=10, bias=True)
print(net)
ModuleDict 类
net = nn.ModuleDict({
'linear':nn.Linear(784,256),
'act':nn.ReLU(),
})
#类似字典的访问方法
net['output']=nn.Linear(256,10)
# 查看单层模型
print(net['linear'])
print(net.output)
print(net) # 查看整个网络模型
构造复杂模型
class FancyMLP(nn.Module):
def __init__(self):
super(FancyMLP, self).__init__()
self.rand_weight = torch.rand((20, 20), requires_grad=False) #常数参数
# 权重参数不迭代
self.linear = nn.Linear(20, 20)
def forward(self, x):
x = self.linear(x)
# 使用创建的常数参数
x = nn.functional.relu(torch.mm(x, self.rand_weight.data) + 1)
# 复用全连接层。等价于两个全连接层共享参数
x = self.linear(x)
# 控制流,这里我们需要调用item函数来返回标量进行比较
while x.norm().item() > 1:
x /= 2
if x.norm().item() < 0.8:
x *= 10
return x.sum()
X = torch.rand(2, 20)
net = FancyMLP()
print(net) # 只有一层结构
net(X)
class NestMLP(nn.Module):
def __init__(self):
super(NestMLP, self).__init__()
self.net = nn.Sequential(nn.Linear(40, 30), nn.ReLU())
def forward(self, x):
return self.net(x)
net = nn.Sequential(NestMLP(), nn.Linear(30, 20), FancyMLP())
#嵌套调用FancyMLP和Sequential
X = torch.rand(2, 40)
print(net) # 多层复合网络模型
net(X)