AlexNet模型实现(3. C++模型实现)

  • Post author:
  • Post category:其他

对代码进行了一下修改https://github.com/aitazhixin/DL/tree/master/AlexNet,目前的运行效率比较低,准备采用多线程的方式实现一下。

根据原文,所有卷积层和池化层采用了ReLU激活函数,激活函数的导数为0或1(激活值非0时)。第三卷积层和第一、第二全连接层使用了Dropout方式。没有采用原文使用的LRN技术,采用了最大池化。在ImageNet2012数据集中选取了10类图片进行训练,但是迭代的效果不好。贴出代码希望集思广益,希望高手拔刀相助。

一些初始化或者辅助接口:

slqAlexNet::~slqAlexNet()
        {
            if (inRaw)
            {
                delete inRaw;
                inRaw = nullptr;
            }
            deletevar(&mlabel);
            deletevar(&inMap);
            deletevar(&c1Map);
            deletevar(&s1Map);
            deletevar(&c2Map);
            deletevar(&s2Map);
            deletevar(&c3Map);
            deletevar(&c4Map);
            deletevar(&c5Map);
            deletevar(&s5Map);
            deletevar(&f1Map);
            deletevar(&f2Map);
            deletevar(&f3Map);

            deletevar(&c1Conv);
            deletevar(&s1Pool);
            deletevar(&c2Conv);
            deletevar(&s2Pool);
            deletevar(&c3Conv);
            deletevar(&c4Conv);
            deletevar(&c5Conv);
            deletevar(&s5Pool);
            deletevar(&f1Conn);
            deletevar(&f2Conn);
            deletevar(&f3Conn);

            deletevar(&c1Bias);
            deletevar(&s1Bias);
            deletevar(&c2Bias);
            deletevar(&s2Bias);
            deletevar(&c3Bias);
            deletevar(&c4Bias);
            deletevar(&c5Bias);
            deletevar(&s5Bias);
            deletevar(&f1Bias);
            deletevar(&f2Bias);
            deletevar(&f3Bias);

            deletevar(&c1MapDt);
            deletevar(&s1MapDt);
            deletevar(&c2MapDt);
            deletevar(&s2MapDt);
            deletevar(&c3MapDt);
            deletevar(&c4MapDt);
            deletevar(&c5MapDt);
            deletevar(&s5MapDt);
            deletevar(&f1MapDt);
            deletevar(&f2MapDt);
            deletevar(&f3MapDt);

            deletevar(&c1ConvDt);
            deletevar(&s1PoolDt);
            deletevar(&c2ConvDt);
            deletevar(&s2PoolDt);
            deletevar(&c3ConvDt);
            deletevar(&c4ConvDt);
            deletevar(&c5ConvDt);
            deletevar(&s5PoolDt);
            deletevar(&f1ConnDt);
            deletevar(&f2ConnDt);
            deletevar(&f3ConnDt);

            deletevar(&c1BiasDt);
            deletevar(&s1BiasDt);
            deletevar(&c2BiasDt);
            deletevar(&s2BiasDt);
            deletevar(&c3BiasDt);
            deletevar(&c4BiasDt);
            deletevar(&c5BiasDt);
            deletevar(&s5BiasDt);
            deletevar(&f1BiasDt);
            deletevar(&f2BiasDt);
            deletevar(&f3BiasDt);

            deletevar(&c1ConvEDt);
            deletevar(&s1PoolEDt);
            deletevar(&c2ConvEDt);
            deletevar(&s2PoolEDt);
            deletevar(&c3ConvEDt);
            deletevar(&c4ConvEDt);
            deletevar(&c5ConvEDt);
            deletevar(&s5PoolEDt);
            deletevar(&f1ConnEDt);
            deletevar(&f2ConnEDt);
            deletevar(&f3ConnEDt);

            deletevar(&c1BiasEDt);
            deletevar(&s1BiasEDt);
            deletevar(&c2BiasEDt);
            deletevar(&s2BiasEDt);
            deletevar(&c3BiasEDt);
            deletevar(&c4BiasEDt);
            deletevar(&c5BiasEDt);
            deletevar(&s5BiasEDt);
            deletevar(&f1BiasEDt);
            deletevar(&f2BiasEDt);
            deletevar(&f3BiasEDt);
        }

        void slqAlexNet::init()
        {
            initParm();
        }

        void slqAlexNet::CreateConv3Table()
        {
            int oIdx;
            int iIdx;
#define AO true
#define AX false
            for (oIdx = 0; oIdx < c3ConvNum; oIdx++)
            {
                for (iIdx = 0; iIdx < c3ConvDeep; iIdx++)
                {
                    if ((oIdx >= iIdx) && (oIdx < iIdx + c3ConvDeep/2))
                    {
                        CONV3Table[oIdx][iIdx] = AX;
                        continue;
                    }
                    CONV3Table[oIdx][iIdx] = AO;
                }
            }

            for (oIdx = 0; oIdx < s5UnitNum; oIdx++)
            {
                for (iIdx = 0; iIdx < f1UnitNum; iIdx++)
                {
                    if ((oIdx >= iIdx) && (oIdx < iIdx + f1UnitNum/2))
                    {
                        F1Table[oIdx][iIdx] = AX;
                        continue;
                    }
                    F1Table[oIdx][iIdx] = AO;
                }
            }

            for (oIdx = 0; oIdx < f1UnitNum; oIdx++)
            {
                for (iIdx = 0; iIdx < f2UnitNum; iIdx++)
                {
                    if ((oIdx >= iIdx) && (oIdx < iIdx + f2UnitNum/2))
                    {
                        F2Table[oIdx][iIdx] = AX;
                        continue;
                    }
                    F2Table[oIdx][iIdx] = AO;
                }
            }
#undef AO
#undef AX
        }


        void slqAlexNet::deletevar(float **var)
        {
            if (nullptr != *var)
            {
                delete *var;
                *var = nullptr;
            }
        }


        void slqAlexNet::initParm()
        {
            newParam();

            // all weights follow gauss distribution
            uniform_rand(c1Conv, c1ConvUNum, 0.f, 0.f);
            uniform_rand(s1Pool, s1MapNum, 0.f, 0.f);
            uniform_rand(c2Conv, c2ConvUNum, 0.f, 0.f);
            uniform_rand(s2Pool, s2MapNum, 0.f, 0.f);
            uniform_rand(c3Conv, c3ConvUNum, 0.f, 0.f);
            uniform_rand(c4Conv, c4ConvUNum, 0.f, 0.f);
            uniform_rand(c5Conv, c5ConvUNum, 0.f, 0.f);
            uniform_rand(s5Pool, s5MapNum, 0.f, 0.f);
            uniform_rand(f1Conn, f1ConnNum, 0.f, 0.f);
            uniform_rand(f2Conn, f2ConnNum, 0.f, 0.f);
            uniform_rand(f3Conn, f3ConnNum, 0.f, 0.f);

            // 2th, 4th, 5th conv bias set to 1
            std::fill(c2Bias, c2Bias + c2MapNum, 1.0f);
            std::fill(c4Bias, c4Bias + c4MapNum, 1.0f);
            std::fill(c5Bias, c5Bias + c5MapNum, 1.0f);

        }


        void slqAlexNet::newParam()
        {
            mlabel = new float[f3UnitNum]();
            inRaw = new char[inUnitNum]();
            inMap = new float[inUnitNum]();
            c1Map = new float[c1UnitNum]();
            s1Map = new float[s1UnitNum]();
            c2Map = new float[c2UnitNum]();
            s2Map = new float[s2UnitNum]();
            c3Map = new float[c3UnitNum]();
            c4Map = new float[c4UnitNum]();
            c5Map = new float[c5UnitNum]();
            s5Map = new float[s5UnitNum]();
            f1Map = new float[f1UnitNum]();
            f2Map = new float[f2UnitNum]();
            f3Map = new float[f3UnitNum]();

            c1Conv = new float[c1ConvUNum]();
            s1Pool = new float[s1MapNum]();
            c2Conv = new float[c2ConvUNum]();
            s2Pool = new float[s2MapNum]();
            c3Conv = new float[c3ConvUNum]();
            c4Conv = new float[c4ConvUNum]();
            c5Conv = new float[c5ConvUNum]();
            s5Pool = new float[s5MapNum]();
            f1Conn = new float[f1ConnNum]();
            f2Conn = new float[f2ConnNum]();
            f3Conn = new float[f3ConnNum]();

            c1Bias = new float[c1MapNum]();
            s1Bias = new float[s1MapNum]();
            c2Bias = new float[c2MapNum]();
            s2Bias = new float[s2MapNum]();
            c3Bias = new float[c3MapNum]();
            c4Bias = new float[c4MapNum]();
            c5Bias = new float[c5MapNum]();
            s5Bias = new float[s5MapNum]();
            f1Bias = new float[f1UnitNum]();
            f2Bias = new float[f2UnitNum]();
            f3Bias = new float[f3UnitNum]();

            c1MapDt = new float[c1UnitNum]();
            s1MapDt = new float[s1UnitNum]();
            c2MapDt = new float[c2UnitNum]();
            s2MapDt = new float[s2UnitNum]();
            c3MapDt = new float[c3UnitNum]();
            c4MapDt = new float[c4UnitNum]();
            c5MapDt = new float[c5UnitNum]();
            s5MapDt = new float[s5UnitNum]();
            f1MapDt = new float[f1UnitNum]();
            f2MapDt = new float[f2UnitNum]();
            f3MapDt = new float[f3UnitNum]();

            c1ConvDt = new float[c1ConvUNum]();
            s1PoolDt = new float[s1MapNum]();
            c2ConvDt = new float[c2ConvUNum]();
            s2PoolDt = new float[s2MapNum]();
            c3ConvDt = new float[c3ConvUNum]();
            c4ConvDt = new float[c4ConvUNum]();
            c5ConvDt = new float[c5ConvUNum]();
            s5PoolDt = new float[s5MapNum]();
            f1ConnDt = new float[f1ConnNum]();
            f2ConnDt = new float[f2ConnNum]();
            f3ConnDt = new float[f3ConnNum]();


            c1BiasDt = new float[c1MapNum]();
            s1BiasDt = new float[s1MapNum]();
            c2BiasDt = new float[c2MapNum]();
            s2BiasDt = new float[s2MapNum]();
            c3BiasDt = new float[c3MapNum]();
            c4BiasDt = new float[c4MapNum]();
            c5BiasDt = new float[c5MapNum]();
            s5BiasDt = new float[s5MapNum]();
            f1BiasDt = new float[f1UnitNum]();
            f2BiasDt = new float[f2UnitNum]();
            f3BiasDt = new float[f3UnitNum]();

            c1ConvEDt = new float[c1ConvUNum]();
            s1PoolEDt = new float[s1MapNum]();
            c2ConvEDt = new float[c2ConvUNum]();
            s2PoolEDt = new float[s2MapNum]();
            c3ConvEDt = new float[c3ConvUNum]();
            c4ConvEDt = new float[c4ConvUNum]();
            c5ConvEDt = new float[c5ConvUNum]();
            s5PoolEDt = new float[s5MapNum]();
            f1ConnEDt = new float[f1ConnNum]();
            f2ConnEDt = new float[f2ConnNum]();
            f3ConnEDt = new float[f3ConnNum]();

            c1BiasEDt = new float[c1MapNum]();
            s1BiasEDt = new float[s1MapNum]();
            c2BiasEDt = new float[c2MapNum]();
            s2BiasEDt = new float[s2MapNum]();
            c3BiasEDt = new float[c3MapNum]();
            c4BiasEDt = new float[c4MapNum]();
            c5BiasEDt = new float[c5MapNum]();
            s5BiasEDt = new float[s5MapNum]();
            f1BiasEDt = new float[f1UnitNum]();
            f2BiasEDt = new float[f2UnitNum]();
            f3BiasEDt = new float[f3UnitNum]();
        }

        void slqAlexNet::UpgradeNetwork()
        {
            UpdateParameters(c1ConvDt, c1ConvEDt, c1Conv, c1ConvUNum);
            UpdateParameters(c1BiasDt, c1BiasEDt, c1Bias, c1MapNum);

            UpdateParameters(s1PoolDt, s1PoolEDt, s1Pool, s1MapNum);
            UpdateParameters(s1BiasDt, s1BiasEDt, s1Bias, s1MapNum);

            UpdateParameters(c2ConvDt, c2ConvEDt, c2Conv, c2ConvUNum);
            UpdateParameters(c2BiasDt, c2BiasEDt, c2Bias, c2MapNum);

            UpdateParameters(s2PoolDt, s2PoolEDt, s2Pool, s2MapNum);
            UpdateParameters(s2BiasDt, s2BiasEDt, s2Bias, s2MapNum);

            UpdateParameters(c3ConvDt, c3ConvEDt, c3Conv, c3ConvUNum);
            UpdateParameters(c3BiasDt, c3BiasEDt, c3Bias, c3MapNum);

            UpdateParameters(c4ConvDt, c4ConvEDt, c4Conv, c4ConvUNum);
            UpdateParameters(c4BiasDt, c4BiasEDt, c4Bias, c4MapNum);

            UpdateParameters(c5ConvDt, c5ConvEDt, c5Conv, c5ConvUNum);
            UpdateParameters(c5BiasDt, c5BiasEDt, c5Bias, c5MapNum);

            UpdateParameters(s5PoolDt, s5PoolEDt, s5Pool, s5MapNum);
            UpdateParameters(s5BiasDt, s5BiasEDt, s5Bias, s5MapNum);

            UpdateParameters(f1ConnDt, f1ConnEDt, f1Conn, f1ConnNum);
            UpdateParameters(f1BiasDt, f1BiasEDt, f1Bias, f1UnitNum);

            UpdateParameters(f2ConnDt, f2ConnEDt, f2Conn, f2ConnNum);
            UpdateParameters(f2BiasDt, f2BiasEDt, f2Bias, f2UnitNum);

            UpdateParameters(f3ConnDt, f3ConnEDt, f3Conn, f3ConnNum);
            UpdateParameters(f3BiasDt, f3BiasEDt, f3Bias, f3UnitNum);
        }


        void slqAlexNet::UpdateParameters(float *delta, float *Edelta, float *para, int len)
        {
            for (int lIdx = 0; lIdx < len; lIdx++)
            {
                Edelta[lIdx] = 0.9f * Edelta[lIdx] - 0.0005 * Alpha * delta[lIdx];
                para[lIdx] += Edelta[lIdx];
            }
        }

        void slqAlexNet::ConvolutionOpt(float *inPtr, float *outPtr, float *convPtr, float *biPtr, int param[])
        {
            int inMapNo     = param[0];
            int outMapNo    = param[1];
            int inMapH      = param[2];
            int inMapW      = param[3];
            int outMapH     = param[4];
            int outMapW     = param[5];
            int convH       = param[6];
            int convW       = param[7];
            int convStride  = param[8];
            int expand      = param[9];

            int odeepIdx;
            int ideepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;
            int svh;

            int insize = inMapH * inMapW;
            int convsize = inMapNo * convH * convW;
            int convtsor = convH * convW;

            for (odeepIdx = 0; odeepIdx < outMapNo; odeepIdx++)
            {
                for (ohIdx = expand; ohIdx < outMapH - expand; ohIdx++)
                {
                    iod = odeepIdx * outMapH * outMapW + ohIdx * outMapW;
                    for (owIdx = expand; owIdx < outMapW - expand; owIdx++)
                    {
                        float *curmap = outPtr + iod + owIdx;
                        float cur = 0.f;

                        for (ideepIdx = 0; ideepIdx < inMapNo; ideepIdx++)
                        {
                            if ((inMapNo == s2MapNum) && (outMapNo == c3MapNum) && (!CONV3Table[odeepIdx][ideepIdx]))
                                continue;

                            vod = odeepIdx * convsize + ideepIdx * convtsor;
                            svh = ideepIdx * insize + (ohIdx - expand) * convStride * inMapW + (owIdx - expand) * convStride;

                            float *curcv = convPtr + vod;
                            float *curin = inPtr + svh;

                            for (phIdx = 0; phIdx < convH; phIdx++)
                            {
                                for (pwIdx = 0; pwIdx < convW; pwIdx++)
                                {
                                    
                                    cur += *(curcv + phIdx * convW + pwIdx) * (*(curin + phIdx * inMapW + pwIdx));
                                }
                            }
                        }

                        *curmap = cur + *(biPtr + odeepIdx);
                        *curmap = ACTIVATION(*curmap);
                    }
                }
            }

        }

        void slqAlexNet::PoolingOpt(float *inPtr, float *outPtr, float *poolPtr, float *biPtr, int param[])
        {
            int mapNo       = param[0];
            int imapH       = param[1];
            int imapW       = param[2];
            int omapH       = param[3];
            int omapW       = param[4];
            int poolspace   = param[5];
            int poolstride  = param[6];
            int expand      = param[7];

            int deepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;

            for(deepIdx = 0; deepIdx < mapNo; deepIdx++)
            {
                for (ohIdx = expand; ohIdx < omapH - expand; ohIdx++)
                {
                    iod = deepIdx * omapH * omapW + ohIdx * omapW;
                    for (owIdx = expand; owIdx < omapW - expand; owIdx++)
                    {
                        vod = deepIdx * imapH * imapW + (ohIdx - expand) * poolstride * imapW + (owIdx - expand) * poolstride;
                        float *curmap = outPtr + iod + owIdx;
                        float *curin = inPtr + vod;
                        float cur = FLT_MIN;
                        for (phIdx = 0; phIdx < poolspace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolspace; pwIdx++)
                            {
                                //cur += *(curin + phIdx * imapW + pwIdx);
                                cur = cur >(*(curin + phIdx * imapW + pwIdx)) ? cur : (*(curin + phIdx * imapW + pwIdx));
                            }
                        }

                        //*curmap = cur / (poolspace * poolspace) + *(biPtr + deepIdx);
                        *curmap = cur + *(biPtr + deepIdx);
                        *curmap = ACTIVATION(*curmap);
                    }
                }
            }
        }

        void slqAlexNet::SaveParameters()
        {
            ofstream fileStream;

            fileStream.open("alexParams", ofstream::out | ofstream::binary);
            if (!fileStream)
            {
                cout << "Error to create Parameters file" << endl;
                return;
            }

            fileStream.write((char*)c1Conv, c1ConvUNum * sizeof(float));
            fileStream.write((char*)c1BiasDt, c1MapNum * sizeof(float));

            fileStream.write((char*)s1PoolDt, s1MapNum * sizeof(float));
            fileStream.write((char*)s1BiasDt, s1MapNum * sizeof(float));

            fileStream.write((char*)c2ConvDt, c2ConvUNum * sizeof(float));
            fileStream.write((char*)c2BiasDt, c2MapNum * sizeof(float));

            fileStream.write((char*)s2PoolDt, s2MapNum * sizeof(float));
            fileStream.write((char*)s2BiasDt, s2MapNum * sizeof(float));

            fileStream.write((char*)c3ConvDt, c3ConvUNum * sizeof(float));
            fileStream.write((char*)c3BiasDt, c3MapNum * sizeof(float));

            fileStream.write((char*)c4ConvDt, c4ConvUNum * sizeof(float));
            fileStream.write((char*)c4BiasDt, c4MapNum * sizeof(float));

            fileStream.write((char*)c5ConvDt, c5ConvUNum * sizeof(float));
            fileStream.write((char*)c5BiasDt, c5MapNum * sizeof(float));

            fileStream.write((char*)s5PoolDt, s5MapNum * sizeof(float));
            fileStream.write((char*)s5BiasDt, s5MapNum * sizeof(float));

            fileStream.write((char*)f1ConnDt, f1ConnNum * sizeof(float));
            fileStream.write((char*)f1BiasDt, f1UnitNum * sizeof(float));

            fileStream.write((char*)f2ConnDt, f2ConnNum * sizeof(float));
            fileStream.write((char*)f2BiasDt, f2UnitNum * sizeof(float));

            fileStream.write((char*)f3ConnDt, f3ConnNum * sizeof(float));
            fileStream.write((char*)f3BiasDt, f3UnitNum * sizeof(float));

        }


        void slqAlexNet::ReadParameters()
        {
            ifstream fileStream;

            fileStream.open("alexParams", ifstream::in | ifstream::binary);
            if (!fileStream)
            {
                cout << "Error to Open Params file" << endl;
                return;
            }

            fileStream.read((char*)c1Conv, c1ConvUNum * sizeof(float));
            fileStream.read((char*)c1BiasDt, c1MapNum * sizeof(float));

            fileStream.read((char*)s1PoolDt, s1MapNum * sizeof(float));
            fileStream.read((char*)s1BiasDt, s1MapNum * sizeof(float));

            fileStream.read((char*)c2ConvDt, c2ConvUNum * sizeof(float));
            fileStream.read((char*)c2BiasDt, c2MapNum * sizeof(float));

            fileStream.read((char*)s2PoolDt, s2MapNum * sizeof(float));
            fileStream.read((char*)s2BiasDt, s2MapNum * sizeof(float));

            fileStream.read((char*)c3ConvDt, c3ConvUNum * sizeof(float));
            fileStream.read((char*)c3BiasDt, c3MapNum * sizeof(float));

            fileStream.read((char*)c4ConvDt, c4ConvUNum * sizeof(float));
            fileStream.read((char*)c4BiasDt, c4MapNum * sizeof(float));

            fileStream.read((char*)c5ConvDt, c5ConvUNum * sizeof(float));
            fileStream.read((char*)c5BiasDt, c5MapNum * sizeof(float));

            fileStream.read((char*)s5PoolDt, s5MapNum * sizeof(float));
            fileStream.read((char*)s5BiasDt, s5MapNum * sizeof(float));

            fileStream.read((char*)f1ConnDt, f1ConnNum * sizeof(float));
            fileStream.read((char*)f1BiasDt, f1UnitNum * sizeof(float));

            fileStream.read((char*)f2ConnDt, f2ConnNum * sizeof(float));
            fileStream.read((char*)f2BiasDt, f2UnitNum * sizeof(float));

            fileStream.read((char*)f3ConnDt, f3ConnNum * sizeof(float));
            fileStream.read((char*)f3BiasDt, f3UnitNum * sizeof(float));

        }


        void slqAlexNet::RandomBias(float *randVector, int vLen)
        {}


        void slqAlexNet::ProduceLabel()
        {
            int lIdx;
            for (lIdx = 0; lIdx < f3UnitNum; lIdx++)
            {
                if (curLabl == lIdx)
                {
                    mlabel[lIdx] = 0.8f;
                }
                else
                {
                    mlabel[lIdx] = -0.8f;
                }
            }
        }


        void slqAlexNet::RegularMap(char *cmap, float *mapdata)
        {
            int mIdx;
            float maxv = -10.f;
            float minv = 256.f;
            char *curc = cmap;
            float *curmap = mapdata;

            for (mIdx = 0; mIdx < inMapSize; mIdx++)
            {
                float cur = curc[mIdx] < 0 ? (curc[mIdx] + 256.f) : curc[mIdx];
                maxv = cur > maxv ? cur : maxv;
                minv = cur < minv ? cur : minv;
            }

            for (mIdx = 0; mIdx < inMapSize; mIdx++)
            {
                float cur = curc[mIdx] < 0 ? (curc[mIdx] + 256.f) : curc[mIdx];
                curmap[mIdx] = (cur - minv) / (maxv - minv) * 2.f - 1.f;
            }

            maxv = -10.f;
            minv = 256.f;
            curc = cmap + inMapSize;
            curmap = mapdata + inMapSize;
            for (mIdx = 0; mIdx < inMapSize; mIdx++)
            {
                float cur = curc[mIdx] < 0 ? (curc[mIdx] + 256.f) : curc[mIdx];
                maxv = cur > maxv ? cur : maxv;
                minv = cur < minv ? cur : minv;
            }

            for (mIdx = 0; mIdx < inMapSize; mIdx++)
            {
                float cur = curc[mIdx] < 0 ? (curc[mIdx] + 256.f) : curc[mIdx];
                curmap[mIdx] = (cur - minv) / (maxv - minv) * 2.f - 1.f;
            }

            maxv = -10.f;
            minv = 256.f;
            curc = cmap + inMapSize*2;
            curmap = mapdata + inMapSize*2;
            for (mIdx = 0; mIdx < inMapSize; mIdx++)
            {
                float cur = curc[mIdx] < 0 ? (curc[mIdx] + 256.f) : curc[mIdx];
                maxv = cur > maxv ? cur : maxv;
                minv = cur < minv ? cur : minv;
            }

            for (mIdx = 0; mIdx < inMapSize; mIdx++)
            {
                float cur = curc[mIdx] < 0 ? (curc[mIdx] + 256.f) : curc[mIdx];
                curmap[mIdx] = (cur - minv) / (maxv - minv) * 2.f - 1.f;
            }

        }


        void slqAlexNet::uniform_rand(float* src, int len, float min, float max)
        {
            int rIdx = 0;

            for (; rIdx < len; rIdx++)
            {
                src[rIdx] = uniform_rand(min, max);
            }
        }


        float slqAlexNet::uniform_rand(float min, float max)
        {
            static float U, V;
            static int phase = 0;
            float gaussz = 0;

            if (0 == phase)
            {
                U = (rand() + EspCNN) / (RAND_MAX + 1.0f);
                V = (rand() + EspCNN) / (RAND_MAX + 1.0f);

                gaussz = 0.01f * std::sqrt(-2.0f * log(U)) * sin(2.0f * CV_PI * V);
            }
            else
            {
                gaussz = 0.01f * std::sqrt(-2.0f * log(U)) * cos(2.0f * CV_PI * V);
            }

            phase = 1 - phase;
            return gaussz;
        }

训练接口:

        void slqAlexNet::train()
        {
            int epo;
            int ipo = 0;
            float acc = 0.0f;
            ifstream trainStream;
            ifstream trainlabel;

            for (epo = 0; epo < EpochLoop; epo++)
            {
                trainStream.open("imgTrainArray", ifstream::in | ifstream::binary);
                trainlabel.open("imgTrainLabel", ifstream::in | ifstream::binary);
                if ((!trainStream) || (!trainlabel))
                {
                    if (trainStream)
                        trainStream.close();
                    if (trainlabel)
                        trainlabel.close();
                    cout << "There does not exist train data" << endl;
                    return;
                }

                while (EOF != trainStream.peek())
                {
                    trainStream.read(inRaw, sizeof(char)*inUnitNum);
                    trainlabel.read(&curLabl, sizeof(char));

                    //Mat img(227, 227, CV_8UC1);
                    //memcpy((char*)img.data, inRaw, 227*227);
                    //cv::namedWindow("inRaw");
                    //cv::imshow("inRaw", img);
                    //cv::waitKey(0);

                    //memcpy((char*)img.data, inRaw + 227*227, 227 * 227);
                    //cv::namedWindow("inRaw");
                    //cv::imshow("inRaw", img);
                    //cv::waitKey(0);

                    //memcpy((char*)img.data, inRaw + 227*227*2, 227 * 227);
                    //cv::namedWindow("inRaw");
                    //cv::imshow("inRaw", img);
                    //cv::waitKey(0);

                    ProduceLabel();
                    RegularMap(inRaw, inMap);

                    ForwardC1();
                    ForwardS1();
                    ForwardC2();
                    ForwardS2();
                    ForwardC3();
                    ForwardC4();
                    ForwardC5();
                    ForwardS5();
                    ForwardF1();
                    ForwardF2();
                    ForwardF3();

                    BackwardF3();
                    BackwardF2();
                    BackwardF1();
                    BackwardS5();
                    BackwardC5();
                    BackwardC4();
                    BackwardC3();
                    BackwardS2();
                    BackwardC2();
                    BackwardS1();
                    BackwardC1();

                    UpgradeNetwork();

                    ipo++;
                }

                trainlabel.close();
                trainStream.close();

                acc = test();
                cout << "epoch " << epo << " accuracy " << acc << endl;

                if (acc >= AccuracyRate)
                {
                    cout << "Save Params ..." << endl;
                    SaveParameters();
                }
                else if (acc < 0)
                {
                    return;
                }
            }

            if (EpochLoop == epo)
            {
                cout << "End loop, Save Params" << endl;
                SaveParameters();
            }

        }

