Paddle网络结构中的层和模型
Posted 卓晴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Paddle网络结构中的层和模型相关的知识,希望对你有一定的参考价值。
简 介: 这是 Paddle中的模型与层 的内容学习笔记。对于Paddle中的层的构造,操作进行了初步的测试与相关的学习。
关键词
: Layer,Paddle
§01 模型与层
模型是深度学习中的重要概念之一。模型的核心功能是将一组输入变量经过一系列计算,映射到另一组输出变量,该映射函数即代表一种深度学习算法。在Paddle
框架中,模型包括以下两方面内容:
- 一系列层的组合用于进行映射(前向执行)
- 一些参数变量在训练过程中实时更新
本文档中,你将学习如何定义与使用Paddle
模型,并了解模型与层的关系。
一、在Paddle中定义模型与层
在Paddle
中,大多数模型由一系列层组成,层是模型的基础逻辑执行单元。层中持有两方面内容:
- 一方面是计算所需的变量,以临时变量或参数的形式作为层的成员持有
- 另一方面则持有一个或多个具体的
Operator
来完成相应的计算。
1、模型与层
从零开始构建变量、Operator
,从而组建层、模型是一个很复杂的过程,并且当中难以避免的会出现很多冗余代码,因此Paddle
提供了基础数据类型 paddle.nn.Layer
,来方便你快速的实现自己的层和模型。模型和层都可以基于 paddle.nn.Layer
扩充实现,因此也可以说模型只是一种特殊的层。下面将演示如何利用 paddle.nn.Layer
建立自己的模型:
class Model(paddle.nn.Layer):
def __init__(self):
super(Model, self).__init__()
self.flatten = paddle.nn.Flatten()
def forward(self, inputs):
y = self.flatten(inputs)
return y
当前示例中,通过继承 paddle.nn.Layer 的方式构建了一个模型类型 Model ,模型中仅包含一个 paddle.nn.Flatten 层。模型执行时,输入变量inputs会被 paddle.nn.Flatten 层展平。
2、测试用例
x = paddle.to_tensor([[1,2,3],[4,5,6]])
print(x)
model = Model()
y = model(x)
print(y)
Tensor(shape=[2, 3], dtype=int64, place=CPUPlace, stop_gradient=True,
[[1, 2, 3],
[4, 5, 6]])
Tensor(shape=[2, 3], dtype=int64, place=CPUPlace, stop_gradient=True,
[[1, 2, 3],
[4, 5, 6]])
这是什么鬼?结果怎么没有被层展平呢?
将前面的代码修改:
class Model(paddle.nn.Layer):
def __init__(self):
super(Model, self).__init__()
def forward(self, inputs):
y = self.Flatten(inputs)
return y
def Flatten(self, x):
xx = x.numpy().flatten()
return paddle.to_tensor(xx)
x = paddle.to_tensor([[1,2,3],[4,5,6]])
print(x)
model = Model()
y = model(x)
print(y)
可以得到想要的结果了:
Tensor(shape=[2, 3], dtype=int64, place=CPUPlace, stop_gradient=True,
[[1, 2, 3],
[4, 5, 6]])
Tensor(shape=[6], dtype=int64, place=CPUPlace, stop_gradient=True,
[1, 2, 3, 4, 5, 6])
二、子层接口
如果想要访问或修改一个模型中定义的层,则可以调用SubLayer相关的接口。
1、继承子层
以上文创建的简单模型为例,
如果想要查看模型中定义的所有子层:
class Model(paddle.nn.Layer):
def __init__(self):
super(Model, self).__init__()
self.flatten = paddle.nn.Flatten()
def forward(self, inputs):
y = self.Flatten(inputs)
return y
[Flatten()]
----------------------
('flatten', Flatten())
以看到,通过调用 model.sublayers()
接口,打印出了前述模型中持有的全部子层(这时模型中只有一个 paddle.nn.Flatten
子层)。
而遍历 model.named_sublayers()
时,每一轮循环会拿到一组 ( 子层名称('flatten')
,子层对象(paddle.nn.Flatten)
)的元组。
下面增加self中的一个层次,可以看到多出了更多的层。
class Model(paddle.nn.Layer):
def __init__(self):
super(Model, self).__init__()
self.flatten = paddle.nn.Flatten()
self.f1 = paddle.nn.Flatten()
def forward(self, inputs):
y = self.Flatten(inputs)
return y
model = Model()
print(model.sublayers())
print("----------------------")
for item in model.named_sublayers():
print(item)
[Flatten(), Flatten()]
----------------------
('flatten', Flatten())
('f1', Flatten())
2、增加子层
接下来如果想要进一步添加一个子层,则可以调用 add_sublayer()
接口:
fc = paddle.nn.Linear(10, 3)
model.add_sublayer("fc", fc)
print(model.sublayers())
[Flatten(), Linear(in_features=10, out_features=3, dtype=float32)]
可以看到 model.add_sublayer()
向模型中添加了一个 paddle.nn.Linear
子层,这样模型中总共有 paddle.nn.Flatten
和 paddle.nn.Linear
两个子层了。
3、修改子层
通过上述方法可以往模型中添加成千上万个子层,当模型中子层数量较多时,如何高效地对所有子层进行统一修改呢?
Paddle
提供了 apply()
接口。通过这个接口,可以自定义一个函数,然后将该函数批量作用在所有子层上:
def function(layer):
print(layer)
model.apply(function)
Flatten()
Linear(in_features=10, out_features=3, dtype=float32)
Model(
(flatten): Flatten()
(fc): Linear(in_features=10, out_features=3, dtype=float32)
)
当前例子中,定义了一个以layer
作为参数的函数function
,用来打印传入的layer
信息。通过调用 model.apply()
接口,将function
作用在模型的所有子层中,也因此输出信息中打印了model中所有子层的信息。
另外一个批量访问子层的接口是 children()
或者 named_children()
。这两个接口通过Iterator
的方式访问每个子层:
sublayer_iter = model.children()
for sublayer in sublayer_iter:
print(sublayer)
Flatten()
Linear(in_features=10, out_features=3, dtype=float32)
可以看到,遍历 model.children()
时,每一轮循环都可以按照子层注册顺序拿到对应 paddle.nn.Layer 的对象。
三、层中的变量成员
1、参数变量添加与修改
有的时候希望向网络中添加一个参数作为输入。比如在使用图像风格转换模型时,会使用参数作为输入图像,在训练过程中不断更新该图像参数,最终拿到风格转换后的图像。
这时可以通过 create_parameter()
与 add_parameter()
组合,来创建并记录参数:
class Model(paddle.nn.Layer):
def __init__(self):
super(Model, self).__init__()
img = self.create_parameter([1,3,256,256])
self.add_parameter("img", img)
self.flatten = paddle.nn.Flatten()
def forward(self):
y = self.flatten(self.img)
return y
上述例子创建并向模型中添加了一个名字为"img"
的参数。随后可以直接通过调用model.img
来访问该参数。
对于已经添加的参数,可以通过 parameters()
或者 named_parameters()
来访问
model = Model()
model.parameters()
print('--------------------------------------------')
for item in model.named_parameters():
print(item)
[Parameter containing:
Tensor(shape=[1, 3, 256, 256], dtype=float32, place=CPUPlace, stop_gradient=False,
[[[[-0.00323536, 0.00417978, 0.00387184, ..., -0.00263438,
0.00336105, -0.00079275],
[-0.00398997, 0.00305213, 0.00338405, ..., 0.00321609,
0.00385862, 0.00383085],
[ 0.00456822, 0.00335924, -0.00396630, ..., -0.00260351,
0.00388722, 0.00292703],
...,
...,
[-0.00302772, -0.00052290, -0.00259735, ..., 0.00325148,
0.00051726, 0.00464376],
[ 0.00238924, -0.00105374, 0.00219904, ..., -0.00279356,
-0.00214116, -0.00319181],
[ 0.00180969, 0.00476100, 0.00380237, ..., 0.00249749,
0.00374650, 0.00050141]]]])]
---------------------以上是关于Paddle网络结构中的层和模型的主要内容,如果未能解决你的问题,请参考以下文章
森说AI:用paddle2.x完成resnet50模型转写并实现前向对齐