【问题标题】:Perceptron Model in C++ not ConvergingC ++中的感知器模型不收敛
【发布时间】:2016-09-03 03:41:49
【问题描述】:

所以我正在编写一个简单的感知器模型,当我完成代码并看到没有错误时,我感到非常惊讶。但我的模型似乎没有收敛(以及其他一些奇怪的东西)。

基本上,它在每个 epoch 都会不断获得 25/100 个样本。当每个 epoch 结束时,权重总是回到 0。

由于代码位于多个文件中,因此我将其放在 Google Drive 上,它是: https://drive.google.com/folderview?id=0B_r3mf9HbUrLaDNlc1F6RXhNMnM&usp=sharing

这是一个 Visual Studio Community 2013 项目。您可以打开并运行它,以便获得更好的想法。

这里是文件的快速预览。

main.cpp:

#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <string>
#include <math.h> 

#include "LinearAlgebra.h"
#include "MachineLearning.h"

using namespace std;
using namespace LinearAlgebra;
using namespace MachineLearning;

void printVector(vector< vector<float> > X);
vector< vector<float> > getIrisX();
vector<float> getIrisy();

int main()
{
    vector< vector<float> > X = getIrisX();
    vector<float> y = getIrisy();
    vector<float> test1;
    test1.push_back(5.0);
    test1.push_back(3.3);
    test1.push_back(1.4);
    test1.push_back(0.2);

    vector<float> test2;
    test2.push_back(6.0);
    test2.push_back(2.2);
    test2.push_back(5.0);
    test2.push_back(1.5);

    //printVector(X);
    //for (int i = 0; i < y.size(); i++){ cout << y[i] << " "; }cout << endl;

    perceptron clf(0.1, 10);
    clf.fit(X, y);
    cout << "Now Predicting: 5.0,3.3,1.4,0.2(CorrectClass=1,Iris-setosa) -> " << clf.predict(test1) << endl;
    cout << "Now Predicting: 6.0,2.2,5.0,1.5(CorrectClass=-1,Iris-virginica) -> " << clf.predict(test2) << endl;

    system("PAUSE");
    return 0;
}

void printVector(vector< vector<float> > X)
{
    for (int i = 0; i < X.size(); i++)
    {
        for (int j = 0; j < X[i].size(); j++)
        {
            cout << X[i][j] << " ";
        }
        cout << endl;
    }
}

vector<float> getIrisy()
{
    vector<float> y;

    ifstream inFile;
    inFile.open("y.data");
    string sampleClass;
    for (int i = 0; i < 100; i++)
    {
        inFile >> sampleClass;
        if (sampleClass == "Iris-setosa")
        {
            y.push_back(1);
        }
        else
        {
            y.push_back(-1);
        }
    }

    return y;
}

vector< vector<float> > getIrisX()
{
    ifstream af;
    ifstream bf;
    ifstream cf;
    ifstream df;
    af.open("a.data");
    bf.open("b.data");
    cf.open("c.data");
    df.open("d.data");

    vector< vector<float> > X;

    for (int i = 0; i < 100; i++)
    {
        char scrap;
        int scrapN;
        af >> scrapN;
        bf >> scrapN;
        cf >> scrapN;
        df >> scrapN;

        af >> scrap;
        bf >> scrap;
        cf >> scrap;
        df >> scrap;
        float a, b, c, d;
        af >> a;
        bf >> b;
        cf >> c;
        df >> d;
        X.push_back(vector < float > {a, b, c, d});
    }

    af.close();
    bf.close();
    cf.close();
    df.close();

    return X;
}

机器学习.h:

#pragma once
#include<vector>

using namespace std;

namespace MachineLearning{

    class perceptron
    {
    public:
        perceptron(float eta,int epochs);
        float netInput(vector<float> X);
        int predict(vector<float> X);
        void fit(vector< vector<float> > X, vector<float> y);
    private:
        float m_eta;
        int m_epochs;
        vector < float > m_w;
        vector < float > m_errors;
    };

}

机器学习.cpp

#include<vector>
#include <algorithm>
#include <iostream>
#include<fstream>
#include <math.h> 

#include "MachineLearning.h"

using namespace std;

namespace MachineLearning{

    perceptron::perceptron(float eta, int epochs)
    {
        m_epochs = epochs;
        m_eta = eta;
    }

    void perceptron::fit(vector< vector<float> > X, vector<float> y)
    {
        for (int i = 0; i < X[0].size() + 1; i++) // X[0].size() + 1 -> I am using +1 to add the bias term
        {
            m_w.push_back(0);
        }
        for (int i = 0; i < m_epochs; i++)
        {
            int errors = 0;
            for (int j = 0; j < X.size(); j++)
            {
                float update = m_eta * (y[j] - predict(X[j]));
                m_w[0] = update;
                for (int w = 1; w < m_w.size(); w++){ m_w[w] = update * X[j][w - 1]; }
                errors += update != 0 ? 1 : 0;
            }
            m_errors.push_back(errors);
        }
    }

    float perceptron::netInput(vector<float> X)
    {
        // Sum(Vector of weights * Input vector) + bias
        float probabilities = m_w[0];
        for (int i = 0; i < X.size(); i++)
        {
            probabilities += X[i] * m_w[i + 1];
        }
        return probabilities;
    }

    int perceptron::predict(vector<float> X)
    {
        return netInput(X) > 0 ? 1 : -1; //Step Function
    }

}

非常感谢任何形式的帮助。

提前致谢。 帕诺斯 P.

【问题讨论】:

  • 在深入代码之前...您是否检查了数据集是否线性可分? (老实说,我宁愿在 MATLAB 或其他高级语言中执行此操作。使用绘图进行视觉验证可以让生活变得更轻松。)
  • 感知器保证收敛当且仅当数据集是线性可分的
  • 我使用的是线性可分的 iris 数据集。我也在 python 中实现了代码,并且运行良好。另外,如果问题是它不会收敛,那么它至少在每个时期不会有不同的错误吗?我认为这与在每个 epoch 结束时变回 0 的权重相结合,表明代码一定有问题。

标签: c++ machine-learning


【解决方案1】:

经过几个小时的繁琐调试,我终于找到了错误。当我更新权重时,我的代码中有一个错误。

for (int j = 0; j < X.size(); j++)
        {
            float update = m_eta * (y[j] - predict(X[j]));
            m_w[0] = update;
            for (int w = 1; w < m_w.size(); w++){ m_w[w] = update * X[j][w - 1]; }
            errors += update != 0 ? 1 : 0;
        }

注意:

m_w[w] = update * X[j][w - 1]

我将权重设置为等于更新。看起来我忘记了一个“+”号。现在可以正常使用了。

现在是这样:

m_w[w] += update * X[j][w - 1]

有时最愚蠢的错误会导致最烦人的错误。 我希望这可以帮助任何犯同样错误的人。

【讨论】:

    猜你喜欢
    • 2020-08-01
    • 2018-02-21
    • 1970-01-01
    • 2018-10-05
    • 2010-12-14
    • 2018-12-14
    • 2017-06-18
    • 2013-10-09
    相关资源
    最近更新 更多