• BP的matlab实现


    %2015.04.26 Kang Yongxin ----v 2.0
    %完成作业中BP算法,采用批量方式更新权重
    %%
    %输入数据格式
    %x 矩阵 : 样本个数*特征维度 
    %y 矩阵 :样本个数*类别个数(用01000形式表示)
    close all;
    clear all;
    clc ;
    load data.mat;%
    x_test=x(1:3:30,:);%从原始数据中留出一部分 作为测试样本
    y_test=y(1:3:30,:);
    x_train=[x(2:3:30,:);x(3:3:30,:)];%x(1:2:30,:);%[x(11:25,:);x(26:30,:);x(1:10,:)];
    y_train=[y(2:3:30,:);y(3:3:30,:)];%%[y(11:25,:);y(26:30,:);y(1:10,:)];
    %%
    %定义变量名称,初始化网络
    d=size(x_train,2);%特征维度,也是输入层节点个数
    num_trains=size(x_train,1);%训练样本个数
    n_class=size(y_train,2);%样本类别数
    node_layer=[d 4 n_class];%每层的节点个数 %[d 3 5 n_class];%构建更多层的网络
    num_layer=size(node_layer,2)-1;%网络层数
    for i=1:1:num_layer-1
        f_name{i}='sigmoid';%对应每层的激活函数
    end
    f_name{num_layer}='tanh';%'sigmoid';%最后一层的激活函数
    eta=0.08;%学习率
    theta=10e-4;%终止条件
    W=cell(num_layer,1);%初始化权重矩阵,都设曾1,
    for i=1:1:num_layer
        W{i}=rand(node_layer(i),node_layer(i+1));
    end
    W_init=W;
    %开始循环
    item=1;
    while item>0 && item<1500
      %%
      %初始化权值增量
       for layer=1:1:num_layer
            delta_sum{layer}=zeros(size(W{layer})) ;
       end
       %%
        for k=1:1:num_trains
            %对于每个样本的循环
           %%%%%%%%%%%%%%%%%%%
            %前向计算
            x_in=x_train(k,:);
            for layer=1:1:num_layer
                %对于每一层进行前向计算,并且保存输出值y_out
                y_out{layer}=forward(x_in,W{layer},f_name{layer});%批量更新时候W要跟随外层循环
                x_in=y_out{layer};
            end
            %%%%%%%%%%%%%%%
            %%%%%%%%%%%%%% 
            %反向传播,最后一层要单算,因为只有一个输出 
            delta_out{layer}=y_train(k,:)-y_out{layer};%输出与真值的差
            J(k)=0.5*sum(delta_out{layer}.^2);%均方误
            delta_error{layer}=delta_out{layer}.*d_function(y_out{layer},f_name{num_layer});%从指向节点收集到的误差
            delta_w{layer}=eta*(y_out{layer-1})'*delta_error{layer};%本层的权重变化量
            while layer>1
               %反向传播误差,保存delta_w
               layer=layer-1;
               delta_error{layer}=delta_error{layer+1}*(W{layer+1})'.*d_function(y_out{layer},f_name{layer});%从指向节点收集到的误差并使用之前的权重进行加权
               if layer~=1
                   %如果没到第一层,就用layer-1层的输出作为输入
                   delta_w{layer}=eta*(y_out{layer-1})'*delta_error{layer};%本层的权重变化量
               else
                   %如果是第一层就用本次训练的x作为输入   
                   delta_w{layer}=eta*(x_train(k,:))'*delta_error{layer};%本层的权重变化量
               end
            end  
           %%%%%%%%%%%%%%%
           %%%%%%%%%%%%%%%%%
           %批量更新,要对所有样的贡献进行加和
           for layer=1:1:num_layer
                delta_sum{layer}=delta_sum{layer}+delta_w{layer} ;
           end
        end%k个样本对权重 变化量的贡献计算完毕
        %%
        
        figure(1);
        JW(item)=sum(J);
        if item>10
            Delta_JW=abs(JW(item)-JW(item-1));
            if Delta_JW<theta
                 break;%循环终止条件
            end
        end
        plot(item,JW(item),'.')
        hold on;
        item=item+1;
        
      %更新权重
        for layer=1:1:num_layer
            %对于每一层更新权重,这个更新放的位置决定是进行批量更新还是每次更新
           W{layer}=W{layer}+delta_sum{layer};%批量更新
        end
    end
    %%
    %计算准确率
    x_in=x_test;
    for layer=1:1:num_layer
        %对于每一层进行前向计算,并且保存输出值y_out
        y_out{layer}=forward(x_in,W{layer},f_name{layer});%批量更新时候W要跟随外层循环
        x_in=y_out{layer};
    end
    [C,I]=max(y_out{layer},[],2);        
    [C,I_true]=max(y_test,[],2);
    Trues=find((I-I_true)==0);
    Precision=size(Trues,1)/size(y_test,1)
    
    function [ y ] = forward( x,w,f_name )
    %FORWARD 前向计算得到输出值
    %   输入 x:输入向量1*m
    %        w:权重矩阵m*n
    %        f_name:函数名称(暂时支持'sigmoid''tanh')
    %   输出 y:输出向量1*n 公式为  y=f(x*w)
    if strcmp(f_name,'sigmoid')
        y=sigmoid(x*w);
    else if strcmp(f_name,'tanh')
            y=tanh(x*w);%matlab 自带
        else
           disp('wrong function name ');
        end
    end
    end
    function [d_f ] = d_function( y,f_name )
    %D_FOUNCTION 对相关函数进行求导数
    %   输入是该层的输出值y 
    if strcmp(f_name,'sigmoid')
        d_f=y.*(1-y);
    else if strcmp(f_name,'tanh')
            d_f=1-y.^2;%matlab 自带
        else
           disp('wrong function name at d_function');
        end
    end
    end
    
    
    function [ y ] = sigmoid( x )
    %MY_SIGMOID 
    %   输入向量x,输出
    y=1./(1+exp(-x));
    end
    
    
  • 相关阅读:
    hdu 4476 Cut the rope (2-pointer && simulation)
    hdu 1286 找新朋友 (容斥原理 || 欧拉函数)
    函数存储的另一种思路
    grunt 入门 应用grunt对代码进行压缩
    sublime flatLand 主题
    如何应用r.js对requirejs下的js代码合并
    如何在requirejs下引用bootstrap
    学习在requirejs下如何使用underscore.js模板
    应用js函数柯里化currying 与ajax 局部刷新dom
    js 函数arguments一种用法
  • 原文地址:https://www.cnblogs.com/simayuhe/p/5437083.html
Copyright © 2020-2023  润新知