大家好,我是锋哥。最近连载更新《TensorFlow2 Python深度学习》技术专题。
本课程主要讲解基于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中最简单的线性堆叠模型,各层之间按顺序依次连接,前一层的输出作为后一层的输入。这种模型适合构建简单的神经网络结构。
先提前了解下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层(全连接层)之外,还有许多常用的层,用于构建各种神经网络结构。以下是一些常见的层及其功能:
- 卷积层 (Convolutional Layers)
- Conv1D: 适用于一维数据(如时间序列数据)。常用于处理序列数据,如文本和音频。
- Conv2D: 适用于二维数据(如图像)。常用于图像处理和计算机视觉任务。
- Conv3D: 适用于三维数据(如视频或3D体积数据)。
- 池化层 (Pooling Layers)
- MaxPooling1D: 适用于一维数据,执行最大池化操作。
- MaxPooling2D: 适用于二维数据,执行最大池化操作。
- MaxPooling3D: 适用于三维数据,执行最大池化操作。
- AveragePooling1D: 适用于一维数据,执行平均池化操作。
- AveragePooling2D: 适用于二维数据,执行平均池化操作。
- AveragePooling3D: 适用于三维数据,执行平均池化操作。
- 循环层 (Recurrent Layers)
- LSTM: 长短期记忆网络(Long Short-Term Memory),用于处理序列数据,解决传统RNN的梯度消失问题。
- GRU: 门控循环单元(Gated Recurrent Unit),比LSTM简化,通常训练更快。
- SimpleRNN: 基本的循环神经网络层,适用于简单的序列任务。
- 归一化层 (Normalization Layers)
- BatchNormalization: 批量归一化,用于加速训练,稳定学习过程,减少内部协变量偏移。
- LayerNormalization: 层归一化,主要用于对每一层的输入进行标准化。
- GroupNormalization: 分组归一化,将特征分为小组进行归一化。
- Dropout层
- Dropout: 随机丢弃神经网络中的一部分神经元,用于防止过拟合。
- 激活函数层
-
Activation
: 将某种激活函数应用到输入。常见的激活函数有:
relu:线性整流单元sigmoid:Sigmoid函数tanh:双曲正切函数softmax:常用于分类任务的输出层
- Flatten层
- Flatten: 将多维输入展平为一维数据,通常用于将卷积层或池化层的输出展平,以连接到全连接层。
- 全连接层 (Fully Connected Layers)
- Dense: 前向传播过程中常用的全连接层。可以有多个神经元,通常用于模型的最终分类或回归任务。
- Embedding层
- Embedding: 用于将离散数据(如词索引)映射到稠密的向量空间,常用于自然语言处理任务。
- Reshape层
- Reshape: 用于改变输入数据的形状。
- 自定义层
- Lambda: 创建自定义操作,可以用于实现一些复杂的数学操作或将某些操作封装到一个层中。
- Global池化层
- GlobalMaxPooling1D/2D/3D: 全局最大池化,减少维度,保留全局特征。
- GlobalAveragePooling1D/2D/3D: 全局平均池化,减少维度,保留全局特征。
- Separable卷积层
- SeparableConv2D: 分离卷积,使用深度可分离卷积提高计算效率,尤其在移动设备上很常用。
tanh
- UpSampling层
- UpSampling1D/2D/3D: 上采样层,用于增大输入的尺寸,通常用于生成模型和上采样任务。
Keras 激活函数
激活函数是神经网络中的非线性变换函数,它决定了神经元的输出。没有激活函数,神经网络就只是线性回归模型,无法学习复杂模式。常用激活函数,如 'relu', 'sigmoid', 'softmax', 'tanh'
说明:
- Sigmoid 和 Softmax 主要用于分类问题的输出层,尤其是二分类和多分类任务。
- Tanh 通常用于需要输出负值的任务,且它的输出范围较对称。
- ReLU 和 Leaky ReLU 常用于隐藏层,尤其是深度神经网络中,后者通过为负数部分引入斜率,避免了 ReLU 的“死神经元”问题。
- 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)
核心参数:
- optimizer(优化器)
-
作用:定义模型参数更新的算法
-
常用选项:
'adam'- 自适应矩估计(最常用)'sgd'- 随机梯度下降'rmsprop'- 适用于RNN'adagrad'- 自适应学习率
- loss(损失函数)
-
作用:定义模型训练中要最小化的目标函数
-
常用选项:
-
分类问题:
'binary_crossentropy'- 二分类'categorical_crossentropy'- 多分类 适用于标签采用one-hot编码的情况(如[1,0,0]表示类别1)'sparse_categorical_crossentropy'- 整数标签多分类 适用于标签为整数编码的情况(如直接使用类别序号3、1等)。
-
回归问题:
'mean_squared_error'- 均方误差'mean_absolute_error'- 平均绝对误差
-
- metrics(评估指标)
-
作用:监控训练和测试过程的性能指标
-
常用选项:
'accuracy'- 准确率(分类)'precision','recall'- 精确率、召回率'mae','mse'- 回归指标
我们看下示例代码:
import tensorflow as tf
from keras import Input, layers
# 正确的权重和偏置
TRUE_W = 3.0
TRUE_B = 2.0
NUM_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)
运行结果:
使用TensorFlow2 Keras实现线性回归问题 - 房价预测案例
TensorFlow2 Keras主要是解决分类问题的。不过线性问题也同样能做。因为默认没有带线性问题的案例数据集。所以我们把前面scikit-learn自带的房价数据集拿过来。用TensorFlow2 Keras来实现下线性回归问题。
加州房价数据集介绍
- 数据集概况
- 来源:该数据集源自 1990 年的加州人口普查。
- 用途:用于回归模型的练习和测试,目标是预测加州各区域的房屋中位价。
- 样本数量:20,640 条记录。这比波士顿数据集(506条)大得多,能更好地体现机器学习算法的效果。
- 特征数量:8 个数值型特征。这些特征涵盖了人口、地理位置和经济指标。
- 目标变量:
MedHouseVal- 街区群体的房屋中位价,单位是十万美元。
注意:目标变量是分组中位价。这意味着一个街区的所有房屋都被分配了该街区的 median house value。对于任何位于该街区的房屋,目标值都是相同的。
- 特征详细说明
这8个特征提供了预测房价的不同维度信息:
-
MedInc:街区居民的收入中位数。
-
HouseAge:街区内房屋年龄中位数。
-
AveRooms:平均房间数(每户)。
-
AveBedrms:平均卧室数(每户)。
-
Population:街区人口数。
-
AveOccup:平均家庭成员数(每户)。
-
Latitude:街区的纬度。
-
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 个特征组成,这些特征描述了肿瘤细胞的几何形状、纹理、面积等。特征的详细描述如下:
- 半径(radius): 肿瘤的半径大小
- 纹理(texture): 肿瘤表面的纹理粗糙度
- 周长(perimeter): 肿瘤的外周长
- 面积(area): 肿瘤的表面积
- 平滑度(smoothness): 细胞核边缘的平滑度
- 其他的特征还包括紧凑度、对称性、均匀性等。
类别标签
目标变量(即标签)只有两个类别:
- 恶性肿瘤(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}")
运行结果:
3,训练历史History
keras.src.callbacks.History 对象是 Keras 中用于存储模型训练过程中各项指标历史的类,通常作为 fit() 函数的返回值。通过 History 对象,你可以访问训练过程中各个 epoch 的训练和验证指标,包括损失、精度、学习率等。
使用场景:
在模型训练过程中,History 对象会记录每个 epoch 结束时的训练和验证指标。你可以利用这些数据进行后续分析或可视化,帮助你了解模型的学习过程。
主要功能:
- 存储训练过程中的历史数据:
History对象包含了每个 epoch 的训练和验证损失(loss)、精度(accuracy)等指标。 - 获取历史数据: 通过
history.history属性,你可以访问包含训练过程中的所有指标的字典。 - 方便的可视化: 你可以直接利用
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')
也可以看下准确率图表:
plt.plot(history.epoch, history.history['accuracy'], label='accuracy')
使用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}")
运行输出: