程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> NTU-Coursera機器學習:HomeWork 1 Q15-20

NTU-Coursera機器學習:HomeWork 1 Q15-20

編輯:C++入門知識

NTU-Coursera機器學習:HomeWork 1 Q15-20


Question15

\

訓練數據格式如下:

\

輸入有4個維度,輸出為{-1,+1}。共有400條數據。

題目要求將權向量元素初始化為0,然後使用“Naive Cycle”遍歷訓練集,求停止迭代時共對權向量更新了幾次。

所謂“Naive Cycle”指的是在某數據條目x(i)上發現錯誤並更新權向量後,下次從x(i+1)繼續讀數據,而不是回到第一條數據x(0)從頭開始。

#include 
#include 
#include 
 
using namespace std;
 
#define DEMENSION 5                //數據維度
 
double weights[DEMENSION];         //權重向量
int step= 0;                       //迭代次數
int length = 0;                    //數據條目個數
int index = 0;                     //當前數據條目索引
bool isFinished = false;           //迭代終止狀態
char *file = "training_data.txt";
 
struct record {
    double input[DEMENSION];   //輸入
    int output;                //輸出   
};
vector trainingSet;        //訓練數據
 
int sign(double x)
{
    if(x<0)       return -1;
    else if(x>0) return 1;
    else         return -1;
}
 
//兩個向量相加,更新第一個向量
void add(double *v1, double *v2, int demension)
{
    for(int i=0;i>curRecord.input[i]; }
        dataFile>>curRecord.output;
        trainingSet.push_back(curRecord);
    }
    dataFile.close();
    length = trainingSet.size();
}
 
