我编写了一个简单的多层感知器神经网络,并且得到了一些奇怪的准确性值,想再次检查一下。
这是我的预期设置:特征矩阵有913个样本和192个特征(913,192)。我分类的是两种结果,所以我的标签是二进制的,形状为(913,1)。有一个隐藏层,包含100个单元(目前)。所有激活函数都使用tanh,所有损失函数都使用L2正则化,并用SGD优化。
代码如下。这是在Python中使用Keras框架编写的(http://keras.io/),但我的问题并不特定于Keras
input_size = 192hidden_size = 100output_size = 1lambda_reg = 0.01learning_rate = 0.01num_epochs = 100batch_size = 10model = Sequential()model.add(Dense(input_size, hidden_size, W_regularizer=l2(lambda_reg), init='uniform'))model.add(Activation('tanh'))model.add(Dropout(0.5))model.add(Dense(hidden_size, output_size, W_regularizer=l2(lambda_reg), init='uniform'))model.add(Activation('tanh'))sgd = SGD(lr=learning_rate, decay=1e-6, momentum=0.9, nesterov=True)model.compile(loss='mean_squared_error', optimizer=sgd, class_mode="binary")history = History()model.fit(features_all, labels_all, batch_size=batch_size, nb_epoch=num_epochs, show_accuracy=True, verbose=2, validation_split=0.2, callbacks=[history])score = model.evaluate(features_all, labels_all, show_accuracy=True, verbose=1)
我想再次检查我编写的代码是否真的符合我的需求,包括参数选择和它们的数值等。
使用上面的代码,我得到的训练集和测试集准确率在50-60%左右。可能是我使用的特征不好,但我想测试一下可能出错的地方,所以我手动设置了所有标签和特征为可预测的值:
labels_all[:500] = 1labels_all[500:] = 0features_all[:500] = np.ones(192)*500features_all[500:] = np.ones(192)
所以我将前500个样本的标签设置为1,其余的标签设置为0。我手动将前500个样本的所有特征设置为500,其余样本的所有特征设置为1
当我运行这个时,我得到的训练准确率约为65%,验证准确率约为0%。我期望这两个准确率都非常高/几乎完美 – 这是错误的吗?我的想法是,具有极高值的特征都具有相同的标签(1),而具有低值的特征得到标签0
主要是我在想我的代码/模型是否有误,或者我的逻辑是否有问题。
回答:
我不熟悉那个库,所以我无法告诉你这是否正确实现,但看起来是合法的。
我认为你的问题在于激活函数 – tanh(500)=1 而 tanh(1)=0.76。这两个值之间的差异对我来说似乎太小了。试着在测试时使用-1代替500,并将你的真实数据归一化到大约[-2, 2]的范围。如果你需要完整的实数范围,尝试使用线性激活函数。如果你只关心实数的正半部分,我建议使用softplus或ReLU。我已经检查过,Keras提供了所有这些函数。
你也可以尝试对输出进行阈值处理 – 当期望1时回答0.75,当期望0时回答0.25是有效的,但可能会影响你的准确性。
此外,尝试调整你的参数。我可以根据自己的经验建议你使用以下参数:
- 学习率 = 0.1
- L2中的lambda = 0.2
- 轮数 = 250及以上
- 批量大小约为20-30
- 动量 = 0.1
- 学习率衰减约为10e-2或10e-3
我认为学习率、轮数、动量和lambda是这里最重要的因素 – 按从最重要到最不重要的顺序排列。
附注:我刚刚注意到你使用均匀分布初始化权重(这甚至是个词吗?我不是母语者…)。我无法告诉你为什么,但我的直觉告诉我这不是一个好主意。我会选择随机初始权重。