验证接口:

        float slqAlexNet::test()
        {
            float acc = 0.f;
            float prc = 0.f;
            float maxv = -10.f;
            int maxI;
            char tlabl;
            int mIdx;
            int count = 0;
            ifstream testStream;
            ifstream testlabl;

            testStream.open("imgTestArray", ifstream::in | ifstream::binary);
            testlabl.open("imgTestLabel", ifstream::in | ifstream::binary);
            if ((!testStream) || !testlabl)
            {
                if (testStream)
                    testStream.close();
                if (testlabl)
                    testlabl.close();
                cout << "There does not exist test data" << endl;
                return -1.f;
            }

            while (EOF != testStream.peek())
            {
                count++;

                testStream.read(inRaw, sizeof(char)* inUnitNum);
                testlabl.read(&tlabl, sizeof(char));

                RegularMap(inRaw, inMap);

                ForwardC1();
                ForwardS1();
                ForwardC2();
                ForwardS2();
                ForwardC3();
                ForwardC4();
                ForwardC5();
                ForwardS5();
                ForwardF1();
                ForwardF2();
                ForwardF3();

                for (mIdx = 0; mIdx < f3UnitNum; mIdx++)
                {
                    maxI = f3Map[mIdx] > maxv ? mIdx : maxI;
                    maxv = f3Map[mIdx] > maxv ? f3Map[mIdx] : maxv;
                }

                if (maxI == tlabl)
                    prc += 1;
            }

            testStream.close();
            testlabl.close();

            return (prc / count);
        }

