您的位置:首页 > 其它

基于PaddlePaddle框架的CV学习

2020-04-22 09:08 190 查看

〇、前言

可是说这应该是第一次尝试深度学习,在学长的安利下尝试了百度推出的深度学习课程,其中包含免费的七日打卡训练营和7*12h的V100算力卡。(咳,我当初才不是因为可以白嫖才被安利成功的)

当然才使用过程中也发现了PaddlePaddle的很多方便之处,以及提供的PaddleSlim可以很方便的进行模型压缩。

可以通过访问飞桨官网(https://www.paddlepaddle.org.cn/)获取关于百度PaddlePaddle的详细信息。

一、数据爬取

在学习过程中,第一个接触到的是数据爬取。

很容易可以想到,深度学习离不开海量的数据,除了使用公开或非公开的数据库外,从网络上爬取需要的数据也是一种非常方便且可行的手段。(比如在后续的口罩识别打卡任务中就使用了从网络上爬取的戴口罩的图片,作为maskimage数据集的一部分)

该训练营也是把这一项任务作为第一次打卡的学习内容,我想除了复习巩固一下基础python知识,也是深度学习序幕的拉开。

(第一在数据爬取之余还讲解了pychart的使用,用于数据可视化。)

二、全连接DNN网络结构

DNN算是图像分类中最基础的网络之一。
其主要特征是上层与下层的神经元都能够形成链接。该网络结构全部由全连接层(fc层)组成,但在PaddlePaddle中没有使用FC这一名称,而是选择了Linear 接口。

在训练营中最先接触的也是全连接DNN网络结构,并在手势识别打卡任务中使用了这一网络,为了跑到0.98至0.99以上的正确率,多次调整全连接层,选择激活函数、通过正则优化和适当的dropout等等来提高准确率、防止过拟合。
DNN所难以避免的是参数量过多的问题,这是全连接DNN网络结构的本身特点所决定的。

class MyDNN(fluid.dygraph.Layer):
def __init__(self):
super(MyDNN,self).__init__()
self.hidden1 = Linear(100,100,act="relu")
self.hidden2 = Linear(100,100,act="relu")
self.hidden3 = Linear(3*100*100,10,act="softmax")
def forward(self,input):
x=self.hidden1(input)
x=fluid.layers.dropout(x,dropout_prob=0.6)
x=self.hidden2(x)
x=fluid.layers.reshape(x,shape=[-1,3*100*100])
y=self.hidden3(x)
return y

三、CNN网络结构

在后续的车牌识别打卡任务中学习到的CNN网络结构在一定程度上解决了前者的问题,其主要增加了卷积层和池化层,且全连接层可以很方便的引入relu参数,使用非线性的激活函数,增强网络的表现能力。

可惜能力不足,在车牌识别中只达到0.98的正确率。

同时,在这次训练任务中学习了如何计算并使用卷积核,防止报错。(依稀记得第二天使用DNN跑手势识别模型的时候想要使用DNN网络结构,结果被一系列error难受到了)

CNN比较基础的是LeNet。在直播课程中除了介绍LeNet,也详细阐述了VGG,ResNet等网络结构。并在后续的口罩识别打卡任务中应用到了VGG的网络结构来提高口罩识别的正确率。

受于VGG网络本身的优势和数据集的局限,在多次epoch后达到了1.0的正确率。(毕竟数据集确实小了点……)

#定义网络
class MyLeNet(fluid.dygraph.Layer):
def __init__(self):
super(MyLeNet,self).__init__()
self.hidden1_1 = Conv2D(1,28,5,1)#通道数、卷积核个数、卷积核大小、步长?
self.hidden1_2 = Pool2D(pool_size=2 , pool_type='max' , pool_stride=1)
self.hidden2_1 = Conv2D(28,32,3,1)
self.hidden2_2 = Pool2D(pool_size=2 , pool_type='max' , pool_stride=1)
self.hidden3 = Conv2D(32,32,3,1)
self.hidden4 = Linear(32*10*10,65,act="softmax")
def forward(self,input):
x=self.hidden1_1(input)
x=self.hidden1_2(x)
x=self.hidden2_1(x)
x=self.hidden2_2(x)
x=self.hidden3(x)
x=fluid.layers.reshape(x,shape=[-1,32*10*10])
y=self.hidden4(x)
return y
class ConvPool(fluid.dygraph.Layer):
'''卷积+池化'''
def __init__(self,
num_channels,
num_filters,
filter_size,
pool_size,
pool_stride,
groups,
pool_padding=0,
pool_type='max',
conv_stride=1,
conv_padding=1,
act=None):
super(ConvPool, self).__init__()

self._conv2d_list = []

for i in range(groups):
conv2d = self.add_sublayer(   #返回一个由所有子层组成的列表。
'bb_%d' % i,
fluid.dygraph.Conv2D(
num_channels=num_channels, #通道数
num_filters=num_filters,   #卷积核个数
filter_size=filter_size,   #卷积核大小
stride=conv_stride,        #步长
padding=conv_padding,      #padding大小,默认为0
act=act)
)
num_channels=num_filters
self._conv2d_list.append(conv2d)

self._pool2d = fluid.dygraph.Pool2D(
pool_size=pool_size,           #池化核大小
pool_type=pool_type,           #池化类型,默认是最大池化
pool_stride=pool_stride,       #池化步长
pool_padding=pool_padding      #填充大小
)

def forward(self, inputs):
x = inputs
for conv in self._conv2d_list:
x = conv(x)
x = self._pool2d(x)
return x

class VGGNet(fluid.dygraph.Layer):
'''
VGG网络
'''
def __init__(self):
super(VGGNet, self).__init__()

#   num_channel  num_filters  filter_size  pool_size  pool_stride  num
self.convpool_1=ConvPool( 3, 64, 3, 2, 2, 2, act="relu")
self.convpool_2=ConvPool( 64,128, 3, 2, 2, 2, act="relu")
self.convpool_3=ConvPool(128,256, 3, 2, 2, 3, act="relu")
self.convpool_4=ConvPool(256,512, 3, 2, 2, 3, act="relu")
self.convpool_5=ConvPool(512,512, 3, 2, 2, 3, act="relu")

self.fc_1=fluid.dygraph.Linear(512*7*7,4096,act="relu")
self.fc_2=fluid.dygraph.Linear(4096, 4096,act="relu")
self.fc_3=fluid.dygraph.Linear(4096, 2,act="softmax")

def forward(self, inputs, label=None):
"""前向计算"""
out=self.convpool_1(inputs)
out=self.convpool_2(out)
out=self.convpool_3(out)
out=self.convpool_4(out)
out=self.convpool_5(out)

out=fluid.layers.reshape(out,shape=[-1,512*7*7])
out=self.fc_1(out)
out=self.fc_2(out)
out=self.fc_3(out)

if label is not None:
acc=fluid.layers.accuracy(input=out,label=label)
return out,acc
else:
return out

四、PaddleSlim

PaddleSlim是一个模型压缩工具库,其主要包含模型剪裁、定点量化、知识蒸馏、超参搜索和模型结构搜索等一系列模型压缩策略。

老师在直播课程中详细讲解了四个主要策略的算法原理和PaddleSlim的应用场景(包括但不限于手机、嵌入式等移动领域。)并实操演示了模型剪裁的一个简易demo。这些课程最大的特点就是理论与时间相结合,每次直播课程都有理论老师先行讲解理论基础,然后由实践老师进行实操演示。

我也在打卡任务中尝试使用了量化api来压缩模型(达到了-71.3%的压缩比,却提高了1.5%的精确度),我主要是使用了int8代替float32来表示模型参数。

PaddleSlim的API使用十分简单,可以在官方文档中获得详细的介绍。

五、结尾

优点:干货足、门槛低、上限高。
缺点:不涉及过于基础的知识,比如像我这样的纯小白就表现得很菜。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
路何求 发布了1 篇原创文章 · 获赞 0 · 访问量 37 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: