全链接神经网络python简单实现

2023-11-03

什么是全链接神经网络(full connected, FC)

借用此图来直观的表示一下。

规则如下:

  • 神经元按照来布局。最左边的层叫做输入层,负责接收输入数据;最右边的层叫输出层,我们可以从这层获取神经网络输出数据。输入层和输出层之间的层叫做隐藏层,因为它们对于外部来说是不可见的。
  • 同一层的神经元之间没有连接。
  • 第N层的每个神经元和第N-1层的所有神经元相连(这就是full connected的含义),第N-1层神经元的输出就是第N层神经元的输入。
  • 每个连接都有一个权值

 全链接神经网络是神经网络的基础结构,很多其它结构的神经网络,比如卷积神经网络(CNN)、循环神经网络(RNN),他们都是以全链接神经网络为基础形成的不同的连接规则网络。

对于全链接神经网络很多人都抽象的说就是左边输入,中间计算,右边输出的结构,如:

 简单的来说的化,好像确实是这么回事。

前向计算、反向传播应该是对训练全链接神经网络最合适的说辞,前向计算指的是计算出隐藏层和输出层各节点的值,反向传播说的是误差项的传播。反向传播算法是目前用来训练人工神经网络(Artificial Neural Network,ANN)的最常用且最有效的算法,对于全链接神经网络的契合度很高。

全链接神经网络中神经元节点的激活函数往往选择为sigmoid函数或tanh函数。这里我们选择sigmoid函数:

其导数为:

 接下来我们介绍下前向计算和反向传播的具体过程:

 前向计算:

以单个神经元为单位下:

 

 矩阵形式的表示:

 反向传播算法(Back Propagation):误差项的传播

其中 就是节点 i 的误差项。下面给出公式描述过程骨架:

 详细的解释可以参考:零基础入门深度学习(3) - 神经网络和反向传播算法 - 作业部落 Cmd Markdown 编辑阅读器

 下面是代码的实现:

import numpy as np

# question: 数据的归一化处理可不可以添加进入, 初始数据的样例, 初始权值的选取
# 本身程序的错误:解决-->类中使用的都是实例方法,规定必须含有一个位置参数self

class Begin:
    def __init__(self, x, wa, wb, y, b1, b2, n): # 前向计算所需要的属性有:x最初输入,wa、wb最初权重  后向传播所需要的属性有:y
        self.x = x
        self.wa = wa
        self.wb = wb
        self.y = y
        self.n = n
        self.b1 = b1
        self.b2 = b2

    # 前向计算部分
    def hide_output(self, x, wa, b1):  # 隐藏层输出值函数
        return sigmoid(np.dot(x, wa) + b1) # 返回的是隐藏层的ai矩阵

    def out_output(self, a2, wb, b2):  # 这里的x对应着隐藏层的输出矩阵
        return sigmoid(np.dot(a2, wb) + b2) # 返回的是隐藏层的ai矩阵
    
    def count_front(self):  # 计算出预测值和隐藏层节点的值
        # 得到各神经元的结果, 前向计算完成
        self.wa = np.transpose(self.wa)
        a1 = self.hide_output(self.x, self.wa, self.b1) # 得到1x4
        self.wa = np.transpose(self.wa)

        self.wb = np.transpose(self.wb)
        t = self.out_output(a1, self.wb, self.b2)  # 得到的预测输出值   -->  矩阵相乘对形势有要求: 如果存在偏置,那么应该a1还要加上偏执对应的1
        self.wb = np.transpose(self.wb)
        # print('a1的矩阵形式:', a1.shape, '\nt的矩阵形式:', t.shape)
        return a1, t


    def hide_deviation(self, a1, det, wb):  # 隐藏层误差函数
        return a1 * (1 - a1) * np.dot(det, wb)

    def out_deviation(self, y, t):  # 输出层误差函数
        return t * (1 - t) * (y - t)
    
    def count_back(self, t, a1):
        # 后向传输:先做一次迭代

        # 输出层节点误差
                    # 问题是矩阵的运算出现知识短缺:dot得到的都是数字,而不是理想的矩阵!!!  问题解决
                # # 模拟一下矩阵对公式的适用性
                # y = np.array([[1, 2, 3, 4]])
                # t = np.array([[4, 3, 2, 1]])
                # #      问题:矩阵无法满足我们想的对应元素乘法好像
                # # 问题解决:当*表示的是两个np.array相乘时,表示矩阵对应元素的相乘;   当*表示的是两个np.matrix表示的是普通的矩阵乘法
                # # print(y * t)
                # det = y * (1 - y) * (t - y)
                # print(det)
        det = self.out_deviation(self.y, t)
        # print('输出层节点误差:\n', det, '\ndet的形式:', det.shape)

        # 隐藏层节点误差
            # 问题:偏置权重有没有?公式的计算有没有影响,例如矩阵的计算时用到那个a的矩阵?
            # 误差值与偏置没有关系,公式中并没有偏置的影响,偏置影响到的是输出值的求解和迭代

        det1 = self.hide_deviation(a1, det, wb) # 偏置对的是节点吗:是的,每个节点都一个偏置,就算是输出层节点也有偏置
        # print('隐藏层节点误差:\n', det1, '\ndet1的形式:', det1.shape)
        return det1, det

    def mount(self):
        a1, t = self.count_front()
        det1, det = self.count_back(t, a1)
        return det1, det, a1

