【tensorflow】MTCNN网络基本函数cls_ohem()

cls_ohem()函数的作用就是返回人脸分类任务训练的loss值,其中只用loss值较大的前百分之七十参与反向传播。

import numpy as np
import tensorflow as tf
def cls_ohem(cls_prob, label):
    num_keep_radio = 0.7
    # label = tf.placeholder(tf.float32, shape=[config.BATCH_SIZE], name='label')
    # cls_prob的shape是[384,2]
    # label的shape是[384]

    zeros = tf.zeros_like(label)
    # 建立一个和label相同shape的全0数组
    # label=-1 --> label=0net_factory

    # pos -> 1, neg -> 0, others -> 0
    # tf.less(x,y):x,y都是一个tensor,返回值是一个bool型的tensor,(逐元素返回是否x<y)
    # tf.where(a,b,c)可以简单的认为a为真时,返回b,不然返回c
    # 所以下面的操作是将正样本的label保持为1,负样本label为0,其他的的两个样本label值为0。
    label_filter_invalid = tf.where(tf.less(label, 0), zeros, label)

    # 返回cls_prob中元素的个数,384*2
    num_cls_prob = tf.size(cls_prob)

    # reshape成768行
    cls_prob_reshape = tf.reshape(cls_prob, [num_cls_prob, -1])

    # 将label_filter_invalid转化为int32类型
    label_int = tf.cast(label_filter_invalid, tf.int32)

    # 获取class_prob的行数,384
    num_row = tf.to_int32(cls_prob.get_shape()[0])

    # row = [0,2,4.....]
    row = tf.range(num_row) * 2

    # 因为conv4_1输出的的shape是[batch,2],每一张图片经过网络后,再经过softmax函数,输出的的是两个概率值
    # 第一个值表示非人脸的概率,第二个值表示是人脸的概率,加起来的和为1,此时的label_int仍是[batch]
    # 只是里面只有pos样本对应的label值是1,其余均为0,所以row + label_int表示的是cls_prob_reshape里面pos样本的索引
    indices_ = row + label_int
    # 使用tf.gather函数将pos样本提取出来,再使用tf.squeeze函数将shape变成(384,)
    # 此时label_prob是里面有384个概率,是pos样本对应的概率和非pos样本对应的概率:pos样本为概率与非pos样本对应的概率
    label_prob = tf.squeeze(tf.gather(cls_prob_reshape, indices_))

    # 是一个二分类问题,使用的交叉熵损失函数。加上1e-10,是为了防止里面的label_prob值太小,输出为负无穷
    loss = -tf.log(label_prob + 1e-10)

    zeros = tf.zeros_like(label_prob, dtype=tf.float32)
    ones = tf.ones_like(label_prob, dtype=tf.float32)

    # set pos and neg to be 1, rest to be 0
    # 建立一个valid_inds,里面将正样本和负样本的label设置为1,其余的为0
    valid_inds = tf.where(label < zeros, zeros, ones)

    # get the number of POS and NEG examples
    # 获得正样本和负样本的数量
    num_valid = tf.reduce_sum(valid_inds)
    # 获取正样本和负样本数量的百分之70
    keep_num = tf.cast(num_valid * num_keep_radio, dtype=tf.int32)
    # FILTER OUT PART AND LANDMARK DATA
    # 去除掉part样本和landmark样本
    loss = loss * valid_inds
    # 得到loss值中大小排前百分之七十的样本  为了找到输入的张量的最后的一个维度的最大的k个值和它的下标!
    loss, _ = tf.nn.top_k(loss, k=keep_num)
    #返回loss
    with tf.Session() as sess:
       # print(sess.run(indices_))
        #print(sess.run(cls_prob_reshape))
        print(sess.run(tf.gather(cls_prob_reshape, indices_)))
        print(sess.run(label_prob))
        print("Loss:%s"%(sess.run(tf.reduce_mean(loss))))
    return tf.reduce_mean(loss)


#cls_prob1 = np.array([[0.5,0.6],[0.5,0.6],[0.5,0.6],[0.5,0.6],[0.5,0.6],[0.5,0.6],[0.5,0.6],[0.5,0.6],[0.5,0.6],[0.5,0.6]])
cls_prob = tf.random_uniform([10,2],0,1,seed = 100)
with tf.Session() as sess:
    print("cls_prob:%s"%(sess.run(cls_prob)))
#print(cls_prob1)
label = np.array([1,0,0,0,0,0,0,0,0,0])
cls_ohem(cls_prob, label)


在这里插入图片描述
注释:
tf.gather:用一个一维的索引数组,将张量中对应索引的向量提取出来
tf.squeeze()给定张量输入,此操作返回相同类型的张量,并删除所有尺寸为1的尺寸。 如果不想删除所有尺寸1尺寸,可以通过指定squeeze_dims来删除特定尺寸1尺寸。
如果不想删除所有大小是1的维度,可以通过squeeze_dims指定。

# 't' is a tensor of shape [1, 2, 1, 3, 1, 1]
shape(squeeze(t)) ==> [2, 3]
Or, to remove specific size 1 dimensions:
 
# 't' is a tensor of shape [1, 2, 1, 3, 1, 1]
shape(squeeze(t, [2, 4])) ==> [1, 2, 3, 1]
import numpy as np
import tensorflow as tf

cl = tf.Variable([[1],
                  [4],
                  [5],
                  [1],
                  [7]])
t = tf.Variable([[1,2,3,5,6,1]])
label_prob1 = tf.squeeze(cl)
label_prob = tf.squeeze(t)
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
print("label_prob1:%s"%(sess.run(label_prob1)))
print("label_prob1:%s"%(sess.run(label_prob)))

在这里插入图片描述

tf.nn.top_k(
input,
k=1,
sorted=True,
name=None
)

为了找到输入的张量的最后的一个维度的最大的k个值和它的下标!

如果输入的是一个向量,也就是rank=1,找到最大的k个数在这个向量,则输出最大的k个数字和最大的这k个数字的下标。如果输入的张量是一个更高rank的矩阵,那么我们只要找到每一行的最大的k个数字,以及他们的下标。如果两个元素相同,那么低一点的下标先出现。

参数:
input:输入的tensor,不能是array这些啊!要么输入1-D,要是更高维度必须保证最后的一个维度长度必须大于等于K
k:0-D的int32的数字张量。
sorted:如果sorted=True,那么选出来的k个数字就需要按照降序的顺序排序
name:可选项,也就是这个操作的名字

返回:

values:也就是每一行的最大的k个数字
indices:这里的下标是在输入的张量的最后一个维度的下标

import tensorflow as tf
import numpy as np

# 选出每一行的最大的前两个数字,返回的是最大的k个数字,同时返回的是最大的k个数字在最后的一个维度的下标
a = tf.constant(np.random.rand(4, 4))
b = tf.nn.top_k(a, k=3)
with tf.Session() as sess:
    print(sess.run(a))
    print(sess.run(b))

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖子工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值