void PLA()
{
    int start = index;
    double curInput[DEMENSION];
         
        //找到下一個錯誤記錄的index
    while( trainingSet[index].output == 
    sign(multiply(weights,trainingSet[index].input,DEMENSION)) )
    {  
        if(index==length-1) {index = 0;}
        else            {index++;}
        if(index==start)    {isFinished = true; break;}  //沒發現錯誤,迭代結束
    }
 
    if(isFinished){
        cout<<"計算結果:step = "< 文件打開失敗"<測試結果如下所示:
\

多次運行程序,迭代次數均為45次。

Question16

vc/C0rvC1rzGy+O/qsq81NnW2NDCxcXQ8qOs1ti4tDIwMDC0zqOsx/O21Mioz/LBv7XExr2++dDe1f20zsr9oaM8YnIgLz48L3A+PHA+PHByZSBjbGFzcz0="brush:java;">#include #include #include #include using namespace std; #define DEMENSION 5 //數據維度 int step= 0; //迭代次數 int index = 0; //當前數據條目索引 bool isFinished = false; //迭代終止狀態 char *file = "training_data.txt"; struct record { double input[DEMENSION]; //輸入 int output; //輸出 }; int sign(double x) { //同Q15 } void add(double *v1, double *v2, int demension) { //同Q15 } //兩個向量相乘,返回內積 double multiply(double *v1, double *v2, int demension) { //同Q15 } //向量與實數相乘,結果通過*result返回,不改變參與計算的向量 void multiply(double *result, double *v, double num, int demension) { //同Q15 } //對 traininig set 創建一個隨機排序 void setRandomOrder(vector &trainingSet, vector &randIndexes) { srand((unsigned)time(NULL)); int length = trainingSet.size(); vector assignedIndexes(length,false); for(int i=0;i &trainingSet) { while(!dataFile.eof()){ record curRecord; curRecord.input[0] = 1; for(int i=1;i>curRecord.input[i]; } dataFile>>curRecord.output; trainingSet.push_back(curRecord); } dataFile.close(); } void PLA(vector &trainingSet, vector &randIndexes, double *weights) { int length = trainingSet.size(); int start = index; double curInput[DEMENSION]; //找到下一個錯誤記錄的index while( trainingSet[randIndexes[index]].output == sign(multiply(weights,trainingSet[randIndexes[index]].input,DEMENSION)) ){ if(index==length-1) {index = 0;} else {index++;} if(index==start) {isFinished = true; break;} //沒發現錯誤,迭代結束 } if(isFinished){ return; }else{ step++; //更新: weights = weights + curOutput * curInput multiply( curInput, trainingSet[randIndexes[index]].input, trainingSet[randIndexes[index]].output, DEMENSION ); add( weights, curInput, DEMENSION ); if(index==length-1) {index = 0;} else {index++;} PLA(trainingSet, randIndexes, weights); } return; } void main() { int totalSteps = 0; for(int i=0;i<2000;++i){ double weights[DEMENSION]; //權重向量 vector trainingSet; //訓練數據 vector randIndexes; //訪問數據的隨機索引列表 ifstream dataFile(file); step = 0; index = 0; isFinished = false; if(dataFile.is_open()){ getData(dataFile,trainingSet); setRandomOrder(trainingSet,randIndexes); }else{ cerr<<"ERROR ---> 文件打開失敗"<

Question17

\

本題要求在更新權向量時乘以一個0.5的系數,代碼變動很少。

測試結果:

\

Question18

\

第18題要求在第16題 Random PLA 算法的基礎上使用 Pocket 算法對數據做二元劃分。Pocket算法在博文NTU-Coursera機器學習:機器學習問題與二元分類 介紹過,通常用來處理有雜質的數據集,在每一次更新 Weights(權向量)之後,把當前犯錯最少的Weights放在pocket中,直至達到指定迭代次數(50次),pocket中的Weights即為所求。然後用測試數據驗證W(pocket)的錯誤率,進行2000次計算取平均。

#include 
#include 
#include 
#include 
 
using namespace std;
 
#define DEMENSION 5                    //數據維度
 
int index = 0;                         //當前數據條目索引
int step = 0;                          //當前權向量更新次數
char *file = "training_data.txt";
char *file_test = "test_data.txt";
 
struct record {
    double input[DEMENSION];       //輸入
    int output;                    //輸出   
};
 
 
 
int sign(double x)
{
    //同Q16
}
 
//兩個向量相加,更新第一個向量
void add(double *v1, double *v2, int demension)
{
    //同Q16
}
 
//兩個向量相乘,返回內積
double multiply(double *v1, double *v2, int demension)
{
    //同Q16
}
 
//向量與實數相乘,結果通過*result返回,不改變參與計算的向量
void multiply(double *result, double *v, double num, int demension)
{
    //同Q16
}
 
//對 traininig set 創建一個隨機排序
void setRandomOrder(vector &trainingSet, vector &randIndexes)
{
    //同Q16
}
 
//讀取數據
void getData(ifstream & dataFile, vector &data)
{
    //同Q16
}
 
//錯誤統計及Pocket向量更新
void errCountAndPocketUpdate(vector &trainingSet, vector &randIndexes, 
        double *weights, double *pocketWeights, double &trainingErrRate, int dataLength)
{
    int errCount = 0;
    double curTrainingErrRate = 1.0;
 
    for(int i=0;i &trainingSet, vector &randIndexes, double *weights, 
        double *pocketWeights, double &trainingErrRate)
{
    int length = trainingSet.size();
    double curInput[DEMENSION];   
 
    errCountAndPocketUpdate(trainingSet, randIndexes, weights, 
        pocketWeights, trainingErrRate, length);
         
        //找到下一個錯誤記錄的index
    while( trainingSet[randIndexes[index]].output == 
        sign(multiply(weights,trainingSet[randIndexes[index]].input,DEMENSION)) ){
        if(index==length-1) {index = 0;}
        else                {index++;}
    }
     
    if(step<50){
        step++;
         
        //更新: weights = weights + curOutput * curInput
        multiply( curInput, trainingSet[randIndexes[index]].input, 
            trainingSet[randIndexes[index]].output, DEMENSION ); 
        add( weights, curInput, DEMENSION );   
 
        if(index==length-1) {index = 0;}
        else            {index++;}
 
        Pocket(trainingSet, randIndexes, weights, pocketWeights, trainingErrRate); 
    }else{     
        return;
    }
}
 
//統計 W(pocket) 在測試數據集上的錯誤率
double getTestErrRate(vector &testSet, double *pocketWeights, int dataLength)
{
    int errCount = 0;
 
    for(int i=0;i trainingSet;             //訓練數據
        vector testSet;                 //測試數據
        vector randIndexes;                //訪問數據的隨機索引列表
        ifstream dataFile(file);
        ifstream testDataFile(file_test);
        double trainingErrRate = 1.0;           //訓練集中的錯誤率[0.0, 1.0]
        double testErrRate = 1.0;               //測試集中的錯誤率[0.0, 1.0]
 
        step = 0;            
        index = 0;                
 
        if( dataFile.is_open() && testDataFile.is_open() ){
            getData(dataFile,trainingSet); 
            getData(testDataFile,testSet); 
            setRandomOrder(trainingSet,randIndexes);
        }else{
            cerr<<"ERROR ---> 文件打開失敗"<


Question19

\

題19要求用經過50次更新的W(50)進行驗證,而不是W(pocket),由於W(50)未必是當下最優,所以平均錯誤率一定會升高。代碼幾乎沒有改動,只需在調用 getTestErrRate 函數是傳入W(50)的指針即可。

測試結果:

\

Question20

\

本題要求把 Weights 的更新次數從50增加到100,可以預計平均錯誤率是降低的。

測試結果:

\


關於Machine Learning更多討論與交流,敬請關注本博客和新浪微博songzi_tea.


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved