提交 659db800 编写于 作者: A Aston Zhang

dl compute class deaccent

上级 6df3fa14
......@@ -49,13 +49,13 @@ class MLP(nn.Block):
* `__init__`:创建模型的参数。在上面的例子里,模型的参数被包含在了两个`Dense`层里。
* `forward`:定义模型的计算。
接下来我们解释一下`MLP`里面用的其他命令:
接下来我们解释一下MLP类用的其他命令:
* `super(MLP, self).__init__(**kwargs)`:这句话调用`MLP`父类Block的构造函数`__init__`。这样,我们在调用`MLP`的构造函数时还可以指定函数参数`prefix`(名字前缀)或`params`(模型参数,下一节会介绍)。这两个函数参数将通过`**kwargs`传递给Block的构造函数。
* `super(MLP, self).__init__(**kwargs)`:这句话调用MLP父类Block的构造函数`__init__`。这样,我们在调用`MLP`的构造函数时还可以指定函数参数`prefix`(名字前缀)或`params`(模型参数,下一节会介绍)。这两个函数参数将通过`**kwargs`传递给Block的构造函数。
* `with self.name_scope()`:本例中的两个`Dense`层和其中模型参数的名字前面都将带有模型名前缀。该前缀可以通过构造函数参数`prefix`指定。若未指定,该前缀将自动生成。我们建议,在构造模型时将每个层至少放在一个`name_scope()`里。
* `with self.name_scope()`:本例中的两个Dense层和其中模型参数的名字前面都将带有模型名前缀。该前缀可以通过构造函数参数`prefix`指定。若未指定,该前缀将自动生成。我们建议,在构造模型时将每个层至少放在一个`name_scope()`里。
我们可以实例化`MLP`类得到`net2`,并让`net2`根据输入数据`x`做一次计算。其中,`y = net2(x)`明确调用了`MLP`中的`__call__`函数(从Block继承得到)。在Gluon中,这将进一步调用`MLP`中的`forward`函数从而完成一次模型计算。
我们可以实例化MLP类得到`net2`,并让`net2`根据输入数据`x`做一次计算。其中,`y = net2(x)`明确调用了MLP实例中的`__call__`函数(从Block继承得到)。在Gluon中,这将进一步调用`MLP`中的`forward`函数从而完成一次模型计算。
```{.python .input n=4}
net = MLP()
......@@ -73,7 +73,7 @@ print('hidden layer name with "my_mlp_" prefix:', net.hidden.name)
print('output layer name with "my_mlp_" prefix:', net.output.name)
```
接下来,我们重新定义`MLP_NO_NAMESCOPE`类。它和`MLP`的区别就是不含`with self.name_scope():`。这是,隐藏层和输出层的名字前都不再含指定的前缀`prefix`
接下来,我们重新定义MLP_NO_NAMESCOPE类。它和`MLP`的区别就是不含`with self.name_scope():`。这是,隐藏层和输出层的名字前都不再含指定的前缀`prefix`
```{.python .input n=6}
class MLP_NO_NAMESCOPE(nn.Block):
......@@ -95,9 +95,9 @@ print('output layer name without prefix:', net.output.name)
Block主要提供模型参数的存储、模型计算的定义和自动求导。你也许已经发现了,以上Block的子类中并没有定义如何求导,或者是`backward`函数。事实上,MXNet会使用`autograd``forward`自动生成相应的`backward`函数。
### `Sequential`类是Block的子类
### Sequential类是Block的子类
在Gluon里,`Sequential`类是Block的子类。`Sequential`类或实例也可以被看作是一个Block的容器:通过`add`函数来添加Block。在`forward`函数里,`Sequential`实例把添加进来的Block逐一运行。
在Gluon里,Sequential类是Block的子类。Sequential类或实例也可以被看作是一个Block的容器:通过`add`函数来添加Block。在`forward`函数里,Sequential实例把添加进来的Block逐一运行。
一个简单的实现是这样的:
......
# 自定义层
深度学习的一个魅力之处在于神经网络中各式各样的层,例如全连接层和后面章节中将要介绍的卷积层、池化层与循环层。虽然Gluon提供了大量常用的层,但有时候我们依然希望自定义层。本节将介绍如何使用`NDArray`来自定义一个Gluon的层,从而以后可以被重复调用。
深度学习的一个魅力之处在于神经网络中各式各样的层,例如全连接层和后面章节中将要介绍的卷积层、池化层与循环层。虽然Gluon提供了大量常用的层,但有时候我们依然希望自定义层。本节将介绍如何使用NDArray来自定义一个Gluon的层,从而以后可以被重复调用。
## 不含模型参数的自定义层
......@@ -14,7 +14,7 @@ from mxnet import nd, gluon
from mxnet.gluon import nn
```
下面通过继承Block自定义了一个将输入减掉均值的层`CenteredLayer`,并将层的计算放在`forward`函数里。这个层里不含模型参数。
下面通过继承Block自定义了一个将输入减掉均值的层:CenteredLayer类,并将层的计算放在`forward`函数里。这个层里不含模型参数。
```{.python .input n=1}
class CenteredLayer(nn.Block):
......@@ -52,7 +52,7 @@ y.mean()
## 含模型参数的自定义层
我们还可以自定义含模型参数的自定义层。这样,自定义层里的模型参数就可以通过训练学出来了。我们在[“模型参数”](parameters.md)一节里介绍了`Parameter`类。其实,在自定义层的时候我们还可以使用Block自带的`ParameterDict`类型的成员变量`params`。顾名思义,这是一个由字符串类型的参数名字映射到`Parameter`类型的模型参数的字典。我们可以通过`get``ParameterDict`创建`Parameter`
我们还可以自定义含模型参数的自定义层。这样,自定义层里的模型参数就可以通过训练学出来了。我们在[“模型参数”](parameters.md)一节里介绍了Parameter类。其实,在自定义层的时候我们还可以使用Block自带的ParameterDict类型的成员变量`params`。顾名思义,这是一个由字符串类型的参数名字映射到Parameter类型的模型参数的字典。我们可以通过`get``ParameterDict`创建`Parameter`
```{.python .input n=7}
params = gluon.ParameterDict(prefix="block1_")
......@@ -75,7 +75,7 @@ class MyDense(nn.Block):
return nd.relu(linear)
```
下面,我们实例化`MyDense`来看下它的模型参数。这里我们特意加了名字前缀`prefix`。在[“模型构造”](block.md)一节中介绍过,这是Block的构造函数自带的参数。
下面,我们实例化MyDense类来看下它的模型参数。这里我们特意加了名字前缀`prefix`。在[“模型构造”](block.md)一节中介绍过,这是Block的构造函数自带的参数。
```{.python .input}
dense = MyDense(5, in_units=10, prefix='o_my_dense_')
......
......@@ -44,7 +44,7 @@ net(x)
## 访问模型参数
在Gluon中,模型参数的类型是`Parameter`。下面让我们创建一个名字叫“good_param”、形状为$2 \times 3$的模型参数。在默认的初始化中,模型参数中的每一个元素是一个在`[-0.07, 0.07]`之间均匀分布的随机数。相应地,该模型参数还有一个形状为$2 \times 3$的梯度,初始值为0。
在Gluon中,模型参数的类型是Parameter类。下面让我们创建一个名字叫“good_param”、形状为$2 \times 3$的模型参数。在默认的初始化中,模型参数中的每一个元素是一个在`[-0.07, 0.07]`之间均匀分布的随机数。相应地,该模型参数还有一个形状为$2 \times 3$的梯度,初始值为0。
```{.python .input n=4}
my_param = gluon.Parameter("good_param", shape=(2, 3))
......@@ -53,7 +53,7 @@ print('data: ', my_param.data(), '\ngrad: ', my_param.grad(),
'\nname: ', my_param.name)
```
接下来,让我们访问本节开头定义的多层感知机`net`中隐藏层`hidden`的模型参数:权重`weight`和偏差`bias`。它们的类型也都是`Parameter`。我们可以看到它们的名字、形状和数据类型。
接下来,让我们访问本节开头定义的多层感知机`net`中隐藏层`hidden`的模型参数:权重`weight`和偏差`bias`。它们的类型也都是Parameter类。我们可以看到它们的名字、形状和数据类型。
```{.python .input n=5}
w = net.hidden.weight
......@@ -68,7 +68,7 @@ print('weight:', w.data(), '\nweight grad:', w.grad(), '\nbias:', b.data(),
'\nbias grad:', b.grad())
```
另外,我们也可以通过`collect_params`来访问Block里的所有参数(包括所有的子Block)。它会返回一个名字到对应`Parameter`的字典。在这个字典中,我们既可以用`[]`(需要指定前缀),又可以用`get()`(不需要指定前缀)来访问模型参数。
另外,我们也可以通过`collect_params`来访问Block里的所有参数(包括所有的子Block)。它会返回一个名字到对应Parameter实例的字典。在这个字典中,我们既可以用`[]`(需要指定前缀),又可以用`get`函数(不需要指定前缀)来访问模型参数。
```{.python .input n=7}
params = net.collect_params()
......@@ -130,10 +130,7 @@ print('output layer modified weight:', net.output.weight.data())
## 延后的初始化
我们在本节开头定义的`MLP`模型的层`nn.Dense(4)``nn.Dense(2)`中无需指定它们的输入单元个数。定义`net = MLP()`和输入数据`x`。我们在[“模型构造”](block.md)一节中介绍过,执行`net(x)`将调用`net``forward`函数计算模型输出。在这次计算中,`net`也将从输入数据`x`的形状自动推断模型中每一层尚未指定的输入单元个数,得到模型中所有参数形状,并真正完成模型参数的初始化。因此,在上面两个例子中,我们总是在调用`net(x)`之后访问初始化的模型参数。
这种延后的初始化带来的一大便利是,我们在构造模型时无需指定每一层的输入单元个数。
我们在本节开头定义的MLP类里的层`nn.Dense(4)``nn.Dense(2)`中无需指定它们的输入单元个数。给定`net = MLP()`和输入数据`x`。我们在[“模型构造”](block.md)一节中介绍过,执行`net(x)`将调用`net``forward`函数计算模型输出。在这次计算中,`net`也将从输入数据`x`的形状自动推断模型中每一层尚未指定的输入单元个数,得到模型中所有参数形状,并真正完成模型参数的初始化。因此,在上面两个例子中,我们总是在调用`net(x)`之后访问初始化的模型参数。这种延后的初始化带来的一大便利是,我们在构造模型时无需指定每一层的输入单元个数。
下面,我们具体来看延后的初始化是怎么工作的。让我们新建一个网络并打印所有模型参数。这时,两个全连接层的权重的形状里都有0。它们代表尚未指定的输入单元个数。
......@@ -159,7 +156,7 @@ net.collect_params()
## 共享模型参数
在有些情况下,我们希望模型的多个层之间共享模型参数。这时,我们可以通过Block的`params`来指定模型参数。在下面使用`Sequential`类构造的多层感知机中,模型的第二隐藏层(`net[1]`)和第三隐藏层(`net[2]`)共享模型参数。
在有些情况下,我们希望模型的多个层之间共享模型参数。这时,我们可以通过Block的`params`来指定模型参数。在下面使用Sequential类构造的多层感知机中,模型的第二隐藏层(`net[1]`)和第三隐藏层(`net[2]`)共享模型参数。
```{.python .input n=15}
net = nn.Sequential()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册