深度学习初遇——自己动手实现三层神经网络

简介: 深度学习初遇——自己动手实现三层神经网络

介绍

深度学习中,神经网络是最基础的数据结构,本文想自己动手实现一个神经网络,并使用它来对mnist数据集做预测。

本文内容参考了大神塔里克拉希德的著作《Python神经网络编程》,有兴趣的读者可以在网上找到这本书,或联系笔者,笔者免费赠送。

神经网络结构

神经网络的结构想必大家都很熟悉了,看张图吧,这里除了输入层外,其他层每个节点都有激活函数,比如sigmoid或relu等。

这里,权重很重要,在神经网络中,要更新的参数就是权重,而且后面我们会看到,误差的反向传播也要用到当前的权重。每两层之间的权重可以用一个矩阵表示,在理论研究和代码编程时,这很有用。

前馈

前馈的过程是根据输入数据,逐层计算输出值,进而得到输出层的输出值,给定权重(通过优化算法更新前的权重,最开始是按一定规则人为初始化的)和输入值,代入公式即可得到,这个操作很简单,但很重要,后面我们会看到,权重的更新需要用到后一层节点的输出值以及前一层节点的输出值(注意,我们是站在两层之间的地方),从上一小节的图示中,我们很容易有一个形象的感受。

误差的反向传播

我们通过当前权重和输入值计算出了输出值,而且训练数据的目标值是给定的,所以模型的误差也很容易算出来,有了整个模型的误差值,那还要每一层的误差做什么呢?或者为什么要进行误差反向传播呢?误差又是怎么进行反向传播的呢?

后面我们会看到,每一层权重的更新,都要用到下一层的误差值,所以反向传播很有必要,那它怎么传播呢?

如下图所示,一般地,误差会根据当前节点输入连接的权重进行拆分,假如右边节点的输出误差为e ee,左边第一个节点的误差为e r r 1 = W 1 , 1 W 1 , 1 + W 2 , 1 ∗ e err_1=\frac{W_{1,1}}{W_{1,1}+ W_{2,1}}*eerr1=W1,1+W2,1W1,1e,左边第二个节点的误差为e r r 2 = W 2 , 1 W 1 , 1 + W 2 , 1 ∗ e err_2=\frac{W_{2,1}}{W_{1,1}+ W_{2,1}}*eerr2=W1,1+W2,1W2,1e

多个节点的误差会拆分后叠加到上一层中每一个节点的误差上去,例如下图所示

这时,e r r 1 = W 1 , 1 W 1 , 1 + W 2 , 1 ∗ e 1 + W 1 , 2 W 1 , 2 + W 2 , 2 ∗ e 2 err_1=\frac{W_{1,1}}{W_{1,1}+ W_{2,1}}*e_1+\frac{W_{1,2}}{W_{1,2}+ W_{2,2}}*e_2err1=W1,1+W2,1W1,1e1+W1,2+W2,2W1,2e2,左边第二个节点的误差为e r r 2 = W 2 , 1 W 1 , 1 + W 2 , 1 ∗ e 1 + W 2 , 2 W 1 , 2 + W 2 , 2 ∗ e 2 err_2=\frac{W_{2,1}}{W_{1,1}+ W_{2,1}}*e_1+\frac{W_{2,2}}{W_{1,2}+ W_{2,2}}*e_2err2=W1,1+W2,1W2,1e1+W1,2+W2,2W2,2e2

不断重复上述拆分,便可以计算出每一层的输出误差,在实际应用中,通常用权重代替上面公式中的分数部分,即使用W 1 , 1 W_{1,1}W1,1代替W 1 , 1 W 1 , 1 + W 2 , 1 \frac{W_{1,1}}{W_{1,1}+ W_{2,1}}W1,1+W2,1W1,1,使用W 1 , 2 W_{1,2}W1,2代替W 1 , 2 W 1 , 2 + W 2 , 2 \frac{W_{1,2}}{W_{1,2}+ W_{2,2}}W1,2+W2,2W1,2,以此类推。这样利用权重矩阵和当前层的输出误差,便可以计算出前一层的误差。

权重更新

