# Mnist_QT
**Repository Path**: smilerll/mnist_-qt
## Basic Information
- **Project Name**: Mnist_QT
- **Description**: 基于QT C++的Mnist手写数字识别。
- **Primary Language**: C++
- **License**: GPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2023-08-29
- **Last Updated**: 2023-08-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 基于QT的BP神经网络手写数字识别
## 方案设计
### 单个神经元概述
一个神经元有多个输入及对应的输入权重,仅有一个输出但是可连接到多个神经元上。
S阈值函数
$$
y=\frac{1}{1+e^{-x}}
$$
该函数把所有输入量化在$0-1$的范围内,而且只有在正负无穷时才会达到两个逻辑的极限即$0和1$ 。
该函数的求导过程为:
$$
y^‘=\frac{-e^{-x}}{(1+e^{-x})^2}=\frac{-(1+e^{-x})+1}{(1+e^{-x})^2} \\=-y+y^2=y(y-1)
$$
### 多神经元连接计算

$$
o_1=i_1*w_{1,1}+i_2*w_{2,1}
\\o_2=i_1*w_{1,2}+i_2*w_{2,2}
$$
矩阵形式
$$
\left[
\begin{matrix}
o_1 \\
o_2
\end{matrix}
\right]
=
\left[
\begin{matrix}
w_{1,1}&w_{2,1} \\
w_{1,2}&w_{2,2}
\end{matrix}
\right]
\left[
\begin{matrix}
i_1\\
i_2
\end{matrix}
\right]\\
X=W*I
$$
W为权重矩阵,I为输入矩阵。
再看一个三层网络,为了便于观察这里暂时忽略S函数作用
$$
o_{2,1}=i_1*w_{1,1}+i_2*w_{2,1}+i_3*w_{3,1}\\
o_{2,2}=i_1*w_{1,2}+i_2*w_{2,2}+i_3*w_{3,2}\\
o_{2,3}=i_1*w_{1,3}+i_2*w_{2,3}+i_3*w_{3,3}\\
\\
o_{3,1}=o_{2,1}*w_{1,1}+o_{2,2}*w_{2,1}+o_{2,3}*w_{3,1}\\
o_{3,2}=o_{2,1}*w_{1,2}+o_{2,2}*w_{2,2}+o_{2,3}*w_{3,2}\\
o_{3,3}=o_{2,1}*w_{1,3}+o_{2,2}*w_{2,3}+o_{2,3}*w_{3,3}\\
$$
需要注意的是上述两组等式中的$W$并不相同,这里指的是不同层之间的权重信息。矩阵形式为
$$
\left[
\begin{matrix}
o_{2,1} \\
o_{2,2} \\
o_{2,3}
\end{matrix}
\right]
=
\left[
\begin{matrix}
w_{1,1}&w_{2,1}&w_{3,1} \\
w_{1,2}&w_{2,2}&w_{3,2} \\
w_{1,3}&w_{2,3}&w_{3,3}
\end{matrix}
\right]
\left[
\begin{matrix}
i_1\\
i_2\\
i_3
\end{matrix}
\right]\\
X_2=W_{1,2}*I\\
\left[
\begin{matrix}
o_{3,1} \\
o_{3,2} \\
o_{3,3}
\end{matrix}
\right]
=
\left[
\begin{matrix}
w_{1,1}&w_{2,1}&w_{3,1} \\
w_{1,2}&w_{2,2}&w_{3,2} \\
w_{1,3}&w_{2,3}&w_{3,3}
\end{matrix}
\right]
\left[
\begin{matrix}
o_{2,1} \\
o_{2,2} \\
o_{2,3}
\end{matrix}
\right]\\
X_3=W_{2,3}*X_2
$$
合并为:
$$
X_3=W_{2,3}*W_{1,2}*I
$$
### 误差的反向传播
根据输出层的误差$e_1,e_2$,根据权重计算层1的误差$e_{h1},e_{h2}$
$$
e_{h1} =e_1\frac{w_{1,1}}{w_{1,1}+w_{2,1}}+e_2\frac{w_{1,2}}{w_{1,2}+w_{2,2}}\\
e_{h2} =e_1\frac{w_{2,1}}{w_{1,1}+w_{2,1}}+e_2\frac{w_{2,2}}{w_{1,2}+w_{2,2}}
\\
\left[
\begin{matrix}
e_{h1} \\
e_{h2}
\end{matrix}
\right]
=
\left[
\begin{matrix}
\frac{w_{1,1}}{w_{1,1}+w_{2,1}}&\frac{w_{1,2}}{w_{1,2}+w_{2,2}} \\
\frac{w_{2,1}}{w_{1,1}+w_{2,1}}&\frac{w_{2,2}}{w_{1,2}+w_{2,2}}
\end{matrix}
\right]
\left[
\begin{matrix}
e_1\\
e_2
\end{matrix}
\right]\\
$$
忽略分母因子可得
$$
\left[
\begin{matrix}
e_{h1} \\
e_{h2}
\end{matrix}
\right]
=
\left[
\begin{matrix}
w_{1,1}&w_{1,2} \\
w_{2,1}&w_{2,2}
\end{matrix}
\right]
\left[
\begin{matrix}
e_1\\
e_2
\end{matrix}
\right]\\
Error=W^TE
$$
### 梯度下降更新权重
根据反向传播可以得到节点的误差,又由于神经元节点处的输出由前一层输出加权后累计得出,则该层的误差实际上也由上一层的误差加权累加得出:
$E = w_1*e_1+...+w_n*e_n$
所以可对该神经元节点的误差求梯度,根据梯度采取梯度下降法修正加权值使其向方差减小的方向进行。
$$
\frac{\sigma E}{\sigma w_{i,j}} = \frac{\sigma}{\sigma w_{i,j}}(t_k-o_k)^2\\
=-2(t_k-o_k)\frac{\sigma o_k}{\sigma w_{i,j}}\\
=-2(t_k-o_k)\frac{\sigma}{\sigma w_{i,j}}sigmoid(\sum_jw_{j,k}*o_j)\\
=-2(t_k-o_k)sigmoid(\sum_jw_{j,k}*o_j)(1-sigmoid(\sum_jw_{j,k}*o_j))o_j\\
$$
由于我们关心的只是方向,可以把上述的2去掉
$$
\frac{\sigma E}{\sigma w_{i,j}}=-(t_k-o_k)sigmoid(\sum_jw_{j,k}*o_j)(1-sigmoid(\sum_jw_{j,k}*o_j))o_j
$$
最后再通过学习率调整权重$w_{j,k}$
$$
(new)w_{j,k}=(old) w_{j,k}-(\Delta)w_{j,k}
$$
其中$\alpha$为学习率,也就是根据梯度对$w_{j,k}$的修正速度。
$$
\Delta W=
\left[
\begin{matrix}
E_1*S_1(1-S_1) \\
E_2*S_2(1-S_2) \\
...
\end{matrix}
\right]
\left[
\begin{matrix}
O_1,O_2,... \\
\end{matrix}
\right]
$$
### 网络设计
这里输入层为$28*28=784$个节点,隐藏层布置15个节点,输出层10个节点。
输出过程为
$$
O_1(15,1)=W_{0,1}(15,784)*I(784,1)\\
O_2(10,1)=W_{1,2}(10,15)W_{0,1}(15,784)*I(784,1)
$$
反向传播过程为:
$$
E_2(10,1)=EE-O_2\\
E_1(15,1)=W_{1,2}^T(15,10)*E_2(10,1)
$$
梯度下降过程为:
$$
\Delta W_{1,2}(10,15)=\alpha(E_2(10,1)*O_2(10,1)(1-O_2)(10,1))(10,1)*O_1^T(1,15)\\
\Delta W_{0,1}(15,784)=\alpha(E_1*O_1(1-O_1))(15,1)*I^T(1,784)
$$
## 外观&功能
### 手动训练

### 文件训练

### 文件测试

### 手写测试

## 参考资料
[Python神经网络](https://pan.baidu.com/s/1O1_akJbr8lqkDFChOmuwhw):提取码:oekl