2014-06-22 53 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