c# Bp神经网络

 使用了周志华老师写的机器学习中的神经网络的公式,具体公式可以看《机器学习》--周志华第103页,用的时标准BP算法

具体代码在下面,注释明确

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace mssbyi
{
  //Random Random = new Random();
  class BpDeep
  {
    Random Random = new Random();
    //构造函数,构造bp网络,n为学习率,MST为最大学习次数
    public BpDeep(List<int> net_size, double n, int MST, double min_error)
    {
      //模型参数传入
      inputSize = net_size[0];
      numLaters = net_size.Count;
      netSize = net_size;
      outputSize = net_size.Last();
      N = n;
      MaxStudyTimes = MST;
      //设置输入层
      layers.Add(new layer(netSize[0], netSize[1], n));
      //初始化隐藏层
      for (int i = 1; i < numLaters - 1; i++)
      {
        layers.Add(new layer(netSize[i], netSize[i + 1], n));
      }
      //初始化输出层
      layers.Add(new layer(netSize.Last(), 0, n));//后期需要设置分类数量!!!!!!!!!!!
      error = 100;//初使可以用很大的值
      minError = min_error;
    }
    //正向传播
    public void forward(List<double> input)
    {
      layers[0].Y = input;
      for (int i = 1; i < numLaters; i++)
      {
        layers[i].forward(layers[i - 1]);
      }
    }
    //反向传播
    public void backward(List<double> output_real)
    {
      //计算误差


      //计算误差和输出层神经元梯度项
      List<double> g = new List<double>();
      for (int i = 0; i < outputSize; i++)
      {
        g.Add((layers.Last().Y[i] * (1 - layers.Last().Y[i]) * (output_real[i] - layers.Last().Y[i])));
        error += 0.5 * Math.Pow((output_real[i] - layers.Last().Y[i]), 2);
      }
      //设置输出层的阈值
      List<double> db_last = new List<double>();
      for (int i = 0; i < layers[numLaters - 1].numNeuron; i++)
      {
        db_last.Add(-1 * N * g[i]);
        //db_last[i] = -1 * N * g[i];
      }
      layers[numLaters - 1].setDB = db_last;
     
      //计算最后一个隐藏层的神经元梯度项
      List<double> e = new List<double>();
      for (int i = 0; i < layers[numLaters - 2].numNeuron; i++)
      {
        double sum = 0;
        for (int j = 0; j < outputSize; j++)
        {
          sum += layers[numLaters - 2].getW[i][j] * g[j];
        }
        e.Add(layers[numLaters - 2].Y[i] * (1 - layers[numLaters - 2].Y[i]) * sum);
        //e[i] = layers[numLaters - 2].Y[i] * (1 - layers[numLaters - 2].Y[i]) * sum;
      }
      layers[numLaters - 2].setE = e;
      //设置最后一个隐藏层参数改正量
      List<List<double>> dw = new List<List<double>>();
      List<double> db_lastsecond = new List<double>();
      for (int i = 0; i < layers[numLaters - 2].numNeuron; i++)
      {
        db_lastsecond.Add(-1 * N * e[i]);
        //db_last[i] = -1 * N * e[i];
        dw.Add(new List<double>());
        for (int j = 0; j < layers[numLaters - 1].numNeuron; j++)
        {
          //w[i].Add(new double());
          //dw[i] = new List<double>();
          dw[i].Add(N * g[j] * layers[numLaters - 2].Y[i]);
          //dw[i][j] = N * g[j] * layers[numLaters - 2].Y[i];
        }
        layers[numLaters - 2].setDW = dw;
      }
      layers[numLaters - 2].setDB = db_lastsecond;

      
      //从倒数第二个隐藏层开始反向传播
      for (int i = numLaters - 3; i >= 0; i--)
      {
        layers[i].backward(layers[i + 1]);
      }
      for(int i=numLaters-1;i>=0;i--)
      {
        layers[i].refreshW();
        layers[i].refreshB();
      }
     
    }
    //设置训练集和测试集,l为训练集的比例
    public void setTrainAndTest(List<List<double>> input, List<List<double>> output, double l)
    {
      //将数据随机打乱
      List<List<double>> newInput = new List<List<double>>();
      List<List<double>> newOutput = new List<List<double>>();
      for (int i = 0; i < input.Count; i++)
      {
        int j = Random.Next(newInput.Count + 1);
        newInput.Insert(j, input[i]);
        newOutput.Insert(j, output[i]);
      }
      //将数据集分为训练集和测试集
      int num_train = (int)(input.Count * l);
      int num_test = input.Count - num_train;

      trainInput = newInput; //(List<List<double>>)newInput.Take(num_train);
      trainOutput = newOutput;// (List<List<double>>)newOutput.Take(num_train);
                              //layers.Last().numNeuron = trainOutput.Count;

      //layers.Add(new layer(trainOutput.Count, 0));
      //  testInput = (List<List<double>>)newInput.Skip(num_train);
      // testOutput = (List<List<double>>)newOutput.Skip(num_train);
    }
    //训练
    public double trainning()
    {
      int sum = 0;
      while (error > minError && sum < MaxStudyTimes)
      {
        error = 0;

        for (int i = 0; i < trainInput.Count; i++)
        {
          forward(trainInput[i]);
          backward(trainOutput[i]);
          
        }
        error = error / outputSize;
        sum++;
        
      }
      return error;
    }
    //预测
    public int predict(List<double> input)
    {
      forward(input);
      List<double> output = layers.Last().Y;
      int key = -1;
      double max = -1;
      for (int i = 0; i < output.Count; i++)
      {
        if (output[i] > max)
        {
          max = output[i];
          key = i;
        }

      }
      return key;
    }
    private int inputSize;//输入层神经元数
    private int numLaters;//网络总层数
    private List<int> netSize = new List<int>();   //各层神经元数量
    private int outputSize;//输出层神经元数量
    private double N;//学习率
    public  double error;//误差
    private double minError;//最小误差
    private int MaxStudyTimes;
    private List<layer> layers = new List<layer>();
    public List<List<double>> trainInput = new List<List<double>>();
    public List<List<double>> trainOutput = new List<List<double>>();
    List<List<double>> testInput = new List<List<double>>();
    List<List<double>> testOutput = new List<List<double>>();
  };
  class layer
  {
    Random Random = new Random();
    //生成高斯分布的随机数
    public double Rand(double u, double d)
    {
      double u1, u2, z, x;
      //Random ram = new Random();
      if (d <= 0)
      {
        return u;
      }
      u1 = Random.NextDouble();
      u2 = Random.NextDouble();
      z = Math.Sqrt(-2 * Math.Log(u1)) * Math.Sin(2 * Math.PI * u2);
      x = u + d * z;
      return x;
    }
    //构造函数
    public layer(int num_neuron = 0, int last_nn = 0, double n=0.1)
    {
      numNeuron = num_neuron;
      //初始化权值和阈值
      db = new List<double>(numNeuron);
     // dw.Add(numNeuron);
     
      for (int i = 0; i < numNeuron; i++)
      {
        dw.Add(new List<double>());
        b.Add(Rand(0, 0.3));
        //b[i] = Rand(0, 0.3); 
        w.Add(new List<double>());
        y.Add(new double());
        db.Add(new double());
        e.Add(last_nn);
        for (int j = 0; j < last_nn; j++)
        {
          w[i].Add(Rand(0, 0.3));
          dw[i].Add(new double());
          //w[i][j] = Rand(0, 0.3);
        }
      }
      N = n;
    }
    //激发函数
    public double sigmoid(double x)
    {
      return 1 / (1 + Math.Exp(-x));
    }

    //正向传播,需要知道前一层的信息
    public void forward(layer layer)
    {
      //List<List<double>> wl = new List<List<double>>(layer.w);
      // List<double> x = new List<double>(layer.y);
      for (int i = 0; i < numNeuron; i++)
      {
        for (int j = 0; j < layer.numNeuron; j++)
        {
          y[i] = y[i] + layer.y[j] * layer.w[j][i];
        }
        y[i] = sigmoid(y[i] + b[i]);
      }

    }
    //误差逆传播,需要知道后一层的信息
    public void backward(layer layer)
    {
      //计算这一层的神经元梯度项
      for (int i = 0; i < numNeuron; i++)
      {
        double sum = 0;
        for (int j = 0; j < layer.numNeuron; j++)
        {
          sum += w[i][j] * layer.e[j];
        }
       // e.Add(y[i] * (1 - y[i]) * sum);
         e[i] = y[i] * (1 - y[i]) * sum;
      }
      //计算这一层的参数改正数
      for (int i = 0; i < numNeuron; i++)
      {
        //db.Add(-1 * N * e[i]);
        db[i] = -1 * N * e[i];
       // dw.Add(new List<double>());
        for (int j = 0; j < layer.numNeuron; j++)
        {
          //dw[i].Add(N * layer.e[j] * y[i]);
          dw[i][j] = N * layer.e[j] * y[i];
        }
      }
     
    }
    //设置输出(用于训练时设置输入层)
    public List<double> Y
    {
      set { y = value; }
      get { return y; }
    }
    public List<List<double>> getW
    {
      get { return w; }
    }
    public List<List<double>> setDW
    {
      set { dw = value; }
    }
    public List<double> setDB
    {
      set { db = value; }
    }
    public List<double> setE
    {
      set { e = value; }
    }
    //刷新
    public void refreshW()
    {
      for (int i = 0; i < numNeuron; i++)
      {
        for (int j = 0; j < w[i].Count; j++)
        {
          w[i][j] = w[i][j] + dw[i][j];
        }
      }
    }
    public void refreshB()
    {
      for (int i = 0; i < numNeuron; i++)
      {
        b[i] = b[i] + db[i];
      }
    }
    //神经元数量
    public int numNeuron = 0;
    //权值
    List<List<double>> w = new List<List<double>>();
    List<List<double>> dw = new List<List<double>>();
    //阈值
    List<double> b = new List<double>();
    List<double> db;// = new List<double>();
    //输出
    List<double> y = new List<double>();
    //学习率
    public double N;
    //神经元梯度项
    List<double> e = new List<double>();


  };


}

