自学内容网 自学内容网

cnn突破九(我们的五层卷积核bpnet网络就是lenet-1)

cnn突破八中最后说明白了,但没给出结果,我们今天算出结果:

在四层中:\frac{\partial E}{\partial w1cnn[0]}=.....ds(hocnn[1])*x[17];

这个公式实际对应14*14(x【】)-》5*5(hocnn【】)

同样在5层中:\frac{\partial E}{\partial w784[i]}=......ds(hxo[])*x[i=?]

这个公式实际对应28*28(x【】)-》12*12(hox【】),

所以我们通过hox【】求x【】的方法和四层网络是一样的。

14*14(x【】)-》5*5(hocnn【】)被12*12(hox【】)-》4*4(hocnn【】)替代,就形成:

28*28-》12*12-》4*4-》80-》10

因为hox就相当于四层中的原图像x【】,我们已经能求出来,也就是说hxo【】我们能求出来,我们在五层网络中再走一遍:

hxi【】来自temphicnn【】2*2最大池化:

temphicnn[0]+=x[i=0,j=0,5*5方阵]*w784[0-24],

hxi[]与hxo【】是12*12的,temphicnn是【】24*24的,x是【】28*28的。

hxi【1】来自temphicnn【2】【3】【26】【27】,一一对应池化中的位置(0,0)(0,1)(1,0)(1,1),假定(1,1)最大,即27=(第二行=1,第四列=3),即temphicnn【27=1*24+3】最大,对应x【31=1*28+3】

所以,一个hxi对应一个hxo,一个hxo【1】对应25个w784更新:显然:

\frac{\partial E}{\partial w784[0]}=.....ds(hxo[1])*x[31];

\frac{\partial E}{\partial w784[1]}=.....ds(hxo[1])*x[32];

......

从上面看出来:hxo显然是12*12的,每一个hxo:w784【】有25个就对应25个x【】取值。

下面我们看实现代码:前向网络forward代码(前面四个卷积核,后头16个卷积核):

   public void cnnforward()//202409180943使用4层网络,抄过来(这里还是三层网络),14*14->5*5->15->10
        {
            hIcnntemp = new double[576];
            hIcnntemp1 = new double[576]; hIcnntemp2 = new double[576]; hIcnntemp3 = new double[576];
            hIcnn1na = new double[144]; hIcnn2na = new double[144]; hIcnn3na = new double[144];
            hIcnnna = new double[144];//每一幅图片都要重置
              jilumnna.Clear();//forwardcnn执行一次,就是换一张图片
            jilumn1na.Clear();
            jilumn2na.Clear(); jilumn3na.Clear();
            for (int i = 0; i < 24; i++)
                for (int j = 0; j < 24; j++)//
                {
                    int l = (i) * 24 + j;

                    for (int m = 0; m < 5; m++)
                        for (int n = 0; n < 5; n++)
                        {
                            int k = (i + m) * 28 + j + n;
                            hIcnntemp[l] += xI[k] * w576cnn[m * 5 + n, 0];//始终用零组,其他三个组不用
                            //为了方便,如此设计202409181006
                            hIcnntemp1[l] += xI[k] * w576cnn[m * 5 + n, 1];

                            hIcnntemp2[l] += xI[k] * w576cnn[m * 5 + n, 2];
                            hIcnntemp3[l] += xI[k] * w576cnn[m * 5 + n, 3];
                        }
                }

            //第二步,10*10-》5*5
            //第二步,24*24》12*12
            for (int i = 0; i < 12; i++)
                for (int j = 0; j < 12; j++)//
                {
                    int l = (i) * 12 + j;
                    double tempb = 0;
                    Point tempPt = new Point();
                    for (int m = 0; m < 2; m++)
                        for (int n = 0; n < 2; n++)//需要记住m,n和序号L,202409181018
                        {
                            int k = (i * 2 + m) * 24 + j * 2 + n;
                            //  tempb += B1[k] * Wb2c[m * 2 + n, l];//取均值?还是取最大值?
                            if (hIcnntemp[k] > tempb)
                            {
                                tempb = hIcnntemp[k];//如果是最大值,核就变得没有意义,back怎么办?202409170727
                                tempPt = new Point(n, m);//m是h,n是w,这个要小心用错

                            }
                        }
                    //   C1[l] = (byte)(tempb/4f);
                    jilumnna.Add(tempPt);//25个数据,就有25组m,n,序号一一对应
                    hIcnnna[l] = tempb;//25个数据,通过这个关系,就能找到14*14matrix中去。202409181038
                }
            //  showbuffer2pictmod4(B1, 5, 5, pictureBox17);
            for (int i = 0; i <12; i++)
                for (int j = 0; j < 12; j++)//
                {
                    int l = (i) * 12 + j;
                    double tempb = 0;
                    Point tempPt = new Point();
                    for (int m = 0; m < 2; m++)
                        for (int n = 0; n < 2; n++)//需要记住m,n和序号L,202409181018
                        {
                            int k = (i * 2 + m) * 24 + j * 2 + n;
                            //  tempb += B1[k] * Wb2c[m * 2 + n, l];//取均值?还是取最大值?
                            if (hIcnntemp1[k] > tempb)
                            {
                                tempb = hIcnntemp1[k];//如果是最大值,核就变得没有意义,back怎么办?202409170727
                                tempPt = new Point(n, m);//m是h,n是w,这个要小心用错

                            }
                        }
                    //   C1[l] = (byte)(tempb/4f);
                    jilumn1na.Add(tempPt);//25个数据,就有25组m,n,序号一一对应
                    hIcnn1na[l] = tempb;//25个数据,通过这个关系,就能找到14*14matrix中去。202409181038
                }
            for (int i = 0; i < 12; i++)
                for (int j = 0; j < 12; j++)//
                {
                    int l = (i) * 12 + j;
                    double tempb = 0;
                    Point tempPt = new Point();
                    for (int m = 0; m < 2; m++)
                        for (int n = 0; n < 2; n++)//需要记住m,n和序号L,202409181018
                        {
                            int k = (i * 2 + m) * 24 + j * 2 + n;
                            //  tempb += B1[k] * Wb2c[m * 2 + n, l];//取均值?还是取最大值?
                            if (hIcnntemp2[k] > tempb)
                            {
                                tempb = hIcnntemp2[k];//如果是最大值,核就变得没有意义,back怎么办?202409170727
                                tempPt = new Point(n, m);//m是h,n是w,这个要小心用错

                            }
                        }
                    //   C1[l] = (byte)(tempb/4f);
                    jilumn2na.Add(tempPt);//25个数据,就有25组m,n,序号一一对应
                    hIcnn2na[l] = tempb;//25个数据,通过这个关系,就能找到14*14matrix中去。202409181038
                }
            for (int i = 0; i < 12; i++)
                for (int j = 0; j < 12; j++)//
                {
                    int l = (i) * 12+ j;
                    double tempb = 0;
                    Point tempPt = new Point();
                    for (int m = 0; m < 2; m++)
                        for (int n = 0; n < 2; n++)//需要记住m,n和序号L,202409181018
                        {
                            int k = (i * 2 + m) * 24 + j * 2 + n;
                            //  tempb += B1[k] * Wb2c[m * 2 + n, l];//取均值?还是取最大值?
                            if (hIcnntemp3[k] > tempb)
                            {
                                tempb = hIcnntemp3[k];//如果是最大值,核就变得没有意义,back怎么办?202409170727
                                tempPt = new Point(n, m);//m是h,n是w,这个要小心用错

                            }
                        }
                    //   C1[l] = (byte)(tempb/4f);
                    jilumn3na.Add(tempPt);//25个数据,就有25组m,n,序号一一对应
                    hIcnn3na[l] = tempb;//25个数据,通过这个关系,就能找到14*14matrix中去。202409181038
                }
            /
            // 上面已经达成12*12的四张特征图202409211852,下面每张特征图再卷积成8*8,下采样,生成4张4*4
         //   List<double[]>
                hebingbackImg = new List<double[]>();
         //   List<List<Point>> 
                hebingpos = new List<List<Point>>();
          //  for (int i = 0; i < 4; i++)
            {
                List<double[] >tempbackImg=new List<double[]>();
                List<List<Point>>
                    temp=chongfu(hIcnnna, w1cnn, tempbackImg);//重复一次,生成4张4*4特征图和16个位置记录要返回,4次就是,16张图,64个位置记录
                for (int i = 0; i < 4; i++)
                {
                    hebingpos.Add(temp[i]);
                    hebingbackImg.Add(tempbackImg[i]);
                }
                tempbackImg.Clear();
                temp.Clear();
                temp = chongfu(hIcnn1na, w1cnn2, tempbackImg);//重复一次,生成4张4*4特征图和16个位置记录要返回,4次就是,16张图,64个位置记录
                for (int i = 0; i < 4; i++)
                {
                    hebingpos.Add(temp[i]);
                    hebingbackImg.Add(tempbackImg[i]);
                }
                tempbackImg.Clear();
                temp.Clear();
                temp = chongfu(hIcnn2na, w1cnn3, tempbackImg);//重复一次,生成4张4*4特征图和16个位置记录要返回,4次就是,16张图,64个位置记录
                for (int i = 0; i < 4; i++)
                {
                    hebingpos.Add(temp[i]);
                    hebingbackImg.Add(tempbackImg[i]);
                }
                tempbackImg.Clear();
                temp.Clear();
                temp = chongfu(hIcnn3na, w1cnn4, tempbackImg);//重复一次,生成4张4*4特征图和16个位置记录要返回,4次就是,16张图,64个位置记录
                for (int i = 0; i < 4; i++)
                {
                    hebingpos.Add(temp[i]);
                    hebingbackImg.Add(tempbackImg[i]);
                }
            }
            hocnnhebing = new double[16*16];
            for(int i=0;i<16;i++)
                for (int j = 0; j < 16; j++)
                {
                    hocnnhebing[i*16+j] = sigmoid(hebingbackImg[i][j]);//i代表16服图像,j代表pixel4*4
                }


            //
              hocnnhebing=new double[75];
            //hocnnhebing = new double[100];
            //for (int i = 0; i < 25; i++)
            //{
            //    //hO[i] = sigmoid(hI[i]+bh[i]);
            //    hocnnhebing[i] = hocnn[i] = sigmoid(hIcnn[i]);
            //    hocnnhebing[i + 25] = hocnn1na[i] = sigmoid(hIcnn1na[i]);
            //    hocnnhebing[i + 50] = sigmoid(hIcnn2na[i]);
            //    hocnnhebing[i + 75] = sigmoid(hIcnn3na[i]);
            //}
            //下面开始全连接202409181044
            hI2cnn = new double[50];//15gai 25
           
            for (int i = 0; i < 16*16; i++)//128             
                for (int j = 0; j < 50; j++)//60
                    hI2cnn[j] += (hocnnhebing[i]) * w12cnn[i, j];//75,25
          

            //通过激活函数对隐藏层进行计算 
            for (int i = 0; i < 50; i++)
                hO2cnn[i] = sigmoid(hI2cnn[i]);

            yicnn = new double[10];
            //通过w2计算隐藏层-输出层
            for (int i = 0; i < 50; i++)
                for (int j = 0; j < 10; j++)

                    yicnn[j] += hO2cnn[i] * w2cnn[i, j];

            //通过激活函数求yo
            for (int i = 0; i < 10; i++)
                //yO[i] = sigmoid(yi[i]+by[i]);
                yOcnn[i] = sigmoid(yicnn[i]);
        }

