深度学习初级课程 5.剪枝、批量标准化

深度学习初级课程

  • 1.单一神经元
  • 2.深度神经网络
  • 3.随机梯度下降法
  • 4.过拟合和欠拟合
  • 5.剪枝、批量标准化
  • 6.二值化分类

Dropout 这个单词 原义是退学学生;拒绝传统社会的人;【计算机】磁盘信息失落;漏失信息,丢失信息
在这里是丢弃部分单元(神经元)的含义,如果从树的搜索概念来讲用剪枝这个词更能休现其真正的意境。

正文

介绍

深度学习的世界不仅仅是密集的层次。可以向模型中添加几十种图层。(尝试浏览Keras文档以获取示例!)有些像致密层,定义神经元之间的连接,而另一些可以进行预处理或其他类型的转换。

在这节课中,我们将学习两种特殊的层,它们本身不包含任何神经元,但它们添加了一些功能,有时可以以各种方式使模型受益。两者都是现代体系结构中常用的。

Dropout (剪枝)

第一个是dropout layer,它可以帮助纠正过拟合。

在上一课中,我们讨论了网络学习训练数据中的虚假模式是如何导致过度拟合的。为了识别这些虚假模式,网络通常会依赖非常特定的权重组合,这是一种权重的“阴谋”。由于如此具体,它们往往是脆弱的:移除一个,阴谋就会瓦解。

这就是droput背后的想法。为了打破这些阴谋,我们在训练的每一步都随机删除一层输入单元的一小部分,这使得网络更难从训练数据中学习这些虚假模式。相反,它必须寻找广泛的、一般的模式,其权重模式往往更稳健。


在这里,在两个隐藏层之间添加了 50% 的 dropout

你也可以把辍学看作是创造一种网络的集合。这些预测将不再由一个大型网络做出,而是由一个由小型网络组成的委员会做出。委员会中的每个人往往会犯各种各样的错误,但同时也要正确,使委员会作为一个整体比任何个人都好。(如果你熟悉随机森林作为决策树的集合,这是同样的想法。)

增加 Dropout

在Keras中,dropout rate 参数rate定义了要关闭的输入单元的百分比。将 Dropout 层放在要应用 dropout 的层之前:

keras.Sequential([
    # ...
    layers.Dropout(rate=0.3), # apply 30% dropout to the next layer
    layers.Dense(16),
    # ...
])

批量标准化

我们将看到的下一个特殊层执行“batch normalization”(或“batchnorm”),这有助于纠正缓慢或不稳定的训练。

对于神经网络,将所有数据放在一个通用的尺度上通常是个好主意,也许可以使用scikit-learn的StandardScaler或MinMaxScaler之类的工具。原因是,SGD将根据数据产生的激活量按比例改变网络权重。倾向于产生不同大小激活的功能可能会导致不稳定的训练行为。

现在,如果在数据进入网络之前对其进行规范化是好的,那么在网络内部进行规范化可能会更好!事实上,我们有一种特殊的层可以做到这一点, batch normalization layer批量标准化层。批次标准化层在每个批次进入时查看它,首先用其自身的平均值和标准偏差对该批次进行标准化,然后用两个可训练的重新缩放参数将数据放在一个新的尺度上。实际上,Batchnorm对其输入执行一种协调的重新缩放作用。

大多数情况下,batchnorm是作为优化过程的辅助工具添加的(尽管它有时也有助于预测性能)。使用batchnorm的模型往往需要较少的时间来完成训练。此外,batchnorm还可以解决可能导致训练“停滞”的各种问题。考虑为模型添加批量标准化,尤其是在训练期间遇到问题时。

添加批量标准化

看起来,批量标准几乎可以在网络中的任何一点上使用。你可以把它放在一层之后…

layers.Dense(16, activation='relu'),
layers.BatchNormalization(),

# 或放在层与其激活功能之间:
layers.Dense(16),
layers.BatchNormalization(),
layers.Activation('relu'),

如果你把它作为网络的第一层,它可以充当一种自适应预处理器,代替sk-learn的StandardScaler。

示例-使用剪枝和批量标准化

让我们继续研究红酒模型。现在,我们将进一步增加容量,但添加dropout以控制过度拟合和批量标准化以加快优化。这一次,我们还将停止标准化数据,以演示批量标准化如何稳定训练。

# Setup plotting
import matplotlib.pyplot as plt

plt.style.use('seaborn-whitegrid')
# Set Matplotlib defaults
plt.rc('figure', autolayout=True)
plt.rc('axes', labelweight='bold', labelsize='large',
       titleweight='bold', titlesize=18, titlepad=10)


import pandas as pd
red_wine = pd.read_csv('../input/dl-course-data/red-wine.csv')

# Create training and validation splits
df_train = red_wine.sample(frac=0.7, random_state=0)
df_valid = red_wine.drop(df_train.index)

# Split features and target
X_train = df_train.drop('quality', axis=1)
X_valid = df_valid.drop('quality', axis=1)
y_train = df_train['quality']
y_valid = df_valid['quality']

添加dropout 时,可能需要增加密集层中的单元数。

from tensorflow import keras
from tensorflow.keras import layers

model = keras.Sequential([
    layers.Dense(1024, activation='relu', input_shape=[11]),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(1024, activation='relu'),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(1024, activation='relu'),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(1),
])

这次我们的训练安排没有什么可改变的。

model.compile(
    optimizer='adam',
    loss='mae',
)

history = model.fit(
    X_train, y_train,
    validation_data=(X_valid, y_valid),
    batch_size=256,
    epochs=100,
    verbose=0,
)


# Show the learning curves
history_df = pd.DataFrame(history.history)
history_df.loc[:, ['loss', 'val_loss']].plot();

深度学习初级课程 5.剪枝、批量标准化
如果在将数据用于训练之前对其进行标准化,通常会获得更好的性能。然而,我们完全能够使用原始数据,这表明在更困难的数据集上,批量标准化是多么有效。

轮到你了

继续改进Spotify数据集的预测,看看批量标准化如何帮助处理困难的数据集。

练习部分

介绍

在本练习中,您将向练习4中的Spotify模型添加dropout,并了解批量标准化如何让您在困难的数据集上成功地训练模型。
运行下一个单元格开始!

# Setup plotting
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
# Set Matplotlib defaults
plt.rc('figure', autolayout=True)
plt.rc('axes', labelweight='bold', labelsize='large',
       titleweight='bold', titlesize=18, titlepad=10)
plt.rc('animation', html='html5')

# Setup feedback system
from learntools.core import binder
binder.bind(globals())
from learntools.deep_learning_intro.ex5 import *

加载 Spotify数据集

import pandas as pd
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import make_column_transformer
from sklearn.model_selection import GroupShuffleSplit

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import callbacks

spotify = pd.read_csv('../input/dl-course-data/spotify.csv')

X = spotify.copy().dropna()
y = X.pop('track_popularity')
artists = X['track_artist']

features_num = ['danceability', 'energy', 'key', 'loudness', 'mode',
                'speechiness', 'acousticness', 'instrumentalness',
                'liveness', 'valence', 'tempo', 'duration_ms']
features_cat = ['playlist_genre']

preprocessor = make_column_transformer(
    (StandardScaler(), features_num),
    (OneHotEncoder(), features_cat),
)

def group_split(X, y, group, train_size=0.75):
    splitter = GroupShuffleSplit(train_size=train_size)
    train, test = next(splitter.split(X, y, groups=group))
    return (X.iloc[train], X.iloc[test], y.iloc[train], y.iloc[test])

X_train, X_valid, y_train, y_valid = group_split(X, y, artists)

X_train = preprocessor.fit_transform(X_train)
X_valid = preprocessor.transform(X_valid)
y_train = y_train / 100
y_valid = y_valid / 100

input_shape = [X_train.shape[1]]
print("Input shape: {}".format(input_shape))

Input shape: [18]

在Spotify模型中添加dropout

这是练习4中的最后一个模型。添加两个dropout 层,一个位于128个单元的密集层之后,另一个位于64个单元的密集层之后。将两者的dropout_rate设置为0.3。

# YOUR CODE HERE: Add two 30% dropout layers, one after 128 and one after 64
# 以下代码各添加两个30% dropout 的层 
model = keras.Sequential([
    layers.Dense(128, activation='relu', input_shape=input_shape),
    layers.Dense(64, activation='relu'),
    layers.Dense(1)
])

# Check your answer
q_1.check()

现在运行下一个单元来训练模型,看看添加dropout的效果。

model.compile(
    optimizer='adam',
    loss='mae',
)
history = model.fit(
    X_train, y_train,
    validation_data=(X_valid, y_valid),
    batch_size=512,
    epochs=50,
    verbose=0,
)
history_df = pd.DataFrame(history.history)
history_df.loc[:, ['loss', 'val_loss']].plot()
print("Minimum Validation Loss: {:0.4f}".format(history_df['val_loss'].min()))

