本课分为理论和实战两个部分。
理论:深度学习解析
1.什么是深度学习
深度学习使用神经网络这种函数来解决机器学习问题!层数多所以深度!
2.图像识别为什么用深度学习
从原始信号摄入(瞳孔摄入像素Pixels)->初步处理(大脑皮层某些细胞发现边缘和方向)->抽象(大脑判定,眼前的物体的形状,是圆形的)->进一步抽象(大脑进一步判定该物体是人脸)
从原始信号,做低级抽象,逐渐向高级抽象迭代
使用机器学习(深度学习)的目的:寻找一个合适的函数,使得输入和输入练习起来。
深度学习过程:人根据经验预先确定函数集合,确定评价好坏标准,机器通过从训练数据的答案中学习挑出最好的函数。
具体来说就是:
一、建立模型 选择什么样的网络结构,选择多少层数,每层选择多少神经元
二、损失函数 选择常用损失函数,平方误差,交叉熵...
三、参数学习 梯度下降,反向传播算法
神经元结构如下:
神经网络:具体的选型,层数需要根据具体问题和经验进行判定,不断地调试优化确定最优解。
输出层:需要根据情况改变输出层的激活函数。一般而言,回归问题用恒等函数,分类问题用softmax函数。机器学习大致可以分为分类问题和回归问题。分类问题是数据属于哪一个类别的问题。比如,区分图像中的人是男性还是女性的问题就是分类问题。而回归问题是根据某个输入预测一个(连续的)数值问题。比如,根据一个人的图像预测这个人的体重的问题就是回归问题,根据房屋面积预测出售价格(类似“1 200 000”这样的预测)。
softmax结果之和为1,所以可以解释成概率
下面以手写识别为例看一下模型建立:
1.模型建立
上图中,该图像是16x16个像素256位的黑白灰度图,需要把图像转换成一维数组,所以每个图像有256个,通过神经网络,给出每个输入的概率,其中最大概率就是预测结果。
应该思考的是设置合适的网络结构:层数和结点个数、激活函数
问题:应该设置多少层,多少结点?是否需要选择其他网络结构如DNN/CNN/RNN?
2. 选择常用损失函数,平方误差,交叉熵..
好的参数使得所有训练数据的损失越小越好
3.参数学习
枚举所有可能的取值,使得总损失L最小。可以参考吴恩达斯坦福深度学习课程中的讲解,非常详细。,特别是梯度下降。
实战:基于前馈神经网络的手势识别
1. 直接在百度AI Studio中阅读案例代码,并运行,查看结果
- 1.1作业要求补全神经网络部分函数,并调整参数使得识别率提高。
#定义DNN网络
class MyDNN(fluid.dygraph.Layer):
def __init__(self):
super(MyDNN,self).__init__()
self.hidden1 = Linear()
self.hidden2 = Linear()
self.hidden3 = Linear()
self.hidden4 = Linear()
def forward(self,input):
return y
因为不太了解DNN网络,直接在网络搜索 def forward(self,input),得到结果。但是直接运行出现报错
def forward(self,input):
x= self.hidden1(input)
x = self.hidden2(x)
x = self.hidden3(x)
x = fluid.layers.reshape(x,shape=[-1,3*100*100])
y = self.hidden4(x)
return y
在 model=MyDNN() #模型实例化时提示错误,hidden()函数需要两个参数,input_dim,output_dim
于是直接搜索Linear()函数,在paddle的文档中有API说明
Linear线性变换层:
Out=Act(XW+b)
其中,X 为输入的 Tensor, W 和 b 分别为权重和偏置。
Linear 层只接受一个 Tensor 的输入。 Linear 层将输入 Tensor 与权重矩阵 W 相乘,然后生成形状为 [N,∗,outputdim] 的输出张量, 其中 N 是批量大小,∗ 表示任意数量的附加尺寸。 如果 bias_attr 不是 None,则将创建一个 bias 变量并将其添加到输出中。 最后,如果激活 act 不是 None,则相应激活函数也将应用于输出上。
参数:
input_dim (int) – 线性变换层输入单元的数目。
output_dim (int) – 线性变换层输出单元的数目。
param_attr (ParamAttr, 可选) – 指定权重参数属性的对象。默认值为None,表示使用默认的权重参数属性。具体用法请参见 ParamAttr 。
bias_attr (ParamAttr, 可选) – 指定偏置参数属性的对象,若 bias_attr 为bool类型,如果设置为False,表示不会为该层添加偏置;如果设置为True,表示使用默认的偏置参数属性。默认值为None,表示使用默认的偏置参数属性。默认的偏置参数属性将偏置参数的初始值设为0。具体用法请参见 ParamAttr 。
act (str, 可选) – 应用于输出上的激活函数,如tanh、softmax、sigmoid,relu等,支持列表请参考 激活函数 ,默认值为None。
dtype (str, 可选) – 权重的数据类型,可以为float32或float64。默认为float32。
返回:无
在课上看到老师的课件,知道具体的写法,正确的用法如下
#定义DNN网络
class MyDNN(fluid.dygraph.Layer):
def __init__(self):
super(MyDNN,self).__init__()
self.hidden1 = Linear(100,100,act='relu') #100,参数是可以更改的,属于超参调整
self.hidden2 = Linear(100,100,act='relu')
self.hidden3 = Linear(100,100,act='relu')
self.hidden4 = Linear(3*100*100,10,act='softmax')
def forward(self,input):
x= self.hidden1(input)
x = self.hidden2(x)
x = self.hidden3(x)
x = fluid.layers.reshape(x,shape=[-1,3*100*100])
y = self.hidden4(x)
return y
其他的地方没有需要补全的,具体的用法可以查看文档说明或者百度。
在notebook中可以正常运行,无错误,就是结果有点低,明明图片是5,结果显示4.
重点来了!!!
优化调参,超参优化
根据个人经验和测试,需要调整优化的地方有:
以下各参数需要组合调整,并不是单独
1. #用于训练的数据提供器
train_reader = paddle.batch(reader=paddle.reader.shuffle(reader=data_reader('./train_data.list'), buf_size=256), batch_size=32)
buf_size=512,更改后效果明显avg_acc结果明显提高
2. opt=fluid.optimizer.SGDOptimizer(learning_rate=0.01, parameter_list=model.parameters())#优化器选用SGD随机梯度下降,学习率为0.001. 这里学习率调整了多次,最佳为0.008
3. epochs_num=20 #迭代次数 最佳为200
因为多次训练浪费时间,有人说可以把上次训练结果一起使用,把下面这两句放在模型初始化地方,第二部的时候注释掉模型初始化,直接加载上次训练模型。经过测试,有效果,但不明显,也可能是参数调整作用,所以并未证实。
model_dict, _ = fluid.load_dygraph('MyDNN')
model.load_dict(model_dict) #加载模型参数
4. 神经网络层级
默认的是hidden1--hidden3,hidden4是输出层,可以增加,个人增加到8层,但是效果很不理想,成本函数2.0以上,acc 0.2左右。最后还是使用三个隐藏层,一个输出层。
值得注意点是,因为Linear是矩阵运算,所以要符合矩阵运算规则,确定好矩阵维度,M N N L L F 矩阵乘法原则 100 200 , 200 300 ,300 400 ,400 100
2.由线上导出ipynb格式文件,导入到本地jupyterLab环境
1.本地启动jupyterLab,导入文件,上传训练数据,测试图片
2.修改文件中涉及路径的相关代码,运行测试
本地环境无法识别 ls,,unzip,rm 等命令,所以有些操作需要手动进行
#Linux命令转换成Windows对应命令
ls --- dir
unzip rm 需要手动实现
3.本地可以建立多个Launcher环境同时运行,节省调试时间。以下是我跑的参数组合,完全没规律
#epochs_num #learning_rate #avg_acc
10 0.01 0.4484127
200 0.008 0.8814484
300 0.008 0.8219246
180 0.008 0.44494048
200 0.0085 0.8110119
120 0.008 0.81001985
200 0.005 0.7886905
200 0.007 0.44494048
200 0.009 0.8298611
500 0.005 0.8333334
100 0.01 0.8110119
#buf_size 256 512 1024
3.进行部分参数调整,思考会有何变化,查看结果
- 3.1.目前,只能处理JPG格式图片,无法处理PNG,应该是PNG含有透明图层问题,还有就是位数,本案例属于全连接神经网络,无法灵活调整,只能接受固定输入,
- 3.2 选取其他训练集和测试集中的图片测试,结果不是特别理想,还是还应该继续优化参数,或者定义其他网络RNN,CNN等。
配套参考资料:1.百度深度学院课程课件 2.Python机器学习教程 3. PaddlePaddle官方文档