政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(三)—— 随机梯度下降

news2024/11/15 12:28:52

政安晨的个人主页政安晨

欢迎 👍点赞✍评论⭐收藏

收录专栏: TensorFlow与Keras实战演绎

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

这篇文章中,咱们将使用Keras和TensorFlow训练一个神经网络,如果您是第一次看到这篇文章,那就是训练您的第一个神经网络。

前言

随机梯度下降(Stochastic Gradient Descent,简称SGD)是深度学习中最常用的优化算法之一。它是一种迭代的优化算法,用于求解目标函数的最小值。

在深度学习中,目标是通过不断调整模型的参数来最小化损失函数。

SGD的基本思想是每次迭代时,随机选择一小批训练样本(称为一个mini-batch),计算这个mini-batch的梯度,并用梯度的负方向更新模型的参数。这样反复进行迭代,直到达到停止条件为止。

与传统的梯度下降算法不同,SGD每次迭代只利用一个mini-batch来估计梯度,因此计算速度更快。此外,在数据比较多的情况下,SGD还具有一定的随机性,能够逃离局部最小值,从而更有可能达到全局最小值。

然而,SGD也存在一些问题。由于每次迭代只使用一个mini-batch,因此梯度估计可能不够准确,导致更新方向不够理想,收敛速度较慢。为了解决这个问题,可以使用一些改进的SGD算法,如批量梯度下降(Batch Gradient Descent)、动量法(Momentum)、Adam等。

总的来说,SGD是深度学习中非常重要的优化算法,能够高效地训练深度神经网络模型。它的简单性和可扩展性使其成为了深度学习中的核心算法之一。


在这个系列的前两篇文章中,我们学习了如何通过堆叠稠密层来构建全连接网络。当网络首次创建时,所有的权重都是随机设置的 - 网络还不知道任何东西。

在本文中,我们将看到如何训练神经网络我们将看到神经网络如何学习

与所有机器学习任务一样,我们首先需要一组训练数据训练数据中的每个示例由一些特征(输入)和一个期望的目标结果(输出)组成。训练网络意味着调整其权重,使其能够将特征转化为目标结果。

例如,在80种麦片数据集中,我们希望有一个网络可以获取每种麦片的“糖分”、“纤维”和“蛋白质”含量,并预测该麦片的“卡路里”含量。如果我们成功地训练了一个网络来做到这一点,那么它的权重必须以某种方式表示这些特征与目标结果之间的关系,如训练数据所示。

除了训练数据,我们还需要两个东西

一个“损失函数”,用于衡量网络的预测效果。 一个“优化器”,用于告诉网络如何调整权重。

损失函数

我们已经了解了如何为网络设计架构,但我们还没有看到如何告诉网络解决什么问题。

这就是损失函数的工作。

损失函数衡量的是目标的真实值与模型预测值之间的差异

不同的问题需要不同的损失函数

我们一直在研究回归问题,其中的任务是预测一些数值--比如80种谷物中的卡路里,红酒质量评分。其他回归任务可能包括预测房屋价格或汽车燃油效率。

回归问题常用的损失函数是平均绝对误差(MAE)对于每个预测值y_pred,MAE通过计算真实目标值y_true与预测值之间的绝对差abs(y_true - y_pred)来衡量它们之间的差异。

在数据集上的总MAE损失是所有这些绝对差异的均值

平均绝对误差是拟合曲线与数据点之间的平均距离

除了MAE之外,你可能在回归问题中看到其他的损失函数,如均方误差(MSE)或Huber损失(在Keras中都可用)。

在训练过程中,模型将使用损失函数作为指导,找到其权重的正确值(较低的损失更好)。换句话说,损失函数告诉网络它的目标。

优化器 - 随机梯度下降

我们已经描述了我们希望网络解决的问题,但现在我们需要说明如何解决这个问题。

这是优化器的工作优化器是一种调整权重以最小化损失的算法。

