神经网络无法正常工作(C#,反向传播,字母识别)

时间:2019-01-29 20:51:35

标签: c# neural-network backpropagation

我试图从头开始在C#中使用反向传播实现神经网络,但是它不能正常工作。我使用this数据集进行学习。代码:

    private void learningFunc()
    {
        string[] files;
        System.IO.FileStream fs;
        unsafe
        {
            for (int s = 0; s < letters; s++)
            {
                UpdateProgress(s);
                expectedResult[s] = 1.0;
                char symbol = (char)(s + 65);
                files = System.IO.Directory.GetFiles(dataset_path + Convert.ToString(symbol));
                foreach (string fileName in files.Take(500))
                {
                    fs = new System.IO.FileStream(fileName, System.IO.FileMode.Open);
                    bmp = (Bitmap)System.Drawing.Bitmap.FromStream(fs);
                    fs.Close();
                    fs.Dispose();
                    BitmapData bData = bmp.LockBits(new Rectangle(0, 0, 28, 28), ImageLockMode.ReadWrite, bmp.PixelFormat);
                    byte* scan0 = (byte*)bData.Scan0.ToPointer();
                    //Bitmap bmp123 = new Bitmap(28, 28);
                    for (int i = 0; i < pixels; ++i)
                    {
                        byte* data = scan0 + i * 4;
                        l0[i] = data[0] / 255.0;
                        //bmp123.SetPixel(i %28, i / 28, Color.FromArgb((int)Math.Floor(l0[i] * 255), (int)Math.Floor(l0[i] * 255), (int)Math.Floor(l0[i] * 255)));
                    }
                    //pictureBox2.Image = bmp123;
                    bmp.UnlockBits(bData);
                    bmp.Dispose();
                    for (int i = 0; i < hidden_layer; ++i)
                    {
                        l1_in[i] = synapse0_bias[i];
                        for (int j = 0; j < pixels; ++j)
                        {
                            l1_in[i] += l0[j] * synapse0[j, i];
                        }
                        l1[i] = sigmoid(l1_in[i]);
                    }
                    for (int i = 0; i < letters; ++i)
                    {
                        l2_in[i] = synapse1_bias[i];
                        for (int j = 0; j < hidden_layer; ++j)
                        {
                            l2_in[i] += l1[j] * synapse1[j, i];
                        }
                        l2[i] = sigmoid(l2_in[i]);
                        l2_err[i] = (expectedResult[i] - l2[i]) * sigmoid_derivative(l2_in[i]);
                    }
                    for (int i = 0; i < letters; ++i)
                    {
                        for (int j = 0; j < hidden_layer; ++j)
                        {
                            synapse1_delta[j, i] = teaching_velocity * l2_err[i] * l1[j];
                        }
                        synapse1_bias_delta[i] = teaching_velocity * l2_err[i];
                    }
                    for (int i = 0; i < hidden_layer; ++i)
                    {
                        l1_err[i] = 0;
                        for (int j = 0; j < letters; ++j)
                        {
                            l1_err[i] += l2_err[j] * synapse1[i, j];
                        }
                        l1_err[i] = l1_err[i] * sigmoid_derivative(l1_in[i]);
                    }
                    for (int i = 0; i < hidden_layer; ++i)
                    {
                        for (int j = 0; j < pixels; ++j)
                        {
                            synapse0_delta[j, i] = teaching_velocity * l1_err[i] * l0[j];
                        }
                        synapse0_bias_delta[i] = teaching_velocity * l1_err[i];
                    }
                    for (int i = 0; i < letters; ++i)
                    {
                        for (int j = 0; j < hidden_layer; ++j)
                        {
                            synapse1[j, i] += synapse1_delta[j, i];
                        }
                        synapse1_bias[i] += synapse1_bias_delta[i];
                    }
                    for (int i = 0; i < hidden_layer; ++i)
                    {
                        for (int j = 0; j < pixels; ++j)
                        {
                            synapse0[j, i] += synapse0_delta[j, i];
                        }
                        synapse0_bias[i] += synapse0_bias_delta[i];
                    }
                }
                expectedResult[s] = 0.0;
            }
        }
        System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\Users\\user\\Downloads\\az-handwritten-alphabets-in-csv-format\\A_Z Handwritten Data\\synapses.txt");
        foreach (double syn in synapse0)
        {
            sw.WriteLine(syn);
        }
        sw.WriteLine("\r\n");
        foreach (double syn in synapse1)
        {
            sw.WriteLine(syn + " ");
        }
        sw.Close();
        sw.Dispose();
        UpdateProgress(0);
        //TeachButton.Enabled = true;
    }

    private double sigmoid(double x)
    {
        return 2.0 / (1 + Math.Exp(-x)) - 0.5;
    }

    private double sigmoid_derivative(double x)
    {
        return sigmoid(x) * (1 - sigmoid(x));
        //return x * (1 - x);
    }

    private void RecognizeButton_Click(object sender, EventArgs e)
    {
        bmp = new Bitmap(pictureBox1.Image, new Size(28, 28));
        for(int i=0; i<hidden_layer; i++)
        {
            hl_assumptions[i] = synapse0_bias[i];
            for(int j=0; j<28; j++)
            {
                for(int k=0; k<28; k++)
                {
                    hl_assumptions[i] += synapse0[j * 28 + k, i] * bmp.GetPixel(k, j).B / 255.0;
                }
            }
            hl_assumptions[i] = sigmoid(hl_assumptions[i]);
        }
        for (int i = 0; i < letters; i++)
        {
            assumptions[i] = synapse1_bias[i];
            for (int j = 0; j < hidden_layer; j++)
            {
                assumptions[i] += synapse1[j, i] * hl_assumptions[j];
            }
            assumptions[i] = sigmoid(assumptions[i]);
        }
        string textToOutput = "";
        for(int i=0; i<letters; i++)
        {
            char symbol = (char)(65 + i);
            textToOutput += symbol + ": " + assumptions[i].ToString() + "\r\n";
        }
        textBox1.Text = textToOutput;
        bmp.Dispose();
    }

完整的代码在这里: https://drive.google.com/open?id=1nOUYRgsHeiABNQfrTcmlp8SXINGBsmeO

我希望得到一个由26个元素组成的数组(每个元素对应一个字母),填充值介于-0.5到1.5之间,显示相似度,但是我总是使数组填充-0.5。我是机器学习的新手。预先感谢您的帮助!

P.S。该程序很可能在多线程和垃圾回收方面也有问题,但是在解决了这个问题之后,我将解决它们。

0 个答案:

没有答案