前向运算:

        void slqAlexNet::ForwardC1()
        {
            int params[] = {inMapNum, c1MapNum, inMapHigh, inMapWidth, c1MapHigh, c1MapWidth, c1ConvHigh, c1ConvWidth, c1ConvStride, 0 };

            std::fill(c1Map, c1Map + c1UnitNum, 0.f);
            ConvolutionOpt(inMap, c1Map, c1Conv, c1Bias, params);
        }


        void slqAlexNet::ForwardS1()
        {
            int params[] = {s1MapNum, c1MapHigh, c1MapWidth, s1MapHigh, s1MapWidth, poolSpace, poolStride, 2};

            float tmp[c1UnitNum];
            memcpy((char*)tmp, (char*)c1Map, sizeof(float)*c1UnitNum);
            
            std::fill(s1Map, s1Map + s1UnitNum, 0.f);
            PoolingOpt(c1Map, s1Map, s1Pool, s1Bias, params);
        }


        void slqAlexNet::ForwardC2()
        {
            int params[] = { s1MapNum / 2, c2MapNum / 2, s1MapHigh, s1MapWidth, c2MapHigh, c2MapWidth, c2ConvHigh, c2ConvWidth, c2ConvStride, 0 };

            float tmp[s1UnitNum];
            memcpy((char*)tmp, (char*)s1Map, sizeof(float)*s1UnitNum);

            std::fill(c2Map, c2Map + c2UnitNum, 0.f);
            ConvolutionOpt(s1Map, c2Map, c2Conv, c2Bias, params);

            ConvolutionOpt(s1Map + s1MapNum / 2 * s1MapSize, c2Map + c2MapNum / 2 * c2MapSize, c2Conv + c2MapNum / 2 * c2ConvSize, c2Bias + c2MapNum / 2, params);

        }


        void slqAlexNet::ForwardS2()
        {
            int params[] = { s2MapNum, c2MapHigh, c2MapWidth, s2MapHigh, s2MapWidth, poolSpace, poolStride, 1 };

            float tmp[c2UnitNum];
            memcpy((char*)tmp, (char*)c2Map, sizeof(float)*c2UnitNum);

            std::fill(s2Map, s2Map + s2UnitNum, 0.f);
            PoolingOpt(c2Map, s2Map, s2Pool, s2Bias, params);
        }


        void slqAlexNet::ForwardC3()
        {
            int params[] = { s2MapNum, c3MapNum, s2MapHigh, s2MapWidth, c3MapHigh, c3MapWidth, c3ConvHigh, c3ConvWidth, c3ConvStride, 1 };

            float tmp[s2UnitNum];
            memcpy((char*)tmp, (char*)s2Map, sizeof(float)*s2UnitNum);

            std::fill(c3Map, c3Map + c3UnitNum, 0.f);
            ConvolutionOpt(s2Map, c3Map, c3Conv, c3Bias, params);            

        }


        void slqAlexNet::ForwardC4()
        {
            int params[] = { c3MapNum / 2, c4MapNum / 2, c3MapHigh, c3MapWidth, c4MapHigh, c4MapWidth, c4ConvHigh, c4ConvWidth, c4ConvStride, 1 };

            float tmp[c3UnitNum];
            memcpy((char*)tmp, (char*)c3Map, sizeof(float)*c3UnitNum);

            std::fill(c4Map, c4Map + c4UnitNum, 0.f);
            ConvolutionOpt(c3Map, c4Map, c4Conv, c4Bias, params);

            ConvolutionOpt(c3Map + c3MapNum / 2 * c3MapSize, c4Map + c4MapNum / 2 * c4MapSize, c4Conv + c4MapNum / 2 * c4ConvSize, c4Bias + c4MapNum / 2, params);

        }


        void slqAlexNet::ForwardC5()
        {
            int params[] = { c4MapNum / 2, c5MapNum / 2, c4MapHigh, c4MapWidth, c5MapHigh, c5MapWidth, c5ConvHigh, c5ConvWidth, c5ConvStride, 0 };

            float tmp[c4UnitNum];
            memcpy((char*)tmp, (char*)c4Map, sizeof(float)*c4UnitNum);

            std::fill(c5Map, c5Map + c5UnitNum, 0.f);
            ConvolutionOpt(c4Map, c5Map, c5Conv, c5Bias, params);

            ConvolutionOpt(c4Map + c4MapNum / 2 * c4MapSize, c5Map + c5MapNum / 2 * c5MapSize, c5Conv + c5MapNum / 2 * c5ConvSize, c5Bias + c5MapNum / 2, params);

        }


        void slqAlexNet::ForwardS5()
        {
            int params[] = { s5MapNum, c5MapHigh, c5MapWidth, s5MapHigh, s5MapWidth, poolSpace, poolStride, 0 };

            float tmp[c5UnitNum];
            memcpy((char*)tmp, (char*)c5Map, sizeof(float)*c5UnitNum);

            std::fill(s5Map, s5Map + s5UnitNum, 0.f);
            PoolingOpt(c5Map, s5Map, s5Pool, s5Bias, params);

        }


        void slqAlexNet::ForwardF1()
        {
            int oIdx;
            int iIdx;

            float tmp[s5UnitNum];
            memcpy((char*)tmp, (char*)s5Map, sizeof(float)*s5UnitNum);

            std::fill(f1Map, f1Map + f1UnitNum, 0.f);
            for (oIdx = 0; oIdx < f1UnitNum; oIdx++)
            {
                float *curmap = f1Map + oIdx;
                for (iIdx = 0; iIdx < s5UnitNum; iIdx++)
                {
                    if (!F1Table[iIdx][oIdx])
                        continue;

                    *curmap += s5Map[iIdx] * f1Conn[iIdx * f1UnitNum + oIdx];
                }

                *curmap += f1Bias[oIdx];
                *curmap = ACTIVATION(*curmap);
            }
        }


        void slqAlexNet::ForwardF2()
        {
            int oIdx;
            int iIdx;


            float tmp[f1UnitNum];
            memcpy((char*)tmp, (char*)f1Map, sizeof(float)*f1UnitNum);

            std::fill(f2Map, f2Map + f2UnitNum, 0.f);
            for (oIdx = 0; oIdx < f2UnitNum; oIdx++)
            {
                float *curmap = f2Map + oIdx;
                for (iIdx = 0; iIdx < f1UnitNum; iIdx++)
                {
                    if (!F2Table[iIdx][oIdx])
                        continue;

                    *curmap += f1Map[iIdx] * f2Conn[iIdx * f2UnitNum + oIdx];
                }

                *curmap += f2Bias[oIdx];
                *curmap = ACTIVATION(*curmap);
            }
        }


        void slqAlexNet::ForwardF3()
        {
            int oIdx;
            int iIdx;


            float tmp[f2UnitNum];
            memcpy((char*)tmp, (char*)f2Map, sizeof(float)*f2UnitNum);


            std::fill(f3Map, f3Map + f3UnitNum, 0.f);
            for (oIdx = 0; oIdx < f3UnitNum; oIdx++)
            {
                float *curmap = f3Map + oIdx;
                for (iIdx = 0; iIdx < f2UnitNum; iIdx++)
                {
                    *curmap += f2Map[iIdx] * f3Conn[iIdx * f3UnitNum + oIdx];
                }

                *curmap += f3Bias[oIdx];
                *curmap = ACTIVATION(*curmap);
            }
        }

