我在Python v2.7中使用Keras v2.0.8(Tensorflow后端)进行实验,尝试创建小型神经网络来计算简单的算术函数(加法、减法、乘法等),但我有些困惑。下面的代码是我创建的一个网络,它生成了一组随机的整数训练数据集和对应的标签(两个输入相加的结果):
def create_data(low, high, examples): train_data = [] label_data = [] a = np.random.randint(low=low, high=high, size=examples, dtype='int') b = np.random.randint(low=low, high=high, size=examples, dtype='int') for i in range(0, examples): train_data.append([a[i], b[i]]) label_data.append((a[i] + b[i])) train_data = np.array(train_data) label_data = np.array(label_data) return train_data, label_dataX, y = create_data(0, 500, 10000)model = Sequential()model.add(Dense(3, input_dim=2))model.add(Dense(5, activation='relu'))model.add(Dense(3, activation='relu'))model.add(Dense(5, activation='relu'))model.add(Dense(1, activation='relu'))model.compile(optimizer='adam', loss='mean_squared_error', metrics=['accuracy'])model.fit(X, y, epochs=10, batch_size=10)test_data, _ = create_data(0, 500, 10)results = model.predict(test_data, batch_size=2)sq_error = []for i in range(0, len(test_data)): print 'test value:', test_data[i], 'result:', results[i][0], 'error:',\ '%.2f' %(results[i][0] - (test_data[i][0] + test_data[i][1])) sq_error.append((results[i][0] - (test_data[i][0] + test_data[i][1])))print '\n total rmse error: ', sqrt(np.sum(np.array(sq_error)))
这个网络训练得很好,没有产生意外的结果。然而,当我通过将两个输入相乘来创建训练数据时,每个epoch的模型损失保持在7,000,000,000左右,并且模型完全不收敛。用于此的创建数据的函数如下:
def create_data(low, high, examples): train_data = [] label_data = [] a = np.random.randint(low=low, high=high, size=examples, dtype='int') b = np.random.randint(low=low, high=high, size=examples, dtype='int') for i in range(0, examples): train_data.append([a[i], b[i]]) label_data.append((a[i] * b[i])) train_data = np.array(train_data) label_data = np.array(label_data) return train_data, label_data
当我使用单个输入整数的训练数据并通过平方输入数据来创建标签时,我也遇到了同样的问题。然而,当我仅将单个输入乘以一个常数值或进行加减常数操作时,它工作得很好。
我有两个问题:
1) 为什么会这样?我认为这与神经网络的基本原理有关,但我无法弄明白。
2) 我如何调整这段代码来训练一个能够将两个输入数字相乘的模型。
目前的网络架构(2 – 3 – 5 – 3 – 5 – 1)是相当随机的。我尝试了很多不同层的和不同神经元的架构,这一个碰巧在我写这段文字时出现在我的屏幕上,并且在两个输入相加时达到了100%的准确率。
回答:
这是由于训练数据中的大数值导致的大梯度更新引起的。在使用神经网络时,你首先应该确保训练数据落在较小的范围内(通常是[-1,1]或[0,1]),以帮助优化过程并防止破坏性的梯度更新。因此,你应该首先对数据进行归一化。在这种情况下,一个好的候选方法是对数归一化。
此外,Keras中的'accuracy'
指标是用于分类问题的。对于回归问题,使用它没有意义,相反,最好使用相关的指标,如“平均绝对误差”或'mae'
。