天天看點

統計學習方法 --- 感覺機模型原理及c++實作 1. 感覺機模型 2. 感覺機政策3. 感覺機算法

參考部落格 Liam Q部落格 和李航的《統計學習方法》

感覺機學習旨在求出将訓練資料集進行線性劃分的分類超平面,為此,導入了基于誤分類的損失函數,然後利用梯度下降法對損失函數進行極小化,進而求出感覺機模型。感覺機模型是神經網絡和支援向量機的基礎。下面分别從感覺機學習的模型、政策和算法三個方面來介紹。

1. 感覺機模型

      感覺機模型如下:

f(x)= sign(w*x+b)

      其中,x為輸入向量,sign為符号函數,括号裡面大于等于0,則其值為1,括号裡面小于0,則其值為-1。w為權值向量,b為偏置。求感覺機模型即求模型參數w和b。感覺機預測,即通過學習得到的感覺機模型,對于新的輸入執行個體給出其對應的輸出類别1或者-1。

2. 感覺機政策

      假設訓練資料集是線性可分的,感覺機學習的目标就是求得一個能夠将訓練資料集中正負執行個體完全分開的分類超平面,為了找到分類超平面,即确定感覺機模型中的參數w和b,需要定義一個損失函數并通過将損失函數最小化來求w和b。

       這裡選擇的損失函數是誤分類點到分類超平面S的總距離。輸入空間中任一點x 0到超平面S的距離為:

統計學習方法 --- 感覺機模型原理及c++實作 1. 感覺機模型 2. 感覺機政策3. 感覺機算法

其中,||w||為w的L2範數。

 其次,對于誤分類點來說,當-y i (wx i + b)>0時,y i=-1,當-y i(wx i + b)<0時,y i=+1。是以對誤分類點(x i, y i)滿足:

-yi (wxi +b) > 0

是以誤分類點(x i, y i)到分類超平面S的距離是:

統計學習方法 --- 感覺機模型原理及c++實作 1. 感覺機模型 2. 感覺機政策3. 感覺機算法

3. 感覺機算法

       感覺機學習問題轉化為求解損失函數式(1)的最優化問題,最優化的方法是随機梯度下降法。感覺機學習算法是誤分類驅動的,具體采用随機梯度下降法。首先,任意選取一個超平面w0,b0,然後用梯度下降法不斷極小化目标函數式(1)。極小化的過程不是一次使M中所有誤分類點的梯度下降,而是一次随機選取一個誤分類點使其梯度下降。

   損失函數L(w,b)的梯度是對w和b求偏導,即:

統計學習方法 --- 感覺機模型原理及c++實作 1. 感覺機模型 2. 感覺機政策3. 感覺機算法

其中,(0<<=1)是學習率,即學習的步長。 随機梯度下降法:假如你站在曲面的一點,要以最快的速度到達最低點,當然會沿着坡度最大的方向往下走(梯度的反方向) 綜上,感覺機學習算法如下: 算法1 感覺機學習算法的原始形式

統計學習方法 --- 感覺機模型原理及c++實作 1. 感覺機模型 2. 感覺機政策3. 感覺機算法

原始形式C++實作的源代碼 

  感覺機算法的原始形式 算法2 感覺機學習算法的對偶形式 對偶形式的基本想法是,将w和b表示為執行個體x i和标記y i的線性組合形式,通過求解其系數而求得w和b。對誤分類點(x i, y i)通過

統計學習方法 --- 感覺機模型原理及c++實作 1. 感覺機模型 2. 感覺機政策3. 感覺機算法

是以,感覺機學習算法的對偶形式如下:

統計學習方法 --- 感覺機模型原理及c++實作 1. 感覺機模型 2. 感覺機政策3. 感覺機算法

對偶形式C++實作的源代碼 