几乎所有用于深度学习的优化算法都属于一种称为随机梯度下降(SGD)的算法家族。它们是迭代算法,在训练网络时分步进行。

训练的一个步骤如下所示

1. 抽样一些训练数据,并通过网络进行预测。

2. 衡量预测结果与真实值之间的损失。

3. 最后,调整权重以使损失减小。

这种调整的步骤可以一直小到你接受为止,当然,这种调整也是有限度的,是有边界的。

使用随机梯度下降训练神经网络。

每个迭代的训练数据样本被称为一个小批量(通常简称为“批量”),而完整的一轮训练数据被称为一个周期。

你训练的周期数决定了网络将会看到每个训练样本的次数。

上面左边第一幅图淡红色的点表示整个训练集,而实心红点表示小批量。每当看到一个新的小批量时,它会将权重(斜率w和y截距b)向着该批量上的正确值进行调整。一批一批地训练,最终线条会收敛到最佳拟合。你可以看到,随着权重接近其真实值,损失越来越小。

学习率和批大小

请注意,该行只在每个批次的方向上进行了小幅度的偏移(而不是完全移动)。这些偏移的大小由学习率决定。较小的学习率意味着网络需要看到更多的小批量数据,才能使其权重收敛到最佳值。

学习率和小批量大小是对训练过程影响最大的两个参数。它们之间的相互作用常常是微妙的,选择这些参数的正确方式并不总是明显的。(我们将在练习中探讨这些影响。)

幸运的是,对于大多数工作来说,不必进行广泛的超参数搜索就能获得令人满意的结果。Adam是一种具有自适应学习率的SGD算法,它适用于大多数问题,无需任何参数调整(在某种意义上它是“自我调节的”)。Adam是一个非常好的通用优化器。

添加损失函数和优化器

定义模型后,可以使用模型的compile方法添加损失函数和优化器:

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

请注意,我们可以仅通过一个字符串来指定损失函数和优化器。您也可以通过Keras API直接访问这些(如果您想要调整参数的话),但对于我们来说,使用默认值就可以了。

名字有什么重要性?

梯度是一个向量,告诉我们权重需要朝着哪个方向前进。

更准确地说,它告诉我们如何改变权重,以使损失函数最快地变化。

我们将这个过程称为梯度下降,因为它使用梯度来沿着损失曲线向最小值降低。

随机意味着“由机会决定”。

我们的训练是随机的,因为小批量是从数据集中随机抽取的样本。这就是为什么它被称为随机梯度下降(SGD)!

例子 - 红酒品质

现在我们知道我们需要开始训练深度学习模型的一切了。那么让我们来看看它的实际效果吧!我们将使用红酒质量数据集。

该数据集包含大约1600种葡萄牙红葡萄酒的理化测量数据。还包括每种葡萄酒的品质评级,评级是通过盲品测试得出的。我们能否通过这些测量数据来预测葡萄酒的品质感知程度?

我们已经将所有的数据准备工作放在了下一个隐藏单元中。

这并不是后面讨论的关键,所以你可以随意跳过它。现在你可能要注意的一件事是,我们已经将每个特征重新缩放到了区间 [0,1]。正如我们将在第5课中讨论的那样,神经网络在输入具有相同的尺度时表现最佳。

import pandas as pd
from IPython.display import display

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)
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']

这个网络应该有多少个输入?

我们可以通过查看数据矩阵中的列数来发现这一点。确保在这里不包括目标变量('quality'),只包括输入特征。

print(X_train.shape)

十一个列意味着十一个输入。

我们选择了一个三层网络,有超过1500个神经元。这个网络应该能够学习数据中相当复杂的关系。

from tensorflow import keras
from tensorflow.keras import layers

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',
)

现在我们准备开始训练!

我们告诉Keras每次将256行训练数据一次性输入优化器(即batch_size),并在整个数据集上重复这个过程10次(即epochs)。

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

