【深度学习(deep learning)】花书第11章 实践方法论 读书笔记

【深度学习(deep learning)】花书第11章 实践方法论 读书笔记


前言

打基础,阅读花书,感觉一次性啃不动。看一点算一点,写一点笔记留作纪念。以便日后查看与回顾。炼丹啦,炼丹啦,我是炼丹的小行家~ 2020.12.5-2020.12.5

以下是正式内容。

一、实践方法论 走进丹方

1.确定目标,明确任务要干什么,并且选定对应的误差度量指标,设定目标值。
2.构建一个端到端的工作流程。包括数据、模型、评估等部分。数据部分保证要有一个合适的输入,模型部分保证要有一个基本正确的输出,评估部分落实度量指标的计算,指导优化,并进行结果的可视化。
3.搭建系统,分析性能。确定性能瓶颈,对低于预期的部分进行分析找出原因。
4.根据分析结果,反复调整、优化模型。比如收集新数据调整超参数,改进算法等。

二、性能度量

西瓜书上有更详细的介绍,这里就只放一些公式和简要的说明

不同的任务对应不同的性能度量指标。要有一个初步的目标性能预期。

2.1 分类

  • 准确率误差
    误差 error rate :输出错误的样本的比例
    准确率 accuracy:输出正确的样本的比例 = 1 - err
    A C C = T P + T N T P + F N + F P + T N ACC=\frac{TP+TN}{TP+FN+FP+TN} ACC=TP+FN+FP+TNTP+TN
  • 查准率 / 查全率 / F1度量
    混淆矩阵(图来自参考文献3)混淆矩阵
    查准率 / 精度 / precision:希望 查到的,都是真的;也就是宁可放过一千,不可错杀一个 P = T P T P + F P P=\frac{TP}{TP+FP} P=TP+FPTP
    查全率 / 召回率 / recall:希望 真的,都能被查到;也就是宁可错杀一千,不能放过一个 R = T P T P + F N R=\frac{TP}{TP+FN} R=TP+FNTP
    F1度量:查准和查全的调和平均 F 1 = 2 × P × R P + R F1=\frac{2\times P\times R}{P+R} F1=P+R2×P×R
  • PR曲线 / ROC曲线 / AUC面积
    PR曲线:查准率P为y轴,查全率R为x轴。
    ROC曲线:真正例率TPR为y轴,假正例率FPR为x轴。
    T P R = R = T P T P + F N TPR=R=\frac{TP}{TP+FN} TPR=R=TP+FNTP F P R = F P F P + T N FPR=\frac{FP}{FP+TN} FPR=FP+TNFP
    AUC面积:ROC曲线下的面积
  • 覆盖
    分类结果是有置信度的,当分类置信度不够时,模型可能会拒绝预测。在合理置信度区间的结果才是可接受的,模型才会响应
    覆盖:系统能产生响应的样本的比率。

2.2 回归(略)

2.3 聚类(略)

2.4 降维(略)

三、基准模型 baseline

加粗样式对应不同任务需求,尽快地建立一个端到端的模型,从一个简单的机器学习/深度学习模型开始。
1.一个简单的任务,可以先使用简单统计模型,如逻辑回归。
2.AI完全的任务,如对象识别、语音识别、机器翻译等要使用深度模型。

  • 根据数据:定长向量的有监督学习,使用全连接前馈网络(激活函数选relu函数);有一定固定拓扑结构的,使用卷积网络;如果输入或输出是序列,可以使用循环网络。
  • 优化算法:具有衰减学习率以及动量的SGD;或者Adam算法。可以加入批标准化(BN层) 帮助优化,特别是卷积网络与具有非线性函数的网络。
  • 正则化:可以先加一点的正则化;应用早停;使用dropout,或者使用BN层代替dropout
  • 使用现成的模型:卷积网络可以从ResNet,AlexNet开始,循环网络使用LSTM及其各种变体等。图像任务可以使用imagenet中各种成熟的卷积网络迁移过去。
  • 配合一些无监督模型:自然语言处理中,可以加入词嵌入等。如果没有这样的特定需要,可以不在基准模型中加这样的无监督学习过程。

有了基准模型,运行数据集,就可以得到结果,根据性能度量决定如何改进算法。改进首先考虑的是扩充数据集/改善数据集,而不是替换模型算法。如果扩充数据依旧不可行,那就只能改进学习算法本身。

  1. 如何决定是否需要添加数据?
    首先,考虑训练集的结果是否可接受。如果训练集上性能都很差,说明模型的容量不够,这时候没有必要添加数据,而是要去改善模型的容量。可以尝试调整超参数等改善当前的算法。如果精心调整过后,依然表现不佳,那可能问题出在了数据上。可以进行数据改善,如重新清洗,或重新收集更干净的数据,或者重新提取特征。
    当训练集的结果可接受后,考虑测试集性能。 如果测试集性能比训练集差得多,那么就可以考虑收集更多的数据。但是要考虑收集数据的成本问题,如果成本太高,可以改进正则化、降低容量等。如果调整正则化后,测试集结果依旧不可接受,收集数据就是必要的。

  2. 收集多少数据?
    绘制曲线,观察训练集规模和泛化误差之间的关系。一般而言,要在对数尺度上改变规模,才有显著提升,如倍增数据。

