home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 3_2004-2005.ISO / Data / Zips / Face_Recog1866873232005.psc / NNFaceRec / cNetFast.cls < prev   
Text File  |  2005-03-23  |  25KB  |  748 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "NetFast"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15. #Const ShowDebugTimes = 0
  16.  
  17. '----------------------------------------------------------------------------------------------------------------
  18. ' Neural Net Code and classes originally by Ulli (umgedv@aol.com)
  19. ' Conversion to ActiveX Object Library and other improvements
  20. ' by Jonathan Daniel (bigcalm@hotmail.com)
  21. ' This class is an array based version of a neural net.
  22. '
  23. ' This code is shareware.  Please credit the authors if you use this code.
  24. '
  25. ' Bugs, fixes, improvements, and suggestions to bigcalm@hotmail.com
  26. '
  27. '----------------------------------------------------------------------------------------------------------------
  28. ' Many thanks to Chikh for all his help.
  29. ' Some code was adapted from Jason Tiscione's java code.
  30. ' Urgh my brain hurts after reading the neural net FAQ at faqs.org
  31.  
  32.  
  33. Private Declare Function GetTickCount Lib "kernel32" () As Long
  34.  
  35. Private Type Synapse
  36.   TransferWeight As Double
  37. End Type
  38.  
  39. Private Type Neuron
  40.   Value As Double
  41.   Error As Double
  42.   BaseValue As Double
  43. End Type
  44.  
  45. Private Type Layer
  46.   StartNeuron As Long
  47.   EndNeuron As Long
  48.   StartDendrite As Long
  49.   EndDendrite As Long
  50.   NeuronCount As Long
  51.   DendriteCount As Long
  52. End Type
  53.  
  54. Private StartTime As Long
  55.  
  56. ' Constants for load/save.
  57. Private Const OCXNAME As String = "Perceptron"
  58. Private Const VERSION As String = "1.3"
  59.  
  60. ' Main objects
  61. Private Dendrites() As Synapse
  62. Private Neurons() As Neuron
  63. Private Layers() As Layer
  64.  
  65. ' From cNet
  66. Private mvarCreated As Boolean
  67. Private mTag As Variant
  68. Private mTrainingCycles As Long
  69. Private mLearningCoefficient As Double
  70. Private mLearningRateIncrease As Double
  71. Private mLearningRateDecrease As Double
  72. 'Private mMaximumErrorRate As Double
  73. Private mAnnealingEpoch As Long
  74. Private mAnnealingSSE As Double
  75. Private mLastAnnealingSSE As Double
  76. Private mSumSquaredError As Double
  77. Private mRunning As Boolean ' Because we're allowing the caller to utilise
  78.   ' DoEvents when we Raise an event, we need a Boolean value to stop
  79.   ' something being called twice (or say Destroy being called while we're training).
  80.   ' Also allow owner to read this property if they want.
  81. Private mStopping As Boolean ' Set this flag to abort current procedure.
  82.       ' Set by calling StopWorking.  Not available as a property (yet).
  83. ' Events
  84. ' These three events will be raised so the controlling application has information
  85. ' on what's going on.  It'll also give the controlling app a chance to do things
  86. ' like DoEvents for example.
  87. ' These are useful for progress bars/panels/etc.  Just define your net "WithEvents"
  88. ' to use these.
  89. Public Event InfoMessage(vTag As Variant, Info As String)
  90. Public Event Progress(vTag As Variant, Percentage As Single)
  91. '
  92. ' Example use for Progress...
  93. ' Private WithEvents MyNet as New cNet
  94. ' Private Sub Form_Click()
  95. '   If MyNet.Running = True Then
  96. '     Exit Sub
  97. '   End If
  98. '   ProgressBar1.Visible = True
  99. '   ProgressBar1.Min = 0
  100. '   ProgressBar1.Max = 0
  101. '   ProgressBar1.Value = 0
  102. '   MyNet.CreateNet(Array(60,8,2))
  103. '   ProgressBar1.Visible = False
  104. ' End Sub
  105. ' Private Sub MyNet_Progress(vTag as Variant, Percentage as Single)
  106. '   ProgressBar1.Value = Percentage
  107. '   DoEvents
  108. ' End Sub
  109.  
  110. ' Property Let/Get/Sets. from cNet
  111. Public Property Get Created() As Boolean
  112.   Created = mvarCreated
  113. End Property
  114. Friend Property Let Created(ByVal vData As Boolean)
  115.   mvarCreated = vData
  116. End Property
  117. Public Property Get TrainingCycles() As Long
  118.   TrainingCycles = mTrainingCycles
  119. End Property
  120. Friend Property Let TrainingCycles(ByVal vData As Long)
  121.   mTrainingCycles = vData
  122. End Property
  123. Public Property Let LearningCoefficient(ByVal vData As Double)
  124.   mLearningCoefficient = vData
  125. End Property
  126. Public Property Get LearningCoefficient() As Double
  127.   LearningCoefficient = mLearningCoefficient
  128. End Property
  129. Public Property Let LearningRateIncrease(ByVal vData As Double)
  130.   mLearningRateIncrease = vData
  131. End Property
  132. Public Property Get LearningRateIncrease() As Double
  133.   LearningRateIncrease = mLearningRateIncrease
  134. End Property
  135. Public Property Let LearningRateDecrease(ByVal vData As Double)
  136.   mLearningRateDecrease = vData
  137. End Property
  138. Public Property Get LearningRateDecrease() As Double
  139.   LearningRateDecrease = mLearningRateDecrease
  140. End Property
  141. 'Public Property Let MaximumErrorRate(ByVal vData As Double)
  142. '  mMaximumErrorRate = vData
  143. 'End Property
  144. 'Public Property Get MaximumErrorRate() As Double
  145. '  MaximumErrorRate = mMaximumErrorRate
  146. 'End Property
  147.  
  148. Public Property Get SumSquaredError() As Double
  149.   SumSquaredError = mSumSquaredError
  150. End Property
  151. Friend Property Let SumSquaredError(ByVal vData As Double)
  152.   mSumSquaredError = vData
  153. End Property
  154.  
  155. ' This should properly be called "Mean Square Error"
  156. Public Property Get AverageSquaredError() As Double
  157.   If mvarCreated = True Then
  158.     AverageSquaredError = mSumSquaredError / Layers(UBound(Layers)).NeuronCount
  159.   Else
  160.     AverageSquaredError = 0
  161.   End If
  162. End Property
  163. Public Property Get AnnealingEpoch() As Long
  164.   AnnealingEpoch = mAnnealingEpoch
  165. End Property
  166. Public Property Let AnnealingEpoch(ByVal vData As Long)
  167.   mAnnealingEpoch = vData
  168. End Property
  169.  
  170. Public Property Get Tag() As Variant
  171.   If IsObject(mTag) Or mTag Is Nothing Then
  172.     Set Tag = mTag
  173.   Else
  174.     Tag = mTag
  175.   End If
  176. End Property
  177. Public Property Set Tag(ByVal vData As Variant)
  178.   Set mTag = vData
  179. End Property
  180. Public Property Let Tag(ByVal vData As Variant)
  181.   mTag = vData
  182. End Property
  183.  
  184. Public Property Get Running() As Boolean
  185.   Running = mRunning
  186. End Property
  187. Private Property Let Running(ByVal vData As Boolean)
  188.   mRunning = vData
  189. End Property
  190. Public Property Get TotalNeuronCount() As Long
  191.   TotalNeuronCount = UBound(Neurons) - LBound(Neurons) + 1
  192. End Property
  193.  
  194. Public Property Get OutputLayer(Index As Long) As Double
  195.   If mvarCreated = True Then
  196.     OutputLayer = Neurons(Layers(UBound(Layers)).StartNeuron + Index - 1).Value
  197.   Else
  198.     Err.Raise vbObjectError + 2, "Perceptron", "You must initialise your net before you attempt to retrieve output from it"
  199.     OutputLayer = 0
  200.   End If
  201. End Property
  202.  
  203. Public Sub SetInput(Data As Variant)
  204. Dim i As Long
  205.  
  206.     If mStopping = True Then
  207.       Exit Sub
  208.     End If
  209.     
  210.     ' error checking on passed Data here:
  211.     
  212.     RaiseEvent InfoMessage(mTag, "Initialising Input Layer")
  213.     
  214.     For i = Layers(LBound(Layers)).StartNeuron To Layers(LBound(Layers)).EndNeuron
  215.         Neurons(i).Value = CDbl(Data(i))
  216.     Next i
  217. End Sub
  218.  
  219. ' This can be publicly called - the function that actually does the work is a hidden
  220. ' procedure called CalculateOutput (below).
  221. Public Sub ProcessOutput()
  222.   If mvarCreated = False Then
  223.     Err.Raise vbObjectError + 2, "Perceptron", "You must initialise your net before you attempt to retrieve output from it"
  224.     Exit Sub
  225.   End If
  226.   If mRunning = True Then
  227.     Exit Sub
  228.   End If
  229.   #If ShowDebugTimes = 1 Then
  230.   StartTime = GetTickCount
  231.   #End If
  232.   mRunning = True
  233.   mStopping = False
  234.   CalculateOutput
  235.   #If ShowDebugTimes = 1 Then
  236.   Debug.Print "Time to process output: " & GetTickCount - StartTime & " ms"
  237.   #End If
  238.   mRunning = False
  239. End Sub
  240.  
  241. Friend Sub CalculateOutput()
  242. Dim i As Long, j As Long, k As Long
  243. Dim TotalToDo As Long
  244. Dim Percentage As Long
  245. Dim WorkDone As Long
  246. Dim PrevNLayerPtr As Long
  247.   
  248.   ' Calculate work to be done
  249.   TotalToDo = UBound(Neurons) - Layers(LBound(Layers) + 1).StartNeuron + 1
  250.   Percentage = TotalToDo / 100
  251.   WorkDone = 0
  252.   
  253.   ' Apologies for the complexity of this - whenever I've seen nn code before, it's
  254.   ' always too complex to understand.  Hence the original OO stuff adapted from
  255.   ' Ulli.  However, I've gone back to complexity to save on speed. :-(
  256.   
  257.   ' Go through all the layers except the first one
  258.   For i = LBound(Layers) + 1 To UBound(Layers)
  259.     RaiseEvent InfoMessage(mTag, "Calculating Output For Layer " & i)
  260.     ' Go through all neurons in this layer
  261.     For j = Layers(i).StartNeuron To Layers(i).EndNeuron
  262.       ' for each neuron, sum the total of it's inputs from the previous layer.
  263.       Neurons(j).Value = 0
  264.       PrevNLayerPtr = Layers(i - 1).StartNeuron
  265.       For k = Layers(i).StartDendrite + ((j - Layers(i).StartNeuron) * Layers(i - 1).NeuronCount) To Layers(i).StartDendrite + ((j - Layers(i).StartNeuron) * Layers(i - 1).NeuronCount) + Layers(i - 1).NeuronCount
  266.         Neurons(j).Value = Neurons(j).Value + (Neurons(PrevNLayerPtr).Value * Dendrites(k).TransferWeight)
  267.         PrevNLayerPtr = PrevNLayerPtr + 1
  268.       Next k
  269.       ' sigmoid squash
  270.       Neurons(j).Value = Squish(Neurons(j).Value + Neurons(j).BaseValue)
  271.       WorkDone = WorkDone + 1
  272.       If WorkDone Mod Percentage = 0 Then
  273.         RaiseEvent Progress(mTag, (WorkDone / TotalToDo) * 100)
  274.       End If
  275.       If mStopping = True Then
  276.         Exit For
  277.       End If
  278.     Next j
  279.     If mStopping = True Then
  280.       Exit For
  281.     End If
  282.   Next i
  283. End Sub
  284.  
  285. Private Sub AdjustWeights(Target As Variant)
  286.   Dim i As Long, j As Long, k As Long
  287. Dim Percentage As Long
  288. Dim WorkDone As Long
  289. Dim TotalToDo As Long
  290. Dim SSE As Double
  291. Dim PrevNLayerPtr As Long
  292.  
  293.     j = 0
  294.     RaiseEvent InfoMessage(mTag, "Training the Net")
  295.     
  296.     'calculation of raw error in output layer
  297.     SSE = 0
  298.     For i = Layers(UBound(Layers)).StartNeuron To Layers(UBound(Layers)).EndNeuron
  299.       Neurons(i).Error = CDbl(Target(j)) - Neurons(i).Value
  300.       SSE = SSE + (Neurons(i).Error * Neurons(i).Error)
  301.       j = j + 1
  302.     Next i
  303.     
  304.     ' Simulated annealing - adjustment of learning coefficient to match error value.
  305.     If mAnnealingEpoch > 0 Then
  306.         mAnnealingSSE = mAnnealingSSE + SSE
  307.         If mTrainingCycles Mod mAnnealingEpoch = 0 And mTrainingCycles > 0 Then
  308.             If mLastAnnealingSSE > 0 Then
  309.                 If mAnnealingSSE < mLastAnnealingSSE Then
  310.                     mLearningCoefficient = mLearningCoefficient * mLearningRateDecrease
  311.                 Else
  312.                     mLearningCoefficient = mLearningCoefficient * mLearningRateIncrease
  313.                 End If
  314.             End If
  315.             mLastAnnealingSSE = mAnnealingSSE
  316.             mAnnealingSSE = 0
  317.         End If
  318.     End If
  319.     
  320.     mSumSquaredError = SSE
  321.     
  322.     If mStopping = True Then
  323.       Exit Sub
  324.     End If
  325.     
  326.     ' Calculate work to be done
  327.     TotalToDo = UBound(Neurons) - Layers(LBound(Layers) + 1).StartNeuron + 1
  328.     Percentage = TotalToDo \ 100
  329.     WorkDone = 0
  330.     
  331.     'hidden layers
  332.     For i = UBound(Layers) To LBound(Layers) + 1 Step -1
  333.         RaiseEvent InfoMessage(mTag, "Running Back Propogation on Layer " & i)
  334.         For j = Layers(i).StartNeuron To Layers(i).EndNeuron
  335.           ' Back propagate.
  336.           With Neurons(j)
  337.             .Error = .Error * .Value * (1# - .Value) ' proportional error
  338.           End With
  339.           ' Now, update all connected neurons error appropriately:
  340.           PrevNLayerPtr = Layers(i - 1).StartNeuron
  341.           For k = Layers(i).StartDendrite + ((j - Layers(i).StartNeuron) * Layers(i - 1).NeuronCount) To Layers(i).StartDendrite + ((j - Layers(i).StartNeuron) * Layers(i - 1).NeuronCount) + Layers(i - 1).NeuronCount
  342.             Neurons(PrevNLayerPtr).Error = Neurons(PrevNLayerPtr).Error + (Neurons(j).Error * Dendrites(k).TransferWeight)
  343.             PrevNLayerPtr = PrevNLayerPtr + 1
  344.           Next k
  345.         Next j
  346.         WorkDone = WorkDone + 1
  347.         If WorkDone Mod Percentage = 0 Then
  348.           RaiseEvent Progress(mTag, (WorkDone / TotalToDo) * 100)
  349.         End If
  350.         If mStopping = True Then
  351.           Exit For
  352.         End If
  353.     Next i
  354.         
  355.     If mStopping = True Then
  356.       Exit Sub
  357.     End If
  358.     
  359.     ' Calculate work to be done
  360.     TotalToDo = UBound(Neurons) - Layers(LBound(Layers) + 1).StartNeuron + 1
  361.     Percentage = TotalToDo \ 100
  362.     WorkDone = 0
  363.     
  364.     ' Update weights
  365.     For i = UBound(Layers) To LBound(Layers) + 1 Step -1
  366.           RaiseEvent InfoMessage(mTag, "Updating Weights in Layer " & i)
  367.           For j = Layers(i).StartNeuron To Layers(i).EndNeuron
  368.               ' update base value
  369.               With Neurons(j)
  370.                 .BaseValue = .BaseValue + mLearningCoefficient * .Error
  371.               End With
  372.               ' update dendrite weights
  373.               PrevNLayerPtr = Layers(i - 1).StartNeuron
  374.               For k = Layers(i).StartDendrite + ((j - Layers(i).StartNeuron) * Layers(i - 1).NeuronCount) To Layers(i).StartDendrite + ((j - Layers(i).StartNeuron) * Layers(i - 1).NeuronCount) + Layers(i - 1).NeuronCount
  375.                 With Dendrites(k)
  376.                   .TransferWeight = .TransferWeight + mLearningCoefficient * Neurons(PrevNLayerPtr).Value * Neurons(j).Error
  377.                 End With
  378.                 PrevNLayerPtr = PrevNLayerPtr + 1
  379.               Next k
  380.               ' reset neuron error for next training cycle.
  381.               Neurons(j).Error = 0
  382.               WorkDone = WorkDone + 1
  383.               If WorkDone Mod Percentage = 0 Then
  384.                 RaiseEvent Progress(mTag, (WorkDone / TotalToDo) * 100)
  385.               End If
  386.               If mStopping = True Then
  387.                 Exit For
  388.               End If
  389.           Next j
  390.           If mStopping = True Then
  391.             Exit For
  392.           End If
  393.     Next i
  394.     
  395. End Sub
  396.  
  397. Public Sub Train(Data As Variant, Target As Variant)
  398.   If mvarCreated = True Then
  399.     If mRunning = True Then
  400.       Exit Sub
  401.     End If
  402.     ' need some error checking for data and target arrays to see if they're valid.
  403.     
  404.     mRunning = True
  405.     mStopping = False
  406.     #If ShowDebugTimes = 1 Then
  407.     StartTime = GetTickCount
  408.     #End If
  409.  
  410.     SetInput Data
  411.     If mStopping = False Then
  412.       CalculateOutput
  413.       If mStopping = False Then
  414.         AdjustWeights Target
  415.       End If
  416.     End If
  417.     
  418.   Else
  419.     Err.Raise vbObjectError + 1, "Perceptron", "You must initialise your net before you attempt to train it"
  420.     mStopping = True
  421.   End If
  422.   If mStopping = False Then
  423.     mTrainingCycles = mTrainingCycles + 1
  424.   End If
  425.   #If ShowDebugTimes = 1 Then
  426.   Debug.Print "Time for one training cycle to take place: " & GetTickCount - StartTime & " ms"
  427.   #End If
  428.   mRunning = False
  429. End Sub
  430.  
  431. ' Test Ok.
  432. Public Sub CreateNet(pTag As Variant, ParamArray Struc() As Variant)
  433. Dim TotalToDo As Long
  434. Dim TotalDone As Long
  435. Dim PercentageHit As Long
  436. Dim i As Long, TotalNeurons As Long, TotalSynapses As Long
  437.  
  438.     If mRunning = True Then
  439.       Exit Sub
  440.     End If
  441.     mRunning = True
  442.     mStopping = False
  443.     #If ShowDebugTimes = 1 Then
  444.     StartTime = GetTickCount
  445.     #End If
  446.     ' Initialise
  447.     ' Need to destroy first
  448.     DestroyNicely
  449.     Set Tag = pTag
  450.     mTrainingCycles = 0
  451.     mSumSquaredError = 0
  452.         
  453.     ' Redim all arrays.
  454.     ' Layers
  455.     ReDim Layers(LBound(Struc) To UBound(Struc)) ' maintains array base of ParamArray
  456.     ' Neurons
  457.     ' Total neurons - add up all the values in the Struc array.
  458.     ' Total synapses = Layer1*Layer2 + Layer2*Layer3 + Layer3*Layer4 etc.
  459.     TotalNeurons = 0
  460.     TotalSynapses = 0
  461.     RaiseEvent InfoMessage(mTag, "Initialising Neural arrays")
  462.     For i = LBound(Struc) To UBound(Struc)
  463.       Layers(i).StartNeuron = TotalNeurons
  464.       TotalNeurons = TotalNeurons + Struc(i)
  465.       Layers(i).EndNeuron = TotalNeurons - 1
  466.       Layers(i).NeuronCount = Struc(i)
  467.       If i <> LBound(Struc) Then
  468.         Layers(i).StartDendrite = TotalSynapses
  469.         TotalSynapses = TotalSynapses + (Struc(i) * Struc(i - 1))
  470.         Layers(i).EndDendrite = TotalSynapses - 1
  471.         Layers(i).DendriteCount = Struc(i) * Struc(i - 1)
  472.       Else
  473.         Layers(i).StartDendrite = 0
  474.         Layers(i).EndDendrite = 0
  475.         Layers(i).DendriteCount = 0
  476.       End If
  477.     Next i
  478.     ReDim Neurons(0 To TotalNeurons)
  479.     ReDim Dendrites(0 To TotalSynapses)
  480.         
  481.     ' Calculate work to be done
  482. '    RaiseEvent InfoMessage(mTag, "Randomising Weights and Base Values")
  483. '    TotalToDo = -LBound(Neurons) + UBound(Neurons) + 1 - LBound(Dendrites) + UBound(Dendrites) + 1
  484. '    PercentageHit = TotalToDo / 100
  485. '    TotalDone = 0
  486.     
  487.     NguyenWidrowInitialise
  488.     
  489. '    ' Set BaseValue for each neuron
  490. '    For i = LBound(Neurons) To UBound(Neurons)
  491. '      Neurons(i).BaseValue = GetRand
  492. '      TotalDone = TotalDone + 1
  493. '      If TotalDone Mod PercentageHit = 0 Then
  494. '        RaiseEvent Progress(mTag, (TotalDone / TotalToDo) * 100)
  495. '      End If
  496. '    Next i
  497. '    ' Set TransferWeight for each dendrite.
  498. '    For i = LBound(Dendrites) To UBound(Dendrites)
  499. '      Dendrites(i).TransferWeight = GetRand
  500. '      TotalDone = TotalDone + 1
  501. '      If TotalDone Mod PercentageHit = 0 Then
  502. '        RaiseEvent Progress(mTag, (TotalDone / TotalToDo) * 100)
  503. '      End If
  504. '    Next i
  505.     
  506. '    For i = LBound(Layers) To UBound(Layers)
  507. '      Debug.Print "Layer " & i & ": Neurons: " & Layers(i).StartNeuron; " - " & Layers(i).EndNeuron & "(" & Layers(i).NeuronCount & ")" & "      Dendrites: " & Layers(i).StartDendrite & " - " & Layers(i).EndDendrite & "(" & Layers(i).DendriteCount & ")"
  508. '    Next i
  509.     
  510.     If mStopping = True Then
  511.     Else
  512.       mvarCreated = True
  513.     End If
  514.     #If ShowDebugTimes = 1 Then
  515.     Debug.Print "Time to create net: " & GetTickCount - StartTime & " ms"
  516.     #End If
  517.     mRunning = False
  518. End Sub
  519.  
  520. ' This is a bit pointless now - just here to preserve compatibility with original cNet module.
  521. Public Sub DestroyNicely()
  522.   If mRunning = True Then
  523.     Exit Sub
  524.   End If
  525.   #If ShowDebugTimes = 1 Then
  526.   StartTime = GetTickCount
  527.   #End If
  528.   RaiseEvent InfoMessage(mTag, "Destroying Dendrites")
  529.   Erase Dendrites
  530.   RaiseEvent InfoMessage(mTag, "Destroying Neurons")
  531.   Erase Neurons
  532.   RaiseEvent InfoMessage(mTag, "Destroying Layers")
  533.   Erase Layers
  534.   mvarCreated = False
  535.   #If ShowDebugTimes = 1 Then
  536.   Debug.Print "Time to destroy net: " & GetTickCount - StartTime & " ms"
  537.   #End If
  538. End Sub
  539.  
  540. Private Sub Class_Initialize()
  541.   Randomize
  542.   mvarCreated = False
  543.   mLearningRateIncrease = 1#
  544.   mLearningRateDecrease = 1#
  545.   mAnnealingEpoch = 0
  546.   mAnnealingSSE = 0
  547.   mLastAnnealingSSE = 0
  548. End Sub
  549.  
  550. Private Sub Class_Terminate()
  551.   Erase Dendrites
  552.   Erase Neurons
  553.   Erase Layers
  554. End Sub
  555.  
  556. Public Sub Jitter(Optional MaxVariance As Double = 0.05)
  557. Dim i As Long, j As Long, k As Long
  558. Dim Variance As Double
  559. Dim TotalToDo As Long
  560. Dim TotalDone As Long
  561. Dim PercentageHit As Long
  562.  
  563.   If mRunning = True Or mvarCreated = False Then
  564.     Exit Sub
  565.   End If
  566.   mRunning = True
  567.   mStopping = False
  568.   #If ShowDebugTimes = 1 Then
  569.   StartTime = GetTickCount
  570.   #End If
  571.  
  572.   
  573.   TotalToDo = UBound(Dendrites) - LBound(Dendrites) + 1
  574.   PercentageHit = TotalToDo / 100
  575.   TotalDone = 0
  576.   
  577.   RaiseEvent InfoMessage(mTag, "Adding random noise to the net's weights")
  578.   For i = LBound(Dendrites) To UBound(Dendrites)
  579.     Variance = (MaxVariance * Rnd * 2) - MaxVariance
  580.     Dendrites(i).TransferWeight = Dendrites(i).TransferWeight + Variance
  581.     If Dendrites(i).TransferWeight < -1 Then
  582.       Dendrites(i).TransferWeight = -1
  583.     End If
  584.     If Dendrites(i).TransferWeight > 1 Then
  585.       Dendrites(i).TransferWeight = 1
  586.     End If
  587.     TotalDone = TotalDone + 1
  588.     If TotalDone Mod PercentageHit = 0 Then
  589.       RaiseEvent Progress(mTag, (TotalDone / TotalToDo) * 100)
  590.     End If
  591.   Next i
  592.   
  593.   #If ShowDebugTimes = 1 Then
  594.   Debug.Print "Time to jitter net: " & GetTickCount - StartTime & " ms"
  595.   #End If
  596.   
  597.   mRunning = False
  598. End Sub
  599.  
  600. Public Sub KickZeros(Optional Amount As Double = 0.05)
  601. Dim i As Long
  602. Dim tmpAmount As Double
  603.   For i = LBound(Dendrites) To UBound(Dendrites)
  604.     If Dendrites(i).TransferWeight <= 0.001 And Dendrites(i).TransferWeight >= -0.001 Then
  605.       tmpAmount = Amount * 2 * Rnd - Amount
  606.       Dendrites(i).TransferWeight = tmpAmount
  607.     End If
  608.   Next i
  609.   For i = LBound(Neurons) To UBound(Neurons)
  610.     If Neurons(i).BaseValue <= 0.001 And Neurons(i).BaseValue >= -0.001 Then
  611.       tmpAmount = Amount * Rnd
  612.       Dendrites(i).TransferWeight = tmpAmount
  613.     End If
  614.   Next i
  615. End Sub
  616.  
  617. Public Sub StopWorking()
  618.   mStopping = True
  619. End Sub
  620.  
  621. ' ok
  622. Public Function SaveNet(Filename As Variant, Optional SaveVersion As String = VERSION) As Boolean
  623. Dim FileNumber As Long
  624. Dim ll             As Long
  625. Dim Percentage As Long
  626. Dim WorkDone As Long
  627. Dim TotalToDo As Long
  628. Dim i As Long, j As Long, k As Long
  629. Dim SaveHeader As String
  630. Dim strVersion As String
  631.  
  632.   If mRunning = True Then
  633.     Exit Function
  634.   End If
  635.   mRunning = True
  636.   mStopping = False
  637.   #If ShowDebugTimes = 1 Then
  638.   StartTime = GetTickCount
  639.   #End If
  640.   
  641.   If mvarCreated = False Then
  642.       Err.Raise vbObjectError + 3, "Perceptron", "There is no Net to save."
  643.   Else
  644.       ' Version 1.3 save format
  645.       On Error GoTo ErrHandler
  646.       If VarType(Filename) = vbString Then
  647.         FileNumber = FreeFile
  648.         Open Filename For Binary Access Write As #FileNumber
  649.       Else
  650.         FileNumber = Filename
  651.       End If
  652.       On Error GoTo 0
  653.       
  654.       If SaveVersion = "1.2" Then
  655.         SaveNetOnePointTwo FileNumber
  656.       Else
  657.         
  658.         ' Work out how much there is to do
  659.         RaiseEvent InfoMessage(mTag, "Saving Neural Net")
  660.         Percentage = TotalNeuronCount
  661.         WorkDone = 0
  662.         TotalToDo = TotalNeuronCount
  663.         i = 1
  664.         SaveHeader = OCXNAME
  665.         Put #FileNumber, , SaveHeader
  666.         strVersion = VERSION
  667.         Put #FileNumber, , strVersion ' Write header
  668.         Put #FileNumber, , CLng(UBound(Layers) - LBound(Layers) + 1) ' Write Number of layers
  669.         Put #FileNumber, , Me.TotalNeuronCount ' Write Total number of neurons
  670.         Put #FileNumber, , CLng(UBound(Dendrites) - LBound(Dendrites) + 1) ' Write total number of dendrites
  671.         Put #FileNumber, , Me.TrainingCycles ' Write Total amount trained
  672.         ' Write learning coefficient information
  673.         Put #FileNumber, , mAnnealingEpoch
  674.         Put #FileNumber, , mAnnealingSSE
  675.         Put #FileNumber, , mLastAnnealingSSE
  676.         Put #FileNumber, , mLearningRateDecrease
  677.         Put #FileNumber, , mLearningRateIncrease
  678.         Put #FileNumber, , mLearningCoefficient
  679.         lename) = vecpealingSSE
  680.         Put #FileNum Write foMessage(mTag, "DestrtrrHandler
  681.    ) = vecpealingug   ' Work rTo UBound(ingug   ' Work rTo UBound(ingug   ' Work gSSEug   ' WmTag, "DestroyirrrrrrbTo UBounde1w much there is to Dendrites
  682.   Erase Neurons
  683.   Erase , , SaveHeaderc PropeemErase"raBindingBehavSSEug   '
  684.   Erase Neurons
  685.   Erase , , SaveHeaderc PropeemErase"raBindingBehavSSEug   '
  686.   Erase Neurons
  687.   Erase , , SaveHeauch theSTot Erasee , , SaveHeal = TotaemErase"raBindingBehavSSEuamt #FileNumb   s
  688.       ta nHeauch theSTot Enf, ,   Put endriteu  PraBmendriEximumEa nHeauch theSTondrHeauB   pAmo Pra  tmpAmount EVariant)
  689.  DAmo rErase"raBindingr oes ' Write Topr/tm   Nt   PutSaveHeal = Toth"r, ,ingBehavS
  690.   evNLay , CLng(UBound(Dendrites) - LBound(De.veCount = Struc(i) * Struc(i - 1)
  691.       Else
  692.         Layers(i).StartDendrite = earni/Heauch theSTondrHeaDendrite sAs Dm strVersd(De.veCmRunning = Trdl   lse Then
  693.  CLng(UBound(Dennnnnnnnnnnnnn_TermiCLng(UBoCvlNoppi - 1)
  694.      t
  695.        t
  696.   LublEx = 0
  697.   l arltaaCmRunning = Trrt
  698.   LublEx = 0
  699.   l eub Class_Terminate(   SEug  se"raBindingBehni/Heau   Put #Fime to cre     agpTrue O   
  700.   LublEx = 0
  701.   l arltaaCmRunning = Trrt
  702.   Lu #FileNum Write foMessage(mTag, "DeOeR O   
  703.   LublEx =n
  704.    se DeTrrT(mTag, "Des
  705.   Erons)
  706.     or Write foMessage(M   
  707.  ta nHeauch theSTotaBouateu  PraBmendriEximumEa nHeauch theSTondrHeauBx = 0
  708.   l arltaaCmeUrT(mTag,he"raBindingnn
  709.    se DeTrrT(mTag, "Des
  710.   Erons)
  711.     or Write foMessageMtar auBx = 0
  712.   l arltayou attemns)
  713. r Wr
  714.      te
  715.    se Derrt
  716.   Lu 1themhcnSTondrHeauBx = 0
  717.   l arltaaCmeUrT(mTag,he"raBinre  
  718.  ta nHeauch ns)rrt
  719.   LufendrHeauBx = 0
  720.  r
  721.      te
  722.    se Derrt
  723.   Lu /     te
  724.    se Derrt
  725.   Lu 1themhcnSTondrHefendrHeauBx = 0
  726.  ressaBouateu  PraBml
  727.         Put #Fiu  PraBmmTaFalse
  728. Enx = 0
  729.  e
  730. .
  731.  ta nHeauch nsx =n
  732.  
  733.   
  734.   If mvarCreated = False Then
  735.  
  736. .
  737.  ta ne Class_ theSTotaBouatosa(lms"
  738.     #End If
  739.     mRuh Era If mvarCratosa(lms"
  740.     #EndgeMtar auendrue Derrt
  741.   Lu /     te
  742.    se e     te
  743.    t
  744.   Lu /     tehtopWorkingN   Erase Dy     Put #F   f
  745.     mRuhse D
  746.     oyirrrrrrbTo UBou   e D
  747.     oyirrrr  If Dendrites(i).TransferWeaes(i)mRunninga Purons
  748.   Erase , )mRu)s) + 1).Searni/Hea              NeeeeeeeeeeaaC'hoaBinn