你可以看到,在模型训练过程中,Keras会实时更新并显示损失值。

通常,更好的观察损失的方法是将其绘制出来。实际上,fit方法会在训练过程中记录损失值,并保存在一个名为History的对象中。我们将把这些数据转换为Pandas的dataframe格式,以便更容易进行绘图。

import pandas as pd

# convert the training history to a dataframe
history_df = pd.DataFrame(history.history)
# use Pandas native plot method
history_df['loss'].plot();

注意随着每个周期的进行,损失逐渐趋于平缓。当损失曲线变得水平时,意味着模型已经学习到了它所能学习的所有知识,没有继续训练更多周期的必要了。

练习:随机梯度下降

介绍

在这个练习中,您将在燃油经济数据集上训练神经网络,然后探索学习率和批处理大小对随机梯度下降(SGD)的影响。

当您准备好后,请运行以下代码:

# Setup plotting
import matplotlib.pyplot as plt
from learntools.deep_learning_intro.dltools import animate_sgd
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.ex3 import *

在燃油经济数据集中,您的任务是根据其发动机类型或制造年份等特征预测汽车的燃油经济性。

首先通过运行下面的单元格来加载数据集。

import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import make_column_transformer, make_column_selector
from sklearn.model_selection import train_test_split

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

X = fuel.copy()
# Remove target
y = X.pop('FE')

preprocessor = make_column_transformer(
    (StandardScaler(),
     make_column_selector(dtype_include=np.number)),
    (OneHotEncoder(sparse=False),
     make_column_selector(dtype_include=object)),
)

X = preprocessor.fit_transform(X)
y = np.log(y) # log transform target instead of standardizing

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

如果你喜欢的话,可以看一下数据。

在这个案例中,我们的目标是“FE”列,其余列都是特征。

# Uncomment to see original data
fuel.head()
# Uncomment to see processed features
pd.DataFrame(X[:10,:]).head()

下面是定义我们将用于此任务的网络。

from tensorflow import keras
from tensorflow.keras import layers

model = keras.Sequential([
    layers.Dense(128, activation='relu', input_shape=input_shape),
    layers.Dense(128, activation='relu'),    
    layers.Dense(64, activation='relu'),
    layers.Dense(1),
])

1.添加损失函数和优化器。

在训练网络之前,我们需要定义要使用的损失函数和优化器。使用模型的compile方法,添加Adam优化器和MAE损失。

# YOUR CODE HERE
____

# Check your answer
q_1.check()
# Lines below will give you a hint or solution code
#q_1.hint()
#q_1.solution()

2.训练模型

一旦您已经定义了模型并使用损失函数和优化器进行了编译,您就可以开始训练了。

使用批量大小为128,在200个周期内训练网络。输入数据为X,目标为y。

# YOUR CODE HERE
history = ____

# Check your answer
q_2.check()
# Lines below will give you a hint or solution code
#q_2.hint()
#q_2.solution()

最后一步是查看损失曲线并评估训练情况。运行下面的单元格以获得训练损失的图表。

import pandas as pd

history_df = pd.DataFrame(history.history)
# Start the plot at epoch 5. You can change this to get a different view.
history_df.loc[5:, ['loss']].plot();

评估培训成功程度

如果您进一步训练模型,您是否预期损失会进一步减少?

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

你通过学习率和批量大小可以对以下方面进行一定程度的控制:

* 模型训练所花费的时间

* 学习曲线的噪声程度

* 损失的减小程度

为了更好地理解这两个参数,我们将看看线性模型,即最简单的神经网络。

只有一个权重和一个偏置,更容易看出参数的变化会产生什么影响。

下一个单元格将生成类似教程中的动画。

更改learning_rate、batch_size和num_examples(数据点的数量),然后运行该单元格。(可能需要一两分钟。)尝试以下组合,或尝试一些自己的组合:

# YOUR CODE HERE: Experiment with different values for the learning rate, batch size, and number of examples
learning_rate = 0.05
batch_size = 32
num_examples = 256

