無限不可能性ドライブ

『ニューラルネットワーク自作入門』に刺激されてExcelVBAでニューラルネットワークを作ってみたものの、やっぱり数学やらなきゃと思い少しずつやってきたのもあって、自分の知識の整理とかそういった感じです。

【VBA編】ニューラルネットワーク(classInputUnit, classUnit)

入力層のユニットクラス

入力層のみ実装が異なります。

'[classInputUnit - 入力層のユニットクラス]
Option Explicit

Dim mX As Double

'入力データをセットする
'[引数] <- inputData : Double / 入力データ
Public Property Let X(ByRef aInputData As Double)
    mX = aInputData
End Property

'入力データを返す
'[戻り値] -> X : Double / 入力データ
Public Property Get X() As Double
    X = mX
End Property

ユニットクラス

ユニットクラスの実装です。

'[classUnit - ユニットクラス]
Option Explicit
Option Base 1

Dim mWeightList() As Double         '重みのリスト
Dim mBias As Double                 'バイアス
Dim mU As Double                    '活性化関数適用前の合計値
Dim mZ As Double                    '出力値

'パラメータ(重みとバイアス)を初期化する
'[引数] <- aWeightCount : Long / 重みの数
Public Sub Initialize(ByRef aWeightCount As Long)
    Dim i As Long
    
    ReDim mWeightList(aWeightCount)
    '各重みをランダム値で初期化
    For i = 1 To aWeightCount
        mWeightList(i) = ML.getRandom()
    Next
    
    'バイアスを0で初期化
    mBias = 0
    
End Sub

'活性化関数適用前の合計値を計算する
'入力値にそれぞれの重みを掛けてバイアス値を加える
'[引数] <- aInputDataList() : Double / 入力値のリスト
Public Sub CalcU(ByRef aInputDataList() As Double)
    Dim i As Long

    mU = mBias
    For i = 1 To UBound(aInputDataList)
        mU = mU + (mWeightList(i) * aInputDataList(i))
    Next
    
End Sub

'活性化関数適用前の合計値を返す
'[戻り値] -> U : Double / 活性化関数適用前の合計値
Public Property Get U() As Double
    U = mU
End Property

'出力値を格納する
'[引数] <- aActivatedU : Double / 活性化関数適用後の合計値
Public Property Let Z(ByRef aActivatedU As Double)
    mZ = aActivatedU
End Property

'出力値を返す
'[戻り値] -> Z : Double / 出力値
Public Property Get Z() As Double
    Z = mZ
End Property

'バイアス値をセットする
'[引数] <- aBias : Double / バイアス値
Public Sub SetBias(ByRef aBias As Double)
    mBias = aBias
End Sub

'バイアス値を返す
'[戻り値] -> GetBias : Double / バイアス値
Public Function GetBias() As Double
    GetBias = mBias
End Function

'重みをセットする
'[引数] <- aIndex : Long / インデックス, aW : Double / 重み
Public Sub SetW(ByRef aIndex As Long, ByRef aW As Double)
    mWeightList(aIndex) = aW
End Sub

'重みを返す
'[引数] <- aIndex : Long / インデックス
'[戻り値] -> GetW : Double / 重み
Public Function GetW(ByRef aIndex As Long) As Double
    GetW = mWeightList(aIndex)
End Function

'バックプロパゲーション(重みを更新する)
'(学習率 × 勾配 × 入力値)の計算結果を重みから引いて、重みを更新する
'バイアスも同様に計算する(ただし、バイアスの入力値は 1)
'[引数] <- aDelta : Double / 勾配の計算結果, aInputDataList() : Double / 入力値のリスト
'Public Sub UpdateWeight(ByRef aDelta As Double, ByRef aInputDataList() As Double)
Public Sub Backprop(ByRef aDelta As Double, ByRef aInputDataList() As Double)
    Dim i As Long
    
    For i = 1 To UBound(mWeightList)
        mWeightList(i) = mWeightList(i) - (G.LearningRate * aDelta * aInputDataList(i))
    Next
    
    mBias = mBias - (G.LearningRate * aDelta * 1)
    
End Sub


f:id:celaeno42:20181212233850p:plain