在机器学习中,对模型的优化一般采用梯度下降法,这就需要知道误差对更新参数的斜率,在神经网络中,我们需要知道输出误差对每一个权重的斜率。

求导的过程《Python神经网络编程》里面讲的很详细了,这里只给出这个神奇的公式,

这里,每一层的输出误差已经通过误差的反向传播获得,当前的权重是给定的,输出值也可以通过前馈过程获得,所以,误差对权重的斜率也自然可以轻松获得,用矩阵的语言,某两层之间的权重矩阵更新值可以表示为:

本文代码部分摘自《Python神经网络编程》并对其做了注释。

代码

import numpy
import numpy as np
import scipy.special
# 神经网络类
class NeuralNetwork:
    def __init__(self, inodes, hnodes, onodes, learning_rate=0):
        # 输入层节点数
        self.inodes = inodes
        # 隐藏层节点数
        self.hnodes = hnodes
        # 输出层节点数
        self.onodes = onodes
        # 学习率
        self.learning_rate = learning_rate
        # 输入层到隐藏层的权重矩阵
        # self.wih = np.random.rand(self.hnodes, self.inodes) - 0.5
        self.wih = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
        # 隐藏层到输出层的权重矩阵
        # self.who = np.random.rand(self.onodes, self.hnodes) - 0.5
        self.who = np.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
        # 激活函数
        self.activation_function = lambda x: scipy.special.expit(x)
    # 前馈
    def forward(self, input_data):
        # 输入
        inputs = np.array(input_data, ndmin=2).T
        # 隐藏层输入数据
        hidden_inputs = np.dot(self.wih, inputs)
        # 隐藏层输出数据
        hidden_outputs = self.activation_function(hidden_inputs)
        # 输出层输入数据
        final_inputs = np.dot(self.who, hidden_outputs)
        # 输出层输出数据
        final_outputs = self.activation_function(final_inputs)
        return final_outputs
    # 模型训练
    def train(self, input_data, target_data):
        # 输入
        inputs = np.array(input_data, ndmin=2).T
        # 输入数据标签
        targets = np.array(target_data, ndmin=2).T
        # 隐藏层输入数据
        hidden_inputs = np.dot(self.wih, inputs)
        # 隐藏层输出数据
        hidden_outputs = self.activation_function(hidden_inputs)
        # 输出层输入数据
        final_inputs = np.dot(self.who, hidden_outputs)
        # 输出层输出数据
        final_outputs = self.activation_function(final_inputs)
        # 输出层误差
        output_errors = targets - final_outputs
        # 反向传播至隐藏层的误差
        hidden_errors = np.dot(self.who.T, output_errors)
        # 更新隐藏层和输出层的权重矩阵
        delta_who = np.dot((output_errors * final_outputs * (1.0 - final_outputs)), np.transpose(hidden_outputs))
        self.who += self.learning_rate * delta_who
        # 更新输入层和隐藏层的权重矩阵
        delta_wih = np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs))
        self.wih += self.learning_rate * delta_wih
if __name__ == "__main__":
    # 神经网络模型
    inodes = 784
    hnodes = 100
    onodes = 10
    model = NeuralNetwork(inodes, hnodes, onodes, 0.3)
    # 读取训练数据
    data_file = open("./mnist_dataset/mnist_train.csv")
    data_set = data_file.readlines()
    data_file.close()
    # 对每一项输入数据进行模型训练
    for record in data_set:
        all_values = record.split(",")
        # 对训练数据进行放缩
        inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
        # 对训练数据标签进行编码
        targets = np.zeros(onodes) + 0.01
        targets[int(all_values[0])] = 0.99
        # 训练模型
        model.train(inputs, targets)
    # 加载测试数据
    test_data_file = open("./mnist_dataset/mnist_test.csv", 'r')
    test_data_list = test_data_file.readlines()
    test_data_file.close()
    # 分数卡
    scorecard = []
    # 对每一项测试数据进行预测
    for record in test_data_list:
        all_values = record.split(',')
        # 正确的标签
        correct_label = int(all_values[0])
        print(correct_label, "correct label")
        inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
        # 用神经网络模型预测
        outputs = model.forward(inputs)
        # 取出最大输出值对应的标签索引
        label = numpy.argmax(outputs)
        print(label, "network's answer")
        # 计分卡计数
        if label == correct_label:
            scorecard.append(1)
        else:
            scorecard.append(0)
    print(scorecard)
    # 计算分数
    scorecard_array = np.asarray(scorecard)
    print("performance = ", scorecard_array.sum() / scorecard_array.size)

