神经网络算法

神经网络算法_第1张图片
image

这是典型的三层神经网络的基本构成,Layer L1是输入层,Layer L2是隐含层,Layer L3是隐输出,我们现在手里有一堆数据{x1,x2,x3,...,xn},输出也是一堆数据{y1,y2,y3,...,yn},现在要他们在隐含层做某种变换,让你把数据灌进去后得到你期望的输出。如果你希望你的输出和原始输入一样,那么就是最常见的自编码模型(Auto-Encoder)。如果你的输出和原始输入不一样,那么就是很常见的人工神经网络了,相当于让原始数据通过一个映射来得到我们想要的输出数据,也就是我们今天要讲的话题。

假设,你有这样一个网络层:

神经网络算法_第2张图片
image

第一层是输入层,包含两个神经元i1,i2,和截距项b1;第二层是隐含层,包含两个神经元h1,h2和截距项b2,第三层是输出o1,o2,每条线上标的wi是层与层之间连接的权重,激活函数我们默认为sigmoid函数。

现在对他们赋上初值,如下图:

神经网络算法_第3张图片
image

其中,输入数据 i1=0.05,i2=0.10;

       输出数据 o1=0.01,o2=0.99;

       初始权重  w1=0.15,w2=0.20,w3=0.25,w4=0.30;

w5=0.40,w6=0.45,w7=0.50,w8=0.55

目标:给出输入数据i1,i2(0.05和0.10),使输出尽可能与原始输出o1,o2(0.01和0.99)接近。

公式:

权重计算:

神经网络算法_第4张图片
image
    sigmoid函数:
神经网络算法_第5张图片
image

Step 1 前向传播

1.输入层---->隐含层:

计算神经元h1的输入加权和:

神经网络算法_第6张图片
image

神经元h1的输出o1:(此处用到激活函数为sigmoid函数):

神经网络算法_第7张图片
image

同理,可计算出神经元h2的输出o2:

image

2.隐含层---->输出层:

计算输出层神经元o1和o2的值:

神经网络算法_第8张图片
image
image

这样前向传播的过程就结束了,我们得到输出值为[0.75136079 , 0.772928465],与实际值[0.01 , 0.99]相差还很远,现在我们对误差进行反向传播,更新权值,重新计算输出。

Step 2 反向传播

1.计算总误差

代价函数(总误差):

神经网络算法_第9张图片
image

但是有两个输出,所以分别计算o1和o2的误差,总误差为两者之和:

image
image
image

2.输出层---->隐含层的权值更新:

以权重参数w5为例,如果我们想知道w5对整体误差产生了多少影响,可以用整体误差对w5求偏导求出:(链式法则)

神经网络算法_第10张图片
image

下面的图可以更直观的看清楚误差是怎样反向传播的:

神经网络算法_第11张图片
image

现在我们来分别计算每个式子的值:

神经网络算法_第12张图片
image

这样我们就计算出整体误差E(total)对w5的偏导值。

神经网络算法_第13张图片
image

3.隐含层---->隐含层的权值更新:

方法其实与上面说的差不多,但是有个地方需要变一下,在上文计算总误差对w5的偏导时,是从out(o1)---->net(o1)---->w5,但是在隐含层之间的权值更新时,是out(h1)---->net(h1)---->w1,而out(h1)会接受E(o1)和E(o2)两个地方传来的误差,所以这个地方两个都要计算。

神经网络算法_第14张图片
image
神经网络算法_第15张图片
image

这样误差反向传播法就完成了,最后我们再把更新的权值重新计算,不停地迭代,在这个例子中第一次迭代之后,总误差E(total)由0.298371109下降至0.291027924。迭代10000次后,总误差为0.000035085,输出为0.015912196,0.984065734,证明效果还是不错的。

代码

'''
import numpy as np

定义双曲函数和他们的导数

def tanh(x):
return np.tanh(x)

def tanh_deriv(x):
return 1.0 - np.tanh(x)**2

def logistic(x):
return 1/(1 + np.exp(-x))

def logistic_derivative(x):
return logistic(x)*(1-logistic(x))

定义NeuralNetwork 神经网络算法

class NeuralNetwork:
#初始化,layes表示的是一个list,eg[10,10,3]表示第一层10个神经元,第二层10个神经元,第三层3个神经元
def init(self, layers, activation='tanh'):
"""
:param layers: A list containing the number of units in each layer.
Should be at least two values
:param activation: The activation function to be used. Can be
"logistic" or "tanh"
"""
if activation == 'logistic':
self.activation = logistic
self.activation_deriv = logistic_derivative
elif activation == 'tanh':
self.activation = tanh
self.activation_deriv = tanh_deriv

    self.weights = []
    #循环从1开始,相当于以第二层为基准,进行权重的初始化
    for i in range(1, len(layers) - 1):
        #对当前神经节点的前驱赋值
        self.weights.append((2*np.random.random((layers[i - 1] + 1, layers[i] + 1))-1)*0.25)
        #对当前神经节点的后继赋值
        self.weights.append((2*np.random.random((layers[i] + 1, layers[i + 1]))-1)*0.25)

#训练函数   ,X矩阵,每行是一个实例 ,y是每个实例对应的结果,learning_rate 学习率, 
# epochs,表示抽样的方法对神经网络进行更新的最大次数
def fit(self, X, y, learning_rate=0.2, epochs=10000):
    X = np.atleast_2d(X) #确定X至少是二维的数据
    temp = np.ones([X.shape[0], X.shape[1]+1]) #初始化矩阵
    temp[:, 0:-1] = X  # adding the bias unit to the input layer
    X = temp
    y = np.array(y) #把list转换成array的形式

    for k in range(epochs):
        #随机选取一行,对神经网络进行更新
        i = np.random.randint(X.shape[0]) 
        a = [X[i]]

        #完成所有正向的更新
        for l in range(len(self.weights)):
            a.append(self.activation(np.dot(a[l], self.weights[l])))
        #
        error = y[i] - a[-1]
        deltas = [error * self.activation_deriv(a[-1])]

        #开始反向计算误差,更新权重
        for l in range(len(a) - 2, 0, -1): # we need to begin at the second to last layer
            deltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_deriv(a[l]))
        deltas.reverse()
        for i in range(len(self.weights)):
            layer = np.atleast_2d(a[i])
            delta = np.atleast_2d(deltas[i])
            self.weights[i] += learning_rate * layer.T.dot(delta)

#预测函数            
def predict(self, x):
    x = np.array(x)
    temp = np.ones(x.shape[0]+1)
    temp[0:-1] = x
    a = temp
    for l in range(0, len(self.weights)):
        a = self.activation(np.dot(a, self.weights[l]))
    return a

'''

你可能感兴趣的:(神经网络算法)