背景与简介
在现代数据分析和机器学习的世界中,Excel可能不是第一个被想到的工具。然而,借助VBA(Visual Basic for Applications),Excel具备创建复杂且功能强大的神经网络工具箱的能力。本文将介绍如何利用Excel和VBA实现一个基本的神经网络工具箱,帮助用户进行机器学习任务,并展示其在处理数据集、构建神经网络、训练及测试模型中的具体应用。
神经网络工具箱的基本结构
首先,我们需要定义神经网络的基本结构。神经网络由多个层组成,每一层包含若干“神经元”。每个神经元模拟一个感知器,通过输入信号经过加权求和,再通过激活函数得到输出。
1. 神经元的数据结构
在VBA中,我们可以用Type定义一个简单的神经元数据结构:
Public Type NNUnit
b As Double ‘ 偏置值
w() As Double ‘ 权值数组
End Type
2. 层的数据结构
每一层包含若干神经元,同时需要指定激活函数类型:
Public Type layer
units() As NNUnit ‘ 此层的所有神经元
ActiF As Byte ‘ 激活函数类型
End Type
3. 网络的数据结构
整个神经网络包含若干层,并且需要一个明确的输入层和输出层:
Public Type NN
inSize As Long ‘ 输入向量的大小
hLayer() As layer ‘ 隐藏层数组
hLayerCount As Long ‘ 隐藏层的计数
OutLayer As layer ‘ 输出层
End Type
神经网络的创建与初始化
1. 创建新神经网络
我们可以通过以下函数创建一个单层网络:
Public Function newNN(name As String, inSize As Long, outSize As Long, outF As Byte) As NN
Dim net As NN, l As layer
Dim i As Long
With l
ReDim .units(1 To outSize)
For i = 1 To outSize
.units(i) = newUnit(inSize) ‘ 插入空单元到输出层
.units(i).utf = outF
Next
End With
With net
.inSize = inSize
.OutLayer = l
.hLayerCount = 0
End With
newNN = net
End Function
2. 添加隐藏层
为了增加网络的深度,可以在输出层之前插入新的隐藏层:
Public Function NNAddLayer(net As NN, ByVal B As Long, f As Byte) As NN
Dim newLayer As layer
Dim i As Long, j As Long, k As Long
‘ 重置输出层的连接数
For i = 1 To net.OutLayer.units.Count
ReDim net.OutLayer.units(i).w(1 To B)
Next
‘ 创建新的隐藏层并添加到网络中
Set newLayer = New layer
With newLayer
ReDim .units(1 To B)
For i = 1 To B
.units(i) = newUnit(net.hLayer(UBound(net.hLayer)).units.Count)
.units(i).utf = f
Next
End With
ReDim net.hLayer(UBound(net.hLayer) + 1)
net.hLayer(UBound(net.hLayer) – 1) = newLayer
ReDim net.hLayerCount(net.hLayerCount + 1)
NNAddLayer = net
End Function
前向传播算法的实现
在前向传播中,神经网络的每一层都会接收输入信号,并通过激活函数生成输出。以下是前向传播的实现代码:
Private Function calcUnit(unit As NNUnit, vec() As Double, f As Byte, Optional d As Byte = 1) As Double
‘ 计算单个神经元的输出值
Dim wc As Long, vc As Long, dimension As Byte
Dim i As Long, j As Long, k As Long
Dim result As Double
On Error GoTo errorHandler
With unit
result = 0
Select Case d
Case 1
For i = 1 To UBound(.w, 1)
result = result + .w(i) * vec(i)
Next
Case 2
For i = 1 To UBound(.w, 1)
For j = 1 To UBound(.w, 2)
result = result + .w(i, j) * vec(i, j)
Next
Next
Case 3
For i = 1 To UBound(.w, 1)
For j = 1 To UBound(.w, 2)
For k = 1 To UBound(.w, 3)
result = result + .w(i, j, k) * vec(i, j, k)
Next
Next
Next
End Select
result = result + .b
result = UTFunction(f, result)
End With
calcUnit = result
Exit Function
errorHandler:
MsgBox “Error calculating the unit value.”
End Function
训练数据的导入与处理
在训练神经网络之前,必须准备好数据。我们可以通过以下方式导入和处理数据:
1. 从单元格区域导入数据
Sub BuildFromRange()
Dim rng As Range, c As Range, data() As Double, yData() As Double
Dim i As Long, j As Long, t As Long, titleRow As Boolean
t = Timer
On Error Resume Next
Set rng = Application.InputBox(“请选择数据区域”, “”, , Type:=8)
If rng Is Nothing Then Exit Sub
titleRow = rng.Cells(1, 1).HasFormula
If titleRow Then
t = Timer
ReDim data(1 To rng.Rows.Count, rng.Columns.Count)
For i = 1 To rng.Rows.Count
For j = 1 To rng.Columns.Count
data(i, j) = rng.Cells(i, j).Value
Next
Next
yData = data ‘ 假设最后一列为Target数据
ReDim PreserveData(1 To UBound(data, 1) – 1, 1 To UBound(data, 2) – 1)
For i = 1 To UBound(PreserveData)
For j = 1 To UBound(PreserveData(i))
PreserveData(i, j) = data(i, j)
Next
Next
Call TrainAndTestAnn(PreserveData, yData)
MsgBox “用时 ” & (Timer – t) & ” 秒”
Else
MsgBox “请勾选标题行”
End If
End Sub
2. 数据归一化处理
Sub NormalizeData(data() As Double) ‘ 数据归一化处理略过,类似前面例子中的实现方法
神经网络的训练算法
1. 梯度下降法
Sub GradientDescent(ByRef ann As NN, ByRef dataX() As Double, ByRef dataY() As Double, ByVal learningRate As Double, ByVal maxEpochs As Long)
Dim i As Long, j As Long, k As Long, n As Long, m As Long ‘ 训练轮数和样本计数略过,具体实现参考前面的代码段
‘…
End Sub
2. Levenberg-Marquardt (Levenberg-Marquardt) 算法和SCG算法等可以类似地实现。
总结与展望
通过以上步骤和代码示例,我们已经实现了一个基本的Excel神经网络工具箱,能够创建神经网络、导入和处理数据、进行前向传播和反向传播等操作。这个工具箱不仅可以用于教学演示,还能在实际应用中发挥其作用。未来,我们可以进一步扩展功能,支持更多种类的神经网络和优化算法,以增强其在机器学习任务中的实用性和灵活性。