上一篇我总结了自己在学完逻辑回归后,实现了对手写数字的初步识别 , 在学完了Andrew教授的神经网络简易教程后,趁着知识刚学完没多久,记下了自己在运用简易神经网络实现手写数字识别过程中的总结和问题 ^_^ 菜鸡QP的第二篇学习笔记 ~ 错误在所难免 ,希望自己可以通过一篇篇菜鸡的笔记心得 ,取得一点点的进步 ~\(≧▽≦)/~ )
依旧是给定 5000个20 * 20像素点的手写数字图片 ,与前几天自己完成的逻辑回归完成任务不同 ,这次自己终于要用到极富魅力的神经网络啦(虽然只是最基础的模型 ,但还是小激动啊 ~ >_<) 读入数据啥的 ,就不赘述了 ,第一步 ,先构建出最基本的神经网络来吧!
(下图是Andrew教授课后作业中设计的神经网络模型)
输入层由于每个样本给定400个像素点,不会变 。 同样,输出层只能是0-9中的一个 ,也不会变 。因此主要是设计隐藏层 。 作业里设计的 25个单隐藏层 ,Andrew 教授课上说过 ,一般只需选择单隐藏层 , 而隐藏单元个数只要合适即可 0.0 。
设计好神经单元结构后 ,接下来就是进行前向传播去计算代价函数啦 ! 一般来说 ,首先是得随机初始化Theta的值,但是Andrew教授第五周的作业 ,一上来就让我导入给定的参数文件。。。。喵喵喵? 着实让QP困惑了好久 ,后来发现 ,原来这个参数文件的作业只是让了我检测CostFunction是不是正确的—————Andrew已经为我们算好了给定参数下正确的J ,因此在我把给定的参数代入我自己的代价函数后,只需与Andrew教授的J作比较就可知道自己的CostFunction是不是正确的啦 QAQ
关于前向传播,需要注意的是要在输入层和隐藏层加上为 +1的偏差值(如上图)。计算完成后 ,我就可以根据最后的h(x)/a3 得出J
接下来 ,我希望能够尽可能不用到for循环 ,用向量化解决m个样例的所有计算。如下图 ,因此我直接把X(5000 * 400的矩阵)作为了输入层 ,直接对5000个数据进行前向传播,值得注意的是 ,作业里给的数据y是没个样例对应的标签值 ,即y(i)= 0 -9 而我们需要的是
这样的标签矩阵 ,因此我需要将给的y 转变成对应的Y(结果还是不得不向 for循环屈服? )
然后去进行前向传播(下面的对应值实际都是m个样例所组成的矩阵),注意我们需要对Cost Function进行正则化以避免过拟合 ,
其中正则化的过程原始式子为
注意 ,正则化过程不需要偏差单元对应参与 ,因此我舍弃了两个求和中 k=0的对应值 ,相关的Matla实现如同上面我的代码(实现过程略微繁琐了点 hhhhh)
完成了CostFunction后 ,想要进行梯度下降或其他高级算法 ,就需要算出 grad 。即J的偏导数 。通过后向传播 ,我可以比较快速地求出偏导数 。
第一步是先算出delta_3, 这一步只需将对应的h(X)与Y做差就可以求出来,然后通过后向传播 ,一步一步算出delta_2 和delta_1
然而在这个地方 ,我的向量化进程遇到了困难ORZ ,具体来说 ,上面我得到的a(l)矩阵一定是一个 m *( s(l) + 1)的矩阵 ,delta_(l +1)是一个 m*s(l + 1) 的矩阵 ,而我想做的是让 delta_(l +1)转置的第i列和a(l) 的第i行相乘得到全新矩阵并且累加 。我实在找不到不使用for循环的其他方法,若是之后的学习我找到了一步完成这操作的方法 ,我会回头来添上(或者希望看到这的大佬们给我指点下 QAQ)
具体的实现如下:
其中有几点我应当注意:1.因为delta_2是需要去除掉偏差单元的 , z也是不加上偏置单元的 ,但是Theta2是对应偏置单元的 ,所以维数就对不上了 ,(因为 delta_2 和 z2 都是不加偏置单元 ,而Theta2加上了 ,相应维数就多了1) ,所以我选择了复制一个临时参数 ,把Theta2的对应偏置单元的部分删除了
2.注意 ,梯度正规化过程中
注意,这里同样不需要对偏置单元进行正则化处理 ,因此需要将 Theta对应的第一列置为0 。
接下来我将对反向传播得到的grad进行梯度检测 。 Andrew为我们设置了一个简易的检测神经网络 ,附带一些简单的参数 ,以检测我们自己计算的梯度是否正确。
我们设置e = 10-4 带入梯度检测中简易的参数 ,算出检测得到的偏导数 ,再将参数带入我们自己建立的梯度计算函数 ,比较两个不同函数得到的结果 ,如果相差很小,几乎忽略不计 ,那就说明我们的梯度计算没有问题,否则说明我们的计算出现了偏差,是要负责任的。
所幸我的结果是符合的 (~\(≧▽≦)/~)
至此 ,我的模型已经完全搞定啦 ,剩下的就是训练我的神经网络了 !
首先我需要随机初始化参数Theta
W即是我们返回的随机化初始的Theta , L_out和 L_in即表示得到的矩阵的维数 。我分别初始化了Theta1和Theta2 ,紧接着,我对这两个参数进行了展开处理 。铺展开的参数能够更好进行算法的进行。
这里的梯度算法,我用了Andrew老师给予我们课后作业的随带的fmincg() ,(关于这个算法 ,我也希望最近可以写一篇关于分析这个算法的笔记),经过5000个样例的训练后 ,我们得到了最终的参数 ,此时我们再将得到的最终参数reshape为Theta1 和Theta2 ,至此我们的神经网络已经训练完毕。
最后我们只需再将测试样例(我还是用的训练集ORZ) 代回神经网络 ,选取最大输出神经元对应的标签 ,即可得到预测结果 。
最后Andrew还贴心的把隐藏层可视化了 hhhhhh 看起来很有趣
此时 ,我得到的神经网络的准确率为
这当然与我随机化的初始参数和选取的lambda有关 。
(回顾我的第一次实现神经网络的过程 , 不得不说比逻辑回归复杂但是同时得到的结果也是好上不少 , 同时我也在想哦 ,这仅仅只是 20*20的黑白像素点 ,仅仅只有5000个样例 ,当像素点复杂了 ,样本多了 ,我又该怎样对像素点进行有效降维 ,对结构进行合理设计 ,对算法进行优化呢? 菜鸡QP的路 ,才迈出第一脚哇 ^_^ 今后我也会不断记录下自己的学习中遇到的问题和心得 ,当然错误是肯定有的 ,但我也是希望错误越来越少的,进步越来越多的哇 ~\(≧▽≦)/~ 这里是菜鸡QP 一只咸鱼的学习笔记 ^_^)