神经网络实现除法遇未知秩形状错误及结果异常的解决求助
问题描述
尝试通过神经网络实现两数乘除法运算:先训练加减、单个数平方的模型,除法通过「被除数 × 除数倒数」转换为乘法,利用公式 ab = [(a+b)² -a² -b²]/2 计算结果。乘法运行正常,但除法出现以下问题:
- 初始代码中
Ydiv = 1/Y时,报错:
Exception encountered when calling Sequential.call(). Cannot take the length of shape with unknown rank.
- 修改为
Ydiv = np.reciprocal(Y)后错误消失,但除法结果始终近似为某个固定值(每次运行固定值不同)。
原始代码:
import tensorflow as tf import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from tensorflow.keras import regularizers #Models for adding and subtracting two numbers num_train = 1000 X_train = np.random.rand(num_train, 2) y_train_add = X_train[:, 0] + X_train[:, 1] y_train_subtract = X_train[:, 0] - X_train[:, 1] model_add = Sequential( [ Dense(10), Dense(1) ] ) model_subtract = Sequential( [ Dense(10), Dense(1) ] ) batch_size = 32 epochs = 100 model_add.compile(loss = 'mse', optimizer='adam') model_add.fit(X_train, y_train_add, batch_size=batch_size, epochs=epochs, verbose = 1) model_subtract.compile(loss = 'mse', optimizer='adam') model_subtract.fit(X_train, y_train_subtract, batch_size=batch_size, epochs=epochs, verbose = 1) #Model for squaring a number x_train = np.random.random((10000,1))*100-50 y_train = np.square(x_train) model_sqr = Sequential( [ Dense(8, activation = 'relu', kernel_regularizer = regularizers.l2(0.001), input_shape = (1,)), Dense(8, activation = 'relu', kernel_regularizer = regularizers.l2(0.001)), Dense(1) ] ) batch_size = 64 epochs = 2000 model_sqr.compile(loss = 'mse', optimizer='adam') model_sqr.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose = 1) #Code for calculating the product and quotient of two numbers using models x = "n" while True: print("enter first num:") x = input() if x == "end": break print("Enter operation:") op= input() print("enter second num:") y = input() X = int(x) Y = int(y) Ydiv = 1/Y if op == "*": predicted_product = model_sqr.predict(model_add.predict(np.array([[X, Y]]))) - model_sqr.predict(np.array([X])) - model_sqr.predict(np.array([Y])) print(predicted_product/2) elif op =="/": predicted_quot = model_sqr.predict(model_add.predict(np.array([[X, Ydiv]]))) - model_sqr.predict(np.array([X])) - model_sqr.predict(np.array([Ydiv])) print(predicted_quot/2)
问题解答
1. 原错误产生的原因
model_sqr的输入要求是二维张量(形状为(None, 1)),对应训练时的输入x_train是(10000,1)的二维数组。
- 当使用
Ydiv = 1/Y时,Ydiv是Python float类型,np.array([Ydiv])生成的是一维数组(形状(1,)),TensorFlow无法识别该输入的维度(rank),因此抛出"Cannot take the length of shape with unknown rank"错误。 np.reciprocal(Y)返回的是numpy float标量,np.array([Ydiv])同样是一维数组,但numpy的类型转换让TensorFlow暂时绕过了维度检查,不过输入维度不匹配的问题依然存在,这也是后续结果固定的根源之一。
2. 除法运算问题的修正方案
核心修正点:
- 统一输入维度:所有传给
model_sqr.predict的输入必须是二维数组,即把np.array([X])改为np.array([[X]]),np.array([Ydiv])改为np.array([[Ydiv]])。 - 统一训练数据范围:加减模型的训练数据
X_train仅覆盖0-1区间,但平方模型覆盖-50到50,除法中输入的X(整数)和Ydiv(分数)大概率超出加减模型的训练范围,导致model_add预测X+Ydiv严重失真。需将加减模型的训练数据范围改为与平方模型一致:X_train = np.random.random((num_train,2))*100 -50 - 增加除数非零判断:避免除法运算中除数为0的崩溃。
- 可选优化:适当提升加减模型的拟合能力,比如增加神经元数量或层数,应对更大范围的输入。
修正后的关键代码片段:
# 修正加减模型训练数据范围 X_train = np.random.random((num_train,2))*100 -50 # 修正乘除法计算部分的输入维度与除数判断 if op == "*": # 所有predict输入改为二维数组 sum_ab = model_add.predict(np.array([[X, Y]])) sqr_sum = model_sqr.predict(sum_ab) sqr_a = model_sqr.predict(np.array([[X]])) sqr_b = model_sqr.predict(np.array([[Y]])) predicted_product = (sqr_sum - sqr_a - sqr_b)/2 print(predicted_product) elif op =="/": if Y == 0: print("Error: Divisor cannot be zero") continue Ydiv = 1.0/Y sum_a_invb = model_add.predict(np.array([[X, Ydiv]])) sqr_sum = model_sqr.predict(sum_a_invb) sqr_a = model_sqr.predict(np.array([[X]])) sqr_invb = model_sqr.predict(np.array([[Ydiv]])) predicted_quot = (sqr_sum - sqr_a - sqr_invb)/2 print(predicted_quot)
内容的提问来源于stack exchange,提问作者harry
相关产品推荐
相关产品推荐