反馈运算:

        void slqAlexNet::BackwardF3()
        {
            int oIdx;
            int iIdx;

            float tmpf3[f3UnitNum];
            memcpy((char*)tmpf3, (char*)f3Map, sizeof(float)*f3UnitNum);

            for (oIdx = 0; oIdx < f3UnitNum; oIdx++)
            {
                f3MapDt[oIdx] = (f3Map[oIdx] - mlabel[oIdx]) * ACTDEVICE(f3Map[oIdx]);
                f3BiasDt[oIdx] = f3MapDt[oIdx];


                for (iIdx = 0; iIdx < f2UnitNum; iIdx++)
                {
                    f3ConnDt[iIdx*f3UnitNum + oIdx] = f3MapDt[oIdx] * f2Map[iIdx];
                }
            }


        }


        void slqAlexNet::BackwardF2()
        {
            int oIdx;
            int iIdx;

            for (oIdx = 0; oIdx < f2UnitNum; oIdx++)
            {
                float curdt = 0.f;
                for (iIdx = 0; iIdx < f3UnitNum; iIdx++)
                {
                    curdt += f3MapDt[iIdx] * f3Conn[oIdx * f3UnitNum + iIdx];
                }

                f2MapDt[oIdx] = ACTDEVICE(f2Map[oIdx]) * curdt;
                f2BiasDt[oIdx] = f2MapDt[oIdx];


                for (iIdx = 0; iIdx < f1UnitNum; iIdx++)
                {
                    if (!F2Table[iIdx][oIdx])
                        continue;

                    f2ConnDt[iIdx * f2UnitNum + oIdx] = f2MapDt[oIdx] * f1Map[iIdx];
                }
            }


        }


        void slqAlexNet::BackwardF1()
        {
            int oIdx;
            int iIdx;

            for (oIdx = 0; oIdx < f1UnitNum; oIdx++)
            {
                float curdt = 0.f;
                for (iIdx = 0; iIdx < f2UnitNum; iIdx++)
                {
                    if (!F2Table[oIdx][iIdx])
                        continue;

                    curdt += f2MapDt[iIdx] * f2Conn[oIdx * f2UnitNum + iIdx];

                }

                f1MapDt[oIdx] = ACTDEVICE(f1Map[oIdx]) * curdt;
                f1BiasDt[oIdx] = f1MapDt[oIdx];


                for (iIdx = 0; iIdx < s5UnitNum; iIdx++)
                {
                    if (!F1Table[iIdx][oIdx])
                        continue;

                    f1ConnDt[iIdx * f1UnitNum + oIdx] = f1MapDt[oIdx] * s5Map[iIdx];
                }
            }


        }


        void slqAlexNet::BackwardS5()
        {
            int iIdx;
            int iod;

            int odeepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            std::fill(s5BiasDt, s5BiasDt + s5MapNum, 0.f);
            std::fill(s5PoolDt, s5PoolDt + s5MapNum, 0.f);
            for (odeepIdx = 0; odeepIdx < s5MapNum; odeepIdx++)
            {
                for (ohIdx = 0; ohIdx < s5MapHigh; ohIdx++)
                {
                    iod = odeepIdx*s5MapSize + ohIdx * s5MapWidth;
                    for (owIdx = 0; owIdx < s5MapWidth; owIdx++)
                    {
                        float curdt = 0.f;
                        for (iIdx = 0; iIdx < f1UnitNum; iIdx++)
                        {
                            if (!F1Table[iod + owIdx][iIdx])
                                continue;

                            curdt += f1MapDt[iIdx] * f1Conn[(iod + owIdx)*f1UnitNum + iIdx];
                        }

                        s5MapDt[iod + owIdx] = ACTDEVICE(s5Map[iod + owIdx]) * curdt;
                        s5BiasDt[odeepIdx] += s5MapDt[iod + owIdx];

                        float *curin = c5Map + odeepIdx * c5MapSize + ohIdx * poolStride * c5MapWidth + owIdx * poolStride;
                        curdt = FLT_MIN;
                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                curdt = curdt > (*(curin + phIdx * c5MapWidth + pwIdx)) ? curdt : (*(curin + phIdx * c5MapWidth + pwIdx));
                            }
                        }

                        s5PoolDt[odeepIdx] += curdt * s5MapDt[iod + owIdx];
                    }
                }
            }

        }


        void slqAlexNet::BackwardC5()
        {
            int odeepIdx;
            int ideepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;
            int svh;

            std::fill(c5MapDt, c5MapDt + c5UnitNum, 0.f);
            std::fill(c5BiasDt, c5BiasDt + c5MapNum, 0.f);
            std::fill(c5ConvDt, c5ConvDt + c5ConvUNum, 0.f);

            for (odeepIdx = 0; odeepIdx < c5MapNum; odeepIdx++)
            {
                for (ohIdx = 0; ohIdx < s5MapHigh; ohIdx++)
                {
                    for (owIdx = 0; owIdx < s5MapWidth; owIdx++)
                    {
                        iod = odeepIdx * c5MapSize + ohIdx * poolStride * c5MapWidth + owIdx * poolStride;
                        vod = odeepIdx * s5MapSize + ohIdx * s5MapWidth + owIdx;
                        float curmax = FLT_MIN;
                        int hmax = 0;
                        int wmax = 0;
                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                hmax = curmax > c5Map[iod + phIdx * c5MapWidth + pwIdx] ? hmax : phIdx;
                                wmax = curmax > c5Map[iod + phIdx * c5MapWidth + pwIdx] ? wmax : pwIdx;
                                curmax = curmax > c5Map[iod + phIdx * c5MapWidth + pwIdx] ? curmax : c5Map[iod + phIdx * c5MapWidth + pwIdx];
                            }
                        }

                        c5MapDt[iod + hmax * c5MapWidth + wmax] += ACTDEVICE(c5Map[iod + hmax * c5MapWidth + wmax]) * s5Pool[odeepIdx] * s5MapDt[vod];

                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                c5BiasDt[odeepIdx] += c5MapDt[iod + phIdx * c5MapWidth + pwIdx];
                            }
                        }
                    }
                }
            }

            for (odeepIdx = 0; odeepIdx < c5MapNum / 2; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c5ConvDeep; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c5ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c5ConvWidth; pwIdx++)
                        {
                            iod = odeepIdx * c5ConvSize + ideepIdx * c5ConvTensor + phIdx * c5ConvWidth + pwIdx;
                            float *curconv = c5ConvDt + iod;

                            for (ohIdx = 0; ohIdx < c5MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c5MapWidth; owIdx++)
                                {
                                    svh = ideepIdx * c4MapSize + (phIdx + ohIdx * c5ConvStride)*c4MapWidth + (pwIdx + owIdx * c5ConvStride);
                                    vod = odeepIdx * c5MapSize + ohIdx * c5MapWidth + owIdx;
                                    *curconv += c4Map[svh] * c5MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }

            for (odeepIdx = c5MapNum / 2; odeepIdx < c5MapNum; odeepIdx++)
            {
                for (ideepIdx = c5ConvDeep; ideepIdx < c4MapNum; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c5ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c5ConvWidth; pwIdx++)
                        {
                            iod = odeepIdx * c5ConvSize + (ideepIdx - c5ConvDeep) * c5ConvTensor + phIdx * c5ConvWidth + pwIdx;
                            float *curconv = c5ConvDt + iod;

                            for (ohIdx = 0; ohIdx < c5MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c5MapWidth; owIdx++)
                                {
                                    svh = ideepIdx * c4MapSize + (phIdx + ohIdx * c5ConvStride)*c4MapWidth + (pwIdx + owIdx * c5ConvStride);
                                    vod = odeepIdx * c5MapSize + ohIdx * c5MapWidth + owIdx;
                                    *curconv += c4Map[svh] * c5MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }
        }


        void slqAlexNet::BackwardC4()
        {
            int odeepIdx;
            int ideepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;
            int svh;


            std::fill(c4MapDt, c4MapDt + c4UnitNum, 0.f);
            std::fill(c4BiasDt, c4BiasDt + c4MapNum, 0.f);
            std::fill(c4ConvDt, c4ConvDt + c4ConvUNum, 0.f);
            for (odeepIdx = 0; odeepIdx < c4MapNum / 2; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c5MapNum / 2; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c5ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c5ConvWidth; pwIdx++)
                        {
                            svh = ideepIdx * c5ConvSize + odeepIdx * c5ConvTensor + phIdx * c5ConvWidth + pwIdx;
                            for (ohIdx = 0; ohIdx < c5MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c5MapWidth; owIdx++)
                                {
                                    iod = odeepIdx * c4MapSize + (phIdx + ohIdx * c5ConvStride) * c4MapWidth + (pwIdx + owIdx * c5ConvStride);
                                    vod = ideepIdx * c5MapSize + ohIdx * c5MapWidth + owIdx;
                                    c4MapDt[iod] += ACTDEVICE(c4Map[iod]) * c5Conv[svh] * c5MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }

            for (odeepIdx = c4MapNum / 2; odeepIdx < c4MapNum; odeepIdx++)
            {
                for (ideepIdx = c5MapNum / 2; ideepIdx < c5MapNum; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c5ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c5ConvWidth; pwIdx++)
                        {
                            svh = ideepIdx * c5ConvSize + (odeepIdx - c5ConvDeep) * c5ConvTensor + phIdx * c5ConvWidth + pwIdx;
                            for (ohIdx = 0; ohIdx < c5MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c5MapWidth; owIdx++)
                                {
                                    iod = odeepIdx * c4MapSize + (phIdx + ohIdx * c5ConvStride) * c4MapWidth + (pwIdx + owIdx * c5ConvStride);
                                    vod = ideepIdx * c5MapSize + ohIdx * c5MapWidth + owIdx;
                                    c4MapDt[iod] += ACTDEVICE(c4Map[iod]) * c5Conv[svh] * c5MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }

            for (odeepIdx = 0; odeepIdx < c4MapNum / 2; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c4ConvDeep; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c4ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c4ConvWidth; pwIdx++)
                        {
                            iod = odeepIdx * c4ConvSize + ideepIdx * c4ConvTensor + phIdx * c4ConvWidth + pwIdx;
                            for (ohIdx = 1; ohIdx < c4MapHigh - 1; ohIdx++)
                            {
                                for (owIdx = 1; owIdx < c4MapWidth - 1; owIdx++)
                                {
                                    vod = odeepIdx * c4MapSize + ohIdx * c4MapWidth + owIdx;
                                    svh = ideepIdx * c3MapSize + ((ohIdx - 1) * c4ConvStride + phIdx) * c3MapWidth + ((owIdx - 1) * c4ConvStride + pwIdx);
                                    c4BiasDt[odeepIdx] += c4MapDt[vod];
                                    c4ConvDt[iod] += c3Map[svh] * c4MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }

            for (odeepIdx = c4MapNum / 2; odeepIdx < c4MapNum; odeepIdx++)
            {
                for (ideepIdx = c4ConvDeep; ideepIdx < c3MapNum; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c4ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c4ConvWidth; pwIdx++)
                        {
                            iod = odeepIdx * c4ConvSize + (ideepIdx - c4ConvDeep) * c4ConvTensor + phIdx * c4ConvWidth + pwIdx;
                            for (ohIdx = 1; ohIdx < c4MapHigh - 1; ohIdx++)
                            {
                                for (owIdx = 1; owIdx < c4MapWidth - 1; owIdx++)
                                {
                                    vod = odeepIdx * c4MapSize + ohIdx * c4MapWidth + owIdx;
                                    svh = ideepIdx * c3MapSize + ((ohIdx - 1)  * c4ConvStride + phIdx) * c3MapWidth + ((owIdx - 1) * c4ConvStride + pwIdx);
                                    c4BiasDt[odeepIdx] += c4MapDt[vod];
                                    c4ConvDt[iod] += c3Map[svh] * c4MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }

        }


        void slqAlexNet::BackwardC3()
        {
            int odeepIdx;
            int ideepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;
            int svh;

            std::fill(c3MapDt, c3MapDt + c3UnitNum, 0.f);
            std::fill(c3BiasDt, c3BiasDt + c3MapNum, 0.f);
            std::fill(c3ConvDt, c3ConvDt + c3ConvUNum, 0.f);
            for (odeepIdx = 0; odeepIdx < c3MapNum / 2; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c4MapNum / 2; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c4ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c4ConvWidth; pwIdx++)
                        {
                            svh = ideepIdx * c4ConvSize + odeepIdx * c4ConvTensor + phIdx * c4ConvWidth + pwIdx;
                            for (ohIdx = 1; ohIdx < c4MapHigh - 1; ohIdx++)
                            {
                                for (owIdx = 1; owIdx < c4MapWidth - 1; owIdx++)
                                {
                                    iod = odeepIdx * c3MapSize + (phIdx + (ohIdx - 1) * c4ConvStride) * c3MapWidth + (pwIdx + (owIdx - 1) * c4ConvStride);
                                    vod = ideepIdx * c4MapSize + ohIdx * c4MapWidth + owIdx;
                                    c3MapDt[iod] += ACTDEVICE(c3Map[iod]) * c4Conv[svh] * c4MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }

            for (odeepIdx = c3MapNum / 2; odeepIdx < c3MapNum; odeepIdx++)
            {
                for (ideepIdx = c4MapNum / 2; ideepIdx < c4MapNum; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c4ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c4ConvWidth; pwIdx++)
                        {
                            svh = ideepIdx * c4ConvSize + (odeepIdx - c4ConvDeep) * c4ConvTensor + phIdx * c4ConvWidth + pwIdx;
                            for (ohIdx = 1; ohIdx < c4MapHigh - 1; ohIdx++)
                            {
                                for (owIdx = 1; owIdx < c4MapWidth - 1; owIdx++)
                                {
                                    iod = odeepIdx * c3MapSize + (phIdx + (ohIdx - 1) * c4ConvStride) * c3MapWidth + (pwIdx + (owIdx - 1) * c4ConvStride);
                                    vod = ideepIdx * c4MapSize + ohIdx * c4MapWidth + owIdx;
                                    c3MapDt[iod] += ACTDEVICE(c3Map[iod]) * c4Conv[svh] * c4MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }

            for (odeepIdx = 0; odeepIdx < c3MapNum; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c3ConvDeep; ideepIdx++)
                {
                    if (!CONV3Table[odeepIdx][ideepIdx])
                        continue;

                    for (phIdx = 0; phIdx < c3ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c3ConvWidth; pwIdx++)
                        {
                            iod = odeepIdx * c3ConvSize + ideepIdx * c3ConvTensor + phIdx * c3ConvWidth + pwIdx;
                            for (ohIdx = 1; ohIdx < c3MapHigh - 1; ohIdx++)
                            {
                                for (owIdx = 1; owIdx < c3MapWidth - 1; owIdx++)
                                {
                                    vod = odeepIdx * c3MapSize + ohIdx * c3MapWidth + owIdx;
                                    svh = ideepIdx * s2MapSize + ((ohIdx - 1) * c3ConvStride + phIdx) * s2MapWidth + ((owIdx - 1) * c3ConvStride + pwIdx);
                                    c3BiasDt[odeepIdx] += c3MapDt[vod];
                                    c3ConvDt[iod] += c3MapDt[vod] * s2Map[svh];
                                }
                            }
                        }
                    }
                }
            }
        }


        void slqAlexNet::BackwardS2()
        {
            int odeepIdx;
            int ideepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;
            int svh;

            std::fill(s2MapDt, s2MapDt + s2UnitNum, 0.f);
            std::fill(s2BiasDt, s2BiasDt + s2MapNum, 0.f);
            std::fill(s2PoolDt, s2PoolDt + s2MapNum, 0.f);
            for (odeepIdx = 0; odeepIdx < s2MapNum; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c3MapNum; ideepIdx++)
                {
                    if (!CONV3Table[ideepIdx][odeepIdx])
                        continue;

                    for (phIdx = 0; phIdx < c3ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c3ConvWidth; pwIdx++)
                        {
                            svh = ideepIdx * c3ConvSize + odeepIdx * c3ConvTensor + phIdx * c3ConvWidth + pwIdx;
                            for (ohIdx = 1; ohIdx < c3MapHigh - 1; ohIdx++)
                            {
                                for (owIdx = 1; owIdx < c3MapWidth - 1; owIdx++)
                                {
                                    iod = odeepIdx * s2MapSize + (phIdx + (ohIdx - 1) * c3ConvStride) * s2MapWidth + (pwIdx + (owIdx - 1) * c3ConvStride);
                                    vod = ideepIdx * c3MapSize + ohIdx * c3MapWidth + owIdx;
                                    s2MapDt[iod] += ACTDEVICE(s2Map[iod]) * c3Conv[svh] * c3MapDt[vod];
                                }
                            }
                        }
                    }
                }
            }


            for (odeepIdx = 0; odeepIdx < s2MapNum; odeepIdx++)
            {
                for (ohIdx = 1; ohIdx < s2MapHigh - 1; ohIdx++)
                {
                    iod = odeepIdx*s2MapSize + ohIdx * s2MapWidth;
                    for (owIdx = 1; owIdx < s2MapWidth - 1; owIdx++)
                    {
                        float *curin = c2Map + odeepIdx * c2MapSize + (ohIdx - 1) * poolStride * c2MapWidth + (owIdx - 1) * poolStride;
                        float curdt = FLT_MIN;
                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                curdt = curdt >(*(curin + phIdx * c2MapWidth + pwIdx)) ? curdt : (*(curin + phIdx * c2MapWidth + pwIdx));
                            }
                        }

                        s2BiasDt[odeepIdx] += s2MapDt[iod + owIdx];
                        s2PoolDt[odeepIdx] += curdt * s2MapDt[iod + owIdx];

                    }
                }

            }
        }


        void slqAlexNet::BackwardC2()
        {
            int odeepIdx;
            int ideepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;
            int svh;

            std::fill(c2MapDt, c2MapDt + c2UnitNum, 0.f);
            std::fill(c2BiasDt, c2BiasDt + c2MapNum, 0.f);
            std::fill(c2ConvDt, c2ConvDt + c2ConvUNum, 0.f);
            for (odeepIdx = 0; odeepIdx < c2MapNum; odeepIdx++)
            {
                for (ohIdx = 1; ohIdx < s2MapHigh - 1; ohIdx++)
                {
                    for (owIdx = 1; owIdx < s2MapWidth - 1; owIdx++)
                    {
                        iod = odeepIdx * c2MapSize + (ohIdx - 1) * poolStride * c2MapWidth + (owIdx - 1) * poolStride;
                        vod = odeepIdx * s2MapSize + ohIdx * s2MapWidth + owIdx;
                        float curmax = FLT_MIN;
                        int hmax = 0;
                        int wmax = 0;
                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                hmax = curmax > c2Map[iod + phIdx * c2MapWidth + pwIdx] ? hmax : phIdx;
                                wmax = curmax > c2Map[iod + phIdx * c2MapWidth + pwIdx] ? wmax : pwIdx;
                                curmax = curmax > c2Map[iod + phIdx * c2MapWidth + pwIdx] ? curmax : c2Map[iod + phIdx * c2MapWidth + pwIdx];
                            }
                        }

                        c2MapDt[iod + hmax * c2MapWidth + wmax] += ACTDEVICE(c2Map[iod + phIdx * c2MapWidth + pwIdx]) * s2Pool[odeepIdx] * s2MapDt[vod];

                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                c2BiasDt[odeepIdx] += c2MapDt[iod + phIdx * c2MapWidth + pwIdx];
                            }
                        }
                    }
                }
            }

            for (odeepIdx = 0; odeepIdx < c2MapNum / 2; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c2ConvDeep; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c2ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c2ConvWidth; pwIdx++)
                        {
                            iod = odeepIdx * c2ConvSize + ideepIdx * c2ConvTensor + phIdx * c2ConvWidth + pwIdx;
                            for (ohIdx = 0; ohIdx < c2MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c2MapWidth; owIdx++)
                                {
                                    vod = odeepIdx * c2MapSize + ohIdx * c2MapWidth + owIdx;
                                    svh = ideepIdx * s1MapSize + (ohIdx * c2ConvStride + phIdx) * s1MapWidth + (owIdx * c2ConvStride + pwIdx);
                                    c2ConvDt[iod] += c2MapDt[vod] * s1Map[svh];

                                }
                            }
                        }
                    }
                }
            }

            for (odeepIdx = c2MapNum / 2; odeepIdx < c2MapNum; odeepIdx++)
            {
                for (ideepIdx = c2ConvDeep; ideepIdx < s1MapNum; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c2ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c2ConvWidth; pwIdx++)
                        {
                            iod = odeepIdx * c2ConvSize + (ideepIdx - c2ConvDeep) * c2ConvTensor + phIdx * c2ConvWidth + pwIdx;
                            for (ohIdx = 0; ohIdx < c2MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c2MapWidth; owIdx++)
                                {
                                    vod = odeepIdx * c2MapSize + ohIdx * c2MapWidth + owIdx;
                                    svh = ideepIdx * s1MapSize + (ohIdx * c2ConvStride + phIdx) * s1MapWidth + (owIdx * c2ConvStride + pwIdx);
                                    c2ConvDt[iod] += c2MapDt[vod] * s1Map[svh];

                                }
                            }
                        }
                    }
                }
            }
        }


        void slqAlexNet::BackwardS1()
        {
            int odeepIdx;
            int ideepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;
            int svh;

            std::fill(s1MapDt, s1MapDt + s1UnitNum, 0.f);
            std::fill(s1BiasDt, s1BiasDt + s1MapNum, 0.f);
            std::fill(s1PoolDt, s1PoolDt + s1MapNum, 0.f);
            for (odeepIdx = 0; odeepIdx < s1MapNum / 2; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c2ConvDeep; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c2ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c2ConvWidth; pwIdx++)
                        {
                            vod = odeepIdx * c2ConvSize + ideepIdx * c2ConvTensor + phIdx * c2ConvHigh + pwIdx;
                            for (ohIdx = 0; ohIdx < c2MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c2MapWidth; owIdx++)
                                {
                                    iod = odeepIdx * s1MapSize + (ohIdx * c2ConvStride + phIdx) * s1MapWidth + (owIdx * c2ConvStride + pwIdx);
                                    svh = ideepIdx * c2MapSize + ohIdx * c2MapWidth + owIdx;
                                    s1MapDt[iod] += ACTDEVICE(s1Map[iod]) * c2Conv[vod] * c2MapDt[svh];
                                }
                            }
                        }
                    }
                }
            }


            for (odeepIdx = s1MapNum / 2; odeepIdx < s1MapNum; odeepIdx++)
            {
                for (ideepIdx = 0; ideepIdx < c2ConvDeep; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c2ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c2ConvWidth; pwIdx++)
                        {
                            vod = odeepIdx * c2ConvSize + ideepIdx * c2ConvTensor + phIdx * c2ConvHigh + pwIdx;
                            for (ohIdx = 0; ohIdx < c2MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c2MapWidth; owIdx++)
                                {
                                    iod = odeepIdx * s1MapSize + (ohIdx * c2ConvStride + phIdx) * s1MapWidth + (owIdx * c2ConvStride + pwIdx);
                                    svh = (ideepIdx + c2ConvDeep) * c2MapSize + ohIdx * c2MapWidth + owIdx;
                                    s1MapDt[iod] += ACTDEVICE(s1Map[iod]) * c2Conv[vod] * c2MapDt[svh];
                                }
                            }
                        }
                    }
                }
            }


            for (odeepIdx = 0; odeepIdx < s1MapNum; odeepIdx++)
            {
                for (ohIdx = 2; ohIdx < s1MapHigh - 2; ohIdx++)
                {
                    iod = odeepIdx*s1MapSize + ohIdx * s1MapWidth;
                    for (owIdx = 2; owIdx < s1MapWidth - 2; owIdx++)
                    {

                        float *curin = c1Map + odeepIdx * c1MapSize + (ohIdx - 2) * poolStride * c1MapWidth + (owIdx - 2) * poolStride;
                        float curdt = FLT_MIN;
                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                curdt = curdt > (*(curin + phIdx * c1MapWidth + pwIdx)) ? curdt : (*(curin + phIdx * c1MapWidth + pwIdx));
                            }

                        }

                        s1BiasDt[odeepIdx] += s1MapDt[iod + owIdx];
                        s1PoolDt[odeepIdx] += curdt * s1MapDt[iod + owIdx];
                    }
                }
            }

        }


        void slqAlexNet::BackwardC1()

        {
            int odeepIdx;
            int ideepIdx;
            int ohIdx;
            int owIdx;
            int phIdx;
            int pwIdx;

            int iod;
            int vod;
            int svh;

            std::fill(c1MapDt, c1MapDt + c1UnitNum, 0.f);
            std::fill(c1BiasDt, c1BiasDt + c1MapNum, 0.f);
            std::fill(c1ConvDt, c1ConvDt + c1ConvUNum, 0.f);
            for (odeepIdx = 0; odeepIdx < c1MapNum; odeepIdx++)
            {
                for (ohIdx = 2; ohIdx < s1MapHigh - 2; ohIdx++)
                {
                    for (owIdx = 2; owIdx < s1MapWidth - 2; owIdx++)
                    {
                        iod = odeepIdx * c1MapSize + (ohIdx - 2) * poolStride * c1MapWidth + (owIdx - 2) * poolStride;
                        vod = odeepIdx * s1MapSize + ohIdx * s1MapWidth + owIdx;
                        float curmax = FLT_MIN;
                        int hmax = 0;
                        int wmax = 0;

                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                hmax = curmax > c1Map[iod + phIdx * c1MapWidth + pwIdx] ? hmax : phIdx;
                                wmax = curmax > c1Map[iod + phIdx * c1MapWidth + pwIdx] ? wmax : pwIdx;
                                curmax = curmax > c1Map[iod + phIdx * c1MapWidth + pwIdx] ? curmax : c1Map[iod + phIdx * c1MapWidth + pwIdx];
                            }
                        }

                        c1MapDt[iod + hmax * c1MapWidth + wmax] += ACTDEVICE(c1Map[iod + hmax * c1MapWidth + wmax]) * s1Pool[odeepIdx] * s1MapDt[vod];

                        for (phIdx = 0; phIdx < poolSpace; phIdx++)
                        {
                            for (pwIdx = 0; pwIdx < poolSpace; pwIdx++)
                            {
                                c1BiasDt[odeepIdx] += c1MapDt[iod + phIdx * c1MapWidth + pwIdx];
                            }
                        }
                    }
                }

                for (ideepIdx = 0; ideepIdx < c1ConvDeep; ideepIdx++)
                {
                    for (phIdx = 0; phIdx < c1ConvHigh; phIdx++)
                    {
                        for (pwIdx = 0; pwIdx < c1ConvWidth; pwIdx++)
                        {
                            vod = odeepIdx * c1ConvSize + ideepIdx * c1ConvTensor + phIdx * c1ConvWidth + pwIdx;

                            for (ohIdx = 0; ohIdx < c1MapHigh; ohIdx++)
                            {
                                for (owIdx = 0; owIdx < c1MapWidth; owIdx++)
                                {
                                    iod = ideepIdx * inMapSize + (phIdx + ohIdx * c1ConvStride) * inMapWidth + (pwIdx + owIdx * c1ConvStride);
                                    svh = odeepIdx * c1MapSize + ohIdx * c1MapWidth + owIdx;
                                    c1ConvDt[vod] += inMap[iod] * c1MapDt[svh];
                                }
                            }
                        }
                    }

                }

            }


        }




版权声明:本文为aitazhixin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。