政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(四)—— 过拟合和欠拟合

政安晨的个人主页政安晨

欢迎 👍点赞✍评论⭐收藏

收录专栏政安晨的机器学习笔记

希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正!

通过增加容量或提前停止来提高性能。

在深度学习中,过拟合和欠拟合是两个常见的问题,它们可能会影响模型的性能和泛化能力。

过拟合(overfitting)指的是模型在训练数据上表现良好,但在新的未见过的数据上表现较差的现象。过拟合发生的原因通常是模型能够在训练数据上学习到过多的细节和噪声,导致模型对训练数据的特点过度拟合。过拟合的表现通常是模型在训练数据上表现很好,但在验证集或测试集上表现较差。

欠拟合(underfitting)指的是模型在训练数据和新的未见过的数据上表现都不理想的现象。欠拟合发生的原因通常是模型不能够充分拟合数据的特征或模型复杂度不够。欠拟合的表现通常是模型在训练数据和新数据上的表现都不够好,无法捕捉到数据的复杂性。

解决过拟合和欠拟合的方法有一些共同的基本原则。

首先增加训练数据量可以减少过拟合和欠拟合的可能性,因为更多的数据能够提供更多的样本和变化情况,有助于模型学习到更好的特征。

其次调整模型的复杂度可以避免过拟合和欠拟合。如果模型过于复杂,可以考虑减少模型的参数或使用正则化技术来约束模型的学习能力。如果模型过于简单,可以增加模型的层数或参数,提高模型的学习能力。此外,还可以使用数据增强、丢弃法(dropout)等技术来减少过拟合。

总之,过拟合和欠拟合是深度学习中常见的问题,需要根据具体情况采取相应的调整措施来提高模型的性能和泛化能力。


前言

回顾一下以前文章中的示例,Keras将会保存训练和验证损失的历史记录,这些损失是在训练模型的过程中逐个epoch记录的。

在本文中,我们将学习如何解释这些学习曲线,并如何利用它们来指导模型的开发。特别是,我们将检查学习曲线以寻找欠拟合和过拟合的迹象,并讨论一些纠正策略。

解读学习曲线

可能你可以将训练数据中的信息分为两种类型:信号和噪声

信号是可以概括的部分,可以帮助我们的模型从新数据中进行预测。

噪声则是只在训练数据中存在的部分;噪声是来自现实世界数据的所有随机波动,或者是所有不能真正帮助模型进行预测的非相关模式。噪声是看起来有用但实际上并非如此的部分。

通过选择使损失函数最小化的权重或参数来训练模型。然而,您可能知道,为了准确评估模型的性能,我们需要在新的数据集上进行评估,即验证数据集。

当我们训练模型时,我们会将每个时期的训练集损失绘制成图表。此外,我们还会绘制验证数据的图表。这些图表被称为学习曲线。为了有效地训练深度学习模型,我们需要能够解读这些学习曲线。

验证损失提供了对未见数据的预期错误的估计。

现在,当模型学习到信号或噪声时,训练损失会下降。但是,只有当模型学习到信号时,验证损失才会下降。(模型从训练集中学到的噪声不会推广到新数据。)因此,当模型学习到信号时,两条曲线都下降,但是当模型学习到噪声时,曲线间会出现差距差距的大小告诉您模型学到了多少噪声。

理想情况下我们希望创建的模型能够学习到所有的信号,而不学习到任何噪音

然而实际上这几乎不可能发生。相反,我们要进行一种权衡。

我们可以让模型学习更多的信号,但代价是学习到更多的噪音。只要这种权衡对我们有利,验证损失就会继续减小。然而,在某一点之后,这种权衡可能会对我们不利,代价超过了收益,验证损失开始上升。

这种权衡表明,在训练模型时可能出现两个问题信号不足或噪声过多

欠拟合训练集是指由于模型没有学到足够的信号,导致损失值没有降低到最低。

过拟合训练集是指由于模型学到了过多的噪声,导致损失值没有降低到最低。

训练深度学习模型的关键是找到二者之间的最佳平衡点。

我们将探讨一些方法,既可以在减少噪音的同时提取更多的训练数据信号。

容量

