《python深度学习》学习笔记与代码实现(第四章)

第四章:机器学习基础

本章涵盖了
1.分类和回归以外的机器学习形式
2.机器学习模型的正式评估过程
3.为深度学习准备数据
4.特征工程
5.解决过拟合
6.解决机器学习问题的通用工作流程

在第三章的三个实际例子之后,您应该开始熟悉如何使用神经网络来处理分类和回归问题,并且您已经看到了机器学习的核心问题:过拟合。
这一章将把你的一些新直觉形式化到一个坚固的概念框架中,用来解决深度学习的问题。我们将把所有这些概念——模型评估、数据预处理和特性工程,以及处理过拟合——整合到一个详细的七步工作流程中,以处理任何机器学习任务。


4.1 机器学习的四个分支

监督学习: 这是目前为止最常见的情况。它包括,在给定一组示例(通常由人来注释)的情景下,学习将输入数据映射到已知目标(也称为注解(annotations))。到目前为止,你在这本书中遇到的四个例子都是有监督学习的典型例子。一般来说,目前备受关注的深度学习的几乎所有应用都属于这一类,例如光学字符识别(optical character recognition, OCR)、语音识别、图像分类和语言翻译。虽然有监督学习主要由分类和回归组成,但也有更多的外来变体,包括以下(有例子):
分类、回归、序列生成(sequence generation)、语法树预测(syntax tree prediction)、目标预测(object detection)、图像分割(image segmentation)

无监督学习:机器学习的这个分支包括在不借助任何目标的情况下对输入数据进行有趣的转换,以实现数据可视化、数据压缩或数据去噪,或者更好地理解当前数据中的相关性。无监督学习是数据分析的主要内容,在试图解决一个有监督学习的问题之前,它通常是更好地理解数据集的必要步骤。
降维(dimensionality reduction)、聚类(clustering)

自监督学习:这是监督学习的一个特例,但它的不同之处足以让它应该有自己的类别。自主监督学习是一种无需人为标记标签的监督学习——可以把它看作是没有任何人参与的监督学习。这里仍然涉及到标签(因为学习必须受到某些东西的监督),但它们是由输入数据生成的,通常使用启发式算法。
例如,autoencoders是自监督学习的一个众所周知的实例,其中生成的目标是输入,没有修改。同样地,给定过去的帧,试图预测视频中的下一帧,或给定之前的单词,预测文本中的下一个单词,都是自我监督学习的实例(短暂的监督学习(temporally supervised learning),在这种情况下:监督来自未来的输入数据)。请注意,监督学习、自我监督学习和非监督学习之间的区别有时可能是模糊的——这些类别更像是没有固定边界的连续统一体。自我监督学习可以被重新解释为监督学习或非监督学习,这取决于你关注的是学习机制还是它的应用环境。
自编码器(autoencoder)

强化学习:这个机器学习的分支被长期忽视,直到最近在谷歌DeepMind成功地将其应用于学习玩Atari游戏(后来,学习玩围棋到最顶尖水平)之后,它开始受到很多关注。在强化学习中,agent会接收环境的信息,并学会选择能获得最大回报的行为。例如,可以通过强化学习来训练一个神经网络,它“看”电子游戏屏幕并输出游戏动作以最大化它的分数。
目前,强化学习主要是一个研究领域,在游戏之外还没有取得显著的实际成功。然而,随着时间的推移,我们预计强化学习将接管越来越广泛的现实应用领域:自动驾驶汽车、机器人、资源管理、教育等等。这个想法的时机已经到来,或者即将到来。
选择使奖励最大化的行动

相关术语

样本(sample)或输入(input)
预测(predict)或输出(output)
目标(target)
预测误差(prediction error)
类别(class)
标签(label)
真值(ground-truth)或标注(annotation)
二分类(binary classification)
多分类(multiclass classification)
多标签分类(multilabel classification)
标量回归(scalar regression)
向量回归(vector regression)
小批量(mini-batch)或批量(batch):通常是2的幂次。8~128


4.2 评估机器学习模型

机器学习目的:得到好的泛化(generalize)模型

4.2.1 训练集、验证集和测试集

验证模型时,有可能会发生消息泄露(information leak)

评估方法:

简单的留出验证(hold-out validation)
K折验证(K-fold validation)
带打乱数据的重复K折验证(iterated K-fold validation with shuffling)

4.2.2 评估模型的注意事项

数据代表性(data representativeness):随机打乱数据
时间箭头(the arrow of time):预测与时间相关,不能随机打乱;且确保测试集数据晚于训练集数据
数据冗余(redundancy in your data):确保训练集和数据集没有交集


4.3 数据预处理、特征工程和特征学习

4.3.1 神经网络的数据预处理

预处理目的:使原始数据更适合于神经网络处理,向量化、标准化、处理缺失值和特征处理

向量化:输入和预测值必须是浮点数张量。数据向量化(data vectorization)
值标准化:取值较小,同质化(homogeneous)平均值为0,标准差为1。 x-=x.mean(axis=0) x/=x.std(axis=0)
处理缺失值:缺失值设为0,让网络学到,0意味着缺失值。当测试集有缺失值,而训练集没有时,要手动给训练集加缺失值。
4.3.2 特征工程(feature engineering)

特征工程:将数据输入模型前,利用人对数据的认识,先对数据进行处理。

本质:更简单的方式表述问题,是问题变得简单。


4.4 过拟合与欠拟合

优化(optimization)

泛化(generalization)

4.4.1 减小网络大小

4.4.2 添加权重正则化

奥卡姆剃刀(Occam/s razor)

成本(cost)

L1正则化:系数绝对值

L2正则化:系数平方

惩罚只在训练时有,所以测试误差会小很多。

4.4.3 添加dropout正则化

训练过程中随机把改层输出特征舍弃

dropout比率:通常0.2~0.5

测试时没有单元舍弃,层输出需要按dropout比率缩小。

以下函数,对比添加不同正则项,交叉验证集的损失

# 正则化防止过拟合
from keras import regularizers
from keras import models
from keras import layers
import numpy as np
# 导入数据
from keras.datasets import imdb
(train_data,train_labels),(test_data,test_labels) = imdb.load_data(num_words = 10000)

def vectorize_sequences(sequences,dimension = 10000):
    results = np.zeros((len(sequences),dimension))
    for i,sequence in enumerate(sequences):
        results[i,sequence] = 1
    return results

x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)

# 将标签也进行向量化
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')


x_val = x_train[:10000]
partial_x_train = x_train[10000:]

