TensorFlow 回归模型每次都给出相同的预测

数据挖掘 神经网络 深度学习 回归 张量流
2021-09-24 08:40:49
import tensorflow as tf

x = tf.placeholder(tf.float32, [None,4])    # input vector    
w1 = tf.Variable(tf.random_normal([4,2]))   # weights between first and second layers
b1 = tf.Variable(tf.zeros([2]))             # biases added to hidden layer
w2 = tf.Variable(tf.random_normal([2,1]))   # weights between second and third layer
b2 = tf.Variable(tf.zeros([1]))             # biases added to third (output) layer

def feedForward(x,w,b):                     # function for forward propagation
    Input = tf.add(tf.matmul(x,w), b)
    Output = tf.sigmoid(Input)
    return Output

Out1 = feedForward(x,w1,b1)                # output of first layer
Out2 = feedForward(Out1,w2,b2)             # output of second layer
MHat = 50*Out2                             # final prediction is in the range (0,50)

M = tf.placeholder(tf.float32, [None,1])   # placeholder for actual (target value of marks)
J = tf.reduce_mean(tf.square(MHat - M))    # cost function -- mean square errors                          
train_step = tf.train.GradientDescentOptimizer(0.05).minimize(J)     # minimize J using Gradient Descent
sess = tf.InteractiveSession()             # create interactive session 

tf.global_variables_initializer().run()    # initialize all weight and bias variables with specified values
xs = [[1,3,9,7],    
      [7,9,8,2],                           # x training data
      [2,4,6,5]]

Ms = [[47],
      [43],                                # M training data
      [39]]

for _ in range(1000):                      # performing learning process on training data 1000 times
    sess.run(train_step, feed_dict = {x:xs, M:Ms})

>>> print(sess.run(MHat, feed_dict = {x:[[1,15,9,7]]}))
[[50.]]

>>> print(sess.run(MHat, feed_dict = {x:[[3,8,1,2]]}))
[[50.]]

>>> print(sess.run(MHat, feed_dict = {x:[[6,7,10,9]]}))
[[50.]]

在这段代码中,我试图根据学生在考试前一天的睡眠、学习、使用电子产品和玩耍的时间来预测学生在 50 分中获得的分数 M。这 4 个特征属于输入特征向量 x。

为了解决这个回归问题,我使用了一个深度神经网络,输入层有 4 个感知器(输入特征),隐藏层有两个感知器,输出层有一个感知器。

我使用 sigmoid 作为激活函数。但是,对于我输入的所有可能的输入向量,我得到了与 M 完全相同的预测([[50.0]])。

有人可以告诉我上面的代码有什么问题,为什么我每次都得到相同的结果?

2个回答

您的网络设计/逻辑基本上是正确的,但是您看到了一些非常常见的神经网络数值稳定性问题。这会导致你的体重发散并且训练不准确。

这是修复,其中任何一个都可能有所帮助,但前两个应该用于几乎所有的神经网络项目。

1. 需要对输入进行缩放以与神经网络一起使用。

这称为输入标准化。通常您会在数据预处理中执行此操作,但对于您的简单网络,我们可以在输入中包含缩放:

x_normalised = x * 0.2 - 0.5             # Arbitrary scaling I just made up
Out1 = feedForward(x_normalised,w1,b1)   # output of first layer

最常见的缩放操作是获取所有训练数据并对其进行转换,使其具有均值 0 和标准差 1(通常是每个特征,而不是像我在这里所做的那样对所有数据进行全局缩放) - 存储用于实现该目标的值并将它们应用于所有后续数据以进行训练、测试等。

2.调整学习率,直到你得到一个工作值。

train_step = tf.train.GradientDescentOptimizer(0.001).minimize(J) 

值太高会导致训练失败。一个值太低将需要很长时间才能学到任何东西。

3. 对于小型训练集,使用比您想象的更多的迭代次数

这不是一般的事情,而是特定于具有少量训练数据的演示,例如您的示例,或常用的“学习 XOR 函数”。

for _ in range(10000):                      # performing learning process

   sess.run(train_step, feed_dict = {x:xs, M:Ms})

实际上,对于您非常简单的网络,这可能会导致对训练数据的过度拟合,因此您必须使用一个能够为您提供“合理”结果的值。但是,一般而言,根据您如何测试和测量泛化,如何发现和最小化过度拟合本身就是一个广泛的主题。如果您不确定何时学习,这将需要其他问题。不过,它应该在您要学习的事情清单上很重要。. . 它是产生解决实际问题的有用神经网络的关键技能。

除了上面 Neil Slater 的回答,使用 ReLU 激活你的神经元会更快地收敛(允许你在更短的时间内训练)。

def feedForward(x,w,b):
    Input = tf.add(tf.matmul(x,w), b)
    Output = tf.nn.relu(Input)           # this ReLU
    return Output

MHat = tf.nn.relu(Out2)                  # and for the prediction

Sigmoid 主要用于 0.0 到 1.0 范围内的值(请参阅this)。