animate_sgd(
    learning_rate=learning_rate,
    batch_size=batch_size,
    num_examples=num_examples,
    # You can also change these, if you like
    steps=50, # total training steps (batches seen)
    true_w=3.0, # the slope of the data
    true_b=2.0, # the bias of the data
)

学习率和批量大小

这些参数的变化产生了什么影响?在你考虑完后,观察下面代码后进行讨论。

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

小伙伴们可以参考我这个系列中前面的文章搭建环境,自己演练一下,会有更深的理解。

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

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

相关文章

RAFT: Adapting Language Model to Domain Specific RAG

预备知识 RAG介绍一文搞懂大模型RAG应用(附实践案例) - 知乎 (zhihu.com) RAG的核心理解为“检索生成” 检索:主要是利用向量数据库的高效存储和检索能力,召回目标知识; 生成:利用大模型和Prompt工程&a…

今天聊聊Docker

在数字化时代,软件应用的开发和部署变得越来越复杂。环境配置、依赖管理、版本控制等问题给开发者带来了不小的挑战。而Docker作为一种容器化技术,正以其独特的优势成为解决这些问题的利器。本文将介绍Docker的基本概念、优势以及应用场景,帮…

前缀和(三)

题目:激光炸弹 1 链接 P2280 [HNOI2003] 激光炸弹 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 2.大体思路 先开辟一个全局变量的 s 二维数组,这个二维数组开成 s [ 5010 ] [ 5010 ] ,这个是为了,能够将它所给的所有有价值的…

由vue2版本升级vue3版本遇到的问题

一、vuedraggable 由vue2版本升级vue3版本后,可能会遇到以下几种bug: 1、vue3vuedraggable报错TypeError: Cannot read properties of undefined (reading ‘updated’):这个一般是因为插件使用语法有问题,vue3版本的插件使用时&…

Git基础(24):分支回退

文章目录 前言放弃已修改的内容分支回退到指定commit 前言 将分支回退到之前的某个版本 开发中,可能开发某个功能不需要了,或者想要回退到之前历史的某个commit, 放弃后来修改的内容。 放弃已修改的内容 如果未提交,直接使用 …

一个优秀的开源ChatGpt外壳项目(lobe-chat)

lobe-chat 简介: 开源、现代化设计的 ChatGPT/LLMs 聊天应用与开发框架支持语音合成、多模态、可扩展的插件系统,一键免费拥有你自己的 ChatGPT/Gemini/Ollama 应用。 下载lobe-chat lobe-chat项目开源地址:GitHub - lobehub/lobe-chat: &am…

[Linux]文件缓冲区

文件fd 输出重定向除了用dup2()改变数组下标外&#xff0c;还可以用命令来完成 所有的命令执行&#xff0c;都必须有操作系统将其运行起来变成进程&#xff0c;然后根据>>, <<来判断是输入重定向&#xff0c;还是输出重定向。 缓冲区 之所以有缓冲区&#xff0…

Jenkins+Ant+Jmeter接口自动化集成测试详解

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、Jenkins安装配置 1、安装配置JDK1.6环境变量&#xff1b; …

mysql事务及存储引擎

目录 什么是事务 事务的ACIP特性 事务之间的影响 mysql隔离级别 事务隔离级别的作用范围 事务控制语句 mysql存储引擎 什么是事务 事务是一种机制、一个操作序列&#xff0c;包含了一组数据库操作命令&#xff0c;并且把所有的命令作为一个整体一起向系统提交或撤销操作…

STM32—控制蜂鸣器(定时器)

目录 1 、 电路构成及原理图 2 、编写实现代码 main.c tim_irq.c 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 定时器中断是利用定时器的计数功能&#xff08;向上计数或向下计…

Web前端—CSS属性计算过程

