tf.nn.top_k--tf.gather_nd

在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, 允许人们通过向上或向下加权相对于负误差的正误差的成本来权衡找回率和精确度,通常的交叉熵定义为:

即:

loss=-y*ln(a)*pos\_weight-(1-y)*ln(1-a)=\left\{\begin{matrix} -lna &y=1 \\ -ln(1-a)& y=0 \end{matrix}\right.
可见,普通的交叉熵对于正样本而言,预测的概率值a越大,即预测的比较准确时损失越小;对于负样本而言,预测的概率值a越小,则损失越小.考虑一种情况,训练样本总共有1000张, 9900张都是正样本,100张为负样本, 那么在训练时, 因为输入的大部分都为正样本,经过几轮训练后,网络基本有分辨能力,大量预测值都为1, 损失函数值就非常小,会造成迭代过程中比较缓慢可能无法优化至最优.

来看下引入权重pos_weightws之后的改进的交叉熵,计算方法为

-y*ln(a)*pos\_weight-(1-y)*ln(1-a)

对其进行进一步整理可得,记q=pos_weight

loss=-qy*ln(a)-(1-y)*ln(1-a)\\ =-qy*ln(sigmoid(x))-(1-y)*ln(1-sigmoid(x))\\ =-qy*ln(\frac{1}{1+e^{-x}})-(1-y)*ln(1-\frac{1}{1+e^{-x}})\\ =qy*ln(1+e^{-x})-(1-y)*ln(\frac{e^{-x}}{1+e^{-x}})\\ =qy*ln(1+e^{-x})-(1-y)*[lne^{-x}-ln(1+e^{-x})]\\ =qy*ln(1+e^{-x})+(1-y)*[x+ln(1+e^{-x})]\\ =(1-y)*x+(qy+1-y)*ln(1+e^{-x})\\ =(1-y)*x+[1+(q-1)y]*ln(1+e^{-x})

 

值pos_weightws>1减少了假阴性计数,从而增加了召回率,相反设置pos_weights<1会减少假阳性计数并提高精度,从下一内容可以看出pos_weight是作为损失表达式中的正目标项的乘法系数引入的.
_

来看下focal loss做的改进

l_{fl}=\left\{\begin{matrix} -(1-a)^\gamma lna &y=1 \\ -a^\gamma ln(1-a)& y=0 \end{matrix}\right.

首先在原有的基础上加了一个因子\gamma >0,这样可以减少易分类样本呢的损失,使得更关注于困难的,错分的样本.

例如\gamma =2,对于正样本而言,预测结果a=0.95肯定是正样本,所以(1-0.95)^2=0.0025,相比原来的lna, 乘以0.0025后,损失就会更小,而预测结果a=0.3的样本,所以(1-0.95)^2=0.0025,相比原来的lna, 乘以0.49后.......这段不理解参数的作用

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值