【技术专题】TensorFlow2 Python深度学习 - Keras框架

0 阅读17分钟

大家好,我是锋哥。最近连载更新《TensorFlow2 Python深度学习》技术专题。

QQ截图20260306194834.jpg 本课程主要讲解基于TensorFlow2的Python深度学习知识,包括深度学习概述,TensorFlow2框架入门知识,以及卷积神经网络(CNN),循环神经网络(RNN),生成对抗网络(GAN),模型保存与加载等。同时也配套视频教程 《2026版 TensorFlow2 Python深度学习 视频教程》

在TensorFlow 2.x中,Keras API被整合进TensorFlow核心库,这意味着你可以直接使用tf.keras模块来构建和训练神经网络模型。

使用TensorFlow2里的Keras.Model来定义模型

我们使用TensorFlow2里的Keras.Model来定义模型方式实现下上一个节的实例,然后进行对比下,对我们学习和认识TensorFlow2会有很大帮助。

如果您将tf.keras.Model子类化,则定义模型与其看起来完全相同。请记住,Keras模型最终从模块继承。

# 定义模型
class MyModelKeras(tf.keras.Model):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # 将权重初始化为5.0,偏置初始化为0.0
        # 在实际应用中,这些参数应该被随机初始化
        self.w = tf.Variable(5.0)
        self.b = tf.Variable(0.0)
​
    def call(self, x):
        return self.w * x + self.b
​
keras_model = MyModelKeras()
​
# 训练模型
training_loop(keras_model, x, y)

运行结果:

开始:
     W = 5.00, b = 0.00, loss=10.73324
第 1轮:
     W = 4.48, b = 0.43, loss=6.67150
第 2轮:
     W = 4.09, b = 0.78, loss=4.32498
第 3轮:
     W = 3.81, b = 1.05, loss=2.95827
第 4轮:
     W = 3.61, b = 1.27, loss=2.15569
第 5轮:
     W = 3.46, b = 1.45, loss=1.68053
第 6轮:
     W = 3.35, b = 1.59, loss=1.39699
第 7轮:
     W = 3.27, b = 1.71, loss=1.22649
第 8轮:
     W = 3.21, b = 1.80, loss=1.12323
第 9轮:
     W = 3.17, b = 1.87, loss=1.06027
第10轮:
     W = 3.14, b = 1.93, loss=1.02164

TensorFlow2 Sequential顺序模型

Sequential顺序模型是Keras中最简单的线性堆叠模型,各层之间按顺序依次连接,前一层的输出作为后一层的输入。这种模型适合构建简单的神经网络结构。

image.png

先提前了解下Keras中常用模型

  • Sequential 模型:适用于简单的层按顺序堆叠的模型。
  • Functional API(函数式API) :适用于多输入、多输出、共享权重等更复杂的结构。
  • 子类化模型(Sub-classing Model) :适用于极其自定义的网络结构,提供最大的灵活性。
  • 预训练模型(Pre-trained Models) :使用预训练模型进行迁移学习,特别适用于计算机视觉和自然语言处理。
  • 共享层权重模型(Shared Weights Model) :适用于需要在多个输入之间共享权重的场景,如Siamese 网络。

Keras Input层

Input层是Keras中用于明确指定模型输入张量形状和属性的特殊层。它在构建复杂模型(特别是函数式API)时非常重要。

# 基本用法
input_tensor = Input(shape=(input_shape,))
​
# 完整参数
input_tensor = Input(
    shape=None,
    batch_size=None,
    name=None,
    dtype=None,
    sparse=None,
    tensor=None,
    ragged=None,
    **kwargs
)

核心参数:

  • shape: 输入形状元组,不包括batch大小
  • batch_size: 固定batch大小(可选)
  • name: 层的名称
  • dtype: 数据类型,如tf.float32
  • sparse: 是否创建稀疏张量
  • tensor: 可选现有张量包装为Input层

Keras Dense层

Dense层(全连接层)是神经网络中最基本也是最常用的层类型。每个神经元与前一层的所有神经元相连接,实现特征的线性变换和非线性激活。

