接触神经网络大半年了,但是对于细节不甚清晰,总有种雾里看花的感觉,今天看了一本书,有一种茅塞半顿开状态,写一下我对于神经网络的理解,主要是讲一下代码细节。
训练一个神经网络模型时,我们先定义好如下模型结构,代码都写好了注释。假设是有监督学习,输入训练集与对应的标签,在这里我们定好的神经网络模型就是:
#定义一个神经网络的结构
def init_network():
#声明一个字典
network = {}
这是一个空的神经网络,然后我们定义数据,定义三层神经网络,并且赋予权重偏置等值。应该都能看懂,挺简单的:
#定义一个神经网络的结构
def init_network():
#声明一个字典
network = {}
#神经网络第一层,权重W1
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])
#神经网络第二层,权重W2
network['W2'] = np.array([[0.1, 0.4],[0.2, 0.5], [0.3, 0.6]])
network['b2'] = np.array([0.1, 0.2])
#神经网络第三层,权重W3
network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
network['b3'] = np.array([0.1, 0.2])
return network
定义好了模型之后,我们开始定义模型流程,就是怎么走,数据沿着什么路走,假设输入数据a,a是一个数组或者是一个数字,应该先跟network['W1']相乘,然后加上偏置b1,之后进行激活,变成z1。
之后在进入第二层,跟network['W2']相乘,然后加上偏置b2,之后进行激活,变成z2。
最后进入第三层,跟network['W3']相乘,然后加上偏置b3,之后经过恒等函数,变成z3,也就是y,得到输出值。
下面是代码表示,也很简单:
#前向网络,就是按照神经网络的结构顺序执行
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
最后就是把数据放进去,全部代码如下所示:
# -*- coding: utf-8 -*-
"""
Created on Wed Mar 20 20:10:29 2019
@author: zlee
"""
import numpy as np
#激活函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
#恒等函数,相当于激活函数
def identity_function(x):
return x
#定义一个神经网络的结构
def init_network():
#声明一个字典
network = {}
#神经网络第一层,权重W1
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])
#神经网络第二层,权重W2
network['W2'] = np.array([[0.1, 0.4],[0.2, 0.5], [0.3, 0.6]])
network['b2'] = np.array([0.1, 0.2])
#神经网络第三层,权重W3
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
if __name__ =='__main__':
network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y)
以上结果应该是:[0.31682708 0.69627909]
这是一个定义好的模型,没有任何机器的改动。
那么在这个代码基础上,我们就能了解到,当我们定义一个标签,训练集应该输出的值,比如说对于上面的网络来说,我们输入【1, 0.5】这个数组,作为x,我们期望得到的值是【0.5, 0.5】,而实际值是[0.31682708 0.69627909]。那么解决的途径就只有更改权重参数,这时候,神经网络的功能就得以显现。自动调整调整参数,来达到我们想要的结果。比如我们想要结果变成【0.7, 0.8】,那么网络就会不断循环执行,不停的迭代,调整参数权重来切合我们给出的目标值。
对应到深度学习中,图像矩阵就是输入值,卷积池化操作就是网络结构,不断调整他们的参数,来达到我们想要的结果。
我在这里也有一个大胆的猜想,为什么人们说,机器学习的性能,参数的调整是一门玄学。不同的参数对应不同的不同效果,多个参数达到同一个好的效果,但是参数之间没有关系。也不知道为什么用这个参数效果就这么好。我猜想是因为网络结构大量的参数存在,例如上万个,上千万个,参数的复杂性超过了我们的推理计算能力,所以归咎于一门玄学,其实还是网络结构复杂的相关性造成的。
欢迎关注我的博客,点赞好评~