【百度技术学院机器学习训练营第二期】-实验作业
liushuo008 发布于2019-11-05 浏览:11315 回复:65
15
收藏
最后编辑于2019-11-19

【学习有礼】百度技术学院机器学习训练营第二期作业:

进入训练营实验班级,完成班级作业:猫狗分类实验,并在评论区回答以下问题:

1、网络结构:计算每层网络结构和输入输出尺寸和参数个数。不加BN?更深?每层的尺寸变化?更多结构?

2、尝试不同的Loss函数和优化算法(SGD、Momentum、Adagrad、Adam),观察效果的变化,最好的选择是什么?为什么?

3、尝试不同的样本数量:随着每个类别样本数量由少变多,模型准确率变化的曲线是怎样的?每个类别至少有多少张图片可支撑一个准确率尚可的模型? 使用图像分类模型识别世界的万事万物是否可行?(自己编写数据读取程序,而不用默认函数;先完成同学可以在班级群内推送代码,供同学们参考)

4、使用模型实践:拍一些身边宠物狗的照片(或网上找),处理成32*32尺寸后试试模型效果,准或不准的原因是什么?

5、【挑战题,可选】VGGNet,ResNet如何搭建?在预测效果和训练时间上有怎样的差异?原因是什么? (飞桨官网上有参考代码,但不建议马上看)

 

作业提交截止时间及形式:

截止11月18日中午12点前,跟帖回答作业问题。在跟帖开头请注明:训练营班级+群内昵称(或姓名)以便发送奖励。

 

奖励:

截止11月18日中午12点前,参加【百度技术学院机器学习训练营第二期】并回答作业的同学

1、评论点赞前3名的同学分别获得训练营礼包一份(小度音箱Play1个+机械键盘1个)

2、评论点赞第4-5名同学分别获得机械键盘1个

3、老师点评作业,获得优秀作业同学分别获得双肩背包1个

4、评论有奖:按照评论时间从早到晚的顺序,将抽取第5、10、15、20、25、30、35、40、45、50层同学分别获得招财熊1个。

 

注意:

1、评论点赞前5名要求是回答作业的问题,无关话语不做点赞奖励的计算。

2、如果点赞排名有并列情况,则按照发布时间先后顺序为准,时间早的优先。

3、此奖励仅限训练营同学享有。

收藏
点赞
15
个赞
共65条回复 最后由anfangfei回复于2019-11-19
#63liushuo008回复于2019-11-19

恭喜以下同学获得【学习有礼】的奖品,请以下同学私信班主任小果给我邮寄信息,小果会统一安排邮寄哒~~

1)  作业点赞前五名依次是:
3班Thund1r ;01班郑杨 ; 3班B11040805 ;2班追云戏月 ;3班李震海。
 
2)  老师点评获得优秀作业的同学:
03班新壮;二期02班L;01班叶思风吟;二期01班悠月明;2班追云戏月;189***30;1班袁小白;二期02班李维民;130***50;01班郑杨;二期02班windly;二期01班Lee;2班hulei
 
3)  盖楼有奖获奖同学:
1班袁小白;二期01班悠月明;星光1d1;二期02班李维民;2班追云戏月;01班郑杨;二期02班windly;二期01班Lee

0
#66anfangfei回复于2019-11-19

给同学们点赞点赞了

0
#65liushuo008回复于2019-11-19
#8 130******50回复
我是小白,对于第4题的一些见解 1.使用的测试照片与原训练数据集中相似度本身比较高的,识别比较准。 2.测试照片中物体与背景反差不是很大时,识别不准 3.测试照片中的物体只是某种物体局部的话,识别不准 4.存在逆光照片的话识别不准,与照片拍摄时场景/光线有很大的关系 5.本身训练模型的准确率 6.训练集和测试集的划分不合理等问题 7.训练集中没有我测试图片相关的训练数据 我大概只能说出这么多,基本上是我进行大量替换照片进行测试后得出的结果,其他几道题比较偏理论分析,我会继续加油补上相关的基础知识的,嘻嘻
展开

同学你好,恭喜你获得优秀作业,还请私聊班主任小果,给他邮寄信息,方便邮寄奖品给您。

