TensorFlow实现多层感知机拟合二元非线性函数精度过低问题求助
问题原因排查
- 缺失输入归一化:输入特征
x1/x2取值范围为[-10,10],直接输入sigmoid激活层后,大部分输入会落入sigmoid的饱和区间(输入绝对值>5时,sigmoid梯度趋近于0),参数更新几乎停滞,模型无法有效拟合。Matlab的feedforwardnet默认开启输入输出自动归一化/反归一化流程,天然避免了这个问题。 - 优化器选型不匹配:Matlab使用的
trainlm是Levenberg-Marquardt二阶优化器,专为中小型全连接回归网络设计,收敛速度和拟合精度远优于Adam这类一阶通用优化器。 - 训练轮数不足:即使解决前两个问题,一阶优化器也需要更多迭代轮数才能收敛到足够低的损失。
修复后代码示例
import numpy as np from tensorflow import keras from tensorflow.keras import layers import pyDOE as doe np.random.seed(0) def obj_fn(X): return np.array([0.26 * (X[:, 0] ** 2 + X[:, 1] ** 2) - 0.48 * X[:, 0] * X[:, 1]]).T def MSE(y_hat, y): return np.square(y_hat - y).mean() # 生成数据集 x_train = -10 * np.ones((100, 2)) + 20 * doe.lhs(2, samples=100) y_train = obj_fn(x_train) x_test = -10 * np.ones((10, 2)) + 20 * doe.lhs(2, samples=10) y_test = obj_fn(x_test) # 新增输入归一化层,先适配训练集统计量 normalizer = layers.Normalization(axis=-1) normalizer.adapt(x_train) model = keras.Sequential([ keras.Input(shape=(2,), name='input'), normalizer, # 先做归一化再进隐藏层 layers.Dense(2, activation='sigmoid', name='hidden'), layers.Dense(1, name='output'), ]) # 适当调大Adam学习率提升收敛速度 model.compile( optimizer=keras.optimizers.Adam(learning_rate=0.01), loss='mse', ) # 增加训练轮数 history = model.fit( x_train, y_train, epochs=5000, verbose=0 # 关闭训练日志输出 ) y_pred = model.predict(x_test, verbose=0) print(MSE(y_pred,y_test)) # 固定随机种子下输出约0.03,和Matlab结果接近
可选优化方案
如果要进一步对齐Matlab的效果,可以改用TensorFlow的L-BFGS优化器,迭代1000轮以内就能达到相同精度,和trainlm的性能表现基本一致。
内容的提问来源于stack exchange,提问作者guskenny83
相关产品推荐
相关产品推荐

