65.9K
CodeProject 正在变化。 阅读更多。
Home

模糊逻辑 vs.反向传播网络

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (10投票s)

2003年11月27日

7分钟阅读

viewsIcon

60551

downloadIcon

1378

另一个实验,探讨实现神经网络代码的不同方式。

引言

本文是我目前对神经网络研究的延续,旨在探寻是否存在一种更简便的方法来实现我在之前关于神经网络的文章中设定的目标。这些文章源于我对神经网络的不满以及我始终认为应该有更好的方式来完成神经网络所做工作的挥之不去的感觉。这些文章并非旨在贬低或诋毁神经网络,它们仅仅是我好奇心的表达,并且应该严格从程序员的“我如何实现它”的角度来看待,而不是从数学家或试图复制大脑实际运作方式的人的角度来看待。

我在人工智能研究中经常遇到的一个概念是规则。为了让神经网络正常工作,它必须决定使用哪些规则。它通常通过使用所谓的监督训练来辅助完成此路径,这意味着网络会得到带有答案的测试问题,并必须找出如何从测试数据中得出答案。基本上,它必须找出要使用的规则,然后以某种方式记住它们。也有无监督的神经网络训练方法,但由于本文着眼于反向传播网络,因此我暂时可以忽略它们。

或许不足为奇的是,当我开始研究模糊逻辑时,规则问题再次浮出水面,以至于我提出了我在模糊逻辑 vs. Adaline 神经网络一文中讨论的想法。在那篇文章中,我也表达了我自己的疑问,即我所做的东西是否还能被称为模糊逻辑。Bart Kosko 在他的著作《模糊思维》中说:“模糊系统存储着数十、数百或数千条这些常识性的模糊规则。每条新的数据在某种程度上都会激活所有模糊规则(大多数激活程度为零)。然后,模糊系统将这些输出融合在一起,生成最终的输出或答案”,这使我比之前认为的更有底气。诚然,目前,这些例子很简单,因此在选择使用哪些规则以及规则本身都相当简单。但随着我沿着这些方向前进,一切都将变得更加复杂。

反向传播神经网络

反向传播网络代码背后的思想是,它是对 Adaline 网络的改进,因为它解决了 Adaline 神经网络无法解决的一些问题。有关反向传播网络的完整描述,请参阅神经网络 .NET 第 7 部分 反向传播网络。然而,一个简短的描述是,反向传播网络允许神经网络处理诸如逻辑或 (OR) 的解决方案,例如,如果您有两个输入数字,值为 0 和 1,那么您可以让反向传播网络在其中一个数字(但不是两个)等于 1 时输出 1。这主要是通过使用容差值来完成的,该容差值允许您设置网络的正确性级别。容差级别完全取决于运行网络的人,但例如,如果您将容差级别设置为 0.4,这意味着网络返回的在 0 到 0.4 范围内的所有值都将被归类为等于 0,而返回的在 1 到 0.6 范围内的所有值都将被视为等于 1。这允许运行网络的人员留有一定的余地,当然,容差级别的值越低,训练系统所需的时间就越长。

模糊方法。

这一次,神经网络的任务再次是规则问题,就像之前对 Adaline 网络的探讨一样,我曾指出,尽管神经网络在技术上是自行找出规则的。这些规则实际上在程序员事先就已知晓,而且就像 Adaline 一样,反向传播网络是用问题的答案进行训练的,这意味着网络的训练无非就是找出如何从给定的输入中获取给定的答案。我再次认为,一个简单的基于规则的机制可以在更少的时间和更少的工作量下达到相同的效果。

与之前的示例一样,我从一个描述适用于程序的规则的接口开始。这段代码的接口如下:

public interface IBackPropagationRules
{
  bool IsOneVarEqualOne
  {
    get;
    set;
  }

  bool IsOneVarEqualZero
  {
    get;
    set;
  }

  bool AreBothVarsEqualOne
  {
    get;
    set;
  }

  bool AreBothVarsEqualZero
  {
    get;
    set;
  }
}

这个接口比之前Adaline示例中使用的接口更具体地针对反向传播网络示例,因此它包含在演示代码文件中,而不是作为库的一部分。其基本思想是在代码中定义我们希望使用的规则,而不实际指定这些规则应如何实现。这样做的原因是,在项目中,项目一部分的规则可能与项目不同部分的规则相同,尽管这些规则的实现可能完全不同。这只是一种说法,即这些是此时要实现的规则,你如何实现它们与我无关,但这些是需要使用的规则。

此时,类实现已经设置完毕,这与之前的示例是另一个区别,即该类被专门定义为用于在程序中实现规则的规则类,而不是作为类的一部分进行定义或实现。

class Rules : IBackPropagationRules
{
    private bool bOneVarEqualsOne;
    private bool bOneVarEqualsZero;
    private bool bBothEqualOne;
    private bool bBothEqualZero;

    public Rules()
    {
        bOneVarEqualsOne = false;
        bOneVarEqualsZero = false;
        bBothEqualOne = false;
        bBothEqualZero = false;
    }

这个`Rules`类继承自接口,并实现了接口中定义的规则。该类有四个成员变量,用于跟踪在任何给定时间正在使用哪个规则。这是因为这种方法背后的核心思想之一是规则具有灵活性,即代码或类中的某些要求可能需要对类中的每个对象使用不同的规则。

接口实现如下:

#region IBackPropagationRules Members

