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

TensorFlow模型无法训练实现简单乘法预测问题求助

问题描述

我计划先构建一个能预测简单乘法的神经网络,后续再替换成其他公式。原以为实现起来很简单,代码也不复杂,但模型完全无法训练,几乎学不到任何东西,预测结果毫无合理性。

我生成-100到100之间的两个数作为输入,将它们的乘积作为正确结果。程序能正常运行并完成训练轮次,但无法得到有效的预测结果。我猜测是模型搭建存在问题,当前使用两个含1024个神经元的全连接层,尝试调整层数和神经元数量后,仅改变了训练时长,问题仍未解决。

以下是我的代码:

import tensorflow as tf

import numpy as np
import random

import os.path


def compileModel():
    model = tf.keras.Sequential()
    model.add( tf.keras.layers.InputLayer(shape=(2,)) )
    model.add( tf.keras.layers.Dense(1024) )
    model.add( tf.keras.layers.Dense(1024) )
    model.add( tf.keras.layers.Dense(units=1) )
    
    model.compile(loss="mean_squared_error", optimizer="adam", metrics=["mse"])
    
    return model

def generateData(num):
    vals = np.zeros((num, 2))
    res = np.zeros(num)
    for i in range(num):
        a = random.uniform(-100,100)
        b = random.uniform(-100,100)
        c = a*b
        
        vals[i][0] = a
        vals[i][1] = b
        res[i] = c
    return (vals, res)


modelFilename = 'saved_model.keras'
runTraining = False

if not runTraining and not os.path.isfile(modelFilename):
    runTraining = True

if runTraining:
    trainData, trainRes = generateData(100000)
    
    model = compileModel()
    
    model.fit(x=trainData, y=trainRes, epochs=12, batch_size=100)
    model.save(filepath=modelFilename)
else:
    model = tf.keras.models.load_model(modelFilename)


testData, testRes = generateData(1000)
model.evaluate(x=testData, y=testRes)

print(testData.shape)

res = model.predict(testData[0:1])
print(testData[0:1])
print(testRes[0:1])
print(res)
问题分析与解决方案

你的模型无法学习乘法的核心原因有几个,逐个解决就能改善效果:

1. 缺少激活函数导致模型表达能力受限

当前的全连接层没有添加激活函数,相当于所有层都是线性变换。而乘法是非线性任务,线性模型的组合依然是线性的,根本无法拟合乘法这种非线性关系。

解决办法:在两个隐藏的Dense层后添加非线性激活函数,比如ReLU,或者更适合回归任务的Swish:

def compileModel():
    model = tf.keras.Sequential()
    model.add( tf.keras.layers.InputLayer(shape=(2,)) )
    model.add( tf.keras.layers.Dense(1024, activation='relu') )  # 添加激活函数
    model.add( tf.keras.layers.Dense(1024, activation='relu') )  # 添加激活函数
    model.add( tf.keras.layers.Dense(units=1) )
    
    model.compile(loss="mean_squared_error", optimizer="adam", metrics=["mse"])
    
    return model

2. 输入输出的数值范围差异过大

输入是-100到100的数,乘积的范围是-10000到10000,数值跨度太大,会导致梯度更新不稳定,模型难以收敛。

解决办法:对输入和输出做归一化处理,把数值压缩到0-1或-1-1的区间:

  • 修改generateData函数,对输入和输出做标准化:
def generateData(num):
    vals = np.zeros((num, 2))
    res = np.zeros(num)
    for i in range(num):
        a = random.uniform(-100,100)
        b = random.uniform(-100,100)
        c = a*b
        
        # 归一化输入到[-1, 1]
        vals[i][0] = a / 100.0
        vals[i][1] = b / 100.0
        # 归一化输出到[-1, 1]
        res[i] = c / 10000.0
    return (vals, res)
  • 预测时记得反归一化,把结果还原成实际乘积:
res = model.predict(testData[0:1])
# 反归一化
actual_pred = res * 10000.0
print(testData[0:1] * 100.0)  # 还原输入的原始值
print(testRes[0:1] * 10000.0)  # 还原真实结果
print(actual_pred)

3. 训练参数可以微调

  • 可以把学习率调小一点,比如optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),避免梯度震荡。
  • 增加训练轮次到20-30轮,或者添加EarlyStopping回调,防止过拟合同时确保模型收敛:
from tensorflow.keras.callbacks import EarlyStopping

# 训练时添加回调
early_stop = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)
model.fit(x=trainData, y=trainRes, epochs=30, batch_size=100, validation_split=0.1, callbacks=[early_stop])

4. 模型结构可以简化

不需要1024这么多神经元,过多的神经元反而容易导致过拟合或训练效率低下。可以尝试调整为:

def compileModel():
    model = tf.keras.Sequential()
    model.add( tf.keras.layers.InputLayer(shape=(2,)) )
    model.add( tf.keras.layers.Dense(64, activation='relu') )
    model.add( tf.keras.layers.Dense(32, activation='relu') )
    model.add( tf.keras.layers.Dense(units=1) )
    
    model.compile(loss="mean_squared_error", optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001), metrics=["mse"])
    
    return model

按照以上修改后,模型应该能有效学习乘法关系,预测结果会接近真实值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:34:53