为什么我的机器学习算法会卡住?

问题描述 投票:1回答:1

我的C#机器学习项目遇到了困难。 我正试图训练一个算法来识别数字。 由于这只是一个练习,我有一个200个数字的图像集(0到9各20个)。 显然,如果我想要一个正确训练的算法,我会使用一个更强大的训练集,但这只是一个练习,看看我是否能在第一时间让它工作。 我可以让它达到60%的准确率,但不能超过这个水平。 我对激活函数做了一些研究,据我所知,LeakyRelu是我应该使用的函数。 然而,如果我全面使用LeakyRelu函数,那么它什么也学不到,我不知道如何使用LeakyRelu作为输出激活函数。 使用sigmoid或tanh作为输出激活函数对我来说更有意义。 这里有一段代码块,它创建了反传播的数组。

public static float ACTIVE_VALUE = 1;
public static float INACTIVE_VALUE = -1;

// This is specifically designed for a algorithm that will detect a number between 0 - 9
public static float[] valueToArray(int value)
{

    switch (value)
    {
        case 0:
            return new float[] { ACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };
        case 1:
            return new float[] { INACTIVE_VALUE, ACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };
        case 2:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, ACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };
        case 3:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, ACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };
        case 4:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, ACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };
        case 5:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, 
                                ACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };
        case 6:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, ACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };
        case 7:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, ACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };
        case 8:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, ACTIVE_VALUE, INACTIVE_VALUE };
        case 9:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, ACTIVE_VALUE };
        default:
            return new float[] { INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE,
                                INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE, INACTIVE_VALUE };


    }
}

我不知道如何使用这样的东西 来读取LeakyRelu的输出。 所以我想最好的选择是在输入层和隐藏层使用 LeakyRelu,然后在输出层使用 tanh 或 sigmoid。 然而这就产生了一个问题,因为sigmoid只是返回NAN(据我所知是由于四舍五入的错误),而tanh则返回-1或1,但没有介于两者之间的东西。 如果我全面使用tanh,它可以工作,它可以学习,但它只能达到60%的精度,然后停止发展。我认为这是由于 "消失梯度 "的问题。 然而,如果我使用LeakyRelu作为inpunt和隐藏层,然后使用tanh作为输出,它的准确率保持在12-14%(这和随机猜测一个数字一样好)。

我使用的是一个神经网络,是我从github用户这里得到的。https:/github.comkipgparkerBackPropNetwork。

他在网上发了一篇关于神经网络的研究论文,而且是google上点击率最高的一篇。 我当初就是这样找到的。 我把我的完整项目用压缩包发布在GitHub这里。https:/github.comJoshuaC0352MachineLearning。

我并不反对使用我可以从nuget上得到的库,比如SiaNet (https:/scisharp.github.ioSiaNetapiSiaNet.Layers.AvgPooling1D.html。),然而我对目前正在使用的那个库已经非常熟悉了,我有点不愿意换过来,因为我会觉得自己几乎是从头开始,因为我将不得不学习如何与一个全新的库接口。

EDIT:额外的代码。 这是我的while循环,读取图像并训练算法。

    public static void singleThread()
{

    int batchSize = 10000;
    int rangeLow = 0;
    int rangeHi = 9;

    int hits = 0;


    while (true)
    {

        // alternates between training and testing
        //Console.WriteLine("Training...  ");



        for (int i = 0; i < batchSize; i++)
        {

            // Give a training progress report every 100 iterations, this should increase performance
            if (i % 100 == 0)
            {
                Console.SetCursorPosition(0, Console.CursorTop);
                Console.Write("Training: ");
                Console.Write("(" + (((float)i / (float)batchSize) * 100) + "%)");
                Console.Write("                    ");
            }


            // randomly select an image from the list
            int number = rng.Next(rangeLow, rangeHi);
            int index = rng.Next(1, 20);

            Bitmap loadedImage = (Bitmap)Image.FromFile("Train/" + number + "/" +
                                 index + ".png", true);


            int indexLocation = 0;
            // Convert the image into a grayScale value
            for (int x = 0; x < loadedImage.Width; x++)
            {
                for (int y = 0; y < loadedImage.Height; y++)
                {
                    Color pixel = loadedImage.GetPixel(x, y);
                    int grayValue = (int)((pixel.R * 0.3) + (pixel.G * 0.59) + (pixel.B * 0.11));
                    //Console.WriteLine(grayValue);
                    networkInputs[indexLocation] = grayValue;
                    indexLocation++;
                }
            }

            // The network will guess what the image is, and return the guess as a float array

            float[] guess = currentNetwork.BackPropagate(networkInputs, Interface.valueToArray(number));

            // This if statement checks if the guess was correct
            if (Interface.guessToValue(guess) == number)
            {
                hits++;
            }

        }

        currentNetwork.Performance = ((float) hits / (float) batchSize);
        hits = 0;

        Console.WriteLine("Score: " + (currentNetwork.Performance * 100) + "%");
    }
}
machine-learning deep-learning neural-network backpropagation activation-function
1个回答
1
投票

添加了答案,供以后的访问者参考

  • 试着将灰度值从0-255区间转换为0-1区间。LeakyRELU表现得比sigmoid或tanh更好的事实是,这些值是工具大的。

  • 如果你打算使用tanh或sigmoid,请仔细观察神经网络权重是如何被初始化的。

  • 由于这是一个分类问题,我建议你在输出层中使用软maxactivation函数。

在对数据进行预处理后,@JMC0352只得到了88%的准确率。

之所以只得到88%,是因为神经网络(单独)不适合图像识别,卷积神经网络是用来处理这个问题的。为了直观地理解这个问题,你可以把原始神经网络想象成把所有的像素都放在一起进行感知,而conv.net.则是把相对较近的像素进行感知。

© www.soinside.com 2019 - 2024. All rights reserved.