系列索引:菜菜的深度学习笔记 | 基于Python的理论与实现
一、3层神经网络的实现
(1)分层设计
import numpy as np
def sigmoid(x): # sigmoid函数之所以支持Numpy数组是因为其广播功能
return 1/(1+np.exp(-x))
'''
输入层到第1层的信号传递
'''
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
Z1 = sigmoid(A1)
print(A1) #[0.3 0.7 1.1]
print(Z1) #[0.57444252 0.66818777 0.75026011]
'''
第1层到第2层的信号传递
'''
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(A2)
'''
第2层到输出层的信号传递
'''
def identity_function(x): #恒等函数作为输出层的激活函数
return x
W3 = np.array([0.1,0.3],[0.2,0.4])
B3 = np.array([0.1,0.2])
A3 = np.dot(Z2,W3)+B3
Y = identity_function(A3)
print(Y)
各层代码基本一致,输出层使用恒等函数
作为激活函数。输出层使用的激活函数要根据求解问题的性质决定,一般回归问题可以使用恒等函数,二元分类问题可以使用sigmoid函数,多元分类问题可以使用softmax函数。
(2)代码小结
import numpy as np
def identity_function(x): # 恒等函数作为输出层的激活函数
return x
def sigmoid(x): # sigmoid函数之所以支持Numpy数组是因为其广播功能
return 1/(1+np.exp(-x))
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 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) #[0.31682708 0.69627909]
这里定义了init_network()函数
和forward()函数
,前者进行权重和偏置的初始化,并保存在字典中,后者封装了将输入信号转换为输出信号的处理过程。这里是前向forward处理,在后面的神经网络训练中还将会有backward后向处理。
二、输出层的设计
机器学习的问题大致可以分为分类问题
和回归问题
。分类问题是数据属于哪一类的问题,比如区分图像中是男性还是女性,而回归问题是根据某个输入预测一个数值的问题。
(1)恒等函数和softmax函数
恒等函数
:按输入原样返回
softmax函数
:
y
k
=
e
x
p
(
a
k
)
∑
i
=
1
n
e
x
p
(
a
i
)
y_k = \frac{exp(a_k)}{\sum_{i=1}^nexp(a_i)}
yk=∑i=1nexp(ai)exp(ak)
exp(x)是表示e^x的指数函数,该公式表示假设输出层共有n个神经元,计算第k个神经元的输出y_k。
输出层的各个神经元都受到所有输入信号的影响。
(2)实现softmax函数的注意事项
softmax函数中要进行指数运算,因此很容易出现超大值,造成溢出
问题。
计算机处理的数其数值必须在4字节或者8字节的有限数据宽度内,可以表示的数值范围是有限的。
import numpy as np
a = np.array([1010, 1000, 990])
print(np.exp(a)/np.sum(np.exp(a)))
# RuntimeWarning: invalid value encountered in true_divide
# [nan nan nan]
c = np.max(a)
print(a-c)
# [ 0 -10 -20]
print(np.exp(a-c)/np.sum(np.exp(a-c)))
# [9.99954600e-01 4.53978686e-05 2.06106005e-09]
通过这个例子不难看出直接将一个很大的数进行指数运算会出现异常。因此这里我们对a数组进行处理,方法是利用分子分母同乘以一个数结果不变,这里我简单表述一下公式:
y
k
=
e
x
p
(
a
k
)
∑
e
x
p
(
a
i
)
=
C
e
x
p
(
a
k
)
C
∑
e
x
p
(
a
i
)
=
e
x
p
(
a
k
+
l
o
g
C
)
∑
e
x
p
(
a
i
+
l
o
g
C
)
=
e
x
p
(
a
k
+
C
′
)
∑
e
x
p
(
a
i
+
C
′
)
y_k=\frac{exp(a_k)}{\sum{exp(a_i)}}=\frac{Cexp(a_k)}{C\sum{exp(a_i)}}=\frac{exp(a_k+logC)}{\sum{exp(a_i+logC)}}=\frac{exp(a_k+C')}{\sum{exp(a_i+C')}}
yk=∑exp(ai)exp(ak)=C∑exp(ai)Cexp(ak)=∑exp(ai+logC)exp(ak+logC)=∑exp(ai+C′)exp(ak+C′)
这里C’可以用任意值,但是为了防止溢出,我们使用输入信号的最大值。
def softmax():
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
softmax函数总是输出0.0-1.0之间的实数,其总和为1(重要的性质),因此我们可以将其输出解释为“概率”。
求解机器学习问题的步骤可以分为“学习”和“推理”两个阶段。首先,在学习阶段进行模型的学习,然后,在推理阶段用学到的模型进行推理(分类)。
基于Python的理论与实现 系列持续更新,欢迎
点赞收藏
+关注
上一篇:菜菜的深度学习笔记 | 基于Python的理论与实现(二)
下一篇:菜菜的深度学习笔记 | 基于Python的理论与实现(四)—>手写数字识别
本人水平有限,文章中不足之处欢迎下方👇评论区批评指正~如果感觉对你有帮助,点个赞👍 支持一下吧 ~
不定期分享 有趣、有料、有营养内容,欢迎 订阅关注 🤝 我的博客 ,期待在这与你相遇 ~