# 基本用法
dense_layer = Dense(units, activation=None, **kwargs)
​
# 完整参数
dense_layer = Dense(
    units,
    activation=None,
    use_bias=True,
    kernel_initializer='glorot_uniform',
    bias_initializer='zeros',
    kernel_regularizer=None,
    bias_regularizer=None,
    activity_regularizer=None,
    kernel_constraint=None,
    bias_constraint=None,
    **kwargs
)

核心参数

  • units: 指定该层神经元的个数,决定了该层的输出维度。
  • activation: 激活函数,如 'relu', 'sigmoid', 'softmax', 'tanh' 等
  • use_bias: 布尔值,是否使用偏置向量

初始化器

  • kernel_initializer: 权重矩阵初始化方法
  • bias_initializer: 偏置向量初始化方法

正则化

  • kernel_regularizer: 权重正则化(L1/L2)
  • bias_regularizer: 偏置正则化
  • activity_regularizer: 输出正则化

约束

  • kernel_constraint: 权重约束
  • bias_constraint: 偏置约束

在Keras中,除了Dense层(全连接层)之外,还有许多常用的层,用于构建各种神经网络结构。以下是一些常见的层及其功能:

  1. 卷积层 (Convolutional Layers)
  • Conv1D: 适用于一维数据(如时间序列数据)。常用于处理序列数据,如文本和音频。
  • Conv2D: 适用于二维数据(如图像)。常用于图像处理和计算机视觉任务。
  • Conv3D: 适用于三维数据(如视频或3D体积数据)。
  1. 池化层 (Pooling Layers)
  • MaxPooling1D: 适用于一维数据,执行最大池化操作。
  • MaxPooling2D: 适用于二维数据,执行最大池化操作。
  • MaxPooling3D: 适用于三维数据,执行最大池化操作。
  • AveragePooling1D: 适用于一维数据,执行平均池化操作。
  • AveragePooling2D: 适用于二维数据,执行平均池化操作。
  • AveragePooling3D: 适用于三维数据,执行平均池化操作。
  1. 循环层 (Recurrent Layers)
  • LSTM: 长短期记忆网络(Long Short-Term Memory),用于处理序列数据,解决传统RNN的梯度消失问题。
  • GRU: 门控循环单元(Gated Recurrent Unit),比LSTM简化,通常训练更快。
  • SimpleRNN: 基本的循环神经网络层,适用于简单的序列任务。
  1. 归一化层 (Normalization Layers)
  • BatchNormalization: 批量归一化,用于加速训练,稳定学习过程,减少内部协变量偏移。
  • LayerNormalization: 层归一化,主要用于对每一层的输入进行标准化。
  • GroupNormalization: 分组归一化,将特征分为小组进行归一化。
  1. Dropout层
  • Dropout: 随机丢弃神经网络中的一部分神经元,用于防止过拟合。
  1. 激活函数层
  • Activation

    : 将某种激活函数应用到输入。常见的激活函数有:

    • relu:线性整流单元
    • sigmoid:Sigmoid函数
    • tanh:双曲正切函数
    • softmax:常用于分类任务的输出层
  1. Flatten层
  • Flatten: 将多维输入展平为一维数据,通常用于将卷积层或池化层的输出展平,以连接到全连接层。
  1. 全连接层 (Fully Connected Layers)
  • Dense: 前向传播过程中常用的全连接层。可以有多个神经元,通常用于模型的最终分类或回归任务。
  1. Embedding层
  • Embedding: 用于将离散数据(如词索引)映射到稠密的向量空间,常用于自然语言处理任务。
  1. Reshape层
  • Reshape: 用于改变输入数据的形状。
  1. 自定义层
  • Lambda: 创建自定义操作,可以用于实现一些复杂的数学操作或将某些操作封装到一个层中。
  1. Global池化层
  • GlobalMaxPooling1D/2D/3D: 全局最大池化,减少维度,保留全局特征。
  • GlobalAveragePooling1D/2D/3D: 全局平均池化,减少维度,保留全局特征。
  1. Separable卷积层
  • SeparableConv2D: 分离卷积,使用深度可分离卷积提高计算效率,尤其在移动设备上很常用。

