神经网络基础学习(2)


title: 神经网络基础学习(2)

神经网络基础学习(2)

在本节中我们将学会最简单的三层神经网络搭建

一、矩阵乘法

​ 在了解神经网络中数据传输方法之前,熟练掌握矩阵乘法的规则是必不可少的(学过线性代数的请自行忽略这一点),下面是两个简单的2*2矩阵间的乘法

截屏2022-10-08 下午6.59.24

​ 矩阵的乘积是通过左边矩阵的行(横向)和右边矩阵的列(纵向)以对应元素的方式相乘而得到的。而且运算的结果保存为新的多维数组的元素,下图详细的表现了矩阵乘法的规则

截屏2022-10-08 下午7.13.34

​ 这个运算在Python中可以用如下代码实现

>>>A = np.array([[1, 2], [3, 4]])
>>>A.shape
(2, 2)
>>>B = np.array([[5, 6], [7, 8]])
>>>B.shape
(2, 2)
>>>np.dot(A, B)
array([[19, 22],
       [43, 50]])

​ 在这里AB都是2*2的矩阵,它们的乘积可以通过NumPy的np.dot()函数计算(严谨地来说是点积)。这里要注意的是np.dot(A, B)与np.dot(B, A)的值可能不一样,在矩阵的乘积运算中,矩阵的前后顺序不同会造成乘积结果的不同

二、搭建简单的三层神经网络

1.神经网络大体结构截屏2022-10-08 下午7.34.26

​ 上图就是一个简单的3层神经网络结构图。其中神经网络被分成三个层次:输入层隐藏层输出层,我们一般把出入层称为第0层。在代码实现方面,我们可以灵活地运用NumPy多维数组进行组建,用很少的代码完成神经网络的前向处理

2.各层间的信号传递实现

​ 现在看一下从输出层第一个神经元x1传导到第1层第一层a1的过程

截屏2022-10-08 下午7.45.48

​ 注意,我们在第一层加了一个数值为1的神经元,目的是为了把各个神经元计算所要加的偏置都提取出来,单独把各层权重设置为数值1的权重,这一步操作可以简化我们对神经网络传导函数的书写

​ 现在我们可以把a1的加权信号和写出来

截屏2022-10-08 下午7.50.45

​ 这是我们第一个神经元的信号加权值,但我们神经网络的传输是以层为单位的,也就是说同一层的神经元的计算是同步进行的,然后这一层所有神经元的信号加权和再往下一层传导,所以我们不可能把每一个神经元的计算公式都写出来,不然就太冗余了,所以我们可以写成下面矩阵乘法的形式

截屏2022-10-08 下午8.00.45

​ 其中,A表示要传递到下一层的信号加权和,X为上一层输入值,W为权重,B为偏置,A、B、X、W如下所示

截屏2022-10-08 下午8.06.10

​ 下面我们用NumPy多维数组来实现上面的计算公式

X = np.array([1.0, 0.5])
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
B1 = np.array([0.1, 0.2, 0.3])

A1 = np.dot(X, W1) + B1

​ 数组中的数值先随意设置,通过这一步函数我们成功的把这一层的信号加权和给算出来了,但这只并没有全部完成,我们上一章还讲到了激活函数这一概念,所以我们还需要激活函数sigmoid来激活数值再传导到下一层

Z1 = sigmoid(A1)

​ 如果看到这里你还能保持大脑清醒并条理清晰,恭喜你,你已经会了神经网络的传输原理了,再往后的损失函数、梯度、正反向反馈等函数都是在此基础上的衍生

IMG_1056

​ 好的,我们按照上面第一层的操作,我们同理可以写出第二层和输出层的传递代码

W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
B2 = np.array([0.1, 0.2])

A2 = np.dot(X, W1) + B1
Z2 = sigmoid(A2)

​ 上面的代码与上面如出一辙,只是在数组的维度上有所变化,我们在神经网络传导的时候一定要搞清楚每一层数组的维数,不然很容易报错

​ 在最后一层输出层的信号传导时,最后的激活函数会有所不同,我们会根据最后数据处理的要求选择不同的函数,我们这里就选择直接返回函数值,后面我们会提到不同的输出层的激活函数

def return_function(x):
  return x

A3 = np.dot(Z2, W3) + B3
Y = return_function(A3)			# Y为最后我们的输出值

三、总结代码

​ 下面我们把上面所有的代码全部定义成函数来实现快速调用的功能

# 搭建3层神经网络(以sigmoid函数为激活函数)
import numpy as np


# 初始化各层的权重和偏置

def init_network():
    network = {}
    network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    network["b1"] = np.array([0.1, 0.2, 0.3])
    network["W2"] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
    network["b2"] = np.array([0.1, 0.2])
    network["W3"] = np.array([[0.1, 0.3], [0.2, 0.4]])
    network["b3"] = np.array([0.1, 0.2])

    return network


# 隐藏层激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


# 最后一层激活函数
def identity_function(x):
    return x


# 输入到输出的传递函数
def forward(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 = identity_function(a3)

    return y


network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y)

​ 在上面的代码里,我们首先定义了init_function(),在这个函数中我们创建了一个network的字典来储存各个权重和偏置,起到初始化的作用。然后我们还定义了forward()函数,存入了我们上面讲到的传输计算函数,起到了信息向前传输的作用。

​ 到此为止我们已经成功搭建了一个简单的三层神经网络,你懂了吗?

截屏2022-10-08 下午9.06.06

四、输出层激活函数设计

​ 我们一般用神经网络来解决分类问题回归问题,现在我们来介绍分类问题的激活函数——softmax函数。

​ 分类函数中使用softmax函数可以写成下面的式子

截屏2022-10-08 下午9.18.16

​ softmax函数中的分子时输入信号a的指数函数,分母是所有信号的指数函数的和,用Python我们可以写成下面这个样子

def softmax(a):
  exp_a = np.exp(a)
  sum_exp_a = np.sum(exp_a)
  y = exp_a / sum_exp_a
  
  return y

​ 代码跑出来我们显而易见softmax函数得到的结果都是0.2478……或者0.7865……等小数(0.0到1.0的小数),实际上softmax输出的所有值全部加起来为1,所以我们可以把softmax函数的输出值当作该数据在数据集中出现的概率,所以我们可以把softmax函数当作分类函数的激活函数

IMG_1030

​ 但我们在这里要提到softmax函数有一个非常重要的注意点

​ softmax中用到了指数函数,很容易造成数值过大而溢出的现象,所以我们可以对上面的式子进行一点点修改(证明过程省略)

截屏2022-10-08 下午9.31.54

​ 所以我们也对代码进行小小的修改

def softmax(a):
  c = np.max(a)
  exp_a = np.exp(a - c)
  sum_exp_a = np.sum(exp_a)
  y = exp_a / sum_exp_a
  
  return y

​ 上面我们通过减去输入信号中的最大值(上面的c),这样我们就可以很好的避免溢出的风险了。这里提一句,sigmoid函数也会有同样的风险,解决方法也如出一辙,就不过多赘述了

OK,现在你已经学会了如何搭建三层神经网络,下面我们会通过“手写数字识别”的项目来具体学习神经网络中的学习

大好きだよ

编辑者:Ice Man

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ice Programmer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值