前言:
前面的神经网络初步学习1------感知机,我们大概讲述了神经网络的老祖宗感知机的一些历史和基本感念,本节我们将对神经网络的相关概念进行一个更加深入的了解和认识
一、复习回顾
(1)神经网络的简单例子:
二层神经网络的简单例子
这里我们一般把输入层叫做第零层,中间层叫做第一层,依次类推下去
同时我们的中间层有时也叫做隐藏层,为什么要这样叫呢,我估计我们在研究当中关注的重心放在输入与输出,中间发生了什么,我们并不是很关注,所以我们也不是很清楚中间发生了什么,故叫做隐藏层。
(2)偏置的单独提出
我们在前面的感知机中,我们对以下的感知机可以写成这种形式:


但是在这种表达式当中,我们的偏置b也可以算是一个输入,只是它的权重我们设置为1(或者输入为1,权重为b),故我们这里可以将我们的感知机写成如下模样:

二、激活函数
(1)什么是激活函数:
我们来看看这个公式:

小于等于0输出0;大于1输出1。我们可以把b+w1x1+w2x2 看作一个整体(自变量m),**h(m)**是一个函数,如果m小于等于0则输出0;大于1输出1,即:

此时,我们就把h(m) 称为我们的激活函数,该函数的作用就是将输入信号的总和转换为输出信号
(2)常见的激活函数1------阶跃函数
阶跃函数即我们上面用到的激活函数,在python里面我们可以这样表示出来:
python
def step_function(x):
if x > 0:
return 1
else:
return 0
其图像如下:

阶跃函数以0为界,输出从0切换为1(或者从1切换为0)。 它的值呈阶梯式变化,所以称为阶跃函数。
(3)常见的激活函数2------sigmoid****函数
sigmoid函数的表达式如下:

可以看到是呈现出一个非线性的一个变化,我们可以用python将其写出来:
python
def sigmoid(x):
return 1 / (1 + np.exp(-x)
该函数的图像 如下:

可以看得出两者的区别,sigmoid函数明显更加平滑
(4)常见的激活函数3------ReLU****函数
ReLU函数是最近几年常用的一个激活函数,它的表达形式如下:

肉眼可见的计算简单,它在卷积神经网络中是经常可见的,具体的原因这里不过多解释,
三、python当中的一些数学运算
(1)为什么用numpy
现在你想要打印一个3*3的矩阵,在还没有知道numpy之前,你可能会以列表的形式表现出来,下面做一个示范:
python
import numpy as np
a = [
[1,2,2],
[2,3,2],
[4,2,1]
]
print(a)
如果从numpy的角度去写的话就是下面这样:
python
import numpy as np
b = np.array([[1,2,2],[2,3,2],[4,2,1]])
print(b)
于是乎问题就会出来了,用np.array来构造我们的矩阵有什么好处嘛?
------有的有的,主要有三个方面:
1、内存上,np.array 的构造是连续内存块,而我们手动构造是以指针的形式存储,这样np.array的内存利用更高,速度更快。
2、数学处理上,NumPy 提供大量内置的数学函数,无需手动实现。
3、广播机制,这个在对高维矩阵有很大的用处。
(2)基本信息的查看
比如我给了一个矩阵,现在要知道这个矩阵是什么样的矩阵,我们可以对矩阵进行如下操作:
python
import numpy as np
b = np.array([[1,2,2],[2,3,2],[4,2,1]])
a = np.ndim(b)
print(a)
c = np.shape(b)
print(c)
输出结果如下:
输出结果
np.ndim 是用来检测矩阵的维度(理解一下维度在这里指代什么?),np.shape是检测矩阵的形状大小
(3)矩阵之间的乘法
矩阵之间的乘法我们在线性代数中学过,这里不过多赘述,不了解的可以自行去查阅资料,对于乘法,即矩阵之间的点积,我们通常用np.dot来实现:
python
import numpy as np
a = np.array([[1,1],[1,1],[1,1]])
b = np.array([[1,2],[1,1]])
c = np.dot(a, b)
print(c)
输出结果如下:
矩阵点积结果
用np.array还有一个好处就是它的输出结果可以看到长得很像我们书写矩阵的样子
(4)在神经网络中的运用
矩阵与神经网络的结合可谓是数学非常美妙的一件事情,那到底是怎样结合的呢?我们不妨以三层神经网络来举例:
三层神经网络(未加上偏置项)
我们不妨以第一层为例子,首先我们把w与b加上:
第零层到第一层
我们有如下表达式:
Z与X的表达式
如果我们用矩阵的形式来表示的话,我们可以写成如下形式

最后我们需要让Z通过我们的激活函数, 这里就不表示出来了,假设我们的激活函数是ReLU,那么我们的python 格式就可以写成如下形式(注意:这里没赋值!):
python
X = np.array([X1, X2])
W = np.array([[W1-1, W1-2, W1-3], [W2-1, W2-2, W2-3]])
b = np.array([b1-1, b1-2, b1-3])
Z_1 = np.dot(X, W) + b
Z = ReLU(Z_1)
这就是矩阵的应用,后面的层与层之间的传递均可以写成矩阵相乘加偏置项的形式,在数学上非常方便。
四、输出层的激活函数
对于输出层而言,我们的激活函数主要分为两种:1、恒等函数;2、softmax函数,下面依次来介绍:
(1)恒等函数
恒等函数主要用在回归问题当中,可能有些同学不太理解什么是回归问题(高中有涉及过),鞠躬例子,根据前五年的房价来预测下一个月的房价,那么我们用神经网络的输出层的数据必须与前面推算出来的数据相等(即恒等函数),下面是示意图:
恒等函数示意图
(2)softmax函数
这个输出激活函数就主要用于我们的分类问题,下面是它的表达形式
softmax函数
即:

这个函数不难理解,本质上是做了一个归一化的操作,但是有些聪明的小伙伴就会问了:归一化直接按照下面这种公式写不是更简单嘛(如下),为什么要搞得这么麻烦?
更加简单的归一化操作
关于这个问题,我们放在最后进行讲解哦。
其次,如果我们的输出层的数据过大,那么对于我们的softmax函数的计算是不太友好的,所以在面对量级较大的数据的时候,我们一般进行如下操作:
这里的可以使用任何值,但是为了防止溢出,一般会使用输入信号中的最大值的负值,进行相减过后可以很大程度上减少运算。
(3)关于softmax函数的问题
这一部分主要是解决前面遗留下的问题:归一化直接按照下面这种公式写不是更简单嘛,为什么要搞得这么麻烦?
首先我们要清楚,归一化在分类问题里面一个重要的作用是帮助我们进行概率分析 ,举一个例子:
我们现在有三个输出1,3,6,现在来比较一下两种归一化的差距:
线性归一化:0.1,0.3,0.6
softmax归一化:0.0064, 0.0471, 0.9465
可以看到差距是十分明显的,这样来说,softmax 可以更好地把差距拉大,即放大差异,突出显著值( 的功劳)
其次,softmax 是为主,那么在进行求导处理及其他数学变化来说也更加方便友好
注意:本文参照了《基于Python的理论与实现》(斋藤康毅)此书,大家也可以对比原文进行阅读