y_val = y_train[:10000]
partial_y_train = y_train[10000:]    
#添加l2正则项的模型
model1 = models.Sequential()
model1.add(layers.Dense(16,kernel_regularizer = regularizers.l2(0.001),activation = 'relu',input_shape = (10000,)))
model1.add(layers.Dense(16,kernel_regularizer = regularizers.l2(0.001),activation = 'relu',input_shape = (10000,)))
model1.add(layers.Dense(1,activation = 'sigmoid'))
model1.compile(optimizer = 'rmsprop',loss = 'binary_crossentropy',metrics = ['acc'])
history1 = model1.fit(partial_x_train,partial_y_train,epochs = 12,batch_size = 512,validation_data = (x_val,y_val))
Train on 15000 samples, validate on 10000 samples
Epoch 1/12
15000/15000 [==============================] - 4s 261us/step - loss: 0.5515 - acc: 0.7812 - val_loss: 0.4255 - val_acc: 0.8667
Epoch 2/12
15000/15000 [==============================] - 3s 216us/step - loss: 0.3541 - acc: 0.9037 - val_loss: 0.3517 - val_acc: 0.8892
Epoch 3/12
15000/15000 [==============================] - 3s 214us/step - loss: 0.2833 - acc: 0.9229 - val_loss: 0.3677 - val_acc: 0.8698
Epoch 4/12
15000/15000 [==============================] - 3s 218us/step - loss: 0.2519 - acc: 0.9359 - val_loss: 0.3335 - val_acc: 0.8878
Epoch 5/12
15000/15000 [==============================] - 3s 214us/step - loss: 0.2321 - acc: 0.9415 - val_loss: 0.3340 - val_acc: 0.8869
Epoch 6/12
15000/15000 [==============================] - 3s 215us/step - loss: 0.2126 - acc: 0.9507 - val_loss: 0.4048 - val_acc: 0.8619
Epoch 7/12
15000/15000 [==============================] - 3s 216us/step - loss: 0.2030 - acc: 0.9535 - val_loss: 0.3503 - val_acc: 0.8843
Epoch 8/12
15000/15000 [==============================] - 3s 214us/step - loss: 0.1947 - acc: 0.9566 - val_loss: 0.3726 - val_acc: 0.8748
Epoch 9/12
15000/15000 [==============================] - 3s 217us/step - loss: 0.1850 - acc: 0.9605 - val_loss: 0.3658 - val_acc: 0.8813
Epoch 10/12
15000/15000 [==============================] - 3s 218us/step - loss: 0.1829 - acc: 0.9608 - val_loss: 0.3768 - val_acc: 0.8787
Epoch 11/12
15000/15000 [==============================] - 3s 221us/step - loss: 0.1811 - acc: 0.9609 - val_loss: 0.3972 - val_acc: 0.8777
Epoch 12/12
15000/15000 [==============================] - 3s 223us/step - loss: 0.1712 - acc: 0.9649 - val_loss: 0.4164 - val_acc: 0.8685
#添加l1正则项的模型
model2 = models.Sequential()
model2.add(layers.Dense(16,kernel_regularizer = regularizers.l2(0.001),activation = 'relu',input_shape = (10000,)))
model2.add(layers.Dense(16,kernel_regularizer = regularizers.l2(0.001),activation = 'relu',input_shape = (10000,)))
model2.add(layers.Dense(1,activation = 'sigmoid'))
model2.compile(optimizer = 'rmsprop',loss = 'binary_crossentropy',metrics = ['acc'])
history2 = model2.fit(partial_x_train,partial_y_train,epochs =12,batch_size = 512,validation_data = (x_val,y_val))
Train on 15000 samples, validate on 10000 samples
Epoch 1/12
15000/15000 [==============================] - 4s 234us/step - loss: 0.5751 - acc: 0.7733 - val_loss: 0.4389 - val_acc: 0.8661
Epoch 2/12
15000/15000 [==============================] - 3s 217us/step - loss: 0.3650 - acc: 0.8950 - val_loss: 0.3571 - val_acc: 0.8834
Epoch 3/12
15000/15000 [==============================] - 3s 221us/step - loss: 0.2916 - acc: 0.9178 - val_loss: 0.3396 - val_acc: 0.8830
Epoch 4/12
15000/15000 [==============================] - 4s 235us/step - loss: 0.2518 - acc: 0.9324 - val_loss: 0.3759 - val_acc: 0.8654
Epoch 5/12
15000/15000 [==============================] - 4s 254us/step - loss: 0.2302 - acc: 0.9411 - val_loss: 0.3440 - val_acc: 0.8810
Epoch 6/12
15000/15000 [==============================] - 3s 229us/step - loss: 0.2119 - acc: 0.9499 - val_loss: 0.3355 - val_acc: 0.8849
Epoch 7/12
15000/15000 [==============================] - 3s 216us/step - loss: 0.2083 - acc: 0.9485 - val_loss: 0.3416 - val_acc: 0.8856
Epoch 8/12
15000/15000 [==============================] - 3s 216us/step - loss: 0.1913 - acc: 0.9580 - val_loss: 0.3602 - val_acc: 0.8763
Epoch 9/12
15000/15000 [==============================] - 3s 215us/step - loss: 0.1901 - acc: 0.9566 - val_loss: 0.3566 - val_acc: 0.8808
Epoch 10/12
15000/15000 [==============================] - 3s 215us/step - loss: 0.1801 - acc: 0.9622 - val_loss: 0.3779 - val_acc: 0.8802
Epoch 11/12
15000/15000 [==============================] - 3s 215us/step - loss: 0.1754 - acc: 0.9632 - val_loss: 0.3768 - val_acc: 0.8806
Epoch 12/12
15000/15000 [==============================] - 3s 216us/step - loss: 0.1714 - acc: 0.9647 - val_loss: 0.3969 - val_acc: 0.8772