    public bool IsOneVarEqualOne
    {
        get
        {
            // TODO:  Add Rules.IsOneVarEqualOne getter implementation
            return bOneVarEqualsOne;
        }
        set
        {
            // TODO:  Add Rules.IsOneVarEqualOne setter implementation
            bOneVarEqualsOne = value;
        }
    }

    public bool IsOneVarEqualZero
    {
        get
        {
            // TODO:  Add Rules.IsOneVarEqualZero getter implementation
            return bOneVarEqualsZero;
        }
        set
        {
            // TODO:  Add Rules.IsOneVarEqualZero setter implementation
            bOneVarEqualsZero = value;
        }
    }

    public bool AreBothVarsEqualOne
    {
        get
        {
            // TODO:  Add Rules.AreBothVarsEqualOne getter implementation
            return bBothEqualOne;
        }
        set
        {
            // TODO:  Add Rules.AreBothVarsEqualOne setter implementation
            bBothEqualOne = value;
        }
    }

    public bool AreBothVarsEqualZero
    {
        get
        {
            // TODO:  Add Rules.AreBothVarsEqualZero getter implementation
            return bBothEqualZero;
        }
        set
        {
            // TODO:  Add Rules.AreBothVarsEqualZero setter implementation
            bBothEqualZero = value;
        }
    }

#endregion

如您所见,接口的实现仅仅是标准地设置值,以说明哪个规则已实现,哪个规则未实现。规则的实现是在`Rules`类的`Compare`函数中。

public int Compare( FuzzyInteger nOne, FuzzyInteger nTwo )
{
    if( IsOneVarEqualOne == true )
    {
        if( nOne.Number == 1 && nTwo.Number == 0 
                || nTwo.Number == 1 && nOne.Number == 0 )
            return 1;
        else
            return 0;
    }
    else if( IsOneVarEqualZero == true )
    {
        if( nOne.Number == 0 && nTwo.Number == 1 
                || nTwo.Number == 0 && nOne.Number == 1 )
            return 1;
        else
            return 0;
    }
    else if( AreBothVarsEqualOne == true )
    {
        if( nOne.Number == 1 && nTwo.Number == 1 )
            return 1;
        else
            return 0;
    }
    else if( AreBothVarsEqualZero == true )
    {
        if( nOne.Number == 0 && nTwo.Number == 0 )
            return 1;
        else
            return 0;
    }
    else
        return 0;

}

所有`Compare`函数真正做的就是检查当前正在执行哪个规则,规则的实现非常简单。

代码的循环是

for( int i=0; i<patterns.Count; i++ )
{
    leftValue = ( ( FuzzyIntegerPattern )patterns[ i ] ).InputValue( 0 );
    rightValue = ( ( FuzzyIntegerPattern )patterns[ i ] ).InputValue( 1 );

    Rules rule = new Rules();

    if( this.oneVarCheckBox.Checked == true )
    {
        rule.IsOneVarEqualOne = true;
        rule.IsOneVarEqualZero = false;
        rule.AreBothVarsEqualZero = false;
        rule.AreBothVarsEqualOne = false;
        outputBox.AppendText( "One Var is Equal to One Rule Used\n" );
    }
    else if( this.zeroVarCheckBox.Checked == true )
    {
        rule.IsOneVarEqualZero = true;
        rule.IsOneVarEqualOne = false;
        rule.AreBothVarsEqualOne = false;
        rule.AreBothVarsEqualZero = false;
        outputBox.AppendText( "One Var is Equal to Zero Rule Used\n" );
    }
    else if( this.allOneCheckBox.Checked == true )
    {
        rule.AreBothVarsEqualOne = true;
        rule.IsOneVarEqualOne = false;
        rule.IsOneVarEqualZero = false;
        rule.AreBothVarsEqualZero = false;
        outputBox.AppendText( "Both Vars are Equal to One Rule Used\n" );
    }
    else
    {
        rule.AreBothVarsEqualZero = true;
        rule.IsOneVarEqualOne = false;
        rule.IsOneVarEqualZero = false;
        rule.AreBothVarsEqualOne = false;
        outputBox.AppendText( "Both Vars are Equal to Zero Rule Used\n" );
    }


    switch( rule.Compare( leftValue, rightValue ) )
    {
        case 0: 
        {
            outputBox.AppendText( "Zero returned when comparing, left value :- " 
            + leftValue.Number.ToString() + ", and right value :- " 
            + rightValue.Number.ToString() + "\n" );
        }break;
        case 1:
        {
            outputBox.AppendText( "One returned when comparing, left value :- " 
            + leftValue.Number.ToString() + ", and right value :- " 
            + rightValue.Number.ToString() + "\n" );
        }break;
        default: outputBox.AppendText( "Arrgghh Vomit Stains\n" ); break;
    }

}

代码的主循环只是检查规则页面上哪个复选框被选中,然后实现该规则。如果你手速很快或者电脑非常慢,你或许可以在代码运行时更改规则,但这个示例的目的只是为了展示如何做到这一点。如果你更改规则并直接运行代码,新的规则将会生效。

最后

到目前为止,这个规则概念尚未在任何严肃或稍微复杂的项目上进行测试,看看它是否能像许多好主意一样,经受住超出简单示例的实际开发,或者它是否会消失在混乱之中,这将非常有趣。有时,我觉得它最终会融入大型项目的背景中,而无法提供任何实际好处,而有时,我又觉得它会提供一个更好、更容易理解的结构,但最终,只有一种方法可以找出答案,那就是闭嘴,好好工作。

© . All rights reserved.