【深度学习_TensorFlow】过拟合

这篇具有很好参考价值的文章主要介绍了【深度学习_TensorFlow】过拟合。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

过拟合与欠拟合


欠拟合: 是指在模型学习能力较弱,而数据复杂度较高的情况下,模型无法学习到数据集中的“一般规律”,因而导致泛化能力弱。此时,算法在训练集上表现一般,但在测试集上表现较差,泛化性能不佳。

过拟合: 是指模型在训练数据上表现很好,但在测试数据上表现不佳。这是由于模型过于复杂,记住了训练数据中的噪声和模式,而没有学到一般规则。本文将探讨过拟合问题以及其解决方法。

过拟合的解决方法


方法 描述
增加训练数据
(More data) 通过增加训练数据量,简单粗暴最有效,可以减少过拟合现象。
正则化
(regularization) 在损失函数中添加一项,以惩罚模型的复杂度。常用的正则化方法包括L1正则化、L2正则化和dropout。
早停法
(Early stopping) 在训练过程中,每次迭代后都会评估模型在验证集上的性能。如果性能在连续若干次迭代中没有提高,就停止训练。
数据增强
(Data augmentation) 通过改变原有数据减少过拟合。例如,可以通过旋转、缩放等方式对图像数据进行增强。

写在中间

可以看到随着网络层数增加,模型变得复杂,过拟合现象变得愈发严重。接下来,我们将介绍一系列方法来帮助检测并抑制过拟合现象。

【深度学习_TensorFlow】过拟合,# TensorFlow深度学习,深度学习,tensorflow,人工智能

1. 交叉验证

增加数据集是最有效的方法,但是代价往往是昂贵的,所以要充分利用好现有的数据集。前面我们介绍了数据集需要划分为训练集和测试集,但我们为了挑选模型超参数和检测过拟合线性,一般需要将原来的训练集再次切分为新的训练集和验证集(validation set)。最终数据集被切分为 训练集、验证集、测试集。这三部分数据集的功能如下:

类别 描述
训练集 用于训练模型的参数,通过学习训练数据集来进行模型训练
验证集 用于评估训练过程中的模型表现,调整模型的超参数
测试集 用于评估最终训练好的模型在真实数据上的表现,测试验证模型的性能,评估模型的预测能力和泛化能力

验证集和测试集的区分

验证集使命:根据验证集的表现来调整模型的各种超参数的设置,提升模型的泛化能力。

测试集使命:就是检验模型的能力,其表现不能用来反馈模型的调整(就如你不能拿着期末考试原题来练习,否则期末高分就不能体现出你平时学习的真实状况),我们的办法就是从平常的练习题中抽取几道题组成验证集来检验你的能力。

这是一个将mnist手写数字识别测试集切分的例子,将6万张图像的前5万张划分为训练集,后1万张划分为验证集

(x, y), (x_test, y_test) = datasets.mnist.load_data()

# 60k训练集切分为 50k训练集和 10k验证集
# (x_train, y_train), (x_val, y_val)
x_train, x_val = tf.split(x, num_or_size_splits=[50000, 10000])
y_train, y_val = tf.split(y, num_or_size_splits=[50000, 10000])

# 训练集
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_db = train_db.map(preprocess).shuffle(10000).batch(128)

# 验证集
val_db = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_db = val_db.map(preprocess).shuffle(10000).batch(128)

# 测试集
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_db = test_db.map(preprocess).shuffle(10000).batch(128)

但是这样切分还是有局限性的,训练集只能在前5万张图像中出现,验证集只能在后1万张图像中出现,是否有方法让验证集能使用前5万张的图像呢?还真有,这就是标题所提及的**交叉验证:**我们将训练集的6万张图像划成n份,每训练取其中的 n - 1 份作为训练集,取 1 份作为验证集,而非固定前5万张为训练集,后 1 万张为验证集。

# 创建一个范围为60000的索引数组
idx = tf.range(60000)
# 随机打乱索引数组
idx = tf.random.shuffle(idx)
# 使用索引数组从x和y中获取训练集的样本
# 训练集的样本数量为50000
x_train, y_train = tf.gather(x, idx[:50000]), tf.gather(y, idx[:50000])
# 使用索引数组从x和y中获取验证集的样本
# 验证集的样本数量为10000
x_val, y_val = tf.gather(x, idx[-10000:]), tf.gather(y, idx[-10000:])

也可以不用手动划分,在训练函数中增加参数,即可自动化操作

# 使用60k训练集对网络进行训练,设置训练周期数为6
# 设置验证集占比为0.1,即数据集中10%的数据将作为验证集
# 设置每个2个训练周期进行一次验证
network.fit(train_db, epochs=6, validation_split=0.1, validation_freq=2)