模型的容量是指它能够学习的模式的大小和复杂性对于神经网络来说,这主要取决于它拥有多少个神经元以及它们是如何相连的。如果你的网络似乎无法适应数据,你应该尝试增加它的容量。

您可以通过使网络更宽(增加现有层的单元数)或使网络更深(添加更多层)来增加网络的容量。更宽的网络更容易学习更多线性关系,而更深的网络更喜欢更多非线性关系。哪种方法更好取决于数据集。

model = keras.Sequential([layers.Dense(16, activation='relu'),layers.Dense(1),
])wider = keras.Sequential([layers.Dense(32, activation='relu'),layers.Dense(1),
])deeper = keras.Sequential([layers.Dense(16, activation='relu'),layers.Dense(16, activation='relu'),layers.Dense(1),
])

您将在本文的练习中探讨网络的容量如何影响其性能。

早停止

我们提到,当模型过于迫切地学习噪声时,在训练过程中验证损失可能会开始增加。为了防止这种情况,我们可以在看到验证损失不再下降时简单地停止训练。以这种方式中断训练被称为早停止。

我们保留验证损失最小的模型。

一旦我们检测到验证损失开始再次上升,我们可以将权重重置回最小值出现的位置。这样可以确保模型不会继续学习噪音并过度拟合数据。

使用提前停止的训练方法意味着我们不太容易在网络学习信号完成之前过早停止训练。因此,除了防止过长训练导致过拟合外,提前停止还可以防止训练时间不足导致的欠拟合。只需将训练轮数设置为一个较大的数值(超过实际需要的轮数),提前停止将处理剩下的部分。

添加早停止

【政安晨】

早停止是一种在训练机器学习模型时常用的技术。它的目的是在模型在训练数据上达到最佳性能之前就停止训练,以防止过拟合。

实现早停止的方法有很多种,其中一种常用的方法是通过监控模型在验证集上的性能来决定何时停止训练。通常,我们会定义一个指标,例如验证集上的损失函数或准确率,并设置一个阈值。当模型在连续若干次迭代中都没有达到这个指标时,就可以认为模型已经过拟合,可以停止训练了。

另一种常用的方法是使用早停止的模型来评估测试数据上的性能。如果模型在测试数据上的性能开始下降,那么就可以认为模型已经过拟合,并停止训练。

通过添加早停止技术,可以避免模型在训练数据上过拟合,从而提高模型的泛化能力。注意,早停止并不是一种完全可靠的方法,因为有时模型在训练数据上的性能可能仍然可以提升,但它仍然是一个非常有用的技术,可以帮助我们平衡模型的拟合程度和泛化能力。

在Keras中,我们通过回调函数来包含早停机制。回调函数是在网络训练过程中想要定期运行的函数。早停回调函数将在每个时期后运行。(Keras有许多有用的预定义回调函数,但你也可以自己定义。

from tensorflow.keras.callbacks import EarlyStoppingearly_stopping = EarlyStopping(min_delta=0.001, # minimium amount of change to count as an improvementpatience=20, # how many epochs to wait before stoppingrestore_best_weights=True,
)

这些参数的意思是:“如果在之前的20个迭代中,验证损失没有至少改善0.001,那么停止训练并保留你找到的最佳模型。

有时候很难判断验证损失是由于过拟合还是由于随机批次变异导致的上升。这些参数允许我们设置一些容忍度来确定何时停止训练。

正如我们将在我们的示例中看到的那样,我们将把这个回调函数与损失函数和优化器一起传递给fit方法。

示例 - 使用提前停止训练模型

【政安晨】

在机器学习中,提前停止是一种常用的训练模型的技术。它的原理是在训练过程中监测模型在验证集上的性能,并在性能不再提升时停止训练,以防止过拟合。

以下是一个使用提前停止训练模型的示例:

  1. 准备数据集:首先,需要准备一个数据集,其中包含用于训练和验证的样本。可以使用真实数据集或合成数据集。

  2. 构建模型:选择一个合适的模型结构,并根据数据集的特点构建一个模型。可以选择各种机器学习算法或深度学习模型。

  3. 分割数据集:将数据集分成训练集和验证集。训练集用于训练模型,验证集用于监测模型的性能。

  4. 定义停止条件:定义一个停止条件,例如当验证集上的性能在一定的连续迭代中没有提升时停止训练。

  5. 训练模型:使用训练集对模型进行训练,并在每次迭代后使用验证集评估模型的性能。

  6. 检测性能:在每次迭代后,对模型在验证集上的性能进行检测。如果性能没有提升,则记录当前的迭代次数。

  7. 停止训练:如果模型在一定数量的连续迭代中性能没有提升,停止训练。

使用提前停止训练模型的好处是能够避免过拟合,并在模型性能达到最佳时停止训练,节省时间和计算资源。同时,提前停止还可以对模型进行验证,并提供模型的性能指标。

让我们继续开发上篇文章中示例中的模型。

政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(三)—— 随机梯度下降icon-default.png?t=N7T8https://blog.csdn.net/snowdenkeke/article/details/136903006我们将增加该网络的容量,同时添加一个提前停止的回调函数,以防止过拟合。

这是数据准备的步骤:

import pandas as pd
from IPython.display import displayred_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)
display(df_train.head(4))# Scale to [0, 1]
max_ = df_train.max(axis=0)
min_ = df_train.min(axis=0)
df_train = (df_train - min_) / (max_ - min_)
df_valid = (df_valid - min_) / (max_ - min_)# 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']

