如何训练神经网络以正确求解a+b*c/d类型的四则运算表达式?
问题分析与解决方案
核心问题
你的代码存在三个致命问题,导致无法正确求解四则运算:
- 无训练流程:当前神经网络的权重是固定值
[0.5, 0.5, 0.5],完全没有通过数据学习运算规则,只是做了一次无意义的点积计算。 - 运算顺序错误:手动按从左到右的顺序执行运算符,完全忽略了四则运算的优先级(先乘除后加减),导致计算逻辑本身错误。
- 输入逻辑错误:神经网络没有接收运算符信息,根本不知道需要执行哪些运算,输入仅包含部分操作数,无法学习运算映射关系。
解决方案:从零构建可训练的四则运算神经网络
要让神经网络学会求解四则运算,需要完成数据生成、网络架构设计、训练流程实现三个核心步骤,以下是完整实现:
1. 数据生成:生成带标签的四则运算样本
生成大量包含操作数、运算符的表达式,同时计算出正确结果作为训练标签,自动处理运算优先级。
2. 网络架构:用MLP学习运算映射
针对简单四则运算(如a op1 b op2 c形式),将操作数和运算符编码为网络输入,用多层感知机(MLP)学习从输入到结果的映射。
3. 训练流程:定义损失函数与优化器
回归问题用均方误差(MSE)作为损失函数,用Adam优化器更新权重,完成训练。
完整可运行代码
import numpy as np from sklearn.model_selection import train_test_split from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from tensorflow.keras.optimizers import Adam # 生成四则运算训练样本 def generate_samples(num_samples=10000): samples = [] labels = [] operators = ['+', '-', '*', '/'] for _ in range(num_samples): # 生成3个操作数和2个运算符(对应a op1 b op2 c的形式) a = np.random.uniform(0.1, 100) b = np.random.uniform(0.1, 100) c = np.random.uniform(0.1, 100) op1 = np.random.choice(operators) op2 = np.random.choice(operators) # 构建表达式并计算正确结果(自动处理优先级) expr = f"{a}{op1}{b}{op2}{c}" try: result = eval(expr) # 编码运算符:+→0, -→1, *→2, /→3 op1_code = operators.index(op1) op2_code = operators.index(op2) # 输入特征:[a, op1_code, b, op2_code, c] samples.append([a, op1_code, b, op2_code, c]) labels.append(result) except ZeroDivisionError: continue return np.array(samples), np.array(labels) # 生成数据并划分训练/测试集 X, y = generate_samples(15000) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 构建MLP模型 model = Sequential([ Dense(64, activation='relu', input_shape=(5,)), Dense(32, activation='relu'), Dense(1) # 输出单个结果(回归任务) ]) # 编译模型 model.compile(optimizer=Adam(learning_rate=0.001), loss='mse') # 训练模型 print("开始训练...") history = model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.1) # 测试模型(用你的示例表达式) test_expr = "2+3*10/9" # 解析测试表达式 parts = [] current_num = "" for char in test_expr.replace(" ", ""): if char.isdigit() or char == '.': current_num += char else: parts.append(float(current_num)) parts.append(['+', '-', '*', '/'].index(char)) current_num = "" parts.append(float(current_num)) test_input = np.array([parts]) # 预测结果 pred_result = model.predict(test_input)[0][0] # 计算真实结果 true_result = eval(test_expr) print(f"\n测试表达式: {test_expr}") print(f"神经网络预测结果: {pred_result:.4f}") print(f"真实结果: {true_result:.4f}") print(f"误差: {abs(pred_result - true_result):.4f}")
关键说明
- 运算符编码:将运算符转换为数字编码,让神经网络能理解不同运算类型。
- 数据多样性:生成大量随机样本,覆盖不同操作数和运算符组合,确保网络能泛化。
- 回归任务:四则运算的结果是连续值,所以用MSE损失函数,输出层无激活函数。
- 优先级处理:通过
eval生成标签时自动遵循四则运算优先级,让网络学习到正确的运算逻辑。
如果需要处理更长的表达式,可以改用循环神经网络(LSTM)或Transformer来处理序列输入,这类模型更擅长处理变长的表达式序列。
内容的提问来源于stack exchange,提问作者krip
相关产品推荐
相关产品推荐