四、调参 开始炼丹

超参数选择的两种基本方法:手动选择,自动选择。

4.1 手动选择

需要了解超参数的工作机理,它是如何影响模型的,如何限制/提升模型的性能的,它对训练误差/泛化误差/计算资源的影响。

学习率可能是最重要的参数。
炼丹守则

4.2 自动选择

计算成本高。

4.2.1 网格搜索

3个及以下的超参数。对于多个超参数进行排列组合(笛卡尔乘积)探索。
要设定一个搜索范围:最大最小值可以根据先验知识,搜索在对数尺度上进行。网格搜索可以逐步试探性的重复,以进行最优解的逼近。
指数级上升的搜索代价。

4.2.2 随机搜索

为每个超参数定义一个边缘分布(二元-Bernoulli分布,离散-范畴分布,连续-对数尺度的均匀分布)
根据分布进行采样,然后进行评估。
随机搜索也可以根据上一代结果进行改进迭代。
随机搜索可能会比网格搜索更高效。

4.2.3 基于模型或优化算法的超参数选择

将寻找最优的超参数当作一个优化问题。可以使用模型,比如贝叶斯优化。也可以使用其他优化算法,如进化算法强化学习等。
低效,计算开销大,但是可以不使用任何人工知识就进行自动寻优。

五、调试策略

效果不好,也要查出来到底是哪儿出了岔子。

调试的难点:
1.我们不能提前知道算法的行为,在新的任务上,一个结果对于算法而言是好是坏都很难去断定。
2.模型是相互协调的,一个部分出问题了,其他部分会给弥补回来一部分,整体上看不出那一部分出了大问题。

调试手段:
1.可视化计算中模型的行为。直接看一看模型的工作结果,而不是只依赖于设定的评估指标的数值。比如,图像识别中,把图像识别的结果加到图像中。

2.可视化最严重的错误。 找到那些难以建模的数据,可以进一步分析在数据处理缓解中是否有那些纰漏。

3.根据训练与测试误差检测软件。 要保证程序写的是对的。如果训练误差小,测试误差大:一种可能是过拟合了;另一种可能是软件中模型重载/数据预处理部分出了问题。

4.拟合极小的数据集。当训练误差大,要确定是否欠拟合,还是程序有部分写错了。在一个极小的样本上(最小是单个数据)都不能拟合,那可能就是程序中处理流程出了问题。

5.比较反向传播导数与数值导数。梯度计算有误导致问题。比较自动求导的实现和通过有限差分计算的倒数验证导数计算的正确性。

6.监控激活函数值和梯度的直方图。 可以看到网络训练过程中,各个单元的工作状态,是否饱和,是否激活,饱和/激活的频率如何,饱和的程度如何。梯度可以看到优化是否会出问题(消失/爆炸),参数是如何更新的,如果参数每次更新1%是合理的,如果一次更新50%,或者0.001%就说明模型存在问题。还可以观察那些参数更新,那些不更新,那些更新很快,那些异常更新。

7.检查算法中的约束。 比如优化算法保证目标函数不增加,某些变量的导数一直为0等。


(2020.12.19-)

五、以手写数字数据集的任务为例

此任务根据参考资料6修改。

1.先看看数据长什么样

from keras.datasets import mnist
import matplotlib.pyplot as plt
# load (downloaded if needed) the MNIST dataset
(X_train, y_train), (X_test, y_test) = mnist.load_data()

plt.subplot(221)
plt.imshow(X_train[0], cmap=plt.get_cmap('gray'))
plt.subplot(222)
plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))
# show the plot
plt.show()

手写数字
观察数据,得到的信息:
1.处理的数据是图片,那么首选CNN先试一试
2.目标任务是分类,而且是多分类
3.图片是灰度图片,大小28*28,每个像素在0-255之间,单通道。

2.明确目标

任务:图像分类,10分类
性能度量:准确率(accuracy),损失使用交叉熵损失

model.compile(loss='categorical_crossentropy', metrics=['accuracy'])

3.构建一个baseline

3.1 数据端

# 导入需要的函数库
import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout # Dropout将在训练过程中每次更新参数时按一定概率(rate)随机断开输入神经元,Dropout层用于防止过拟合。
from keras.layers import Flatten # Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。
from keras.layers.convolutional import Conv2D # 二维卷积层,即对图像的空域卷积。
from keras.layers.convolutional import MaxPooling2D # 最大池化(也叫亚采样或下采样)降低了每个特征映射的维度,但是保留了最重要的信息
from keras.utils import np_utils
from keras import backend as K
K.set_image_data_format('channels_first') # 设置图像的维度顺序(‘tf’或‘th’)# 在Keras最新版本中已经把 image_dim_ordering 改为 image_data_format  原来:当前的维度顺序如果为'th',则输入图片数据时的顺序为:channels,rows,cols,否则:rows,cols,channels

seed = 7
numpy.random.seed(seed)