#添加dropout正则项的模型
model3 = models.Sequential()
model3.add(layers.Dense(16,activation = 'relu',input_shape = (10000,)))
model3.add(layers.Dropout(0.5))
model3.add(layers.Dense(16,activation = 'relu'))
model3.add(layers.Dropout(0.5))
model3.add(layers.Dense(1,activation = 'sigmoid'))
# 损失函数为二元交叉熵,三个参数依次为:优化器,损失函数,评价指标
model3.compile(optimizer = 'rmsprop',loss = 'binary_crossentropy',metrics = ['acc'])
history3 = model3.fit(partial_x_train,partial_y_train,epochs = 12,batch_size = 512,validation_data = (x_val,y_val)) 
Train on 15000 samples, validate on 10000 samples
Epoch 1/12
15000/15000 [==============================] - 4s 280us/step - loss: 0.6238 - acc: 0.6515 - val_loss: 0.5140 - val_acc: 0.8315
Epoch 2/12
15000/15000 [==============================] - 3s 221us/step - loss: 0.4963 - acc: 0.7771 - val_loss: 0.4012 - val_acc: 0.8615
Epoch 3/12
15000/15000 [==============================] - 3s 221us/step - loss: 0.4103 - acc: 0.8318 - val_loss: 0.3363 - val_acc: 0.8757
Epoch 4/12
15000/15000 [==============================] - 3s 225us/step - loss: 0.3555 - acc: 0.8645 - val_loss: 0.2922 - val_acc: 0.8877
Epoch 5/12
15000/15000 [==============================] - 3s 220us/step - loss: 0.3028 - acc: 0.8867 - val_loss: 0.2785 - val_acc: 0.8896
Epoch 6/12
15000/15000 [==============================] - 3s 225us/step - loss: 0.2623 - acc: 0.9069 - val_loss: 0.2775 - val_acc: 0.8897
Epoch 7/12
15000/15000 [==============================] - 4s 246us/step - loss: 0.2304 - acc: 0.9239 - val_loss: 0.2847 - val_acc: 0.8880
Epoch 8/12
15000/15000 [==============================] - 4s 279us/step - loss: 0.2036 - acc: 0.9299 - val_loss: 0.2797 - val_acc: 0.8896
Epoch 9/12
15000/15000 [==============================] - 4s 279us/step - loss: 0.1901 - acc: 0.9365 - val_loss: 0.2999 - val_acc: 0.8872
Epoch 10/12
15000/15000 [==============================] - 4s 274us/step - loss: 0.1652 - acc: 0.9448 - val_loss: 0.3106 - val_acc: 0.8902
Epoch 11/12
15000/15000 [==============================] - 4s 262us/step - loss: 0.1483 - acc: 0.9502 - val_loss: 0.3277 - val_acc: 0.8890
Epoch 12/12
15000/15000 [==============================] - 4s 235us/step - loss: 0.1342 - acc: 0.9542 - val_loss: 0.3643 - val_acc: 0.8882