tanh

  1. UpSampling层
  • UpSampling1D/2D/3D: 上采样层,用于增大输入的尺寸,通常用于生成模型和上采样任务。

Keras 激活函数

激活函数是神经网络中的非线性变换函数,它决定了神经元的输出。没有激活函数,神经网络就只是线性回归模型,无法学习复杂模式。常用激活函数,如 'relu', 'sigmoid', 'softmax', 'tanh'

image.png

说明:

  1. SigmoidSoftmax 主要用于分类问题的输出层,尤其是二分类和多分类任务。
  2. Tanh 通常用于需要输出负值的任务,且它的输出范围较对称。
  3. ReLULeaky ReLU 常用于隐藏层,尤其是深度神经网络中,后者通过为负数部分引入斜率,避免了 ReLU 的“死神经元”问题。
  4. Swish 是 Google 提出的新型激活函数,近年来在一些深度学习模型中取得了不错的效果,尤其是在深层网络中。

Keras模型编译方法model.compile()

model.compile()是Keras中配置模型学习过程的关键方法,它在模型构建后、训练前调用,用于指定模型的优化器、损失函数和评估指标。

model.compile(optimizer, loss=None, metrics=None, loss_weights=None, weighted_metrics=None, run_eagerly=None, steps_per_execution=None, **kwargs)

核心参数:

  1. optimizer(优化器)
  • 作用:定义模型参数更新的算法

  • 常用选项

    • 'adam' - 自适应矩估计(最常用)
    • 'sgd' - 随机梯度下降
    • 'rmsprop' - 适用于RNN
    • 'adagrad' - 自适应学习率
  1. loss(损失函数)
  • 作用:定义模型训练中要最小化的目标函数

  • 常用选项

    • 分类问题

      • 'binary_crossentropy' - 二分类
      • 'categorical_crossentropy' - 多分类 适用于标签采用one-hot编码的情况(如[1,0,0]表示类别1)
      • 'sparse_categorical_crossentropy' - 整数标签多分类 适用于标签为整数编码的情况(如直接使用类别序号3、1等)。
    • 回归问题

      • 'mean_squared_error' - 均方误差
      • 'mean_absolute_error' - 平均绝对误差
  1. metrics(评估指标)
  • 作用:监控训练和测试过程的性能指标

  • 常用选项

    • 'accuracy' - 准确率(分类)
    • 'precision', 'recall' - 精确率、召回率
    • 'mae', 'mse' - 回归指标

我们看下示例代码:

import tensorflow as tf
from keras import Input, layers
​
# 正确的权重和偏置
TRUE_W = 3.0
TRUE_B = 2.0NUM_EXAMPLES = 201# 在区间[-2, 2]内生成NUM_EXAMPLES个均匀分布的数值点
x = tf.linspace(-2, 2, NUM_EXAMPLES)
x = tf.cast(x, tf.float32)
​
​
def f(x):
    return x * TRUE_W + TRUE_B
​
​
# 生成随机噪声数据
noise = tf.random.normal(shape=[NUM_EXAMPLES])
​
# 计算y
y = f(x) + noise
​
# 定义一个顺序模型
model = tf.keras.Sequential([
    Input(shape=(1,)),
    layers.Dense(units=1)
])
​
# 打印模型结构
model.summary()
​
# 编译配置模型 使用SGD(随机梯度下降)优化器,均方误差损失函数
model.compile(optimizer='sgd', loss='mean_squared_error')
​
# 训练模型
model.fit(x, y, epochs=10)
# 打印模型参数
print(model.variables)

运行结果:

image.png

使用TensorFlow2 Keras实现线性回归问题 - 房价预测案例

TensorFlow2 Keras主要是解决分类问题的。不过线性问题也同样能做。因为默认没有带线性问题的案例数据集。所以我们把前面scikit-learn自带的房价数据集拿过来。用TensorFlow2 Keras来实现下线性回归问题。