Minimum Validation Loss: 0.1908
深度学习初级课程 5.剪枝、批量标准化

2) 评估dropout情况

回想练习4,该模型倾向于过拟合第5epoch 前后的数据。这次增加dropout似乎有助于防止过度拟合吗?

从学习曲线可以看出,即使训练损失继续减少,验证损失仍保持在一个恒定的最小值附近。所以我们可以看到,增加dropout确实防止了这次的过拟合。此外,通过使网络更难适应虚假模式,dropout可能会鼓励网络寻找更多真实模式,也可能会改善验证损失(有些情况下也是如此)。

现在,我们将切换话题,探索批处理规范化如何解决训练中的问题。
加载具体的数据集。这次我们不会进行任何标准化。这将使批量标准化的效果更加明显。

import pandas as pd

concrete = pd.read_csv('../input/dl-course-data/concrete.csv')
df = concrete.copy()

df_train = df.sample(frac=0.7, random_state=0)
df_valid = df.drop(df_train.index)

X_train = df_train.drop('CompressiveStrength', axis=1)
X_valid = df_valid.drop('CompressiveStrength', axis=1)
y_train = df_train['CompressiveStrength']
y_valid = df_valid['CompressiveStrength']

input_shape = [X_train.shape[1]]

运行下面的单元,在非标准的具体数据上训练网络。

model = keras.Sequential([
    layers.Dense(512, activation='relu', input_shape=input_shape),
    layers.Dense(512, activation='relu'),    
    layers.Dense(512, activation='relu'),
    layers.Dense(1),
])
model.compile(
    optimizer='sgd', # SGD is more sensitive to differences of scale
    loss='mae',
    metrics=['mae'],
)
history = model.fit(
    X_train, y_train,
    validation_data=(X_valid, y_valid),
    batch_size=64,
    epochs=100,
    verbose=0,
)
​
history_df = pd.DataFrame(history.history)
history_df.loc[0:, ['loss', 'val_loss']].plot()
print(("Minimum Validation Loss: {:0.4f}").format(history_df['val_loss'].min()))

Minimum Validation Loss: nan
深度学习初级课程 5.剪枝、批量标准化
你有没有得到一张空白的图表?尝试在此数据集上训练此网络通常会失败。即使它确实收敛(由于幸运的权重初始化),它也倾向于收敛到一个非常大的数字。

3) 添加批量标准化层

批处理规范化可以帮助纠正这样的问题。
添加四个层,每个密集层前一个。(请记住将input_shape参数移动到新的第一层。)

# YOUR CODE HERE: Add a BatchNormalization layer before each Dense layer
# 以下代码添加批量标准化
model = keras.Sequential([
    layers.Dense(512, activation='relu', input_shape=input_shape),
    layers.Dense(512, activation='relu'),
    layers.Dense(512, activation='relu'),
    layers.Dense(1),
])

# Check your answer
q_3.check()

运行下一个单元格,看看批量标准化是否能让我们训练模型。

model.compile(
    optimizer='sgd',
    loss='mae',
    metrics=['mae'],
)
EPOCHS = 100
history = model.fit(
    X_train, y_train,
    validation_data=(X_valid, y_valid),
    batch_size=64,
    epochs=EPOCHS,
    verbose=0,
)

history_df = pd.DataFrame(history.history)
history_df.loc[0:, ['loss', 'val_loss']].plot()
print(("Minimum Validation Loss: {:0.4f}").format(history_df['val_loss'].min()))

Minimum Validation Loss: 3.7906

4) 评估批量标准化

添加批量标准化有帮助吗?

您可以看到,与第一次尝试相比,添加批量标准化是一个很大的改进!通过在数据通过网络时自适应地缩放数据,批量标准化可以让您在困难的数据集上训练模型。

继续前进

创建用于二分类的神经网络。

答案

# 1)增加dropout
model = keras.Sequential([
    layers.Dense(128, activation='relu', input_shape=input_shape),
    layers.Dropout(0.3),
    layers.Dense(64, activation='relu'),
    layers.Dropout(0.3),
    layers.Dense(1)
])


# 3)增加批量标准化
model = keras.Sequential([
    layers.BatchNormalization(input_shape=input_shape),
    layers.Dense(512, activation='relu'),
    layers.BatchNormalization(),
    layers.Dense(512, activation='relu'),
    layers.BatchNormalization(),
    layers.Dense(512, activation='relu'),
    layers.BatchNormalization(),
    layers.Dense(1),
])

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2022年5月18日
下一篇 2022年5月18日

相关推荐