Date: 2020/07/25
Coder: CW
Foreword:
CW有时候逛Github会发现不少项目代码中使用到了Meter这个类,meter这个词的意思是仪表,从名称上来看,能feel到它应该是用来度量和记录某些统计量的,结合项目代码的上下文也能看明白的确是这样的意思。
但是,之前对Meter的理解也就止步于此,由于最近它在我逛Github时出现的频率越来越高,因此就忍不住瞄了下相关源码,现在我就把这成果记录在本文,分享给大家以便快速了解下Meter的打开方式。
Outline
I. Meter概述
II. 举例:AverageValueMeter
III. 举例:ConfusionMeter
Meter概述
Meter 这个类是在torchnet.meter模块中实现的,它其实是一个抽象类,也就是不会干活的家伙,也就装装逼,但能干活的比如ConfusionMeter、AverageValueMeter(后文会介绍)等都得膜拜它当大佬(作为它的子类),废话不多说,先来看看doc string:
Meter(i)如上图所述,它是用来“跟踪”一些统计量的,也就是能够在一段“历程”中记录下某个统计量在迭代过程中不断变化的值,并统计相关的量。
作为大佬(抽象类),它提供了以下接口供小弟(子类)们实现。
Meter(ii)举例:AverageValueMeter
Meter有很多子类,这里就AverageValueMeter来举个例子说明下其作用。
AverageValueMeter(i)从名字看来,AverageValueMeter返回的应该是统计量的均值。哦,看了其实现的value()这个接口后,可以知道它还返回了标准差。由于它暴露给外界获取值的只有value()这个接口,因此通过这个Meter并不能知道统计量每次迭代的最新值,仅仅能够知道均值和标准差。
另外说明下,self.n其实并不一定等于迭代次数。因为可以对每次加入的数值设置单位量(相当于权重),通常来说,每次迭代得到一个新的数值,单位量为1,代表多了一个数,这样的话self.n就等同于迭代次数。
AverageValueMeter(ii)重头戏来了,看看每次迭代更新的过程中,它做了什么。
看下图,如上所述,若加入数值时单位量不为1,那么到头来self.n就不是迭代次数了,而是在整个迭代过程中单位量的总和。
AverageValueMeter(iii)这里对于均值和标准差需要稍微动下脑筋进行推导,此处就均值的计算进行下说明。
self.mean = self.sum / self.n 这点毋庸置疑,OK开始往下推导。
self.sum = sum_old + value,而sum_old=self.mean_old * (self.n - n),于是:
self.sum = self.mean_old * (self.n - n) + value,去括号重新组合下:
self.sum = self.mean_old * self.n + (value - n * self.mean_old)
从而得到 self.mean = self.mean_old + (value - n* self.mean_old) / self.n
举例:ConfusionMeter
一个例子不过瘾?再来个尝尝香不香!
顾名思义,ConfusionMeter是混淆矩阵形式的Meter。
ConfusionMeter(i)self.conf就是混淆矩阵,conf是confusion的意思,初始化为0。
ConfusionMeter(ii)这个Meter暴露给外界的也就是这个混淆矩阵。
ConfusionMeter(iii)这里需要注意下,如果是K分类(通过初始化是设置self.k)问题,那么这里传入的预测和目标的各个值需要在[0, K-1]范围内。
ConfusionMeter(iv) ConfusionMeter(v)target可以是二维的,对应的是one-hot形式。
ConfusionMeter(vi)精华都在以下这张图里,举个例子来说明。
假如是二分类问题,此时self.k=2,同时predicted和target的取值范围都在[0, 1]内,那么x的取值就可能是0、1、2、3这4种情况。直观上来看,处于边界的两种情况(0和3)代表预测效果较好,因为0的时候predicted和target都为0,而3的时候两者都为1,也就是预测都正确了。
np.bincount会根据x的各个值划分bin(区间),然后统计x中每个值出现的次数,对应到每个bin上(想象下条形图那种结构)。最后再将bincount的结果reshape到kxk矩阵的形式。
ConfusionMeter(vii)
网友评论