
在构建机器学习模型时,我们常常倾向于使用更深、更复杂的神经网络来解决问题。然而,对于某些特定类型的回归问题,例如简单的线性关系(y = ax + b)或多项式关系(y = ax^3 + bx^2 + cx + d),过度复杂的模型结构反而可能导致训练困难、收敛缓慢,甚至无法达到理想的预测精度。
例如,当尝试使用一个包含多个隐藏层和Dropout层的深度神经网络来拟合y=10x或y=x^3这样的简单函数时,模型可能会表现出极高的损失值(如2000到200000),即使尝试不同的激活函数(如ReLU或tanh)也无济于事。这通常是因为模型被赋予了学习过于复杂的特征映射任务,而这些任务对于底层数据关系来说是不必要的。原始模型示例如下:
import tensorflow as tf
from tensorflow.keras import layers, models
def PolynomialModel_Complex():
inp = layers.Input((1))
l = layers.Dense(16, activation='tanh')(inp)
l = layers.Dense(8, activation='tanh')(l)
l = layers.Dropout(.5)(l)
l = layers.Dense(4, activation='tanh')(l)
l = layers.Dropout(.5)(l)
output = layers.Dense(1, activation='tanh')(l) # 注意这里的tanh激活函数
return models.Model(inp, output)
# 假设要拟合 y = 10x
# model_complex = PolynomialModel_Complex()
# model_complex.compile(loss='mean_squared_error', optimizer='adam')
# x_data = tf.linspace(-10, 10, 1000)
# y_data = 10.0 * x_data
# model_complex.fit(x_data, y_data, epochs=100) # 可能会观察到高损失上述模型的问题在于:
解决上述问题的关键在于理解多项式回归的本质:它实际上是线性回归的一种形式,只是作用于原始特征的多项式变换上。例如,对于函数y = ax^3 + bx^2 + cx + d,我们可以将其视为对特征向量[x^0, x^1, x^2, x^3]进行线性组合。这里的x^0即为常数项。
因此,与其让神经网络尝试从原始输入x中学习如何生成x^2或x^3这样的复杂特征,不如我们直接在输入阶段就将这些多项式特征计算好,然后提供给一个简单的线性模型。这样,模型只需学习这些多项式特征的线性组合权重即可。
我们将通过手动创建多项式特征并结合一个极简的TensorFlow模型来演示这一方法。
对于一个degree次的多项式回归问题,我们需要的输入特征是[x^0, x^1, ..., x^degree],即degree + 1个特征。模型本身只需要一个简单的全连接层(Dense层)来学习这些特征的线性组合,且输出层不应使用限制范围的激活函数(默认的线性激活即可)。
import tensorflow as tf
from tensorflow.keras import layers, models, optimizers
def PolynomialModel(degree):
"""
构建一个用于多项式回归的简单Keras模型。
输入层大小为 degree + 1,对应 [x^0, x^1, ..., x^degree]
输出层为单个神经元,使用线性激活。
"""
inp = layers.Input((degree + 1)) # 输入大小为 degree + 1
out = layers.Dense(1, activation='linear')(inp) # 线性激活是回归的默认选择
return models.Model(inp, out, name=f"PolynomialRegressor_Degree{degree}")这个模型非常简洁,只包含一个输入层和一个输出层。Dense(1, activation='linear')意味着它将执行一个线性回归操作:y_pred = w_0*x^0 + w_1*x^1 + ... + w_degree*x^degree + b。
假设我们要拟合函数y = x^3。这是一个三阶多项式。因此,我们的degree为3,输入特征需要包括x^0, x^1, x^2, x^3。
# 设定多项式次数
degree = 3
# 生成训练数据
x_data = tf.linspace(-20.0, 20.0, 1000) # 从-20到20生成1000个点
y_true = x_data**3 # 目标函数 y = x^3
# 构建多项式特征矩阵 X
# X 的每一行是一个样本的特征向量 [x^0, x^1, x^2, x^3]
X_features = tf.transpose(tf.convert_to_tensor([x_data**p for p in range(degree + 1)], dtype=tf.float32))
# 确保y_true也是float32
y_true = tf.cast(y_true, dtype=tf.float32)
print(f"X_features shape: {X_features.shape}") # 预期 (1000, 4)
print(f"y_true shape: {y_true.shape}") # 预期 (1000,)现在,我们可以使用构建好的模型和准备好的数据进行训练。我们将使用均方误差(MSE)作为损失函数,并选择Adam优化器。
# 实例化模型
model = PolynomialModel(degree)
# 编译模型
model.compile(loss='mean_squared_error', optimizer=optimizers.Adam(learning_rate=0.1))
# 打印模型摘要,查看参数数量
model.summary()
# 训练模型
print("\n开始训练模型...")
history = model.fit(X_features, y_true, epochs=200, verbose=0) # verbose=0 减少输出
# 打印最终损失
print(f"最终训练损失: {history.history['loss'][-1]:.2e}")
# 进行预测
# 预测 x=4 时 y 的值,即 4^3 = 64
test_x_features = tf.constant([[4**0, 4**1, 4**2, 4**3]], dtype=tf.float32)
prediction_4 = model.predict(test_x_features)
print(f"\n预测 4^3 的结果: {prediction_4[0][0]:.2f} (实际值: 64)")
# 预测 x=3 时 y 的值,即 3^3 = 27
test_x_features_3 = tf.constant([[3**0, 3**1, 3**2, 3**3]], dtype=tf.float32)
prediction_3 = model.predict(test_x_features_3)
print(f"预测 3^3 的结果: {prediction_3[0][0]:.2f} (实际值: 27)")训练输出示例: (实际训练过程中的损失值会快速下降)
Model: "PolynomialRegressor_Degree3" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 4)] 0 dense (Dense) (None, 1) 5 ================================================================= Total params: 5 (20.00 Byte) Trainable params: 5 (20.00 Byte) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________ 开始训练模型... 最终训练损失: 1.44e-11 预测 4^3 的结果: 64.00 (实际值: 64) 预测 3^3 的结果: 27.00 (实际值: 27)
从model.summary()可以看出,模型只有5个参数(4个权重对应x^0到x^3,1个偏置项),这与我们期望的线性模型完全吻合。训练损失迅速降至极低水平(1.44e-11),预测结果也与真实值高度一致,证明了这种方法的有效性。
本文通过一个具体的TensorFlow示例,展示了在处理简单多项式回归问题时,如何通过多项式特征工程和简洁的线性模型来替代复杂的深度神经网络。这种方法不仅能够显著提升模型的训练效率和预测精度,还能使模型更具可解释性。核心思想是:当数据的底层关系可以通过简单的数学变换(如多项式展开)来表示时,直接提供这些变换后的特征给模型,比让模型自己去“发现”这些特征更为高效。在实践中,我们应始终从最简单的模型开始,并根据数据的复杂性逐步增加模型的复杂度。
以上就是TensorFlow中高效实现多项式回归:从深度网络到特征工程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号