Session,feed给Graph,然后就是无休止的等待,有时候运气好,数据本身有很好的区分度,模型自然很快收敛,loss直线下降。但是当数据中混淆数据占比较大时,模型难免不会受到很大的干扰,简单来说就是,在当前batch_size下,你告诉模型向下走,下一个batch_size你告诉模型向上走。所以模型也蒙蔽,你丫的是要向上还是要向下,loss自然会处于波动状态,但是随着模型多跑几个epoch,模型就会听从多数者的建议,就是谁告诉我向下次数多我就听谁的,模型严格遵守了少数服从多数的原则。(这里向上,向下作为一个抽象意义上的表述,对于二分类问题就是判定该样本是正样本还是负样本),那么这样就会存在一个严重的问题,面对现实数据的不平衡,模型完完全全就会倾向样本多的那个类别。当遇到数据混淆时,自然少数服从多数了。尽管我们有多种方法来处理样本不平衡的问题,但是如果数据本身随机性很大,或者数据本身存在极大的混淆,那么即使强如神经网络也不能得到很好的分类。

      以下设计一个简单实验来说明这个问题。

  • 定义网络
import numpy as np
import tensorflow as tf

x = tf.placeholder(shape=(None, 5), dtype=tf.float32)
y = tf.placeholder(shape=(None), dtype=tf.float32)

hidden_layer_1 = tf.layers.dense(units=3, inputs=x, activation=tf.tanh)
hidden_layer_2 = tf.layers.dense(units=3, inputs=hidden_layer_1, activation=tf.tanh)
output = tf.squeeze(tf.layers.dense(units=1, inputs=hidden_layer_2, activation=tf.sigmoid))

loss = tf.reduce_mean(tf.pow(y  - output, 2))
train_op = tf.train.AdamOptimizer(0.01).minimize(loss)
  • 构造数据
def get_batch(batch_size, mode=1):
    if mode == 1:
        x = np.array([
            [1, 0, 0, 0, 0], 
            [1, 0, 0, 0, 0], 
            [0, 1, 0, 0, 1], 
            [1, 0, 0, 0, 0], 
            [0, 1, 0, 0, 0],
            [0, 1, 0, 0, 1]]
        )
    elif mode == 2:
        x = np.random.random(30).reshape(-1, 5)
    else:
        x = np.array([
            [1, 0, 0, 0, 1], 
            [1, 0, 0, 0, 0], 
            [0, 1, 0, 0, 0], 
            [1, 0, 0, 0, 0], 
            [0, 1, 0, 0, 1],
            [0, 1, 0, 0, 1]]
        )
    y = np.array([0, 1, 1, 1, 1, 0])
    index = np.random.randint(0, len(x), batch_size)
    return np.array([x[i] for i in index]), np.array([y[i] for i in index])

# 获取数据 mode生成混淆数据,mode生成随机数据
get_batch(2, mode=1) 

# (array([[0, 1, 0, 0, 0],
#        [0, 1, 0, 0, 0]]), array([1, 1]))
  • 训练模型
import matplotlib.pyplot as plt
for i in [1, 2, None]:
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        steps = []
        loss_s = []
        for step in range(10000):
            inputs_x, inputs_y = get_batch(32, mode=i)
            _, loss_ = sess.run([train_op, loss], feed_dict={x: inputs_x, y: inputs_y})
            # print("Step is {}, loss is {}".format(step, loss_))
            if step % 100 == 0:
                steps.append(step)
                loss_s.append(loss_)
        plt.plot(steps, loss_s)
plt.show()

神经网络 训练 参数包括 神经网络训练结果分析_数据混淆

       如图所示,蓝色和橙色的线是在mode=1,mode=2情况下的,绿色的线是mode=None下的,mode=1代表数据存在混淆,mode=2代表数据属于随机,mode=None是减少数据混淆后的数据,明显可以得到前文所叙述的结论。

       有时候面对很好的数据,也会出现loss不下降的情况,这种情况属于,learning_rate和batch_size大小的设置问题,适当调整总归它可以收敛,(如果损失函数没有定义错的话)。这里再纠正一个之前错误的观念,之前认为神经网络数据越多越好,这里犯了想当然的错误,并不是数据越多越好,这个数据多是有条件的,应该指的是同类别下不同情况下的数据,这样保证神经网络能学习到更多现实情况下的特征。如果全是混淆数据,再多模型也无法收敛,因为数据越多随着而来的噪音就越多。