遗传算法在数据分类中的应用

遗传算法是一种模仿自然界进化过程的优化算法。在自然界中,新一代的生物体通过遗传和变异,能够超越老一代,展现出更强的适应性和一致性。本文将探讨如何利用遗传算法来帮助对数据进行分类,特别是基于一个称为遗传算法函数的函数。

设想有一组数据,这些数据由具有相同行为特征的不同数据组组合而成。这意味着,尽管每个数据组都有自己的功能,但差异仅在于函数参数。下图展示了XY坐标上的一些点。显然,数据由两个数据组组成。现在让想象一个条件,已经知道公式,每个组都是由函数y=ax+b生成的。在这个例子中,没有面临严重的分类问题,因为只有两个组,数据清晰地分开了。

在更复杂的例子中,无法遵循这样的程序。例如,假设有1000个数据集中的五个不同的数据组,这些数据组分散在XY坐标或两个或更多数据组的交叉区域。在这里,人类的观察对于数据分类来说不够可靠。如果尝试为不同的数据组和函数找到均方误差(MSE),只是在浪费时间,因为在大多数情况下,需要计算数十亿个数学项。这就是在这类问题中需要遗传算法的地方。

本文不涵盖所有遗传算法的主题,而只是一个应用示例,展示了如何根据可用的相关性对不同数据进行分类。让考虑一个数据组索引的数组。这个数组的长度等于数据集的数量,对于每个数据集(X和Y),它在自己的元素内部有自己的组索引。例如,在上图中,可能有0和1的数组,因为假设只有两个数据组。

这样的数组可以以不同的形式出现,每种形式都有自己基于遗传算法函数(这里y=ax+b)计算参数的MSE。下图展示了这种数组的十种不同形式。一开始随机设置值。现在遗传算法开始了。

首先,算法应该计算所有十个案例的MSE。称这些案例为遗传算法字符串。显然,每个字符串都有自己的MSE。计算错误后,现在可以猜测更接近最终分类的字符串。这里将字符串从最好的MSE到最差的排序。事实上,每个猜测的索引在字符串内部都有另一个MSE。遗传算法的演变取决于更好的元素选择来进行交换。换句话说,为了选择最好的元素(进行交换),需要知道它的MSE。对于这样的MSE最高值,可以说当前元素没有正确设置,因此它的值可以被附近字符串中具有类似特征的每个元素的值交换。

接下来,开始交换字符串中高内部MSE元素的值,以这种方式,每个字符串与其邻域的字符串交换值。这就是字符串数量是偶数的原因。交换元素的数量可以随机设置,但对于更可靠的结果和更稳定的算法,最好在每个循环中进行更少的交换。在上面的图中,在前两个字符串中进行了两次交换,对于其他字符串对,这个数字可以不同。这里完成了第一个循环。现在必须通过重新计算MSEs重新启动程序。因此,一个循环中的程序包括三个步骤:

  • 计算字符串及其元素的MSEs
  • 根据MSEs对字符串进行排序
  • 交换高误差元素值

请记住,这个算法是可以使用的数十种算法之一。有更多更快收敛的方法和技巧,但这个例子足够简单明了,易于理解和应用。

使用代码

首先,必须声明适合数据处理的数据结构。

Structure DataGroup Dim X() As Double Dim Y() As Double End Structure Structure GeneticString Dim X() As Double Dim Y() As Double End Structure

为了评估MSE,必须将点拟合到GA函数。这个拟合过程的主要结果是回归参数。在这种情况下,假设函数是y=ax+b,所以参数是a和b。

Structure RegressionParameter Dim a As Double Dim b As Double End Structure

显然,需要检查GA在每个循环中的响应。

Structure Output Dim RP() As RegressionParameter Dim BestString As GeneticString Dim MSE As Double End Structure

现在可以声明属性:

属性 类型 描述
Epoch Integer 最大循环次数
MSE Double 期望的MSE
StringCount Short 算法中的字符串数量

还声明了两个事件:Epochs和Goalmet。它们的名字很直接。Epochs事件将在每次循环完成时执行,Goalmet将在达到最大循环次数或错误低于期望MSE时调用。

根据上述三个步骤,可以将子程序和函数分为三组。

Sub CalculateBitError(ByRef GString As _GeneticString, ByVal RParameter() As _RegressionParameter) Function ReturnMSE(ByVal DGroup() As _DataGroup, ByVal RP() As _RegressionParameter) As Double Function FindPointMSE(ByVal X As Double, ByVal Y As Double, ByVal RP As _RegressionParameter) As Double Function FindMSE(ByVal X() As Double, ByVal Y() As Double, ByVal RP As _RegressionParameter) As Double Function PerformRegression(ByVal DGroup() As _DataGroup, ByRef RP() As _RegressionParameter) As Boolean Function LinearRegression(ByVal X() As Double, ByVal Y() As Double, ByRef b As Double, ByRef a As Double) As Boolean Sub Sort(ByRef GString() As _GeneticString) Sub Switch(ByRef Val1 As Double, ByRef Val2 As Double) Sub BitExchange(ByRef STC() As _GeneticString) Sub Exchange(ByRef STC1 As _GeneticString, ByRef STC2 As _GeneticString, ByVal num As Integer) Function PrepareDataGroup(ByVal LineCount As Integer, ByRef GString As _GeneticString, ByVal X() As Double, ByVal Y() As Double) As _DataGroup()

上述大多数子程序和函数的作用是清楚的。所有这些代码都在GA类中,所以需要实例化这个类。

点击分类按钮执行以下代码。这里GetXY子程序返回DataGridView中的X和Y值。

Dim DG As New GA._DataGroup GetXY(DG.X, DG.Y) With GA .DataGroup = DG .StringCount = nud1.Value .Epoch = TextBox1.Text .MaxMSE = TextBox2.Text .Run() End With

结果将保存在GA的Output属性中,可以从GoalMet事件处理程序中读取。最好的GA字符串——这是一个0和1的数组——可以用来用不同的颜色表示分类,如下所示。就是这样!

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485