0
#64liushuo008回复于2019-11-19
#37 189******30回复
1.不加BN对简单网络影响有限,三层网络梯度没那么容易消失吧。增加卷积层数能够提升模型学习更多不同“粒度”下图片特征的能力,增加全连接层能够提升模型分类的“非线性能力”以提升分类精确度 。 2.(1)SGD随机抽取数据收敛较慢;Momentum通过累加梯度加速,比SGD收敛快;Adagrad除以历史梯度的平方叠加,使收敛开始加速,逐渐减速;Adam通过计算梯度的一阶矩估计和二阶矩估计而为不同的参数设计独立的自适应性学习率,结合了Adagrad和RMSProp的长处,是入门使用的最佳选择。这些优化算法本质上都是对SGD收敛速度的优化,主要优化模型的学习速度,而非分类能力。(2)交叉熵不但能反应模型分类的准确与否,还能反应其分类匹配的程度用作梯度下降的依据。如果用分类准确率作为损失函数的话,模型可能会优先选择分类准确率更高的参数,而非匹配度更高的。而模型应当通过匹配度来学习图片数据中的分类特征。那些恰好准确率高而匹配度低的参数是没有学习价值的,是干扰。 3.学习充分的模型的准确率在增加数据量的过程中应该呈对数增长吧,增加数据对准确率的提升应当是逐渐减小的。如果是类似于线性的增长,说明当前的数据量对于此能力的模型来说还不够。当然,能力强的模型对数据量的要求更小。我觉得对一个系统来说,性能的上限是数据决定的。好的模型只能更近更快逼地近这个上限。而且只要每天有新的事物产生,就会产生新的数据。所以理论上分类万事万物是不可能的,就像尺子的刻度永远不能超过尺子本身的长度一样吧。但是对实际应用来说,“人工智能”的性能只要超过“人工”的性能或性价比就有应用价值了吧。 4.自己手机拍*-的照片识别率较低。考虑可能是由于拍摄设备的色差,光线等导致。解决思路:对训练模型的数据和预测数据进行相同的灰度化,自动色阶这样的“归一化”处理,使模型更专注的学习图片的轮廓和纹理特征。
展开

同学你这边获得了优秀作业,请联系班主任小果给他邮寄信息,给你邮寄奖品哈

0
#62学长小美回复于2019-11-18

3班 Thund1r

13
#61B11040805回复于2019-11-17
#60 B11040805回复
1、网络结构:计算每层网络结构和输入输出尺寸和参数个数。不加BN?更深?每层的尺寸变化?更多结构? 输入的尺寸为[128,3,32,32],128为batch size,表示图片有3个通道,大小为32*32; 第一层CNN卷积核为5*5,步长为1*1,卷积核个数20,,每个卷积核的feature map为(32-5)/1+1=28,而池化层窗长为2*2,步长2*2,池化之后大小为(28-2)/2+1=14,那么第一层CNN的输出为[128,20,14,14],参数量为CNN中所有卷积核的weight矩阵大小加bias向量大小,参数量为(5*5+5)*20*3=1800。加BN层不影响参数量大小,BN起到的作用在小训练集对网络启动稳定收敛的作用,在大数据集上影响不大; 第二层CNN计算同理,输入为[128,20,14,14],输出为[128,50,5,5],参数量为(5*5+5)*50*20=30000; 第三层CNN输入为[128,50,5,5],输出为[128,50,1,1],参数量为(5*5+5)*50*50=75000 输出的尺寸为[128,10]。 可以尝试更深层的CNN,但需要更小心的调节训练参数防止梯度消失问题。 2、尝试不同的Loss函数和优化算法(SGD、Momentum、Adagrad、Adam),观察效果的变化,最好的选择是什么?为什么? 在分类问题上我们一般都使用cross entropy作为损失函数,尝试四种不同的优化算法,发现各个算法最终收敛情况如下: 优化算法 验证集loss 验证集acc SGD 1.38066 0.50119 Momentum 1.00568 0.65526 Adagrad 1.27325 0.55014 Adam 1.70402 0.63519 可以看到Momentum方法最终验证集的loss最低,acc最高;而Adam次之,SGD是最差的。 3、尝试不同的样本数量:随着每个类别样本数量由少变多,模型准确率变化的曲线是怎样的?每个类别至少有多少张图片可支撑一个准确率尚可的模型? 使用图像分类模型识别世界的万事万物是否可行?(自己编写数据读取程序,而不用默认函数;先完成同学可以在班级群内推送代码,供同学们参考) 曲线的变化随着样本增加越来越接近100%。每个类别有3万张以上可以训练出一个识别准确率尚可的模型。理论上是可行的,需要注意世界万物种类繁多,很难将其穷测,需要把万物中相似的类别聚合,减少总的类别个数,否则类别过多模型收敛不好。 4、使用模型实践:拍一些身边宠物狗的照片(或网上找),处理成32*32尺寸后试试模型效果,准或不准的原因是什么? 我试了一些网上下载的图片,发现识别准主要依靠狗或者猫在画面中比较突出,能显著的从背景中抠出来,而像素或者清晰度不是主要的决定因素。
展开

第二期03班 B11040805

0
#60B11040805回复于2019-11-17

1、网络结构:计算每层网络结构和输入输出尺寸和参数个数。不加BN?更深?每层的尺寸变化?更多结构?
输入的尺寸为[128,3,32,32],128为batch size,表示图片有3个通道,大小为32*32;
第一层CNN卷积核为5*5,步长为1*1,卷积核个数20,,每个卷积核的feature map为(32-5)/1+1=28,而池化层窗长为2*2,步长2*2,池化之后大小为(28-2)/2+1=14,那么第一层CNN的输出为[128,20,14,14],参数量为CNN中所有卷积核的weight矩阵大小加bias向量大小,参数量为(5*5+5)*20*3=1800。加BN层不影响参数量大小,BN起到的作用在小训练集对网络启动稳定收敛的作用,在大数据集上影响不大;
第二层CNN计算同理,输入为[128,20,14,14],输出为[128,50,5,5],参数量为(5*5+5)*50*20=30000;
第三层CNN输入为[128,50,5,5],输出为[128,50,1,1],参数量为(5*5+5)*50*50=75000
输出的尺寸为[128,10]。
可以尝试更深层的CNN,但需要更小心的调节训练参数防止梯度消失问题。