# 训练函数
def train(det1, det, a1, n, wb, wa, x, b1, b2):
    det1 = np.transpose(det1)
    wa = wa + n * np.dot(det1, x)
    print('wa的迭代变化矩阵:\n', np.dot(det1, x))
    print('迭代后的wa为:\n', wa)
    det1 = np.transpose(det1)

    det = np.transpose(det)
    wb = wb + n * np.dot(det, a1)
    print('wb的迭代变化矩阵:\n', np.dot(det, a1))
    print('迭代后的wb为:\n', wb)
    det = np.transpose(det)

    b1 = b1 + n * det1
    b2 = b2 + n * det

    return wa, wb, b1, b2


# 迭代函数
def iterate(wa, wb, b1, b2, n, e):

    # j = 0
    while True:

        boolx = True
        # 从文件导入数据, 这个前提是基于知道数据存储的样式
        datafile = r'./BP/train_data.txt'
        with open(datafile, encoding='utf-8') as lines:
            for line in lines:
                line = line[:-1]  # 去除换行符
                x1, x2, x3, y1, y2 = line.split(' ')  # 注意最后一行数据必须有换行符
                x1 = float(x1)
                x2 = float(x2)
                x3 = float(x3)
                y1 = float(y1)
                y2 = float(y2)
                x = np.array([[x1, x2, x3]])
                y = np.array([[y1, y2]])
                print('x矩阵为:', x, '\ny矩阵为:', y)
                
                # 每次都要前向计算和后向传播
                one = Begin(x, wa, wb, y, b1, b2, n)
                det1, det, a1 = one.mount()

                # j += 1
                # print(j)

                if det[0][1] < e and det[0][0] < e: # 输出层误差几乎等于0,则退出迭代循环
                    boolx = False
                    break

                # 训练更新权值
                wa, wb, b1, b2 = train(det1, det, a1, n, wb, wa, x, b1, b2)

                # 检测
                print('det为:\n', det)

        if boolx == False:
            print('最终Det为:\n', det)
            print('隐藏层节点的权重wa:', wa, '\n隐藏层节点的权重b1:\n', b1, '\n输出层节点的权重wb:\n', wb, '\n输出层节点的权重b2:\n', b2)
            break

        # if j >=1000:
        #     print('隐藏层节点的权重wa:', wa, '\n隐藏层节点的权重b1:\n', b1, '\n输出层节点的权重wb:\n', wb, '\n输出层节点的权重b2:\n', b2)
        #     break

# 神经网络激活函数为sigmoid函数, 采用numpy方法
def sigmoid(x):
    z = np.exp(-x)
    sig = 1 / (1 + z)

    return sig

