在retinanet的损失函数和其他层的构造中,用到了下面的一些函数
1.tf.nn.top_k
2.tf.gather.
tf.gather_nd
3.tf.ones_like(x, dtype=dtype, name=name)
4. tf.clip_by_value(output, _epsilon, 1 - _epsilon)
5.tf.nn.weighted_cross_entropy_with_logits
下面分别介绍下每个函数的用法:
1.value, indices=tf.nn.top_k(),
#返回值有2个,value为返回值,每行返回k个数, (把input中每行从大到排列,返回前k个数),indices记录了value好中每个数在input中的位置
mport tensorflow as tf
import numpy as np
input = np.array([[1,2,3],[3,4,5],[7,9,4]])
input = tf.convert_to_tensor(input)
k = 2
value,indices= tf.nn.top_k(input, k)#返回值有2个,value为返回值,每行返回k个数,
# (把input中每行从大到排列,返回前k个数),indices记录了value好中每个数在input
#中的位置
with tf.Session() as sess:
print(sess.run(value))#[[3 2]
# [5 4]
# [9 7]]
print(sess.run(indices))#[[2 1]
# [2 1]
# [1 0]]
2. tf.gather(), 在numpy里取矩阵数据非常方便,比如a[1,3,4]就可以把a中元素提取出来,如果要提取的索引不连续的话,在tensorflow里面的用法就要用到tf.gather(input, indices) ,从input中取出indices所指定的行
import tensorflow as tf
import numpy as np
input = np.array([[1,2,3,4],[3,4,5,5],[7,9,4,6]])
input = tf.convert_to_tensor(input)
indices = np.array([0,2,4,9])
sess = tf.Session()
b = tf.gather(input, indices)#取出input的0,2,4,9行,若indices中的元素值超出了input的行的范围,就返回0
print(sess.run(b))#[[1 2 3 4] input 第0行
# [7 9 4 6] input 第2行
# [0 0 0 0] input 第4行不存在,越界,返回0
# [0 0 0 0]] input 第9行不存在,越界,返回0
tf.gather_nd()允许在多维上进行索引,matrix中直接通过坐标取数(索引维度与tensor维度相同):
import tensorflow as tf
import numpy as np
input = np.array([[1,2,3,4],[3,4,5,5],[7,9,4,6]])
input = tf.convert_to_tensor(input)
sess = tf.Session()
indices = [[0, 0], [1, 1]]
c = tf.gather_nd(input, indices)#取出input[0,0]=1,input[1,1]=4
print(sess.run(c))#[1 4]
3. tf.ones_like函数,改函数返回所有元素设置为1的张量
tf.ones_like(tensor,dype=None,name=None) #新建一个与给定的tensor类型大小一致的tensor, 其所有元素值为1
import tensorflow as tf
tensor=[[1, 2, 3], [4, 5, 6]]
x = tf.ones_like(tensor)
sess=tf.Session()
print(sess.run(x))
#[[1 1 1],
# [1 1 1]]
4. tf.clip_by_value(input,a, b),可以将一个张量中的数值限制在一个范围之内,可以避免一些运算错误,可以保证在进行log运算时,不会出现log0这样的错误或者大于1的概率,
参数: input,输入数据,
le-7,1 - _epsilon:对数据的限制
当input<a时,输出a
当a<input<b,输出input
当input>b,输出b
5.tf.nn.weighted_cross_entropy_with_logits(targets, logits,pos_weight,name=None)计算加权交叉熵,类似于sigmoid_cross_entropy_with_logits(),除了pos_weight, 允许人们通过向上或向下加权相对于负误差的正误差的成本来权衡找回率和精确度,通常的交叉熵定义为:
即:
可见,普通的交叉熵对于正样本而言,预测的概率值a越大,即预测的比较准确时损失越小;对于负样本而言,预测的概率值a越小,则损失越小.考虑一种情况,训练样本总共有1000张, 9900张都是正样本,100张为负样本, 那么在训练时, 因为输入的大部分都为正样本,经过几轮训练后,网络基本有分辨能力,大量预测值都为1, 损失函数值就非常小,会造成迭代过程中比较缓慢可能无法优化至最优.
来看下引入权重pos_weightws之后的改进的交叉熵,计算方法为
对其进行进一步整理可得,记q=pos_weight
值pos_weightws>1减少了假阴性计数,从而增加了召回率,相反设置pos_weights<1会减少假阳性计数并提高精度,从下一内容可以看出pos_weight是作为损失表达式中的正目标项的乘法系数引入的.
_
来看下focal loss做的改进
首先在原有的基础上加了一个因子,这样可以减少易分类样本呢的损失,使得更关注于困难的,错分的样本.
例如,对于正样本而言,预测结果a=0.95肯定是正样本,所以
,相比原来的lna, 乘以0.0025后,损失就会更小,而预测结果a=0.3的样本,所以
,相比原来的lna, 乘以0.49后.......这段不理解参数的作用