#无正则项的模型
model4 = models.Sequential()
model4.add(layers.Dense(16,activation = 'relu',input_shape = (10000,)))
model4.add(layers.Dense(16,activation = 'relu'))
model4.add(layers.Dense(1,activation = 'sigmoid'))
# 损失函数为二元交叉熵,三个参数依次为:优化器,损失函数,评价指标
model4.compile(optimizer = 'rmsprop',loss = 'binary_crossentropy',metrics = ['acc'])
history4 = model4.fit(partial_x_train,partial_y_train,epochs = 12,batch_size = 512,validation_data = (x_val,y_val))  
Train on 15000 samples, validate on 10000 samples
Epoch 1/12
15000/15000 [==============================] - 4s 241us/step - loss: 0.5294 - acc: 0.7753 - val_loss: 0.3959 - val_acc: 0.8726
Epoch 2/12
15000/15000 [==============================] - 3s 218us/step - loss: 0.3162 - acc: 0.9009 - val_loss: 0.3145 - val_acc: 0.8837
Epoch 3/12
15000/15000 [==============================] - 3s 218us/step - loss: 0.2306 - acc: 0.9235 - val_loss: 0.2883 - val_acc: 0.8856
Epoch 4/12
15000/15000 [==============================] - 3s 214us/step - loss: 0.1808 - acc: 0.9410 - val_loss: 0.2740 - val_acc: 0.8917
Epoch 5/12
15000/15000 [==============================] - 3s 213us/step - loss: 0.1456 - acc: 0.9535 - val_loss: 0.2896 - val_acc: 0.8834
Epoch 6/12
15000/15000 [==============================] - 3s 214us/step - loss: 0.1221 - acc: 0.9629 - val_loss: 0.2966 - val_acc: 0.8845
Epoch 7/12
15000/15000 [==============================] - 3s 214us/step - loss: 0.0995 - acc: 0.9716 - val_loss: 0.3342 - val_acc: 0.8777
Epoch 8/12
15000/15000 [==============================] - 3s 215us/step - loss: 0.0847 - acc: 0.9762 - val_loss: 0.3831 - val_acc: 0.8644
Epoch 9/12
15000/15000 [==============================] - 3s 215us/step - loss: 0.0709 - acc: 0.9807 - val_loss: 0.3490 - val_acc: 0.8779
Epoch 10/12
15000/15000 [==============================] - 3s 215us/step - loss: 0.0603 - acc: 0.9841 - val_loss: 0.3805 - val_acc: 0.8753
Epoch 11/12
15000/15000 [==============================] - 3s 214us/step - loss: 0.0508 - acc: 0.9883 - val_loss: 0.3967 - val_acc: 0.8757
Epoch 12/12
15000/15000 [==============================] - 3s 215us/step - loss: 0.0414 - acc: 0.9897 - val_loss: 0.4250 - val_acc: 0.8729
#绘制不同的交叉验证集的损失
# 绘制训练损失和验证损失
import matplotlib.pyplot as plt
history1_dict = history1.history
val_loss_values1 = history1_dict['val_loss']

history2_dict = history2.history
val_loss_values2 = history2_dict['val_loss']

history3_dict = history3.history
val_loss_values3 = history3_dict['val_loss']

history4_dict = history4.history
val_loss_values4 = history4_dict['val_loss']

epochs = range(1,len(val_loss_values1) + 1 )

plt.plot(epochs,val_loss_values1,'b',label = 'l2')

plt.plot(epochs,val_loss_values2,'g',label = 'l1')

plt.plot(epochs,val_loss_values3,'r',label = 'Dropout')

plt.plot(epochs,val_loss_values4,'c',label = 'none')

