Working With Structures

madaxe

Member
Joined
Mar 18, 2008
Messages
16
Programming Experience
1-3
I am trying to create a Neural network project to do some basic tasks, and have created some structures which I am implimenting. However my problem comes when I try to loop through and populate the data. I am doing this with a For Each loop which seems to work but it seems to be populating a temporary copy of the structure in memory and not the structure being implimented

The code below shows my structures which i initially had as individual structures in a seperate module but then i nested them which seems to work the same, is there anyhting wrong with nesting the structures like this.

VB.NET:
Public Structure NeuralNetwork

    Public LayerCount As Integer
    Public Layers() As Layer

    Public Structure Layer

        Public NeuronCount As Integer
        Public Neurons() As Neuron

        Public Structure Neuron

            Public InputsCount As Integer
            Public Value As Integer
            Public Threshold As Double
            Public Sumation As Double
            Public ErrorValue As Double
            Public ErrorCorrection As Double
            Public LearningRate As Double
            Public Inputs() As Input
            Public InputBias As Bias

            Public Structure Input

                Public Value As Integer
                Public Weight As Double

            End Structure

            Public Structure Bias

                Public Value As Integer
                Public Weight As Double

            End Structure

        End Structure

    End Structure

End Structure


This code is where im having the probelm with instancing the structures into my project. Within the SetUpRandoms() sub routine the Inputs.Value is not being bpopulated within the instance of the Network.

Please help i dont understand what im doing wrong, i think it has something to do with the NEW keyword either being used or not used incorrectly.

Madaxe

VB.NET:
Public Class Form1

    Public NumberOfLayers As Integer = 1
    Public NumberOfNeurons As Integer = 1
    Public NumberOfInputs As Integer = 16

    Public LearningRate As Double = 0.2
    Public Threshold As Double = 0.5

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim NoLayers As Integer = NumberOfLayers - 1
        Dim NoNeurons As Integer = NumberOfNeurons - 1
        Dim NoInputs As Integer = NumberOfInputs - 1

        Dim MyNetwork As New NeuralNetwork
        Dim MyLayers() As NeuralNetwork.Layer = MyNetwork.Layers


        ReDim MyNetwork.Layers(NoLayers)
        MyNetwork.LayerCount = NumberOfLayers

        ReDim MyNetwork.Layers(NoLayers).Neurons(NoNeurons)
        MyNetwork.Layers(NoLayers).NeuronCount = NumberOfNeurons

        ReDim MyNetwork.Layers(NoLayers).Neurons(NoNeurons).Inputs(NoInputs)
        MyNetwork.Layers(NoLayers).Neurons(NoNeurons).InputsCount = NumberOfInputs

        MyNetwork.Layers(NoLayers).Neurons(NoNeurons).LearningRate = LearningRate
        MyNetwork.Layers(NoLayers).Neurons(NoNeurons).Threshold = Threshold

        MyNetwork.Layers(NoLayers).Neurons(NoNeurons).InputBias.Value = 1
        MyNetwork.Layers(NoLayers).Neurons(NoNeurons).InputBias.Weight = 0.5

        MyNetwork.Layers(NoLayers).Neurons(NoNeurons).Value = SumateData()

        SetUpRandoms(MyNetwork)

    End Sub

    Private Sub SetUpRandoms(ByVal MyNetwork As NeuralNetwork)

        For Each Layer In MyNetwork.Layers

            For Each Neuron In Layer.Neurons

                For Each Inputs In Neuron.Inputs

 [B][I][U]                   Inputs.Weight = RandomWeight()[/U][/I][/B]
                Next

            Next

        Next

    End Sub

    Private Function RandomWeight() As Double

        Dim MyRandom As New Random(System.DateTime.Now.Millisecond)

        Dim MyMin As Integer = -100
        Dim MyMax As Integer = 100

        Return (MyRandom.Next(MyMin, MyMax)) / 100

    End Function

End Class
 
You are quite right that what your code is doing is working on copies. That's how value types work, and structures are value types.

When you assign a value somewhere, you are making a copy of that value. In the case of value types, the value is the object itself, so you are making a copy of the object. In the case of reference types, the value is a reference to the object, so you're creating another reference to the same object.

One interesting exception to that rule is indexing an array. When you get an array element by index, you are getting the original object, even if it's a value type. Now, you might think that your code should be working then, because you're using arrays. You aren't indexing those arrays though, so you are creating copies.

You have three choices:

1. Use classes instead of structures. Your Neuron type really should be a class anyway, given that it exceeds the generally accepted maximum size of a structure, i.e. 16 bytes.

2. Use For loops instead of For Each loops. Then you will be indexing the arrays and you won't be creating copies.

3. After creating the copy and modifying it, assign it back to the array element. For that you'd need the index anyway, so it's not much help if you're not using For loops and, if you were, you wouldn't this option anyway.
 