现在让我们增加网络的容量。我们将选择一个相当大的网络,但依靠回调函数在验证损失开始增加时停止训练。

from tensorflow import keras
from tensorflow.keras import layers, callbacksearly_stopping = callbacks.EarlyStopping(min_delta=0.001, # minimium amount of change to count as an improvementpatience=20, # how many epochs to wait before stoppingrestore_best_weights=True,
)model = keras.Sequential([layers.Dense(512, activation='relu', input_shape=[11]),layers.Dense(512, activation='relu'),layers.Dense(512, activation='relu'),layers.Dense(1),
])
model.compile(optimizer='adam',loss='mae',
)

在定义好回调函数之后,将其作为参数添加到fit函数中(你可以有多个回调函数,所以将其放入一个列表中)。在使用early stopping时选择一个较大的epoch数量,大于你实际需要的数量。

history = model.fit(X_train, y_train,validation_data=(X_valid, y_valid),batch_size=256,epochs=500,callbacks=[early_stopping], # put your callbacks in a listverbose=0,  # turn off training log
)history_df = pd.DataFrame(history.history)
history_df.loc[:, ['loss', 'val_loss']].plot();
print("Minimum validation loss: {}".format(history_df['val_loss'].min()))
结果如下:Minimum validation loss: 0.09269220381975174

果然,Keras在完整的500个epochs之前就停止了训练

练习:过拟合与欠拟合

介绍

在这个练习中,您将学习如何通过包含早停止回调来提高训练结果,以防止过拟合。

# 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.ex4 import *

首先加载Spotify数据集。你的任务是根据各种音频特征(如“节奏”,“舞蹈性”和“模式”)预测一首歌的流行程度。

import pandas as pd
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import make_column_transformer
from sklearn.model_selection import GroupShuffleSplitfrom tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import callbacksspotify = 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),
)# We'll do a "grouped" split to keep all of an artist's songs in one
# split or the other. This is to help prevent signal leakage.
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 # popularity is on a scale 0-100, so this rescales to 0-1.
y_valid = y_valid / 100input_shape = [X_train.shape[1]]
print("Input shape: {}".format(input_shape))

结果看到
Input shape: [18]

让我们从最简单的网络开始,线性模型。这个模型的容量较低。

运行下面的代码,不做任何更改,训练一个线性模型在 Spotify 数据集上。

model = keras.Sequential([layers.Dense(1, input_shape=input_shape),
])
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, # suppress output since we'll plot the curves
)
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()));

曲线呈现“曲棍球杆”形状并不罕见,就像您在这里所看到的一样。这使得训练的最后阶段很难看清楚,所以让我们从第10个周期开始:

# Start the plot at epoch 10
history_df.loc[10:, ['loss', 'val_loss']].plot()
print("Minimum Validation Loss: {:0.4f}".format(history_df['val_loss'].min()));

1. 评估基准线

您可以自己判断一下。你会说这个模型是欠拟合、过拟合还是刚刚好?

# View the solution (Run this cell to receive credit!)
q_1.check()