加载数据并 将数据reshape,CNN的输入是4维的张量(可看做多维的向量),第一维是样本规模,第二维是像素通道,第三维和第四维是长度和宽度。并将数值归一化和类别标签向量化。

# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# reshape to be [samples][pixels][width][height]
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32')

标准化,将0-255的数据缩放到0-1之间。

X_train = X_train / 255
X_test = X_test / 255

将y值进行独热编码

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]

3.2 模型端

创建模型:基本结构是 拍平 - 输出
全连接层:输出层,10类,10个unit;分类,输出函数用softmax

model = Sequential()
model.add(Flatten())
model.add(Dense(num_classes, activation='softmax'))

添加损失函数:交叉熵;优化器默认选择ADAM;评估指标选择准确率

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

3.3 评估端

模型训练并进行评估,查看模型

model.fit(X_train, y_train, epochs=10, batch_size=64, verbose=2)
score = model.evaluate(X_test, y_test)
print(score)
## 查看模型结构与 参数情况
model.summary()

训练过程
评估与查看模型
精度只有0.927

4.搭建系统、调参

当前基线模型只是一个一层的全连接层,效果不是非常理想。我们可以逐步的构建一个完整的cnn。

4.1 加入卷积

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(1, 28, 28), activation='relu'))
model.add(Flatten())
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, batch_size=16, verbose=2)
score = model.evaluate(X_test, y_test)
print(score)
model.summary()

cnn
加入卷积后准确率有0.98

4.2 加入池化,增加全连接

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(1, 28, 28), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, batch_size=16, verbose=2)
score = model.evaluate(X_test, y_test)
print(score)
model.summary()

3
准确率上升到 0.9864

4.3 继续丰富网络结构

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(1, 28, 28), activation='relu'))
model.add(Conv2D(16,kernel_size=(3,3),activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, batch_size=16, verbose=2)
score = model.evaluate(X_test, y_test)
print(score)
model.summary()

4.3

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(1, 28, 28), activation='relu'))
model.add(Conv2D(16,kernel_size=(3,3),activation="relu"))
model.add(Conv2D(8,kernel_size=(3,3),activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, batch_size=16, verbose=2)
score = model.evaluate(X_test, y_test)
print(score)
model.summary()

6
准确率没有上升,反而下降。训练集上也下降了。

4.4 加入正则化
加入dropout 准确率上升到0.9923

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(1, 28, 28), activation='relu'))
model.add(Conv2D(16,kernel_size=(3,3),activation="relu"))
model.add(Conv2D(8,kernel_size=(3,3),activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, batch_size=16, verbose=2)
score = model.evaluate(X_test, y_test)
print(score)
model.summary()

在这里插入图片描述
再次增加复杂度看能不能上升

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(1, 28, 28), activation='relu'))
model.add(Conv2D(16,kernel_size=(3,3),activation="relu"))
model.add(Conv2D(8,kernel_size=(3,3),activation="relu"))
model.add(Conv2D(4,kernel_size=(3,3),activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, batch_size=16, verbose=2)
score = model.evaluate(X_test, y_test)
print(score)
model.summary()

8
发现准确率并没有上升.
然后就是反反复复的上下横跳的过程啦

参考资料

1.机器学习,周志华
2.统计学习方法,第二版,李航
3.https://zhuanlan.zhihu.com/p/38431213
4.https://github.com/MingchaoZhu/DeepLearning
5.https://www.bilibili.com/video/BV1kE4119726?p=5&t=1340
6.https://www.cnblogs.com/ncuhwxiong/p/9774515.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深度学习笔记v5是一本关于深度学习的学习资料,下面我将用300字来回答有关这本笔记的内容。 深度学习机器学习领域的一个重要分支,它主要研究模拟人脑神经网络算法和模型,用于实现复杂的学习任务。深度学习在图像识别、语音识别和自然语言处理等领域取得了很多重要的突破,成为了人工智能领域的热点研究方向。 深度学习笔记v5中,首先介绍了深度学习的基本概念和原理。笔记详细解释了神经网络结构、前向传播、反向传播以及梯度下降等基本概念和算法。这些内容帮助读者理解深度学习的基本原理和工作机制。 接着,笔记介绍了常用的深度学习框架,如TensorFlow和PyTorch。这些框架提供了丰富的工具和函数,使得深度学习的开发变得更加简单和高效。笔记详细介绍了如何使用这些框架进行模型训练和评估。 此外,笔记还包含了一些深度学习的经典应用案例。这些案例涵盖了图像分类、目标检测、语音识别等多个领域。通过这些案例,读者可以深入了解深度学习在实际问题中的应用,并学习如何利用深度学习解决现实世界中的复杂任务。 最后,笔记还提供了大量的代码示例和练习题,帮助读者巩固所学的知识。通过实践,读者可以更好地理解深度学习的原理和应用。 总而言之,深度学习笔记v5是一本系统而全面的学习资料,适合对深度学习感兴趣的读者。通过阅读这本笔记,读者可以了解深度学习的基本概念和原理,掌握常用的深度学习框架,以及应用深度学习解决实际问题的方法。希望这本笔记能够对读者在深度学习领域的学习和研究有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值