2、尝试不同的Loss函数和优化算法(SGD、Momentum、Adagrad、Adam),观察效果的变化,最好的选择是什么?为什么?
在分类问题上我们一般都使用cross entropy作为损失函数,尝试四种不同的优化算法,发现各个算法最终收敛情况如下:

优化算法 验证集loss 验证集acc SGD 1.38066 0.50119 Momentum 1.00568 0.65526 Adagrad 1.27325 0.55014 Adam 1.70402 0.63519

可以看到Momentum方法最终验证集的loss最低,acc最高;而Adam次之,SGD是最差的。
3、尝试不同的样本数量:随着每个类别样本数量由少变多,模型准确率变化的曲线是怎样的?每个类别至少有多少张图片可支撑一个准确率尚可的模型? 使用图像分类模型识别世界的万事万物是否可行?(自己编写数据读取程序,而不用默认函数;先完成同学可以在班级群内推送代码,供同学们参考)
曲线的变化随着样本增加越来越接近100%。每个类别有3万张以上可以训练出一个识别准确率尚可的模型。理论上是可行的,需要注意世界万物种类繁多,很难将其穷测,需要把万物中相似的类别聚合,减少总的类别个数,否则类别过多模型收敛不好。
4、使用模型实践:拍一些身边宠物狗的照片(或网上找),处理成32*32尺寸后试试模型效果,准或不准的原因是什么?
我试了一些网上下载的图片,发现识别准主要依靠狗或者猫在画面中比较突出,能显著的从背景中抠出来,而像素或者清晰度不是主要的决定因素。

9
#59chenhongyin_bj回复于2019-11-17

01班-陈洪银

1、网络结构:计算每层网络结构和输入输出尺寸和参数个数。不加BN?更深?每层的尺寸变化?更多结构?

输入输出尺寸:(不包含批量维度)
初始状态:3*32*32 图片
第一个卷积层,20 * 28 * 28 (28 = 32 - (5 - 1))
最大池化后:20*14*14
参数个数:20x(5x5x3 + 1) = 1520
第二个卷积层,50 * 10 * 10 (10 = 14 - (5-1))
最大池化后:50*5*5
参数个数:50x(5x5x20 + 1)
第三个卷积层:50 * 1 * 1 (1 = 5 - (5 -1))
最大池化后 50*1*1
参数个数:50x(5x5x50 + 1)
输出 全连接 10 个概率值
参数个数:50x(10+1)


带BN的效果:


不加BN的效果:

加BN的好处
局部响应归一化层
较大的学习率,使得训练速度增长很快,具有快速收敛性
使得系统不那么依赖初始值
一定程度上抑制过拟合


尝试修改了一种网络深度:
img.shape: (-1, 3, 32, 32)
conv_pool_1.shape: (-1, 20, 14, 14)
conv_pool_2.shape: (-1, 50, 6, 6)
conv_pool_3.shape: (-1, 50, 2, 2)
conv_pool_4.shape: (-1, 50, 1, 1)
conv_pool_5.shape: (-1, 10)
prediction.shape: (-1, 10)

效果变差


2、尝试不同的Loss函数和优化算法(SGD、Momentum、Adagrad、Adam),观察效果的变化,最好的选择是什么?为什么?
分类问题,交叉熵损失函数最合适
Adam优化算法最好,原因:中和了其他几种优化算法的优点,在训练过程中,每个参数有不同的学习率和Momentum,提升了模型训练的稳定性

3、尝试不同的样本数量:随着每个类别样本数量由少变多,模型准确率变化的曲线是怎样的?每个类别至少有多少张图片可支撑一个准确率尚可的模型? 使用图像分类模型识别世界的万事万物是否可行?(自己编写数据读取程序,而不用默认函数;先完成同学可以在班级群内推送代码,供同学们参考)
从有500以上样本,可以获取不错的准确值
4、使用模型实践:拍一些身边宠物狗的照片(或网上找),处理成32*32尺寸后试试模型效果,准或不准的原因是什么?
效果一般,猜测原因是分辨率过低,导致特征无法有效的被模型识别出来