现在让我们给我们的网络增加一些能力。我们将添加三个隐藏层,每个隐藏层有128个单元。运行下一个单元格来训练网络并查看学习曲线。

model = keras.Sequential([layers.Dense(128, activation='relu', input_shape=input_shape),layers.Dense(64, activation='relu'),layers.Dense(1)
])
model.compile(optimizer='adam',loss='mae',
)
history = model.fit(X_train, y_train,validation_data=(X_valid, y_valid),batch_size=512,epochs=50,
)
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()));

2. 添加容量

对于这些曲线,你如何评估?是欠拟合、过拟合还是恰到好处?

# View the solution (Run this cell to receive credit!)
q_2.check()

3. 定义早停止回调函数

现在定义一个早停回调函数,它等待5个epoch(patience)以至少0.001的验证损失变化(min_delta),并保留具有最佳损失的权重(restore_best_weights)。

from tensorflow.keras import callbacks# YOUR CODE HERE: define an early stopping callback
early_stopping = ____# Check your answer
q_3.check()
# Lines below will give you a hint or solution code
#q_3.hint()
#q_3.solution()

现在运行这个单元格以训练模型并获得学习曲线。注意模型.fit中的callbacks参数。

model = keras.Sequential([layers.Dense(128, activation='relu', input_shape=input_shape),layers.Dense(64, activation='relu'),    layers.Dense(1)
])
model.compile(optimizer='adam',loss='mae',
)
history = model.fit(X_train, y_train,validation_data=(X_valid, y_valid),batch_size=512,epochs=50,callbacks=[early_stopping]
)
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()));

4. 训练和解释

与没有早停训练相比,这是一个改进吗?(呵呵)

# View the solution (Run this cell to receive credit!)
q_4.check()

如果喜欢的话,可以尝试使用耐心和min_delta进行实验,看看可能会有什么不同。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#对于文件中的文件名判断问题

C#中对于文件名的判断问题,我们使用bool值进行值的传递,首先我们使用内置方法进行文件字符串匹配的bool值回传,我们打印出文件名以及相对应的bool,即可知道文件名是否真正生效 bool isHave fileName.Contains("Hello"…

代码学习记录22--回溯算法第三天

随想录日记part22 t i m e : time: time: 2024.03.17 主要内容:今天主要是结合类型的题目加深对回溯算法的理解:1.组合总和;2.组合总和 ;3.分割回文串。 39. 组合总和 40.组合总和II131.分割回文串 Topic1组合总和 题…

【Node.js从基础到高级运用】十四、Node.js 错误处理与日志记录

引言 在这篇博客文章中,我们将深入探讨Node.js中的错误处理和日志记录的最佳实践。我们会了解如何在Node.js应用程序中有效地捕获和处理错误,并利用日志库如morgan来记录应用程序的活动和错误信息。 第1部分:Node.js中的错误处理 同步代码中…

Spring AI Embeddings 和 Vector 入门

在前面 Spring AI Chat 简单示例 中介绍了 Chat 的基本用法,本文在此基础(主要是pom.xml)上继续探索 Embedding 和 Vector。 官方文档: embeddings: https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embedding…

断点重训教程:如何有效地保护深度学习模型训练进度

在深度学习领域,长时间训练是常见的需求,然而,在训练过程中可能会面临各种意外情况,比如计算机故障、断电等,这些意外情况可能导致训练过程中断,造成已经投入的时间和资源的浪费。为了应对这种情况&#xf…

Avue框架实现图表的基本知识 | 附Demo(全)

目录 前言1. 柱状图2. 折线图3. 饼图4. 刻度盘6. 仪表盘7. 象形图8. 彩蛋8.1 饼图8.2 柱状图8.3 折线图8.4 温度仪表盘8.5 进度条 前言 以下Demo,作为初学者来说,会相应给出一些代码注释,可相应选择你所想要的款式 对于以下Demo&#xff0c…

GStreamer简单看看

主要是现在弄摄像头,要用到这东西。所以学学。 最权威主页:GStreamer: open source multimedia framework 大概看了下,好像命令也不难。 gst-launch-1.0 v4l2src device/dev/video0 ! video/x-raw,formatYUY2,width640,height480,framerat…

说说你对webpack的理解?解决了什么问题?

