-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathNeuralNetwork.vb
More file actions
2760 lines (2285 loc) · 112 KB
/
NeuralNetwork.vb
File metadata and controls
2760 lines (2285 loc) · 112 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Imports System.IO
Imports System.Web.Script.Serialization
Imports System.Windows.Forms
Imports System.Xml.Serialization
Imports SpydazWebAI.NeuralNetWork.Basic_NLP.SingleLayerNeuralNetwork
Namespace NeuralNetworkFactory
Public MustInherit Class NeuralNetworkFactory
Public Enum NetworkType
FeedForwards
BackPropergation
None
End Enum
''' <summary>
''' Each layer consists of neurons(nodes) the training cases also use an input layer and an
''' output layer
''' </summary>
''' <remarks></remarks>
Public Class Layer
''' <summary>
''' Each layer consists of nodes (neurons) these are each individual. all layers contain
''' nodes, Used for neural network inputs / outputs / hidden nodes
''' </summary>
''' <remarks></remarks>
Public Class Neuron
''' <summary>
''' The input of the node is the collective sum of the inputs and their respective weights
''' </summary>
''' <remarks></remarks>
Public input As Double
''' <summary>
''' the output of the node is also relational to the transfer function used
''' </summary>
''' <remarks></remarks>
Public output As Double
''' <summary>
''' There is a value attached with dendrite called weight. The weight associated with a
''' dendrites basically determines the importance of incoming value. A weight with
''' larger value determines that the value from that particular neuron is of higher
''' significance. To achieve this what we do is multiply the incoming value with weight.
''' So no matter how high the value is, if the weight is low the multiplication yields
''' the final low value.
''' </summary>
''' <remarks></remarks>
Public weight As Double
''' <summary>
''' Add biasing to the Perceptron
''' </summary>
Public bias As Double
''' <summary>
''' Constructor Single Input
''' </summary>
Public Sub New()
CreateRandWeight(0, 1)
bias = 0.1
End Sub
''' <summary>
''' Initial Weights can be determined by the number of hidden nodes and the number of
''' input nodes this is a rule of thumb
''' </summary>
''' <remarks></remarks>
Public Sub CreateRandWeight(ByRef InputLow As Integer, ByRef InputHigh As Integer)
Randomize()
Dim value As Integer = CInt(Int((InputHigh * Rnd()) + InputLow))
weight = value
End Sub
''' <summary>
''' Sets input of the node
''' </summary>
''' <param name="value"></param>
Public Sub SetInput(ByRef value As Double)
input = value
End Sub
''' <summary>
''' Activates Node and sets the output for the node
''' </summary>
''' <param name="Activation">Activation Function</param>
''' <remarks>ActivationFunction(Node.input * Node.weight)</remarks>
Public Sub ActivateNode(ByRef Activation As TransferFunctionType)
output = TransferFunction.EvaluateTransferFunct(Activation, NodeTotal())
End Sub
''' <summary>
''' Produces a node total which can be fed to the activation function (Stage 1)
''' (input * weight)
''' </summary>
''' <returns>Node input * Node Weight</returns>
''' <remarks></remarks>
Public Function NodeTotal() As Double
Return input * weight + bias
End Function
''' <summary>
''' Recalcualtes the weight for this node
''' </summary>
''' <param name="ActualOutput">Output of node</param>
''' <param name="ExpectedOutput">Expected Output of node</param>
Public Sub RecalculateWeight(ByRef ActualOutput As Double, ByRef ExpectedOutput As Double)
Dim NodeError As Double = ActualOutput - ExpectedOutput
Dim Delta = NodeError * TransferFunction.EvaluateTransferFunctionDerivative(TransferFunctionType.Sigmoid, ActualOutput)
weight += Delta
bias += Delta
End Sub
''' <summary>
''' Returns output from Node Given Activation Function
''' </summary>
''' <param name="Activation"></param>
''' <returns></returns>
Public Function Compute(ByRef Activation As TransferFunctionType) As Double
Return TransferFunction.EvaluateTransferFunct(Activation, NodeTotal())
End Function
''' <summary>
''' deserialize object from Json
''' </summary>
''' <param name="Str">json</param>
''' <returns></returns>
Public Shared Function FromJson(ByRef Str As String) As Neuron
Try
Dim Converter As New JavaScriptSerializer
Dim diag As Neuron = Converter.Deserialize(Of Neuron)(Str)
Return diag
Catch ex As Exception
Dim Buttons As MessageBoxButtons = MessageBoxButtons.OK
MessageBox.Show(ex.Message, "ERROR", Buttons)
End Try
Return Nothing
End Function
''' <summary>
''' Serializes object to json
''' </summary>
''' <returns> </returns>
Public Function ToJson() As String
Dim Converter As New JavaScriptSerializer
Return Converter.Serialize(Me)
End Function
''' <summary>
''' Transfer Function used in the calculation of the following layer
''' </summary>
Public Structure TransferFunction
''' <summary>
''' These are the options of transfer functions available to the network
''' This is used to select which function to be used:
''' The derivative function can also be selected using this as a marker
''' </summary>
Public Enum TransferFunctionType
none
sigmoid
HyperbolTangent
BinaryThreshold
RectifiedLinear
Logistic
StochasticBinary
Gaussian
Signum
End Enum
''' <summary>
''' Returns a result from the transfer function indicated ; Non Derivative
''' </summary>
''' <param name="TransferFunct">Indicator for Transfer function selection</param>
''' <param name="Input">Input value for node/Neuron</param>
''' <returns>result</returns>
Public Shared Function EvaluateTransferFunct(ByRef TransferFunct As TransferFunctionType, ByRef Input As Double) As Integer
EvaluateTransferFunct = 0
Select Case TransferFunct
Case TransferFunctionType.none
Return Input
Case TransferFunctionType.sigmoid
Return Sigmoid(Input)
Case TransferFunctionType.HyperbolTangent
Return HyperbolicTangent(Input)
Case TransferFunctionType.BinaryThreshold
Return BinaryThreshold(Input)
Case TransferFunctionType.RectifiedLinear
Return RectifiedLinear(Input)
Case TransferFunctionType.Logistic
Return Logistic(Input)
Case TransferFunctionType.Gaussian
Return Gaussian(Input)
Case TransferFunctionType.Signum
Return Signum(Input)
End Select
End Function
''' <summary>
''' Returns a result from the transfer function indicated ; Non Derivative
''' </summary>
''' <param name="TransferFunct">Indicator for Transfer function selection</param>
''' <param name="Input">Input value for node/Neuron</param>
''' <returns>result</returns>
Public Shared Function EvaluateTransferFunctionDerivative(ByRef TransferFunct As TransferFunctionType, ByRef Input As Double) As Integer
EvaluateTransferFunctionDerivative = 0
Select Case TransferFunct
Case TransferFunctionType.none
Return Input
Case TransferFunctionType.sigmoid
Return SigmoidDerivitive(Input)
Case TransferFunctionType.HyperbolTangent
Return HyperbolicTangentDerivative(Input)
Case TransferFunctionType.Logistic
Return LogisticDerivative(Input)
Case TransferFunctionType.Gaussian
Return GaussianDerivative(Input)
End Select
End Function
''' <summary>
''' the step function rarely performs well except in some rare cases with (0,1)-encoded
''' binary data.
''' </summary>
''' <param name="Value"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Shared Function BinaryThreshold(ByRef Value As Double) As Double
' Z = Bias+ (Input*Weight)
'TransferFunction
'If Z > 0 then Y = 1
'If Z < 0 then y = 0
Return If(Value < 0 = True, 0, 1)
End Function
Private Shared Function Gaussian(ByRef x As Double) As Double
Gaussian = Math.Exp((-x * -x) / 2)
End Function
Private Shared Function GaussianDerivative(ByRef x As Double) As Double
GaussianDerivative = Gaussian(x) * (-x / (-x * -x))
End Function
Private Shared Function HyperbolicTangent(ByRef Value As Double) As Double
' TanH(x) = (Math.Exp(x) - Math.Exp(-x)) / (Math.Exp(x) + Math.Exp(-x))
Return Math.Tanh(Value)
End Function
Private Shared Function HyperbolicTangentDerivative(ByRef Value As Double) As Double
HyperbolicTangentDerivative = 1 - (HyperbolicTangent(Value) * HyperbolicTangent(Value)) * Value
End Function
'Linear Neurons
''' <summary>
''' in a liner neuron the weight(s) represent unknown values to be determined the
''' outputs could represent the known values of a meal and the inputs the items in the
''' meal and the weights the prices of the individual items There are no hidden layers
''' </summary>
''' <remarks>
''' answers are determined by determining the weights of the linear neurons the delta
''' rule is used as the learning rule: Weight = Learning rate * Input * LocalError of neuron
''' </remarks>
Private Shared Function Linear(ByRef value As Double) As Double
' Output = Bias + (Input*Weight)
Return value
End Function
'Non Linear neurons
Private Shared Function Logistic(ByRef Value As Double) As Double
'z = bias + (sum of all inputs ) * (input*weight)
'output = Sigmoid(z)
'derivative input = z/weight
'derivative Weight = z/input
'Derivative output = output*(1-Output)
'learning rule = Sum of total training error* derivative input * derivative output * rootmeansquare of errors
Return 1 / 1 + Math.Exp(-Value)
End Function
Private Shared Function LogisticDerivative(ByRef Value As Double) As Double
'z = bias + (sum of all inputs ) * (input*weight)
'output = Sigmoid(z)
'derivative input = z/weight
'derivative Weight = z/input
'Derivative output = output*(1-Output)
'learning rule = Sum of total training error* derivative input * derivative output * rootmeansquare of errors
Return Logistic(Value) * (1 - Logistic(Value))
End Function
Private Shared Function RectifiedLinear(ByRef Value As Double) As Double
'z = B + (input*Weight)
'If Z > 0 then output = z
'If Z < 0 then output = 0
If Value < 0 = True Then
Return 0
Else
Return Value
End If
End Function
''' <summary>
''' the log-sigmoid function constrains results to the range (0,1), the function is
''' sometimes said to be a squashing function in neural network literature. It is the
''' non-linear characteristics of the log-sigmoid function (and other similar activation
''' functions) that allow neural networks to model complex data.
''' </summary>
''' <param name="Value"></param>
''' <returns></returns>
''' <remarks>1 / (1 + Math.Exp(-Value))</remarks>
Private Shared Function Sigmoid(ByRef Value As Integer) As Double
'z = Bias + (Input*Weight)
'Output = 1/1+e**z
Return 1 / (1 + Math.Exp(-Value))
End Function
Private Shared Function SigmoidDerivitive(ByRef Value As Integer) As Double
Return Sigmoid(Value) * (1 - Sigmoid(Value))
End Function
Private Shared Function Signum(ByRef Value As Integer) As Double
'z = Bias + (Input*Weight)
'Output = 1/1+e**z
Return Math.Sign(Value)
End Function
Private Shared Function StochasticBinary(ByRef value As Double) As Double
'Uncreated
Return value
End Function
End Structure
End Class
''' <summary>
''' Activation function used by the nodes in the layer
''' </summary>
''' <remarks></remarks>
Public ActivationFunction As TransferFunctionType
''' <summary>
''' Usually 1/0
''' </summary>
Public Bias As Integer
''' <summary>
''' Calculates Layer Error From Output Vector
''' each scalar error output of the vector respective of its output
''' </summary>
Public LayerError As Vector
''' <summary>
''' Type of layer (Input, Hidden, Output)
''' </summary>
''' <remarks></remarks>
Public nLayerType As LayerType
''' <summary>
''' Collection of nodes
''' </summary>
''' <remarks></remarks>
Public Nodes As List(Of Neuron)
''' <summary>
''' The number of nodes is stored to make iteration easier
''' </summary>
''' <remarks></remarks>
Public ReadOnly Property NumberOfNodes As Integer
Get
If Nodes IsNot Nothing Then
NumberOfNodes = Nodes.Count
Else
NumberOfNodes = 0
End If
End Get
End Property
''' <summary>
''' Executes Layer (Forwards Prop)
''' </summary>
''' <param name="Input">input vector</param>
''' <returns>Output Vector for the layer</returns>
Public Function Execute(ByRef Input As Vector) As Vector
SetInput(Input)
ActivateLayer()
Return GetOutput()
End Function
''' <summary>
''' Returns Output as vector (as held in nodes at current state)
''' </summary>
''' <returns></returns>
Public Function GetOutput() As Vector
Dim NewVect As New Vector(New List(Of Double))
For Each ITEM In Nodes
NewVect.values.Add(ITEM.output)
Next
Return NewVect
End Function
''' <summary>
''' Activates each node in the layer -
''' Also the Layer is summed then activated and the single returned value is returned to Layer - output
''' </summary>
''' <remarks>layer to be summed to be passed to the inputs of the next layer</remarks>
Private Sub ActivateLayer()
Dim LayerTotal As Double = 0
For Each node As Neuron In Nodes
'Sum Layer (NodeTotal = Input*Weight)
LayerTotal += node.NodeTotal()
'Activate Output (F(SumOfWeightedInputs)
node.output = TransferFunction.EvaluateTransferFunct(TransferFunctionType.Sigmoid, LayerTotal) + Bias
Next
End Sub
''' <summary>
''' Sets input for the Layer:
''' If input and nodes do not match will not be added
''' </summary>
''' <param name="Input"></param>
Private Sub SetInput(ByRef Input As Vector)
If Nodes.Count <> Input.values.Count Then
'Skip
Else
For i = 0 To Nodes.Count
Nodes(i).SetInput(Input.values(i))
Next
End If
End Sub
''' <summary>
''' Each layer consists of neurons(nodes) the training cases also use an input layer and an
''' output layer
''' </summary>
''' <remarks></remarks>
Public Sub New()
Nodes = New List(Of Neuron)
Bias = 1
End Sub
Public Shared Function CreateLayer(ByRef nLayertype As LayerType, ByRef NodesNo As Integer, ByRef Activation As TransferFunctionType) As Layer
Dim layr As New Layer
layr.nLayerType = nLayertype
layr.ActivationFunction = Activation
For i = 1 To NodesNo
Dim nde As New Neuron
nde.CreateRandWeight(0, 1)
layr.Nodes.Add(nde)
Next
Return layr
End Function
''' <summary>
''' deserialize object from Json
''' </summary>
''' <param name="Str">json</param>
''' <returns></returns>
Public Shared Function FromJson(ByRef Str As String) As Layer
Try
Dim Converter As New JavaScriptSerializer
Dim diag As Layer = Converter.Deserialize(Of Layer)(Str)
Return diag
Catch ex As Exception
Dim Buttons As MessageBoxButtons = MessageBoxButtons.OK
MessageBox.Show(ex.Message, "ERROR", Buttons)
End Try
Return Nothing
End Function
''' <summary>
''' Serializes object to json
''' </summary>
''' <returns> </returns>
Public Function ToJson() As String
Dim Converter As New JavaScriptSerializer
Return Converter.Serialize(Me)
End Function
''' <summary>
''' Given the desired / expected output vector for the layer
''' the internal error is calculated as LAYERERRROR
''' Each Neuron Error for the layer is also produced
''' </summary>
''' <param name="DesiredOutput"> Each Output Error Vector value Corresponds to a node error
''' Its error value is passed to calculate the individual neuron error</param>
Public Sub Recalculate(ByRef DesiredOutput As Vector)
'Calculate Node Errors for the layer
'Each Output Error Vector Corresponds to a node
'Its error value is passed to calculate the individual neuron error recalculating its new weight
Dim cnt As Integer = 0
For Each item In GetOutput.values
For Each nde In Nodes
nde.RecalculateWeight(GetOutput.values(cnt), DesiredOutput.values(cnt))
Next
cnt += 1
Next
End Sub
End Class
'Dim Delta As Double = learningRate * (NodeOutput - ExpectedOutput) * ExpectedOutput * DerivativeOfNodeOutput
''' <summary>
''' This is the Allowed Error threshold for the output,
''' The output could ba a single value or a vector
''' </summary>
Public ErrorThreshold As Double
Public iNetworkType As NetworkType = NetworkType.None
''' <summary>
''' Middle layer: This layer is the real thing behind the network. Without this layer,
''' network would not be capable of solving complex problems. There can be any number or
''' middle or hidden layers. But, for most of the tasks, one is sufficient. The number
''' of neurons in this layer is crucial. There is no formula for calculating the number,
''' just hit and trial works. This layer takes the input from input layer, does some
''' calculations and forwards to the next layer, in most cases it is the output layer.
''' </summary>
''' <remarks>in a deep belief network there can be many hidden layers</remarks>
Public HiddenLayers As List(Of Layer)
''' <summary>
''' layer takes the inputs(the values you pass) and forwards it to hidden layer. You can
''' just imagine input layer as a group of neurons whose sole task is to pass the
''' numeric inputs to the next level. Input layer never processes data, it just hands
''' over it.
''' </summary>
''' <remarks>there is only one layer for the input</remarks>
Public InputLayer As Layer
''' <summary>
''' Output layer: This layer consists of neurons which output the result to you. This
''' layer takes the value from the previous layer, does calculations and gives the final
''' result. Basically, this layer is just like hidden layer but instead of passing
''' values to the next layer, the values are treated as output.
''' </summary>
''' <remarks>there is only one layer for the output</remarks>
Public OutputLayer As Layer
Public Sub New()
HiddenLayers = New List(Of Layer)
End Sub
''' <summary>
''' The number of hidden nodes to become effective is actually unknown yet a simple
''' calculation can be used to determine an initial value which should be effective;
''' </summary>
''' <param name="NumbeOfInputNodes">the number of input node used in the network</param>
''' <param name="NumberOfOutputNodes">the number of out put nodes in the network</param>
''' <returns>a reasonable calculation for hidden nodes</returns>
''' <remarks>
''' Deep layer networks have multiple hidden layers with varied number of nodes
''' </remarks>
Private Function CalculateNumberOfHiddenNodes(ByRef NumbeOfInputNodes As Integer, ByRef NumberOfOutputNodes As Integer) As Integer
CalculateNumberOfHiddenNodes = NumbeOfInputNodes + NumberOfOutputNodes / 2
If CalculateNumberOfHiddenNodes < NumberOfOutputNodes Then CalculateNumberOfHiddenNodes = NumberOfOutputNodes
End Function
''' <summary>
''' Create Neural Network
''' </summary>
''' <param name="InputNodes">number of required nodes</param>
''' <param name="OutputNodes">Number of required nodes</param>
''' <param name="InputTransferFunction">required transfer function</param>
''' <param name="OutputFunction">output transfer function</param>
''' <param name="ErrThreshold">threshold error measurement (used for training network)</param>
Public Sub New(ByRef InputNodes As Integer, OutputNodes As Integer,
ByRef InputTransferFunction As TransferFunctionType, ByRef OutputFunction As TransferFunctionType,
ByRef ErrThreshold As Double)
ErrorThreshold = ErrThreshold
Dim NoHidden As Integer = CalculateNumberOfHiddenNodes(InputNodes, OutputNodes)
InputLayer = New Layer
InputLayer = Layer.CreateLayer(LayerType.Input, InputNodes, InputTransferFunction)
HiddenLayers = New List(Of Layer)
For i = 1 To NoHidden
HiddenLayers.Add(Layer.CreateLayer(LayerType.Hidden, InputNodes, TransferFunctionType.Sigmoid))
Next
OutputLayer = New Layer
OutputLayer = Layer.CreateLayer(LayerType.Output, OutputNodes, OutputFunction)
End Sub
Public Enum LayerType
Input
Hidden
Output
End Enum
''' <summary>
''' Executes Networks (Single Iteration of Neural Network)
''' </summary>
''' <param name="Input">Input vector</param>
''' <returns>Output Vector</returns>
Public MustOverride Function Execute(ByRef Input As Vector) As Vector
''' <summary>
''' Executes Networks (Single Iteration of Neural Network)
''' </summary>
''' <param name="Input">Input vector</param>
''' <returns>Output Vector</returns>
Public MustOverride Function Train(ByRef Input As Vector) As Vector
''' <summary>
''' deserialize object from Json
''' </summary>
''' <param name="Str">json</param>
''' <returns></returns>
Public Shared Function FromJson(ByRef Str As String) As NeuralNetworkFactory
Try
Dim Converter As New JavaScriptSerializer
Dim diag As NeuralNetworkFactory = Converter.Deserialize(Of NeuralNetworkFactory)(Str)
Return diag
Catch ex As Exception
Dim Buttons As MessageBoxButtons = MessageBoxButtons.OK
MessageBox.Show(ex.Message, "ERROR", Buttons)
End Try
Return Nothing
End Function
''' <summary>
''' Serializes object to json
''' </summary>
''' <returns> </returns>
Public Function ToJson() As String
Dim Converter As New JavaScriptSerializer
Return Converter.Serialize(Me)
End Function
End Class
''' <summary>
''' The Perceptron Allows for a multi input vector to single output
''' </summary>
Public Class Perceptron
Public Property Weights As Double() ' The weights of the perceptron
Private Function Sigmoid(x As Double) As Double ' The sigmoid activation function
Return 1 / (1 + Math.Exp(-x))
End Function
''' <summary>
''' the step function rarely performs well except in some rare cases with (0,1)-encoded
''' binary data.
''' </summary>
''' <param name="Value"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Shared Function BinaryThreshold(ByRef Value As Double) As Double
' Z = Bias+ (Input*Weight)
'TransferFunction
'If Z > 0 then Y = 1
'If Z < 0 then y = 0
Return If(Value < 0 = True, 0, 1)
End Function
Public Sub New(NumberOfInputs As Integer) ' Constructor that initializes the weights and bias of the perceptron
CreateWeights(NumberOfInputs)
End Sub
Public Sub CreateWeights(NumberOfInputs As Integer) ' Constructor that initializes the weights and bias of the perceptron
Weights = New Double(NumberOfInputs - 1) {}
For i As Integer = 0 To NumberOfInputs - 1
Weights(i) = Rnd(1.0)
Next
End Sub
' Function to calculate output
Public Function Compute(inputs As Double()) As Integer
CreateWeights(inputs.Count)
Dim sum = 0.0
' Loop through inputs and calculate sum of weights times inputs
For i = 0 To inputs.Length - 1
sum += _Weights(i) * inputs(i)
Next
' Return 1 if sum is greater than 0, otherwise return -1
Return If(sum > 0, 1, -1)
End Function
Public Function ComputeSigmoid(inputs As Double()) As Double ' Compute the output of the perceptron given an input
CreateWeights(inputs.Count)
Dim sum As Double = 0
'Collect the sum of the inputs * Weight
For i As Integer = 0 To inputs.Length - 1
sum += inputs(i) * Weights(i)
Next
'Activate
'We Return the sigmoid of the sum to produce the output
Return Sigmoid(sum)
End Function
Public Function ComputeBinaryThreshold(inputs As Double()) As Double ' Compute the output of the perceptron given an input
CreateWeights(inputs.Count)
Dim sum As Double = 0 ' used to hold the output
'Collect the sum of the inputs * Weight
For i As Integer = 0 To inputs.Length - 1
sum += inputs(i) * Weights(i)
Next
'Activate
'We Return the sigmoid of the sum to produce the output , Applying the Binary threshold funciton to it
Return BinaryThreshold(Sigmoid(sum))
End Function
' Function to train the perceptron
Public Sub Train(inputs As Double(), desiredOutput As Integer, threshold As Double, MaxEpochs As Integer, LearningRate As Double)
Dim guess = Compute(inputs)
Dim nError As Integer = 0
Dim CurrentEpoch = 0
Do Until threshold < nError Or
CurrentEpoch = MaxEpochs
CurrentEpoch += 1
nError = desiredOutput - guess
' Loop through inputs and update weights based on error and learning rate
For i = 0 To inputs.Length - 1
_Weights(i) += LearningRate * nError * inputs(i)
Next
Loop
End Sub
End Class
Public Module NN_tests
''' <summary>
''' Here a single perceptron is used as a Layer
''' </summary>
''' <returns></returns>
Public Property Layers As List(Of Perceptron) ' The layers of the network
Public Function ComputePerceptronLayer(inputs As Double()) As Double ' Compute the output of the network given an input
Dim output As Double() = inputs
For Each layer In Layers
Dim newOutput(layer.Weights.Length - 1) As Double
For i As Integer = 0 To layer.Weights.Length - 1
newOutput(i) = layer.ComputeSigmoid(output)
Next
output = newOutput
Next
Return output(0)
End Function
Public Sub TrainBackProp(inputs As Double()(), outputs As Double(), Optional learningRate As Double = 0.1) ' Train the network given a set of inputs and outputs
Dim errorThreshold As Double = 0.01 ' The error threshold at which to stop training
Dim nError As Double = 1 ' Initialize the error to a high value
While nError > errorThreshold ' Loop until the error is below the threshold
nError = 0 ' Reset the error to zero
For i As Integer = 0 To inputs.Length - 1 ' Loop through each input/output pair
Dim output As Double = ComputePerceptronLayer(inputs(i)) ' Compute the output of the network for this input
Dim delta As Double = learningRate * (outputs(i) - output) * output * (1 - output) ' Compute the delta for each weight and bias in the network
' Dim Delta2 As Double = learningRate * (NodeOutput - ExpectedOutput) * ExpectedOutput * DerivativeOfOutput
For Each layer In Layers ' Loop through each layer in the network
For j As Integer = 0 To layer.Weights.Length - 1 ' Loop through each weight in this layer
layer.Weights(j) += delta * layer.ComputeSigmoid(inputs(i)) ' Update the weight based on this input and delta
Next
' layer.Bias += delta ' Update the bias based on delta
Next
nError += Math.Abs(outputs(i) - output) ' Add the absolute difference between the actual output and predicted output to the total error
Next
nError /= inputs.Length ' Divide the total error by the number of input/output pairs to get the average error
End While
End Sub
End Module
Module helper
Public Function MultiplyMatrix(matrixA As Double(,), matrixB As Double(,)) As Double(,)
Dim rowsA As Integer = matrixA.GetLength(0)
Dim columnsA As Integer = matrixA.GetLength(1)
Dim rowsB As Integer = matrixB.GetLength(0)
Dim columnsB As Integer = matrixB.GetLength(1)
If columnsA <> rowsB Then
Throw New ArgumentException("Invalid matrix dimensions for multiplication.")
End If
Dim resultMatrix As Double(,) = New Double(rowsA - 1, columnsB - 1) {}
For i As Integer = 0 To rowsA - 1
For j As Integer = 0 To columnsB - 1
Dim sum As Double = 0
For k As Integer = 0 To columnsA - 1
sum += matrixA(i, k) * matrixB(k, j)
Next
resultMatrix(i, j) = sum
Next
Next
Return resultMatrix
End Function
Public Sub PrintMatrix(matrix As Double(,))
Dim rows As Integer = matrix.GetLength(0)
Dim columns As Integer = matrix.GetLength(1)
For i As Integer = 0 To rows - 1
For j As Integer = 0 To columns - 1
Console.Write(matrix(i, j) & " ")
Next
Console.WriteLine()
Next
Console.WriteLine()
End Sub
End Module
Public Class Tril
Public Sub Main()
Dim matrix(,) As Integer = {{1, 2, 3, 9}, {4, 5, 6, 8}, {7, 8, 9, 9}}
Dim result(,) As Integer = Tril(matrix)
Console.WriteLine("Matrix:")
PrintMatrix(matrix)
Console.WriteLine("Tril Result:")
PrintMatrix(result)
Console.ReadLine()
End Sub
Public Shared Function Tril(ByVal matrix(,) As Integer) As Integer(,)
Dim rows As Integer = matrix.GetLength(0)
Dim cols As Integer = matrix.GetLength(1)
Dim result(rows - 1, cols - 1) As Integer
For i As Integer = 0 To rows - 1
For j As Integer = 0 To cols - 1
If j <= i Then
result(i, j) = matrix(i, j)
End If
Next
Next
Return result
End Function
Public Shared Function Tril(ByVal matrix(,) As Double) As Double(,)
Dim rows As Integer = matrix.GetLength(0)
Dim cols As Integer = matrix.GetLength(1)
Dim result(rows - 1, cols - 1) As Double
For i As Integer = 0 To rows - 1
For j As Integer = 0 To cols - 1
If j <= i Then
result(i, j) = matrix(i, j)
End If
Next
Next
Return result
End Function
Public Shared Function Tril(ByVal matrix As List(Of List(Of Double))) As List(Of List(Of Double))
Dim rows As Integer = matrix.Count
Dim cols As Integer = matrix(0).Count
Dim result As New List(Of List(Of Double))
For i As Integer = 0 To rows - 1
For j As Integer = 0 To cols - 1
If j <= i Then
result(i)(j) = matrix(i)(j)
End If
Next
Next
Return result
End Function
Public Shared Sub PrintMatrix(ByVal matrix(,) As Double)
Dim rows As Integer = matrix.GetLength(0)
Dim cols As Integer = matrix.GetLength(1)
For i As Integer = 0 To rows - 1
For j As Integer = 0 To cols - 1
Console.Write(matrix(i, j) & " ")
Next
Console.WriteLine()
Next
End Sub
Public Shared Sub PrintMatrix(ByVal matrix(,) As Integer)
Dim rows As Integer = matrix.GetLength(0)
Dim cols As Integer = matrix.GetLength(1)
For i As Integer = 0 To rows - 1
For j As Integer = 0 To cols - 1
Console.Write(matrix(i, j) & " ")
Next
Console.WriteLine()
Next
End Sub
End Class
Public Class Softmax
Public Shared Function Softmax(matrix2 As Integer(,)) As Double(,)
Dim numRows As Integer = matrix2.GetLength(0)
Dim numColumns As Integer = matrix2.GetLength(1)
Dim softmaxValues(numRows - 1, numColumns - 1) As Double
' Compute softmax values for each row
For i As Integer = 0 To numRows - 1
Dim rowSum As Double = 0
' Compute exponential values and sum of row elements
For j As Integer = 0 To numColumns - 1
softmaxValues(i, j) = Math.Sqrt(Math.Exp(matrix2(i, j)))
rowSum += softmaxValues(i, j)
Next
' Normalize softmax values for the row
For j As Integer = 0 To numColumns - 1
softmaxValues(i, j) /= rowSum
Next
Next
' Display the softmax values
Console.WriteLine("Calculated:" & vbNewLine)
For i As Integer = 0 To numRows - 1
For j As Integer = 0 To numColumns - 1
Console.Write(softmaxValues(i, j).ToString("0.0000") & " ")
Next
Console.WriteLine(vbNewLine & "---------------------")
Next
Return softmaxValues
End Function
Public Shared Sub Main()
Dim input() As Double = {1.0, 2.0, 3.0}
Dim output() As Double = Softmax(input)
Console.WriteLine("Input: {0}", String.Join(", ", input))
Console.WriteLine("Softmax Output: {0}", String.Join(", ", output))
Console.ReadLine()
End Sub
Public Shared Function Softmax(ByVal input() As Double) As Double()
Dim maxVal As Double = input.Max()
Dim exponentiated() As Double = input.Select(Function(x) Math.Exp(x - maxVal)).ToArray()
Dim sum As Double = exponentiated.Sum()
Dim softmaxOutput() As Double = exponentiated.Select(Function(x) x / sum).ToArray()
Return softmaxOutput
End Function
End Class
Public Class Vector
Public ReadOnly values As List(Of Double)
Public Function ApplyActivationFunction() As Vector
' Apply the desired activation function to each value in the vector
Dim result As New List(Of Double)()
For Each value In values
result.Add(Sigmoid(value)) ' Applying Sigmoid activation function
Next
Return New Vector(result)
End Function
Private Function Sigmoid(x As Double) As Double
Return 1 / (1 + Math.Exp(-x))
End Function
Public Sub New(values As List(Of Double))
Me.values = values
End Sub
Public Function Add(other As Vector) As Vector
If values.Count <> other.values.Count Then
Throw New ArgumentException("Vector dimensions do not match.")
End If
Dim result As New List(Of Double)()
For i = 0 To values.Count - 1
result.Add(values(i) + other.values(i))
Next