用 Python 从零开始创建神经网络(三):添加层级(Adding Layers)

添加层级(Adding Layers)

  • 引言
  • 1. Training Data
  • 2. Dense Layer Class

引言

我们构建的神经网络变得越来越受人尊敬,但目前我们只有一层。当神经网络具有两层或更多隐藏层时,它们变成了“深度”网络。目前我们只有一层,实际上是一个输出层。为什么我们想要两层或更多隐藏层的原因将在后面的章节中变得明显。目前,我们没有隐藏层。隐藏层不是输入层或输出层;作为科学家,你看到的数据是输入到输入层的数据以及来自输出层的结果数据。这些端点之间的层具有我们不一定处理的值,因此得名“隐藏”。不过,别让这个名字让你认为你不能访问这些值。你通常会使用它们来诊断问题或改进你的神经网络。为了探索这个概念,让我们给这个神经网络增加另一层,并且,现在,让我们假设我们将要拥有的这两层是隐藏层,我们还没有编写我们的输出层。

在我们添加另一层之前,让我们思考一下即将到来的内容。对于第一层,我们可以看到我们有一个包含4个特征的输入:


在这里插入图片描述

将包含 4 个特征的输入层转化为包含 3 个神经元的隐藏层。


样本(特征集数据)通过输入传递,输入本身不会以任何方式改变它,传递到我们的第一个隐藏层,我们可以看到这一层有3组权重,每组包含4个值。

这3组独特的权重集与它们各自的神经元相关联。因此,由于我们有3组权重,这第一个隐藏层就有3个神经元。每个神经元都有一组独特的权重,我们有4个(因为这一层有4个输入),这就是为什么我们的初始权重有一个形状为 ( 3 , 4 ) (3,4) (3,4) 的原因。

现在,我们希望增加另一层。为此,我们必须确保该层的预期输入与前一层的输出匹配。我们通过设置每层有多少组权重和偏差来设定层中的神经元数量。前一层对当前层的权重集的影响是每个权重集需要有每个输入的单独权重。这意味着前一层的每个神经元(或如果我们谈论输入的话,每个特征)都有一个独特的权重。前一层有3组权重和3个偏差,所以我们知道它有3个神经元。这意味着,对于下一层,我们可以有尽可能多的权重集(因为这是这个新层将拥有的神经元数量),但这些权重集中的每一个都必须有3个独立的权重。

为了创建这个新层,我们将复制并粘贴我们的权重和偏差到 weights2 和 biases2,并将它们的值改为新的假设集。这里有一个例子:

import numpy as npinputs = [[1, 2, 3, 2.5],[2., 5., -1., 2],[-1.5, 2.7, 3.3, -0.8]]weights = [[0.2, 0.8, -0.5, 1],[0.5, -0.91, 0.26, -0.5],[-0.26, -0.27, 0.17, 0.87]]
biases = [2, 3, 0.5]weights2 = [[0.1, -0.14, 0.5],[-0.5, 0.12, -0.33],[-0.44, 0.73, -0.13]]
biases2 = [-1, 2, -0.5]

接下来,我们将调用输出 layer1_ouputs

layer1_outputs = np.dot(inputs, np.array(weights).T) + biases
print("layer1_outputs:", layer1_outputs)
>>>
layer1_outputs: [[ 4.8    1.21   2.385][ 8.9   -1.81   0.2  ][ 1.41   1.051  0.026]]

正如之前所述,层的输入要么是来自您正在训练的实际数据集的输入,要么是来自前一层的输出。这就是为什么我们定义了两个版本的权重和偏差,但只有一个输入的原因 —— 因为第二层的输入将是前一层的输出:

layer2_outputs = np.dot(layer1_outputs, np.array(weights2).T) + biases2
print("layer2_outputs:", layer2_outputs)
>>>
layer2_outputs: [[ 0.5031  -1.04185 -2.03875][ 0.2434  -2.7332  -5.7633 ][-0.99314  1.41254 -0.35655]]

