二,神经网络

3.1从感知机到神经网络

  • 神经网络的例子

第0层------输入层

第2层------中间层(隐藏层)

第3层------输出层

(以图1为例)

图1 2层神经网络

  • 复习感知机

图2感知机

图3 表示出偏置(偏置的输入信号一直是1)

式1 感知机的数学式

为了简化上式,引入sigmoid,将式1改写成式2

式2 引入新函数h(x),超过0输出1,否则输出0

式3 h(x)

  • 激活函数

节点a:信号的总加权和

节点y:节点a被激活函数h(x)转换成了节点y

(注:"节点"与"神经元"含义相同)

与一般的神经元图相比,图4在神经元内部明确显示出来激活函数的计算过程

补充:鱼书中的**"朴素感知机"** 是单层 网络,指的是激活函数使用了阶跃函数

"多层感知机" 是指神经网络 ,使用sigmoid 函数等平滑的激活函数的多层网络。

图4 激活函数的计算过程

3.2激活函数

  • sigmoid函数

神经网络中用sigmoid函数作为激活函数,进行信号的转换,转换后的信号被传送到下一个神经元。

这也是感知机和神经网络的主要区别(什么区别呢?感知机一般都用阶跃函数?

式4 sigmoid 函数

  • 阶跃函数的实现

NumPy实现阶跃函数

复制代码
import numpy as np
import matplotlib.pyplot as plt

def step_function(x):
    return np.array(x>0,dtype=int) #x>0,如果元素>0,结果为true;np.array将布尔数组转换成整数数组
x=np.arange(-5.0,5.0,0.1)
y=step_function(x) #出现了x and y must have same first dimension的报错,发现时没有写(x)

print("x.shape:", x.shape)     
print("y.shape:", y.shape)  
#绘图
plt.plot(x,y)
plt.ylim(-0.1,1.1)    
plt.show()

图4 阶跃函数图像

  • sigmoid函数的实现

    import numpy as np
    import matplotlib.pyplot as plt

    #sigmoid函数

    x=np.arange(-5.0,5.0,0.1)
    def sigmoid(x):
    return 1/(1+np.exp(-x))

    x=np.arange(-5.0,5.0,0.1)
    y=sigmoid(x)
    plt.plot(x,y)
    plt.ylim(-0.1,1.1)
    plt.show()

图5 sigmoid函数

  • sigmoid函数&阶跃函数的比较

图6 阶跃&sigmoid

阶跃 :感知机中神经元之间流动的是二元信号(0或1)

sigmoid :神经网络中流动的是连续的实数值信号

共同点:输入小时,输出接近0;输入大时,输出靠近1(当输入信号为重要信息时,二者都会输出较大的值。

  • 非线性函数

神经网络的激活函数必须使用非线性函数。

若使用线性函数,则永远存在(等效的)"无中间层的神经网络"

例如,选择线性函数h(x)=ax,那么将h(x)作为激活函数,3层神经网络对应的运算y=h(h(h(x)))可等价为y=a*x(a=c^3),即:无中间层的神经网络

  • ReLU函数

式5 ReLU函数公式

图7 ReLU函数图像


摸鱼看到了一个回答,将上述内容解释得很清楚:

​编辑神经网络为什么可以(理论上)拟合任何函数?701 赞同 · 42 评论回答

3.3 多维数组的运算

  • 3.3.1多维数组

图1 一维数组

复制代码
import numpy as np
A=np.array([1,2,3,4])
print(A)
A.shape

图2 多维数组

复制代码
B=np.array([[1,2],[3,4]])
B.shape
  • 3.3.2矩阵乘法

式1 矩阵(二维数组)乘积公式

2*2 的矩阵A和2*2的矩阵B的乘积计算

复制代码
A=np.array([[1,2],[3,4]])
A.shape
B=np.array([[5,6],[7,8]])
B.shape
np.dot(A,B)

图3 代码运行结果图

3x2的A矩阵和2x3的B矩阵乘积

!A矩阵的列数==B矩阵的行数

复制代码
A=np.array([[1,2,3],[3,4,5]])
A.shape
B=np.array([[5,6],[7,8],[1,3]])
B.shape
np.dot(A,B)

图4 3x2的矩阵和2x3的矩阵乘积代码运行结果

  • 3.3.3神经网络的内积

忽略偏置b和激活函数,只考虑权重w的神经网络

图5 矩阵的乘积进行神经网络的计算

复制代码
x=np.array([1,2])
x.shape
w=np.array([[1,3,5],[2,4,6]])
w.shape
y=np.dot(x,w)
print(y)

图6 代码实现神经网络的计算

3.4 3层神经网络的实现

输入层(第0层):2个神经元

第1个隐藏层(第1层):3个神经元

第2个隐藏层(第2层):2个神经元

输出层(第3层):2个神经元

图1 3层神经网络示意图

  • 3.4.1符号确认

图2 权重的符号表示

  • 3.4.2 各层间信号传递的实现

输入层到第1层的第1个神经元的信号传递

图 3 输入层到第1层的信号传递

图3对应的第1层第1个神经元的计算公式:

式1 第1层第1个神经元的计算公式

使用矩阵的乘法运算,第1层的加权和计算公式为:

式2 第1层的加权和计算公式(使用了矩阵的乘法计算)

用NumPy多维数组来实现以上计算过程

图4 将式2用代码实现并得到结果

引入激活函数sigmoid函数进行处理

图5 在图4的基础上进行了激活,得到上图结果

第1层到第2层的传递

示意图

图6 第1层到第2层的信号传递示意图

代码实现

(疑惑点:为什么权重w2是3x2的矩阵呢?其行数与Z的列数需相等,所以行数是3我可以理解,但是为什么列数是3呢?(这个问题暂时搁置,先容我想想

补充:下面代码中的Z是第1层神经元,所以就相当于输入层到第1层的代码实现中的x

图 7 第1层到第2层的代码实现

第2层到输出层的传递

传递分析图

图8 第2层到输出层的信号传递图

代码实现

输出层的激活函数不是sigmoid函数,可以视为没有激活函数,只是原样输出,只是为了形式上的统一

疑惑:(为什么输出层的激活函数不用sigmoid函数,而是用恒等函数呢

图9 第2层到输出层的代码实现

输出层的激活函数(一般情况下):

回归问题:使用恒等函数

二元分类问题:使用sigmoid函数

多元分类问题:使用softmax函数

(在3.5 输出层的设计中会详细解释)

  • 3.4.3 代码实现小结

代码实现小结略

以上都是输入到输出的传递处理,即前向(forward) ,与之对应的有输出到输入的传递处理,即后向(backward)

3.5 输出层的设计

  • 3.5.1 恒等函数(sigma)和softmax函数

恒等函数:将输入原样输出

图1 恒等函数的转换处理 图示(一根箭头)

softmax函数

图2 softmax函数

softmax计算公式

式1 softmax函数计算公式、

代码实现softmax计算过程

复制代码
import numpy as np
def softmax(a):
    exp_a=np.exp(a)
    sum_exp_a=np.sum(exp_a)
    y=exp_a/sum_exp_a
    return y

图3 计算结果

  • 3.5.2 实现softmax函数的注意事项

softmax函数中有指数运算,容易出现超大值之间的除法运算,以及会出现超大值无法表示的情况,称之为溢出

溢出问题改进:

公式推导:

式2 softmax函数改进公式

理解:上述公式中的C`可以取-max( 𝑎𝑖 ),避免分子分母出现超大值

溢出问题解决示例:

图4 a=[1000,1010,1020]时结果无法显示

引入常数c,避免分子分母出现超大值,解决了溢出问题

图5 溢出问题解决

  • 3.5.3 softmax函数的特征

softmax函数的输出总和为1,因此,softmax函数的输出解释为"概率"

代码解释:

复制代码
#3.5.3 softmax函数的特征
import numpy as np
a=np.array([0.13,2.9,4.0])
def softmax(a):
    exp_a=np.exp(a)
    sum_exp_a=np.sum(exp_a)
    y=exp_a/sum_exp_a
    return y
a=np.array([0.13,2.9,4.0])
print(softmax(a))
out=np.sum(softmax(a))
print(out)

运行结果:

图6 softmax函数输出总和为1的·验证

由于softmax函数是单调递增函数,因此,输入的大小值和输出的大小值保持一致。由于一般情况下,神经网络只把输出值最大的神经元对应的类别作为识别结果,由于使用softmax函数,输出值最大的神经元的位置也不会变。因此,神经网络在进行分类时,输出层的softmax函数可以省略。

  • 3.5.4 输出层的神经元数量

输出层的神经元数量需要根据待解决的问题来决定,对于分类问题,输出层的神经元数量一般设定为类别的数量。

例如手写数字识别的输出层神经元数量是10

3.6 手写数字识别

使用神经网络解决问题与求解机器学习的过程类似,分别是学习+推理

MNIST数据集是由0到9的数字图像构成的,分为训练图像测试图像

学习 :先使用训练图像进行学习

训练 :将学习到的模型来对测试图像进行分类

复制代码
# coding: utf-8
import sys, os
sys.path.append(os.pardir)  #从父目录导入文件的设置
import numpy as np
from dataset.mnist import load_mnist   #!导入MNIST数据集的加载函数
from PIL import Image   #导入图像处理库,用来显示图像


def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))  #将Nnumpy数组转换为PIL
    pil_img.show()

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False, normalize=False)
'''flatten=True   将28x28的二维矩阵转换为784的一维数组,设置为F,即保持原图;
    normalize=False   设置为T,即将像素0-255 缩放到0-1'''

#取了第一张照片
img = x_train[0]
label = t_train[0]
print(label)  # 5

print(img.shape)  # (784,)
img = img.reshape(28, 28)
'''将形状转换为原始图像大小28x28'''
print(img.shape)  # (28, 28)

img_show(img)

图1 代码运行结果

图2 img_show(x_train[0]) --reshape之后的

关于上面代码的思考:

  1. 为什么要flatten (二维→一维)再reshape(一维→二维)呢?

传统神经网络(非卷积网络)只能处理一维

2.normalize=False

此处没有进行归一化(将像素值从0-255除以255,变成0.0~1.0的小数)

归一化:让数据范围一致,加速模型训练

3.reshape理解

reshape只是改变了数组的view,在内存中的线性存储顺序不变,只是按新形状重新划分行列

dsR1讲解​chat.deepseek.com/a/chat/s/61bd12f3-073f-4317-8530-92ee32bedd73


  • 3.6.2 神经网络的推理处理

神经网络神经元剖析:

输入层:784个神经元(28x28)

第1个隐藏层:50个神经元

第2个隐藏层:100个神经元

输出层:10个神经元(对应10个不同的数字)

预处理

对神经网络的输入数据进行某种既定的转换

在这个例子中,对输入图像进行了正规化的预处理(将每个像素值除以255,压缩至0.0~1.0的范围之间)

定义函数

get_data(),init_network(),predict()

复制代码
# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import pickle
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax


def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    return x_test, t_test


def init_network():
    with open("sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)
    return network


def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y


x, t = get_data()
network = init_network()
accuracy_cnt = 0
for i in range(len(x)):
    y = predict(network, x[i])
    p= np.argmax(y) # 获取概率最高的元素的索引
    if p == t[i]:
        accuracy_cnt += 1

print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

输出结果:

图3 93.52%的数据被正确分类

  • 3.6.2 批处理

输出神经网络的各层权重的形状

图4 各层权重的形状

图5 数组形状的变化

将多张图像进行打包(用predict函数打包处理100张图像)

将X的形状改为100x784即可

图6 批处理中数组形状的变化

  • 3.7 小结
  1. 神经网络中的激活函数常用sigmoid或ReLU函数
  2. 使用NumPy多维数组,可以高效实现神经网络
  3. 机器学习可大致分为分类问题,回归问题
  4. 输出层的激活函数,回归问题中常用恒等函数,分类问题中常用softmax函数
  5. 分类问题中,输出层的神经元数量设置为要分类的类别数
  6. 输入数据的集合称为批,通过以批为单位进行推理处理,能够实现高速的运算

注意:离线环境运行neuralnet_mnist.py提示不能下载,可以先将训练数据图片下载后放到书本源码dataset目录中

参考:《深度学习入门:基于python的理论和实现》

参考:鱼书学习第3章------神经网络 - 知乎 (zhihu.com)

相关推荐
数据库安全1 分钟前
首批|美创智能数据安全分类分级平台获CCIA“网络安全新产品”
大数据·人工智能·web安全
Dymc2 分钟前
【目标检测之Ultralytics预测框颜色修改】
人工智能·yolo·目标检测·计算机视觉
HuashuiMu花水木35 分钟前
PyTorch笔记3----------统计学相关函数
人工智能·pytorch·笔记
算家计算44 分钟前
6 亿参数玩转 20 + 语言!OuteTTS-1.0-0.6B本地部署教程,轻量模型也能 hold 住跨语言合成
人工智能·开源
柠檬味拥抱44 分钟前
USB‑C 式的工具联接:MCP 的模块化及通用标准探讨
人工智能
柠檬味拥抱1 小时前
模块化控制协议(MCP)在网络中增强智能体执行效率的研究
人工智能
神经星星1 小时前
AI 论文周报 | Chai-2刷新抗体设计效率,命中率提高100倍;多篇ICML入围论文一键速览
人工智能·深度学习·机器学习
产品经理独孤虾1 小时前
人工智能大模型如何助力产品经理优化商品定价策略
人工智能·大模型·产品经理·电子商务·数字营销·智能营销·价格策略
阿里云大数据AI技术1 小时前
数据 + 模型 驱动 AI Native 应用发展
大数据·数据库·人工智能
大明哥_2 小时前
100 个 Coze 精品案例:Coze 全自动情感治愈视频混剪。用 Coze 工作流帮您节约 99% 的时间,从此告别手动!!
人工智能·agent