深度学习day02--神经网络(前三节)
神经网络的一个重要性质是它可以自动地从数据中学习到合适的权重参数。

一、从感知机到神经网络
-
神经网络的例子
我们把最左边的一列称为输入层 ,最右边的一列称为输出层 ,中间的一列称为中间层 。中间层有时也称为隐藏层。"隐藏"一词的意思是,隐藏层的神经元(和输入层、输出层不同)肉眼看不见。输入层到输出层依次称为第0层、第1层、第2层。

图中的网络一共由3层神经元构成,但实质上只有2层神经元有权重,因此将其称为"2层网络"。本书将根据实质上拥有权重的层数(输入层、隐藏层、输出层的总数减去 1后的数量)来表示网络的名称。
-
复习感知机
添加权重为b的输入信号1,改写成更加简洁的形式:
-
激活函数的登场
刚才登场的h(x)函数会将输入信号的总和转换为输出信号,这种函数一般称为激活函数(activation function)。激活函数的作用在于决定如何来激活输入信号的总和。
首先,计算加权输入信号和偏置的总和,记为a。然后,式(3.5)用h()函数将a转换为输出y。

二、激活函数
激活函数是连接感知机和神经网络的重要桥梁。
之前的的激活函数以阈值为界,一旦输入超过阈值,就切换输出。这样的函数称为"阶跃函数"。实际上,如果将激活函数从阶跃函数换成其他函数,就可以进入神经网络的世界了。
- sigmoid函数

上一章介绍的感知机和接下来要介绍的神经网络的主要区别就在于这个激活函数。
-
阶跃函数的实现
pythondef step_function(x): if x > 0: return 1 else: return 0

这个实现简单、易于理解,但是参数x只能接受实数(浮点数)。但不允许参数取NumPy数组,如:step_function(np.array([1.0, 2.0]))
,修改如下:
python
def step_function(x):
y = x > 0
return y.astype(int)
用以下例子解释上述代码:
对NumPy数组进行不等号运算后,数组的各个元素都会进行不等号运算,生成一个布尔型数组。这里,数组x中大于0的元素被转换为True,小于等于0的元素被转换为False,从而生成一个新的数组y。用astype()方法转换NumPy数组的类型。
python
import numpy as np
x = np.array([2,-2,100,0.4])
x
y = x > 0
y
y = y.astype(int)
y

-
阶跃函数的图形
pythonimport numpy as np import matplotlib.pyplot as plt def step_function(x): return np.array(x > 0, dtype = int) # np.arange(-5.0, 5.0, 0.1)在−5.0到5.0的范围内,以0.1为单位,生成NumPy数组([-5.0, -4.9,..., 4.9])。 x = np.arange(-5,5,0.1) y = step_function(x) plt.plot(x,y) plt.ylim(-0.1,1.1) plt.show()

-
sigmoid函数的实现
pythondef sigmoid(x): return 1 / (1 + np.exp(-x)) sigmoid(4) sigmoid(np.array([3,10,-2]))

之所以sigmoid函数的实现能支持NumPy数组,秘密就在于NumPy的广播功能

sigmoid函数的图像:
python
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-5,5,0.1)
y = sigmoid(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)
plt.show()

- sigmoid函数和阶跃函数的比较

- 平滑性不同:sigmoid函数是一条平滑的曲线,输出随着输入发生连续性的变化。而阶跃函数以0为界,输出发生急剧性的变化。
- 输出值不同:阶跃函数只能返回0或1,sigmoid函数可以返回0.731...、0.880...等实数
- 相同点:形状相似,两者的结构均是"输入小时,输出接近0(为0);随着输入增大,输出向1靠近(变成1)";输出值都在0和1之间。
-
非线性函数
阶跃函数和sigmoid函数还有其他共同点,就是两者均为非线性函数。线性函数是一条笔直的直线。而非线性函数,顾名思义,指的是不像线性函数那样呈现出一条直线的函数。
为什么不能使用线性函数呢?因为使用线性函数的话,加深神经网络的层数就没有意义了,不管如何加深层数,总是存在与之等效的"无隐藏层的神经网络"。
这里我们考虑把线性函数
h(x) = cx
作为激活函数,把y(x) = h(h(h(x)))
的运算对应3层神经网络,运算后结果为cccx
。但是同样的处理可以由y(x) = ax(a=c^3)
来表示。为了发挥叠加层所带来的优势,激活函数必须使用非线性函数。
-
ReLU函数
在神经网络发展的历史上,sigmoid 函数很早就开始被使用了,而最近则主要使用ReLU(Rectified Linear Unit)函数。
ReLU函数在输入大于0时,直接输出该值;在输入小于等于0时,输出0。
代码:
pythondef relu(x): return np.maximum(0, x) x = np.arange(-10,10,1) y = relu(x) plt.plot(x,y) plt.ylim(-1,10) plt.show()

三、多维数组的运算
-
多维数组
简单地讲,多维数组就是"数字的集合",数字排成一列的集合、排成长方形的集合、排成三维状或者(更加一般化的)N维状的集合都称为多维数组。
一维数组:
pythonimport numpy as np x = np.array([10,2,-1]) print(x) np.ndim(x) # 数组维数 x.shape # 数组形状 结果是个元组 x.shape[0]

二维数组:
python
y = np.array([[1,2,3], [4,57,19]])
np.ndim(y)
y.shape
y.shape[0]

第一个维度对应第0维,第二个维度对应第1维(Python的索引从0开始)。二维数组也称为矩阵(matrix)。数组的横向排列称为行(row),纵向排列称为列(column)。
- 矩阵乘法

矩阵的乘积是通过左边矩阵的行(横向)和右边矩阵的列(纵向)以对应元素的方式相乘后再求和而得到的。
python
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])
A
B
A.shape
B.shape
np.dot(A,B)
# A.dot(B)

np.dot(A, B)和np.dot(B, A)的值可能不一样。矩阵A 的第1维的元素个数(列数)必须和矩阵B的第0维的元素个数(行数)相等。

-
神经网络的内积
这个神经网络省略了偏置和激活函数,只有权重。
pythonX = np.array([1,2]) X.shape W = np.array([[1,3,5],[2,4,6]]) W W.shape Y = np.dot(X,W) Y

通过矩阵的乘积一次性完成计算的技巧在实现的层面非常重要。