1
#58thunder95回复于2019-11-17
#57 thunder95回复
去掉BN层: 不影响输入或输出尺寸变化,也不增加额外的参数数量,实验效果无明显变化 加更深的网络,中间加两层卷积不池化: 在第一层和第二层,以及第二层和第三层中间分别加上filter_size=35, stride=1,filter_size=3的卷积层(没有池 化层下采样),尺寸变化如下: 第一层:(128, 20, 14, 14), 第一加层: (14-3+2)/1+1, 仍旧是(128, 20, 14, 14), 第二层:(128, 50, 5, 5), 第二加层: (5-3+2)/1+1, 仍旧是(128, 50, 5, 5) 第三层和最终输出军保持不变。 同等条件下训练效果:准确率提升至67%, 训练收敛更稳定 修改网络结构,按李老师视频里的建议:,3x3卷积+bn+relu+pool, 增加两个全连接层,输入尺寸不变: (128, 3, 32, 32) 第一层卷积池化(num_filters=64, filter_size=3, padding=1, pool_size=2, pool_stride=2): (128, 64, 16, 16) 第二层卷积池化(num_filters=128, filter_size=3, padding=1, pool_size=2, pool_stride=2):(128, 128, 8, 8) 第三层卷积池化(num_filters=256, filter_size=3, padding=1, pool_size=2, pool_stride=2): (128, 256, 4, 4) 全连接1(size=512):(128, 512) 全连接2(size=512):(128, 512) 全连接3+softmax(size=10): (128, 10) 训练效果: 收敛较快,后期也比较稳定,效果显著提升至79.4% 代码如下: [代码] 第2题: 不同的Loss函数, 均方差误差损失函数(需要修改最后一层全连接,注释掉acc评估): 发现训练集收敛效果较好收敛也较平稳,但是验证集一直来 回震荡不下降,且cost相对训练集非常高(30倍以上)。最终的预测结果也非常差,测试的几张图片全部预测错误。经分析,交叉熵倾向于对正确分类的学习,而均方差对于正确和错误的分类同等对待,这样达不到分类学习的目的。 prediction = fluid.layers.fc(input=conv_pool_3, size=1, act=None) cost = fluid.layers.square_error_cost(input=predict, label=label) 不同的优化算法(SGD、Momentum、Adagrad、Adam):将4个优化器的曲线打印观察,目测是momentum效果最好,但是没做进一步的分析,比如学习率和epochs没做更多调整, 跟其他同学的实验结果有出入,一定程度上跟训练的随机性有关吧。同等条件下,sgd和adagrad震荡剧烈,收敛缓慢,且cost和acc效果都不太好,而adam和momentum相比曲线震荡缓和,cost收敛下降较快,最终的效果也较好。 optimizer =fluid.optimizer.Adam(learning_rate=0.001) optimizer = fluid.optimizer.SGD(learning_rate=0.001) optimizer = fluid.optimizer.MomentumOptimizer(learning_rate=0.001, momentum=0.9) optimizer = fluid.optimizer.Adagrad(learning_rate=0.001) [图片] 第3题: 尝试不同的样本数量:按照cifar给出的data_batch, 分别尝试样本量在10000, 20000, 30000, 40000, 5000的测试集效果,发现数据量越大训练时间越长,平均ACC越高, 样本量越低过拟合越严重,测试集acc低但是训练集acc高; 样本数量在40000时已经能达到全样本量的训练和测试效果。使用图像分类模型识别世界的万事万物个人认为不可行,类别过多,数据量太大训练难度太大,图像分类最好是解决特定的问题效果会更好。我没有重写reader,只是修改原来的reader()函数: [代码] [图片] 第4题: 在百度里下载了宠物猫的图片并resize到32x32大小, 经测试训练的模型效果不太好,应该是模型本身就欠拟合,在验证集上准确率才65%, 所下载的图片跟训练的图片也有些差别,比如背景更加复杂,猫的种类也不一样。  
展开

第5题:
本实验挑战了VGG模型,按照网络结构编写代码如下:

def conv_block(layer, conv_num=2, num_filters=64, pool_size=0):
    for i in range(conv_num):
        layer = fluid.layers.conv2d(input=layer, num_filters=num_filters, filter_size=3, act="relu")
    layer = fluid.layers.pool2d(input=layer, pool_size=pool_size, pool_stride=pool_size)
    return layer

def fc_layers(layer, size_list):
    for size in size_list:
         layer = fluid.layers.fc(input=layer, size=size, act="relu")
    return layer
    
def vgg16_net(img):
    layer = conv_block(img, conv_num=2, num_filters=64, pool_size=2)#第一块
    layer = conv_block(layer, conv_num=2, num_filters=128, pool_size=2)#第二块
    layer = conv_block(layer, conv_num=3, num_filters=256, pool_size=2)#第三块
    layer = conv_block(layer, conv_num=3, num_filters=512, pool_size=2)#第四块
    layer = conv_block(layer, conv_num=3, num_filters=512, pool_size=2)#第五块
    layer = fc_layers(layer, [4096, 4096, 1000])
    return fluid.layers.fc(input=layer, size=10, act='softmax')

需要修改reader_creator函数,将图片大小需要缩放至224*224,代码如下:

    def read_batch(batch):
        data = batch[six.b('data')]
        labels = batch.get(
            six.b('labels'), batch.get(six.b('fine_labels'), None))
        assert labels is not None

        resize = True
        one_hot = False
        for sample, label in six.moves.zip(data, labels):
            #print("============>", sample.shape) #这里是单个样本一维3072
          
            #修改原图大小, 用于vgg
            if resize:
                sample = sample.reshape(3, 32, 32).transpose(1, 2, 0).astype("float")
                sample = cv2.resize(sample, (224,224))
                sample = sample.transpose(2, 0, 1).astype('uint8')
                sample = sample.ravel()
            
            label = int(label)
            #转为one-hot, 修改输出, 测试其他loss所需
            if one_hot:
                a = [0]*10
                a[label] = 1
                label = a
            #print(sample.shape)
            yield (sample / 255.0).astype(numpy.float32), label

