machine-learning - 神经网络误差随每个训练示例而振荡

标签 machine-learning artificial-intelligence neural-network backpropagation

我已经实现了一个反向传播神经网络并根据我的数据对其进行了训练。数据在英语和非洲语句子之间交替。神经网络应该识别输入的语言。

网络结构为27 *16 * 2 输入层对于字母表中的每个字母都有 26 个输入,外加一个偏置单元。

我的问题是,当遇到每个新的训练示例时,错误会猛烈地向相反的方向抛出。正如我提到的,训练示例以交替的方式阅读(英语、非洲语、英语......)

我可以训练网络来识别所有英国人或所有非洲人,但不能在同一 channel 中识别其中任何一个(两者)。

下面的 y 轴是两个输出节点(英语和非洲人)各自的输出信号误差,x 轴是训练示例的数量。在某种程度上,它完全按照我编程的方式执行;当示例是英语时,它会更改权重以更好地识别英语。然而,这样做会使网络在预测非洲人方面变得更差。这就是误差介于正值和负值之间的原因。

显然这不是它应该如何工作,但我被困住了。

enter image description here

我觉得这个错误对我来说是概念性的,但这里是相关代码:

public void train() throws NumberFormatException, IOException{

    // Training Accuracy
    double at = 0;

    //epoch
    int epoch = 0;

    int tNum = 0;

    for(; epoch < epochMax; epoch++){

        // Reads stock files from TestPackage package in existing project
        BufferedReader br = new BufferedReader(new InputStreamReader(this.getClass().
                getResourceAsStream("/TrainingData/" + trainingData.getName())));

        while ((line = br.readLine()) != null) {

            Boolean classified = false;

            tNum++;

            // Set the correct classification Tk
            t[0] = Integer.parseInt(line.split("\t")[0]); //Africaans
            t[1] = (t[0] == 0) ? 1 : 0; // English


            // Convert training string to char array
            char trainingLine[] = line.split("\t")[1].toLowerCase().toCharArray();


            // Increment idx of input layer z, that matches
            // the position of the char in the alphabet
            // a == 0, b == 2, etc.....
            for(int l = 0; l < trainingLine.length; l++){
                if((int)trainingLine[l] >= 97 && (int)trainingLine[l] <= 122)
                    z[(int)trainingLine[l] % 97]++;
            }


            /*System.out.println("Z   " + Arrays.toString(z));
            System.out.println();*/

            // Scale Z
            for(int i = 0; i < z.length-1; i++){
                z[i] = scale(z[i], 0, trainingLine.length, -Math.sqrt(3),Math.sqrt(3));
            }

         /*----------------------------------------------------------------
          *                  SET NET HIDDEN LAYER 
          * Each ith unit of the hidden Layer = 
          * each ith unit of the input layer
          * multiplied by every j in the ith level of the weights matrix ij*/


            for(int j = 0; j < ij.length; j++){  // 3
                double[] dotProduct = multiplyVectors(z, ij[j]);
                y[j] = sumVector(dotProduct);   

            }


            /*----------------------------------------------------------------
             *                 SET ACTIVATION HIDDEN LAYER 
             */

            for(int j = 0; j < y.length-1; j++){
                y[j] = sigmoid(y[j], .3, .7);
            }

            /*----------------------------------------------------------------
             *                       SET NET OUTPUT LAYER 
             * Each jth unit of the hidden Layer = 
             * each jth unit of the input layer
             * multiplied by every k in the jth level of the weights matrix jk*/


            for(int k = 0; k < jk.length; k++){  // 3
                double[] dotProduct = multiplyVectors(y, jk[k]);
                o[k] = sumVector(dotProduct);
            }

            /*----------------------------------------------------------------
             *                   SET ACTIVATION OUTPUT LAYER
             */

            for(int k = 0; k < o.length; k++){
                o[k] = sigmoid(o[k], .3, .7);
            }

            /*----------------------------------------------------------------
             *                     SET OUTPUT ERROR
             * For each traing example, evalute the error.
             * Error is defined as (Tk - Ok)
             * Correct classifications will result in zero error:
             *          (1 - 1) = 0
             *          (0 - 0) = 0
             */

            for(int k = 0; k < o.length; k++){
                oError[k] = t[k] - o[k];
            }

            /*----------------------------------------------------------------
             *                     SET TRAINING ACCURACY
             * If error is 0, then a 1 indicates a succesful prediction.
             * If error is 1, then a 0 indicates an unsucessful prediction.
             */

            if(quantize(o[0],.3, .7) == t[0] && quantize(o[1], .3, .7) == t[1]){
                classified = true;
                at += 1;
            }


            // Only compute errors and change weiths for classification errors
            if(classified){
                continue;
            }

            /*----------------------------------------------------------------
             *                  CALCULATE OUTPUT SIGNAL ERROR
             *                 Error of ok = -(tk - ok)(1 - ok)ok
             */


            for(int k = 0; k < o.length; k++){
                oError[k] = outputError(t[k], o[k]);

            }

            /*----------------------------------------------------------------
             *                  CALCULATE HIDDEN LAYER SIGNAL ERROR
             *                  
             */

            // The term (1-yk)yk is expanded to yk - yk squared

            // For each k-th output unit, multiply it by the
            // summed dot product of the two terms (1-yk)yk and jk[k]


            for(int j = 0; j < y.length; j++){
                for(int k = 0; k < o.length; k++){
                    /*System.out.println(j+"-"+k);*/
                    yError[j] +=  oError[k] * jk[k][j] * (1 -  y[j]) * y[j];

                }
            }   
            /*----------------------------------------------------------------
             *                  CALCULATE NEW WIGHTS FOR HIDDEN-JK-OUTPUT
             *                  
             */

            for(int k = 0; k < o.length; k++){
                for(int j = 0; j < y.length; j++){
                    djk[k][j] = (-1*learningRate)*oError[k]*y[j] + momentum*djk[k][j];

                    // Old weights = themselves + new delta weight
                    jk[k][j] += djk[k][j]; 

                }
            }

            /*----------------------------------------------------------------
             *         CALCULATE NEW WIGHTS FOR INPUT-IJ-HIDDEN
             *                  
             */

            for(int j = 0; j < y.length-1; j++){
                for(int i = 0; i < z.length; i++){

                    dij[j][i] = (-1*learningRate)*yError[j]*z[i] + momentum*dij[j][i];

                    // Old weights = themselves + new delta weight
                    ij[j][i] += dij[j][i]; 

                }
            }
        }
    }
    // Accuracy Percentage
    double at_prec = (at/tNum) * 100;

    System.out.println("Training Accuracy: " + at_prec);    
}