下面有一个示例的使用方法

private void bP神经网络ToolStripMenuItem_Click(object sender, EventArgs e)
    {
      List<int> net_size = new List<int>();
      net_size.Add(bands);
      for(int i=0;i<5;i++)
      {
        net_size.Add(25);
      }
      net_size.Add(form6.ybdata.Count);
      BpDeep net = new BpDeep(net_size, 0.1, 10000,0.01);

      //将样本信息转为训练集和测试集形式,并输入
      List<List<double>> input = new List<List<double>>();
      List<List<double>> output = new List<List<double>>();
      int num = 0;
      double temp;
      double realMax=0;
      for(int i=0;i<pixelData.Count;i++)
      {
        if (pixelData[i].Max() > realMax)
        {
          realMax = pixelData[i].Max();
        }          
      }
      for(int i=0;i<form6.ybdata.Count;i++)//i表示类别
      {
        for(int j=0;j<form6.ybdata[i].Count;j++)//j表示该类别数量
        {
          input.Add(new List<double>());
          output.Add(new List<double>());
          //input.Add((List<double>)(form6.ybdata[i][j]));
          for(int k=0;k<form6.ybdata[i][j].Count;k++)
          {
            temp = form6.ybdata[i][j][k];/// realMax;
            input[num].Add(temp);
            
          }
          for(int k=0;k<form6.ybdata.Count;k++)
          {
            output[num].Add(0);
          }
          output[num][i] = 1;
          num++;
        }
      }
      net.setTrainAndTest(input, output,0.9);
      //训练
      double error=net.trainning();

      


      //预测
      List<double> predict_input = new List<double>();
      for (int xx = 0; xx < width; xx++)
      {
        for (int yy = 0; yy < height; yy++)
        {
          for (int b = 0; b < bands; b++)
          {
            temp = pixelData[b][yy * width + xx];/// realMax;
            predict_input.Add(temp);            
          }
          
          bitmap.SetPixel(xx, yy, Class1.sll[net.predict(predict_input)].color);
          predict_input.Clear();
        }
      }
      pictureBox1.Image = bitmap;
      
      //net.predict()
    }
  }

这个网络还存在一些问题。。。

 

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BP神经网络预测的matlab代码有多种优化模型可供选择。常见的优化算法包括遗传算法、粒子群算法、灰狼优化算法、布谷鸟搜索算法、海鸥优化算法、鲸鱼优化算法、麻雀搜索算法、人工蜂群算法、蚁群算法、原子搜索算法等。 以下是一些常见的BP神经网络预测优化算法模型的matlab代码示例: - 遗传算法优化BP神经网络回归预测MATLAB代码 - 粒子群算法PSO优化BP神经网络回归预测MATLAB代码 - 灰狼优化算法GWO优化BP神经网络回归预测MATLAB代码 - 布谷鸟搜索算法CS优化BP神经网络回归预测MATLAB代码 - 海鸥优化算法SOA优化BP神经网络回归预测MATLAB代码 - 鲸鱼优化算法WOA优化BP神经网络回归预测MATLAB代码 麻雀搜索算法SSA优化BP神经网络回归预测MATLAB代码 - 人工蜂群算法ABC优化BP神经网络回归预测MATLAB代码 - 蚁群算法ACO优化BP神经网络回归预测MATLAB代码 - 原子搜索算法ASO优化BP神经网络回归预测MATLAB代码 等等。 具体的代码实现可以根据所选择的优化算法进行下载并使用。这些代码通过优化BP神经网络的初始权值和阈值,并使用训练样本进行网络训练,最终得到预测值。遗传算法用于优化BP神经网络的要素包括种群初始化、适应度函数、选择算子、交叉算子和变异算子等。通过使用这些优化算法,可以提高BP神经网络在预测任务中的性能。 请注意,以上仅是一些常见的优化算法模型的matlab代码示例,具体使用哪种优化算法取决于实际需求和数据特征。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值