【学习有礼】百度技术学院机器学习训练营第二期作业:
进入训练营实验班级,完成班级作业:猫狗分类实验,并在评论区回答以下问题:
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、此奖励仅限训练营同学享有。
恭喜以下同学获得【学习有礼】的奖品,请以下同学私信班主任小果给我邮寄信息,小果会统一安排邮寄哒~~
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
给同学们点赞点赞了
同学你好,恭喜你获得优秀作业,还请私聊班主任小果,给他邮寄信息,方便邮寄奖品给您。
同学你这边获得了优秀作业,请联系班主任小果给他邮寄信息,给你邮寄奖品哈
3班 Thund1r
第二期03班 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,但需要更小心的调节训练参数防止梯度消失问题。
优化算法 验证集loss 验证集acc SGD 1.38066 0.50119 Momentum 1.00568 0.65526 Adagrad 1.27325 0.55014 Adam 1.70402 0.635192、尝试不同的Loss函数和优化算法(SGD、Momentum、Adagrad、Adam),观察效果的变化,最好的选择是什么?为什么?
在分类问题上我们一般都使用cross entropy作为损失函数,尝试四种不同的优化算法,发现各个算法最终收敛情况如下:
可以看到Momentum方法最终验证集的loss最低,acc最高;而Adam次之,SGD是最差的。
3、尝试不同的样本数量:随着每个类别样本数量由少变多,模型准确率变化的曲线是怎样的?每个类别至少有多少张图片可支撑一个准确率尚可的模型? 使用图像分类模型识别世界的万事万物是否可行?(自己编写数据读取程序,而不用默认函数;先完成同学可以在班级群内推送代码,供同学们参考)
曲线的变化随着样本增加越来越接近100%。每个类别有3万张以上可以训练出一个识别准确率尚可的模型。理论上是可行的,需要注意世界万物种类繁多,很难将其穷测,需要把万物中相似的类别聚合,减少总的类别个数,否则类别过多模型收敛不好。
4、使用模型实践:拍一些身边宠物狗的照片(或网上找),处理成32*32尺寸后试试模型效果,准或不准的原因是什么?
我试了一些网上下载的图片,发现识别准主要依靠狗或者猫在画面中比较突出,能显著的从背景中抠出来,而像素或者清晰度不是主要的决定因素。
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尺寸后试试模型效果,准或不准的原因是什么?
效果一般,猜测原因是分辨率过低,导致特征无法有效的被模型识别出来
第5题:
本实验挑战了VGG模型,按照网络结构编写代码如下:
需要修改reader_creator函数,将图片大小需要缩放至224*224,代码如下:
优化器使用了momentum和学习率衰减,代码如下:
vgg16相比之前的实验网络更加复杂,输入图片也更大,所以训练非常慢,原BATCH_SIZE太大,会导致aistudio自动重启,所以改到了16, 但是训练效果显著提升,在第三个epoch时能达到60%+, 最终的训练和测试效果待训练完成后给出。最终acc提升至63%就停止不前了,训练的epoch是数量不够或者学习率还有待进一步调整。
去掉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%, 所下载的图片跟训练的图片也有些差别,比如背景更加复杂,猫的种类也不一样。
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
训练营2班+hulei
第一题:
计算原网络的输入输出, 如下:
test
01班+夜雨飘零
问题:计算每层网络结构和输入输出尺寸和参数个数。不加BN?更深?每层的尺寸变化?更多结构?
答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层之前:
加入了BN层之后:
用BN层的训练情况:
不使用BN层的训练情况:
从图中可以看出使用BN层的准确率更高,训练过程中损失值和准确率的幅度更加小。
答3: 因为该网络的第三层卷积池化层输出的宽和高都是1,所以不能再增加卷积池化层,如果再使用卷积池化层,就会报以下的错误。
3班-李震海
问题4:
图片的长宽比对预测结果有很大影响,分辨率对结果影响不大。
一图识别为猫,把尺寸调成方形的图2就正确识别为狗,图3分辨率降低未影响识别结果
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张
使用图像分类模型识别世界的万事万物,如果只有识别已有类型尚可,如果物体与物体有所属关系,还有未知物体如何处理,简单的分类识别可能适合于监督学习,要识别世界的万事万物,需要有主动学习的能力,无监督学习可能更适合。
二期01班-Lee
(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。
第二期02班+windly
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如何搭建?在预测效果和训练时间上有怎样的差异?原因是什么? (飞桨官网上有参考代码,但不建议马上看)