美文网首页
神经网络算法

神经网络算法

作者: 煮饺子的茶壶 | 来源:发表于2018-11-02 20:19 被阅读0次
    image

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

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

    image

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

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

    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)接近。

    公式:

    权重计算:

    image
        sigmoid函数:
    
    image

    Step 1 前向传播

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

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

    image

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

    image

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

    image

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

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

    image image

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

    Step 2 反向传播

    1.计算总误差

    代价函数(总误差):

    image

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

    image image image

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

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

    image

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

    image

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

    image

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

    image

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

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

    image 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
    

    '''

    相关文章

      网友评论

          本文标题:神经网络算法

          本文链接:https://www.haomeiwen.com/subject/loncxqtx.html