tensorflow案例1--天气识别,包含(Tensorflow的检查是否GPU、图像数据加载与划分、拿取动态加载的数据、内存优化、神经网络构建、模型超参数设计、模型训练)API讲解

前言

  • 这个案例比较简单,无论是学习tensorflow还是学习神经网络,都是一个很好的案例;
  • 这个案例主要用处是学习tensorflow的API,包含:检查是否GPU、图像数据加载与划分、拿取动态加载的数据、内存优化、神经网络构建、模型超参数设计、模型训练
  • 欢迎收藏 + 关注,本人将持续更新​💌​​💌​​💌​​💌​​💌​​💌​。

1、tensorflow一些API讲解

查阅方法: 阿里巴巴通义千文;up主:K同学啊。

📘 判断是否支持gpu

# 查看是否支持gpu
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")

📖 图像数据加载与分类

用于从目录中加载图像数据并自动进行分类。这个函数可以直接生成一个 tf.data.Dataset 对象,非常适合用于训练深度学习模型。

tf.keras.preprocessing.image_dataset_from_directory(
    directory,
    labels="inferred",
    label_mode="int",
    class_names=None,
    color_mode="rgb",
    batch_size=32,
    image_size=(256, 256),
    shuffle=True,
    seed=None,
    validation_split=None,
    subset=None,
    interpolation="bilinear",
    follow_links=False,
)

👁‍🗨参数说明:

  • directory: 图像文件所在的根目录路径。
  • labels: 标签的来源,默认为 "inferred",表示从目录结构中推断标签。其他选项包括 "inferred"None
  • label_mode: 标签的类型,默认为 "int",表示整数标签。其他选项包括 "categorical"(one-hot 编码)和 "binary"(二进制标签)。
  • class_names: 类别名称列表。如果为 None,则从目录结构中推断类别名称。
  • color_mode: 图像的颜色模式,默认为 "rgb"。其他选项包括 "grayscale""rgba"
  • batch_size: 每个批次的图像数量,默认为 32。
  • image_size: 图像的尺寸,默认为 (256, 256)
  • shuffle: 是否在加载数据时打乱图像,默认为 True
  • seed: 随机种子,用于打乱数据和拆分验证集,确保可重复性。
  • validation_split: 验证集的比例,范围在 0 到 1 之间。如果为 None,则不拆分验证集。
  • subset: 指定要加载的数据子集,选项包括 "training""validation"。只有在 validation_split 不为 None 时才有效。
  • interpolation: 图像缩放时使用的插值方法,默认为 "bilinear"。其他选项包括 "nearest""bicubic" 等。
  • follow_links: 是否跟随符号链接,默认为 False

👼 案例(划分训练集和验证集):

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    directory = './data/',
    validation_split = 0.2,
    batch_size = 32,
    seed = 42,
    image_size = (224, 224),
    subset = 'training',
    shuffle = True
)

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    directory = './data/',
    validation_split = 0.2,
    batch_size = 32,
    seed = 42,
    image_size = (224, 224),
    subset = 'validation',
    shuffle = True
)

🎉 拿取动态加载数据的批次:
API:train_ds.take(1),返回值:

  • images,图片数据
  • labels,分类标签,0,1,2……

📖 优化内存

  • shuffle():打乱数据,关于此函数的详细介绍可以参考:https://zhuanlan.zhihu.com/p/42417456

  • prefetch():预取数据,加速运行,prefetch()功能详细介绍:CPU 正在准备数据时,加速器处于空闲状态。相反,当加速器正在训练模型时,CPU 处于空闲状态。因此,训练所用的时间是 CPU 预处理时间和加速器训练时间的总和。prefetch()将训练步骤的预处理和模型执行过程重叠到一起。当加速器正在执行第 N 个训练步时,CPU 正在准备第 N+1 步的数据。这样做不仅可以最大限度地缩短训练的单步用时(而不是总用时),而且可以缩短提取和转换数据所需的时间。如果不使用prefetch(),CPU 和 GPU/TPU 在大部分时间都处于空闲状态:
    在这里插入图片描述

  • cache():将数据集缓存到内存当中,加速运行

from tensorflow.data.experimental import AUTOTUNE

AUTOTUNE = tf.data.experimental.AUTOTUNE

# buffer_size:缓冲区大小
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
vals_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

📳 模型构建

API:models.Sequential容器,在 TensorFlow 中,用tf.keras.layers 模块提构建神经网络所需的各种层。这些层可以用来构建不同类型的神经网络模型,如卷积神经网络(CNN)、循环神经网络(RNN)等。下面是一些常用的层类型及其简要说明:

