使用java实现CNN的实战

使用java实现CNN的实战

1、要实现CNN,其中包括 卷积、池化(下采样)、分类器、优化方法、分类器、反向传播

2、可以使用一个三维数组来表示一张图片(通道、行、列)

3、卷积,卷积的方式有三种:valid,full,same,在CNN中我们用到了两种:前向传播时,使用valid,反向传播时使  

full:假设我们的图片大小为 resourceImage:4*4,卷积核大小为  kernelSize:2*2,

    1> 前向传播时,valid 卷积的得到的resultImage:3*3 (4-2+1=3,假设stride为 1,pad :0)

    

case "valid" :
{
    resultImage = new double[inputImage.length-kernel.length+1][inputImage[0].length-kernel[0].length+1];
    for(int i=0;i<inputImage.length-kernel.length+1;i++)
    {
        for(int j=0;j<inputImage[0].length-kernel[0].length+1;j++)
        {
            int[] row={i,i+kernel.length-1};
            int[] col={j,j+kernel[0].length-1};
            double [][] regionImage= arroperation.copy2(inputImage,row,col);
            resultImage[i][j]=arroperation.product(regionImage,kernel);
        }
    }
    break;
}

其中 copy2 为我自己定义的函数,指的是复制二维数组指定区域的元素到一个新的二维数组

      product 也是我自己定义的函数,作用是:两个相同大小的二维数组对应位置成绩求和;

     2> 反向传播时,使用 full , (前向传播时 resourceImage:4*4, kernelSize:2*2, resultImage 3*3)

         反向传播,resourceImage:3*3, kernelSize:2*2, resultImage 4*4

我们可以使用补零的方式,使resourceImage 3*3 ------> tempImage 5*5

        然后使用 valid 卷积方式, tempImage:4*4, kernelSize:2*2, resultImage 3*3

case "full":
{
    resultImage = new double[inputImage.length+inputImage[0].length-1][inputImage[0].length+kernel[0].length-1];
    double [][] tempImage=new double[inputImage.length+kernel.length-1][inputImage[0].length+kernel[0].length-1];
    for(int i=0;i<inputImage.length+2*kernel.length-2;i++)
    {
        for (int j=0;j<inputImage[0].length+2*kernel[0].length-2;j++)
        {
            tempImage[i][j]=0;
        }
    }
    for(int i=0;i<inputImage.length;i++)
    {
        for(int j=0;j<inputImage[0].length;j++)
        {
            tempImage[i+kernel.length-1][j+kernel[0].length-1]=inputImage[i][j];
        }
    }
    resultImage = convolutional(tempImage,kernel,"valid");
}

4、pooling 的方式有MAX ,Average , L1 等几种方式,在这里我只实现了,MAX 和 Average

     1> MAX 

case "MAX":
{
    for(int i=0;i<resultImage.length;i++)
    {
        for(int j=0;j<resultImage[0].length;j++)
        {
            int num=0;
            for(int m=0;m<poolingSize[0];m++)
            {
                for(int n=0;n<poolingSize[1];n++)
                {
                    tempArray[num]=resourceImage[i*poolingSize[0]+m][j*poolingSize[0]+n];
                    num=num+1;
                }
            }
            Arrays.sort(tempArray);
            resultImage[i][j]=tempArray[tempArray.length-1];

        }
    }
}
    break;

这里用到了一个Java自带的一维数组排序的方法,可以自动使数组从小到大排列

Arrays.sort(tempArray);

2> Average

case "Average":
{
    double sum=0; // represent the sum of the element in subsampling area
    for(int i=0;i<resultImage.length;i++)
    {
        for(int j=0;j<resultImage[0].length;j++)
        {
            for(int m=0;m<poolingSize[0];m++)
            {
                for(int n=0;n<poolingSize[1];n++)
                {
                   sum=sum+resourceImage[i*poolingSize[0]+m][j*poolingSize[0]+n];
                }
            }
            resultImage[i][j]=sum/poolingSize[0]*poolingSize[1];

        }
    }
}
break;
原文地址:https://www.cnblogs.com/timssd/p/6045482.html