我正在学习二维神经网络,因此遇到了许多障碍,但我相信这是值得的,我非常享受这个学习过程。
这是我的计划:制作一个2-D NN来识别数字图像。图像是5×3的网格,我准备了从零到九的10张图像。例如,这将是数字7:
数字7的索引0,1,2,5,8,11,14为1(或者3,4,6,7,9,10,12,13为0,这不重要),依此类推。因此,我的输入层将是一个5×3的神经元层,我将只输入0或1(没有中间值,索引取决于我输入到层中的图像)。
然而,我的输出层将是一个一维的10个神经元的层。根据识别出的数字,哪个神经元会输出一个值为1,其余的应该为0(不应该激活)。
我已经完成了所有实现,但在计算上遇到了问题,我非常希望得到任何帮助。我得到的错误率极高,所有输出神经元的输出值极低(负值),并且在第10,000次传递后,值(错误和输出)都没有变化。
我很想进一步发布我的反向传播方法,因为我认为问题出在这里。然而,为了分解我的工作,我首先想听听一些评论,我想知道我的设计是否可行。
-
我的计划有意义吗?
-
所有帖子都在谈论范围(
0->1
,-1 ->+1
,0.01 -> 0.5
等),对于输出层使用{ 0 |
.OR.| 1 }
而不是范围是否可行?如果可以,我如何控制这一点? -
我使用
TanHyperbolic
作为我的传递函数。这与sigmoid
和其他函数有什么区别吗?
任何想法/评论/指导都将不胜感激,提前感谢
回答:
根据上述描述,我认为设计和方法是正确的!关于激活函数的选择,请记住这些函数有助于获取激活值最大的神经元,此外,它们的代数属性,如易于求导,有助于定义反向传播。考虑到这一点,你不必担心你选择的激活函数。
你提到的范围对应于输入的缩放过程,最好将你的输入图像缩放到0到1的范围内。这有助于缩放错误表面,并有助于优化过程的速度和收敛。因为你的输入集由图像组成,每个图像由像素组成,像素可以达到的最小值和最大值分别为0和255。在这个例子中,要缩放你的输入,必须将每个值除以255。
现在,关于训练问题,你有尝试检查你的梯度计算程序是否正确吗?例如,通过使用成本函数,并评估成本函数,J
?如果没有,尝试生成一个包含神经网络中所有权重矩阵的玩具向量theta
,并使用梯度的定义在每个点评估梯度,抱歉使用Matlab的例子,但应该很容易移植到C++:
perturb = zeros(size(theta));e = 1e-4;for p = 1:numel(theta) % Set perturbation vector perturb(p) = e; loss1 = J(theta - perturb); loss2 = J(theta + perturb); % Compute Numerical Gradient numgrad(p) = (loss2 - loss1) / (2*e); perturb(p) = 0;end
评估函数后,将数值梯度与使用反向传播计算的梯度进行比较。如果每次计算之间的差异小于3e-9,那么你的实现应该是正确的。
我推荐查看斯坦福人工智能实验室提供的UFLDL教程,你可以在那里找到很多与神经网络及其范式相关的信息,值得一看!