# 初始节点权重定义
# w4, w5, w6, w7, w8, w9都不是矩阵, wa, wb才是矩阵,这和矩阵在python中的定义有关
w4 = np.array([0.4, 0.4, 0.2])  # 隐藏层a4对输入层的权值,无偏置
w5 = np.array([0.3, 0.2, 0.5])  # 隐藏层a5对输入层的权值,无偏置
w6 = np.array([0.6, 0.3, 0.1])  # 隐藏层a6对输入层的权值,无偏置
w7 = np.array([0.3, 0.4, 0.3])  # 隐藏层a7对输入层的权值,无偏置

w8 = np.array([0.2, 0.3, 0.4, 0.1]) # 输出层y1对隐藏层的权值,无偏置
w9 = np.array([0.5, 0.1, 0.3, 0.1]) # 输出层y2对隐藏层的权值,无偏置

wa = np.array([w4, w5, w6, w7]) # 输入隐藏层间的的权重  
wb = np.array([w8, w9]) # 输出隐藏层间的权重
print('wa的矩阵形式:', wa.shape, '\nwb的矩阵形式:', wb.shape)

b1 = np.array([[0, 0.2, 0.5, 0.3]]) # a4--a7的偏置
b2 = np.array([[1, 0]])  # a8-a9的偏置

e = 0.001
n = 0.5

# 迭代
iterate(wa, wb, b1, b2, n, e)

 代码写的很简略,对导入数据的归一化并未加入,而且初始数据其实是随便写的,文件如下图:

 最后的结果也并没有向线性回归时那样规整,因为初始数据少而且粗略,所以代码中学习率这种要求细致的参数也没加入什么操作。

 参考:零基础入门深度学习(3) - 神经网络和反向传播算法 - 作业部落 Cmd Markdown 编辑阅读器

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

全链接神经网络python简单实现 的相关文章

