TensorFlow & Keras 环境搭建
### TensorFlow 与 Keras 的关系 **TensorFlow** 是一个端到端的开源机器学习平台,性能好,但代码风格偏底层。 **Keras** 是一个用 Python 编写的高级神经网络 API,它以 TensorFlow、CNTK 等框架为后端。 > 为了让开发者更方便的使用 TensorFlow,社区编写了一套更加简单易用的 API,并命名为 **Keras**。 **总结:** - TensorFlow 是底层计算引擎 - Keras 是封装在 TensorFlow 之上的高层 API - 通过 Keras 可以用更少的代码完成神经网络搭建
### TF1 + Keras2 环境搭建(Conda) 推荐使用 Ubuntu,新建一个用户进行安装。通过 Keras 调用 TensorFlow,有 GPU 环境就安装 GPU 版本的 TensorFlow(Keras 本身无 CPU/GPU 之分)。 ```bash # 查看 conda 环境列表 conda env list # 创建 Python 3.6 虚拟环境 conda create --name py36 python=3.6 conda activate py36 # 安装基础科学计算包 pip install numpy==1.18.1 pip install matplotlib==3.3.4 pip install pandas==1.1.5 pip install scikit-learn==0.24.2 # 安装 TensorFlow 1.15 和 Keras 2.0 conda install tensorflow=1.15.0 pip install Keras==2.0.0 # Windows 环境补充安装 pip install win_unicode_console # 查看自定义 python 模块路径 python -c "print('\n'.join(__import__('sys').path))" ``` **验证安装:** ```python import tensorflow as tf print(tf.test.is_gpu_available()) ``` ```python import keras # 输出: Using TensorFlow backend. ``` **卸载命令:** ```bash conda uninstall tensorflow=1.15.0 conda uninstall tensorflow-gpu=1.15.0 pip uninstall tensorflow-gpu=1.15.0 ``` **常见问题:** > 警告:`Passing (type, 1) or '1type' as a synonym of type is deprecated` **解决方法:** 修改 `dtype.py` 对应行的代码,将 `np.dtype([("quint8", np.uint8, 1)])` 修改为 `np.dtype([("quint8", np.uint8, (1,))])`
### TF2 + Keras2 环境搭建(Conda / Windows) > Python 3.11 不兼容,推荐使用 **Python 3.10**(截至 2024-06-12) ```bash # 创建 Python 3.10 环境 conda create -n py310 python=3.10 conda activate py310 # 安装依赖 conda install mingw libpython conda install theano # 安装科学计算和依赖包(-U 表示更新安装) pip install -U numpy==1.22.4 pip install -U pandas==2.1.0 pip install -U protobuf==3.9.2 pip install -U tensorflow-io-gcs-filesystem==0.23.1 pip install -U libclang==13.0.0 # 安装 TensorFlow 2.10 和 Keras 2.10 pip install -U tensorflow==2.10.0 pip install -U keras==2.10.0 # 安装可视化 pip install -U matplotlib==3.8.4 conda deactivate ```
### 使用 Micromamba 安装 TensorFlow & Keras [Micromamba](https://mamba.readthedocs.io/en/latest/user_guide/micromamba.html) 是一个轻量级、快速的 conda 包管理器替代品,用 C++ 编写,启动速度快,适合在服务器和 CI 环境中使用。 #### 1. 安装 Micromamba ```bash # Linux (x86_64) curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba # 或者使用 shell 初始化 "${SHELL}" <(curl -L micro.mamba.pm/install.sh) ``` #### 2. 创建 TF1 环境(Python 3.6) ```bash micromamba create -n tf1 python=3.6 -c conda-forge micromamba activate tf1 pip install numpy==1.18.1 matplotlib==3.3.4 pandas==1.1.5 scikit-learn==0.24.2 pip install tensorflow==1.15.0 pip install Keras==2.0.0 ``` #### 3. 创建 TF2 环境(Python 3.10) ```bash micromamba create -n tf2 python=3.10 -c conda-forge micromamba activate tf2 pip install -U numpy==1.22.4 pandas==2.1.0 pip install -U protobuf==3.9.2 tensorflow-io-gcs-filesystem==0.23.1 libclang==13.0.0 pip install -U tensorflow==2.10.0 keras==2.10.0 pip install -U matplotlib==3.8.4 ``` #### 4. 纯 Micromamba 安装 TF2(不使用 pip) > 直接通过 conda-forge 频道安装 TensorFlow,无需 pip ```bash # 创建环境并一次性安装所有包 micromamba create -n tf2-mamba python=3.10 -c conda-forge micromamba activate tf2-mamba # 通过 micromamba 安装 TensorFlow 及相关包 micromamba install tensorflow=2.10 keras=2.10 -c conda-forge micromamba install numpy pandas matplotlib scikit-learn -c conda-forge # 或者创建环境时直接指定所有包 micromamba create -n tf2-all python=3.10 tensorflow=2.10 keras=2.10 numpy pandas matplotlib scikit-learn -c conda-forge micromamba activate tf2-all ``` **验证安装:** ```python import tensorflow as tf print(tf.__version__) # 2.10.0 import keras print(keras.__version__) # 2.10.0 ``` #### 5. GPU 版本安装(Linux + CUDA) > conda-forge 的 `tensorflow` 包本身已包含 CUDA 支持,无需单独安装 `tensorflow-gpu`。关键是通过 micromamba 管理 CUDA/cuDNN 版本。 **通用安装(TF 2.10 + CUDA 11.2):** ```bash # 一次性创建 GPU 环境,安装所有包 micromamba create -n tf2-gpu python=3.10 \ tensorflow=2.10 keras=2.10 \ cuda-toolkit=11.2 cudnn=8.1 \ numpy pandas matplotlib scikit-learn \ -c conda-forge -c nvidia micromamba activate tf2-gpu ``` **针对 RTX 4070 + CUDA 12.7 的安装(TF 2.18 + CUDA 12.5):** > 显卡:NVIDIA GeForce RTX 4070 Laptop,驱动 566.24,CUDA Version: 12.7 > > CUDA 12.7 驱动向下兼容,TF 2.18 使用 CUDA 12.5 + cuDNN 9.3 即可正常调用 GPU - 从 TensorFlow 2.11 开始,GPU 支持不再包含在主包中。 ```bash # 创建匹配 CUDA 12.x 的 TF2 环境 micromamba create -n tf2-gpu-rtx python=3.12 \ tensorflow=2.18 \ cuda-toolkit=12.5 cudnn=9.3 \ numpy pandas matplotlib scikit-learn \ -c conda-forge -c nvidia # 1. 激活环境 micromamba activate tf2-gpu-rtx # 2. 卸载 conda 安装的 tensorflow(保留其他包) micromamba remove tensorflow -y # 3. 如果之前也混用过 pip 安装,再执行一次确保干净 pip uninstall tensorflow tensorflow-cpu -y # 4. 安装 pip 的 GPU 版本(会自动带上所需的 CUDA/cuDNN 库) pip install "tensorflow[and-cuda]==2.18.0" # 5. 验证 python -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))" micromamba activate tf2-gpu-rtx ``` **验证 GPU 是否可用:** ```python import tensorflow as tf print(tf.__version__) # 2.18.0 print(tf.config.list_physical_devices('GPU')) # 应列出 GPU 设备 # 查看 GPU 详细信息 gpu_devices = tf.config.list_physical_devices('GPU') if gpu_devices: for gpu in gpu_devices: print(f" - {gpu.name}") ``` **注意事项:** - CUDA Toolkit 和 cuDNN 版本需与 TensorFlow 版本匹配 | TF 版本 | CUDA | cuDNN | Python | |---------|------|-------|--------| | 2.10 | 11.2 | 8.1 | 3.7–3.10 | | 2.15 | 12.2 | 8.9 | 3.9–3.11 | | 2.16 | 12.3 | 8.9 | 3.9–3.12 | | 2.18 | 12.5 | 9.3 | 3.9–3.12 | - NVIDIA 驱动向下兼容:你的 CUDA 12.7 驱动可以运行 CUDA 12.5 的 TF - Linux 环境推荐使用,Windows 下 GPU 支持建议使用 WSL2 或 pip 安装 #### 6. 常用 Micromamba 命令 ```bash # 查看环境列表 micromamba env list # 删除环境 micromamba env remove -n tf1 # 导出环境 micromamba env export -n tf2 > tf2_env.yml # 从文件创建环境 micromamba create -n tf2 -f tf2_env.yml ```
``` xt@qisan:~$ nvidia-smi Sat Jun 6 15:21:24 2026 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 565.57.01 Driver Version: 566.24 CUDA Version: 12.7 | |-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA GeForce RTX 4070 ... On | 00000000:01:00.0 On | N/A | | N/A 53C P8 4W / 70W | 538MiB / 8188MiB | 12% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | No running processes found | +-----------------------------------------------------------------------------------------+ ```
### TF2 环境 pip list 参考列表 > 以下为 `py310` 环境安装后的完整包列表,供对比参考 | 包名 | 版本 | |------|------| | keras | 2.10.0 | | Keras-Preprocessing | 1.1.2 | | tensorflow | 2.10.0 | | tensorflow-estimator | 2.10.0 | | tensorflow-io-gcs-filesystem | 0.23.1 | | tensorboard | 2.10.0 | | numpy | 1.22.4 | | pandas | 2.1.0 | | matplotlib | 3.8.4 | | scipy | 1.7.3 | | protobuf | 3.9.2 | | libclang | 13.0.0 | | h5py | 3.11.0 | | scikit-learn | — | | pillow | 10.3.0 | | Theano | 1.0.5 | | pygpu | 0.7.6 | | jupyterlab | 4.2.2 | | notebook | 7.2.1 |
Conv2D 二维卷积层
### API 定义 ```python tf.keras.layers.Conv2D( filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), groups=1, 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, ) ```
### 参数说明 - filters - int - 输出空间的维度(即卷积核数量)。决定了输出特征图的通道数 - kernel_size - int/tuple - 卷积核的宽度和高度。可以是单个整数(正方形核)或两个整数的元组 - strides - int/tuple - 卷积的步长。默认为 `(1, 1)`,表示在宽度和高度方向上的步长 - padding - str - 填充模式:`'valid'` 表示不填充(输出尺寸缩小),`'same'` 表示填充使输出尺寸与输入相同(当 strides=1 时) - data_format - str - 输入数据的格式:`'channels_last'`(默认,`(batch, height, width, channels)`)或 `'channels_first'`(`(batch, channels, height, width)`) - dilation_rate - int/tuple - 膨胀卷积的膨胀率。用于扩大卷积核的感受野 - groups - int - 分组卷积的组数。默认为 1(普通卷积) - activation - str/callable - 激活函数。如 `'relu'`、`'sigmoid'`、`'tanh'` 或 `None`(线性) - use_bias - bool - 是否使用偏置项 - kernel_initializer - str/callable - 卷积核权重矩阵的初始化器 - bias_initializer - str/callable - 偏置向量的初始化器 - kernel_regularizer - str/callable - 卷积核权重的正则化函数 - bias_regularizer - str/callable - 偏置的正则化函数 - activity_regularizer - str/callable - 输出的正则化函数 - kernel_constraint - str/callable - 卷积核权重的约束函数 - bias_constraint - str/callable - 偏置的约束函数
### 使用示例 ```python import tensorflow as tf import numpy as np # 创建随机输入数据:batch_size=2, height=28, width=28, channels=3 x = np.random.randn(2, 28, 28, 3).astype(np.float32) print(f"输入 shape: {x.shape}") # 输出 shape: (2, 28, 28, 3) # 创建 Conv2D 层 conv_layer = tf.keras.layers.Conv2D( filters=32, # 输出 32 个特征图 kernel_size=(3, 3), # 3x3 卷积核 strides=(1, 1), # 步长为 1 padding='same', # 保持尺寸 activation='relu' # ReLU 激活 ) # 应用卷积 output = conv_layer(x) print(f"输出 shape: {output.shape}") # 输出 shape: (2, 28, 28, 32) # batch_size 不变,height/width 因 padding='same' 保持不变,channels 变为 filters=32 # 查看卷积核权重 shape print(f"卷积核权重 shape: {conv_layer.kernel.shape}") # 卷积核权重 shape: (3, 3, 3, 32) # (kernel_height, kernel_width, input_channels, output_filters) ``` **不同 padding 和 strides 的影响:** ```python # padding='valid' 时的输出尺寸计算 conv_valid = tf.keras.layers.Conv2D(filters=16, kernel_size=3, strides=2, padding='valid') out_valid = conv_valid(x) print(f"padding='valid' 输出 shape: {out_valid.shape}") # 输出 shape: (2, 13, 13, 16) # 计算公式:output = (input - kernel_size + 2*padding) / strides + 1 # height = (28 - 3 + 0) / 2 + 1 = 13 # padding='same' 时的输出尺寸 conv_same = tf.keras.layers.Conv2D(filters=16, kernel_size=3, strides=2, padding='same') out_same = conv_same(x) print(f"padding='same' 输出 shape: {out_same.shape}") # 输出 shape: (2, 14, 14, 16) # 当 padding='same' 时,输出尺寸为 ceil(input_size / strides) ```
MaxPool2D 最大池化层
### API 定义 ```python tf.keras.layers.MaxPool2D( pool_size=(2, 2), strides=None, padding='valid', data_format=None, name=None, **kwargs ) ```
### 参数说明 - pool_size - int/tuple - 池化窗口的大小。默认为 `(2, 2)`,表示在 2x2 窗口内取最大值 - strides - int/tuple/None - 池化的步长。默认为 `pool_size`,表示不重叠池化 - padding - str - 填充模式:`'valid'`(默认)或 `'same'` - data_format - str - 输入数据的格式:`'channels_last'`(默认)或 `'channels_first'` - name - str - 层的名称
### 使用示例 ```python import tensorflow as tf import numpy as np # 创建输入数据:batch_size=1, height=8, width=8, channels=1 x = np.arange(64).reshape(1, 8, 8, 1).astype(np.float32) print(f"输入 shape: {x.shape}") print(f"输入数据:\n{x[0, :, :, 0]}") # 输出 shape: (1, 8, 8, 1) # 创建 MaxPool2D 层 maxpool_layer = tf.keras.layers.MaxPool2D( pool_size=(2, 2), # 2x2 池化窗口 strides=None, # 默认为 pool_size padding='valid' # 不填充 ) # 应用池化 output = maxpool_layer(x) print(f"\n输出 shape: {output.shape}") # 输出 shape: (1, 4, 4, 1) # 尺寸计算:output = input / pool_size = 8 / 2 = 4 print(f"输出数据:\n{output[0, :, :, 0]}") ``` **不同池化参数的效果:** ```python # 使用 strides=1 的池化(滑动窗口) maxpool_stride1 = tf.keras.layers.MaxPool2D(pool_size=2, strides=1, padding='same') out_stride1 = maxpool_stride1(x) print(f"strides=1 输出 shape: {out_stride1.shape}") # 输出 shape: (1, 8, 8, 1) # strides=1 时输出尺寸保持不变(padding='same') # 使用更大的池化窗口 maxpool_4x4 = tf.keras.layers.MaxPool2D(pool_size=4, strides=4, padding='valid') out_4x4 = maxpool_4x4(x) print(f"pool_size=4 输出 shape: {out_4x4.shape}") # 输出 shape: (1, 2, 2, 1) # 尺寸计算:8 / 4 = 2 ```
Flatten 展平层
### API 定义 ```python tf.keras.layers.Flatten( data_format=None, **kwargs ) ```
### 参数说明 - data_format - str - 输入数据的格式:`'channels_last'`(默认)或 `'channels_first'` **功能说明:** Flatten 层将多维输入(除了 batch 维度)展平为一维向量。通常用于从卷积层过渡到全连接层。
### 使用示例 ```python import tensorflow as tf import numpy as np # 创建输入数据:batch_size=2, height=4, width=4, channels=3 x = np.random.randn(2, 4, 4, 3).astype(np.float32) print(f"输入 shape: {x.shape}") # 输出 shape: (2, 4, 4, 3) # 创建 Flatten 层 flatten_layer = tf.keras.layers.Flatten() # 应用展平 output = flatten_layer(x) print(f"输出 shape: {output.shape}") # 输出 shape: (2, 48) # batch_size 保持不变,其余维度相乘:4 * 4 * 3 = 48 # 验证展平后的元素数量 print(f"展平前元素总数: {x.shape[1] * x.shape[2] * x.shape[3]}") # 展平前元素总数: 48 # 典型使用场景:Conv -> Pool -> Flatten -> Dense model = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Conv2D(64, (3, 3), activation='relu'), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Flatten(), # 将 (batch, 7, 7, 64) 展平为 (batch, 3136) tf.keras.layers.Dense(64, activation='relu'), tf.keras.layers.Dense(10, activation='softmax') ]) # 查看各层输出形状 for layer in model.layers: print(f"{layer.__class__.__name__}: 输入 shape -> 输出 shape") ```
Dense 全连接层
### API 定义 ```python tf.keras.layers.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 - int - 输出空间的维度(即神经元数量) - activation - str/callable - 激活函数。如 `'relu'`、`'sigmoid'`、`'softmax'` 或 `None`(线性) - use_bias - bool - 是否使用偏置项 - kernel_initializer - str/callable - 权重矩阵的初始化器 - bias_initializer - str/callable - 偏置向量的初始化器 - kernel_regularizer - str/callable - 权重的正则化函数 - bias_regularizer - str/callable - 偏置的正则化函数 - activity_regularizer - str/callable - 输出的正则化函数 - kernel_constraint - str/callable - 权重的约束函数 - bias_constraint - str/callable - 偏置的约束函数 **功能说明:** Dense 层实现全连接操作:`output = activation(dot(input, kernel) + bias)`
### 使用示例 ```python import tensorflow as tf import numpy as np # 创建输入数据:batch_size=3, features=5 x = np.random.randn(3, 5).astype(np.float32) print(f"输入 shape: {x.shape}") # 输出 shape: (3, 5) # 创建 Dense 层 dense_layer = tf.keras.layers.Dense( units=10, # 输出 10 个神经元 activation='relu', # ReLU 激活 use_bias=True # 使用偏置 ) # 应用全连接 output = dense_layer(x) print(f"输出 shape: {output.shape}") # 输出 shape: (3, 10) # batch_size 保持不变,features 变为 units=10 # 查看权重和偏置的 shape print(f"权重 matrix shape: {dense_layer.kernel.shape}") # 权重 matrix shape: (5, 10) # (input_features, output_units) print(f"偏置 vector shape: {dense_layer.bias.shape}") # 偏置 vector shape: (10,) ``` **常见激活函数:** ```python # ReLU 激活(最常用) dense_relu = tf.keras.layers.Dense(64, activation='relu') # Sigmoid 激活(用于二分类输出) dense_sigmoid = tf.keras.layers.Dense(1, activation='sigmoid') # Softmax 激活(用于多分类输出) dense_softmax = tf.keras.layers.Dense(10, activation='softmax') # Tanh 激活 dense_tanh = tf.keras.layers.Dense(32, activation='tanh') # 线性(无激活) dense_linear = tf.keras.layers.Dense(16, activation=None) ```
Dropout 随机失活层
### API 定义 ```python tf.keras.layers.Dropout( rate, noise_shape=None, seed=None, **kwargs ) ```
### 参数说明 - rate - float - 丢弃比例。取值范围 [0, 1),表示每个元素被丢弃的概率。如 `rate=0.5` 表示丢弃 50% 的神经元 - noise_shape - tuple - 用于确定二值 dropout mask 的形状 - seed - int - 随机种子 **功能说明:** Dropout 是一种正则化技术,在训练过程中随机将部分神经元的输出设为 0,防止模型过拟合。
### 使用示例 ```python import tensorflow as tf import numpy as np # 创建输入数据 x = np.random.randn(2, 10).astype(np.float32) print(f"输入 shape: {x.shape}") # 输出 shape: (2, 10) # 创建 Dropout 层 dropout_layer = tf.keras.layers.Dropout( rate=0.5 # 丢弃 50% 的神经元 ) # 训练模式下应用 Dropout tf.keras.backend.set_learning_phase(1) # 训练模式 output_train = dropout_layer(x, training=True) print(f"训练模式输出 shape: {output_train.shape}") # 输出 shape: (2, 10) # 约 50% 的元素被置为 0 # 推理模式下不应用 Dropout output_inference = dropout_layer(x, training=False) print(f"推理模式输出 shape: {output_inference.shape}") # 输出 shape: (2, 10) # 输出保持不变(除了缩放) ``` **典型使用场景:** ```python # 典型的网络结构:Conv -> Pool -> Dropout -> Dense model = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Dropout(0.25), # 在卷积层后使用较小的 dropout tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dropout(0.5), # 在全连接层后使用较大的 dropout tf.keras.layers.Dense(10, activation='softmax') ]) ```
BatchNormalization 批归一化层
### API 定义 ```python tf.keras.layers.BatchNormalization( axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', moving_variance_initializer='ones', beta_regularizer=None, gamma_regularizer=None, beta_constraint=None, gamma_constraint=None, synchronized=False, **kwargs ) ```
### 参数说明 - axis - int - 需要归一化的轴。默认为 -1(通道维度) - momentum - float - 移动平均的动量 - epsilon - float - 防止除零的小常数 - center - bool - 是否在输出中加上 beta 偏移 - scale - bool - 是否乘以 gamma 缩放 - beta_initializer - str/callable - beta 参数的初始化器 - gamma_initializer - str/callable - gamma 参数的初始化器 **功能说明:** 批归一化通过对每个 batch 的数据进行标准化(减均值、除方差),加速训练并提高模型稳定性。
### 使用示例 ```python import tensorflow as tf import numpy as np # 创建输入数据:batch_size=4, height=4, width=4, channels=3 x = np.random.randn(4, 4, 4, 3).astype(np.float32) print(f"输入 shape: {x.shape}") # 输出 shape: (4, 4, 4, 3) # 创建 BatchNormalization 层 bn_layer = tf.keras.layers.BatchNormalization() # 应用批归一化 output = bn_layer(x, training=True) print(f"输出 shape: {output.shape}") # 输出 shape: (4, 4, 4, 3) # shape 保持不变,但数据被归一化 ``` **典型使用场景:** ```python # 在 Conv 层后使用 BatchNormalization model = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), input_shape=(28, 28, 1)), tf.keras.layers.BatchNormalization(), # 在激活前使用 BN tf.keras.layers.Activation('relu'), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Conv2D(64, (3, 3)), tf.keras.layers.BatchNormalization(), tf.keras.layers.Activation('relu'), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Flatten(), tf.keras.layers.Dense(128), tf.keras.layers.BatchNormalization(), tf.keras.layers.Activation('relu'), tf.keras.layers.Dense(10, activation='softmax') ]) ```
综合示例:构建简单 CNN
### 网络结构 下面构建一个用于 MNIST 手写数字识别的简单 CNN 网络,整合以上介绍的所有组件: ``` 输入层: (28, 28, 1) ↓ Conv2D(32, 3×3, relu) ↓ shape: (28, 28, 32) MaxPool2D(2×2) ↓ shape: (14, 14, 32) Conv2D(64, 3×3, relu) ↓ shape: (14, 14, 64) MaxPool2D(2×2) ↓ shape: (7, 7, 64) Flatten ↓ shape: (3136,) Dense(128, relu) ↓ shape: (128,) Dropout(0.5) ↓ Dense(10, softmax) ↓ shape: (10,) ```
### 完整代码 ```python import tensorflow as tf from tensorflow.keras import layers, models # 1. 加载数据集 (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data() # 2. 数据预处理 x_train = x_train.reshape(-1, 28, 28, 1).astype('float32') / 255.0 x_test = x_test.reshape(-1, 28, 28, 1).astype('float32') / 255.0 print(f"训练集 shape: {x_train.shape}") # (60000, 28, 28, 1) print(f"测试集 shape: {x_test.shape}") # (10000, 28, 28, 1) # 3. 构建 CNN 模型 model = models.Sequential([ # 第一卷积块 layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)), layers.MaxPooling2D((2, 2)), # 第二卷积块 layers.Conv2D(64, (3, 3), activation='relu'), layers.MaxPooling2D((2, 2)), # 展平并连接全连接层 layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dropout(0.5), # 输出层 layers.Dense(10, activation='softmax') ]) # 4. 查看模型结构 model.summary() ``` **模型输出示例:** ``` Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 28, 28, 32) 320 max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0 conv2d_1 (Conv2D) (None, 14, 14, 64) 18496 max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0 flatten (Flatten) (None, 3136) 0 dense (Dense) (None, 128) 401536 dropout (Dropout) (None, 128) 0 dense_1 (Dense) (None, 10) 1290 ================================================================= Total params: 421,642 Trainable params: 421,642 Non-trainable params: 0 ```
### 训练与评估 ```python # 5. 编译模型 model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'] ) # 6. 训练模型 history = model.fit( x_train, y_train, epochs=5, batch_size=64, validation_split=0.2, verbose=1 ) # 7. 评估模型 test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0) print(f'\n测试集准确率: {test_acc:.4f}') # 8. 进行预测 predictions = model.predict(x_test[:5]) predicted_classes = tf.argmax(predictions, axis=1) print(f"前5个样本的预测结果: {predicted_classes.numpy()}") print(f"前5个样本的真实标签: {y_test[:5]}") # 9. 绘制训练曲线(可选) import matplotlib.pyplot as plt plt.figure(figsize=(12, 4)) # 损失曲线 plt.subplot(1, 2, 1) plt.plot(history.history['loss'], label='Train Loss') plt.plot(history.history['val_loss'], label='Val Loss') plt.title('Training and Validation Loss') plt.xlabel('Epoch') plt.ylabel('Loss') plt.legend() # 准确率曲线 plt.subplot(1, 2, 2) plt.plot(history.history['accuracy'], label='Train Accuracy') plt.plot(history.history['val_accuracy'], label='Val Accuracy') plt.title('Training and Validation Accuracy') plt.xlabel('Epoch') plt.ylabel('Accuracy') plt.legend() plt.show() ``` **预期输出:** ``` Epoch 1/5 750/750 [==============================] - 10s 13ms/step - loss: 0.1864 - accuracy: 0.9436 - val_loss: 0.0645 - val_accuracy: 0.9811 ... Epoch 5/5 750/750 [==============================] - 9s 12ms/step - loss: 0.0386 - accuracy: 0.9879 - val_loss: 0.0367 - val_accuracy: 0.9903 测试集准确率: 0.9915 前5个样本的预测结果: [7 2 1 0 4] 前5个样本的真实标签: [7 2 1 0 4] ```
参考