2. 正则化

之所以出现过拟合的现象,是因为模型太过复杂,这里通过限制网络参数的稀疏性来约束网络的实际容量,这种约束一般通过在损失函数上添加额外的参数稀疏性惩罚项实现,常用的正则化的方式有L0、L1、L2正则化,dropout正则化。


简单介绍

关于正则化的数学原理,本人也搞不明白,也就不滥竽充数了。

有关实现简单概括就是在损失函数中引入模型权重参数的L范数,使学习到的权重参数稀疏化。

正则化的方式可以手动实现,也可以调用API实现:其中手动实现主要在计算loss值的后面,调用API主要在创建层的时候。

import tensorflow as tf
from tensorflow.keras import layers, regularizers

# 网络构建
# 这会在模型损失函数中加入权重参数的L2范数作为惩罚项,力度由0.001控制。
network = Sequential([layers.Dense(256, kernel_regularizer=regularizers.l2(0.001), activation='relu'),
                      layers.Dense(128, kernel_regularizer=regularizers.l2(0.001), activation='relu'),
                      layers.Dense(64, kernel_regularizer=regularizers.l2(0.001), activation='relu'),
                      layers.Dense(32, kernel_regularizer=regularizers.l2(0.001), activation='relu'),
                      layers.Dense(10)])
# 参数构建
network.build(input_shape=(None, 28*28))
# 模型展示
network.summary()
# 截取手动前向计算的代码
for step, (x, y) in enumerate(train_db):
    # 创建一个 GradientTape,用于记录计算过程
    with tf.GradientTape() as tape:
        
        x = tf.reshape(x, (-1, 28*28))  # [b, 28, 28] => [b, 784]
       
        out = network(x)  # [b, 784] => [b, 10]
        
        y_onehot = tf.one_hot(y, depth=10)  # [b] => [b, 10]
        # 使用交叉熵损失函数计算 loss
        loss = tf.reduce_mean(tf.losses.categorical_crossentropy(y_onehot, out, from_logits=True))
        
  
        loss_regularization = []
        for p in network.trainable_variables:  # 重点在这里,遍历网络中所有的可训练参数(network.trainable_variables)。
            loss_regularization.append(tf.nn.l2_loss(p))  # # 对每个参数计算L2正则化项(tf.nn.l2_loss(p)),这会返回一个标量。
        loss_regularization = tf.reduce_sum(tf.stack(loss_regularization))  # # 将所有参数的L2正则化项求和,得到正则化损失loss_regularization。
        # 将损失函数定义为交叉熵损失和 L2 正则化损失的和
        loss = loss + 0.0001 * loss_regularization
    # 使用 tape 计算损失函数关于网络参数的梯度,并应用优化器进行反向传播更新参数
    grads = tape.gradient(loss, network.trainable_variables)
    optimizer.apply_gradients(zip(grads, network.trainable_variables))

正则化效果

【深度学习_TensorFlow】过拟合,# TensorFlow深度学习,深度学习,tensorflow,人工智能

Dropout


通过随机断开神经网络的连接,减少每次训练时实际参与计算的模型的参数量,但是在测试时,Dropout会恢复所有的连接,保证模型测试时获得最好的性能。

【深度学习_TensorFlow】过拟合,# TensorFlow深度学习,深度学习,tensorflow,人工智能

我们以层方式来实现以上功能

import tensorflow as tf
from tensorflow.keras import layers, regularizers

# 网络构建

network = Sequential([layers.Dense(256, activation='relu'),
                      layers.Dropout(0.5),  # 有0.5的概率断开与下一层神经元的连接
                      layers.Dense(128, activation='relu'),
                      layers.Dropout(0.5),
                      layers.Dense(64, activation='relu'),
                      layers.Dense(32, activation='relu'),
                      layers.Dense(10)])
# 参数构建
network.build(input_shape=(None, 28*28))
# 模型展示
network.summary()

for step, (x, y) in enumerate(train_db):
    # 训练时
    with tf.GradientTape() as tape:
      out = network(x, training=True)
      
    # 测试时
    out = network(x, training=False)

3. Early stopping

早停法

那么如何选择合适的 Epoch 就提前停止训练(Early Stopping),避免出现过拟合现象呢?我们可以通过观察验证指标的变化,来预测最适合的 Epoch 可能的位置。具体地,对于分类问题,我们可以记录模型的验证准确率,并监控验证准确率的变化,当发现验证准确率连续𝑛个 Epoch 没有下降时,可以预测可能已经达到了最适合的 Epoch 附近,从而提前终止训练。

from tensorflow.keras.callbacks import EarlyStopping


# 数据集读取···

# 定义早停法回调函数
early_stopping = EarlyStopping(monitor='val_loss',  # 监视验证集loss
                               patience=3,  # 当验证集loss在3个epoch内都没有改善则停止训练
                               mode='min',  # 监测loss时一般设置为min,监测准确值时一般设置为max
                               verbose=1,  # 检测值改善时打印一条信息
                               restore_best_weights=True  # 将权重恢复到最好的一个epoch
                               )
 # 网络构建
 
 # 参数构建

 # 模型装配

 # 模型训练,添加参数
 network.fit(train_db, epochs=100,
            validation_data=val_db, validation_steps=10,
            callbacks=[early_stopping])

这里我们会对手写数字识别的代码再次进行修改,来使用上面提及的方法,你可以通过修改repeat的方式来复制数据集使训练数据增多,更改epochs的方式来增加训练次数,经过测试,这段代码在10 epochs 之后便达到了过拟合

import tensorflow as tf
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics, regularizers
from tensorflow.keras.callbacks import EarlyStopping
# 处理每一张图像
def preprocess(x, y):

    x = tf.cast(x, dtype=tf.float32) / 255.
    x = tf.reshape(x, [28 * 28])
    y = tf.cast(y, dtype=tf.int32)
    y = tf.one_hot(y, depth=10)

    return x, y

# 数据集读取
(x, y), (x_test, y_test) = datasets.mnist.load_data()

# # 固定切分
# # 60k训练集切分为 50k训练集和 10k验证集
# # (x_train, y_train), (x_val, y_val)
# x_train, x_val = tf.split(x, num_or_size_splits=[50000, 10000])
# y_train, y_val = tf.split(y, num_or_size_splits=[50000, 10000])

# 交叉验证切分
idx = tf.range(60000)
idx = tf.random.shuffle(idx)
x_train, y_train = tf.gather(x, idx[:50000]), tf.gather(y, idx[:50000])
x_val, y_val = tf.gather(x, idx[-10000:]), tf.gather(y, idx[-10000:])

# 训练集
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_db = train_db.map(preprocess).shuffle(10000).batch(128).repeat(10)

# 验证集
val_db = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_db = val_db.map(preprocess).shuffle(10000).batch(128)

# 测试集
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_db = test_db.map(preprocess).shuffle(10000).batch(128)

# 定义早停法回调函数
early_stopping = EarlyStopping(monitor='val_loss',  # 监视验证集loss
                               patience=3,  # 当验证集loss在2个epoch内都没有改善则停止训练
                               mode='min',  # 监测loss时一般设置为min,监测准确值时一般设置为max
                               verbose=1,  # 检测值改善时打印一条信息
                               restore_best_weights=True  # 将权重恢复到最好的一个epoch
                               )

# 网络构建
# 正则化:在模型损失函数中加入权重参数的L2范数作为惩罚项,力度由0.001控制。
# Dropout:添加dropout层来随机断开连接
network = Sequential([layers.Dense(256, kernel_regularizer=regularizers.l2(0.001), activation='relu'),
                      layers.Dropout(0.5),
                      layers.Dense(128, kernel_regularizer=regularizers.l2(0.001), activation='relu'),
                      layers.Dropout(0.5),
                      layers.Dense(64, kernel_regularizer=regularizers.l2(0.001), activation='relu'),
                      layers.Dense(32, kernel_regularizer=regularizers.l2(0.001), activation='relu'),
                      layers.Dense(10)])
# 参数构建
network.build(input_shape=(None, 28*28))
# 模型展示
network.summary()
# 模型装配
network.compile(optimizer=optimizers.Adam(learning_rate=0.01),
                loss=tf.losses.CategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])
# 模型训练
network.fit(train_db, epochs=50,
            validation_data=val_db, validation_steps=10,
            callbacks=[early_stopping])
# 模型评估
print('模型评估:')
network.evaluate(test_db)

写在最后

👍🏻点赞,你的认可是我创作的动力!
⭐收藏,你的青睐是我努力的方向!
✏️评论,你的意见是我进步的财富!文章来源地址https://www.toymoban.com/news/detail-688840.html