优化器使用了momentum和学习率衰减,代码如下:

optimizer = fluid.optimizer.Momentum(
    momentum=0.9,
    learning_rate=fluid.layers.natural_exp_decay(
    learning_rate=0.01,
    decay_steps=10000,
    decay_rate=0.5,
    staircase=True))

vgg16相比之前的实验网络更加复杂,输入图片也更大,所以训练非常慢,原BATCH_SIZE太大,会导致aistudio自动重启,所以改到了16, 但是训练效果显著提升,在第三个epoch时能达到60%+, 最终的训练和测试效果待训练完成后给出。最终acc提升至63%就停止不前了,训练的epoch是数量不够或者学习率还有待进一步调整。

 

0
#57thunder95回复于2019-11-17
#56 thunder95回复
batch_size:128 输入尺寸:(128, 3, 32, 32) 第一层参数个数: 20x(5x5x3 + 1), 卷积输出: (32-5+2x0)/1+1=28, 池化输出:(28-2+2x0)/2+1=14,尺寸:(128, 20, 14, 14) 第二层参数个数: 50x(5x5x20 + 1), 卷积输出: (14-5+2x0)/1+1=10, 池化输出:(10-2+2x0)/2+1=5, 尺寸:(128, 50, 5, 5) 第三层参数个数: 50x(5x5x50 + 1), 卷积输出: (5-5+2x0)/1+1=1, 池化输出:(1-2+2x0)/2+1=1, 尺寸: (128,50,1,1) 全连接输出, 参数个数:50x(10+1), 输出尺寸: (128,10) 验证计算,以第一层为例: 直接print某个层的shape查看,或者用fluid.layers.Print可以观察网络结构,包括layer的shape,dtype和具体的data数据 近似计算w和b的比例,查看模型文件 conv2d_0.b_0 : 104b; conv2d_0.w_0: 5.9KB
展开

去掉BN层: 不影响输入或输出尺寸变化,也不增加额外的参数数量,实验效果无明显变化

加更深的网络,中间加两层卷积不池化: 在第一层和第二层,以及第二层和第三层中间分别加上filter_size=35, stride=1,filter_size=3的卷积层(没有池 化层下采样),尺寸变化如下:
第一层:(128, 20, 14, 14), 第一加层: (14-3+2)/1+1, 仍旧是(128, 20, 14, 14),
第二层:(128, 50, 5, 5), 第二加层: (5-3+2)/1+1, 仍旧是(128, 50, 5, 5)
第三层和最终输出军保持不变。
同等条件下训练效果:准确率提升至67%, 训练收敛更稳定

修改网络结构,按李老师视频里的建议:,3x3卷积+bn+relu+pool, 增加两个全连接层,输入尺寸不变: (128, 3, 32, 32)
第一层卷积池化(num_filters=64, filter_size=3, padding=1, pool_size=2, pool_stride=2): (128, 64, 16, 16)
第二层卷积池化(num_filters=128, filter_size=3, padding=1, pool_size=2, pool_stride=2):(128, 128, 8, 8)
第三层卷积池化(num_filters=256, filter_size=3, padding=1, pool_size=2, pool_stride=2): (128, 256, 4, 4)
全连接1(size=512):(128, 512)
全连接2(size=512):(128, 512)
全连接3+softmax(size=10): (128, 10)
训练效果: 收敛较快,后期也比较稳定,效果显著提升至79.4%
代码如下:

conv1 = fluid.layers.conv2d(input=img, num_filters=64, filter_size=3, padding=1)
print("conv1: ", conv1.shape)
bn1 = fluid.layers.batch_norm(input=conv1)
act1 = fluid.layers.relu(bn1)
pool1 = fluid.layers.pool2d(input=act1, pool_size=2, pool_stride=2)

conv2 = fluid.layers.conv2d(input=pool1, num_filters=128, filter_size=3, padding=1)
bn2 = fluid.layers.batch_norm(input=conv2)
act2 = fluid.layers.relu(bn2)
pool2 = fluid.layers.pool2d(input=act2, pool_size=2, pool_stride=2)

conv3 = fluid.layers.conv2d(input=pool2, num_filters=256, filter_size=3, padding=1)
bn3 = fluid.layers.batch_norm(input=conv3)
act3 = fluid.layers.relu(bn3)
pool3 = fluid.layers.pool2d(input=act3, pool_size=2, pool_stride=2)

fc1 = fluid.layers.fc(input=pool3, size=512, act="relu")
fc2 = fluid.layers.fc(input=fc1, size=512, act="relu")
prediction = fluid.layers.fc(input=fc2, size=10, act='softmax')


第2题:

不同的Loss函数, 均方差误差损失函数(需要修改最后一层全连接,注释掉acc评估): 发现训练集收敛效果较好收敛也较平稳,但是验证集一直来 回震荡不下降,且cost相对训练集非常高(30倍以上)。最终的预测结果也非常差,测试的几张图片全部预测错误。经分析,交叉熵倾向于对正确分类的学习,而均方差对于正确和错误的分类同等对待,这样达不到分类学习的目的。

prediction = fluid.layers.fc(input=conv_pool_3, size=1, act=None)
cost = fluid.layers.square_error_cost(input=predict, label=label)
不同的优化算法(SGD、Momentum、Adagrad、Adam):将4个优化器的曲线打印观察,目测是momentum效果最好,但是没做进一步的分析,比如学习率和epochs没做更多调整, 跟其他同学的实验结果有出入,一定程度上跟训练的随机性有关吧。同等条件下,sgd和adagrad震荡剧烈,收敛缓慢,且cost和acc效果都不太好,而adam和momentum相比曲线震荡缓和,cost收敛下降较快,最终的效果也较好。

optimizer =fluid.optimizer.Adam(learning_rate=0.001)
optimizer = fluid.optimizer.SGD(learning_rate=0.001)
optimizer = fluid.optimizer.MomentumOptimizer(learning_rate=0.001, momentum=0.9)
optimizer = fluid.optimizer.Adagrad(learning_rate=0.001)


第3题:
尝试不同的样本数量:按照cifar给出的data_batch, 分别尝试样本量在10000, 20000, 30000, 40000, 5000的测试集效果,发现数据量越大训练时间越长,平均ACC越高, 样本量越低过拟合越严重,测试集acc低但是训练集acc高; 样本数量在40000时已经能达到全样本量的训练和测试效果。使用图像分类模型识别世界的万事万物个人认为不可行,类别过多,数据量太大训练难度太大,图像分类最好是解决特定的问题效果会更好。我没有重写reader,只是修改原来的reader()函数:

def reader():
        while True:
            with tarfile.open(filename, mode='r') as f:
                names = (each_item.name for each_item in f
                         if sub_name in each_item.name)
                         
                batch_num = 0
                target_num = 5 #cifar一共6个批次, 每个批次1w,控制输入批次的数量
                for name in names:
                    batch_num += 1
                    if batch_num>target_num:
                        break
                    
                    if six.PY2:
                        batch = pickle.load(f.extractfile(name))
                    else:
                        batch = pickle.load(
                            f.extractfile(name), encoding='bytes')
                    for item in read_batch(batch):
                        yield item

            if not cycle:
                break

第4题:
在百度里下载了宠物猫的图片并resize到32x32大小, 经测试训练的模型效果不太好,应该是模型本身就欠拟合,在验证集上准确率才65%, 所下载的图片跟训练的图片也有些差别,比如背景更加复杂,猫的种类也不一样。

 

2
#56thunder95回复于2019-11-17

batch_size:128
输入尺寸:(128, 3, 32, 32)
第一层参数个数: 20x(5x5x3 + 1), 卷积输出: (32-5+2x0)/1+1=28, 池化输出:(28-2+2x0)/2+1=14,尺寸:(128, 20, 14, 14)
第二层参数个数: 50x(5x5x20 + 1), 卷积输出: (14-5+2x0)/1+1=10, 池化输出:(10-2+2x0)/2+1=5, 尺寸:(128, 50, 5, 5)
第三层参数个数: 50x(5x5x50 + 1), 卷积输出: (5-5+2x0)/1+1=1, 池化输出:(1-2+2x0)/2+1=1, 尺寸: (128,50,1,1)
全连接输出, 参数个数:50x(10+1), 输出尺寸: (128,10)

验证计算,以第一层为例:
直接print某个层的shape查看,或者用fluid.layers.Print可以观察网络结构,包括layer的shape,dtype和具体的data数据
近似计算w和b的比例,查看模型文件 conv2d_0.b_0 : 104b; conv2d_0.w_0: 5.9KB

0
#55thunder95回复于2019-11-17

训练营2班+hulei
第一题:
计算原网络的输入输出, 如下:

0
#54thunder95回复于2019-11-17

test

0
#53天子骄子fly回复于2019-11-17

01班+夜雨飘零

问题:计算每层网络结构和输入输出尺寸和参数个数。不加BN?更深?每层的尺寸变化?更多结构?

def convolutional_neural_network(img):
    print('输入层的shape:', img.shape)
    conv_pool_1 = fluid.nets.simple_img_conv_pool(
        input=img,
        filter_size=5,
        num_filters=20,
        pool_size=2,
        pool_stride=2,
        act="relu")
    print('第一层卷积池化层输出shape:', conv_pool_1.shape)
    conv_pool_1 = fluid.layers.batch_norm(conv_pool_1)
    conv_pool_2 = fluid.nets.simple_img_conv_pool(
        input=conv_pool_1,
        filter_size=5,
        num_filters=50,
        pool_size=2,
        pool_stride=2,
        act="relu")
    print('第二层卷积池化层输出shape:', conv_pool_2.shape)
    conv_pool_2 = fluid.layers.batch_norm(conv_pool_2)
    conv_pool_3 = fluid.nets.simple_img_conv_pool(
        input=conv_pool_2,
        filter_size=5,
        num_filters=50,
        pool_size=2,
        pool_stride=2,
        act="relu")
    print('第三层卷积池化层输出shape:', conv_pool_3.shape)
    prediction = fluid.layers.fc(input=conv_pool_3, size=10, act='softmax')
    print('全连接层输出shape:', prediction.shape)
    return prediction

 


