神经网络

本文关键字:神经网络 | 更新日期: 2023-09-27 18:29:36

我来这里寻找关于我现在正在编写的程序的一般提示。

目标是:使用神经网络程序识别3个字母[D,O,M](或者,如果我输入了除这3个字母以外的任何字母,则显示"未识别")。

到目前为止,我拥有的是:

我的单神经元课程

public class neuron
{
    double[] weights;
    public neuron()
    {
        weights = null;
    }
    public neuron(int size)
    {
        weights = new double[size + 1];
        Random r = new Random();
        for (int i = 0; i <= size; i++)
        {
            weights[i] = r.NextDouble() / 5 - 0.1;
        }
    }
    public double output(double[] wej)
    {
        double s = 0.0;
        for (int i = 0; i < weights.Length; i++) s += weights[i] * wej[i];
        s = 1 / (1 + Math.Exp(s));
        return s;
    }
}

层的一个类:

public class layer 
{
    neuron[] tab;
    public layer()
    {
        tab = null;
    }
    public layer(int numNeurons, int numInputs)
    {
        tab = new neuron[numNeurons];
        for (int i = 0; i < numNeurons; i++)
        {
            tab[i] = new neuron(numInputs);
        }
    }
    public double[] compute(double[] wejscia)
    {
        double[] output = new double[tab.Length + 1];
        output[0] = 1;
        for (int i = 1; i <= tab.Length; i++)
        {
            output[i] = tab[i - 1].output(wejscia);
        }
        return output;
    }
}

最后是一个网络类

public class network
{
    layer[] layers = null;
    public network(int numLayers, int numInputs, int[] npl)
    {
        layers = new layer[numLayers];
        for (int i = 0; i < numLayers; i++)
        {
            layers[i] = new layer(npl[i], (i == 0) ? numInputs : (npl[i - 1]));
        }
    }
    double[] compute(double[] inputs)
    {
        double[] output = layers[0].compute(inputs);
        for (int i = 1; i < layers.Length; i++)
        {
            output = layers[i].compute(output);
        }
        return output;
    }
}

现在我选择的算法是:

我有一个200x200大小的图片框,你可以在里面画一个字母(或者从jpg文件中读一个)。

然后我将其转换为我的第一个数组(获得整个图片)和第二个数组(剪切周围的非相关背景),如下所示:

Bitmap bmp2 = new Bitmap(this.pictureBox1.Image);
        int[,] binaryfrom = new int[bmp2.Width, bmp2.Height];
        int minrow=0, maxrow=0, mincol=0, maxcol=0;
        for (int i = 0; i < bmp2.Height; i++)
        {
            for (int j = 0; j < bmp2.Width; j++)
            {
                if (bmp2.GetPixel(j, i).R == 0)
                {
                    binaryfrom[i, j] = 1;
                    if (minrow == 0) minrow = i;
                    if (maxrow < i) maxrow = i;
                    if (mincol == 0) mincol = j;
                    else if (mincol > j) mincol = j;
                    if (maxcol < j) maxcol = j;
                }
                else
                {
                    binaryfrom[i, j] = 0;
                }
            }
        }

        int[,] boundaries = new int[binaryfrom.GetLength(0)-minrow-(binaryfrom.GetLength(0)-(maxrow+1)),binaryfrom.GetLength(1)-mincol-(binaryfrom.GetLength(1)-(maxcol+1))];
        for(int i = 0; i < boundaries.GetLength(0); i++)
        {
            for(int j = 0; j < boundaries.GetLength(1); j++)
            {
                boundaries[i, j] = binaryfrom[i + minrow, j + mincol];
            }
        }

并将其转换为我的最终12x8数组(我知道我可以将其缩短一点,但我想让每一步都处于不同的循环中,这样我就可以更容易地看到哪里出了问题(如果有什么问题的话)):

