本文为学习笔记整理

参考书籍:《深度学习入门 : 基于Python的理论与实现 》/ (日) 斋藤康毅著 ; 陆宇杰译. – 北京 : 人民邮电出版社, 2018.7(2019.5重印)、

文章中带编号的图片(如:图3-14)均来自书籍内容。

神经网络的内积

使用NumPy矩阵实现神经网络需要注意输入值 x x x和权重 w w w的维数需要对应,其中:

x x x:存储输入信号的一维数组(向量)

w w w:存储权重参数的多维数组(矩阵)
深度学习基础--神经网络(2)-LMLPHP

3层神经网络的实现

深度学习基础--神经网络(2)-LMLPHP

输入到输出的前向传播:

深度学习基础--神经网络(2)-LMLPHP

联系激活函数的内容:

激活函数:
a = b + w 1 x 1 + w 2 x 2 (3.4) a = b + w_1x_1 + w_2x_2 \tag{3.4} a=b+w1x1+w2x2(3.4)

y = h ( a ) (3.5) y=h(a) \tag{3.5} y=h(a)(3.5)

第一层的神经元 a 1 ( 1 ) a_1^{(1)} a1(1)
a 1 ( 1 ) = w 11 ( 1 ) x 1 + w 12 ( 1 ) x 2 + b 1 ( 1 ) (3.8) a_1^{(1)}=w_{11}^{(1)}x_1+w_{12}^{(1)}x_2+b_1^{(1)} \tag{3.8} a1(1)=w11(1)x1+w12(1)x2+b1(1)(3.8)
使用矩阵的乘法运算,将第一层的加权和表示成:
A ( 1 ) = X W ( 1 ) + B ( 1 ) (3.9) A^{(1)}=XW^{(1)}+B^{(1)} \tag{3.9} A(1)=XW(1)+B(1)(3.9)
A ( 1 ) = ( a 1 ( 1 ) , a 2 ( 1 ) , a 3 ( 1 ) ) A^{(1)}=(a_1^{(1)},a_2^{(1)},a_3^{(1)}) A(1)=(a1(1),a2(1),a3(1))

X = ( x 1 , x 2 ) X=(x_1,x_2) X=(x1,x2)

B ( 1 ) = ( b 1 ( 1 ) , b 2 ( 1 ) , b 3 ( 1 ) ) B^{(1)}=(b_1^{(1)},b_2^{(1)},b_3^{(1)}) B(1)=(b1(1),b2(1),b3(1))

W ( 1 ) = [ w 11 ( 1 ) w 21 ( 1 ) w 31 ( 1 ) w 12 ( 1 ) w 22 ( 1 ) w 32 ( 1 ) ] W^{(1)} = \left[ {\begin{array}{cc} w_{11}^{(1)} & w_{21}^{(1)} & w_{31}^{(1)} \\ w_{12}^{(1)} & w_{22}^{(1)} & w_{32}^{(1)} \\ \end{array} } \right] W(1)=[w11(1)w12(1)w21(1)w22(1)w31(1)w32(1)]
其实就是线型代数中方程组的矩阵表示
深度学习基础--神经网络(2)-LMLPHP

代码实现3层神经网络:

import numpy as np


def sigmoid_function(x):
    """sigmoid激活函数"""
    return 1 / (1 + np.exp(-x))


def identity_function(x):
    """恒等函数"""
    return x


# 输入信号,x1 = 1.0, x2 = 0.5
X = np.array([1.0, 0.5])

"""第一层的前向传播"""
# 第一层的权重参数W1
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
# 第一层的偏置参数B1
B1 = np.array([0.1, 0.2, 0.3])
# 计算a
A1 = np.dot(X, W1) + B1
# 激活函数
Z1 = sigmoid_function(A1)

"""第二层的前向传播"""
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(Z1, W2) + B2
Z2 = sigmoid_function(A2)

"""第三层的前向传播,输出层"""
W3 = np.array([[0.1, 0.3], [0.2, 0.4]])
B3 = np.array([0.1, 0.2])
A3 = np.dot(Z2, W3) + B3
Z3 = identity_function(A3)  # 输出层所用的激活函数,此处为恒等函数

print(Z3)  # [0.31682708 0.69627909]

神经网络比较标准的代码格式,由书中作者提供:

import numpy as np


def sigmoid_function(x):
    """sigmoid激活函数"""
    return 1 / (1 + np.exp(-x))


def identity_function(x):
    """恒等函数"""
    return x


def init_network():
    """进行权重和偏置的初始化"""
    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 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_function(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid_function(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)  # [0.31682708 0.69627909]

输出层的设计

机器学习的问题大致分为两类:

  1. 分类问题,数据属于哪一个类别的问题,一般使用softmax函数
  2. 回归问题,根据某个输入预测一个连续的数值的问题,一般使用恒等函数

恒等函数和softmax函数

恒等函数:输入信号会原封不动地被输出,主要用于回归问题

softmax函数:
y k = e x p ( a k ) ∑ i = 1 n e x p ( a i ) (3.10) y_k=\frac{exp(a_k)}{\sum_{i=1}^nexp(a_i)} \tag{3.10} yk=i=1nexp(ai)exp(ak)(3.10)
e x p ( x ) exp(x) exp(x)= e x e^x ex

y k y_k yk: 第k个神经元的输出 y k y_k yk

softmax函数的分子是输入信号 a k a_k ak的指数函数,分母是所有输入信号的指数函数的和。

深度学习基础--神经网络(2)-LMLPHP

softmax函数的代码实现:

import numpy as np


def softmax_function(x):
    return np.exp(x) / np.sum(np.exp(x))


a = np.array([0.3, 2.9, 4.0])
y = softmax_function(a)
print(y)  # [0.01821127 0.24519181 0.73659691]

softmax函数的实现中要进行指数函数的运算,但是指数函数的值很容易变得非常大,要注意溢出问题

改进函数:

深度学习基础--神经网络(2)-LMLPHP

改进函数代码实现:

import numpy as np


def softmax(x):
    """防止溢出的方法"""
    c = np.max(x)
    return np.exp(x - c) / np.sum(np.exp(x - c))


a = np.array([1010, 1000, 990])
y = softmax(a)
print(y)  # [9.99954600e-01 4.53978686e-05 2.06106005e-09]
print(np.sum(y))  # 1.0

softmax函数的性质:

  1. softmax函数的输出是0.0到1.0之间的实数
  2. softmax函数的输出值总和为1
  3. 使用softmax函数后,各个元素之间的大小关系不会改变

因为性质2,所以可以将函数的输出解释为“概率”

import numpy as np


def softmax(x):
    c = np.max(x)
    return np.exp(x - c) / np.sum(np.exp(x - c))


a = np.array([0.3, 2.9, 4.0])
y = softmax(a)
print(y)  # [0.01821127 0.24519181 0.73659691]
print(np.sum(y))  # 1.0

y中的值视为概率,可以看到最后一个元素的“概率”最高,所以答案就是第三个类别

一般神经网络只把输出值最大的神经元所对应的类别作为识别结果

输出层的神经元数量

对于分类问题,输出层的神经元数量一般设定为类别的数量

比如手写数字识别,有0到9一共十个数字,所以输出层的神经元数量设定为10.

深度学习基础--神经网络(2)-LMLPHP

11-16 10:35