随机推荐

  • 基于centOS7.5 x64/openjdk1.8/tomcat8.5/nginx1.16/nodejs/mysql8.0/redis3/git的服务器环境配置)

    基于centOS7 5 64 openjdk1 8 tomcat nginx nodejs mysql5 7 git的服务器环境配置 我以前的三年和未来的三年从事网站开发 主要手段是JAVA python nodejs 前端大套间 偶尔写写
  • qml绘制仪表盘控件

    刚开始上手qt 说实话迷得很啊 不过qt做的界面是真的漂亮 之前在b站看qt官方发布的一些视频 仪表盘煞是好看 今天倒腾了一天 用qml绘制了一个简单的汽车仪表控件 趁现在还热着 先记下来 新建一个空的qml工程 创建工程的时候要注意 工程
  • PostMan学习记录10 - 上传文件

    后台代码示例 PostMapping upload public String upload RequestParam name files required false MultipartFile files try if files n
  • 目标检测系列:Faster RCNN、FPN

    Faster RCNN FPN Faster RCNN 动机 Fast RCNN虽然对于检测的速度已经接近于达到实时 但是候选区域的提取方法依然是依赖于传统的算法例如选择性搜索 而选择性搜索在CPU上要实现一张图像的候选区域提取需要达到2秒
  • 轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)

    轻量级Java EE企业应用实战 第4版 Struts 2 Spring4 Hibernate整合开发 含CD光盘1张 国家级奖项获奖作品升级版 四版累计印刷27次发行量超10万册的轻量级Java EE经典著作 李刚 编著 ISBN 978
  • 概率论【常见的五种分布】--猴博士爱讲课

    4 常见的五种分布 1 6 符合均匀分布 求概率 均匀分布U a b 2 6 符合泊松分布 求概率 泊松分布P A lambda是参数 x是某某次数 如果是这样的 千万不要用1 P X 6 这种 要一个一个算 3 6符合二项分布 求概率 4
  • 面试官,我已经掌握了MyBits,你看我还有机会吗?

    一 MyBatis 面试题 1 什么是 Mybatis 2 Mybaits 的优点 3 MyBatis 框架的缺点 4 MyBatis 框架适用场合 5 MyBatis 与 Hibernate 有哪些不同 6 和 的区别是什么 7 当实体类
  • Docker - 国内镜像的配置及使用

    开发十年 就只剩下这套Java开发体系了 gt gt gt Docker国内镜像 DaoCloud Docker加速器阿里云 开发者平台 微镜像 希云cSphere镜像广场 时速云灵雀云网易蜂巢 阿里云的Docker加速器 阿里云 开发者平
  • 对老赵写的简单性能计数器的修改

    对老赵写的简单性能计数器的修改 早上看到老赵写的这个性能计数器 感觉很实用 不过老赵用了很多 C 3 0 的新语法 还用了 VISTA 和 Server 2008 下特有的Win32 API 对于还在用C 2 0 或者还工作在 XP 或者
  • nginx启动只有master没有worker_探究Nginx的工作原理,才知道为什么这么高效!

    1 Nginx的模块 Nginx的模块从结构上分为核心模块 基础模块和第三方模块 核心模块 HTTP模块 EVENT模块和MAIL模块 基础模块 HTTP Access模块 HTTP FastCGI模块 HTTP Proxy模块和HTTP
  • 平面设计除了PS还有哪些工具推荐

    平面设计在我们的日常生活中无处不在 无论是传统媒体还是网络媒体 我们每天都会沉浸在大量的平面设计作品中 因此 我们或多或少会对设计有自己的看法 其实 即使是非专业人士 市场上也有很多平面设计软件 本文盘点了平面设计的五大软件 1 即时设计
  • Android 6.0 解决recyclerview 在 scrollview 中不能全部显示,高度不正常的问题。

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 这个问题困扰了我半天 国内百度上的资料非常的烂 根本无法解决问题 在android 4 5 版本中 scrollview 包含了一个recyclerview 滚动一切正常
  • 教你使用windeployqt工具来进行Qt的打包发布

    Qt 官方开发环境使用的动态链接库方式 在发布生成的exe程序时 需要复制一大堆 dll 如果自己去复制dll 很可能丢三落四 导致exe在别的电脑里无法正常运行 因此 Qt 官方开发环境里自带了一个工具 windeployqt exe 问
  • ARM64基础14:ARM64的中断处理之GIC400实现(以树莓派4采用的BCM2711芯片为例)

    接上篇 ARM64基础13 ARM64的异常处理之中断处理 以树莓派4采用的BCM2711芯片为例 1 GIC的诞生背景 传统中断控制器 比如树莓派4b的legacy interrupt controller 具备 中断enable寄存器
  • osgEarth+VS2015开发环境搭建

    前言 osgEarth是基于OpenSceneGraph OSG 实现的3DGIS引擎 而OSG是一个开源的三维实时场景图形开发框架 学习osgEarth之前最好先学习下OSG 这是OSG官网有很多学习资料可以参考 osgEarth同时支持
  • STM32CubeMX官网下载方法

    目录 CubeMX下载 芯片包下载 和CubeIDE区别 CubeMX下载 主要是对下载链接做个记录 不再从打开百度 搜索ST这样一步步记录 点击STM32CubeMX STM32Cube initialization code gener
  • 共识算法 PBFT浅析

    PBFT是PracticalByzantine Fault Tolerance的缩写 意为实用拜占庭容错算法 该算法是Miguel Castro 卡斯特罗 和Barbara Liskov 利斯科夫 在1999年提出来的 解决了原始拜占庭容错
  • 百度深度强化学习框架PARL技术学习笔记

    目录 前言 寄语 基础准备和预习 第一节课 玩个简单的迷宫游戏吧 第二节课 基于表格型方法求解RL 1 SARSA算法 2 Q Learning算法 第三节课 基于神经网络求解RL 第三节课 基于策略梯度求解RL 第四节课 连续动作空间上求
  • 前端开发工程师面试最常见问题(20题&附答案)

    目录 1 在制作一个Web应用或Web站点的过程中 你是如何考虑它的UI 安全性 高性能 SEO 可维护性以及技术因素的 2 谈谈你喜欢的开发环境 例如操作系统 编辑器 浏览器 工具等等 3 你最熟悉哪一套版本控制系统 4 描述一下当你制作
  • 全链接神经网络python简单实现

    什么是全链接神经网络 full connected FC 借用此图来直观的表示一下 规则如下 神经元按照层来布局 最左边的层叫做输入层 负责接收输入数据 最右边的层叫输出层 我们可以从这层获取神经网络输出数据 输入层和输出层之间的层叫做隐藏