调用函数:

    public List<List<Point>> chongfu(double []输入图像,double [,] 卷积核,List<double[]>fanhuituxiang)
        {
            List<List<Point>> templlp = new List<List<Point>>();
            // 上面已经达成12*12的四张特征图202409211852,下面每张特征图再卷积成8*8,下采样,生成4张4*4
            ThIcnntemp = new double[64];
            ThIcnntemp1 = new double[64]; ThIcnntemp2 = new double[64]; ThIcnntemp3 = new double[64];
            ThIcnn1na = new double[16]; ThIcnn2na = new double[16]; ThIcnn3na = new double[16];
            ThIcnnna = new double[16];//每一幅图片都要重置
            Tjilumnna.Clear();//forwardcnn执行一次,就是换一张图片
            Tjilumn1na.Clear();
            Tjilumn2na.Clear(); Tjilumn3na.Clear();
            for (int i = 0; i < 8; i++)
                for (int j = 0; j < 8; j++)//
                {
                    int l = (i) * 8 + j;

                    for (int m = 0; m < 5; m++)
                        for (int n = 0; n < 5; n++)
                        {
                            int k = (i + m) * 12 + j + n;
                            ThIcnntemp[l] += 输入图像[k] * 卷积核[m * 5 + n, 0];//始终用零组,其他三个组不用
                            //为了方便,如此设计202409181006
                            ThIcnntemp1[l] += 输入图像[k] * 卷积核[m * 5 + n, 1];

                            ThIcnntemp2[l] += 输入图像[k] * 卷积核[m * 5 + n, 2];
                            ThIcnntemp3[l] += 输入图像[k] * 卷积核[m * 5 + n, 3];//一个图像用四个卷积核生成4个特征图*8*8
                            //ThIcnntemp[l] += hIcnnna[k] * w1cnn[m * 5 + n, 0];//始终用零组,其他三个组不用
                            为了方便,如此设计202409181006
                            //ThIcnntemp1[l] += hIcnnna[k] * w1cnn[m * 5 + n, 1];

                            //ThIcnntemp2[l] += hIcnnna[k] * w1cnn[m * 5 + n, 2];
                            //ThIcnntemp3[l] += hIcnnna[k] * w1cnn[m * 5 + n, 3];//一个图像用四个卷积核生成4个特征图*8*8
                        }
                }
            //第二步,8*8-》4*4

            for (int i = 0; i < 4; i++)
                for (int j = 0; j < 4; j++)//
                {
                    int l = (i) * 4 + j;
                    double tempb = 0;
                    Point tempPt = new Point();
                    for (int m = 0; m < 2; m++)
                        for (int n = 0; n < 2; n++)//需要记住m,n和序号L,202409181018
                        {
                            int k = (i * 2 + m) * 8 + j * 2 + n;
                            //  tempb += B1[k] * Wb2c[m * 2 + n, l];//取均值?还是取最大值?
                            if (ThIcnntemp[k] > tempb)
                            {
                                tempb = ThIcnntemp[k];//如果是最大值,核就变得没有意义,back怎么办?202409170727
                                tempPt = new Point(n, m);//m是h,n是w,这个要小心用错

                            }
                        }
                    //   C1[l] = (byte)(tempb/4f);
                    Tjilumnna.Add(tempPt);//25个数据,就有25组m,n,序号一一对应
                    ThIcnnna[l] = tempb;//25个数据,通过这个关系,就能找到14*14matrix中去。202409181038
                }
            templlp.Add(Tjilumnna); fanhuituxiang.Add(ThIcnnna);
            for (int i = 0; i < 4; i++)
                for (int j = 0; j < 4; j++)//
                {
                    int l = (i) * 4 + j;
                    double tempb = 0;
                    Point tempPt = new Point();
                    for (int m = 0; m < 2; m++)
                        for (int n = 0; n < 2; n++)//需要记住m,n和序号L,202409181018
                        {
                            int k = (i * 2 + m) * 8 + j * 2 + n;
                            //  tempb += B1[k] * Wb2c[m * 2 + n, l];//取均值?还是取最大值?
                            if (ThIcnntemp1[k] > tempb)
                            {
                                tempb = ThIcnntemp1[k];//如果是最大值,核就变得没有意义,back怎么办?202409170727
                                tempPt = new Point(n, m);//m是h,n是w,这个要小心用错

                            }
                        }
                    //   C1[l] = (byte)(tempb/4f);
                    Tjilumn1na.Add(tempPt);//25个数据,就有25组m,n,序号一一对应
                    ThIcnn1na[l] = tempb;//25个数据,通过这个关系,就能找到14*14matrix中去。202409181038
                }
            templlp.Add(Tjilumn1na); fanhuituxiang.Add(ThIcnn1na);
            for (int i = 0; i < 4; i++)
                for (int j = 0; j < 4; j++)//
                {
                    int l = (i) * 4 + j;
                    double tempb = 0;
                    Point tempPt = new Point();
                    for (int m = 0; m < 2; m++)
                        for (int n = 0; n < 2; n++)//需要记住m,n和序号L,202409181018
                        {
                            int k = (i * 2 + m) * 4 + j * 2 + n;
                            //  tempb += B1[k] * Wb2c[m * 2 + n, l];//取均值?还是取最大值?
                            if (ThIcnntemp2[k] > tempb)
                            {
                                tempb = ThIcnntemp2[k];//如果是最大值,核就变得没有意义,back怎么办?202409170727
                                tempPt = new Point(n, m);//m是h,n是w,这个要小心用错

                            }
                        }
                    //   C1[l] = (byte)(tempb/4f);
                    Tjilumn2na.Add(tempPt);//25个数据,就有25组m,n,序号一一对应
                    ThIcnn2na[l] = tempb;//25个数据,通过这个关系,就能找到14*14matrix中去。202409181038
                }
            templlp.Add(Tjilumn2na); fanhuituxiang.Add(ThIcnn2na);
            for (int i = 0; i < 4; i++)
                for (int j = 0; j < 4; j++)//
                {
                    int l = (i) * 4 + j;
                    double tempb = 0;
                    Point tempPt = new Point();
                    for (int m = 0; m < 2; m++)
                        for (int n = 0; n < 2; n++)//需要记住m,n和序号L,202409181018
                        {
                            int k = (i * 2 + m) * 8 + j * 2 + n;
                            //  tempb += B1[k] * Wb2c[m * 2 + n, l];//取均值?还是取最大值?
                            if (ThIcnntemp3[k] > tempb)
                            {
                                tempb = ThIcnntemp3[k];//如果是最大值,核就变得没有意义,back怎么办?202409170727
                                tempPt = new Point(n, m);//m是h,n是w,这个要小心用错

                            }
                        }
                    //   C1[l] = (byte)(tempb/4f);
                    Tjilumn3na.Add(tempPt);//25个数据,就有25组m,n,序号一一对应
                    ThIcnn3na[l] = tempb;//25个数据,通过这个关系,就能找到14*14matrix中去。202409181038
                }
            templlp.Add(Tjilumn3na); fanhuituxiang.Add(ThIcnn3na);
            return templlp;
        }

