Private Inputs() As Integer = {-2, 1, 1} '(Change in cholesterol level,
'Change in weight,
'Family history)
Private Const alpha As Single = 0.01 'Learning rate (alpha), which limits
'the size of a weight/bias adjustment
'step in a single training iteration.
'The smaller the value of alpha, the
'longer a network will take to train.
Private Const mu As Single = 0.7 'Momentum value (mu). This enables the
'weight to change in response to the
'current gradient step and also to the
'previous one. It allows the network to
'find a reasonable solution in fewer
'training iterations. When both the
'current step and previous step are in
'agreement, it allows for a larger step size.
Private Const n As Integer = 3 'The number neurons in the input
'layer equals the number of variables
'inherent to the problem.
Private Const m As Integer = 3
Private Const NumCases As Integer = 8
Private Const TestCases As Integer = 3
Private Const CR As String = Chr(13) + Chr(10)
Private hbias(m - 1) As Single ' 'h' refers to the hidden layer.
Private hweight(n - 1, m - 1) As Single
Private obias As Single ' 'o' refers to the output layer.
Private oweight(m - 1) As Single
Private hbias2(m - 1) As Single ' '2' refers to training copies.
Private hweight2(n - 1, m - 1) As Single
Private obias2 As Single
Private oweight2(m - 1) As Single
Private hin(m - 1) As Single
Private hout(m - 1) As Single
Private oin As Single
Private oout As Single 'Since the physicians only want to know
'whether or not the individual is at
'risk for the disease, you'll only
'need a single output neuron.
Private InputNeuron(n - 1) As Integer
Private X1 As Single(,) = New Single(,) {{-3, -1, -3}, _
{-9, -1, 4}, _
{12, 1, 15}, _
{17, 1, 23}, _
{-16, -1, 2}, _
{26, -1, 16}, _
{3, -1, -12}, _
{-15, 1, -3}}
Private X2 As Single(,) = New Single(,) {{-6, -1, 2}, _
{4, -1, 17}, _
{12, 1, -6}}
Private targval As Single() = New Single() {-1, -1, 1, 1, -1, 1, -1, -1}
Private targval2 As Single() = New Single() {-1, 1, 1}
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) _
Handles Button1.Click
Dim TrainError As Single
Dim I, J, K As Integer
Dim TrainingCycles As Integer
Dim TrainingComplete As Boolean = False
Initialize(n, m)
J = 0
Do Until J = 10001
TrainError = 0
For I = 0 To NumCases - 1
For K = 0 To n - 1
InputNeuron(K) = X1(I, K)
Next
hiddeninput(n, m)
outputinput(m)
oout = Sigmoid(oin)
BackPropagate(I, m)
If J > 999 Then
If J Mod 1000 = 0 Then
Text1.Text += CStr(J) & " " & CStr(I) & " " & CStr(targval(I)) _
& " " & CStr(oout) & CR
End If
End If
TrainError = TrainError + (targval(I) - oout) ^ 2
Next I
TrainError = System.Math.Sqrt(TrainError / NumCases)
If J > 999 Then
If J Mod 1000 = 0 Then
Text1.Text += "Training Error: " + CStr(TrainError) + CR
End If
End If
If TrainError < 0.01 Then
If TrainingComplete = False Then
TrainingCycles = J
TrainingComplete = True
End If
End If
J += 1
Loop
Text1.Text += CR + "Training iterations needed: " + CStr(TrainingCycles) + CR
ExaminePatient()
ValidateNet()
End Sub
Private Sub Initialize(ByVal n As Integer, ByVal m As Integer)
'Since there's no way of knowing the appropriate weights and
'biases prior to training, randomly initialize each neuron
'with a weight between –0.5 and 0.5
Dim I, J As Integer
Randomize(Microsoft.VisualBasic.Timer)
For I = 0 To n - 1
For J = 0 To m - 1
hweight(I, J) = (Rnd() - 0.5) 'hidden layer connections.
hweight2(I, J) = hweight(I, J) 'copies for training.
Next J
Next I
For J = 0 To m - 1
hbias(J) = (Rnd() - 0.5) 'hidden layer biases.
hbias2(J) = hbias(J) 'copies for training.
oweight(J) = (Rnd() - 0.5) 'output layer connections.
oweight2(J) = oweight(J) 'copies for training.
Next J
obias = (Rnd() = 0.5) 'output neuron bias
obias2 = obias 'copy for training.
End Sub
Private Sub hiddeninput(ByVal n As Integer, ByVal m As Integer)
'This carries out the summation process for each neuron in the
'hidden layer of the neural network.
'The input value to a node is:
'the bias for that node
'added to the sum of each input interconnection,
'where the value of an interconnection is the input neuron's value
'multiplied by the weight of the connection.
Dim I, J As Integer
Dim sum As Single
For J = 0 To m - 1
sum = 0
For I = 0 To n - 1
sum = sum + (InputNeuron(I) * hweight(I, J))
Next I
hin(J) = hbias(J) + sum
Next J
'Send each scaled input of the hidden layer through
'the bipolar sigmoid (trans) function.
For J = 0 To m - 1
hout(J) = Sigmoid(hin(J))
Next J
End Sub
Private Sub outputinput(ByVal m As Integer)
'Pass hidden layer values through the weighted
'connections to the output layer.
Dim J As Integer
Dim sum As Single
sum = 0
For J = 0 To m - 1
sum = sum + (hout(J) * oweight(J))
Next J
oin = obias + sum
End Sub
Private Sub BackPropagate(ByVal I As Integer, ByVal m As Integer)
'Back-propagates the error to the interconnections between
'the output and hidden layer neurons.
Dim J As Integer
Dim odelta, dobias, doweight(m - 1) As Single
odelta = SigmoidDerivative(oin) * (targval(I) - oout)
For J = 0 To m - 1
doweight(J) = (alpha * odelta * hout(J)) + (mu * (oweight(J) - _
oweight2(J)))
oweight2(J) = oweight(J)
oweight(J) = oweight(J) + doweight(J)
Next J
dobias = (alpha * odelta) + (mu * (obias - obias2))
obias2 = obias
obias = obias + dobias
updatehidden(n, m, odelta)
End Sub
Private Sub updatehidden(ByVal n As Integer, ByVal m As Integer, ByVal d As Single)
'Since there can be multiple hidden layer neurons as well as multiple
'input neurons, some additional loops are utilized to ensure that every
'weight and bias is updated appropriately.
Dim I, J, K As Integer
Dim hdelta, dhbias(m - 1), dhweight(n - 1, m - 1) As Single
For J = 0 To m - 1
hdelta = (d * oweight(J)) * SigmoidDerivative(hin(J))
For I = 0 To n - 1
dhweight(I, J) = (alpha * hdelta * InputNeuron(I)) + (mu * _
(hweight(I, J) - _
hweight2(I, J)))
hweight2(I, J) = hweight(I, J)
hweight(I, J) = hweight(I, J) + dhweight(I, J)
Next I
dhbias(J) = (alpha * hdelta) + (mu * (hbias(J) - hbias2(J)))
hbias2(J) = hbias(J)
hbias(J) = hbias(J) + dhbias(J)
Next J
End Sub
Private Sub ExaminePatient()
InputNeuron(0) = Inputs(0) 'Change in cholesterol.
InputNeuron(1) = Inputs(1) 'Change in weight.
InputNeuron(2) = Inputs(2) 'Family members with heart disease.
hiddeninput(n, m)
outputinput(m)
oout = Sigmoid(oin)
If oout < 0 Then
Text1.Text += CR + "The patient is at a reduced risk for disease" + CR
Else
Text1.Text += CR + "The patient is at an increased risk for disease" + CR
End If
End Sub
Private Sub ValidateNet()
Dim I, J, K As Integer
Dim Correct As Integer = 0
For I = 0 To TestCases - 1
For K = 0 To n - 1
InputNeuron(K) = X2(I, K)
Next
hiddeninput(n, m)
outputinput(m)
oout = Sigmoid(oin)
If targval2(I) = System.Math.Round(oout) Then
Correct = Correct + 1
End If
Text1.Text += "Expected: " + CStr(targval2(I)) + " Actual: " + CStr(oout) + CR
Next I
If Correct >= 2 Then
Text1.Text += CStr(Correct) & " out of " & CStr(TestCases) & _
" Match. Validation Successful." + CR
Else
Text1.Text += CStr(Correct) & " out of " & CStr(TestCases) & _
" Match. Validation Unsuccessful." + CR
End If
End Sub
Private Function Sigmoid(ByVal Val As Single) As Single
'A.K.A. the activation function, it takes the sum of all the neurons'
'weighted inputs and uses the value to calculate the neurons' output.
'This output is also thought of as the "excitation" of the neuron.
Dim f As Single
f = (2 / (1 + (System.Math.Exp(-Val)))) - 1 'Output ranges from -1 to 1.
Sigmoid = f
End Function
Private Function SigmoidDerivative(ByVal Val As Single) As Single
'Backpropagation:
'Calculate delta by multiplying the difference between:
'an output computed by the neural network for a given pattern,
'and a target value for a known outcome for the given pattern,
'by the derivative of the activation function (Sigmoid).
Dim f As Single
f = (1 / 2) * (1 + Sigmoid(Val)) * (1 - Sigmoid(Val))
SigmoidDerivative = f
End Function