As I promised, I'm posting my sketch following the discussion of storage and access to the neuron data.
This is just cultural techniques which you may or may not be well familiar with.
These techniques illustrate the following:
- Separation of storage layer from semantic layer.
- You don't need to work with arrays, instead, you need array-like interface to the network with the use of indexed property
this
. - You do not need rank-2 array for storage; it is essentially the rank-1 array.
- How to use the same data using the interface of rank-1 and rank-2 (rank-3, or whatever else) array at the same time. See
GetStorageIndex
. - How to develop a class supporting more than one indexed property
this
with different signature. The only way to do this is implementing interface with the indexed property this
. - How to limit visibility of the storage layer.
- How to use identical storage schema for different dimensions of the neural network. See
NeuralNetworkMetadata
used to support, store and load dimensions.
I hope your disk storage is binary? It should be, for the sake of performance. Also, the stream should be buffered.
using System.IO;
using StreamPosition = System.Int64;
using StorageIndex = System.UInt64;
using NeuronIndex = System.UInt32;
using NeuronLayerIndex = System.UInt32;
class NeuronStorage {
internal static Neuron Load(Stream stream) { return null; }
internal void Store(Stream stream) { }
}
class Neuron : NeuronStorage { }
interface INeuralNetworkStorage {
Neuron this[StorageIndex index] { get; set; }
}
interface INeuralNetwork : INeuralNetworkStorage {
Neuron this[NeuronLayerIndex layer, NeuronIndex index] { get; set; }
}
class NeuralNetworkMetadata {
internal NeuronIndex NeuronsPerLayer { get { } }
internal NeuronLayerIndex LayerCount { get { } }
internal static NeuralNetworkMetadata Load(Stream stream) { }
internal void Store(Stream stream) { }
}
class NeuralNetworkStorage : INeuralNetworkStorage {
public NeuralNetworkStorage(string fileName) { }
public Neuron this[StorageIndex index] {
get {
Stream.Seek(GetNeuronStreamPosition(index), SeekOrigin.Begin);
return Neuron.Load(Stream);
}
set {
Stream.Seek(GetNeuronStreamPosition(index), SeekOrigin.Begin);
value.Store(Stream);
}
}
internal protected NeuralNetworkMetadata Metadata;
StreamPosition GetNeuronStreamPosition(StorageIndex index) { }
Stream Stream;
}
class NeuralNetwork : NeuralNetworkStorage, INeuralNetwork {
public NeuralNetwork(string fileName) : base(fileName) { }
public NeuralNetwork(string fileName, NeuralNetworkMetadata metadata) : base(fileName) { }
public Neuron this[NeuronIndex index, NeuronLayerIndex layer] {
get { return this[GetStorageIndex(index, layer)]; }
set { this[GetStorageIndex(index, layer)] = value; }
}
StorageIndex GetStorageIndex(NeuronIndex neutron, NeuronLayerIndex layer) {
return layer * Metadata.NeuronsPerLayer + neutron;
}
}
The separate section of storage should be designated for relationships between neutron. The technique may depend on several factors, first of an how sparse is the Cartesian Square, how big is the total number of associations, how the should be used.
I hope all the techniques and ideas I provide can be useful.
—SA