下面是backward函数:

 //反向传播函数 
        void backcnn()//应该引入结局b的更新,这样可以加快收敛速度202409140818
        {

          
            for (int i = 0; i < 50; i++)//15
                for (int j = 0; j < 10; j++)//10
                {//q=10
                    double delta = (yOcnn[j] - d[j]) * dsigmoid(yOcnn[j]) * hO2cnn[i];//图像28*28是ling,则标签是0,d[]={1,0,0,0,0,0,0,0,0,0};图像28*28是wu,则标签是5,d[]={0,0,0,0,0,1,0,0,0,0}
                    w2cnn[i, j] -= delta * learnRate;
                }
        
            double[] W3 = new double[50];//
           
            for (int j = 0; j < 50; j++)//15
                for (int k = 0; k < 10; k++)//10
                    W3[j] += (yOcnn[k] - d[k]) * dsigmoid(yOcnn[k]) * w2cnn[j, k];

         
            for (int i = 0; i < 16*16; i++)//256
            
                for (int j = 0; j < 50; j++)//15
                {

                    
                    double delta = dsigmoid(hO2cnn[j]) * (hocnnhebing[i]) * W3[j];//这里要的是系数
                    w12cnn[i, j] -= delta * learnRate;
                }

            //double[] deltacnn = new double[25];//每一个deltacnn,都对应25个14*14中的数据元素,以及一个5*5的卷积核
            //for (int i = 0; i < 25; i++)//25
               double[] deltacnn = new double[16];
              for (int i = 0; i < 16; i++)//25
                for (int j = 0; j < 50; j++)//15
               
                {
                   //这里处理的对不对?直觉对不对?回头验算一下202409191114
                    deltacnn[i] = dsigmoid(hO2cnn[j]) * W3[j] * w12cnn[i, j] * dsigmoid(hocnnhebing[i]);
                }//全连接还是好处理202409200708
            for (int i = 0; i <16; i++)
            {//hebingpos
                Point temppt = 求二维(i, hebingpos[0][i].Y, hebingpos[0][i].X);
                //Point temppt = 求二维(i, jilumn[i].Y, jilumn[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {
                        //   temp = chongfu(hIcnnna, w1cnn, tempbackImg);//相当于原图像12*12
                   //  hebingbackImg[i][j],8*8

                        int newIndex = (temppt.Y + k) * 12 + (temppt.X + z);
                        double delta = hIcnnna[newIndex] * deltacnn[i];//一共25个
                        w1cnn[k * 5 + z, 0] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }

            //另一个卷积核202409191112

            double[] deltacnn1 = new double[16];//每一个deltacnn,都对应25个14*14中的数据元素,以及一个5*5的卷积核
            for (int i = 16; i <32; i++)//25
           
                for (int j = 0; j < 50; j++)//15
                {
                  
                    deltacnn1[i - 16] = dsigmoid(hO2cnn[j]) * W3[j] * w12cnn[i, j] * dsigmoid(hocnnhebing[i]);
                }
            for (int i = 0; i < 16; i++)
            {
                //Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                Point temppt = 求二维(i, hebingpos[1][i].Y, hebingpos[1][i].X);//1代表第二波16个
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {
                        

                        int newIndex = (temppt.Y + k) * 12 + (temppt.X + z);
                        double delta = hIcnnna[newIndex] * deltacnn1[i];//一共25个
                        w1cnn[k * 5 + z, 1] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            //第三个卷积核202409191112

            double[] deltacnn2 = new double[16];//每一个deltacnn,都对应25个14*14中的数据元素,以及一个5*5的卷积核
            for (int i = 32; i < 48; i++)//25
                //for (int j = 0; j < 15; j++)//15
                for (int j = 0; j < 50; j++)//15
                {
                    //deltacnn1[i-25] = dsigmoid(hO2[j]) * W3[j] * w12cnn[i, j] * dsigmoid(hocnn1na[i]);
                    deltacnn2[i - 32] = dsigmoid(hO2cnn[j]) * W3[j] * w12cnn[i, j] * dsigmoid(hocnnhebing[i]);
                }
            for (int i = 0; i < 16; i++)
            {
              //  Point temppt = 求二维(i, jilumn2na[i].Y, jilumn2na[i].X);
                Point temppt = 求二维(i, hebingpos[2][i].Y, hebingpos[2][i].X);//2代表第san波16个
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {                      
                        int newIndex = (temppt.Y + k) * 12 + (temppt.X + z);
                        double delta = hIcnnna[newIndex] * deltacnn2[i];//一共25个
                        w1cnn[k * 5 + z, 2] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            //第四个卷积核202409191112
            double[] deltacnn3 = new double[16];//每一个deltacnn,都对应25个14*14中的数据元素,以及一个5*5的卷积核
            for (int i = 48; i < 64; i++)//25
                //for (int j = 0; j < 15; j++)//15
                for (int j = 0; j < 50; j++)//15
                {
                    //deltacnn1[i-25] = dsigmoid(hO2[j]) * W3[j] * w12cnn[i, j] * dsigmoid(hocnn1na[i]);
                    deltacnn3[i -48] = dsigmoid(hO2cnn[j]) * W3[j] * w12cnn[i, j] * dsigmoid(hocnnhebing[i]);
                }
            for (int i = 0; i < 16; i++)
            {
              //  Point temppt = 求二维(i, jilumn3na[i].Y, jilumn3na[i].X);
                Point temppt = 求二维(i, hebingpos[3][i].Y, hebingpos[3][i].X);//3代表第si波16个
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {                      
                        int newIndex = (temppt.Y + k) * 12 + (temppt.X + z);
                        double delta = hIcnnna[newIndex] * deltacnn3[i];//一共25个
                        w1cnn[k * 5 + z, 3] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            //4个卷积核已经更新完,下面第5个到16
            double[] deltacnn5 = 更新卷积核(W3, 5, hIcnn1na, w1cnn2);//5->0,w1cnn2[25,(5 - 1) % 4]->w1cnn2[25,(6 - 1) % 4]->w1cnn2[25,(7 - 1) % 4]->w1cnn2[25,(8 - 1) % 4]
             double[] deltacnn6=  更新卷积核(W3, 6, hIcnn1na, w1cnn2);
             double[] deltacnn7 = 更新卷积核(W3, 7, hIcnn1na, w1cnn2);
             double[] deltacnn8 = 更新卷积核(W3, 8, hIcnn1na, w1cnn2);

             double[] deltacnn9 = 更新卷积核(W3, 9, hIcnn2na, w1cnn3);//9->0,w1cnn3[25,(9- 1) % 4]->w1cnn3[25,(10 - 1) % 4]->w1cnn3[25,(11- 1) % 4]->w1cnn3[25,(12 - 1) % 4]
             double[] deltacnn10 = 更新卷积核(W3, 10, hIcnn2na, w1cnn3);
             double[] deltacnn11 = 更新卷积核(W3, 11, hIcnn2na, w1cnn3);
             double[] deltacnn12 = 更新卷积核(W3, 12, hIcnn2na, w1cnn3);

             double[] deltacnn13 = 更新卷积核(W3, 13, hIcnn3na, w1cnn4);//卷积核w1cnn4[25,0],5*5的卷积核
             double[] deltacnn14 = 更新卷积核(W3, 14, hIcnn3na, w1cnn4);//卷积核w1cnn4[25,1]
             double[] deltacnn15 = 更新卷积核(W3, 15, hIcnn3na, w1cnn4);//卷积核w1cnn4[25,2]
             double[] deltacnn16 = 更新卷积核(W3, 16, hIcnn3na, w1cnn4);//卷积核w1cnn4[25,3]//hIcnn3na是12*12的图像《-8**《-4*4,backup

            //继续向上,四个卷积核刚好对应一副原始图像,即四个卷积核向上对应一个卷积核28*28-》24*24-》12*12
            //卷积核w1cnn[25,4]对应xI[k] * w576cnn[m * 5 + n, 0]
            //卷积核w1cnn1[25,4]对应xI[k] * w576cnn[m * 5 + n, 1]

            double[] deltacnnX = new double[16];//每一个deltacnnx,都对应25个28*28中的数据元素,以及一个5*5的卷积核
            
            for (int i = 0; i < 16; i++)//16
              
                for (int j = 0; j < 25; j++)//25
               
                {
                    //  int newIndex = (temppt.Y + k) * 12 + (temppt.X + z);
                    //deltacnnX[i] = deltacnn[i] * w1cnn[k * 5 + z, 0] * dsigmoid(hocnnhebing[i]);hIcnnna[newIndex] 
                    deltacnnX[i] = deltacnn[i] * w1cnn[j, 0];//* dsigmoid(hocnnhebing[i]);hIcnnna[newIndex] 
                }//全连接还是好处理202409200708
            for (int i = 0; i < 16; i++)
            {//jilumnna
                Point temppt = 求二维(i, jilumnna[i].Y, jilumnna[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28+ (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnnna[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 0] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }

            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn1[i] * w1cnn[j, 1];//*
                }
            for (int i = 0; i < 16; i++)
            {//jilumnna
                Point temppt = 求二维(i, jilumnna[i].Y, jilumnna[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnnna[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 0] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn2[i] * w1cnn[j, 2];//*
                }
            for (int i = 0; i < 16; i++)
            {//jilumnna
                Point temppt = 求二维(i, jilumnna[i].Y, jilumnna[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnnna[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 0] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn3[i] * w1cnn[j, 3];//*
                }
            for (int i = 0; i < 16; i++)
            {//jilumnna
                Point temppt = 求二维(i, jilumnna[i].Y, jilumnna[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnnna[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 0] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            //第二轮开始
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn5[i] * w1cnn2[j, 0];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn1na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 1] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn6[i] * w1cnn2[j, 1];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn1na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 1] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn7[i] * w1cnn2[j, 2];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn1na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 1] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn8[i] * w1cnn2[j, 3];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn1na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 1] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            //第san轮开始
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn9[i] * w1cnn3[j, 0];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn2na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 2] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn10[i] * w1cnn3[j, 1];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn2na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 2] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn11[i] * w1cnn3[j, 2];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn2na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 2] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn12[i] * w1cnn3[j, 3];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn2na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 2] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            //最后yilun
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn13[i] * w1cnn4[j, 0];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn3na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 3] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn14[i] * w1cnn4[j, 1];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn3na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 3] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn15[i] * w1cnn4[j, 2];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn3na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 3] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
            for (int i = 0; i < 16; i++)//16
                for (int j = 0; j < 25; j++)//25
                {
                    deltacnnX[i] = deltacnn16[i] * w1cnn4[j, 3];//*
                }//jilumn1na
            for (int i = 0; i < 16; i++)
            {//jilumn1na
                Point temppt = 求二维(i, jilumn1na[i].Y, jilumn1na[i].X);
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {      //   int k = (i * 2 + m) * 24 + j * 2 + n;                 
                        int newIndex = (temppt.Y + k) * 28 + (temppt.X + z);
                        double delta = xI[newIndex] * deltacnnX[i] * dsigmoid(hIcnn3na[(temppt.Y / 2 + k) * 12 + temppt.X / 2 + z]);//一共25个
                        w576cnn[k * 5 + z, 3] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430
                    }
            }
        }
        public double[] 更新卷积核(double[] 中间值, int 卷积核序号, double[] 图像, double[,] 卷积核)//=4,=5,卷积核序号从1开始
        {
            //第四个卷积核202409191112
            double[] deltacnn3 = new double[16];//每一个deltacnn,都对应25个14*14中的数据元素,以及一个5*5的卷积核
            int kk = 0;
            int temp=(卷积核序号-1) * 16;
            for (int i = temp; i < temp+ 16; i++)
            {
                for (int j = 0; j < 50; j++)//15
                {                  
                    deltacnn3[kk] = dsigmoid(hO2cnn[j]) * 中间值[j] * w12cnn[i, j] * dsigmoid(hocnnhebing[i]);
                }
                kk++;
            }
            for (int i = 0; i < 16; i++)
            {
                Point temppt = 求二维(i, hebingpos[卷积核序号 - 1][i].Y, hebingpos[卷积核序号 - 1][i].X);//3代表第si波16个
                for (int k = 0; k < 5; k++)
                    for (int z = 0; z < 5; z++)
                    {
                        int newIndex = (temppt.Y + k) * 12 + (temppt.X + z);
                        //double delta = hIcnnna[newIndex] * deltacnn3[i];//一共25个
                        //w1cnn[k * 5 + z, 卷积核序号 - 1] -= delta * learnRate;//只用一个卷积核,核forward就对应上了202409181430

                        //5,6,7,8
                        double delta = 图像[newIndex] * deltacnn3[i];//一共25个
                     //   w1cnn1[k * 5 + z, 卷积核序号 - 1] -= delta * learnRate;
                        卷积核[k * 5 + z, (卷积核序号 - 1) % 4] -= delta * learnRate;
                    }
            }
            return deltacnn3;
        }
        public Point 求二维(int index, int mm, int nn)
        {
            Point rePt = new Point();
            for (int i = 0; i < 5; i++)
                for (int j = 0; j < 5; j++)
                {
                    int n = i * 5 + j;
                    if (index == n)
                    {
                        int h = i * 2 + mm;
                        int w = j * 2 + nn;
                        rePt.X = w;
                        rePt.Y = h;                       
                        i = 5;
                        j = 5;//end 2 for loop;
                    }
                }
            return rePt;
        }

代码虽然复杂,但原理不复杂!编程大多数是注意细节和找bug!


原文地址:https://blog.csdn.net/ganggangwawa/article/details/142773480

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!