2014-06-22 86 views
0

我一直在努力學習神經網絡,並且我在互聯網上看到的所有例子都給出了仿真邏輯門的例子,說XOR門。但我想要做的是創建一個可以訓練模擬功能的網絡,如x^2e^x。這可能嗎?我需要做什麼網絡變化? 這是我的一個神經網絡的代碼,由1個輸入節點,一個由3個節點組成的隱藏層和一個輸出節點組成。創建一個神經網絡來評估邏輯功能

#include <iostream.h> 
    #include <fstream.h> 
    #include <math.h> 
    #include <time.h> 
    const double eeta=0.9; 
    const int n=5; 
    struct Net_elem 
    { 
     double weights1[3]; 
     double weights2[3]; 
     double bias1,bias2; 
    };//structure to store network paramenters 
    Net_elem net_elem; 
    double sigma(double input) 
    { 
     return 1/(1+exp(-input)); 
     } 
    void show_net_elem() 
    { 
       cout.precision(15); 
       for(int i=0;i<3;i++) 
       { 
         cout<<"weights1["<<i<<"]="<<net_elem.weights1[i]; 
         cout<<endl; 
       } 
       for(int i=0;i<3;i++) 
       { 
         cout<<"weights2["<<i<<"]="<<net_elem.weights2[i]; 
         cout<<endl; 
       } 
       cout<<"bias1="<<net_elem.bias1<<" bias2="<<net_elem.bias2<<endl; 
       system("pause"); 
       system("cls"); 
    } 
    //function to train the network 
    void train(double input,double expected) 
    { 
    double Output,output[3],Delta,delta[3],delta_bias1,delta_bias2; 

    //Propogate forward 
    double sum=0; 
    for(int i=0;i<3;i++) 
     output[i]=sigma(input*net_elem.weights1[i]+net_elem.bias1); 
    sum=0; 
    for(int i=0;i<3;i++) 
     sum=sum+output[i]*net_elem.weights2[i]; 
    Output=sigma(sum+net_elem.bias2); 
    cout<<"Output="<<Output<<endl; 

    //Backpropogate 

    Delta=expected-Output; 
    for(int i=0;i<3;i++) 
     delta[i]=net_elem.weights2[i]*Delta; 
     delta_bias2=net_elem.bias2*Delta; 

    //Update weights 

    for(int i=0;i<3;i++) 
     net_elem.weights1[i]=net_elem.weights1[i]+eeta*delta[i]*output[i]*(1-output[i])*input; 
    for(int i=0;i<3;i++) 
     net_elem.weights2[i]=net_elem.weights2[i]+eeta*Delta*Output*(1-Output)*output[i]; 
    net_elem.bias2=net_elem.bias2+eeta*delta_bias2; 
    double sum1=0; 
    for(int i=0;i<3;i++) 
     sum1=sum1+net_elem.weights1[i]*delta[i]; 
    net_elem.bias1=net_elem.bias1+eeta*sum1; 
    show_net_elem(); 
} 
void test() 
{ 
    cout.precision(15); 
    double input,Output,output[3]; 
    cout<<"Enter Input:"; 
    cin>>input; 
    //Propogate forward 
    double sum=0; 
    for(int i=0;i<3;i++) 
     output[i]=sigma(input*net_elem.weights1[i]+net_elem.bias1); 
    for(int i=0;i<3;i++) 
     sum=sum+output[i]*net_elem.weights2[i]; 
    Output=sigma(sum+net_elem.bias2); 
    cout<<"Output="<<Output<<endl;  
} 

我試圖運行它來模擬平方根函數。但輸出只是在0和1之間交替跳轉。

主營:

int main() 
{ 
    net_elem.weights1[0]=(double)(rand()%100+0)/10; 
    net_elem.weights1[1]=(double)(rand()%100+0)/10; 
    net_elem.weights1[2]=(double)(rand()%100+0)/10; 
    net_elem.weights2[0]=(double)(rand()%100+0)/10; 
    net_elem.weights2[1]=(double)(rand()%100+0)/10; 
    net_elem.weights2[2]=(double)(rand()%100+0)/10;; 
    net_elem.bias1=(double)(rand()%100+0)/10; 
    net_elem.bias2=(double)(rand()%100+0)/10; 
    double output[n],input[n]; 
    int ch; 
    for(int i=1;i<n;i++) 
    { 
      input[i]=100; 
      output[i]=sqrt(input[i]); 
    } 
    do 
    { 
      cout<<endl<<"1. Train"<<endl; 
      cout<<"2. Test"<<endl; 
      cout<<"3. Exit"<<endl; 
      cin>>ch; 
      switch(ch) 
      { 
         case 1:for(int i=1;i<n;i++) 
         { 
          train(input[i],output[i]); 
         } 
          break; 
         case 2:test();break; 
         case 3:break; 
         default:cout<<"Enter Proper Choice"<<endl; 
      } 
    }while(ch!=3); 
} 
+1

要知道需要做些什麼改變,我們需要知道我們正在改變*。你能向我們展示一個你嘗試過的例子嗎? – christopher

+0

你教你的網絡sqrt(100)= 10,對吧?首先'input [i]'應該取決於'i'或者一個隨機值。其次,我會嘗試大規模地進行培訓。成千上萬的訓練至少在運行。 *然後*你可以問自己爲什麼它沒有學到任何東西。第三,我看到一些格式問題。是'delta_bias2 = net_elem.bias2 * Delta;'應該在'for'循環中?第四...這是一個非常明顯的調試問題恕我直言。 – TobiMcNamobi

回答

0

我認爲你缺少使用神經網絡的點。神經網絡不模仿已知的功能。它們將未知矢量空間中的區域分開。異或問題往往是作爲一個例子,因爲它是最小的非線性可分問題:一個簡單的感知是一個簡單的線在你分開兩個方面的問題

enter image description here

在這種情況下,可以用簡單的線將藍點與紅點分開(問題是可線性分離)。然而,在XOR問題,點被位於這樣的:

enter image description here

這裏,單個線(感知)是不夠的。但是,多層感知器(很可能是您正在使用的神經網絡類型)可以使用多個感知器(在這種情況下爲兩個感知器)來分隔藍色和紅色點。以類似的方式,神經網絡可以分隔任何空間。

但是,XOR問題產生兩種類型的輸出,我們使用神經網絡來分離它們。另一方面,x^2產生連續的點,所以沒有什麼可以分開的。另外,請記住模仿異或函數是作爲這樣的問題的一個例子。在實踐中,沒有人使用神經網絡來替代XOR函數。如果你想使用一個函數,就使用它,而不是構建一個近似它的東西。 PS:如果你仍然想模擬練習中的x^2函數,你需要回歸。你在做什麼是分類(因爲你在輸出中使用sigma函數)。但是,練習你最好堅持分類問題。他們更加普遍。另外,對於這樣的問題,請嘗試使用Matlab,或者,如果您想用C++編寫代碼,請使用一些線性代數庫(例如EIGEN 3),以便無需一千次循環就可以輕鬆編寫代碼。

+0

_「神經網絡不會模仿已知的功能。」_對不起,但我必須強烈反對,已經證明25年左右,2層感知器是任意連續函數的通用逼近器。 – Dolma

+0

@Dolma:這是正確的。但是,這種能力允許網絡本身在未知問題空間中創建用於分類或迴歸的廣義函數。它在實踐中從未用於模擬用戶已知的功能。 OP似乎在問爲什麼XOR函數經常被引用作爲例子,並且我想清楚地說明我們如何組合線性分類器來分類非線性可分離的數據集,這是任何一個新的神經網絡的開始。 –

+0

是的,你是絕對正確的!雖然有時我們確實想使用已知的函數。例如,爲了測試網絡架構和/或學習算法的泛化能力,我們可以使用已知函數,應用一些隨機擾動,然後使用擾動輸出來訓練網絡,以期它適合原始的無干擾函數。除此之外,我同意你的看法,這不是你在練習中做的很多事情;) – Dolma