完整:

import numpy as npinputs = [[1, 2, 3, 2.5],[2., 5., -1., 2],[-1.5, 2.7, 3.3, -0.8]]weights = [[0.2, 0.8, -0.5, 1],[0.5, -0.91, 0.26, -0.5],[-0.26, -0.27, 0.17, 0.87]]
biases = [2, 3, 0.5]weights2 = [[0.1, -0.14, 0.5],[-0.5, 0.12, -0.33],[-0.44, 0.73, -0.13]]
biases2 = [-1, 2, -0.5]layer1_outputs = np.dot(inputs, np.array(weights).T) + biases
print("layer1_outputs:", layer1_outputs)layer2_outputs = np.dot(layer1_outputs, np.array(weights2).T) + biases2
print("layer2_outputs:", layer2_outputs)

此时,我们的神经网络可以直观地表示为:
在这里插入图片描述


1. Training Data

训练数据


接下来,我们将使用一个可以创建非线性数据的函数,而不是手工输入随机数据。什么叫非线性数据?线性数据可以用直线拟合或表示。


在这里插入图片描述

可用直线(绿线)表示(拟合)的数据(橙色点)示例


非线性数据无法用直线很好地表示:


在这里插入图片描述

直线拟合不理想的数据(橙色点)示例。


如果你要绘制形式为 ( x , y ) (x, y) (x,y) 的数据点,其中 y = f ( x ) y = f(x) y=f(x),并且看起来像是一条具有明显趋势或斜率的线,那么很可能,这些是线性数据!线性数据可以非常容易地被比神经网络简单得多的机器学习模型近似。其他机器学习算法不容易近似的是非线性数据集。为了简化这一点,我们创建了一个可以通过 pip 安装的Python包,名为 nnfs:

pip3 install nnfs

nnfs 软件包包含一些函数,我们可以用它们来创建数据。例如:

from nnfs.datasets import spiral_data

螺旋数据(spiral_data)函数是从 https://cs231n.github.io/neural-networks-case-study/ 上稍加修改的,它是本主题的一个很好的补充资源。


通常你不会为你的神经网络从函数生成训练数据。你会有一个实际的数据集。这种方式生成数据集纯粹是为了目前阶段的便利性。我们还将使用这个包来确保每个人的重复性,使用 nnfs.init(),在导入NumPy之后:

import numpy as np
import nnfsnnfs.init()

nnfs.init()执行三件事:它将随机种子设置为0(默认情况下),创建一个 float32 数据类型的默认值,并覆盖NumPy的原始点积函数。所有这些都是为了确保后续操作的可重复结果。

spiral_data函数允许我们创建一个数据集,可以有我们想要的任意多的类别。该函数有参数可以选择类别数和每个类别中点/观测的数量,来生成结果中的非线性数据集。例如:

import numpy as np
import nnfs
from nnfs.datasets import spiral_data
import matplotlib.pyplot as pltnnfs.init()X, y = spiral_data(samples=100, classes=3)plt.scatter(X[:,0], X[:,1])
plt.show()

在这里插入图片描述

未着色的螺旋数据集


如果从中心开始追踪,就可以分别确定所有 3 个类别,但对于机器学习分类器来说,这是一个非常具有挑战性的问题。在图表中添加颜色可以让这一点更加清晰:

import numpy as np
import nnfs
from nnfs.datasets import spiral_data
import matplotlib.pyplot as pltnnfs.init()X, y = spiral_data(samples=100, classes=3)plt.scatter(X[:,0], X[:,1])
plt.show()plt.scatter(X[:, 0], X[:, 1], c=y, cmap='brg')
plt.show()

在这里插入图片描述

在这里插入图片描述

按类别着色的螺旋数据集


请记住,神经网络不会意识到颜色的差异,因为数据没有类别编码。这只是作为对读者的一种指导。在上述数据中,每个点都是特征,其坐标是构成数据集的样本。该点的 “分类 ”与它属于哪种螺旋有关,如上图中的蓝色、绿色或红色。然后,这些颜色将被分配一个类别编号,供模型拟合,如 0,1和2。


