接触神经网络大半年了,但是对于细节不甚清晰,总有种雾里看花的感觉,今天看了一本书,有一种茅塞半顿开状态,写一下我对于神经网络的理解,主要是讲一下代码细节。

 

训练一个神经网络模型时,我们先定义好如下模型结构,代码都写好了注释。假设是有监督学习,输入训练集与对应的标签,在这里我们定好的神经网络模型就是:

#定义一个神经网络的结构
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】,那么网络就会不断循环执行,不停的迭代,调整参数权重来切合我们给出的目标值。

对应到深度学习中,图像矩阵就是输入值,卷积池化操作就是网络结构,不断调整他们的参数,来达到我们想要的结果。

 

我在这里也有一个大胆的猜想,为什么人们说,机器学习的性能,参数的调整是一门玄学。不同的参数对应不同的不同效果,多个参数达到同一个好的效果,但是参数之间没有关系。也不知道为什么用这个参数效果就这么好。我猜想是因为网络结构大量的参数存在,例如上万个,上千万个,参数的复杂性超过了我们的推理计算能力,所以归咎于一门玄学,其实还是网络结构复杂的相关性造成的。

 

欢迎关注我的博客,点赞好评~