2016-09-02 9 views
0

私は単純なパーセプトロンモデルを書いていました。コードを完成させてエラーがないことがわかったとき、私はかなり驚いていました。しかし、私のモデルは収束していないようです(他の奇妙なものと一緒に)。C++のパーセプトロンモデルは収束しません

基本的に、すべてのエポックで25/100サンプルを取得し続けます。すべてのエポックは、重みは常に私はGoogleドライブ上に置くためのコードが複数のファイルであるという事実に戻っ0

に来て終了した場合、ここには、次のとおりです。 https://drive.google.com/folderview?id=0B_r3mf9HbUrLaDNlc1F6RXhNMnM&usp=sharing

それは、Visual Studioでコミュニティ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; 
} 

MachineLearning.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; 
    }; 

} 

MachineLearning.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.

+2

コードをダイビングする前に...データセットが線形に分離可能かどうかをチェックしましたか? (正直なところ、私はむしろMATLABやその他の高水準言語でこれを行うでしょう。プロットを使って視覚的に検証することは、人生をもっと楽にしてくれるでしょう) – bot1131357

+1

パーセプトロンはデータセットが線形分離可能である場合にのみコンバージェンスを保証します –

+0

私は虹彩データセット直線的に分離可能である。私もPythonでコードを実装して、それは正常に働いた。また、問題が収束しないとすれば、各エポックには少なくとも異なるエラーがありますか?私はこれが、すべてのエポックの終わりに0に変化する重みと組み合わされて、コードに何か間違っていなければならないことを示していると思います。 – Panos

答えて

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_w[w] = update * X[j][w - 1] 

は私が更新に等しいと重みを設定しています。私は "+"記号を忘れたようです。今それは正常に動作します。

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

時には最も馬鹿馬鹿しいミスがエラーの最も厄介を引き起こす可能性があります。ここでは

は、それが今あるのです。 これが同じミスをした人に役立つことを願っています。

関連する問題