2. Dense Layer Class

密集层级


既然我们不再需要手工输入数据,我们就应该为各种类型的神经网络层创建类似的功能。到目前为止,我们只使用了所谓的密集层或全连接层。这些层在论文、文献和代码中通常被称为 “密集 ”层,但你偶尔也会在代码中看到它们被称为全连接层,简称 “FC”。我们的密集层类将以两个方法开始:

class Layer_Dense:# Layer initializationdef __init__(self, n_inputs, n_neurons):# Initialize weights and biasespass # using pass statement as a placeholder# Forward passdef forward(self, inputs):# Calculate output values from inputs, weights and biasespass # using pass statement as a placeholder

如前所述,模型的权重通常是随机初始化的,但不总是这样。如果你希望加载一个预训练的模型,你将把参数初始化为预训练模型完成时的状态。也有可能即使是对于一个新模型,你也有一些除了随机之外的其他初始化规则。现在,我们将坚持使用随机初始化。接下来,我们有前向方法。当我们从头到尾通过模型传递数据时,这被称为前向传递。然而,就像其他一切一样,这并不是唯一的做事方式。你可以让数据回环并做其他有趣的事情。我们将保持通常的做法,执行一个常规的前向传递。

为了继续 Layer_Dense 类的代码,让我们添加权重和偏置的随机初始化:

import numpy as npclass Layer_Dense:# Layer initializationdef __init__(self, n_inputs, n_neurons):# Initialize weights and biasesself.weights = 0.01 * np.random.randn(n_inputs, n_neurons)self.biases = np.zeros((1, n_neurons))# Forward passdef forward(self, inputs):# Calculate output values from inputs, weights and biasespass # using pass statement as a placeholder

在这里,我们将权重设置为随机,偏置设置为0。请注意,我们将权重初始化为(输入,神经元),而不是(神经元,输入)。我们提前这样做,而不是每次执行前向传递时都转置,如上一章所解释的。为什么偏置为零?在特定情况下,例如当许多样本包含0值时,偏置可以确保神经元最初被激活。有时将偏置初始化为某个非零数可能是合适的,但偏置最常见的初始化是0。然而,在这些情况下,你可能会发现以另一种方式做事会成功。这将根据你的用例而有所不同,并且只是你在尝试改进结果时可以调整的许多事情之一。一个你可能想尝试其他方法的情况是所谓的死神经元。我们还没有在实践中讨论激活函数,但想象一下我们之前提到的阶跃函数:

在这里插入图片描述

权重 · 输入 + 偏置没有达到阶跃函数的阈值时,可能会导致神经元输出0。单独来看,这不是一个大问题,但如果每一个输入样本都导致这个神经元发生这种情况,就会成为一个问题(一旦我们讲解反向传播,这将变得清晰)。因此,这个神经元的0输出就成为另一个神经元的输入。任何与零相乘的权重都将是零。随着输出0的神经元数量增加,更多的输入将传递给下一个神经元这些0,使得网络基本上无法训练,或者“死亡”。


接下来,让我们更详细地探讨 np.random.randnnp.zeros 这些方法。这些方法是初始化数组的便捷方式。np.random.randn 产生一个均值为0和方差为1的高斯分布,这意味着它将生成以0为中心的随机数,正负都有,平均值接近0。一般来说,神经网络在 -1 到 +1 之间的值下工作最好,我们将在即将到来的章节中讨论这一点。因此,np.random.randn 生成围绕这些数字的值。我们将乘以 0.01 的高斯分布用于权重,以生成比较小的数值。否则,模型在训练过程中将需要更多时间来适应数据,因为开始的值与训练过程中进行的更新相比过大。这里的想法是用足够小的非零值开始一个模型,这些值不会影响训练。这样,我们就有一堆值可以开始使用,但希望没有太大或为零的值。如果你愿意,可以尝试除0.01之外的其他值。最后,np.random.randn 函数接受维度大小作为参数,并创建具有此形状的输出数组。

这里的权重将是第一维度的输入数量和第二维度的神经元数量。这类似于我们之前虚构的权重数组,只是随机生成的。每当有一个你不确定的函数或代码块时,你总是可以打印它出来。例如:

import numpy as np
import nnfsnnfs.init()random_test = np.random.randn(2,5)
zero_array = np.zeros((2,5))print("random_test:", random_test)
print("zero_array:", zero_array)
>>>
random_test: [[ 1.7640524   0.4001572   0.978738    2.2408931   1.867558  ][-0.9772779   0.95008844 -0.1513572  -0.10321885  0.41059852]]
zero_array: [[0. 0. 0. 0. 0.][0. 0. 0. 0. 0.]]

np.random.randn(2,5)函数调用返回了一个2x5的数组(我们也可以说它的“形状是 ( 2 , 5 ) (2,5) (2,5)”),数据是从均值为0的高斯分布中随机抽样得到的。

在调用 np.random.randn(2, 5) 时:参数 2 和 5 指定了生成数组的形状。 2 表示数组有行。 5 表示数组有列。

接下来,np.zeros 函数接受一个期望的数组形状作为参数,并返回一个填充了零的该形状数组。


我们将以行向量的形式初始化偏置,其形状为 ( 1 , n _ n e u r o n s ) (1, n\_{neurons}) (1,n_neurons),这将使我们能够在以后轻松地将其加到点积的结果上,无需进行转置等额外操作。

看一个我们方法初始化权重和偏置的例子:

import numpy as np
import nnfsnnfs.init()n_inputs = 2
n_neurons = 4weights = 0.01 * np.random.randn(n_inputs, n_neurons)
biases = np.zeros((1, n_neurons))print("weights:", weights)
print("biases:", biases)
>>>
weights: [[ 0.01764052  0.00400157  0.00978738  0.02240893][ 0.01867558 -0.00977278  0.00950088 -0.00151357]]
biases: [[0. 0. 0. 0.]]

接下来是我们的正演方法——我们需要用点积+偏差计算来更新它:

import numpy as npclass Layer_Dense:# Layer initializationdef __init__(self, n_inputs, n_neurons):# Initialize weights and biasesself.weights = 0.01 * np.random.randn(n_inputs, n_neurons)self.biases = np.zeros((1, n_neurons))# Forward passdef forward(self, inputs):# Calculate output values from inputs, weights and biasesself.output = np.dot(inputs, self.weights) + self.biases

我们已经准备好使用这个新类来代替硬编码计算,因此让我们使用讨论过的数据集创建方法生成一些数据,然后使用我们的新层来执行前向传递:

import numpy as np
import nnfs
from nnfs.datasets import spiral_datannfs.init()class Layer_Dense:# Layer initializationdef __init__(self, n_inputs, n_neurons):# Initialize weights and biasesself.weights = 0.01 * np.random.randn(n_inputs, n_neurons)self.biases = np.zeros((1, n_neurons))# Forward passdef forward(self, inputs):# Calculate output values from inputs, weights and biasesself.output = np.dot(inputs, self.weights) + self.biases# Create dataset
X, y = spiral_data(samples=100, classes=3)# Create Dense layer with 2 input features and 3 output values
dense1 = Layer_Dense(2, 3)# Perform a forward pass of our training data through this layer
dense1.forward(X)# Let's see output of the first few samples:
print(dense1.output[:5])
>>>
[[ 0.0000000e+00  0.0000000e+00  0.0000000e+00][-1.0475188e-04  1.1395361e-04 -4.7983500e-05][-2.7414842e-04  3.1729150e-04 -8.6921798e-05][-4.2188365e-04  5.2666257e-04 -5.5912682e-05][-5.7707680e-04  7.1401405e-04 -8.9430439e-05]]

在输出结果中,你可以看到我们有 5 行数据,每行有 3 个值。这 3 个值中的每一个都是dense1层中 3 个神经元输入每个样本后的值。好极了!我们有了一个神经元网络,所以我们的神经网络模型几乎名副其实了,但我们还缺少激活函数,所以接下来让我们完成激活函数!

代码的可视化:https://nnfs.io/ch3

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

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

相关文章

ClickHouse 24.10 版本发布说明

本文字数:13817;估计阅读时间:35 分钟 作者:ClickHouse Team 本文在公众号【ClickHouseInc】首发 又到了新版本发布的时间! 发布概要 本次ClickHouse 24.10 版本包含了25个新功能🎁、15项性能优化&#x1f…

AI4SCIENSE(鄂维南院士:再谈AI for Science)

鄂维南院士:再谈AI for Science_哔哩哔哩_bilibili 以往处理高维问题 量子力学:单变量乘积 统计学:旋转 AI4S 处理数据 蛋白质折叠? 不是纯粹的数据驱动 物理学等学科基本原理 例:分子动力学 数据模型 流程图 这…

华为云全新上线Serverless应用中心,支持一键构建文生图应用

近日,华为云全新上线Serverless应用中心,提供大量应用模板,帮助用户实现一键部署函数和周边依赖资源,节省部署时间,快速上手将应用部署到华为云函数工作流FunctionGraph,并一键开通周边依赖资源。 体验入口…

F5-TTS 整合包详细部署文档1110更新

F5-TTS 整合包详细部署文档:1110更新 F5-TTS 整合包详细部署教程1110更新 更新内容 本次更新加入了通义千问对话模型,以增强F5-TTS的功能和性能。 下载相关资源 F5-TTS文本转语音 链接:F5-TTS资源下载 文件列表 文件名大小说明01-主程序…

【bayes-Transformer-GRU多维时序预测】多变量输入模型。matlab代码,2023b及其以上

% 1. 数据准备 X_train 训练数据输入; Y_train 训练数据输出; X_test 测试数据输入; % 2. 模型构建 inputSize size(X_train, 2); numHiddenUnits 100; numResponses 1; layers [ … sequenceInputLayer(inputSize) biLSTMLayer(numHiddenUnits, ‘OutputMode’, ‘se…

AUTOSAR CP TCP/IP堆栈规范导读

一、规范的主要内容 该规范是AUTOSAR中关于TCP/IP堆栈的规范,主要内容包括以下几个方面: 总体介绍 功能概述:提供了发送和接收互联网协议数据的功能,位于Socket Adaptor和以太网接口模块之间。文档信息:包含文档标题…

redis安装

Redis的安装配置 安装Redis 安装gcc依赖 Redis是使用C语言编写的,Linux上并没有C语言的编译器,需要手动安装 yum install -y gcc tcl上传安装包并解压 将压缩包放在任意目录解压 tar -xzf redis-6.2.6.tar.gz安装 1.进入redis目录 cd redis-6.2.62.运行…

Linux系统程序设计--3. 文件操作

文件属性 存放文件属性的结构体 文件属性操操作函数 文件类型(7种) - 普通文件d目录p 管道文件l 符号链接(软链接) 判断文件类型的小程序 #include<sys/types.h> #include<sys/stat.h> #include<string.h> #include<stdio.h> #include<memory.h&…

单词反转和数组去重,附经典面试题一份

博彦科技笔试&#xff1a; 给定字符&#xff0c;拼接成单词进行反转单词&#xff1b; package org.example;public class Main {public static void main(String[] args) {char[] input {h, e, l, l, o, , w, o, r, l, d, , J, a, v, a};String inputToString new String(…

HTB:Precious[WriteUP]

目录 连接至HTB服务器并启动靶机 使用nmap对靶机TCP端口进行开放扫描 使用curl访问靶机80端口 使用ffuf爆破一下子域 使用浏览器访问该域名 使用curl访问该域名响应头 使用exiftool工具查看该pdf信息 横向移动 USER_FLAG&#xff1a;adf5793a876a190f0c08b3b6247cec32…

【2024.11.10实测有效:Win11右键默认显示更多设置教程】

winX 选择管理员 reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve# 再 taskkill /f /im explorer.exe & start explorer.exe! none taskkill /f /im explorer.exe; start explorer.exe

环形链表问题(图 + 证明 + 题)

文章目录 判断链表是否有环返回链表开始入环的第一个结点 判断链表是否有环 题目链接 思路&#xff1a; 可以明确的是&#xff1a;若一个链表带环&#xff0c;那么用指针一直顺着链表遍历&#xff0c;最终会回到某个地方。 我们可以定义两个指针&#xff08;快慢指针&#xf…

【优选算法 — 滑动窗口】最大连续1的个数 将 x 减到0的最小操作数

最大连续1的个数 最大连续1的个数 题目描述 题目解析 给我们一个元素全是0或者1的数组&#xff0c;和一个整数 k &#xff0c;然后让我们在数组选出最多的 k 个0&#xff1b;这里翻转最多 k 个0的意思&#xff0c;是翻转 0 的个数< k&#xff0c;而不是一定要翻转 k …

HTML基础

1.HTML基本结构标签 在Visual Studio Code中&#xff0c;使用&#xff01;回车就可以创建一个HTML的基本结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"wi…

CSM快速匹配与多分辨率匹配代码实现

0. 简介 CSM在Cartographer中是比较基础且非常适合拓展的功能。他主要的步骤如下图。 主要实现的步骤为&#xff1a; 1&#xff09;获取先验位姿&#xff0c;通过TF获取里程计的值&#xff0c;作为当前scan的预测位姿&#xff0c;将这个预测位姿当做扫描匹配的先验。 2&…

力扣力扣力:动态规划入门(1)

相信大家在第一次学动态规划的时候都是一脸懵逼的&#xff0c;在看了很多题解之后&#xff0c;陷入到了空的“最优子结构”等的大词上&#xff0c;依旧看不懂动态规划到底在干什么。今天我们也是老样子再一次的从零开始学习与讲解&#xff0c;俺也是从零开始学动态规划&#xf…

私域流量时代下的新型商业模式:以开源链动 2 + 1 模式、AI 智能名片、S2B2C 商城小程序源码为例

摘要&#xff1a;本文探讨了私域流量时代的特点及其对商业盈利模式的影响。通过分析从大众消费时代到私域流量时代的转型&#xff0c;阐述了商品到“人”的变化过程。同时&#xff0c;深入研究了开源链动 2 1 模式、AI 智能名片和 S2B2C 商城小程序源码在私域流量发展中的作用…

多模态交互智能体全面解析:定义、架构、学习机制、系统实现、分类、应用场景及评估方法

多模态AI系统很可能会成为我们日常生活中无处不在的存在。使这些系统更具交互性的一种有希望的方法是将它们作为物理和虚拟环境中的智能体。目前&#xff0c;系统利用现有的基础模型作为创建具身智能体的基本构建块。将智能体嵌入这些环境中&#xff0c;有助于模型处理和解释视…

助眠白噪音视频素材哪里找?这些平台帮你快速找到放松素材

在现代社会&#xff0c;信息的轰炸让人们的生活节奏变得越来越快&#xff0c;很多人晚上都在床上辗转反侧&#xff0c;难以入眠。如果你也遇到这样的困扰&#xff0c;想要寻找助眠的白噪音视频素材&#xff0c;那么今天介绍的这些网站将会是你的福音&#xff01;它们提供高质量…

一年四起供应链投毒事件的幕后黑手

前言 2017年&#xff0c;黑客入侵Avast服务器&#xff0c;在CCleaner更新中植入恶意代码&#xff0c;被数百万用户下载。 2017年&#xff0c;M.E.Doc遭黑客攻击&#xff0c;篡改更新植入NotPetya&#xff0c;影响全球公司。 2020年&#xff0c;黑客入侵SolarWinds服务器&…