为什么我的机器学习算法陷入停滞?

我在进行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 - 9public 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作为输入和隐藏层的激活函数,然后使用tanh作为输出层的激活函数,准确率会停留在12-14%(这和随机猜测一个数字一样好)。

我使用了一个来自GitHub用户的神经网络

他在网上发布了一篇关于神经网络的研究论文,这是谷歌搜索的顶级结果之一。这就是我最初找到它的方式。我在GitHub上以zip格式发布了我的完整项目:在这里

我并不反对使用从nuget获取的库,比如SiaNet(这里),然而我已经非常熟悉我目前正在使用的这个,我有点不愿意切换,因为我感觉我几乎是从头开始,因为我必须学习如何与一个全新的库进行交互。

编辑:添加了额外的代码。这是我读取图像并训练算法的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) + "%");    }}

回答:

为未来的访问者添加了回答

  • 尝试将灰度值从0-255区间转换为0-1区间。只需将每个像素值除以255。LeakyRELU比sigmoid或tanh表现得更好,是因为这些值太大。大到被tanh和sigmoid误处理,并被计算机四舍五入为整数。

  • 如果打算使用tanh或sigmoid,请仔细查看神经网络权重的初始化方式。

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

在预处理数据后,@JMC0352仅获得了88%的准确率。

你只得到88%的原因是单独的神经网络不适合图像识别。卷积神经网络用于此类任务。为了直观地理解这个问题,你可以把原始神经网络想象成一起处理所有像素,而卷积网络则处理相对接近的像素。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注