损失开始高而不减少

我开始用tensorflow编写神经元网络,并且在我的每个示例项目中似乎都会遇到一个问题。

我的损失总是从50或更高的东西开始,并且不会降低,或者如果它降低了,它的速度会很慢,以至于在我所有的时代之后,我甚至没有接近可接受的损失率。

它已经尝试过的东西 (并且不会非常影响结果)

  • 测试过度拟合,但在下面的例子中,你可以看到我有15000个训练和15000个测试数据集和900个神经元
  • 测试了不同的优化器和优化器值
  • 尝试使用testdata作为训练数据以及增加traingdata
  • 试图增加和减少批量
  • 我根据https://youtu.be/vq2nnJ4g6N0的知识创建了网络

    但让我们看看我的一个测试项目

    我有一个名单的名单,并想要承担性别,所以我的原始数据如下所示:

    names=["Maria","Paul","Emilia",...]
    
    genders=["f","m","f",...]
    

    为了将它馈送到网络中,我将名称转换为一个charCodes数组(期望最大长度为30),并将性别转换为位数组

    names=[[77.,97. ,114.,105.,97. ,0. ,0.,...]
           [80.,97. ,117.,108.,0.  ,0. ,0.,...]
           [69.,109.,105.,108.,105.,97.,0.,...]]
    
    genders=[[1.,0.]
             [0.,1.]
             [1.,0.]]
    

    我为输出层建立了3个隐藏层[30,20],[20,10],[10,10]和[10,2]。 所有隐藏层都具有ReLU作为激活功能。 输出层具有softmax。

    # Input Layer
    x = tf.placeholder(tf.float32, shape=[None, 30])
    y_ = tf.placeholder(tf.float32, shape=[None, 2])
    
    # Hidden Layers
    # H1
    W1 = tf.Variable(tf.truncated_normal([30, 20], stddev=0.1))
    b1 = tf.Variable(tf.zeros([20]))
    y1 = tf.nn.relu(tf.matmul(x, W1) + b1)
    
    # H2
    W2 = tf.Variable(tf.truncated_normal([20, 10], stddev=0.1))
    b2 = tf.Variable(tf.zeros([10]))
    y2 = tf.nn.relu(tf.matmul(y1, W2) + b2)
    
    # H3
    W3 = tf.Variable(tf.truncated_normal([10, 10], stddev=0.1))
    b3 = tf.Variable(tf.zeros([10]))
    y3 = tf.nn.relu(tf.matmul(y2, W3) + b3)
    
    # Output Layer
    W = tf.Variable(tf.truncated_normal([10, 2], stddev=0.1))
    b = tf.Variable(tf.zeros([2]))
    y = tf.nn.softmax(tf.matmul(y3, W) + b)
    

    现在计算损失,准确性和训练操作:

    # Loss
    cross_entropy = -tf.reduce_sum(y_*tf.log(y))
    
    # Accuracy
    is_correct = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
    accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
    
    # Training
    train_operation = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
    

    我分批培训网络100

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    for i in range(150):
        bs = 100
        index = i*bs
        inputBatch = inputData[index:index+bs]
        outputBatch = outputData[index:index+bs]
    
        sess.run(train_operation, feed_dict={x: inputBatch, y_: outputBatch})
        accuracyTrain, lossTrain = sess.run([accuracy, cross_entropy], feed_dict={x: inputBatch, y_: outputBatch})
    
        if i%(bs/10) == 0:
            print("step %d loss %.2f accuracy %.2f" % (i, lossTrain, accuracyTrain))
    

    我得到以下结果:

    step 0 loss 68.96 accuracy 0.55
    step 10 loss 69.32 accuracy 0.50
    step 20 loss 69.31 accuracy 0.50
    step 30 loss 69.31 accuracy 0.50
    step 40 loss 69.29 accuracy 0.51
    step 50 loss 69.90 accuracy 0.53
    step 60 loss 68.92 accuracy 0.55
    step 70 loss 68.99 accuracy 0.55
    step 80 loss 69.49 accuracy 0.49
    step 90 loss 69.25 accuracy 0.52
    step 100 loss 69.39 accuracy 0.49
    step 110 loss 69.32 accuracy 0.47
    step 120 loss 67.17 accuracy 0.61
    step 130 loss 69.34 accuracy 0.50
    step 140 loss 69.33 accuracy 0.47
    


    我究竟做错了什么?

    为什么它在我的项目中以69开头,而不是更低?


    非常感谢你们!


    作为二元分类的起点,每个样本的0.69个熵是没有问题的。

    如果您转换为基准0.69/log(2) ,则您会看到每个样本几乎恰好为1位,如果您不确定二元分类的准确性,那么这正是您所期望的。

    我通常使用平均损失而不是总和,因此对批量大小不太敏感。

    你也不应该直接自己计算熵,因为这个方法很容易中断。 你可能想要tf.nn.sigmoid_cross_entropy_with_logits

    我也喜欢从Adam Optimizer开始,而不是纯渐变下降。

    以下是导致此问题的两个原因:

    1)字符代码是有序的,但顺序没有任何意义。 如果网络作为一个热点向量输入,您的输入将更容易作为输入。 所以你的输入将是一个26x30 = 780元素的向量。 没有这些,网络必须浪费一大堆能力来学习字母之间的界限。

    2)你只有完全连接的层。 这使得它不可能学习一个独立于名称绝对位置的事实。 2015年排名前10位的女孩中有6位以'a'结尾,而前10位男孩中的0位取得了成功。 按照目前的写法,你的网络需要重新学习“通常这是一个女孩的名字,如果它以'a'结尾”,每个名字的长度都是独立的。 使用一些卷积层将允许它在所有名字长度上学习事实。

    链接地址: http://www.djcxy.com/p/32045.html

    上一篇: loss starts high and does not decrease

    下一篇: ConvNet not improving (Tensorflow)