基础层

  • Dense:全连接层,用于构建标准的前馈神经网络。
    • 参数:units(输出维度),activation(激活函数),use_bias(是否使用偏置项)等。
  • Activation:独立的激活层,可以应用于任何其他层的输出。
    • 参数:activation(激活函数名或函数对象)。
  • Dropout:用于防止过拟合,通过随机丢弃一部分神经元来实现。
    • 参数:rate(丢弃率,即每个神经元被丢弃的概率)。
  • Flatten:将多维输入展平成一维向量,常用于连接卷积层和全连接层之间。
    • 参数:无。

卷积层

  • Conv1DConv2DConv3D:一维、二维、三维卷积层,分别适用于时间序列数据、图像数据和视频数据。
    • 参数:filters(滤波器数量),kernel_size(卷积核大小),strides(步长),padding(填充方式),activation(激活函数)等。
  • SeparableConv1DSeparableConv2D:深度可分离卷积层,用于减少计算量和参数数量。
    • 参数与普通卷积层类似。
  • DepthwiseConv2D:深度卷积层,用于处理通道之间的信息。
    • 参数:kernel_sizestridespadding等。

池化层

  • MaxPooling1DMaxPooling2DMaxPooling3D:最大池化层,用于降低数据的空间尺寸。
    • 参数:pool_size(池化窗口大小),stridespadding等。
  • AveragePooling1DAveragePooling2DAveragePooling3D:平均池化层,作用类似于最大池化层,但采用的是平均值而不是最大值。
    • 参数与最大池化层相同。

循环层

  • SimpleRNN:简单的循环神经网络层。
    • 参数:units(输出维度),activationuse_bias等。
  • LSTM:长短期记忆网络层,是一种特殊的 RNN 层,能够学习长期依赖关系。
    • 参数与 SimpleRNN 相似。
  • GRU:门控循环单元层,是 LSTM 的简化版本。
    • 参数与 SimpleRNN 和 LSTM 相似。

正则化层

  • BatchNormalization:批量归一化层,用于加速训练过程并减少内部协变量转移。
    • 参数:axis(指定要进行归一化的轴),momentum(移动平均的动量),epsilon(防止除零的小值)等。

输入层

  • InputLayer:显式定义模型的输入层。
    • 参数:input_shape(输入张量的形状),batch_size(批处理大小)等。

注意力机制相关层

  • Attention:注意力机制层,用于在模型中引入注意力机制。
    • 参数:use_scale(是否使用缩放因子),causal(是否为因果注意力)等。

当然,这些只是 tf.keras.layers 模块提供的一部分层。


超参数设置

API:model.compile

model.compile(
    optimizer='adam',  # 优化器
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),  # 损失函数
    metrics=['accuracy']  # 准确率
)
  1. optimizer
    • 作用:指定优化算法,用于更新模型的权重以最小化损失函数。
    • 常见选项
      • 'adam':自适应矩估计(Adam)优化器,通常是一个不错的选择。
      • 'sgd':随机梯度下降(SGD)优化器。
      • 'rmsprop':均方根传播(RMSprop)优化器。
      • 'adagrad':Adagrad 优化器。
      • 你也可以使用自定义的优化器,例如 tf.keras.optimizers.Adam(learning_rate=0.001)
  2. loss
    • 作用:指定损失函数,用于衡量模型预测值与真实值之间的差距。
    • 常见选项
      • tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False):用于多分类任务,当标签是整数时使用。
      • tf.keras.losses.CategoricalCrossentropy(from_logits=False):用于多分类任务,当标签是 one-hot 编码时使用。
      • tf.keras.losses.BinaryCrossentropy(from_logits=False):用于二分类任务。
      • tf.keras.losses.MeanSquaredError():用于回归任务。
  3. metrics
    • 作用:指定评估模型性能的指标。
    • 常见选项
      • 'accuracy':分类任务中常用的准确率。
      • 'mse':均方误差,用于回归任务。
      • 'mae':平均绝对误差,用于回归任务。
      • 你也可以使用自定义的评估指标,例如 tf.keras.metrics.AUC()

🤞 模型训练

API:model.fit

