您当前的位置:首页 > IT编程 > 深度学习
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:二分类问题中,大量的负样本会影响到网络的训练吗?

51自学网 2020-10-08 08:12:01
  深度学习
这篇教程二分类问题中,大量的负样本会影响到网络的训练吗?写得很实用,希望能帮到您。

在分类问题中,比如我们训练一个网络,让它识别出这张照片是否为人,我们的数据集假设有张1000张,其中100张为人,900张不是人(里面包含了车,飞机,花朵等乱七八糟的图片),可以看到这个数据集出现了负样本远大于正样本的情况.现在假设我们把这1000张图片一次性送入网络进行训练,那么得到的损失值如何计算?负样本对损失值有贡献吗?

答案:

(1)损失值loss计算公式:

假设真实标签值y_true=[y1,y2,y3,...yn]

预测值y_pred=[z1,z2,z3,...zn]

loss=-\frac{y_1*logz_1+y_2*logz_2+y_3*logz_3...+y_n*logz_n}{n}      (1)

(2) 负样本对损失值有贡献,主要体现到上面的loss计算上,虽然负样本标签值=0,分子中遇到负样本0,y_i*log(z_i)=0, 但是在分母中,n的值是正负样本样本的总数量,所以负样本对损失值是有贡献的,特别当正负样本比例失衡,负样本远大于正样本时,会造成训练进行不下去.

还是用一段程序来证明吧


 
  1. import tensorflow as tf
  2. y_true=[[0], [0],[0],[0],[1], [1]]#真实标签
  3. y_pre=[[0.9],[0.9],[0.9],[0.9],[0.6],[0.5]]#预测值
  4. cross_entropy=-tf.reduce_mean(y_true*tf.log(tf.clip_by_value(y_pre,1e-10,1.0)))#-ylogp
  5. a=-tf.log(0.6)-tf.log(0.5)#就算所有样本的损失和,可以看出这里负样本因为标签值=0,所以无论预测值是多少,对损失和是没有影响的
  6. with tf.Session() as sess:
  7. print(sess.run(a))#1.20397
  8. print(sess.run(a / 2))#0.601986
  9. print(sess.run(a / 6))#0.200662
  10. print(sess.run(cross_entropy))#0.200662#这里可以看出经过reduce_mean之后,这个是按照所有的样本数量来求平均值的,虽然前面正样本只有2个,
  11. # 但是算平均损失的话,这里是除以样本总数的,所以随着负样本的增多,当其数量远远大于正样本数量时,无论网络对于正样本是否预测正确,最后的总的损失值会很小,
  12. #即由负样本主导了损失函数值,造成损失函数值非常小,无法反向传播,训练失败

完整例子,来源于tensorflow实战google深度学习框架


 
  1. import tensorflow as tf
  2. from numpy.random import RandomState
  3. batch_size=8
  4. w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))#第一个权重矩阵
  5. #tf.randdom_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name=None)
  6. #shape:输出张量的形状,必选,mean正态分布的均值,默认=0,stddev标准差,默认=1,dtype,输出的类型,默认=tf.float32
  7. #seed随机数种子,是一个整数,当设置之后,每次生成的随机数都一样,name操作的名称
  8. w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))#生成3行1列矩阵
  9.  
  10. x=tf.placeholder(tf.float32,shape=(None,2),name='x-input')#训练样本,?x2的矩阵
  11. y_=tf.placeholder(tf.float32,shape=(None,1),name='y-input')#训练样本的标签,?x1的矩阵
  12. a=tf.matmul(x,w1)#计算x*w1,[?,2]*[2,3]=[?,3]
  13. y=tf.matmul(a,w2)#计算a*w2=x*w1*w2,[?,2]*[2,3]*[3,1=[?,3]*[3,1]=[?,1]
  14. cross_entropy=-tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0)))#-ylogp
  15. #tf.reduce_mean(input_tensor,axis=None,)函数用于计算张量tensor沿着指定的数轴tensor的某一维度)上的平均值,主要用作将维或者计算tensor
  16. # (图像)的平均值,
  17. #第一个参数input_tensor:输入的待降维的tensor
  18. #axis: 指定的轴,如果不指定,则计算所有元素的均值
  19. train_step=tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
  20. rdm=RandomState(1)#因为这里固定了随机数种子,所以每次运行程序,生成的训练样本都是一样的
  21. dataset_size=3
  22. X=rdm.rand(dataset_size,2)#生成128x2的训练样本
  23. Y=[[int(x1+x2<1)] for (x1,x2) in X]#对训练样本生成标签,值=0或1
  24.  
  25. with tf.Session() as sess:
  26. init_op=tf.initialize_all_variables()
  27. sess.run(init_op)
  28. print(sess.run(w1))
  29. print(sess.run(w2))
  30. # print('x', sess.run(X))
  31. # print('y', sess.run(Y))
  32. steps=5000
  33. for i in range(steps):
  34. start=(i*batch_size)%dataset_size
  35. end=min(start+batch_size,dataset_size)
  36. sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})
  37. if i%1000==0:
  38. total_cross_entropy=sess.run(cross_entropy,feed_dict={x:X,y_:Y})
  39. print('after %d training steps, cross entropy on all data is %g'%(i,total_cross_entropy))#%g啥意思?
  40. print(sess.run(w1))
  41. print(sess.run(w2))
  42.  
  43.  

解决方案:

挖坑1: 从等式(1)可以看出负样本对损失函数值的影响主要体现在分母上,那我干脆对于y_true, 多加一列,标记一下其是负样本,这样我就不把它统计到样本总量中不久可以了吗?

  具体操作:把y_true中值=1的个数统计出来,假设=m,求均值时,分母=m即可.这个操作可以在retinanet或其他有构造anchor的代码中发现.


 
  1. cls_loss = focal_weight * keras.backend.binary_crossentropy(target=labels, output=classification)
  2.  
  3. # compute the normalizer: the number of positive anchors
  4. normalizer = backend.where(keras.backend.equal(anchor_state, 1))#只计算正样本的数量,忽略负样本的数量
  5. normalizer = keras.backend.cast(keras.backend.shape(normalizer)[0], keras.backend.floatx())
  6. normalizer = keras.backend.maximum(1.0, normalizer)#尽管anchor中负样本特别多,这里算平均值时只除以正样本的数量,可有效避免负样本主导损失函数造成loss很小,
  7. #导致的训练失败

挖坑2:在实际的应用场景中,做目标检测时,同一张图片中会出现多个目标,而且这多个目标可能属于不同的类别中,比如在一张图片中出现了一个人和一群狗,我们的网络任务为在这图片中找出人和狗,并识别出是狗还是人,所以这里我们对同一张图片,就会

后面问题不知道如何描述了,让我想想再写,2019-09-04


深度可分离卷积和正常卷积图文解析浅显易懂
损失函数改进之Large-Margin Softmax Loss
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。