加州房价数据集介绍

  1. 数据集概况
  • 来源:该数据集源自 1990 年的加州人口普查
  • 用途:用于回归模型的练习和测试,目标是预测加州各区域的房屋中位价
  • 样本数量20,640 条记录。这比波士顿数据集(506条)大得多,能更好地体现机器学习算法的效果。
  • 特征数量8 个数值型特征。这些特征涵盖了人口、地理位置和经济指标。
  • 目标变量MedHouseVal - 街区群体的房屋中位价,单位是十万美元

注意:目标变量是分组中位价。这意味着一个街区的所有房屋都被分配了该街区的 median house value。对于任何位于该街区的房屋,目标值都是相同的。

  1. 特征详细说明

这8个特征提供了预测房价的不同维度信息:

  1. MedInc:街区居民的收入中位数。

  2. HouseAge:街区内房屋年龄中位数。

  3. AveRooms:平均房间数(每户)。

  4. AveBedrms:平均卧室数(每户)。

  5. Population:街区人口数。

  6. AveOccup:平均家庭成员数(每户)。

  7. Latitude:街区的纬度。

  8. Longitude:街区的经度。

    3.目标变量:

  • MedHouseVal:房屋中位价(单位:十万美元)。

我们先安装下scikit-learn:

pip install scikit-learn -i http://mirrors.aliyun.com/pypi/simple/  --trusted-host mirrors.aliyun.com

我们回顾下scikit-learn机器学习的实现,线性回归-正规方程使用 LinearRegression。

from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
​
# 1,加载数据
california = fetch_california_housing()
print(california.data, california.data.shape)
print(california.target)
print(california.feature_names)
​
# 2,数据预处理
X_train, X_test, y_train, y_test = train_test_split(california.data, california.target, test_size=0.2, random_state=20)
scaler = StandardScaler()  # 数据标准化:消除不同特征量纲的影响
X_train_scaled = scaler.fit_transform(X_train)  # fit计算生成模型,transform通过模型转换数据
X_test_scaled = scaler.transform(X_test)  # # 使用训练集的参数转换测试集# 3,创建和训练线性回归模型(正规方程)
lr_model = LinearRegression()  # 创建分类器实例
lr_model.fit(X_train_scaled, y_train)  # 训练模型
print('权重系数:', lr_model.coef_)
print('偏置值:', lr_model.intercept_)  # 在线性回归模型中,•偏置(截距)•(bias)是模型参数之一,表示当所有特征值为0时,目标变量的期望值。# 4,模型评估
y_predict = lr_model.predict(X_test_scaled)
print('预测值:', y_predict)
mse = mean_squared_error(y_test, y_predict)
print('正规方程-均方误差:', mse)

我们来用下Tensorflow2 keras多层神经网络实现下:

from sklearn.datasets import fetch_california_housing
​
import tensorflow as tf
from keras import Input, layers
​
# 1,加载数据
california = fetch_california_housing()
print(california.data, california.data.shape)
print(california.target)
print(california.feature_names)
X_train = california.data
y_train = california.target
​
# 2,构建多层神经网络回归模型
model = tf.keras.models.Sequential([
    Input(shape=(X_train.shape[1],)),
    layers.Dense(64, activation='relu'),
    layers.Dense(32, activation='relu'),
    layers.Dense(16, activation='relu'),
    layers.Dense(1)  # 输出层,线性激活
])
​
# 3,模型训练
model.compile(optimizer='adam', loss='mse', metrics=['mse'])
​
# 4,模型训练
history = model.fit(X_train,  # 输入数据(特征)
                    y_train,  # 目标数据(标签)
                    epochs=100,  # 训练轮数
                    batch_size=32,  # 每个训练批次的样本数量
                    validation_split=0.2,  # 从训练数据中划分验证集的比例
                    verbose=1  # 日志显示模式(0=不显示,1=进度条,2=简洁显示)
                    )
​
print(f"最终MSE: {history.history['mse'][-1]:.4f}")

