C# BP神经网络 类与实例

来源:互联网 发布:youtube翻墙软件 编辑:程序博客网 时间:2024/06/04 18:39

类:

using System;using System.IO;using System.Text;namespace BpANNet{    /// <summary>    /// BpNet 的摘要说明。    /// </summary>    public class BpNet    {        public int inNum;//输入节点数        int hideNum;//隐层节点数        public int outNum;//输出层节点数        public int sampleNum;//样本总数        Random R;        double[] x;//输入节点的输入数据        double[] x1;//隐层节点的输出        double[] x2;//输出节点的输出        double[] o1;//隐层的输入        double[] o2;//输出层的输入        public double[,] w;//权值矩阵w        public double[,] v;//权值矩阵V        public double[,] dw;//权值矩阵w        public double[,] dv;//权值矩阵V        public double rate;//学习率        public double[] b1;//隐层阈值矩阵        public double[] b2;//输出层阈值矩阵        public double[] db1;//隐层阈值矩阵        public double[] db2;//输出层阈值矩阵        double[] pp;//输出层的误差        double[] qq;//隐层的误差        double[] yd;//输出层的教师数据        public double e;//均方误差        double in_rate;//归一化比例系数        public int computeHideNum(int m, int n)        {            double s = Math.Sqrt(0.43 * m * n + 0.12 * n * n + 2.54 * m + 0.77 * n + 0.35) + 0.51;            int ss = Convert.ToInt32(s);            return ((s - (double)ss) > 0.5) ? ss + 1 : ss;        }        public BpNet(double[,] p, double[,] t)        {            // 构造函数逻辑            R = new Random();            this.inNum = p.GetLength(1); //数组第二维大小 为 输入节点数            this.outNum = t.GetLength(1); //输出节点数            this.hideNum = computeHideNum(inNum, outNum); //隐藏节点数,不知其原理            //      this.hideNum=18;            this.sampleNum = p.GetLength(0); //数组第一维大小 为 样本总数            Console.WriteLine("输入节点数目: " + inNum);            Console.WriteLine("隐层节点数目:" + hideNum);            Console.WriteLine("输出层节点数目:" + outNum);            Console.ReadLine(); //读个空行            x = new double[inNum];            x1 = new double[hideNum];            x2 = new double[outNum];            o1 = new double[hideNum];            o2 = new double[outNum];            w = new double[inNum, hideNum];            v = new double[hideNum, outNum];            dw = new double[inNum, hideNum];            dv = new double[hideNum, outNum];            b1 = new double[hideNum];            b2 = new double[outNum];            db1 = new double[hideNum];            db2 = new double[outNum];            pp = new double[hideNum];            qq = new double[outNum];            yd = new double[outNum];            //初始化w            for (int i = 0; i < inNum; i++)            {                for (int j = 0; j < hideNum; j++)                {                    w[i, j] = (R.NextDouble() * 2 - 1.0) / 2;                }            }            //初始化v            for (int i = 0; i < hideNum; i++)            {                for (int j = 0; j < outNum; j++)                {                    v[i, j] = (R.NextDouble() * 2 - 1.0) / 2;                }            }            rate = 0.8;            e = 0.0;            in_rate = 1.0;        }        //训练函数        public void train(double[,] p, double[,] t)        {            e = 0.0;            //求p,t中的最大值            double pMax = 0.0;            for (int isamp = 0; isamp < sampleNum; isamp++)            {                for (int i = 0; i < inNum; i++)                {                    if (Math.Abs(p[isamp, i]) > pMax)                    {                        pMax = Math.Abs(p[isamp, i]);                    }                }                for (int j = 0; j < outNum; j++)                {                    if (Math.Abs(t[isamp, j]) > pMax)                    {                        pMax = Math.Abs(t[isamp, j]);                    }                }                in_rate = pMax;            }//end isamp            for (int isamp = 0; isamp < sampleNum; isamp++)            {                //数据归一化                for (int i = 0; i < inNum; i++)                {                    x[i] = p[isamp, i] / in_rate;                }                for (int i = 0; i < outNum; i++)                {                    yd[i] = t[isamp, i] / in_rate;                }                //计算隐层的输入和输出                for (int j = 0; j < hideNum; j++)                {                    o1[j] = 0.0;                    for (int i = 0; i < inNum; i++)                    {                        o1[j] += w[i, j] * x[i];                    }                    x1[j] = 1.0 / (1.0 + Math.Exp(-o1[j] - b1[j]));                }                //计算输出层的输入和输出                for (int k = 0; k < outNum; k++)                {                    o2[k] = 0.0;                    for (int j = 0; j < hideNum; j++)                    {                        o2[k] += v[j, k] * x1[j];                    }                    x2[k] = 1.0 / (1.0 + Math.Exp(-o2[k] - b2[k]));                }                //计算输出层误差和均方差                for (int k = 0; k < outNum; k++)                {                    qq[k] = (yd[k] - x2[k]) * x2[k] * (1.0 - x2[k]);                    e += (yd[k] - x2[k]) * (yd[k] - x2[k]);                    //更新V                    for (int j = 0; j < hideNum; j++)                    {                        v[j, k] += rate * qq[k] * x1[j];                    }                }                //计算隐层误差                for (int j = 0; j < hideNum; j++)                {                    pp[j] = 0.0;                    for (int k = 0; k < outNum; k++)                    {                        pp[j] += qq[k] * v[j, k];                    }                    pp[j] = pp[j] * x1[j] * (1 - x1[j]);                    //更新W                    for (int i = 0; i < inNum; i++)                    {                        w[i, j] += rate * pp[j] * x[i];                    }                }                //更新b2                for (int k = 0; k < outNum; k++)                {                    b2[k] += rate * qq[k];                }                //更新b1                for (int j = 0; j < hideNum; j++)                {                    b1[j] += rate * pp[j];                }            }//end isamp            e = Math.Sqrt(e);            //      adjustWV(w,dw);            //      adjustWV(v,dv);        }//end train        public void adjustWV(double[,] w, double[,] dw)        {            for (int i = 0; i < w.GetLength(0); i++)            {                for (int j = 0; j < w.GetLength(1); j++)                {                    w[i, j] += dw[i, j];                }            }        }        public void adjustWV(double[] w, double[] dw)        {            for (int i = 0; i < w.Length; i++)            {                w[i] += dw[i];            }        }        //数据仿真函数        public double[] sim(double[] psim)        {            for (int i = 0; i < inNum; i++)                x[i] = psim[i] / in_rate;            for (int j = 0; j < hideNum; j++)            {                o1[j] = 0.0;                for (int i = 0; i < inNum; i++)                    o1[j] = o1[j] + w[i, j] * x[i];                x1[j] = 1.0 / (1.0 + Math.Exp(-o1[j] - b1[j]));            }            for (int k = 0; k < outNum; k++)            {                o2[k] = 0.0;                for (int j = 0; j < hideNum; j++)                    o2[k] = o2[k] + v[j, k] * x1[j];                x2[k] = 1.0 / (1.0 + Math.Exp(-o2[k] - b2[k]));                x2[k] = in_rate * x2[k];            }            return x2;        } //end sim        //保存矩阵w,v        public void saveMatrix(double[,] w, string filename)        {            StreamWriter sw = File.CreateText(filename);            for (int i = 0; i < w.GetLength(0); i++)            {                for (int j = 0; j < w.GetLength(1); j++)                {                    sw.Write(w[i, j] + " ");                }                sw.WriteLine();            }            sw.Close();        }        //保存矩阵b1,b2        public void saveMatrix(double[] b, string filename)        {            StreamWriter sw = File.CreateText(filename);            for (int i = 0; i < b.Length; i++)            {                sw.Write(b[i] + " ");            }            sw.Close();        }        //读取矩阵W,V        public void readMatrixW(double[,] w, string filename)        {            StreamReader sr;            try            {                sr = new StreamReader(filename, Encoding.GetEncoding("gb2312"));                String line;                int i = 0;                while ((line = sr.ReadLine()) != null)                {                    string[] s1 = line.Trim().Split(' ');                    for (int j = 0; j < s1.Length; j++)                    {                        w[i, j] = Convert.ToDouble(s1[j]);                    }                    i++;                }                sr.Close();            }            catch (Exception e)            {                // Let the user know what went wrong.                Console.WriteLine("The file could not be read:");                Console.WriteLine(e.Message);            }        }        //读取矩阵b1,b2        public void readMatrixB(double[] b, string filename)        {            StreamReader sr;            try            {                sr = new StreamReader(filename, Encoding.GetEncoding("gb2312"));                String line;                int i = 0;                while ((line = sr.ReadLine()) != null)                {                    b[i] = Convert.ToDouble(line);                    i++;                }                sr.Close();            }            catch (Exception e)            {                // Let the user know what went wrong.                Console.WriteLine("The file could not be read:");                Console.WriteLine(e.Message);            }        }    }//end bpnet} //end namespace


主程序:

//主调用程序using System;namespace BpANNet{    /// <summary>    /// Class1 的摘要说明。    /// </summary>    class Class1    {        /// <summary>        /// 应用程序的主入口点。        /// </summary>        [STAThread]        static void Main(string[] args)        {            //0.1399,0.1467,0.1567,0.1595,0.1588,0.1622,0.1611,0.1615,0.1685,0.1789,0.1790            //      double [,] p1=new double[,]{{0.05,0.02},{0.09,0.11},{0.12,0.20},{0.15,0.22},{0.20,0.25},{0.75,0.75},{0.80,0.83},{0.82,0.80},{0.90,0.89},{0.95,0.89},{0.09,0.04},{0.1,0.1},{0.14,0.21},{0.18,0.24},{0.22,0.28},{0.77,0.78},{0.79,0.81},{0.84,0.82},{0.94,0.93},{0.98,0.99}};            //      double [,] t1=new double[,]{{1,0},{1,0},{1,0},{1,0},{1,0},{0,1},{0,1},{0,1},{0,1},{0,1},{1,0},{1,0},{1,0},{1,0},{1,0},{0,1},{0,1},{0,1},{0,1},{0,1}};            double[,] p1 = new double[,] { { 0.1399, 0.1467, 0.1567, 0.1595, 0.1588, 0.1622 }, { 0.1467, 0.1567, 0.1595, 0.1588, 0.1622, 0.1611 }, { 0.1567, 0.1595, 0.1588, 0.1622, 0.1611, 0.1615 }, { 0.1595, 0.1588, 0.1622, 0.1611, 0.1615, 0.1685 }, { 0.1588, 0.1622, 0.1611, 0.1615, 0.1685, 0.1789 } };            double[,] t1 = new double[,] { { 0.1622 }, { 0.1611 }, { 0.1615 }, { 0.1685 }, { 0.1789 }, { 0.1790 } };            BpNet bp = new BpNet(p1, t1);            int study = 0;            do            {                study++;                bp.train(p1, t1);                //       bp.rate=0.95-(0.95-0.3)*study/50000;                //        Console.Write("第 "+ study+"次学习: ");                //        Console.WriteLine(" 均方差为 "+bp.e);            } while (bp.e > 0.001 && study < 50000);            Console.Write("第 " + study + "次学习: ");            Console.WriteLine(" 均方差为 " + bp.e);            bp.saveMatrix(bp.w, "w.txt");            bp.saveMatrix(bp.v, "v.txt");            bp.saveMatrix(bp.b1, "b1.txt");            bp.saveMatrix(bp.b2, "b2.txt");            //      double [,] p2=new double[,]{{0.05,0.02},{0.09,0.11},{0.12,0.20},{0.15,0.22},{0.20,0.25},{0.75,0.75},{0.80,0.83},{0.82,0.80},{0.90,0.89},{0.95,0.89},{0.09,0.04},{0.1,0.1},{0.14,0.21},{0.18,0.24},{0.22,0.28},{0.77,0.78},{0.79,0.81},{0.84,0.82},{0.94,0.93},{0.98,0.99}};            double[,] p2 = new double[,] { { 0.1399, 0.1467, 0.1567, 0.1595, 0.1588, 0.1622 }, { 0.1622, 0.1611, 0.1615, 0.1685, 0.1789, 0.1790 } };            int aa = bp.inNum;            int bb = bp.outNum;            int cc = p2.GetLength(0);            double[] p21 = new double[aa];            double[] t2 = new double[bb];            for (int n = 0; n < cc; n++)            {                for (int i = 0; i < aa; i++)                {                    p21[i] = p2[n, i];                }                t2 = bp.sim(p21);                for (int i = 0; i < t2.Length; i++)                {                    Console.WriteLine(t2[i] + " ");                }            }            Console.ReadLine();        }    }}