到了这里,关于【深度学习_TensorFlow】过拟合的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 人工智能之Tensorflow技术特点及组件结构

    前言 Tensorflow的前身时谷歌的神经网络算法库DistBelief,被广泛应用于各类机器学习、深度学习算法的编程实现。Tensorflow具有实现代码简洁、编程范式灵活、分布式深度学习算法执行效率高、多语言API支持、CPU/GPU部署方便、良好的可扩展性、可移植性及在学术研究和产品研发

    2024年02月21日
    浏览(53)
  • 【Python/人工智能】TensorFlow 框架原理及使用教程

    TensorFlow 是一款由 Google 开源的人工智能框架,是目前应用最广泛的深度学习框架之一。它可以在各种硬件平台上运行,包括单个 CPU、CPU 集群、GPU,甚至是分布式环境下的 CPU 和 GPU 组合。 除了深度学习领域,TensorFlow 还支持其他机器学习算法和模型,如 决策树 、 SVM 、 k-m

    2024年04月28日
    浏览(45)
  • 人工智能TensorFlow MNIST手写数字识别——实战篇

    上期文章TensorFlow手写数字-训练篇,我们训练了我们的神经网络,本期使用上次训练的模型,来识别手写数字(本期构建TensorFlow神经网络代码为上期文章分享代码) http://scs.ryerson.ca/~aharley/vis/conv/ 0、插入第三方库 1、图片处理函数

    2024年02月15日
    浏览(56)
  • 人工智能:Pytorch,TensorFlow,MXNET,PaddlePaddle 啥区别?

    学习人工智能的时候碰到各种深度神经网络框架:pytorch,TensorFlow,MXNET,PaddlePaddle,他们有什么区别? PyTorch、TensorFlow、MXNet和PaddlePaddle都是深度学习领域的开源框架,它们各自具有不同的特点和优势。以下是它们之间的主要区别: PyTorch是一个开源的Python机器学习库,它基

    2024年04月16日
    浏览(66)
  • 人工智能TensorFlow PyTorch物体分类和目标检测合集【持续更新】

    1. 基于TensorFlow2.3.0的花卉识别 基于TensorFlow2.3.0的花卉识别Android APP设计_基于安卓的花卉识别_lilihewo的博客-CSDN博客 2. 基于TensorFlow2.3.0的垃圾分类 基于TensorFlow2.3.0的垃圾分类Android APP设计_def model_load(img_shape=(224, 224, 3)_lilihewo的博客-CSDN博客   3. 基于TensorFlow2.3.0的果蔬识别系统的

    2024年02月09日
    浏览(58)
  • 【人工智能】Transformers 快速上手: 为 Jax、PyTorch 和 TensorFlow 打造的先进的自然语言处理

    为 Jax、PyTorch 和 TensorFlow 打造的先进的自然语言处理 🤗 Transformers 提供了数以千计的预训练模型,支持 100 多种语言的文本分类、信息抽取、问答、摘要、翻译、文本生成。它的宗旨是让最先进的 NLP 技术人人易用。 🤗 Transformers 提供了便于快速下载和使用的API,让你可以把

    2024年02月08日
    浏览(56)
  • 17- TensorFlow中使用Keras创建模型 (TensorFlow系列) (深度学习)

    知识要点 Keras 是一个用 Python 编写的高级神经网络 API 数据的开方:  np.sqrt(784)       # 28 代码运行调整到 CPU 或者 GPU: 模型显示: model.summary () 创建模型: 模型创建: model = Sequential () 添加卷积层: model.add (Dense(32, activation=\\\'relu\\\', input_dim=100))  # 第一层需要 input_dim 添加dropout: mod

    2024年02月01日
    浏览(87)
  • Tensorflow入门(1)——深度学习框架Tesnsflow入门 & 环境配置 & 认识Tensorflow

    1.anaconda以及Tensorflow的安装: https://blog.csdn.net/qq_33505204/article/details/81584257 2.Anaconda详细安装及使用教程: https://blog.csdn.net/ITLearnHall/article/details/81708148 3.windows平台下,TensorFlow的安装、卸载以及遇到的各种错误: https://blog.csdn.net/qq_27245699/article/details/81050035 CONDA环境安装: co

    2024年02月12日
    浏览(44)
  • 深度学习TensorFlow

      博主简介 博主是一名大二学生,主攻人工智能研究。感谢让我们在CSDN相遇,博主致力于在这里分享关于人工智能,c++,Python,爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主,博主会继续更新的,如果有错误之处,大家可以指正。 专栏简介:   本专栏主要研

    2023年04月08日
    浏览(36)
  • 【深度学习笔记】TensorFlow 基础

    在 TensorFlow 2.0 及之后的版本中,默认采用 Eager Execution 的方式,不再使用 1.0 版本的 Session 创建会话。Eager Execution 使用更自然地方式组织代码,无需构建计算图,可以立即进行数学计算,简化了代码调试的过程。本文主要介绍 TensorFlow 的基本用法,通过构建一个简单损失函数

    2024年02月13日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包