运行结果

performance =  0.9468

作者这水平有限,有不足之处欢迎留言指正

相关文章
|
7天前
|
机器学习/深度学习 人工智能 算法
深度学习入门:理解神经网络与反向传播算法
【9月更文挑战第20天】本文将深入浅出地介绍深度学习中的基石—神经网络,以及背后的魔法—反向传播算法。我们将通过直观的例子和简单的数学公式,带你领略这一技术的魅力。无论你是编程新手,还是有一定基础的开发者,这篇文章都将为你打开深度学习的大门,让你对神经网络的工作原理有一个清晰的认识。
|
3天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络(CNN)及其应用
【9月更文挑战第24天】本文将深入探讨深度学习中的一种重要模型——卷积神经网络(CNN)。我们将通过简单的代码示例,了解CNN的工作原理和应用场景。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息。
18 1
|
8天前
|
机器学习/深度学习 人工智能 自动驾驶
深度学习中的卷积神经网络(CNN)及其在图像识别中的应用
【9月更文挑战第19天】在人工智能的浩瀚星海中,卷积神经网络(CNN)如同一颗璀璨的星辰,照亮了图像处理的天空。本文将深入CNN的核心,揭示其在图像识别领域的强大力量。通过浅显易懂的语言和直观的比喻,我们将一同探索CNN的奥秘,并见证它如何在现实世界中大放异彩。
|
9天前
|
机器学习/深度学习 算法 自动驾驶
深度学习的奥秘:探索神经网络的魔法
【9月更文挑战第18天】本文将带领读者深入理解深度学习背后的科学原理,通过直观的例子和简单的语言解释复杂的技术概念。我们将一起探讨如何通过构建神经网络模型来模拟人脑的工作方式,并了解这一领域如何影响我们的日常生活。
|
8天前
|
机器学习/深度学习 人工智能 算法
植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面
植物病害识别系统。本系统使用Python作为主要编程语言,通过收集水稻常见的四种叶片病害图片('细菌性叶枯病', '稻瘟病', '褐斑病', '稻瘟条纹病毒病')作为后面模型训练用到的数据集。然后使用TensorFlow搭建卷积神经网络算法模型,并进行多轮迭代训练,最后得到一个识别精度较高的算法模型,然后将其保存为h5格式的本地模型文件。再使用Django搭建Web网页平台操作界面,实现用户上传一张测试图片识别其名称。
55 21
植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面
|
8天前
|
机器学习/深度学习 人工智能 算法
鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别
鸟类识别系统。本系统采用Python作为主要开发语言,通过使用加利福利亚大学开源的200种鸟类图像作为数据集。使用TensorFlow搭建ResNet50卷积神经网络算法模型,然后进行模型的迭代训练,得到一个识别精度较高的模型,然后在保存为本地的H5格式文件。在使用Django开发Web网页端操作界面,实现用户上传一张鸟类图像,识别其名称。
50 12
鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别
|
7天前
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
37 6
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
4天前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
18 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
2天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习与神经网络:探索复杂数据的表示
【9月更文挑战第26天】深度学习作为人工智能领域的明珠,通过神经网络自动从大数据中提取高级特征,实现分类、回归等任务。本文介绍深度学习的基础、张量表示、非线性变换、反向传播及梯度下降算法,并探讨其在计算机视觉、自然语言处理等领域的应用与挑战。未来,深度学习将更加智能化,揭示数据背后的奥秘。
|
8天前
|
机器学习/深度学习 人工智能 算法
深度学习中的卷积神经网络(CNN)入门与实践
【9月更文挑战第19天】在这篇文章中,我们将探索深度学习的一个重要分支——卷积神经网络(CNN)。从基础概念出发,逐步深入到CNN的工作原理和实际应用。文章旨在为初学者提供一个清晰的学习路径,并分享一些实用的编程技巧,帮助读者快速上手实践CNN项目。