paddlepaddle 21 基于dropout实现用4行代码dropblock

dropblock的作用不在累述,这里只分享使用4行代码实现dropblock。dropblock的介绍可以参考博主的另一篇文章pytorch 22 8种Dropout方法的简介 及 基于Dropout用4行代码快速实现DropBlock_万里鹏程转瞬至的博客-CSDN博客

1、基本库方法实现

这里主要实现三个函数,图片展示、图片读取和tensor转img

from PIL import Image
from matplotlib import pyplot as plt
import paddle
from paddle import nn
def myimshows(imgs, titles=False, fname="test.jpg", size=6):
    lens = len(imgs)
    fig = plt.figure(figsize=(size * lens,size))
    if titles == False:
        titles="0123456789"
    for i in range(1, lens + 1):
        cols = 100 + lens * 10 + i
        plt.xticks(())
        plt.yticks(())
        plt.subplot(cols)
        if len(imgs[i - 1].shape) == 2:
            plt.imshow(imgs[i - 1], cmap='Reds')
        else:
            plt.imshow(imgs[i - 1])
        plt.title(titles[i - 1])
    plt.xticks(())
    plt.yticks(())
    plt.savefig(fname, bbox_inches='tight')
    plt.show()
    
def read_img_as_nparr(path):
    im=Image.open(path)
    img=np.array(im)
    if len(img.shape)==2:
        np_arr=img.reshape((1,1,img.shape[0],img.shape[1]))
    else:
        img=img.transpose((2,0,1))
        np_arr=img.reshape((1,*img.shape))
    return np_arr,np.array(im)
 
def tensor2img(tensor):
    np_arr=tensor.numpy()[0]
    if np_arr.shape[0]==1:
        np_arr=np_arr[0]
    else:
        np_arr=np_arr.transpose((1,2,0))
        
    if np_arr.max()>1:
        np_arr[np_arr>255]=255
        np_arr=np_arr.astype(np.uint8)
    return np_arr

2、基于dropout实现dropblock

import paddle
from paddle import nn
class DropBlock(nn.Layer):
    def __init__(self,block_size,drop_rate,chanel_independent=True):
        super(DropBlock, self).__init__()
        self.block_size = block_size
        self.drop_rate = drop_rate
        self.chanel_independent = chanel_independent
        
    def forward(self, x):
        if self.training and self.drop_rate>0:
            b,c,h,w=x.shape
            if self.block_size[0]>h or self.block_size[1]>w:
                error_msg="block_size:(%s,%s) feature map size:(%s,%s)"%(self.block_size[0],self.block_size[1],h,w)
                print(error_msg)
                raise("The block_size must be smaller or equal to the feature map! ")
            #针对不同的chanel使用不同的概率进行drop_block, 在提出者的实验中chanel不同的使用不同的mask效果更好
            if self.chanel_independent==False:
                c=1#针对所有的chanel都采用相同的mask
            mask=paddle.ones((b,c,int(h/self.block_size[0]),int(w/self.block_size[1])))
            mask_drop = nn.functional.dropout(mask,p=self.drop_rate)
            big_mask=nn.functional.upsample(mask_drop,size=(h,w), mode='nearest',data_format='NCHW', name=None)
            drop_block_result=x*big_mask#这里用到了自动广播,使big_mask的shape变成了b,c,h,w
            return drop_block_result
        else:
            return x
    
    
np_arr_for_tensor,np_arr=read_img_as_nparr("work/img_train/T104281.jpg")
x=paddle.to_tensor(np_arr_for_tensor,dtype=paddle.float32)
 
dropblock1=DropBlock((80,80),0.3,chanel_independent=False)
drop_block_result1=dropblock1(x)
np_arr_drop_block1=tensor2img(drop_block_result1)

dropblock2=DropBlock((80,80),0.3,chanel_independent=True)
drop_block_result2=dropblock2(x)
np_arr_drop_block2=tensor2img(drop_block_result2)

myimshows([np_arr,np_arr_drop_block1,np_arr_drop_block2],['img','img + dropblock1(chanel_independent=False)','img + dropblock2(chanel_independent=True)'])
图1 dropblock两种使用效果

 这里只强调一点,dropblock应该用在网络的深层,同时drop_rate应该是慢慢变大的,其提出者的多种实验都表明drop_rate为0.1效果最佳。此外,提出者还将dropblock的block_size设得与feature map同样大,达到了dropout2d的效果,实验表明dropout2d与dropblock配合使用效果更佳。

猜你喜欢

转载自blog.csdn.net/a486259/article/details/123964892