history = model.fit(
    x=train_ds,  # 训练数据
    validation_data=val_ds,  # 验证数据
    epochs=10,  # 训练轮数
    batch_size=32,  # 批次大小(如果数据集已经是批处理形式,可以省略)
    verbose=1,  # 日志显示模式
    callbacks=None  # 回调函数列表
)
  1. x

    • 作用:训练数据。可以是 tf.data.Dataset 对象、NumPy 数组、Python 列表等。
    • 示例x=train_ds
  2. y

    • 作用:训练数据的标签。如果 xtf.data.Dataset 对象,可以省略 y,因为 tf.data.Dataset 已经包含了标签。
    • 示例y=train_labels(如果 x 是 NumPy 数组)
  3. validation_data

    • 作用:验证数据,用于在每个 epoch 结束时评估模型的性能。
    • 示例validation_data=val_ds
  4. epochs

    • 作用:训练的轮数,即模型将在整个训练数据集上迭代的次数。
    • 示例epochs=10
  5. batch_size

    • 作用:每个批次的样本数量。如果 xtf.data.Dataset 对象,通常不需要指定 batch_size,因为 tf.data.Dataset 已经设置了批次大小。
    • 示例batch_size=32
  6. verbose

    • 作用

      :日志显示模式。

      • 0:不输出日志。
      • 1:输出进度条。
      • 2:每个 epoch 输出一行记录。
    • 示例verbose=1

  7. callbacks

    • 作用:回调函数列表,用于在训练过程中执行特定的操作,如保存模型、早停、学习率调整等。

    • 常见回调

      • tf.keras.callbacks.ModelCheckpoint:定期保存模型。
      • tf.keras.callbacks.EarlyStopping:在验证性能不再提升时提前停止训练。
      • tf.keras.callbacks.ReduceLROnPlateau:在验证性能不再提升时降低学习率。

2、天气案例详解

数据量较小,模型泛化能力较差,仅适合学习,要分类的数据有四类,一共1000多张图片。

1、数据处理

1、导入库

import tensorflow as tf 
from tensorflow.keras import datasets, layers, models
import numpy as np 

# 查看是否支持gpu
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")

gpus

输出:

[]   // 说明本机tensorflow不是gpu版本,不支持gpu

2、图片类别

import os, PIL, pathlib 

# 转化为pathlib对象
data_dir = './data/'
data_dir = pathlib.Path(data_dir)

data_paths = data_dir.glob('*')
classNums = [str(path).split('\\')[1] for path in data_paths]
classNums

输出:

['cloudy', 'rain', 'shine', 'sunrise']

3、数据划分

tf.keras.preprocessing.image_dataset_from_directory是tensorflow中加载数据的API,用于处理数据集的划分功能.
在tf.keras.preprocessing.image_dataset_from_directory中,提供了如何划分训练集和验证集的选项,要注意的是:

  • 当选择训练集的的时候,validation_split=0.2,说明选择0.8作为训练集;
  • 当选择验证集的时候,validation_split=0.2,说明选择0.2作为验证集。

数据划分:

  • 数据划分为训练集和验证集,训练集0.8,验证集0.2;

训练集、验证集、测试集:

  • 训练集:用来训练模型,找寻数据特性,调整模型参数;
  • 验证集:验证集没有参与模型训练,定期评估模型性能,但不参与模型参数的更新,所以在狭义的角度来看,他没有参与模型训练,从广义来看,参与了
  • 测试集:用来检测模型,用于最终的评估模型性能。
batch_size = 32

# 加载数据
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    directory = './data/',
    validation_split = 0.2,
    batch_size = 32,
    seed = 42,
    image_size = (224, 224),
    subset = 'training',
    shuffle = True
)

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    directory = './data/',
    validation_split = 0.2,
    batch_size = 32,
    seed = 42,
    image_size = (224, 224),
    subset = 'validation',
    shuffle = True
)
Found 1125 files belonging to 4 classes.
Using 900 files for training.
Found 1125 files belonging to 4 classes.
Using 225 files for validation.

# 查看训练集名字,图片分类名字
class_names = train_ds.class_names
class_names

输出:

['cloudy', 'rain', 'shine', 'sunrise']

4、数据可视化

取批次函数:
train_ds.take(1),返回值:images,labels(下标)

import matplotlib.pyplot as plt 

plt.figure(figsize=(20, 10))

for images, labels in train_ds.take(1):   # 类别存储0, 1
    for i in range(20):  # 展示20
        plt.subplot(5, 10, i + 1)
        
        plt.imshow(images[i].numpy().astype("uint8"))
        plt.title(class_names[labels[i]])  # 类别是存储0,1
        
        plt.axis('off')  # 去掉边框


在这里插入图片描述


# 查看图片批次、大小、颜色通道,和存储数据类别
for X, classes in train_ds:
    print(X.shape)
    print(classes)
    break
(32, 224, 224, 3)
tf.Tensor([0 3 1 3 1 2 1 0 2 2 2 1 0 3 2 3 0 3 2 1 3 2 0 0 0 3 3 3 2 0 2 2], shape=(32,), dtype=int32)

5、数据配置

原理请看第一大点中有讲解。

from tensorflow.data.experimental import AUTOTUNE