統計學習方法 --- 感覺機模型原理及c++實作 1. 感覺機模型 2. 感覺機政策3. 感覺機算法
1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 
  5 #define random(x) (rand()%(x))
  6 
  7 //向量的點積
  8 double dot_product(std::vector<double>& a, std::vector<double>& b){
  9     if(a.size() != b.size()) return 0;
 10     double res = 0;
 11     for(int i = 0 ; i < a.size(); ++ i){
 12         res +=a[i]*b[i];
 13     }
 14     return res;
 15 }
 16 
 17 //感覺機模型類
 18 class Preception{
 19 public:
 20     Preception(int iters = 100,int learnRate = 1,double initw = 0, double initb = 0){
 21         iterators = iters;
 22         a.push_back(initw);
 23         b = initb;
 24         step = learnRate;
 25     }
 26 
 27     ~Preception(){
 28         a.clear();
 29         b = 0;
 30     }
 31 
 32     //訓練資料
 33     //如果疊代次數完,還沒有找到a和b, 則認為資料集不是線性可分的,傳回false
 34     //如果找到了a和b,則認為資料集是線性可分的,傳回true
 35     bool train(std::vector<std::vector<double> >& train_x,std::vector<int>& train_y){
 36         if(train_x.size() != train_y.size()) return false;
 37         initWeight(train_x.size());
 38         std::vector<std::vector<double> > gram = productGram(train_x);
 39         for(int i = 0 ; i < a.size(); ++ i){
 40             int iter = 0;
 41             while(iter < iterators){
 42                 double sum = b;
 43                 for(int j = 0; j < a.size(); ++ j){
 44                     sum += a[j]*train_y[j]*gram[j][i];
 45                 }
 46                 sum *= train_y[i];
 47                 if(sum <= 0) update(i,train_y[i]);
 48                 else break;
 49                 ++iter;
 50             }
 51             if(iter >= iterators) return false;
 52         }
 53         return true;
 54     }
 55     
 56     //批量預測資料
 57     std::vector<int> predict(std::vector<std::vector<double> >& data_x){
 58         std::vector<int> ret;
 59         for(int i = 0 ; i < data_x.size(); ++ i){
 60             ret.push_back(predict(data_x[i]));
 61         }
 62         return ret;
 63     }
 64 
 65     //預測x
 66     int predict(std::vector<double>& x){
 67         return dot_product(x,a)+ b > 0 ? 1 : -1;
 68     }
 69 
 70     //列印感覺機模型
 71     void printPreceptronModel(){
 72         std::cout<<"原始形式感覺機模型:f(x)=sign(";
 73         for(int i = 0 ; i < a.size(); ++ i){
 74             if( i ) std::cout<<"+";
 75             if(a[i]!=1) std::cout<<a[i];
 76             std::cout<<"x"<<i+1;
 77         }
 78         if(b > 0) std::cout<<"+";
 79         std::cout<<b<<")"<<std::endl;
 80     }
 81 
 82 private:
 83     //初始化向量a的維數
 84     void initWeight(int size){
 85         for(int i = 1; i < size; ++ i){
 86             a.push_back(a[0]);
 87         }
 88     }
 89 
 90     //生成Gram矩陣
 91     std::vector<std::vector<double> > productGram(std::vector<std::vector<double> >& train_x){
 92         int n = train_x.size();
 93         std::vector<std::vector<double> > gram(n, std::vector<double>(n,0));
 94         for(int i = 0 ; i < n ; ++ i){
 95             for(int j = 0 ; j  < n; ++ j){
 96                 gram[i][j] = dot_product(train_x[i], train_x[j]);
 97             }
 98         }
 99         return gram;
100     }
101 
102     //更新w和b
103     void update(int index, double y){
104         a[index] +=1; 
105         b += step*y;
106     }
107 
108 private:
109     int iterators;          //疊代次數
110 
111     std::vector<double> a;    //注意w是向量
112     double b;
113 
114     double step;  //學習速率
115 };
116 
117 int main(){
118     std::vector<std::vector<double> >test_x(3);
119     test_x[0].push_back(3);test_x[0].push_back(3);
120     test_x[1].push_back(4);test_x[1].push_back(3);
121     test_x[2].push_back(1);test_x[2].push_back(1);
122     std::vector<int> test_y(3);
123     test_y[0] = 1;
124     test_y[1] = 1;
125     test_y[2] = -1;
126    
127     Preception *model = new Preception();
128     model->train(test_x,test_y);
129     model->printPreceptronModel();
130 }      
網址:http://www.cnblogs.com/xiongqiangcs/p/4185648.html?utm_source=tuicool&utm_medium=referral