1.Keras简介
1.1 什么是Keras?
Keras 是一个开源的深度学习框架,用 Python 编写,构建于 TensorFlow 之上。它以简单、快速和易于使用为主要设计目标,适合初学者和研究者。
Keras 提供了高层次的 API,帮助用户快速构建和训练深度学习模型,而无需处理底层复杂的数学运算或框架细节。最初由 François Chollet 开发,现在是 TensorFlow 的核心部分。
1.2 Keras 有什么用?
Keras 的主要用途是帮助用户构建和训练深度学习模型,在计算机视觉、自然语言处理、时间序列分析等领域广泛使用。以下是其主要功能和作用:
(1)快速搭建深度学习模型
- 提供简洁的接口,用户只需几行代码即可完成神经网络的搭建。
- 支持常见的模型结构,例如多层感知机(MLP)、卷积神经网络(CNN)、循环神经网络(RNN)等。
(2)数据预处理与增强
- 提供工具处理数据,例如归一化、标准化等。
- 提供数据增强功能(如图像旋转、缩放等),提高模型的泛化能力。
(3)灵活的模型训练与优化
- 通过简单配置,可以快速设置训练参数(如学习率、损失函数、优化器等)。
- 支持分布式训练、GPU 加速,提升训练速度。
(4)模型评估与应用
- 提供模型评估方法,例如准确率、损失值等指标。
- 支持模型的保存与加载,便于部署到实际应用中。
(5) 兼容性强
- 可以与其他深度学习框架(如 TensorFlow、Theano)配合使用。
- 提供丰富的第三方扩展和预训练模型(如 ResNet、VGG)。
1.4 keras应用场景?
1.4.1 计算机视觉(Computer Vision)
Keras 提供了对图像处理和分析的强大支持,包括预训练模型和数据增强工具。
(1)常见应用:
- 图像分类(Image Classification)
- 如猫狗分类、垃圾分类等。
- 目标检测(Object Detection)
- 在图像中定位和标记目标物体,如人脸检测。
- 图像分割(Image Segmentation)
- 如医学影像分析、自动驾驶中的道路分割。
- 图像生成(Image Generation)
- 使用生成对抗网络(GAN)生成新的图像。
(2)实例:
- 使用 Keras 中的 VGG、ResNet 等预训练模型对照片进行分类。
- 数据增强:对图片进行旋转、缩放、裁剪等操作提升模型性能。
1.4.2 自然语言处理(Natural Language Processing, NLP)
Keras 支持处理文本数据并构建 NLP 模型。
(1)常见应用:
- 文本分类(Text Classification)
- 如垃圾邮件检测、情感分析。
- 机器翻译(Machine Translation)
- 将文本从一种语言翻译成另一种语言。
- 语言生成(Language Generation)
- 生成对话内容或自动写作。
- 情感分析(Sentiment Analysis)
- 判断文本的情感(如正面、负面)。
(2)实例:
- 使用循环神经网络(RNN)、长短期记忆网络(LSTM)处理时间序列数据。
- 使用词嵌入(Word Embedding)方法,如 Word2Vec 或 GloVe,提取文本特征。
1.4.3 时间序列分析与预测(Time Series Analysis and Forecasting)
Keras 可以处理时间序列数据,用于建模和预测。
(1)常见应用:
- 股票价格预测。
- 电力负载预测。
- 传感器数据分析(如工业设备维护预测)。
- 心率信号分析(如医疗中的ECG分析)。
(2)实例:
- 构建基于 LSTM 或 GRU 的时间序列预测模型。
- 结合滑动窗口技术对时间序列数据进行处理。
1.4.4 语音与音频处理(Speech and Audio Processing)
Keras 能处理语音信号和音频数据。
(1)常见应用:
- 语音识别(Speech Recognition)
- 如语音助手(Alexa、Siri)。
- 音乐生成与分类(Music Generation and Classification)
- 根据音频特征分类音乐类型。
- 声音事件检测(Sound Event Detection)
- 如智能家居中检测警报声。
(2)实例:
- 使用卷积神经网络(CNN)提取音频的时频特征。
- 结合 RNN 模型处理语音数据序列。
1.4.5 医疗健康(Healthcare and Biomedicine)
Keras 在医学领域有广泛的应用,如诊断和健康监测。
(1)常见应用:
- 医学影像分析(Medical Image Analysis)
- 如癌症检测(X 光片、CT 扫描分析)。
- 生物信号处理(Biomedical Signal Processing)
- 如心电图(ECG)和脑电图(EEG)分析。
- 疾病预测(Disease Prediction)
- 通过患者数据预测疾病风险。
(2)实例:
- 使用图像分割模型检测肿瘤。
- 用 Keras 处理生物数据(如基因序列分析)。
1.4.6 推荐系统(Recommendation Systems)
Keras 支持构建个性化推荐系统。
(1)常见应用:
- 电商平台推荐(如亚马逊的产品推荐)。
- 视频推荐(如 Netflix 的电影推荐)。
- 音乐推荐(如 Spotify 的歌曲推荐)。
(2)实例:
- 使用嵌入层(Embedding Layer)对用户和物品特征进行建模。
- 利用协同过滤方法提升推荐系统效果。
1.4.7 游戏与强化学习(Gaming and Reinforcement Learning)
Keras 可用于设计游戏 AI 和强化学习算法。
(1)常见应用:
- 游戏 AI
- 训练智能体玩游戏(如 AlphaGo)。
- 自动化任务优化
- 如物流路径优化。
(2)实例:
- 使用 Keras 构建深度 Q 网络(DQN)或策略梯度模型。
1.4.8 生成模型与创意应用
Keras 支持生成对抗网络(GAN)和变分自编码器(VAE)等生成模型,应用于创意设计和艺术领域。
(1)常见应用:
- 图像生成(如人脸生成)。
- 文本生成(如自动写诗)。
- 音乐生成(如 AI 作曲)。
(2)实例:
- 使用 GAN 生成逼真的图像。
- 利用 VAE 生成新型设计草图。
1.4 keras包含哪些数据集?
1.4.1 图像数据集
(1)MNIST (手写数字数据集)
- 简介:包含 10 类手写数字(0-9),灰度图像。
- 用途:图像分类任务中的入门实验。
- 数据量:60,000 张训练图像,10,000 张测试图像。
- 加载方式:
from keras.datasets import mnist (x_train, y_train), (x_test, y_test) = mnist.load_data()
(2)
Fashion-MNIST
- 简介:类似 MNIST,但图像是 Zalando 的时尚商品图片(10 类)。
- 用途:分类任务的入门实验,作为 MNIST 的替代品。
- 数据量:60,000 张训练图像,10,000 张测试图像。
- 加载方式:
from keras.datasets import fashion_mnist (x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
(3)CIFAR-10
- 简介:包含 10 类彩色图像,如飞机、汽车、猫等。
- 用途:小规模图像分类。
- 数据量:50,000 张训练图像,10,000 张测试图像。
- 加载方式:
from keras.datasets import cifar10 (x_train, y_train), (x_test, y_test) = cifar10.load_data()
(4)CIFAR-100
- 简介:类似 CIFAR-10,但包含 100 类图像。
- 用途:小规模多分类任务。
- 数据量:50,000 张训练图像,10,000 张测试图像。
- 加载方式:
from keras.datasets import cifar100 (x_train, y_train), (x_test, y_test) = cifar100.load_data()
(5)IMDB (电影评论数据集)
- 简介:包含 50,000 条影评,每条评论已被标注为正面或负面。
- 用途:文本分类或情感分析。
- 加载方式:
from keras.datasets import imdb (x_train, y_train), (x_test, y_test) = imdb.load_data()
1.4.2 文本数据集
(1)IMDB (电影评论情感分析)
- 简介:50,000 条影评数据,分为正面和负面两类。
- 用途:情感分析、文本分类。
- 加载方式:
from keras.datasets import imdb (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=10000)
(2)Reuters (路透社新闻分类数据集)
- 简介:包含 46 类新闻数据,适合文本分类任务。
- 用途:多分类任务实验。
- 加载方式:
from keras.datasets import reuters (x_train, y_train), (x_test, y_test) = reuters.load_data(num_words=10000)
1.4.3 时间序列和其他数据集
Boston Housing (波士顿房价数据集)
- 简介:包含 13 个特征和房价数据,用于回归任务。
- 用途:回归模型实验。
- 加载方式:
from keras.datasets import boston_housing (x_train, y_train), (x_test, y_test) = boston_housing.load_data()
1.4.4 加载和使用数据
Keras 的数据集加载方式非常简单,所有数据集都分为训练集和测试集两部分。一般步骤如下:
- 导入数据集模块。
- 使用
load_data()
方法加载数据。 - 对数据进行预处理,如归一化、数据增强等。
1.4.5 总结
Keras 提供的数据集涵盖了图像、文本和时间序列任务,适合深度学习模型的快速实验。以下是内置数据集的汇总表:
数据集 | 类型 | 数据量 | 用途 |
MNIST | 图像 | 60,000 / 10,000 | 手写数字分类 |
Fashion-MNIST | 图像 | 60,000 / 10,000 | 时尚商品分类 |
CIFAR-10 | 图像 | 50,000 / 10,000 | 小规模图像分类 |
CIFAR-100 | 图像 | 50,000 / 10,000 | 小规模多分类任务 |
IMDB | 文本 | 50,000 | 情感分析、文本分类 |
Reuters | 文本 | 11,228 | 新闻分类任务 |
Boston Housing | 时间序列 | 506 | 回归任务 |
2.实验
2.1 利用 Dataset 对象处理数据
2.1.1 代码和结果
import tensorflow as tf
import numpy as npdataset = tf.data.Dataset.from_tensor_slices(np.array([1.0, 2.0, 3.0, 4.0, 5.0])
)for element in dataset:print(element)
tf.Tensor(1.0, shape=(), dtype=float64)
tf.Tensor(2.0, shape=(), dtype=float64)
tf.Tensor(3.0, shape=(), dtype=float64)
tf.Tensor(4.0, shape=(), dtype=float64)
tf.Tensor(5.0, shape=(), dtype=float64)
2.1.2 代码与结果分析
这段代码使用了 TensorFlow 和 NumPy 来创建一个数据集,并遍历其中的元素打印出来。
(1)导入库
import tensorflow as tf import numpy as np
tensorflow
:用于处理 TensorFlow 模型和数据。numpy
:用于处理数值计算和数组操作。
(2)创建数据集
dataset = tf.data.Dataset.from_tensor_slices( np.array([1.0, 2.0, 3.0, 4.0, 5.0]) )
np.array([1.0, 2.0, 3.0, 4.0, 5.0])
:创建了一个包含 5 个浮动数字的 NumPy 数组。tf.data.Dataset.from_tensor_slices()
:这个函数将 NumPy 数组转换为 TensorFlow 数据集。数据集中的每个元素就是数组中的一个项。对于这个例子,数据集将包含元素1.0
,2.0
,3.0
,4.0
,5.0
。
(3)遍历数据集
for element in dataset: print(element)
- 这个
for
循环会遍历数据集中的每一个元素。由于数据集是由一个浮动数组创建的,因此每个元素会是一个tf.Tensor
,表示一个浮动值。
(4)输出解释
tf.Tensor(1.0, shape=(), dtype=float64)
tf.Tensor(2.0, shape=(), dtype=float64)
tf.Tensor(3.0, shape=(), dtype=float64)
tf.Tensor(4.0, shape=(), dtype=float64)
tf.Tensor(5.0, shape=(), dtype=float64)
tf.Tensor
:输出是一个 TensorFlow 的张量。张量是 TensorFlow 的基本数据结构。1.0, 2.0, 3.0, ...
:这些是来自 NumPy 数组的实际值。shape=()
:张量的形状是()
(空元组),意味着每个张量是一个标量值,也就是没有维度的单一数字。dtype=float64
:dtype
表示张量的数据类型是float64
,即 64 位浮动数,和 NumPy 的默认浮动数类型一致。
2.2 读取数据
2.2.1 代码与结果
from tensorflow.keras import datasets # 导入经典数据集加载模块
import matplotlib.pyplot as plt# 导入数据
(X_train, y_train), (X_test, y_test) = datasets.mnist.load_data()# 总结加载的数据集
print('训练集: X={0}, y={1}'.format(X_train.shape, y_train.shape))
print('测试集: X={0}, y={1}'.format(X_test.shape, y_test.shape))# 绘制前4个图片
for i in range(4):# 定义子图plt.subplot(2, 2, i + 1)# 绘制像素数据plt.title('label = {}'.format(y_train[i]))plt.imshow(X_train[i], cmap=plt.get_cmap('gray_r'))plt.axis('off')# 显示图片
plt.show()
这段代码使用了 TensorFlow Keras 提供的经典数据集 MNIST
,并利用 Matplotlib 来显示前四张手写数字的图片。以下是对这段代码的详细解释:
2.2.2 代码解析
这段代码展示了如何加载 MNIST 数据集、检查数据形状以及可视化部分样本图片。MNIST 数据集是机器学习和深度学习中一个常用的基准数据集,主要用于图像分类任务。
(1)导入所需库:
from tensorflow.keras import datasets # 导入经典数据集加载模块
import matplotlib.pyplot as plt
tensorflow.keras.datasets
:用于加载 TensorFlow 提供的经典数据集(比如 MNIST、CIFAR-10 等)。matplotlib.pyplot
:用于生成图形和绘制数据。
(2)加载 MNIST 数据集:
# 导入数据
(X_train, y_train), (X_test, y_test) = datasets.mnist.load_data()
datasets.mnist.load_data()
:从 TensorFlow 中加载 MNIST 数据集。这个数据集包含手写数字(0到9)的图片,训练集和测试集分别包括 60,000 和 10,000 张 28x28 的灰度图片。X_train
和X_test
:分别是训练集和测试集的图片数据,形状为(60000, 28, 28)
和(10000, 28, 28)
,表示每张图片的大小为 28x28 像素。y_train
和y_test
:分别是训练集和测试集的标签(即每张图片对应的数字),形状为(60000,)
和(10000,)
。
(3)输出数据集信息:
# 总结加载的数据集
print('训练集: X={0}, y={1}'.format(X_train.shape, y_train.shape))
print('测试集: X={0}, y={1}'.format(X_test.shape, y_test.shape))
这两行代码打印出训练集和测试集的图片数据和标签的形状信息:
X_train.shape
输出(60000, 28, 28)
,表示训练集包含 60,000 张 28x28 的图片。y_train.shape
输出(60000,)
,表示训练集有 60,000 个标签。X_test.shape
输出(10000, 28, 28)
,表示测试集包含 10,000 张 28x28 的图片。y_test.shape
输出(10000,)
,表示测试集有 10,000 个标签。
(4)绘制前 4 张图片:
# 绘制前4个图片
for i in range(4):# 定义子图plt.subplot(2, 2, i + 1)# 绘制像素数据plt.title('label = {}'.format(y_train[i]))plt.imshow(X_train[i], cmap=plt.get_cmap('gray_r'))plt.axis('off')
这段代码用于绘制前四张训练集图片:
plt.subplot(2, 2, i + 1)
:在一个 2x2 的子图中选择当前的位置。2, 2
表示 2 行 2 列的布局,i + 1
表示当前的位置编号(从 1 开始)。plt.title('label = {}'.format(y_train[i]))
:为每个子图添加标题,标题为当前图像的标签(即数字)。plt.imshow(X_train[i], cmap=plt.get_cmap('gray_r'))
:使用imshow
显示图片,X_train[i]
代表第i
张图片,cmap='gray_r'
设置图像的颜色映射为反色的灰度图(即灰度反转)。plt.axis('off')
:关闭坐标轴的显示。
(5)显示图片:
plt.show()
- 这行代码调用
show()
来显示所有的子图。
2.2.3 结果分析
这段代码运行后会显示一个包含 4 张图片的图像窗口,每张图片下方的标题会显示相应的标签(手写数字)。
(1)训练集与测试集形状:
- 训练集包含 60000 张图片,每张图片大小为 28×28 像素。
- 测试集包含 10000 张图片,每张图片大小为 28×28 像素。
(2)样本图片展示: 显示了训练集中前 4 张图片及其对应的标签:
图片展示了手写数字的样式,标签(label
)正确反映了图片的内容。
- 第一张图片:数字 5。
- 第二张图片:数字 0。
- 第三张图片:数字 4。
- 第四张图片:数字 1。
2.3 keras 搭建模型
2.3.1 代码与结果
import numpy as np
import tensorflow as tf
from tensorflow.keras import datasets, Sequential, layers# 导入数据
(X_train, y_train), (X_test, y_test) = datasets.mnist.load_data()# 数据预处理
X_train = tf.convert_to_tensor(X_train, dtype=tf.float32) / 255.0
dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
dataset = dataset.batch(32).repeat(10)# 构建模型
model = Sequential() # 搭建空顺序模型
model.add(layers.Flatten(input_shape=(28, 28))) # 输入层展平
model.add(layers.Dense(10, activation='softmax')) # 输出层,10分类model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
dense (Dense) (None, 10) 7850
=================================================================
Total params: 7,850
Trainable params: 7,850
Non-trainable params: 0
_________________________________________________________________
2.3.2 代码与结果分析
这段代码的目的是使用 TensorFlow 和 Keras 搭建一个简单的神经网络模型,并对 MNIST 数据集进行训练。代码包含了数据加载、预处理、模型构建和准备工作,但没有包含训练过程。我将详细解释每一部分。
(1)导入必要的库
import numpy as np
import tensorflow as tf
from tensorflow.keras import datasets, Sequential, layers
numpy
:用于处理数值计算和数组操作。tensorflow
:用于构建和训练深度学习模型。datasets
:用于加载经典数据集(例如 MNIST)。Sequential
:用于定义一个线性堆叠的模型,层逐层叠加。layers
:Keras 中的层,用于构建神经网络。
(2)加载 MNIST 数据集
(X_train, y_train), (X_test, y_test) = datasets.mnist.load_data()
- 这行代码从 TensorFlow 中加载 MNIST 数据集。MNIST 是一个包含手写数字(0-9)的图像数据集。
X_train
和X_test
是图像数据,形状分别为(60000, 28, 28)
和(10000, 28, 28)
,即 60,000 张训练图像和 10,000 张测试图像,每张图像为 28x28 像素。y_train
和y_test
是图像的标签,分别对应训练集和测试集的数字类别,形状为(60000,)
和(10000,)
。
(3)数据预处理:
# 数据预处理
X_train = tf.convert_to_tensor(X_train, dtype=tf.float32) / 255.0
dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
dataset = dataset.batch(32).repeat(10)
X_train = tf.convert_to_tensor(X_train, dtype=tf.float32) / 255.0
:将训练集的图片数据转换为 TensorFlow 的张量(tf.float32
类型),并将像素值缩放到 [0, 1] 之间。原始图片像素值是从 0 到 255,经过除以 255 后,每个像素值变成 0 到 1 的浮动数。dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
:将训练数据转换为tf.data.Dataset
类型,便于批处理和迭代。每个元素包含一个图像(X_train[i]
)和它的标签(y_train[i]
)。dataset = dataset.batch(32).repeat(10)
:对数据集进行批处理(每个批次包含 32 张图片)并重复 10 次。批处理的目的是加速训练,重复是为了确保每次迭代模型都会训练到所有的数据。
(4)构建神经网络模型:
# 构建模型
model = Sequential() # 搭建空顺序模型
model.add(layers.Flatten(input_shape=(28, 28))) # 输入层展平
model.add(layers.Dense(10, activation='softmax')) # 输出层,10分类model.summary()
model = Sequential()
:创建一个顺序模型,表示网络的层按顺序堆叠。model.add(layers.Flatten(input_shape=(28, 28)))
:添加一个展平层(Flatten),用于将每张 28x28 的图片展平为一个 784(28x28)维的向量。这个层是神经网络的输入层。model.add(layers.Dense(10, activation='softmax'))
:添加一个全连接层(Dense),该层的输出维度为 10,对应数字类别 0 到 9。使用softmax
激活函数,因为这是一个多分类问题,softmax
可以将输出值转化为 10 类的概率分布。- model.summary():打印模型
2.3.3 模型解释
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
dense (Dense) (None, 10) 7850
=================================================================
Total params: 7,850
Trainable params: 7,850
Non-trainable params: 0
_________________________________________________________________
(1)Flatten Layer
- Layer (type):
flatten (Flatten)
- Output Shape:
(None, 784)
None
表示批量大小(batch size),可以是任意值,784 是输入的维度,即 28x28 的图片被展平后的大小(784 个像素)。
- Param #: 0
- 这一层没有需要训练的参数。它只是将 28x28 的图像展平为一个一维向量。
(2)Dense Layer
- Layer (type):
dense (Dense)
- Output Shape:
(None, 10)
None
仍然表示批量大小,10 表示输出有 10 个神经元,对应 10 类分类问题(MNIST 手写数字分类,数字从 0 到 9)。
- Param #: 7850
- 这个参数是权重和偏置的数量。784 个输入特征与 10 个输出神经元的每一对都连接,有 7840 个权重参数。再加上 10 个偏置项,总共 7850 个参数。
(3)Total params, Trainable params, Non-trainable params
- Total params: 7850
- 这是模型的总参数数量,包括所有层的权重和偏置。
- Trainable params: 7850
- 这些参数是可以训练的,即模型在训练过程中会根据损失函数的梯度更新这些权重。
- Non-trainable params: 0
- 没有非训练参数,所有参数都可以训练。
(4)模型结构总结
你的模型包含两层:
- Flatten 层:将输入的 28x28 图片展平为 784 个数值。
- Dense 层:一个全连接层,输出 10 个神经元,代表 10 个分类的概率分布(通过 softmax 激活函数)。
总的来说,模型结构比较简单,适用于基础的图像分类任务,如 MNIST 数据集的手写数字识别。
2.4 构建梯度递减模型
2.4.1 代码与结果
import numpy as np
import tensorflow as tf
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics# 导入数据
(X_train, y_train), (X_test, y_test) = datasets.mnist.load_data()# 数据预处理
X_train = tf.convert_to_tensor(X_train, dtype=tf.float32) / 255.0
dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
dataset = dataset.batch(32).repeat(10)# 获取图片的大小
in_shape = X_train.shape[1:] # 形状为 (28, 28)
# 获取类别数目
n_classes = len(np.unique(y_train)) # 类别数为10# 构建模型
model = Sequential() # 搭建空顺序模型
model.add(layers.Flatten(input_shape=in_shape)) # 展平层
model.add(layers.Dense(n_classes, activation='softmax')) # 输出层# 定义优化器,学习率为0.01
optimizer = optimizers.SGD(learning_rate=0.01)# 定义累积准确率的指标
acc_meter = metrics.Accuracy()# 开始训练
for step, (x, y) in enumerate(dataset):with tf.GradientTape() as tape:# 计算模型输出out = model(x)# 将标签转为 one-hot 编码y_onehot = tf.one_hot(y, depth=10)# 计算损失loss = tf.square(out - y_onehot)loss = tf.reduce_sum(loss) / 32# 更新准确率acc_meter.update_state(tf.argmax(out, axis=1), y)# 计算梯度并优化grads = tape.gradient(loss, model.trainable_variables)optimizer.apply_gradients(zip(grads, model.trainable_variables))# 每200步打印一次日志if step % 200 == 0:print('step {0}, loss: {1:.3f}, acc: {2:.2f} %'.format(step, float(loss), acc_meter.result().numpy() * 100))acc_meter.reset_states()
model.summary()
step 0, loss: 0.946, acc: 3.12 %
step 200, loss: 0.814, acc: 27.14 %
step 400, loss: 0.724, acc: 47.03 %
step 600, loss: 0.534, acc: 56.72 %
step 800, loss: 0.438, acc: 68.31 %
step 1000, loss: 0.448, acc: 73.23 %
step 1200, loss: 0.359, acc: 78.52 %
step 1400, loss: 0.378, acc: 79.81 %
step 1600, loss: 0.291, acc: 81.39 %
step 1800, loss: 0.249, acc: 84.28 %
......
step 16800, loss: 0.143, acc: 90.75 %
step 17000, loss: 0.161, acc: 92.09 %
step 17200, loss: 0.079, acc: 90.75 %
step 17400, loss: 0.147, acc: 89.89 %
step 17600, loss: 0.153, acc: 90.94 %
step 17800, loss: 0.053, acc: 90.64 %
step 18000, loss: 0.248, acc: 89.52 %
step 18200, loss: 0.179, acc: 89.98 %
step 18400, loss: 0.124, acc: 90.48 %
step 18600, loss: 0.078, acc: 89.67 %
2.4.2 代码分析
这段代码是使用 TensorFlow 和 Keras 自定义训练循环来训练一个简单的神经网络模型,处理 MNIST 数据集。代码中的核心部分包括数据加载与预处理、模型构建、优化器设置、损失函数计算和准确率计算,以及训练过程。下面是对每一部分的详细解释。
(1)导入所需库
import numpy as np
import tensorflow as tf
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics
numpy
:用于处理数组和数值计算。tensorflow
:用于构建和训练深度学习模型。datasets
:加载经典数据集(如 MNIST)。layers
:用于构建神经网络的不同层。optimizers
:提供优化器,调整模型参数。Sequential
:构建顺序模型(层按顺序堆叠)。metrics
:提供不同的评估指标。
(2)加载 MNIST 数据集
(X_train, y_train), (X_test, y_test) = datasets.mnist.load_data()
X_train
和X_test
:图片数据,形状分别为(60000, 28, 28)
和(10000, 28, 28)
,表示 28x28 的灰度图。y_train
和y_test
:对应的标签,形状为(60000,)
和(10000,)
,表示每张图片的数字标签。
(3)数据预处理
# 数据预处理
X_train = tf.convert_to_tensor(X_train, dtype=tf.float32) / 255.0
dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
dataset = dataset.batch(32).repeat(10)
tf.convert_to_tensor(X_train, dtype=tf.float32) / 255.0
:将图片数据转换为 TensorFlow 张量并将像素值缩放到 [0, 1] 范围。dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
:将训练数据转换为tf.data.Dataset
格式,便于批量处理。dataset = dataset.batch(32).repeat(10)
:每次训练使用 32 张图片为一个批次,并且重复整个数据集 10 次(即训练 10 个 Epoch)。
(4)获取图片的形状和类别数目
# 获取图片的大小
in_shape = X_train.shape[1:] # 形状为 (28, 28)
# 获取类别数目
n_classes = len(np.unique(y_train)) # 类别数为10
in_shape = X_train.shape[1:]
:获取输入数据的形状,即每张图片的大小(28, 28)
。n_classes = len(np.unique(y_train))
:获取类别的数量,MNIST 数据集有 10 类(0到9)。
(5)构建模型
model = Sequential() # 搭建空顺序模型
model.add(layers.Flatten(input_shape=in_shape)) # 展平层
model.add(layers.Dense(n_classes, activation='softmax')) # 输出层
Sequential()
:创建一个顺序模型,表示层按顺序堆叠。layers.Flatten(input_shape=in_shape)
:添加一个展平层,将每张 28x28 的图片展平为一个 784 维的向量,作为全连接层的输入。layers.Dense(n_classes, activation='softmax')
:添加一个全连接层,输出 10 个单元(分别表示 10 类数字)。使用softmax
激活函数将输出转化为概率分布。
(6)定义优化器和指标
# 定义优化器,学习率为0.01
optimizer = optimizers.SGD(learning_rate=0.01)# 定义累积准确率的指标
acc_meter = metrics.Accuracy()
optimizers.SGD(learning_rate=0.01)
:使用随机梯度下降(SGD)优化器,学习率为 0.01。metrics.Accuracy()
:定义累积准确率的指标,用于计算模型在每个批次上的准确度。
(7)开始训练
# 开始训练
for step, (x, y) in enumerate(dataset):with tf.GradientTape() as tape:# 计算模型输出out = model(x)# 将标签转为 one-hot 编码y_onehot = tf.one_hot(y, depth=10)# 计算损失loss = tf.square(out - y_onehot)loss = tf.reduce_sum(loss) / 32
for step, (x, y) in enumerate(dataset)
:遍历训练数据集,x
是当前批次的输入(图片),y
是标签(数字类别)。with tf.GradientTape() as tape
:创建一个计算梯度的上下文环境。TensorFlow 计算图是在这个上下文中构建的。out = model(x)
:将输入数据传入模型,计算模型的输出。y_onehot = tf.one_hot(y, depth=10)
:将标签y
转换为 one-hot 编码,depth=10
表示类别数为 10。loss = tf.square(out - y_onehot)
:计算每个样本的损失(平方误差)。注意:这不是常见的分类损失函数(如交叉熵),但作为示例也能工作。loss = tf.reduce_sum(loss) / 32
:对整个批次的损失进行求和并计算平均值。
(8)计算准确率并优化
# 更新准确率acc_meter.update_state(tf.argmax(out, axis=1), y)# 计算梯度并优化grads = tape.gradient(loss, model.trainable_variables)optimizer.apply_gradients(zip(grads, model.trainable_variables))
acc_meter.update_state(tf.argmax(out, axis=1), y)
:更新准确率指标,tf.argmax(out, axis=1)
得到模型输出的最大概率索引(即预测类别),y
是实际标签。grads = tape.gradient(loss, model.trainable_variables)
:计算模型参数的梯度。optimizer.apply_gradients(zip(grads, model.trainable_variables))
:使用优化器应用梯度更新模型参数。
(9)日志输出
# 每200步打印一次日志if step % 200 == 0:print('step {0}, loss: {1:.3f}, acc: {2:.2f} %'.format(step, float(loss), acc_meter.result().numpy() * 100))acc_meter.reset_states()
- 每经过 200 步打印一次日志,输出当前的损失和准确率。
acc_meter.reset_states()
:每次输出后重置准确率计算器的状态,以便进行下一批次的计算。
2.4.3 结果分析
step 0, loss: 0.946, acc: 3.12 %
step 200, loss: 0.814, acc: 27.14 %
step 400, loss: 0.724, acc: 47.03 %
step 600, loss: 0.534, acc: 56.72 %
step 800, loss: 0.438, acc: 68.31 %
step 1000, loss: 0.448, acc: 73.23 %
step 1200, loss: 0.359, acc: 78.52 %
step 1400, loss: 0.378, acc: 79.81 %
step 1600, loss: 0.291, acc: 81.39 %
step 1800, loss: 0.249, acc: 84.28 %
......
step 16800, loss: 0.143, acc: 90.75 %
step 17000, loss: 0.161, acc: 92.09 %
step 17200, loss: 0.079, acc: 90.75 %
step 17400, loss: 0.147, acc: 89.89 %
step 17600, loss: 0.153, acc: 90.94 %
step 17800, loss: 0.053, acc: 90.64 %
step 18000, loss: 0.248, acc: 89.52 %
step 18200, loss: 0.179, acc: 89.98 %
step 18400, loss: 0.124, acc: 90.48 %
step 18600, loss: 0.078, acc: 89.67 %
(1)训练过程概览
初期训练(前几百步):
在训练的前几百步中,模型的损失值逐步减少,从约 0.946
降到 0.724
,而准确率从 3.12%
提升到 47.03%
。这个阶段表明模型正在从随机初始化的状态逐步学习训练数据。
中期训练(1000 步到 16000 步):
随着训练的推进,损失值继续下降,准确率持续增长。比如在第 1600
步时,模型的损失降到 0.291
,而准确率达到了 81.39%
。这个阶段通常是模型学习到一些有用的特征的阶段,开始表现出比较好的性能。
后期训练(17000 步以后):
在训练的后期,尽管损失继续下降(例如,第 16800
步时损失降到 0.143
),但是准确率的提升变得缓慢,达到了 90%
左右。这通常是训练过程中常见的现象:模型接近于饱和,进一步提高准确率变得更加困难。
(2)损失和准确率的波动
在某些步骤中(如第 17200
步),损失虽然有所回升(从 0.079
增加到 0.147
),但准确率并没有大幅下降,仍保持在较高水平。这表明模型在训练过程中的表现相对稳定,尽管偶尔会出现小的波动。
例如在 18000
步,损失突然增大到 0.248
,但准确率仍保持在 89.52%
,表明模型可能在某些批次的训练中遇到了一些不平衡或异常情况,但整体性能依然维持在一个不错的水平。
(3)评估
最终性能:在第 18600
步时,损失值为 0.078
,准确率为 89.67%
,说明模型已经学到了相当有用的特征,但仍有一些提升空间。
(4)总结
模型的准确率从 3.12%
开始,在训练过程中逐渐提高,最终稳定在接近 90%
的水平。随着训练的继续,准确率提高的幅度变得越来越小,表明模型逐渐收敛。
损失值在初期阶段快速下降,在后期逐步趋于平稳,表明模型逐渐拟合数据并减少误差。
(5)可能的改进
进一步优化学习率:如果你希望进一步提高模型性能,可能需要调节学习率(比如使用学习率衰减,或尝试更高效的优化器)。
更多的训练时间或数据:虽然模型已经达到 90%
准确率,但如果希望模型进一步提高,可以尝试增加训练的轮数,或者使用更多的数据进行训练,避免过拟合。
2.5 线性回归
2.5.1 代码与结果
import numpy as np
from tensorflow.keras.datasets import mnist
import tensorflow as tf
from tensorflow import keras# 定义预处理函数
def preprocess(x, y):# 标准化像素值到 [0, 1]x = tf.cast(x, dtype=tf.float32) / 255.0x = tf.reshape(x, [-1, 28, 28]) # 调整形状y = tf.cast(y, dtype=tf.int32) # 转换标签为整数y = tf.one_hot(y, depth=10) # 转为 one-hot 编码# 返回预处理后的 x 和 yreturn x, y# 加载数据
(X_train, y_train), (X_test, y_test) = mnist.load_data()# 获取图片的大小
in_shape = X_train.shape[1:] # 形状为 (28, 28)
# 获取类别的个数
n_classes = len(np.unique(y_train)) # 类别数为10# 数据预处理
X_train = X_train.astype('float32') / 255.0
X_test = X_test.astype('float32') / 255.0# 构建模型
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=in_shape)) # 展平层
model.add(keras.layers.Dense(n_classes, activation='softmax')) # 输出层# 编译模型:定义优化器、损失函数和评价指标
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy']
)model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten_3 (Flatten) (None, 784) 0
dense_3 (Dense) (None, 10) 7850
=================================================================
Total params: 7,850
Trainable params: 7,850
Non-trainable params: 0
_________________________________________________________________
2.5.2 代码与结果分析
这段代码是一个完整的 MNIST 手写数字分类任务,包括数据预处理、模型构建和模型编译。接下来我会逐步解释代码的各个部分,并在最后加入模型的打印输出。
(1) 导入必要的库
import numpy as np
from tensorflow.keras.datasets import mnist
import tensorflow as tf
from tensorflow import keras
numpy
:用于进行数组操作和数值计算。mnist
:Keras 提供的一个经典手写数字数据集加载接口。tensorflow
和keras
:TensorFlow 是一个开源机器学习框架,Keras 是 TensorFlow 中高层 API,用于简化深度学习模型的构建和训练。
(2)定义预处理函数
def preprocess(x, y):# 标准化像素值到 [0, 1]x = tf.cast(x, dtype=tf.float32) / 255.0x = tf.reshape(x, [-1, 28, 28]) # 调整形状y = tf.cast(y, dtype=tf.int32) # 转换标签为整数y = tf.one_hot(y, depth=10) # 转为 one-hot 编码# 返回预处理后的 x 和 yreturn x, y
这段代码定义了一个预处理函数 preprocess(x, y)
,用于对数据进行以下处理:
- 标准化:将图片的像素值转换为 [0, 1] 范围,便于模型训练。
x = tf.cast(x, dtype=tf.float32) / 255.0
将图片像素值从 [0, 255] 转换到 [0, 1]。 - 形状调整:
x = tf.reshape(x, [-1, 28, 28])
将输入数据的形状调整为(batch_size, 28, 28)
,每张图片的大小是 28x28 像素。 - 标签转换:将标签
y
转换为整数类型,并通过tf.one_hot(y, depth=10)
将其转化为 one-hot 编码。MNIST 数据集有 10 类(数字 0-9)。
注意:preprocess
函数在这个代码中并没有被直接调用。
(3)加载数据
(X_train, y_train), (X_test, y_test) = mnist.load_data()
mnist.load_data()
:加载 MNIST 数据集,返回训练集(X_train, y_train)
和测试集(X_test, y_test)
。X_train
和X_test
:分别是训练和测试数据的图像数据,形状为(60000, 28, 28)
和(10000, 28, 28)
,即 28x28 像素的灰度图。y_train
和y_test
:分别是训练和测试数据的标签,形状为(60000,)
和(10000,)
,每个标签是数字 0-9 之间的整数,表示该图像所属的类别。
(4)获取图片的形状和类别数
# 获取图片的大小
in_shape = X_train.shape[1:] # 形状为 (28, 28)
# 获取类别的个数
n_classes = len(np.unique(y_train)) # 类别数为10
in_shape = X_train.shape[1:]
:获取输入数据的形状,即每张图片的大小(28, 28)
。n_classes = len(np.unique(y_train))
:计算数据集中的类别数,这里是 10 类(0 到 9)。
(5)数据预处理
X_train = X_train.astype('float32') / 255.0
X_test = X_test.astype('float32') / 255.0
将 X_train
和 X_test
转换为 float32
类型,并标准化每个像素值到 [0, 1] 范围,便于神经网络模型训练。
(6)构建神经网络模型
# 构建模型
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=in_shape)) # 展平层
model.add(keras.layers.Dense(n_classes, activation='softmax')) # 输出层
model = keras.Sequential()
:创建一个空的顺序模型Sequential
,表示模型层按顺序堆叠。model.add(keras.layers.Flatten(input_shape=in_shape))
:添加一个展平层。这个层将每张 28x28 的图片展平为一个 784 维的向量,作为全连接层的输入。model.add(keras.layers.Dense(n_classes, activation='softmax'))
:添加一个全连接层(Dense
)。该层的输出单元数为n_classes
(即 10 类),并使用softmax
激活函数。softmax
激活函数将输出转换为概率分布,表示每个类别的概率。
(7)编译模型
# 编译模型:定义优化器、损失函数和评价指标
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy']
)
optimizer='adam'
:使用 Adam 优化器。Adam 是一种常用的优化算法,适用于大多数深度学习任务。loss='sparse_categorical_crossentropy'
:使用sparse_categorical_crossentropy
作为损失函数,这是多类分类问题常用的损失函数。sparse_categorical_crossentropy
适用于标签是整数编码(如 0-9)的情况。metrics=['accuracy']
:使用准确率(accuracy)作为评估指标。
(9)总结
这段代码使用 Keras 构建了一个简单的多层感知机(MLP)模型用于处理 MNIST 手写数字分类任务。模型结构非常简单:
- 输入层展平图片,
- 输出层有 10 个神经元,使用
softmax
激活函数进行分类。
通过 model.compile
配置了优化器(Adam)、损失函数(sparse_categorical_crossentropy
)和评估指标(准确率)。通过 model.summary()
打印模型的结构和参数信息。
2.6 训练与预测
2.6.1 代码与结果
# 模型拟合
model.fit(X_train, y_train, epochs=10, batch_size=128, verbose=0)# 评估模型
loss, acc = model.evaluate(X_test, y_test, verbose=0)
print('测试集的预测准确率: {0:.3f}'.format(acc))# 单个图片预测
image = X_train[100] # 选择第101张图片做测试
import tensorflow as tf
image = tf.expand_dims(image, axis=0) # 扩展维度yhat = model.predict([image]) # 预测
print('预测的数字为: {0}'.format(np.argmax(yhat)))# 绘制像素数据
import matplotlib.pyplot as plt
plt.title('label = {}'.format(y_train[100]))
plt.imshow(X_train[100], cmap=plt.get_cmap('gray')) # 灰度显示
# plt.axis('off') # 关闭坐标轴# 显示图片
plt.show()
2.6.2 代码与结果分析
这段代码主要用于训练模型、评估性能、进行单个图片预测以及展示预测结果和图片。以下是逐步解释:
(1)模型训练(模型拟合)
# 模型拟合
model.fit(X_train, y_train, epochs=10, batch_size=128, verbose=0)
model.fit()
:用于训练模型,X_train
和y_train
是训练数据和标签。epochs=10
:设置训练的轮数(即模型会遍历训练数据 10 次)。batch_size=128
:每次训练使用 128 张图片作为一批次来更新模型的参数。较小的批量可能会导致训练时间较长,但通常能够获得更好的性能。verbose=0
:设置训练时不输出日志。如果设置为 1 或 2,Keras 会打印训练过程中的信息。
这行代码执行完后,模型会通过 10 轮训练来学习 MNIST 数据集中的图像和标签的关系。
(2)模型评估
# 评估模型
loss, acc = model.evaluate(X_test, y_test, verbose=0)
print('测试集的预测准确率: {0:.3f}'.format(acc))
model.evaluate(X_test, y_test, verbose=0)
:评估模型在测试集上的表现。X_test
和y_test
是测试数据和标签。返回值loss
是测试集上的损失值,acc
是测试集上的准确率。verbose=0
:设置评估时不输出日志。print('测试集的预测准确率: {0:.3f}'.format(acc))
:输出模型在测试集上的预测准确率。{0:.3f}
将准确率格式化为小数点后三位。
(3)单个图片预测
# 单个图片预测
image = X_train[100] # 选择第101张图片做测试
import tensorflow as tf
image = tf.expand_dims(image, axis=0) # 扩展维度yhat = model.predict([image]) # 预测
print('预测的数字为: {0}'.format(np.argmax(yhat)))
image = X_train[100]
:选择X_train
中的第 101 张图片(X_train[100]
是第 100 索引处的图片)。image = tf.expand_dims(image, axis=0)
:由于模型需要输入的是一个批量(即一个 4D 张量),而我们只选择了一个图片,所以需要将图片的维度从(28, 28)
扩展为(1, 28, 28)
,表示一个包含单张图片的批量。expand_dims()
函数用来在指定的轴上扩展维度,axis=0
表示在最前面添加一个维度。yhat = model.predict([image])
:使用训练好的模型对这张图片进行预测,返回的是一个包含每个类别概率的数组。np.argmax(yhat)
:返回yhat
数组中最大值的索引,即预测的类别。argmax()
函数返回最大值的索引,在这里即为预测的数字。print('预测的数字为: {0}'.format(np.argmax(yhat)))
这行代码会输出预测结果,即模型预测出的数字类别。
(4)绘制图片
# 绘制像素数据
import matplotlib.pyplot as plt
plt.title('label = {}'.format(y_train[100]))
plt.imshow(X_train[100], cmap=plt.get_cmap('gray')) # 灰度显示
# plt.axis('off') # 关闭坐标轴# 显示图片
plt.show()
plt.title('label = {}'.format(y_train[100]))
:设置图片的标题,显示真实标签。这里显示的是y_train[100]
的值,即第 101 张图片的真实标签。plt.imshow(X_train[100], cmap=plt.get_cmap('gray'))
:绘制这张图片,并使用灰度色彩映射(gray
)。X_train[100]
是第 101 张图片。plt.show()
:显示这张图片。
(5)预测和可视化
测试集准确率
- 测试集的预测准确率:
92.8%
。
这表示模型在未见过的数据(即测试集)上的表现非常好,说明模型不仅在训练集上拟合良好,而且具有较强的泛化能力。准确率高于90%
通常是一个非常好的结果,尤其是在像 MNIST 这种经典数据集上。
单个样本预测
- 预测的数字为:
5
。
对于选择的测试样本(第101张图片),模型正确预测出数字为5
。
2.7 保存模型
2.7.1 代码与结果
# 将模型结构序列化为JSON格式
model_json = model.to_json()
with open("model.json", "w") as json_file:json_file.write(model_json)# 将模型权值序列化为HDF5格式
model.save_weights("model.h5")
print("成功:将模型保存本地!")
2.7.2 代码与结果分析
这段代码展示了如何将训练好的模型保存到本地,具体包括两部分:模型结构和模型权重。下面是这两部分的详细解释:
(1)保存模型结构为JSON格式
# 将模型结构序列化为JSON格式
model_json = model.to_json()
with open("model.json", "w") as json_file:json_file.write(model_json)
model.to_json()
:将 Keras 模型的结构(即网络架构)转化为一个 JSON 格式的字符串。这个 JSON 字符串保存了模型的层次、每一层的类型、每一层的配置等信息,但不包含模型的权重(即学习到的参数)。open("model.json", "w")
:以写模式打开名为model.json
的文件。如果该文件不存在,Python 会自动创建一个新文件。json_file.write(model_json)
:将 JSON 格式的模型结构写入到文件中。这样,你就可以将模型结构保存到本地文件中,以便在将来加载。
(2)保存模型权重为HDF5格式
# 将模型权值序列化为HDF5格式
model.save_weights("model.h5")
print("成功:将模型保存本地!")
model.save_weights("model.h5")
:将模型的权重保存到文件中,这里保存的格式是 HDF5(.h5
)。HDF5 是一种用于存储大量数据的格式,它可以高效地存储模型的所有训练参数(即每一层的权重、偏置等)。- print:在保存操作完成后,程序会输出这条消息,表示模型已经成功保存到本地文件中。
2.8 反序列化模型
2.8.1 代码与结果
# 读取模型文件
json_file = open('model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()# 反序列化:导入模型结构
from tensorflow.keras.models import model_from_json
loaded_model = model_from_json(loaded_model_json)# 反序列化:将权值导入到加载的模型中
loaded_model.load_weights("model.h5")
print("成功:从本地文件中导入权值参数!")# 编译导入的模型
loaded_model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy']
)# 测试模型是否可用
loss, acc = loaded_model.evaluate(X_test, y_test, verbose=0)
print('测试集合的预测准确率: {0:.2f} %'.format(acc * 100))
成功:从本地文件中导入权值参数!
测试集合的预测准确率: 92.80 %
2.8.2 代码与结果分析
这段代码的目的是加载之前保存的模型结构(model.json
文件)和模型权重(model.h5
文件),然后对加载后的模型进行编译,并在测试集上进行评估。下面是对每一部分代码的解释:
(1)读取并加载模型结构
# 读取模型文件
json_file = open('model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
- 这段代码打开
model.json
文件并读取其内容。文件中包含了模型的结构(每一层的配置)。 - 通过
json_file.read()
方法将文件内容存储在变量loaded_model_json
中。
(2)反序列化:导入模型结构
# 反序列化:导入模型结构
from tensorflow.keras.models import model_from_json
loaded_model = model_from_json(loaded_model_json)
- 使用
model_from_json()
方法反序列化加载 JSON 格式的模型结构。 - 这个方法返回一个
Sequential
模型对象,loaded_model
现在包含了从 JSON 文件中恢复的模型结构。
(3)反序列化:加载模型权重
# 反序列化:将权值导入到加载的模型中
loaded_model.load_weights("model.h5")
print("成功:从本地文件中导入权值参数!")
- 使用
load_weights()
方法将保存的权重文件model.h5
加载到模型中。 - 这将把模型的权重应用到加载的
loaded_model
中,使其拥有和原来相同的权重参数。 - 打印成功的消息,确认权重已经正确加载。
(4)编译模型
# 编译导入的模型
loaded_model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy']
)
- 在加载了结构和权重后,需要编译模型才能进行训练或评估。
optimizer='adam'
表示使用 Adam 优化器,loss='sparse_categorical_crossentropy'
表示使用稀疏的分类交叉熵作为损失函数,metrics=['accuracy']
表示在训练和评估时监控准确率。
(5)评估模型
# 测试模型是否可用
loss, acc = loaded_model.evaluate(X_test, y_test, verbose=0)
print('测试集合的预测准确率: {0:.2f} %'.format(acc * 100))
- 使用
evaluate()
方法评估加载后的模型在测试集上的表现。 X_test
和y_test
分别是测试集的输入和标签数据。verbose=0
表示不显示详细的训练过程日志。evaluate()
方法返回模型的损失值和准确率。- 最后打印出测试集上的预测准确率。