Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
d2l-zh
提交
a915afa5
D
d2l-zh
项目概览
OpenDocCN
/
d2l-zh
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
d2l-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a915afa5
编写于
5月 22, 2018
作者:
A
Aston Zhang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
reg done
上级
0ea6ea43
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
37 addition
and
54 deletion
+37
-54
chapter_supervised-learning/reg-gluon.md
chapter_supervised-learning/reg-gluon.md
+14
-23
chapter_supervised-learning/reg-scratch.md
chapter_supervised-learning/reg-scratch.md
+23
-31
未找到文件。
chapter_supervised-learning/reg-gluon.md
浏览文件 @
a915afa5
# 正则化——使用Gluon
本章介绍如何使用
``Gluon``
的正则化来应对
[
过拟合
](
underfit-overfit.md
)
问题。
## 高维线性回归数据集
我们使用与
[
上一节
](
reg-scratch.md
)
相同的高维线性回归为例来引入一个过拟合问题。
本节将介绍如何使用Gluon实现上一节介绍的正则化。导入实验所需的包或模块。
```
{.python .input n=1}
%matplotlib inline
...
...
@@ -17,6 +13,10 @@ from mxnet import autograd, gluon, init, nd
from mxnet.gluon import data as gdata, loss as gloss, nn
```
## 生成数据集
我们使用和上一节完全一样的方法生成数据集。
```
{.python .input n=2}
n_train = 20
n_test = 100
...
...
@@ -40,7 +40,7 @@ loss = gloss.L2Loss()
## 定义训练和测试
跟前一样定义训练模块。你也许发现了主要区别,
`Trainer`
有一个新参数
`wd`
。我们通过优化算法的
``wd``
参数 (weight decay)实现对模型的正则化。这相当于$L_2$范数正则化
。
在训练和测试的定义中,我们分别定义了两个Trainer实例。其中一个对权重参数做$L_2$范数正则化,另一个并没有对偏差参数做正则化。我们在上一节也提到了,实际中有时也对偏差参数做正则化。这样只需要定义一个Trainer实例就可以了
。
```
{.python .input n=3}
gb.set_fig_size(mpl)
...
...
@@ -48,10 +48,11 @@ gb.set_fig_size(mpl)
def fit_and_plot(weight_decay):
net = nn.Sequential()
net.add(nn.Dense(1))
net.initialize(init.Normal(sigma=
0.0
1))
#
注意到这里 'wd'
net.initialize(init.Normal(sigma=1))
#
对权重参数做L2范数正则化,即权重衰减。
trainer_w = gluon.Trainer(net.collect_params('.*weight'), 'sgd', {
'learning_rate': learning_rate, 'wd': weight_decay})
# 不对偏差参数做L2范数正则化。
trainer_b = gluon.Trainer(net.collect_params('.*bias'), 'sgd', {
'learning_rate': learning_rate})
train_ls = []
...
...
@@ -76,36 +77,26 @@ def fit_and_plot(weight_decay):
return 'w[:10]:', net[0].weight.data()[:,:10], 'b:', net[0].bias.data()
```
##
# 训练模型并观察过拟合
##
观察实验结果
接下来我们训练并测试我们的高维线性回归模型
。
以下实验结果和上一节中的类似
。
```
{.python .input n=4}
fit_and_plot(0)
```
即便训练误差可以达到0.000000,但是测试数据集上的误差很高。这是典型的过拟合现象。
观察学习的参数。事实上,大部分学到的参数的绝对值比真实参数的绝对值要大一些。
## 使用``Gluon``的正则化
下面我们重新初始化模型参数并在
`Trainer`
里设置一个
`wd`
参数。
```
{.python .input n=5}
fit_and_plot(5)
```
我们发现训练误差虽然有所提高,但测试数据集上的误差有所下降。过拟合现象得到缓解。
但打印出的学到的参数依然不是很理想,这主要是因为我们训练数据的样本相对维度来说太少。
## 小结
*
使用
``Gluon``
的
`weight decay`
参数可以很容易地使用正则化来应对过拟合问题。
*
使用Gluon的
`wd`
超参数可以使用正则化来应对过拟合问题。
*
我们可以定义多个Trainer实例对不同的模型参数使用不同的迭代方法。
## 练习
*
如何从字面正确理解
`weight decay`
的含义?它为何相当于$L_2$范式正则化?
*
调一调本节实验中的
`wd`
超参数。观察并分析实验结果。
## 扫码直达[讨论区](https://discuss.gluon.ai/t/topic/985)
...
...
chapter_supervised-learning/reg-scratch.md
浏览文件 @
a915afa5
...
...
@@ -36,9 +36,9 @@ from matplotlib import pyplot as plt
from mxnet import autograd, gluon, nd
```
## 生成数据集
##
#
生成数据集
对于训练数据集和测试数据集中特征为$x_1, x_2,
\l
dots, x_p$的任一样本,我们使用如下的线性函数来生成该样本的标签:
设数据样本特征的维度为$p$。
对于训练数据集和测试数据集中特征为$x_1, x_2,
\l
dots, x_p$的任一样本,我们使用如下的线性函数来生成该样本的标签:
$$y = 0.05 +
\s
um_{i = 1}^p 0.01x_i +
\e
psilon,$$
...
...
@@ -59,13 +59,13 @@ train_features, test_features = features[:n_train, :], features[n_train:, :]
train_labels, test_labels = labels[:n_train], labels[n_train:]
```
## 初始化模型参数
##
#
初始化模型参数
下面
我们随机初始化模型参数。之后训练时我们需要对这些参数求导来更新它们的值,所以我们需要创建它们的
梯度。
下面
定义函数来随机初始化模型参数,并为它们附上
梯度。
```
{.python .input n=5}
def init_params():
w = nd.random.normal(scale=
0.0
1, shape=(num_inputs, 1))
w = nd.random.normal(scale=1, shape=(num_inputs, 1))
b = nd.zeros(shape=(1,))
params = [w, b]
for param in params:
...
...
@@ -73,30 +73,24 @@ def init_params():
return params
```
## $L_2$范数正则化
这里我们引入$L_2$范数正则化。不同于在训练时仅仅最小化损失函数(Loss),我们在训练时其实在最小化
### 定义$L_2$范数惩罚项
$$
\t
ext{loss} +
\l
ambda
\s
um_{p
\i
n
\t
extrm{params}}
\|
p
\|
_2^2。$$
直观上,$L_2$范数正则化试图惩罚较大绝对值的参数值。下面我们定义L2正则化。注意有些时候大家对偏移加罚,有时候不加罚。通常结果上两者区别不大。这里我们演示对偏移也加罚的情况:
下面定义$L_2$范数惩罚项。这里只惩罚模型的权重参数。
```
{.python .input n=6}
def l2_penalty(w):
return (w**2).sum() / 2
```
```
{.python .input}
num_epochs = 10
lr = 0.003
```
## 定义训练和测试
### 定义训练和测试
下面
我们定义剩下的所需要的函数。这个跟之前的教程大致一样,主要是区别在于计算
`loss`
的时候我们加上了L2正则化,以及我们将训练和测试损失都画了出来
。
下面
定义如何在训练数据集和测试数据集上分别训练和测试模型。和前面几节中不同的是,这里在计算最终的损失函数时添加了$L_2$范数惩罚项
。
```
{.python .input n=7}
batch_size = 1
num_epochs = 10
lr = 0.003
net = gb.linreg
loss = gb.squared_loss
gb.set_fig_size(mpl)
...
...
@@ -108,6 +102,7 @@ def fit_and_plot(lambd):
for _ in range(num_epochs):
for X, y in gb.data_iter(batch_size, n_train, features, labels):
with autograd.record():
# 添加了 L2 范数惩罚项。
l = loss(net(X, w, b), y) + lambd * l2_penalty(w)
l.backward()
gb.sgd(params, lr, batch_size)
...
...
@@ -124,36 +119,33 @@ def fit_and_plot(lambd):
return 'w[:10]:', w[:10].T, 'b:', b
```
## 观察过拟合
##
#
观察过拟合
接下来
我们训练并测试我们的高维线性回归模型。注意这时我们并未使用正则化
。
接下来
,让我们训练并测试高维线性回归模型。当
`lambd`
设为0时,我们没有使用正则化。结果训练误差远小于测试数据集上的误差。这是典型的过拟合现象
。
```
{.python .input n=8}
fit_and_plot(0)
fit_and_plot(
lambd=
0)
```
即便训练误差可以达到0.000000,但是测试数据集上的误差很高。这是典型的过拟合现象。
### 使用正则化
观察学习的参数。事实上,大部分学到的参数的绝对值比真实参数的绝对值要大一些
。
下面我们使用$L_2$范数正则化。我们发现训练误差虽然有所提高,但测试数据集上的误差有所下降。过拟合现象得到一定程度上的缓解。另外,学到的权重参数的绝对值比不使用正则化时相比更接近0
。
## 使用正则化
下面我们重新初始化模型参数并设置一个正则化参数。
然而,即便是使用了正则化的模型依然没有学出较准确的模型参数。这主要是因为训练数据集的样本数相对维度来说太小。
```
{.python .input n=9}
fit_and_plot(5)
fit_and_plot(
lambd=
5)
```
我们发现训练误差虽然有所提高,但测试数据集上的误差有所下降。过拟合现象得到缓解。但打印出的学到的参数依然不是很理想,这主要是因为我们训练数据的样本相对维度来说太少。
## 小结
*
我们可以使用正则化来应对过拟合问题。
*
$L_2$范数正则化通常会使学到的权重参数的元素较接近0。
*
$L_2$范数正则化也叫权重衰减。
## 练习
*
除了正则化、增大训练量、以及使用
合适的模型,你觉得还有
哪些办法可以应对过拟合现象?
*
除了正则化、增大训练量、以及使用
复杂度合适的模型,你还能想到
哪些办法可以应对过拟合现象?
*
如果你了解贝叶斯统计,你觉得$L_2$范数正则化对应贝叶斯统计里的哪个重要概念?
## 扫码直达[讨论区](https://discuss.gluon.ai/t/topic/984)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录