# java手写数字识别 **Repository Path**: i7606/java-mnist-learning ## Basic Information - **Project Name**: java手写数字识别 - **Description**: java手写数字识别学习案例,包含图片形式的训练集和测试集,以及训练好的模型权重和代码,仅基础神经网络,没有正则化等优化项 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-12-29 - **Last Updated**: 2026-01-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: Java, Swing, mnist ## README # java手写数字识别 ## 介绍 java手写数字识别学习案例,包含图片形式的训练集和测试集,以及训练好的模型权重和代码,仅基础神经网络,没有正则化等优化项. 软件图片如下: ![Excel神经网络](./images/soft-window.png "Excel神经网络") ## 项目说明 神经网络的计算公式: ~~~ o = softmax( w₂ · sigmoid( w₁·a + b₁ ) + b₂ ) ~~~ 反向传播说明: a → [a·w₁ + b₁] → m → sigmoid → h → [h·w₂ + b₂] → z → softmax(z) → o 一般情况下,不需要主动去推导反向传播的过程,除非是为了了解神经网络的底层原理,以下就是这个神经网络的反向传播的推导过程: 在反向传播中,需要通过链式法则对当前函数的组成部分进行求导,因为函数之间的关系就是组合关系,需要找该函数的组成部分,就需要使用链式法则公式`dy/dx = dy/du * du/dx`进行求导, 求softmax的导数: > 因为o函数的直接组成部分只有`z`,因为`o`是直接通过`z`函数计算得出的结果,所以首先需要对`z`进行求导,`z`经过`softmax`函数的计算,所以求`z`的导数就是`loss`函数, > 设真实标签为y,即`dL/dz = (o - y)`。因为整个网络结构都是一个完整的算式,所以可以根据链式法则,找到对应函数的组成部分,比如`h * w₂ + b₂ = z`,z函数的组成部分是`h`和`w`, > 而此处的`b`在函数图像中用于平移,并不影响函数图像的形状,所以`b`的变化率总是1(即没有变化),所以误差对`b`的导数,就等于传递到该层的误差值本身。 求w₂和b₂的导数: > 根据`h * w₂ + b₂ = z`可以得出对应的求导表达式`dz/dw₂ = h`,`dz/b₂ = 1`,`dz/dh = w₂`,因为此处局部表达式的`h`和`w₂`前面没有数,所以不再分解。因为要修改w₂, > 可以得出`dL/dw₂ = dL/dz * dz/dw₂ * 1`,但是一般不写1,所以简化为`dL/dw₂ = dL/dz * dz/dw₂`,因为`dz/dw₂ = h`,所以简化为`dL/dw₂ = dL/dz * h`,与学习率相乘, > 再赋以负号表示反方向调节,让`w₂`加上这个数进行调节就完成对`w₂`的调整。 > > 修改`b₂`的式子为`dL/db₂ = dL/dz * dz/db₂`,因为`dz/b₂ = 1`,所以`dL/db₂ = dL/dz`,与学习率相乘,再赋以负号表示反方向调节,让`b₂`加上这个数进行调节就完成对b₂的调整。 求输入层到隐藏层中w₁和b₁的导数: > 对`sigmoid`求导得`dh/dm = h*(1 - h)`,根据`a * w₁ + b₁ = m`,得`dm/dw₁ = a`, `dm/b₁ = 1`,需要修改w₁,所以求`dL/dw₁:dL/dw₁ = dL/dh * dh/dm * dm/dw₁`; > > 求`dL/db₁`: `dL/db₁ = dL/dh * dh/dm`,同样将结果与学习率相乘,再赋以负号表示反向调节,与偏置数相加得到结果。