Thanks I kind of understood that, but now i have more questions.

So do i make a class for each piece of the structure or just the network?

So for each loops are making copies of the object when it indexes through? So when should i use for each loops?

After i make a copy how do i assign it back tot he array element?

I really appreciate all of the help

Madaxe
 
Ok I worked on it a little bit more and I think I did everything correctly as to your post which i thanks you again for so for starters

I turned the structures into classes

VB.NET:
Public Class NeuralNetwork

    Public LayerCount As Integer
    Public Layers(LayerCount) As Layer

End Class

Public Class Layer

    Public NeuronCount As Integer
    Public Neurons(NeuronCount) As Neuron

End Class

Public Class Neuron

    Public InputsCount As Integer
    Public Value As Integer
    Public Threshold As Double
    Public Sumation As Double
    Public ErrorValue As Double
    Public ErrorCorrection As Double
    Public LearningRate As Double
    Public Inputs(InputsCount) As Input
    Public InputBias As Bias

End Class

Public Class Input

    Public Value As Integer
    Public Weight As Double

End Class

Then i rewrote this, how did i do?

VB.NET:
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim NoLayers As Integer = NumberOfLayers - 1
        Dim NoNeurons As Integer = NumberOfNeurons - 1
        Dim NoInputs As Integer = NumberOfInputs - 1

        Dim MyNetwork As New NeuralNetwork
        MyNetwork.LayerCount = NumberOfLayers
        ReDim MyNetwork.Layers(MyNetwork.LayerCount)

        Dim LayerIndex As Integer = 0
        Dim NeuronIndex As Integer = 0
        Dim InputIndex As Integer = 0

        For LayerIndex = 0 To NoLayers

            ReDim Preserve MyNetwork.Layers(LayerIndex)
            MyNetwork.Layers(LayerIndex) = New Layer
            MyNetwork.Layers(LayerIndex).NeuronCount = NumberOfNeurons

            For NeuronIndex = 0 To NoNeurons

                ReDim Preserve MyNetwork.Layers(LayerIndex).Neurons(NeuronIndex)
                MyNetwork.Layers(LayerIndex).Neurons(NeuronIndex) = New Neuron
                MyNetwork.Layers(LayerIndex).Neurons(NeuronIndex).InputsCount = NumberOfInputs

                For InputIndex = 0 To NoInputs

                    ReDim Preserve MyNetwork.Layers(LayerIndex).Neurons(NeuronIndex).Inputs(InputIndex)
                    MyNetwork.Layers(LayerIndex).Neurons(NeuronIndex).Inputs(InputIndex) = New Input
                    MyNetwork.Layers(LayerIndex).Neurons(NeuronIndex).Inputs(InputIndex).Weight = RandomWeight()

                Next

            Next

        Next

    End Sub
 
Unless you have a very good reason for using arrays, like you need to fix the number of elements, I would suggest using collections exposed via read-only properties. That's the way it's done throughout the .NET Framework, e.g.
VB.NET:
Friend Class Layer

    Private _neurons As New List(Of Neuron)

    Public ReadOnly Property Neurons() As List(Of Neuron)
        Get
            Return _neurons
        End Get
    End Property

End Class
You can then do this:
VB.NET:
For i = 1 To neuronCount
    Dim n As New Neuron

    '...

    myLayer.Neurons.Add(n)
Next
 
Im sorry I have only really worked in VBA so when it comes to; shared, friend etc im not very good could you explain a little more please

I believe the _ indicates the inheritable object am i correct? BUt i though Neurons would be there own class?


Thanks

Madaxe
 
You're trying to read too much into what I posted. The Friend part isn't really relevant. That simply means that the type is not accessible outside the current project, which is appropriate for an application. It doesn't affect the functionality of the type, only the accessibility. The underscore doesn't mean anything. It's simply part of the name. Using it like that is a common way to allow a property and its backing field to effectively have the same name.

The important thing to take away from that code example is that the Layer class has a Private field that refers to a collection of Neuron objects. Yes, Neuron is a separate class and that collection contains objects of that type. The collection is used instead of an array. The collection is exposed via a Public ReadOnly property. By making it read-only, callers can get the collection, enabling them you get, add and remove items, but they cannot replace the entire collection with another collection.

This pattern is used liberally throughout the .NET Framework. The Control class has a Controls property that is a collection of its child controls. The ImageList class has an Images property that is a collection of Images. The DataTable class has Columns and Rows properties that are collections of DataColumns and DataRows. The DataSet class has Tables and Relations properties that are collections of DataTables and DataRelations. Etc, etc.

In your case, your Neuron class would have an Inputs property that is a collection of Input objects your Layer class would have a Neurons property that is a collection of Neuron objects.
 
Back
Top