入门神经网络——浅层神经网络

news2024/12/23 19:34:28

文章目录

  • 一、基础知识
    • 1.浅层神经网络介绍
    • 2.浅层神经网络的正向传播
    • 3.反向传播
  • 二、浅层神经网络代码实例

一、基础知识

1.浅层神经网络介绍

此次构件浅层神经网络,相比于单神经元,浅层神经网络拥有多个神经元,因此又可以称为多神经元网络,如下图所示。
在这里插入图片描述
多神经元网络基本由三部分组成:输入层、隐藏层、输出层
**输入层:**最前面负责输入特征的层(注:在统计神经网络层数时通常不把这一层统计在内,像上图是一个2层的神经网络)。
**隐藏层:**中间的所有层称为隐藏层。
**输出层:**最后一层负责输出最后结果的层。

2.浅层神经网络的正向传播

以下图为例,首先分别计算第一层的每一个神经元的a,其中上标[]里的数字表示第几层,下标数字表示该层中的第几个神经元。
在这里插入图片描述
计算公式如下所示
在这里插入图片描述
此例子中的隐藏层的神经元个数为4个,但是当神经元个数较多时需要用向量的形式计算:
第一层:
在这里插入图片描述
第二层:
在这里插入图片描述
此例子中输入为单样本,当进行多样本输入训练时,
在这里插入图片描述
由此计算出 成本J,完成了依此正向传播。

3.反向传播

在这里插入图片描述
首先计算第二层的相关偏导数,与单神经元网络一致:
在这里插入图片描述
之后再计算第一层相关偏导数,由于第一层没有与损失函数直接相邻,只能通过链式法则。计算第一层相关偏导数时,首先需要计算出dZ[1],dW[1],db[1]都可以通过dZ[1]求得。
在这里插入图片描述
之后再进行向量化,最终得到反向传播后计算的相关偏导数如下所示
在这里插入图片描述

二、浅层神经网络代码实例

此次实例采用代码生成的虚拟数据集来演示,这个数据集由400个样本组成。这400个样本是400个颜色点。输入特征X是点的横纵坐标,标签Y是点的颜色标签(0表示红色,1表示蓝色)。
该样本点如下图所示:
在这里插入图片描述
此次的目标就是通过训练一个神经网络来通过坐标值判断在上图坐标系中某一点可能的颜色,例如坐标(-4,2)的点可能是什么颜色,(-4,3)最可能是什么颜色。将红色和蓝色的点区分出来。

import numpy as np
import matplotlib.pyplot as plt
import sklearn  # 其它库之前我们都介绍过了。这个新库是用于数据挖掘,数据分析和机器学习的库,例如它里面就内置了很多人工智能函数
import sklearn.datasets
import sklearn.linear_model


# 生成数据集函数
def load_planar_dataset():
    np.random.seed(1)
    m = 400  # number of examples
    N = int(m / 2)  # number of points per class
    D = 2  # dimensionality
    X = np.zeros((m, D))  # data matrix where each row is a single example
    Y = np.zeros((m, 1), dtype='uint8')  # labels vector (0 for red, 1 for blue)
    a = 4  # maximum ray of the flower

    for j in range(2):
        ix = range(N * j, N * (j + 1))
        t = np.linspace(j * 3.12, (j + 1) * 3.12, N) + np.random.randn(N) * 0.2  # theta
        r = a * np.sin(4 * t) + np.random.randn(N) * 0.2  # radius
        X[ix] = np.c_[r * np.sin(t), r * np.cos(t)]
        Y[ix] = j

    X = X.T
    Y = Y.T

    return X, Y


# 画图函数
def plot_decision_boundary(model, X, y):
    # Set min and max values and give it some padding
    x_min, x_max = X[0, :].min() - 1, X[0, :].max() + 1
    y_min, y_max = X[1, :].min() - 1, X[1, :].max() + 1
    h = 0.01
    # Generate a grid of points with distance h between them
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Predict the function value for the whole grid
    Z = model(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # Plot the contour and training examples
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.ylabel('x2')
    plt.xlabel('x1')
    plt.scatter(X[0, :], X[1, :], c=y, cmap=plt.cm.Spectral)


# 激活函数
def sigmoid(x):
    """
    Compute the sigmoid of x

    Arguments:
    x -- A scalar or numpy array of any size.

    Return:
    s -- sigmoid(x)
    """
    s = 1 / (1 + np.exp(-x))
    return s


# 初始化参数w和b函数
def initialize_parameters(n_x, n_h, n_y):
    """
    参数:
    n_x -- 输入层的神经元个数
    n_h -- 隐藏层的神经元个数
    n_y -- 输出层的神经元个数
    """

    np.random.seed(2)

    # 随机初始化第一层(隐藏层)相关的参数w.
    # 每一个隐藏层神经元都与输入层的每一个神经元相连。每一个相连都会有一个对应的参数w。
    # 所以W1的维度是(n_h, n_x),表示(隐藏层的神经元个数,输入层神经元个数)
    W1 = np.random.randn(n_h, n_x) * 0.01

    # 将第一层的参数b赋值为0,因为w已经非0了,所以b可以为0
    # 因为每一个神经元只有一个对应的b,所以b1的维度是(n_h, 1),表示(隐藏层神经元个数,1)
    b1 = np.zeros(shape=(n_h, 1))

    # 同理,初始化第二层的w和b
    W2 = np.random.randn(n_y, n_h) * 0.01
    b2 = np.zeros(shape=(n_y, 1))

    # 将初始化好的参数放入一个字典变量中
    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}

    return parameters


# 前向传播函数
def forward_propagation(X, parameters):
    """
    参数:
    X -- 输入特征,维度是 (横纵坐标, 样本数)
    parameters -- 参数w和b

    Returns:
    A2 -- The sigmoid output of the second activation
    cache -- a dictionary containing "Z1", "A1", "Z2" and "A2"
    """

    m = X.shape[1]  # 获取样本数
    # print("样本数:" + str(m))

    # 从字典中取出参数
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']

    # 实现前向传播算法
    Z1 = np.dot(W1, X) + b1
    A1 = np.tanh(Z1)  # 第一层的激活函数我们使用tanh。numpy库里面已经帮我们实现了tanh工具函数
    Z2 = np.dot(W2, A1) + b2
    A2 = sigmoid(Z2)  # 第二层我们使用sigmoid,因为我们要解决的这个问题属于二分问题。这个函数是我们自己在planar_utils里面实现的。

    # 将这些前向传播时得出的值保存起来,因为在后面进行反向传播计算时会用到他们。
    cache = {"Z1": Z1,
             "A1": A1,
             "Z2": Z2,
             "A2": A2}

    return A2, cache


# 这个函数被用来计算成本
def compute_cost(A2, Y, parameters):
    """
    参数:
    A2 -- 神经网络最后一层的输出结果
    Y -- 数据的颜色标签
    """

    m = Y.shape[1]

    logprobs = np.multiply(np.log(A2), Y) + np.multiply((1 - Y), np.log(1 - A2))
    cost = - np.sum(logprobs) / m

    return cost


# 然后就是反向传播
def backward_propagation(parameters, cache, X, Y):
    """
    参数:
    parameters -- 参数w和b
    cache -- 前向传播时保存起来的一些数据
    X -- 输入特征
    Y -- 标签
    """
    m = X.shape[1]  # 获取样本数

    W1 = parameters['W1']
    W2 = parameters['W2']

    A1 = cache['A1']
    A2 = cache['A2']

    # 根据我们文章中介绍的算法公式来计算梯度(偏导数)
    dZ2 = A2 - Y
    dW2 = (1 / m) * np.dot(dZ2, A1.T)
    db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)
    dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.power(A1, 2))
    dW1 = (1 / m) * np.dot(dZ1, X.T)
    db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True)

    grads = {"dW1": dW1,
             "db1": db1,
             "dW2": dW2,
             "db2": db2}

    return grads  # 返回计算得到的梯度


# 用上面得到的梯度来进行梯度下降(更新参数w和b,使其更优化)
def update_parameters(parameters, grads, learning_rate=1.2):
    """
    参数:
    parameters -- 参数w和b
    grads -- 梯度
    """

    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']

    dW1 = grads['dW1']
    db1 = grads['db1']
    dW2 = grads['dW2']
    db2 = grads['db2']

    # 根据梯度和学习率来更新参数,使其更优
    W1 = W1 - learning_rate * dW1
    b1 = b1 - learning_rate * db1
    W2 = W2 - learning_rate * dW2
    b2 = b2 - learning_rate * db2

    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}

    return parameters


# 上面已经将各个所需的功能函数都编写好了。现在我们将它们组合在一个大函数中来构建出一个训练模型。
def nn_model(X, Y, n_h, num_iterations=10000, print_cost=True):
    """
    Arguments:
    X -- 输入特征
    Y -- 标签
    n_h -- 隐藏层的神经元个数
    num_iterations -- 训练多少次
    print_cost -- 是否打印出成本
    """

    np.random.seed(3)
    n_x = X.shape[0]  # 根据输入特征的维度得出输入层的神经元个数
    n_y = Y.shape[0]  # 根据标签的维度得出输出层的神经元个数

    # 初始化参数
    parameters = initialize_parameters(n_x, n_h, n_y)
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']

    # 在这个循环里进行训练,一次一次地对参数进行优化
    for i in range(0, num_iterations):
        # 进行前向传播
        A2, cache = forward_propagation(X, parameters)

        # 计算出本次的成本
        cost = compute_cost(A2, Y, parameters)

        # 进行反向传播。根据前向传播得到的一些值算出梯度。
        grads = backward_propagation(parameters, cache, X, Y)

        # 根据梯度对参数进行一次优化(下降)
        parameters = update_parameters(parameters, grads)

        # 将本次训练的成本打印出来
        if print_cost and i % 1000 == 0:
            print("在训练%i次后,成本是: %f" % (i, cost))

    return parameters


# 我们已经可以通过上面的函数来进行参数训练。
# 这个函数可以利用上面学习到的参数来对新数据进行预测
def predict(parameters, X):
    """
    参数:
    parameters -- 训练得出的参数(学习到的参数)
    X -- 预测数据
    """

    # 预测其实就是简单地执行一次前向传播
    A2, cache = forward_propagation(X, parameters)
    predictions = np.round(A2)  # 对结果进行四舍五入,小于0.5就是0,否则就是1

    return predictions


np.random.seed(1)  # 设置一个随机数种子,来保证后面我的代码产生的随机数与你们电脑上产生的一样,这样我的结果才能和你们运行的结果一样
X, Y = load_planar_dataset()

# 将训练集送入模型中,并设置隐藏层数为4层,训练次数为1000次
parameters = nn_model(X, Y, n_h=50, num_iterations=20000,print_cost=True)
# 然后用训练得出的参数进行预测。
predictions = predict(parameters, X)
print('预测准确率是: %d' % float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%')
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y.ravel())
plt.show()

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/439461.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python杂事】 处理Excel中日期时间之间没有空格问题

目录 一、数据源要求二、逻辑思路1、ROI区域2、对ROI区域进行判定 三、代码实现四、成果展示总结 碰到一个非常有趣的问题: 在我们的日常工作中,常常需要处理各种各样的数据,其中不乏包含日期和时间信息的数据。有时候我们会发现这些数据中日…

事件抽取的概念

1. 事件的定义 事件是指发生在某个特定的时间点或时间段、某个特定的地域范围内,由一个或者多个角色参与的一个或者多个动作组成的事情或状态的改变。 2. 事件基本元素 时间、地点、人物、原因、结果 3.事件抽取的定义 主要研究如何从描述事件信息的文本中抽取…

python共词矩阵分析结果一步到位

import os import re import pandas as pd from PyPDF2 import PdfFileReader import string import yakeif __name__ __main__:# 运行第一部分代码pdf_files_path C:/Users/win10/Documents/美国智库/pdf_files# 定义一个函数,用于读取PDF文件并将其转化成文本de…

C++学习之交互式表达式求值的详细讲解和简单代码示例

一、怎么理解交互式表达式求值: 交互式求表达式值是指通过命令行交互的方式,接收用户输入的数值和运算符号,然后计算出其表达式的值并返回给用户。这种方式可以方便地进行简单的计算和查错,也可以用于程序设计中一系列复杂的计算…

单CDN与融合CDN之间的对比:优缺点及注意事项

CDN是现代互联网服务的重要组成部分,它CDN可帮助内容提供者高速交付内容,不同的服务器部署在全球不同的数据中心,并在它们之间共享相同的网络路径。随着企业意识到CDN的重要性,越来越多的企业正在使用CDN作为内容分发工具。互联网…

完美解决丨RuntimeError: create_session() called before __init__().

错误&#xff1a; import sys sys.path.append(/home/pi/ssd-detect) import ssd_detect ssd_detect.detect(/home/pi/ssd-detect/test.jpg) 报错如下&#xff1a; Traceback (most recent call last): File "test.py", line 6, in <module ssd_detect.detect(/ho…

ArcGIS制作建设项目使用林地现状图

近年来&#xff0c;随着经济社会的快速发展&#xff0c;各地建设项目不断增多&#xff0c;占用征用林地项目的数量也呈逐年上升的趋势。根据《占用征用林地审核审批管理规范》规定&#xff0c;建设项目申请占用征用林地&#xff0c;应编制的项目使用林地可行性报告&#xff1b;…

Linux-升级CMake版本(Ubuntu18.4)

一、简介 在一些场景中&#xff0c;因为CMake版本过低而无法编译&#xff0c;此时就需要升级CMake的版本。 二、升级 卸载 先卸载旧的cmake sudo apt-get autoremove cmake 安装 切换文件夹 cd /usr/src 下载cmake包。需要哪个版本&#xff0c;可以自行修改版本号。 注&#…

中国人工智能公司CIMCAI集装箱识别云服务全球用户量领先核心科技领先,免费人工智能集装箱识别云服务,智能化港航中国人工智能公司

中国人工智能公司CIMCAI集装箱识别云服务全球用户量领先核心科技领先&#xff0c;免费人工智能集装箱识别云服务&#xff0c;智能化港航智慧港航.全球领先CIMCAI ENGINE集装箱AI检测云服务&#xff0c;集装箱号识别率99.98%&#xff0c;全球超4000企业用户使用&#xff0c;集装…

npm 包本地调试(详细流程:包本地路径、npm link 、yalc)

一、使用 包本地路径安装 package.json 中的包名叫 dzmtest&#xff08;这个才是重点&#xff09;&#xff0c;包的文件夹名 test。 获取到包的文件夹路径 执行安装命令&#xff0c;然后提示安装成功 $ npm install 包文件夹路径# 例如&#xff1a; $ npm install /Users/d…

【Linux】Linux第一个小程序-进度条

前言&#xff1a; 在之前的学习中&#xff0c;我们已经基本掌握了关于了 Linux 下的一些工具的使用&#xff0c;接下来我们运用之前学到的知识&#xff0c;我将带领大家写了一个关于 进度条 的小程序来练练手&#xff01;&#xff01;&#xff01; 本文目录 &#xff08;一&am…

密码模块非入侵式攻击及其缓解技术GMT0083-2020

密码模块非入侵式攻击&#xff0c;是一种攻击方式&#xff0c;在这种攻击中&#xff0c;攻击者不会直接访问受攻击者的密码模块。相反&#xff0c;攻击者会利用其他途径获得用户的凭证&#xff0c;然后使用这些凭证去访问密码模块。这种攻击通常使用钓鱼邮件、社交工程等技巧&a…

户外软件推荐与介绍——奥维和两步路

文章目录 &#xff08;一&#xff09;记录坐标的网站1、奥维互动地图注册2、记录坐标3、如何导出坐标点到ArcGIS4、导航5、记录轨迹6、下载离线地图 &#xff08;二&#xff09;记录轨迹的软件&#xff08;三&#xff09;离线地图的下载&#xff08;四&#xff09;如何使用3D地…

Chapter5-消息队列的核心机制

Broker 是 RocketMQ 的核心&#xff0c;大部分‘重量级”工作都是由 Broker 完成的&#xff0c;包括接收 Producer 发过来的消息、处理 Consumer 的消费消息请求、&#xff0d;消息的持久化存储、消息的 HA 机制以及服务端过滤功能等。 5.1 消息存储和发送 分布式队列因为有高…

网络协议-TCP、IP协议和互联网协议群

目录 TCP/IP协议群简介&#xff08;互联网协议群&#xff09;&#xff08;Internet Protocol Suite&#xff09; 应用层&#xff08;Application&#xff09;(合并简化了展示层&#xff0c;会话层) 传输层&#xff08;Transport&#xff09; 网络层&#xff08;Internet&am…

射频功率放大器在铝板损伤量化表征中的应用

实验名称&#xff1a;基于异常指数的铝板损伤量化表征 研究方向&#xff1a;损伤量化 测试目的&#xff1a; 结构损伤检测与量化评估对于保障航空、航天、船舶、石油化工及兵器工业等领域的基础设施结构安全性具有重要意义&#xff0c;受到了广泛的关注。在现有的结构监测技术中…

微内核与宏内核

了解Linux发展史的同学都知道&#xff0c;关于linux吵架史的一段佳话&#xff0c;就是关于内核设计思想之争&#xff0c;这段故事在linus Tovalds的自传中也有提到。我们都知道linux操作系统由Linus Tovalds模仿minix操作系统开发的。 虽然Linux是受MINIX启发而发明&#xff0c…

Git——利用SSH密钥本地仓库上传远程GitHub库

文章目录 1、前言2、详细步骤2.1 创建密钥2.2 进入密钥文件并复制2.3 在GitHub上添加密钥2.4 回到本地仓库文件夹&#xff0c;连接GitHub并上传 3. 结语 1、前言 现在想要从本地设备将本地仓库上传到GitHub上需要用到SSH密钥&#xff0c;接下来讲解大致的步骤&#xff0c;本文默…

一本通 3.4.6 拓扑排序

1352&#xff1a;【例4-13】奖金 【题目描述】 由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出&#xff0c;Yali Company总经理Mr.Z心情好&#xff0c;决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。 于是Mr.Z下令召开m方会谈…

openEuler实验-基于openEuler的云景平台文件管理系统

一些常见的Linux命令 目录 前言 实验目的 实验内容 实验知识点 实验环境 实验分析 系统登录和电源管理 1&#xff09;使用login命令登录系统 2&#xff09;退出openEuler 3&#xff09;退出当前的shell 软件管理 1&#xff09;查询目录信息 2&#xff09;切换目录路…