属性计算过程 CSS 属性计算过程1. 确定声明值2. 层叠冲突比较源的重要性比较优先级比较次序 3. 使用继承4. 使用默认值 CSS 属性计算过程 我们所书写的任何一个 HTML 元素&#xff0c;实际上都有完整的一整套 CSS 样式&#xff08;该元素上面会有 CSS 所有的属性。&#xff0…

Windows 7 一键恢复 - 联想拯救系统

Windows 7 一键恢复 - 联想拯救系统 1. 联想拯救系统1.1. OEM 分区1.2. 一键恢复 References 1. 联想拯救系统 1.1. OEM 分区 计算机 -> 管理 -> 存储 -> 磁盘管理 1.2. 一键恢复 重新启动电脑 F11 -> 从初始备份恢复 References [1] Yongqiang Cheng, https…

实在数字员工,助力菜鸟智慧物流高效腾飞,领航行业新高度

秉承人人都有一个智能助理的发展愿景&#xff0c;自2023年首个数字员工落地以来&#xff0c;菜鸟数字员工累计运行时长已达10万小时。 在智能物流科技不断飞速迭代的今天&#xff0c;物流行业作为社会经济运行的重要支柱和电子商务生态链的关键环节&#xff0c;面临着前所未…

Python灰帽子网络安全实践

教程介绍 旨在降低网络防范黑客的入门门槛&#xff0c;适合所有中小企业和传统企业。罗列常见的攻击手段和防范方法&#xff0c;让网站管理人员都具备基本的保护能力。Python 编程的简单实现&#xff0c;让网络运维变得更简单。各种黑客工具的理论和原理解剖&#xff0c;让人知…

PLC常用通信协议应用

PLC通信协议 ModbusModbus协议介绍Modbus协议的应用Modbus通信模式 Modbus RTU通讯Modbus RTU报文映射寄存器常见功能码数据类型Modbus CRC校验计算Modbus RTU举例&#xff08;读位&#xff09;Modbus RTU举例&#xff08;读字&#xff09; Modbus TCP协议应用TCP数据帧Modbus …

Spring IOC 容器的加载过程(bean 的创建过程)

Spring IOC 容器的加载过程&#xff08;bean 的创建过程&#xff09; 配置Bean 通过xml或者是Component Bean 等进行配置 解析Bean,得到BeanDefinition定义对象 通过 BeanDefintionReader 将 bean 进行解析&#xff0c;准备要创建的bean对象的定义对象BeanDefinition,存放到Be…

Elasticsearch 索引模板、生命周期策略、节点角色

简介 索引模板可以帮助简化创建和二次配置索引的过程&#xff0c;让我们更高效地管理索引的配置和映射。 索引生命周期策略是一项有意义的功能。它通常用于管理索引和分片的热&#xff08;hot&#xff09;、温&#xff08;warm&#xff09;和冷&#xff08;cold&#xff09;数…

尽可能使用清晰、统一的方式初始化所有对象:列表初始化。【C++】

不管是为了统一性&#xff0c;还是避免发生窄化转换&#xff0c;尽可能使用初始化列表。 说明哪些对象可以使用列表初始化&#xff1f;代码演示 说明 C11 引入了列表初始化&#xff08;也称为统一初始化或初始化列表&#xff09;&#xff0c;它是一种使用花括号 {} 来初始化对…

对象实例化在bean注入之前导致@Autowired失效

开发时遇到一个问题&#xff0c;Springboot的Autowired失效&#xff0c;无法注入bean&#xff0c;获取的到的mqttProperties一直为空。 MqttProperties定义&#xff1a; 业务代码&#xff1a; 按理来说&#xff0c;我的MqttProperties和当前类 NettyMqttClient都注册为了bea…

铁道障碍物检测6种YOLOV8

铁道障碍物检测6种&#xff0c;采用YOLOV8训练&#xff0c;得到PT模型&#xff0c;然后转换成ONNX模型&#xff0c;OPENCV调用 铁道障碍物检测6种YOLOV8