最佳答案

我同意这样的评论,即该模型可能不是最适合您的分类问题,但如果您有兴趣尝试使其发挥作用,我会告诉您我认为这种振荡的原因以及我将尝试的方式解决这个问题。

根据我对您的问题和评论的理解,我无法理解网络在这种情况下实际“学习”的内容。您输入字母(这是该字母在句子中出现的次数吗?),然后强制它映射到输出。假设你现在只使用英语,英语对应的输出为 1。因此,你在一个句子上“训练”它,为了论证,它选择字母“a”作为确定输入,这是一个非常常见的字母。它设置网络权重,使得当它看到“a”时,输出为 1,并且所有其他字母输入都会被加权,这样它们就不会影响输出。它可能不是那么黑白分明,但它可能会做一些非常相似的事情。现在,每次你输入另一个英语句子时,它只需要看到一个“a”就可以给出正确的输出。对非洲人做同样的事情,输出为零,它将“a”映射到零。因此,每次您在两种语言之间切换时,它都会完全重新分配权重……您不是在结构上构建的。误差的反向传播基本上总是一个固定值,因为没有正确或错误的程度,只有一个或另一个。所以我希望它会像你所看到的那样振荡。

编辑:我认为这可以归结为诸如用于对语言类别进行分类的字母的存在并期望两个极性输出之一的问题,而不是关于定义语言的字母之间的关系的任何内容。

在概念层面上,我将有一个完整的预处理阶段来获取一些统计数据。我可能会凭空计算(我不懂语言): - 句子中字母“a”与“c”出现的比例 - 句子中字母“d”与“p”出现的比例 - 句子中单词的平均长度

对每种语言的 50 个句子执行此操作。一次性输入所有数据并对整个数据集进行训练(70% 用于训练,15% 用于验证,15% 用于测试)。你不能每次都在单个值上训练网络(正如我认为你正在做的那样?),它需要看到整个图片。现在你的输出不再那么黑白分明,它可以灵活地映射到 0 到 1 之间的值,而不是每次都是绝对值。高于 0.5 的为英语,低于 0.5 的为非洲人。从语言的 10 个统计参数开始,隐藏层有 5 个神经元,输出层有 1 个神经元。

关于machine-learning - 神经网络误差随每个训练示例而振荡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30361682/

相关文章:

artificial-intelligence - 模块未找到错误 : no module named 'transformers'

algorithm - 区域覆盖的波前算法

machine-learning - 用于分类/识别 2D 散点图形状的最合适的 ML 技术是什么?

python - 为什么我手工制作的 numpy 神经网络无法学习?

python - Keras Fit_generator 回调

python - K 表示具有指定簇内距离的簇

machine-learning - 为什么我们在 kmeans 聚类方法中使用 kmeans.fit 函数?

machine-learning - 使用文本文档对特征集进行建模

"Text To speech"和 "Voice to Text"的 C++ API

r - R 中 svm 特征选择的示例