我正在学习Keras,并创建了一个简单的网络。特征数据是[1, 2, 3, 4, 5],标签是[7, 9, 11, 13, 15] – 或者说是一条斜率为2,截距为5的直线(Y = X * 2 + 5)。
这是Keras网络的代码:
# simple keras example# # This solves for a lineimport numpy as npimport keras# configuration variablessamples = 5base = 1slope = 2intercept = 5# hyper-parameterslearning_rate = 0.01epochs = 2000model = keras.Sequential()model.add(keras.layers.Dense(1, input_dim=1, activation=keras.activations.linear))sgd = keras.optimizers.SGD(learning_rate=learning_rate)model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['mean_absolute_error'])X = np.array(range(base, base+samples))Y = X * slope + interceptmodel.fit(X, Y, epochs=epochs, batch_size=samples)loss, accuracy = model.evaluate(X, Y)print('Loss: ', loss, ' Accuracy: ', accuracy)k_slope = model.layers[0].get_weights()[0]k_intercept = model.layers[0].get_weights()[1]print('slope: ', k_slope, ' intercept: ', k_intercept)
在第一个epoch时,斜率最终为-0.1879,并且没有进展。我怀疑我可能遗漏了某个参数或设置,或者可能是模型上的某个函数调用。但我无法找出是什么问题。
这里是一个我试图在Keras中复现的TensorFlow网络。这个网络在大约1300个epoch后收敛到正确答案:
#simple linear regression with tensorflow# # This solves for a line#import tensorflow as tfimport numpy as np# configuration variablessamples = 5base = 1slope = 2intercept = 5# hyper-parameterslearning_rate = 0.01epochs = 2000x = tf.placeholder(tf.float32)y = tf.placeholder(tf.float32)m = tf.Variable(0.0)b = tf.Variable(0.0)pred = tf.add(tf.multiply(x, m), b)cost = tf.reduce_mean(tf.abs(y - pred))me_first = tf.global_variables_initializer()optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)session = tf.Session()session.run(me_first)for i in range(epochs): X = np.array(range(base, base+samples)) Y = X * slope + intercept t_slope, t_intercept, total_err, opt = session.run([m, b, cost, optimizer], feed_dict={x:X, y:Y})print('iter: ', i, ' intercept: ', t_intercept, ' slope: ', t_slope, ' error: ', total_err)
回答:
Ollin回答了这个问题。损失函数对于网络来说不合适。”BinaryCrossentropy”应该在数据标签为1或0时使用。在我的情况下,标签可以是任何数字。要制作一个与我的TensorFlow示例等效的网络,损失函数需要设置为”mean_absolute_error”,简称”mae”。
我在调用model.compile()时确实将”metrics”字段设置为了”mean_absolute_error”,我错误地假设这个度量指标将被用作网络的损失度量。实际上,”metrics”会被计算和报告,但算法根本不使用它们。度量指标的存在是为了让开发者能够看到训练数据集的其他损失函数值会是多少。
遗憾的是,Keras在这种情况下悄无声息地失败了。如果它看到除了0或1之外的标签时,能够报告”BinaryCrossentropy”不应该作为损失函数使用,那将是有用的。