You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于TensorFlow的CNN回归模型精度优化:预测线性函数斜率

问题分析与改进建议

我尝试用TensorFlow构建CNN解决回归任务:给定线性函数y=kx的x取值向量和对应y值向量,预测斜率k。生成数据集、模型架构及训练代码如下,训练时验证误差始终小于训练误差,测试集MAE为3.37,精度未达预期,以下是问题分析与改进方案:

一、数据集生成代码

import random
import numpy as np
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow import models, layers
from tensorflow.keras.optimizers import Adam

N_data = 50000 # number of data points

X = [] # features (x and y values)
y = [] # labels (slopes)

for _ in range(N_data):
    # Randomly choose the x values:
    x_min = 200*random.random()-100
    xs = np.linspace(x_min, x_min + 10)

    # Randomly choose the slope:
    k = 200*random.random()-100

    # Calculate the function values:
    ys = k*xs
    
    # Store the data:
    X.append(xs.tolist() + ys.tolist())
    y.append(k)
    
X = np.array(X)
y = np.array(y)

tf.random.set_seed(41)

# Split the data into training, validation and test sets:
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.2, random_state=41)

# Split the temporary set into validation and test sets:
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=41)

二、原模型架构与训练代码

model = models.Sequential()

# Data normalization layer
model.add(layers.InputLayer(input_shape=(X[0].shape[0], 1)))
model.add(layers.BatchNormalization())

# Convolutional block 1:
model.add(layers.Conv1D(32, 3, activation='relu'))
model.add(layers.AveragePooling1D(2))

# Convolutional block 2:
model.add(layers.Conv1D(64, 3, activation='relu'))
model.add(layers.AveragePooling1D(2))

# Convolutional block 3:
model.add(layers.Conv1D(128, 3, activation='relu'))
model.add(layers.MaxPooling1D(2))

model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(1))
model.compile(optimizer=Adam(learning_rate=0.01),
              loss='mean_squared_error',
              metrics=['mae'])

history = model.fit(X_train, y_train, epochs=50, batch_size = 16, 
                    validation_data=(X_val, y_val))

训练与验证MAE曲线显示:验证MAE始终低于训练MAE,两者随训练轮次下降后趋于平稳,最终训练MAE约3.5,验证MAE约3.3,测试集MAE为3.37。


三、问题分析

1. 验证误差低于训练误差的原因

  • BatchNormalization行为差异:训练时BN层使用当前batch的均值/方差做归一化,小batch(16)会引入统计噪声,导致训练误差偏高;验证时BN层使用训练阶段累积的全局统计值,归一化更稳定,误差更低。
  • 误差计算方式差异:训练MAE是每个batch计算后平均,包含batch内的波动;验证MAE是在整个验证集上计算,结果更平滑。

2. 精度不足的核心问题

(1)输入数据格式错误

Conv1D要求输入为三维张量(样本数, 序列长度, 特征数),但原代码中X是二维数组(50000,100),与InputLayer(input_shape=(100,1))的要求不匹配,会导致模型无法正确学习序列特征。此外,将xs和ys拼接成一维向量的方式,破坏了(x,y)的对应关系,CNN无法捕捉每个点的斜率特征。

(2)模型架构与任务不匹配

该任务本质是线性拟合问题,复杂的CNN堆叠反而会引入冗余计算和拟合噪声。原模型的多层卷积+池化会丢失部分关键的线性关系信息。

(3)训练设置不合理

  • 学习率0.01过高,Adam优化器默认学习率为0.001,过高的学习率会导致模型训练不稳定,难以收敛到最优解;
  • batch size=16过小,加剧BN层的统计噪声,影响训练稳定性;
  • 训练轮次可能不足,从曲线看训练误差仍有下降空间。

四、改进方案

1. 修正输入数据格式

  • 添加通道维度:将二维输入转为三维,匹配Conv1D要求:
# 为所有数据集添加通道维度
X_train = X_train[..., np.newaxis]
X_val = X_val[..., np.newaxis]
X_test = X_test[..., np.newaxis]
  • 优化输入结构:将每个样本组织为(50,2)的序列,每个时间步存储对应的(x,y)对,让CNN直接学习点对关系:
# 修改数据生成的存储逻辑
X.append(np.stack([xs, ys], axis=1).tolist())
# 对应调整输入层
model.add(layers.InputLayer(input_shape=(50, 2)))

2. 简化或调整模型架构

  • 最优选择:线性模型/轻量MLP:因为任务是线性拟合,直接用线性层即可达到接近0的MAE:
model = models.Sequential([
    layers.InputLayer(input_shape=(50, 2)),
    layers.Flatten(),
    layers.Dense(1)
])
  • 若坚持用CNN:简化架构,用1x1卷积捕捉点对特征:
model = models.Sequential([
    layers.InputLayer(input_shape=(50, 2)),
    layers.BatchNormalization(),
    layers.Conv1D(32, 1, activation='relu'),
    layers.GlobalAveragePooling1D(),
    layers.Dense(1)
])

3. 优化训练设置

  • 降低学习率:改为0.001或0.0001;
  • 增大batch size:调整为64或128,提升训练稳定性;
  • 添加早停回调:防止过拟合,同时确保模型收敛到最优状态:
from tensorflow.keras.callbacks import EarlyStopping

early_stop = EarlyStopping(monitor='val_mae', patience=10, restore_best_weights=True)
history = model.fit(X_train, y_train, epochs=100, batch_size=64, 
                    validation_data=(X_val, y_val), callbacks=[early_stop])

4. 额外优化

  • 全局归一化:对输入的x和y做标准化(均值0,方差1),提升收敛速度;
  • 标签归一化:将k归一化到[-1,1],训练后再反归一化,帮助模型优化;
  • 基准验证:先用线性模型测试,若线性模型能达到极低MAE,说明数据无问题,再调试CNN模型。

内容的提问来源于stack exchange,提问作者mathslover

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 15:42:03