plt.title('validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

在这里插入图片描述


4.5机器学习的通用工作流

在本节中,我们将展示一个通用蓝图,您可以使用它来攻破和解决任何机器学习问题。蓝图把你在这一章学到的概念联系在一起:问题定义,评估,特性工程,和解决过拟合。
4.5.1定义问题并组装数据集
首先,您必须定义手边的问题:

您的输入数据是什么?你想预测什么?只有当你有可用的训练数据时,你才能学会预测:例如,只有当你有可用的电影评论和情感注释时,你才能学会对电影评论的情绪进行分类。因此,数据可用性通常是这个阶段的限制因素(除非你有办法付钱让别人帮你收集数据)。
你面临什么样的问题?是二分类吗?多分类?标量回归?向量回归?多分类多标签分类问题?
其他的东西,比如聚类、生成或强化学习?识别问题类型将指导您选择模型体系结构、损失函数等。
除非您知道您的输入和输出是什么,以及您将使用什么数据,否则您无法进入下一个阶段。注意你在这个阶段所做的假设:
你假设你的输出可以通过你的输入来预测。
你假设您的可用数据具有足够的信息来了解输入和输出之间的关系。

在你有一个可行的模型之前,这些仅仅是假设,等待着被证实或失效。不是所有的问题都能解决;仅仅因为你装配了输入X和目标Y的样本并不意味着X包含足够的信息来预测。例如,如果你试图预测某只股票在股票市场上的走势,考虑到它最近的历史价格,你不太可能成功,因为历史价格不包含太多的预测信息。
你应该知道的一类不可解问题是非平稳问题(nonstationary problems)。假设您正在尝试构建一个服装推荐引擎,您正在对它为期一个月的数据进行训练(8月份),并且希望在冬季开始生成推荐。一个大问题是,人们购买的服装种类随季节而变化:购买服装在几个月的时间里是一种非固定的现象。你试图建立的模型会随着时间而改变。在这种情况下,正确的做法是不断地根据最近的数据重新训练您的模型,或者在问题稳定的时间段收集数据。对于像买衣服这样的周期性问题,几年的数据就足以捕捉到季节的变化——但是记住把一年中的时间作为你的模型的输入!(备注:机器学习没法解决非平稳序列,其实也好理解,非平稳序列中,你的训练数据与用来预测的数据间的关联信息应该很少。当然例子中如果在同一个季节内部的预测,那就属于一个平稳序列了)
记住,机器学习只能用于记忆训练数据中的模式。你只能认出你以前看到的东西。通过对过去数据的机器学习来预测未来,是在假设未来会像过去一样。通常情况并非如此。
4.5.2选择成功的标准
要控制某事,你需要能够观察它。为了获得成功,你必须定义你所说的成功是什么——accuracy?Precision和recall?客户保留利率?您的成功度量标准将指导损失函数的选择:您的模型将如何优化。它应该直接与你的更高层次的目标相一致,比如你事业的成功。
对于均衡分类问题,每个类都是等概率的,receiver operating特性曲线(ROC AUC)下的accuracy和面积是常用的度量标准。对于分类不平衡的问题,可以使用precision和recall。对于排序问题或多标签分类,可以使用平均精度(mean average precision)。而且,需要定义自己的标准来衡量成功的情况并不少见。要了解机器学习成功指标的多样性以及它们如何与不同的问题领域相关联,浏览data science com网站是很有帮助的。
4.5.3 决策评估方法
一旦你知道你的目标是什么,你必须确定如何衡量你目前的进展。我们之前回顾了三个常见的评估方案:

保持一个保留验证集的方法:当你有足够的数据
执行K-fold cross-validation:当你只有少量的样本用于保留验证时,该选择是明知可靠的选择
执行迭代K-fold验证:在可用数据很少的情况下执行高度精确的模型评估
选一个吧。在大多数情况下,第一种方法都能很好地工作。

4.5.4 准备数据
一旦你知道你在训练什么,你在优化什么,以及如何评估你的方法,你就几乎准备好开始训练模型了。但首先,你应该以一种可以被输入机器学习模型的方式来格式化你的数据——在这里,我们假设一个深层神经网络:

如前所述,数据应该格式化为张量。
张量中的值通常应该按比例缩小到较小的值:例如在[-1,1]或[0,1]之间。
如果不同的特征采用不同范围(异构数据)的值,则应该对数据进行归一化(normalized)
可能需要一些特性工程,特别是对于小数据问题

一旦输入数据和目标数据的张量就绪,就可以开始训练模型。
4.5.5开发一个比基线更好的模型
您在此阶段的目标是实现统计能力(statistical power):即开发一个能够超过静默基线的小型模型。在MNIST digit-classification示例中,任何accuracy达到0.1以上的都可以称为具有统计能力;在IMDB示例中,它的accuracy要求大于0.5。
注意,实现统计能力并不总是可能的。如果在尝试了多个合理的体系结构之后,您不能打破一个随机的基线,那么您所问问题的答案可能不会出现在输入数据中。记住你做了两个假设:

你假设你的输出可以预测给定输入。
您假设可用的数据足以提供足够的信息来了解输入和输出之间的关系。

很可能这些假设是错误的,在这种情况下,你必须回到绘图板(就是说要重新开始设计)。
假设一切顺利,您需要做出三个关键选择来构建您的第一个工作模型:

最后一层的激活函数(Last-layer activation):它建立了网络输出的有用约束。例如,IMDB分类示例在最后一层使用了sigmoid;回归示例没有在最后一层使用任何激活函数等等。
损失函数——这应该与您试图解决的问题类型相匹配。例如,IMDB示例使用binary_crossentropy,回归示例使用mse等等。

优化配置——您将使用什么优化器?它的学习率是多少?在大多数情况下,使用rmsprop,并配合它的默认学习率是安全的。
关于损失函数的选择,请注意,并不是总是能够直接优化用于度量问题成功与否的度量标准。有时,没有简单的方法可以将度量转换为损失函数;毕竟,损失函数只需要给定一小批(mini-batch)数据就可以计算(理想情况下,损失函数只需要计算单个数据点),并且必须是可微的(否则,您不能使用反向传播来训练网络)。例如,广泛使用的分类度量ROC AUC不能直接进行优化。因此,在分类任务中,通常会优化ROC AUC的代理度量,比如交叉熵。一般来说,你可以希望交叉熵越低,ROC AUC就越高。
表4.1为模型选择正确的最后一层激活和损失函数

在这里插入图片描述

4.5.6 扩展:开发一个过拟合的模型
一旦你得到了一个具有统计能力的模型,问题就变成了,你的模型是否足够强大?它是否有足够的层和参数来正确地建模手边的问题?例如,一个只有一个隐藏层和两个单元的网络在MNIST上具有统计能力,但不足以很好地解决这个问题。记住,机器学习中的广义张量是在优化和泛化之间;理想的模型是在不完全拟合和过度拟合之间的边界;在undercapacity和overcapacity之间。想弄清楚这条边界在哪里,你必须先穿过它。
为了弄清楚您需要多大的模型,您必须开发一个过拟合的模型。
这很简单:

添加层
使得层更大
在更多的epochs中训练
始终监控训练损失和验证损失,以及您关心的任何指标的训练和验证值。当您看到模型在验证数据上的性能开始下降时,您已经实现了过拟合。
下一个阶段是开始对模型进行正则化(regularizing)和调优,以尽可能接近既欠拟合也不过拟合的理想模型。

4.5.7模型正则化,调整超参数
这个步骤将花费最多的时间:您将反复修改模型,训练它,评估您的验证数据(此时不是测试数据),再次修改它,然后重复,直到模型达到最佳状态。以下是一些你应该尝试的事情:

添加dropout
尝试不同的架构:添加或移除层
添加L1和L2正则化(regularization)
尝试不同的超参数(例如每层单元的数量或优化器的学习率)来找到最佳配置。
可选地,迭代特性工程:添加新特征,或删除那些看起来不提供信息的特征。

注意以下内容:每次使用验证过程的反馈来优化模型时,您都会将验证过程的信息泄漏到模型中。重复几次,这是无害的;但是在多次迭代中系统地完成,最终会导致您的模型过拟合验证过程(即使模型没有直接针对任何验证数据进行训练)。这使得评估过程不那么可靠。
一旦你建立了一个令人满意的模型配置,您可以在所有可用数据(训练和验证)上训练您的最终产品模型,并在测试集中最后一次评估它。如果测试集上的性能明显低于验证数据上的性能,这可能意味着您的验证过程根本不可靠,或者您在调优模型参数时开始度拟合验证数据。在这种情况下,您可能希望切换到更可靠的评估协议(例如迭代K-fold验证)。

章节总结

定义手头的问题和要训练的数据。收集这些数据,或者在需要时用标签对其进行注释。
选择在你的问题上如何衡量成功。您将在验证数据上监视哪些指标?
确定评估方法:保留验证?K-fold验证?应该使用哪一部分数据进行验证?
开发第一个比基本基线更好的模型:一个具有统计能力的模型。
开发一个过拟合的模型。
根据验证数据的性能,调整模型并调优其超参数。很多机器学习研究倾向于只关注这一步,但要把大局记在心里。

猜你喜欢

转载自blog.csdn.net/qq_41718518/article/details/88062807