欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

机器学习小白修炼之路

程序员文章站 2024-03-14 20:20:41
...

深度学习的基础BP算法

神经元模型

单个神经元就是一个最简单的逻辑回归,只能解决比较简单的classification。
机器学习小白修炼之路
多个神经元可以解决一下较为复杂的分类问题。
机器学习小白修炼之路

前向传播

特征向量x从输入层到最后输出层的过程。
前向传播代码实现(估计是最后次发Matlab代码了,python真香警告!!!):

			......
			z1=theta1*d_x;
            for i=1:5,
                %Matlab构造的向量默认是行向量
                hidden1(i)=sigmoid(z1(i));
            end
            z2=theta2*hidden1';
            for i=1:5,
                hidden2(i)=sigmoid(z2(i));
            end
            z3=theta3*hidden2';
            output=sigmoid(z3);
            ......

上面的d_x向量是列向量。

误差逆传播(BP算法的精华部分)

将误差从输出层返传回紧挨着输入层的隐藏层的过程。返回的过程主要是修改每一层每个连接的权重,达到减少误差的过程。
反向传播代码实现(吴恩达 说的向量化代码也打了注释了,ps:向量化用时少,但是真的不好想)

			......
			%反向传播
            %output层的error(损失函数对Z求偏导)计算方法为直接对Z求偏导,链式法则链到a
            error3=(output-y(num))*(1-output)*output;
            %error2=error3*theta3.*hidden2(i).*(1-hidden2(i));
            for i=1:5,
                error2(i)=error3*theta3(:,i)*hidden2(i)*(1-hidden2(i));
            end
            %error1=error2*theta2.*hidden1(i).*(1-hidden1(i));
            for i=1:5,
                error1(i)=error2*theta2(:,i)*hidden1(i)*(1-hidden1(i));
            end
            %更新权重
            %theta1=theta1-interval*error1'*d_x';
            for i=1:5,
                for j=1:3,
                    theta1(i,j)=theta1(i,j)+interval*error1(i)*x(j);
                end
            end
            %theta2=theta2-interval*error2'*hidden1;
            for i=1:5,
                for j=1:5,
                    theta2(i,j)=theta2(i,j)+interval*error2(i)*hidden1(j);
                end
            end
            %theta3=theta3-interval*error3'*hidden2;
            for i=1:5,
                theta3(i)=theta3(i)+interval*error3*hidden2(i);
            end
            ......

机器学习小白修炼之路

诀窍:(大前提:w1的dimension=[inputsize,hiddensize]…)
从输出层计算error,公式记作:下一层error点乘这一层权重的转置再乘上这层输出函数的导数。(ps:sigmoid函数在a的导数等于sigmoid(a)*(1-sigmoid(a)))
partical J除以partical w(某一层)等于上一层输出的转置点乘这层的error。

完整代码

Matlab

function [ ] = build_bp(  )
    INTERVAL=0.8;
    x=load('D:\machineLearning\逻辑回归\ex4Data\ex4x.dat');
    y=load('D:\machineLearning\逻辑回归\ex4Data\ex4y.dat');
    m=length(x(:,1));
    c_p=find(y==1);
    s_p=find(y==0);
    x(:,1)=(x(:,1)-mean(x(:,1)))./std(x(:,1))
    x(:,2)=(x(:,2)-mean(x(:,2)))./std(x(:,2))
    %plot(x(c_p,1),x(c_p,2),'ro');
    %hold on;
    %plot(x(s_p,1),x(s_p,2),'bs');
    x=[ones(m,1) x];

    %搭建三层神经网络,需要三个权重矩阵
    theta1=rand(5,3)*2*INTERVAL-INTERVAL;
    theta2=rand(5,5)*2*INTERVAL-INTERVAL;
    theta3=rand(1,5)*2*INTERVAL-INTERVAL;
    interval=0.4;
   
    iter=100;
    c=1;
    loss=0;
    while c<=iter,
        t=0;
        for num=1:80,
            transpose_x=x';
            d_x=transpose_x(:,num);
            d_y=y;
            %前向传播
            z1=theta1*d_x;
            for i=1:5,
                %Matlab构造的向量默认是行向量
                hidden1(i)=sigmoid(z1(i));
            end
            z2=theta2*hidden1';
            for i=1:5,
                hidden2(i)=sigmoid(z2(i));
            end
            z3=theta3*hidden2';
            output=sigmoid(z3);
     
            %反向传播
            %output层的error(损失函数对Z求偏导)计算方法为直接对Z求偏导,链式法则链到a
            error3=(output-y(num))*(1-output)*output;
            %error2=error3*theta3.*hidden2(i).*(1-hidden2(i));
            for i=1:5,
                error2(i)=error3*theta3(:,i)*hidden2(i)*(1-hidden2(i));
            end
            %error1=error2*theta2.*hidden1(i).*(1-hidden1(i));
            for i=1:5,
                error1(i)=error2*theta2(:,i)*hidden1(i)*(1-hidden1(i));
            end
            %更新权重
            %theta1=theta1-interval*error1'*d_x';
            for i=1:5,
                for j=1:3,
                    theta1(i,j)=theta1(i,j)+interval*error1(i)*x(j);
                end
            end
            %theta2=theta2-interval*error2'*hidden1;
            for i=1:5,
                for j=1:5,
                    theta2(i,j)=theta2(i,j)+interval*error2(i)*hidden1(j);
                end
            end
            %theta3=theta3-interval*error3'*hidden2;
            for i=1:5,
                theta3(i)=theta3(i)+interval*error3*hidden2(i);
            end
            e=(output-y(num))^2/2;  %计算误差向量  (计算输出-目标输出)  
            t=t+e;
        end
        loss(c)=t;
        c=c+1;
    end
        plot(1:iter,loss);
end


图像

机器学习小白修炼之路

python

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

class Neural_Network(object):
    def __init__(self):
        self.inputSize=2
        self.outputSize=1
        self.hiddenSize = 3
        self.alpha=0.2
        self.iterations=100
        self.count_error=[]
        self.w1=np.random.randn(self.inputSize,self.hiddenSize)
        self.w2=np.random.randn(self.hiddenSize,self.hiddenSize)
        self.w3=np.random.randn(self.hiddenSize, self.outputSize)

    def sigmoid(self,s):
        return 1/(1+np.exp(-s))

    def forward(self,x,y):
        self.z1=np.dot(x,self.w1)
        self.hidden1=self.sigmoid(self.z1)
        self.z2=np.dot(self.hidden1,self.w2)
        self.hidden2=self.sigmoid(self.z2)
        self.z3=np.dot(self.hidden2,self.w3)
        self.output=self.sigmoid(self.z3)
        self.count_error.append(np.mean(np.square(y-self.output)))
        return self.output

    def backward(self,x,y,output):
        #error2表示损失值对Z求偏导数。链式法则:先对a求偏导,再乘以a对Z求偏导
        self.error3=(output-y)*(1-output)*output
        #链式法则,链接到下一层Z求解
        self.error2=self.error3.dot(self.w3.T).dot(np.dot((1-self.hidden2),self.hidden2))
        self.error1=self.error2.dot(self.w2.T).dot(np.dot((1-self.hidden1),self.hidden1))

        self.w1-=self.alpha*x.T.dot(self.error1)
        self.w2-=self.alpha*self.hidden1.T.dot(self.error2)
        self.w3-=self.alpha*self.hidden2.T.dot(self.error3)

    def train(self,x,y):
        for i in range(self.iterations):
            output=self.forward(x,y)
            self.backward(x,y,output)

if __name__=="__main__":
    x=np.array(([0.3,1],[0.2,0.5],[0.4,0.8]),dtype=float)
    y=np.array(([0.9],[0.8],[0.7]),dtype=float)
    #plt.scatter(x[:,0],x[:,1])
    #plt.show()
    NN=Neural_Network()
    NN.train(x,y)

    plt.plot(range(1,NN.iterations+1),NN.count_error)
    plt.title('error')
    plt.xlabel('iteration')
    plt.ylabel('error')
    plt.show()




图像

机器学习小白修炼之路

分析总结

手搓BP反向传播算法,其实Matlab的代码,写好晾了几乎有一礼拜了,之前一直觉得loss值有问题就一直在思考着:loss值振荡是什么鬼东西?其实说到底一个Neuron也就是简单的逻辑回归,逻辑回归的loss函数说到底是个交叉熵,如下图(参考自李宏毅老师的深度学习课程讲解):
机器学习小白修炼之路

如果你记录的loss值不是一轮训练完之后的平均值,而是整个数据集中的单个样本计算出来的loss值,那么有振荡现象是很正常的。当你的记录loss值是一轮训练完之后的平均值的时候,那loss函数的图像应该就会是正常缓慢下降的了。
现在深度学习框架中封装好的损失函数,一般也都是在一轮训练结束后取的平均误差。比如说均方误差,一听名字就知道了。
而且python喂数据的形式和matlab也不一样,二维张量是所有组一起喂到网络里面迭代的。如果在matlab的话会是一次进一组数去迭代,再下一轮进下一组数。
这么想也就明白了奇怪的图像了。