答1: 本网络的的输入数据的shape为(128, 3, 32, 32),所以输出如下:
第一层的卷积层输出shape:(128, 20, 28, 28),参数大小为:20*3*5*5=150020∗3∗5∗5=1500
第一层的池化层输出shape:(128, 20, 14, 14)
第二层的卷积层输出shape:(128, 50, 10, 10),参数大小为:50*20*5*5=2500050∗20∗5∗5=25000
第二层的池化层输出shape:(128, 50, 5, 5)
第三层的卷积层输出shape:(128, 50, 1, 1),参数大小为:50*50*5*5=6250050∗50∗5∗5=62500
第三层的池化层输出shape:(128, 50, 1, 1)
最后的全连接层输出shape:(128, 10),参数大小为:50*10=50050∗10=500
总参数大小:1500+25000+62500+500=895001500+25000+62500+500=89500


PaddlePaddle的网络输出
输入层的shape: (-1, 3, 32, 32)
第一层卷积池化层输出shape: (-1, 20, 14, 14)
第二层卷积池化层输出shape: (-1, 50, 5, 5)
第三层卷积池化层输出shape: (-1, 50, 1, 1)
全连接层输出shape: (-1, 10)

答2:
在没有使用BN层之前:

  • 参数的更新,使得每层的输入输出分布发生变化,称作ICS(Internal Covariate Shift)
  • 差异hui会随着网络深度增大而增大
  • 需要更小的学习率和较好的参数进行初始化


加入了BN层之后:

  • 可以使用较大的学习率
  • 可以减少对参数初始化的依赖
  • 可以拟制梯度的弥散
  • 可以起到正则化的作用
  • 可以加速模型收敛速度


用BN层的训练情况:


不使用BN层的训练情况:



从图中可以看出使用BN层的准确率更高,训练过程中损失值和准确率的幅度更加小。
答3: 因为该网络的第三层卷积池化层输出的宽和高都是1,所以不能再增加卷积池化层,如果再使用卷积池化层,就会报以下的错误。

EnforceNotMet: Due to the settings of padding(0), filter_size(5), dilation(1) and stride(1), the output size is less than 0, please check again. Input_size:1
2
#52lizh_nes回复于2019-11-17

3班-李震海

问题4:

图片的长宽比对预测结果有很大影响,分辨率对结果影响不大。

一图识别为猫,把尺寸调成方形的图2就正确识别为狗,图3分辨率降低未影响识别结果

5
#51gflpower回复于2019-11-17

2班+高飞龙


1、网络结构:计算每层网络结构和输入输出尺寸和参数个数。不加BN?更深?每层的尺寸变化?更多结构?
conv_pool_1 -> 输入为[3*32*32] 卷积后 20*28*28 池化后 20*14*14

conv_pool_2 -> 输入为[20,14,14] 卷积后 50*10*10 池化后 50*5*5

conv_pool_3 -> 输入为50*5*5 卷积后 50*1*1 池化后 50*1*1

prediction -> 全连接层 输出单元的数目为10, 意为有10种输出结果,回归方式为:softmax,


bn的作用是防止过拟合, 一般用在卷积后,池化前


2、尝试不同的Loss函数和优化算法(SGD、Momentum、Adagrad、Adam),观察效果的变化,最好的选择是什么?为什么?
Adam正确效率最高


3、尝试不同的样本数量:随着每个类别样本数量由少变多,模型准确率变化的曲线是怎样的?每个类别至少有多少张图片可支撑一个准确率尚可的模型? 使用图像分类模型识别世界的万事万物是否可行?(自己编写数据读取程序,而不用默认函数;先完成同学可以在班级群内推送代码,供同学们参考)
样本少的情况下,训练时正确率的波动范围较大,成本的波动范围也较大
500张
使用图像分类模型识别世界的万事万物,如果只有识别已有类型尚可,如果物体与物体有所属关系,还有未知物体如何处理,简单的分类识别可能适合于监督学习,要识别世界的万事万物,需要有主动学习的能力,无监督学习可能更适合。

0
#50Simsimilix回复于2019-11-17

二期01班-Lee

0
#49Simsimilix回复于2019-11-17

(1)
input_layer: [32, 32, 3]
conv1_out: [28, 28. 20]
pool1_out: [14, 14, 20]
conv2_out: [10, 10, 50]
pool2_out: [5, 5, 50]
conv3_out; [1, 1, 50]
pool3_out: [1, 1, 50]

