本篇文章是基础版,而实际上对于MNIST数据集的利用程度还没达到极限,对该模型还可进一步探究(反向查询),有兴趣可以看我另一篇文章
https://blog.csdn.net/CxsGhost/article/details/104829332
——————————————————————————————————————————————————
1. MNIST介绍:
- mnist应该是深度学习最著名的数据集之一,包含70,000张图片,其中60,000张是训练数据,10,000是测试数据。
- 每张图片是10个个位数(0到9)的“手写体”,图片是28 * 28像素,除了数字体部分,其它区域都是空白
- 若要在神经网络中使用,很自然想到把图片转化为784(28*28)的向量来进行输入
可以在此下载:
http://www.pjreddie.com/media/files/mnist_train.csv(训练数据)
http://www.pjreddie.com/media/files/mnist_test.csv(测试数据)
在Excel中打开是下面这个样子,其中第一列代表本条数据是数字几(target)
2. 搭建前馈神经网络(全连接):
主要思路:
- 784个输入层节点,500个隐藏层节点(可以按照自己的意愿设置,500个时我得到的准确率最高)
- 10个输出层节点:比如对于数字2的一条训练数据,我们可以把target转化成
2: [0.0, 0.0, 0.99, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
这样做的意思就是,指导神经网络在第2个输出节点输出尽可能大的数字,因为sigmoid函数不能输出1,所以就0.99
所以最终输出的10个数据中,最大数所在的位置,就是神经网络给出的判断
(1)需要具备的属性:
- 输入节点数量,隐藏节点数量,输出节点数量。(隐藏层只一层就可以)
- 学习率
- 节点上采用的激活函数(这里我选择sigmoid)
- 输入层和隐藏层间的权重矩阵,隐藏层和输出层之间的权重矩阵
用numpy中normal函数从正态分布中选取初始权重
-
均值:0.0
-
标准差:前一层的节点数量平方根的倒数(比较科学的选法,自行百度详解)
-
矩阵大小:
输入层与隐藏层(self.wih):输入层节点数为列数,隐藏层节点数为行数
隐藏层与输出层(self.who):隐藏层节点数为列数,输出层节点数为行数计算方法如下图(以一个输入中有两个数据为例), W1,1代表第一个节点与下一层的第一个节点间的权重链接
class NeuralNetwork:
def __init__(self, inputnodes, outputnodes,
hiddennodes, learningrate):
# 设置节点数量属性
self.innodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
self.lr = learningrate
# 按照正态分布设置初始权重矩阵
self.wih = np.random.normal(loc=0.0,
scale=1 / np.sqrt(self.innodes),
size=(self.hnodes, self.innodes))
self.who = np.random.normal(loc=0.0,
scale=1 / np.sqrt(self.hnodes),
size=(self.onodes, self.hnodes))
# 这里scipy.special.expit(),是sigmoid函数,用于正向激活
self.activation_function = lambda x: scipy.special.expit(x)
——————————————————————————————————————————————————
(2)接收数据,更新权重
- 主要方法:梯度下降
- 损失函数:平方损失函数
先把输入数据由行向量转置为列向量,同时把target也转置为列,因为最终输出的是列向量
然后计算输出,结合target更新权重,下面的代码也有注释。
数据是采用一条一条输入进行训练的,矩阵运算的速度非常快
权重更新:
以更新隐藏层和输出层之间的某个权重为例,损失函数是:
对某一个权重求偏导后(把2省略了):
红色的output是这个权重连接的隐藏层的节点的输出,不是输出节点的输出(上面的式子可以自己推一下)
根据以上公式更新权重即可,代码如下:
def train(self, input_list_1, target_list):
# 转置输入数据,以及目标数据
input_1 = np.array(input_list_1, ndmin=2)
input_1 = np.transpose(input_1, axes=(1, 0)