美文网首页
计算CNN感受野 receptive field

计算CNN感受野 receptive field

作者: 铁佛爷 | 来源:发表于2019-03-27 09:30 被阅读0次

    只考虑一维,毕竟大部分图像cnn网络的两个维度也是同样参数。

    # -*- coding: utf-8 -*-
    """
    Created on Tue Mar 26 20:33:32 2019
    
    @author: BigFly
    """
    
    upper = lambda x: int(x) + int( (x-int(x))>0 )
    
    class Layer(object):
        def __init__(self, name, kernel, stride, pad=[0,0], padmode="VALID"):
            self.name = name
            self.kernel = kernel
            self.stride = stride
            self.pad = pad
            self.padmode = padmode
            self.used = False
            
            padding = "%s(%-2d,%-2d)"%(self.padmode,self.pad[0],self.pad[1])
            self.details="['%s':\t  k_%-2d  s_%-2d  p_%s  unused]"\
                    %(self.name, self.kernel, self.stride, padding)
            
        def handle(self,shape):
            reshape = shape+self.pad[0]+self.pad[1]
            outshape = 0
            if self.padmode.lower() == 'valid':
                outshape = upper((reshape-self.kernel+1)/self.stride)
                realshape = (outshape-1)*self.stride+self.kernel
                addpad =[0,realshape-reshape]
            elif self.padmode.lower() == 'same':
                outshape = upper(reshape/self.stride)
                realshape = (outshape-1)*self.stride+self.kernel
                dshape=realshape-reshape
                addpad = [dshape//2, dshape-dshape//2]
            self.padding=[self.pad[i]+addpad[i] for i in [0,1]]
            self.inshape=shape
            self.reshape=realshape
            self.outshape=outshape
            self.used = True
            self.receptive_field()
            self.process="['%s':\t  in:%-4d (%-4d) -> out:%-4d]"\
                    %(self.name, self.inshape,self.reshape,self.outshape)
            
            padding = "%s(%-2d,%-2d)"%(self.padmode,self.padding[0],self.padding[1])
            self.details="['%s':\t  k_%-2d  s_%-2d  p_%s  used]"\
                    %(self.name, self.kernel, self.stride, padding)
            return outshape
            
        def prints(self):
            print(self.details)
            if self.used:
                print(self.process)
                print(self.receptive_field)
    
        def receptive_field(self):
            self.receptive_field=[(-self.padding[0]+i*self.stride,
                                   -self.padding[0]+i*self.stride+self.kernel-1)
                                    for i in range(self.outshape) ]
                
            
    class Networks(object):
        def __init__(self,inshape,layers):
            self.inshape= inshape
            self.layersnum= len(layers)
            layershape= inshape
            for layer in layers:
                layershape = layer.handle(layershape)
            self.details =['input: %d'%(inshape)]+\
                          [layer.details for layer in layers]
            self.process =['input: %d'%(inshape)]+\
                          [layer.process for layer in layers]+\
                          ['output: %d'%(layershape)]
            self.receptive_field = self.clac_receptive_field()
            
        def prints(self):
            print("\n".join(self.details))
            print("----------------")
            print("\n".join(self.process))
            print("----------------")
            for i in range(self.layersnum):
                print("%s \t "%(layers[i].name),self.receptive_field[i])
            print("original range : ",self.receptive_field[-1])
            print("----------------")
            
        def clac_receptive_field(self):
            receptive_field=[layers[0].receptive_field]
            realkernel,realstride = layers[0].kernel,layers[0].stride
            start = layers[0].receptive_field[0][0]
            end = layers[0].receptive_field[-1][1]
            if self.layersnum>1:
                for layer in layers[1:]:
                    cur_rf=[]
                    for rf in layer.receptive_field:
                        cur_rf.append((start+rf[0]*realstride,
                                       start+rf[1]*realstride+realkernel-1))
                    receptive_field.append(cur_rf)
                    start = cur_rf[0][0]
                    end = min(end,cur_rf[-1][1])
                    realstride, realkernel = realstride*layer.stride, \
                                        realstride*(layer.kernel-1)+realkernel
            receptive_field.append([0,end])
            return receptive_field
                
    
    layers=[ Layer("conv1", 11, 4, [0,0]), \
           Layer("pool1", 3, 2, [0,1]), \
           Layer("conv2", 5, 1, [2,2]), \
           Layer("pool2", 3, 2, [0,0]), \
           Layer("conv3", 3, 1, [1,1]), \
           Layer("conv4", 3, 1, [1,1]), \
           Layer("conv5", 3, 1, [1,1]), \
           Layer("pool5", 3, 2, [0,0])]
    cnnf=Networks(224,layers)
    cnnf.prints()
    
    

    相关文章

      网友评论

          本文标题:计算CNN感受野 receptive field

          本文链接:https://www.haomeiwen.com/subject/qrsavqtx.html