params = in_features * height * weight * out_features
conv1_params: 3*5*5*20=1500
conv2_params: 20*5*5*50=25000
conv3_params: 50*5*5*50=62500
fc: 50*10=500

with_BN:
best_acc: 68.02%
no_BN:
best_acc: 68.39%
对于简单网络来说,BN的作用有限。

(2)
epoch=20
SGD: 48%
Moment: 65%
Adagrad: 57%
Adam: 68%
训练相同次数,在此任务下,Adam收敛最快,效果最好。
因为是分类问题,所以使用交叉熵损失函数。
附图如下:可以看出来Adam收敛最好最快。

(3)
直接使用数据时,每类500样本时发生过拟合了。
可以考虑数据增强等方式加强模型效果。

(4)
主体占画面比例过小导致。

(5)
层数变深,参数增多,如果样本不够的话很容易过拟合,同时训练时间变长。所以一般用预训练后的模型来finetune。

1
#48windly4548回复于2019-11-16

第二期02班+windly

0
#47windly4548回复于2019-11-16

class Cifar10DataReader():

    import os

    import random

    import numpy as np

    import pickle

    def __init__(self, cifar_file, one_hot=False, file_number=1):

        self.train_data = list()

                   self.test_data =list()

        self.batch_index = 0  # 第i批次

        self.cifar_file = cifar_file # 数据集所在dir

                   self.one_hot = one_hot

         self.train_data = self.read_train_file()

                   self.test_data = self.read_test_data()  # 得到测试集数据

    # 读取数据函数,返回dict

    def unpickle(self, file):

        with open(file, 'rb') as fo:

            try:

                dicts = self.pickle.load(fo, encoding='bytes')

            except Exception as e:

                print('load error', e)

            return dicts

 

    # 读取一个训练集文件,返回数据list

    def read_train_file(self, files=''):

        files = self.os.path.join(self.cifar_file, files)

                   list_file = os.listdir(files)

                   for i in rang(batch_index,len(list_file)):

            path = os.path.join(rootdir,list_file[i])

                            if os.path.isfile(path):

                                     if path.find(r'data_batch_')>=0:

                                    dict_train = self.unpickle(path)

                                               if len(demo_list):

                                                        train_data.append(zip(dict_train[b'data'], dict_train[b'labels']))

                                               else:

                             train_data = list(zip(dict_train[b'data'], dict_train[b'labels']))  # 将数据和对应标签打包

                                    self.np.random.shuffle(train_data)

    return train_data

 

    # 读取测试集数据

    def read_test_data(self):

        files = self.os.path.join(self.cifar_file, 'test_batch')

        dict_test = self.unpickle(files)

        test_data = list(zip(dict_test[b'data'], dict_test[b'labels']))  # 将数据和对应标签打包

        print('成功读取测试集数据')

        return test_data

 

    # 编码得到的数据,变成张量,并分别得到数据和标签

    def encodedata(self, detum):

        rdatas = list()

        rlabels = list()

        for d, l in detum:

            rdatas.append(self.np.reshape(self.np.reshape(d, [3, 1024]).T, [32, 32, 3]))

            if self.one_hot:

                hot = self.np.zeros(10)

                hot[int(l)] = 1

                rlabels.append(hot)

            else:

                rlabels.append(l)

        return rdatas, rlabels

 

    # 得到batch_size大小的数据和标签

    def nex_train_data(self, batch_size=100):

        assert 1000 % batch_size == 0, 'erro batch_size can not divied!'  # 判断批次大小是否能被整除

 

        # 获得一个batch_size的数据

        if self.batch_index < len(self.train_data) // batch_size:  # 是否超出一个文件的数据量

            detum = self.train_data[self.batch_index * batch_size:(self.batch_index + 1) * batch_size]

            datas, labels = self.encodedata(detum)

            self.batch_index += 1

        else:  # 超出了就加载下一个文件

            self.batch_index = 0

            if self.file_number == 5:

                self.file_number = 1

            else:

                self.file_number += 1

            self.read_train_file()

            return self.nex_train_data(batch_size=batch_size)

        return datas, labels

 

    # 随机抽取batch_size大小的训练集

    def next_test_data(self, batch_size=100):

        detum = self.random.sample(self.test_data, batch_size)  # 随机抽取

        datas, labels = self.encodedata(detum)

        return datas, labels

 

 

if __name__ == '__main__':

    import matplotlib.pyplot as plt

 

    Cifar10 = Cifar10DataReader(r' /home/aistudio/.cache/paddle/dataset/cifar/cifar-10-batches-py ', one_hot=True)

    d, l = Cifar10.nex_train_data()

 

4、使用模型实践:拍一些身边宠物狗的照片(或网上找),处理成32*32尺寸后试试模型效果,准或不准的原因是什么?

模型不准,在测试图片里测试,会出现模型错误,不准的原因应该是网络结构,获取图片批次需要优化,图片训练集过小

 

5、【挑战题,可选】VGGNet,ResNet如何搭建?在预测效果和训练时间上有怎样的差异?原因是什么? (飞桨官网上有参考代码,但不建议马上看)

1
快速回复
TOP
切换版块