int[,] finalnet = new int[12, 8];
        int k = 1;
        int l = 1;
        for (int i = 0; i < finalnet.GetLength(0); i++)
        {
            for (int j = 0; j < finalnet.GetLength(1); j++)
            {
                finalnet[i, j] = 0;
            }
        }
        while (k <= finalnet.GetLength(0))
            {
                while (l <= finalnet.GetLength(1))
                {
                    for (int i = (int)(boundaries.GetLength(0) / finalnet.GetLength(0)) * (k - 1); i < (int)(boundaries.GetLength(0) / finalnet.GetLength(0)) * k; i++)
                    {
                        for (int j = (int)(boundaries.GetLength(1) / finalnet.GetLength(1)) * (l - 1); j < (int)(boundaries.GetLength(1) / finalnet.GetLength(1)) * l; j++)
                        {
                            if (boundaries[i, j] == 1) finalnet[k-1, l-1] = 1;
                        }
                    }
                    l++;
                }
                l = 1;
                k++;
            }
        int a = boundaries.GetLength(0);
        int b = finalnet.GetLength(1);
       if((a%b) != 0){
            k = 1;
            while (k <= finalnet.GetLength(1))
            {
                for (int i = (int)(boundaries.GetLength(0) / finalnet.GetLength(0)) * finalnet.GetLength(0); i < boundaries.GetLength(0); i++)
                {
                    for (int j = (int)(boundaries.GetLength(1) / finalnet.GetLength(1)) * (k - 1); j < (int)(boundaries.GetLength(1) / finalnet.GetLength(1)) * k; j++)
                    {
                        if (boundaries[i, j] == 1) finalnet[finalnet.GetLength(0) - 1, k - 1] = 1;
                    }
                }
                k++;
            }
        }
        if (boundaries.GetLength(1) % finalnet.GetLength(1) != 0)
        {
            k = 1;
            while (k <= finalnet.GetLength(0))
            {
                for (int i = (int)(boundaries.GetLength(0) / finalnet.GetLength(0)) * (k - 1); i < (int)(boundaries.GetLength(0) / finalnet.GetLength(0)) * k; i++)
                {
                    for (int j = (int)(boundaries.GetLength(1) / finalnet.GetLength(1)) * finalnet.GetLength(1); j < boundaries.GetLength(1); j++)
                    {
                        if (boundaries[i, j] == 1) finalnet[k - 1, finalnet.GetLength(1) - 1] = 1;
                    } 
                }
                k++;
            }
            for (int i = (int)(boundaries.GetLength(0) / finalnet.GetLength(0)) * finalnet.GetLength(0); i < boundaries.GetLength(0); i++)
            {
                for (int j = (int)(boundaries.GetLength(1) / finalnet.GetLength(1)) * finalnet.GetLength(1); j < boundaries.GetLength(1); j++)
                {
                    if (boundaries[i, j] == 1) finalnet[finalnet.GetLength(0) - 1, finalnet.GetLength(1) - 1] = 1;
                }
            }
        }

结果是一个由0和1组成的12x8(我可以在代码中更改它以从一些表单控件中获得它)数组,其中1形成了您绘制的字母的大致形状。

现在我的问题是:这是一个正确的算法吗?我的功能是吗

1/(1+Math.Exp(x))

这里用的好吗?拓扑应该是什么?2层或3层,如果是3层,隐藏层中有多少神经元?我有96个输入(finalnet数组的每个字段),所以我应该在第一层中也取96个神经元吗?我应该在最后一层有3个神经元还是4个(考虑到"未识别"的情况),还是没有必要?

谢谢你的帮助。

编辑:哦,我忘了补充,我要用反向传播算法训练我的网络。

神经网络

  1. 使用反向传播方法,您可能需要至少4层才能获得准确的结果。1个输入层、2个中间层和一个输出层。

  2. 12*8矩阵太小(可能会导致数据丢失,从而导致完全失败)-试试16*16。如果你想缩小尺寸,那么你必须进一步剥离黑色像素的外层。

  3. 考虑用你的参考人物来训练人际网络。

  4. 请记住,您必须再次将输出反馈给输入层,并对其进行多次迭代。

前一段时间,我创建了一个神经网络来识别数字0-9(python,对不起),所以根据我的(短期)经验,3层可以,96/50/3拓扑可能会做得很好。至于输出层,这是您的选择;当输入图像不是D、O或M时,您可以反向传播所有0,也可以使用第四个输出神经元来指示字母未被识别。我认为第一个选项是最好的,因为它更简单(训练时间更短,调试网络的问题更少…),你只需要应用一个阈值,在这个阈值下你将图像归类为"未识别"
我还使用了sigmoid作为激活函数,我没有尝试其他函数,但它有效:)