我们比较发现,用Keras多层神经网络,可以不用数据预处理,model.fit()方法自带可以进行训练和验证比例数据划分训练,同时还自带日志显示,最终比较,用神经网络最终训练的模型,性能还高于scikit-learn线性回归模型。神经网络唯一缺点就是费算力,费机器。

Sequential.fit() 是 TensorFlow/Keras 中最常用的训练方法之一。以下是其主要参数的简单介绍:

model.fit(
    x=None,
    y=None,
    batch_size=None,
    epochs=1,
    verbose='auto',
    callbacks=None,
    validation_split=0.0,
    validation_data=None,
    shuffle=True,
    class_weight=None,
    sample_weight=None,
    initial_epoch=0,
    steps_per_epoch=None,
    validation_steps=None,
    validation_batch_size=None,
    validation_freq=1
)

核心参数:

数据相关参数

  • x: 输入数据(特征)
  • y: 目标数据(标签)
  • batch_size: 每个训练批次的样本数量
  • validation_data: 验证数据集(元组 (x_val, y_val))
  • validation_split: 从训练数据中划分验证集的比例

训练过程参数

  • epochs: 训练轮数
  • verbose: 日志显示模式(0=不显示,1=进度条,2=简洁显示)
  • shuffle: 是否在每个epoch前打乱训练数据
  • initial_epoch: 开始训练的epoch序号

验证相关参数

  • validation_freq: 验证频率(每N个epoch验证一次)
  • validation_steps: 每个验证epoch的批次数量

回调与控制

  • callbacks: 回调函数列表(用于早停、模型保存等)
  • steps_per_epoch: 每个训练epoch的批次数量
  • class_weight: 类别权重字典(用于不平衡数据集)

这些参数控制了模型训练的基本行为,包括数据加载、训练周期、验证策略和训练过程监控等关键方面。

参数计算公式:

参数数量 = 输入维度 × 输出维度 + 输出维度

输入Input维度8

第一层Dense(64)

  • 参数 = 64× 8+ 64 = 576

第二层Dense(32)

  • 参数 = 64× 32+ 32= 2080

第三层Dense(16)

  • 参数 = 32× 16+ 16= 528

输出层Dense(1)

  • 参数 = 16× 1 + 1 = 17

使用TensorFlow2 Keras实现逻辑回归

在 TensorFlow 2 中使用 Keras 实现逻辑回归是非常简单的。逻辑回归可以看作是一个二分类问题,Keras 提供了非常方便的接口来搭建模型。

逻辑回归虽然名字中有"回归",但实际上是一种用于二分类问题的线性模型。它通过sigmoid函数将线性输出映射到[0,1]区间,表示属于正类的概率。

下面是使用 TensorFlow 2 和 Keras 实现逻辑回归的示例,使用乳腺癌数据集进行训练和测试。我们将使用 sklearn.datasets.load_breast_cancer 来加载乳腺癌数据集,并使用 Keras 构建一个简单的逻辑回归模型来对其进行分类。

1,乳腺癌数据集介绍

该数据集共有 569 个样本,每个样本有 30 个特征。这些特征是乳腺肿瘤的细胞核属性的量化值,例如半径、纹理、周长、面积、光滑度等。特征数据是通过显微镜分析细胞样本获取的。

特征

每个样本由 30 个特征组成,这些特征描述了肿瘤细胞的几何形状、纹理、面积等。特征的详细描述如下:

  1. 半径(radius): 肿瘤的半径大小
  2. 纹理(texture): 肿瘤表面的纹理粗糙度
  3. 周长(perimeter): 肿瘤的外周长
  4. 面积(area): 肿瘤的表面积
  5. 平滑度(smoothness): 细胞核边缘的平滑度
  6. 其他的特征还包括紧凑度、对称性、均匀性等。

类别标签

目标变量(即标签)只有两个类别:

  • 恶性肿瘤(Malignant,标记为 0)
  • 良性肿瘤(Benign,标记为 1)