文章目录 一、背景二、问题三、是什么参考文献 一、背景 Webpack 最初的目标是实现前端项目的模块化,旨在更高效地管理和维护项目中的每一个资源 模块化 最早的时候,我们会通过文件划分的形式实现模块化,也就是将每个功能及其相关状态数据各…

Batch Normalization(批量归一化)和 Layer Normalization(层归一化)

Batch Normalization(批量归一化)和 Layer Normalization(层归一化)都是深度学习中用于改善网络训练过程的归一化技术。尽管它们的目标相似,即通过规范化中间层的激活值来加速训练过程并提高性能,但它们在细节上有所不同。 Batch Normalization (批量归一化) Batch Nor…

谷歌地图TMS地图服务地址收集2024,测试可用

对于普通的开发者或者GIS从业者来说,免费的底图影像服务,太重要了。之前写过一篇谷歌地图的TMS地址收集的博文,由于谷歌网站关闭已经不能用。最近又发现了谷歌在国内开放了其他地址,在这里给大家分享一下。 https://gac-geo.googl…

Ant Design Vue和VUE3下的upload组件使用以及文件预览

Ant Design Vue和VUE3下的upload组件使用以及文件预览 文章目录 Ant Design Vue和VUE3下的upload组件使用以及文件预览一、多文件上传1.需求2.样例3.代码 二、单文件上传1. 需求2. 样例3.代码 二、多文件上传产生的时间超时问题三、文件系统名称更改1. 修改文件index.html2. 修…

Leetcode热题100:图论

Leetcode 200. 岛屿数量 深度优先搜索法: 对于这道题来说,是一个非常经典的图的问题,我们可以先从宏观上面来看问题,也就是说在不想具体算法的前提下,简单的说出如何找到所有的岛屿呢? 如图中所示&#x…

oracle 19c单机版本补丁升级

文章目录 一、补丁包概述二、备份opatch三、替换高版本opatch四、打DB补丁1、关闭数据库2、关闭监听3、解压补丁4、冲突检测5、补丁空间检查6、执行补丁升级7、将更新内容加载到数据库8、最后查看数据库版本9、卸载补丁包 一、补丁包概述 补丁升级包 链接:https://…

【系统架构设计师】计算机系统基础知识 03

系统架构设计师 - 系列文章目录 01 系统工程与信息系统基础 02 软件架构设计 03 计算机系统基础知识 文章目录 系统架构设计师 - 系列文章目录 文章目录 前言 一、计算机系统概述 1.计算机组成 ​编辑2.存储系统 二、操作系统 ★★★★ 1.进程管理 2.存储管理 1.页式存储 …

Golang Gorm 自动分批查询

场景: 目标查询全量数据,但需要每次Limit分批查询,保护数据库 文档: https://gorm.io/zh_CN/docs/advanced_query.html // Param: // dest 目标地址 // batchSize 大小 // fc 处理函数func (db *DB) FindInBatc…

安卓 Android Activity 生命周期

文章目录 Intro生命周期方法 & 执行顺序结论code Intro 本文提供一个测试类通过打印的方式展示在多个Activity之间互相跳转的时候,各个Activity的生命周期相关方法的执行顺序。 生命周期方法 & 执行顺序结论 下图出自 郭霖 《第一行代码(第二…

电网的正序参数和等值电路(一)

本篇为本科课程《电力系统稳分析》的笔记。 本篇为第二章的第一篇笔记。 电力系统正常运行中,可以认为系统的三相结构和三相负荷完全对称。而对称三相的计算可以用一相来完成,其中所有给出的标称电压都是线电压的有效值,假定系统全部是Y-Y型…

【网站项目】291校园疫情防控系统

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

The 2023 Guangdong Provincial Collegiate Programming Contest

I. Path Planning 嗯,怎么说呢,一般二维图,数据不是很大的比如n*m*log级别允许的,如果一眼不是bfs,可以考虑结合一下二分 本题可知,只能向下或者向右,那么我们就像如果答案为x,那么…

windows下使用压缩包安装mysql8.0数据库

获取安装包 可以访问mysql 官网下载压缩安装包 (官网地址:https://downloads.mysql.com/archives/community/) 根据自己的需要,下载对应mysql版本,我选择是是8.0.16版本 安装 解压之后,可以看到压缩包…