一、前文回顾
上一节设计了小D的神经网络结构,并且了解了激活函数。但是小D到底是死是活?我也不知道,于是我决定召唤两道闪电,给小D点刺激,看看它有没有反应。
※这节充满了代码以及线性代数,枯燥乏味到我都不想写。
二、实现小D
1.信号的传输
为了容易理解接下来的内容,先规定一下标记符号。我们在第一节就提到过权重,来看下面的神经网络图。我们把权重参数和偏置项都标上。
如图所示,神经元x2传向神经元s11的权重标记为w12(第一个1代表下一层第1个神经元,后面的1代表前一层第2个神经元),同理x2→s13的权重标记为w32,约定好符号标记以后,我们看计算s11:
如果用以下↓行列式分别代替各个变量以及参数的话。
那么这个公式就可以简化为
A=W*X+B
这样子python只需要一行代码就可以实现。
A1=np.dot(X,W1)+B1
我们再追加激活函数:
Z1=sigmoid(A1)
OK,第一层用python就实现了。同理第二层也可以实现。
A2=np.dot(Z1,W2)+B2
Z2=sigmoid(A2)
第三层
A3=np.dot(Z2,W3)+B3
但是到这里注意,最后的输出层和中间层不一样,因为在输出层并没有权重,所以不会是A=W*X+B的形式,而是用到我们接下来要讲到的softmax函数。
2.Softmax函数是什么
这货就长这样子,看起来很复杂很高大上的样子。先来解释下各种符号:n代表输出神经元的个数,k代表第k个输出神经元。(n=10,k=5)意思就是10个输出神经元里面第5个神经元的输出。
用python来实现
def softmax(x):
x = x - np.max(x) # 对应over flow
return np.exp(x) / np.sum(np.exp(x))
3.为什么要用Softmax函数
我们来看一个例子,假如小D的输出有三个神经元,分别为【0.3,2.9,4.0】,那么通过Softmax函数计算后就变为【0.01821127,0.24519181,0.73659691】。你会发现经过Softmax函数计算以后,它们的和会约等于1。这便是Softmax函数的最大特征。通过这个特征我们就可以理解为,经过Softmax函数计算后,输出的是每个类别的概率。比如刚才给出的三个输出的概率分别是1.8%,24.5%,73.6%。这有什么用处呢?再举个例子来理解下。
你问小D今天中午吃什么,可选项有三个A:凉皮,B:肉夹馍,C:绝食。这时候相当于小D的输出神经元有三个,假如输出分别是【A:0.3,B:2.9,C:4.0】,然后经过Softmax函数计算,绝食的概率最大(73.6%),那么小D就会告诉你今天要绝食。
※Softmax函数计算省略
4.Python实现小D
import numpy as np
from common.functions import sigmoid, softmax
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=w1*x+b1
a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1) # 对第一层的输出进行激活
# 第二层神经元计算 a2=w2*z1+b2
a2 = np.dot(z1, W2) + b2
z2 = sigmoid(a2) # 对第二层的输出进行激活
# 第三层神经元计算 a3=w3*z2+b3
a3 = np.dot(z2, W3) + b3
# softmax函数求概率
y = softmax(a3)
return y
三、雷劈小D
# 初始化神经网络小D
network = init_network()
# 呼叫两道闪电1.0,0.5
x = np.array([1.0, 0.5])
# 雷劈小D
y = forward(network, x)
# 查看小D啥反应
print("小D被雷劈了以后的反应:", y)
查看输出:
-----小D被雷劈了以后的反应:[0.40625907 0.59374093]-----
看不懂没关系,用自然语言就解释就是,召唤两道闪电(1.0和0.5)劈向小D,然后小D输出了两个数字:0.40625907和0.59374093。这俩数字啥意思?我猜是对我口吐芬芳。。。
不管怎么样证明了小D是活的。
四、总结
既然知道小D是活的,那么怎样才能见识到它的牛B之处呢?
下节内容:小D识数字。
Comentarios