数据集的特点

  • 样本数:569个样本
  • 特征数:30个特征(所有特征都是数字型)
  • 类别数:2(良性或恶性)
  • 数据分布:在 569 个样本中,357 个为良性肿瘤,212 个为恶性肿瘤。

2,Keras实例

import tensorflow as tf
from keras import Input, layers
from sklearn.datasets import load_breast_cancer
​
# 1,加载乳腺癌数据集
data = load_breast_cancer()
X = data.data
y = data.target
print(X, y)
print(data.feature_names)
print(X.shape, y.shape)
​
# 2,构建逻辑回归模型
model = tf.keras.models.Sequential([
    Input(shape=(X.shape[1],)),
    layers.Dense(1, activation='sigmoid')  # 使用sigmoid激活函数
])
​
# 3,模型编译
model.compile(
    optimizer='adam',
    loss='binary_crossentropy',  # 损失函数 二分类交叉熵
    metrics=['accuracy']  # 评估指标 accuracy准确率
)
​
# 4,模型训练
history = model.fit(X, y, epochs=100, batch_size=32, validation_split=0.2, verbose=1)
print(type(history))
print(f"最终准确率: {history.history['accuracy'][-1]:.4f}")

运行结果:

image.png

3,训练历史History

keras.src.callbacks.History 对象是 Keras 中用于存储模型训练过程中各项指标历史的类,通常作为 fit() 函数的返回值。通过 History 对象,你可以访问训练过程中各个 epoch 的训练和验证指标,包括损失、精度、学习率等。

使用场景:

在模型训练过程中,History 对象会记录每个 epoch 结束时的训练和验证指标。你可以利用这些数据进行后续分析或可视化,帮助你了解模型的学习过程。

主要功能:

  1. 存储训练过程中的历史数据History 对象包含了每个 epoch 的训练和验证损失(loss)、精度(accuracy)等指标。
  2. 获取历史数据: 通过 history.history 属性,你可以访问包含训练过程中的所有指标的字典。
  3. 方便的可视化: 你可以直接利用 History 对象中的数据来绘制损失曲线、准确率曲线等图表,从而分析模型的训练情况。

属性:

  • history

    :一个字典,存储每个 epoch 中的训练和验证指标。例如:

    • 'loss': 训练过程中的损失值。
    • 'accuracy': 训练过程中的准确率。
    • 'val_loss': 验证集上的损失值(如果有验证集的话)。
    • 'val_accuracy': 验证集上的准确率(如果有验证集的话)。

我们可以通过matplotlib来看下损失值的可视化图表:

from matplotlib import pyplot as plt
history.history.keys()
plt.plot(history.epoch, history.history['loss'], label='loss')

image.png

也可以看下准确率图表:

plt.plot(history.epoch, history.history['accuracy'], label='accuracy')

image.png

使用TensorFlow2 Keras实现分类问题

我们使用TensorFlow2 Keras实现分类问题,数据集使用之前机器学习用到的鸢尾花数据集。四个特征,三个目标类别。

输出层激活函数是softmax。将网络的原始输出值转换成概率分布,方便理解和比较不同类别的预测。

示例代码:

import tensorflow as tf
from keras import Input, layers
from sklearn.datasets import load_iris
​
# 1,加载鸢尾花数据集
iris = load_iris()
X = iris.data  # 特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度
y = iris.target  # 标签:0-Setosa, 1-Versicolour, 2-Virginica# 2,构建分类模型
model = tf.keras.models.Sequential([
    Input(shape=(X.shape[1],)),  # 输入层
    layers.Dense(16, activation='relu'),  # 隐藏层
    layers.Dense(3, activation='softmax')  # 输出层 3个神经元,对应3个类别
])
​
# 3,模型编译
model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',  # 多分类交叉熵损失函数
    metrics=['accuracy']  # 评估指标:准确率
)
​
# 4,模型训练
history = model.fit(X, y, epochs=200, batch_size=32, verbose=1)
print(f"最终损失: {history.history['loss'][-1]:.4f}, 最终准确率: {history.history['accuracy'][-1]:.4f}")

运行输出:

image.png