AUTOTUNE = tf.data.experimental.AUTOTUNE

# buffer_size:缓冲区大小
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
vals_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

2、网络构建

由于数据集少,故本模型用的模型层数少,一共由3层卷积、2层池化、1层dropout层、2层全连接层组成。

model = models.Sequential([
    # 将像素从[0, 255] --> [0, 1]
    layers.experimental.preprocessing.Rescaling(1./255, input_shape=(224, 224, 3)),
    
    # 卷积层、池化层
    layers.Conv2D(16, (3, 3), activation='relu', input_shape=(224, 224, 3)),    # 卷积核 3 * 3
    layers.AveragePooling2D((2, 2)),
    layers.Conv2D(32, (3, 3), activation='relu'),
    layers.AveragePooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    
    # dropout层
    layers.Dropout(0.3),
    
    # 全连接从层
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(len(class_names))
])
# 打印模型参数
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
rescaling (Rescaling)        (None, 224, 224, 3)       0         
_________________________________________________________________
conv2d (Conv2D)              (None, 222, 222, 16)      448       
_________________________________________________________________
average_pooling2d (AveragePo (None, 111, 111, 16)      0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 109, 109, 32)      4640      
_________________________________________________________________
average_pooling2d_1 (Average (None, 54, 54, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 52, 52, 64)        18496     
_________________________________________________________________
dropout (Dropout)            (None, 52, 52, 64)        0         
_________________________________________________________________
flatten (Flatten)            (None, 173056)            0         
_________________________________________________________________
dense (Dense)                (None, 128)               22151296  
_________________________________________________________________
dense_1 (Dense)              (None, 4)                 516       
=================================================================
Total params: 22,175,396
Trainable params: 22,175,396
Non-trainable params: 0
_________________________________________________________________

3、模型训练

1、超参数设置

# 优化器
opt = tf.keras.optimizers.Adam(learning_rate=0.001)  # 学习率:0.001

# 设置超参数
model.compile(optimizer=opt,
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

2、模型训练

epoches = 10
result =  model.fit(
    x = train_ds,
    validation_data=val_ds,
    epochs = epoches
)
Epoch 1/10
29/29 [==============================] - 17s 577ms/step - loss: 1.4328 - accuracy: 0.6056 - val_loss: 0.6638 - val_accuracy: 0.7067
Epoch 2/10
29/29 [==============================] - 17s 577ms/step - loss: 0.5417 - accuracy: 0.7789 - val_loss: 0.5179 - val_accuracy: 0.8000
Epoch 3/10
29/29 [==============================] - 16s 536ms/step - loss: 0.4496 - accuracy: 0.8267 - val_loss: 0.6159 - val_accuracy: 0.7467
Epoch 4/10
29/29 [==============================] - 14s 475ms/step - loss: 0.3856 - accuracy: 0.8456 - val_loss: 0.4435 - val_accuracy: 0.8578
Epoch 5/10
29/29 [==============================] - 15s 517ms/step - loss: 0.2932 - accuracy: 0.8789 - val_loss: 0.4393 - val_accuracy: 0.8400
Epoch 6/10
29/29 [==============================] - 15s 531ms/step - loss: 0.2014 - accuracy: 0.9278 - val_loss: 0.3550 - val_accuracy: 0.8844
Epoch 7/10
29/29 [==============================] - 16s 548ms/step - loss: 0.1977 - accuracy: 0.9222 - val_loss: 0.6002 - val_accuracy: 0.8089
Epoch 8/10
29/29 [==============================] - 15s 509ms/step - loss: 0.2144 - accuracy: 0.9122 - val_loss: 0.5215 - val_accuracy: 0.8489
Epoch 9/10
29/29 [==============================] - 14s 496ms/step - loss: 0.1975 - accuracy: 0.9211 - val_loss: 0.3932 - val_accuracy: 0.8800
Epoch 10/10
29/29 [==============================] - 16s 542ms/step - loss: 0.1055 - accuracy: 0.9589 - val_loss: 0.4329 - val_accuracy: 0.8756

4、模型效果展示

# 获取训练集和验证集损失率和准确率
acc = result.history['accuracy']
val_acc = result.history['val_accuracy']

loss = result.history['loss']
val_loss = result.history['val_loss']

epochs_range = range(epoches)

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()


在这里插入图片描述

准确率:

  • 测试集准确率很好,验证集接近0.9,且有上升趋势,效果很好;

损失率:

  • 测试集损失率次序降低,但是验证集损失率较高,说明模型泛化能力有待提高,当然这也跟数据集有关,数据集比较小,也有可能和网络结构有关,网络结构比较简单;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值