/// <summary> /// Create the flat neural network. /// </summary> public void Flatten() { bool isRBF = false; IDictionary <ILayer, FlatLayer> regular2flat = new Dictionary <ILayer, FlatLayer>(); IDictionary <FlatLayer, ILayer> flat2regular = new Dictionary <FlatLayer, ILayer>(); IList <ObjectPair <ILayer, ILayer> > contexts = new List <ObjectPair <ILayer, ILayer> >(); this.flat = null; ValidateForFlat val = new ValidateForFlat(); if (val.IsValid(this.network) == null) { if (this.layers.Count == 3 && this.layers[1] is RadialBasisFunctionLayer) { RadialBasisFunctionLayer rbf = (RadialBasisFunctionLayer)this.layers[1]; this.flat = new FlatNetworkRBF(this.network.InputCount, rbf.NeuronCount, this.network.OutputCount, rbf.RadialBasisFunction); FlattenWeights(); this.flatUpdate = FlatUpdateNeeded.None; return; } int flatLayerCount = CountNonContext(); FlatLayer[] flatLayers = new FlatLayer[flatLayerCount]; int index = flatLayers.Length - 1; foreach (ILayer layer in this.layers) { if (layer is ContextLayer) { ISynapse inboundSynapse = network.Structure .FindPreviousSynapseByLayerType(layer, typeof(BasicLayer)); ISynapse outboundSynapse = network .Structure .FindNextSynapseByLayerType(layer, typeof(BasicLayer)); if (inboundSynapse == null) { throw new NeuralNetworkError( "Context layer must be connected to by one BasicLayer."); } if (outboundSynapse == null) { throw new NeuralNetworkError( "Context layer must connect to by one BasicLayer."); } ILayer inbound = inboundSynapse.FromLayer; ILayer outbound = outboundSynapse.ToLayer; contexts .Add(new ObjectPair <ILayer, ILayer>(inbound, outbound)); } else { double bias = this.FindNextBias(layer); IActivationFunction activationType; double[] param = new double[1]; if (layer.ActivationFunction == null) { activationType = new ActivationLinear(); param = new double[1]; param[0] = 1; } else { activationType = layer.ActivationFunction; param = layer.ActivationFunction.Params; } FlatLayer flatLayer = new FlatLayer(activationType, layer .NeuronCount, bias, param); regular2flat[layer] = flatLayer; flat2regular[flatLayer] = layer; flatLayers[index--] = flatLayer; } } // now link up the context layers foreach (ObjectPair <ILayer, ILayer> context in contexts) { // link the context layer on the FlatLayer ILayer layer = context.B; ISynapse synapse = this.network .Structure .FindPreviousSynapseByLayerType(layer, typeof(BasicLayer)); FlatLayer from = regular2flat[context.A]; FlatLayer to = regular2flat[synapse.FromLayer]; to.ContextFedBy = from; } this.flat = new FlatNetwork(flatLayers); // update the context indexes on the non-flat network for (int i = 0; i < flatLayerCount; i++) { FlatLayer fedBy = flatLayers[i].ContextFedBy; if (fedBy != null) { ILayer fedBy2 = flat2regular[flatLayers[i + 1]]; ISynapse synapse = FindPreviousSynapseByLayerType(fedBy2, typeof(ContextLayer)); if (synapse == null) { throw new NeuralNetworkError("Can't find parent synapse to context layer."); } ContextLayer context = (ContextLayer)synapse.FromLayer; // find fedby index int fedByIndex = -1; for (int j = 0; j < flatLayerCount; j++) { if (flatLayers[j] == fedBy) { fedByIndex = j; break; } } if (fedByIndex == -1) { throw new NeuralNetworkError("Can't find layer feeding context."); } context.FlatContextIndex = this.flat.ContextTargetOffset[fedByIndex]; } } // RBF networks will not train every layer if (isRBF) { this.flat.EndTraining = flatLayers.Length - 1; } FlattenWeights(); if (this.IsConnectionLimited) { } this.flatUpdate = FlatUpdateNeeded.None; } else { this.flatUpdate = FlatUpdateNeeded.Never; } }
/// <summary> /// Create the flat neural network. /// </summary> public void Flatten() { bool isRBF = false; IDictionary<ILayer, FlatLayer> regular2flat = new Dictionary<ILayer, FlatLayer>(); IDictionary<FlatLayer, ILayer> flat2regular = new Dictionary<FlatLayer, ILayer>(); IList<ObjectPair<ILayer, ILayer>> contexts = new List<ObjectPair<ILayer, ILayer>>(); this.flat = null; ValidateForFlat val = new ValidateForFlat(); if (val.IsValid(this.network) == null) { if (this.layers.Count == 3 && this.layers[1] is RadialBasisFunctionLayer) { RadialBasisFunctionLayer rbf = (RadialBasisFunctionLayer)this.layers[1]; this.flat = new FlatNetworkRBF(this.network.InputCount, rbf.NeuronCount, this.network.OutputCount, rbf.RadialBasisFunction); FlattenWeights(); this.flatUpdate = FlatUpdateNeeded.None; return; } int flatLayerCount = CountNonContext(); FlatLayer[] flatLayers = new FlatLayer[flatLayerCount]; int index = flatLayers.Length - 1; foreach (ILayer layer in this.layers) { if (layer is ContextLayer) { ISynapse inboundSynapse = network.Structure .FindPreviousSynapseByLayerType(layer, typeof(BasicLayer)); ISynapse outboundSynapse = network .Structure .FindNextSynapseByLayerType(layer, typeof(BasicLayer)); if (inboundSynapse == null) throw new NeuralNetworkError( "Context layer must be connected to by one BasicLayer."); if (outboundSynapse == null) throw new NeuralNetworkError( "Context layer must connect to by one BasicLayer."); ILayer inbound = inboundSynapse.FromLayer; ILayer outbound = outboundSynapse.ToLayer; contexts .Add(new ObjectPair<ILayer, ILayer>(inbound, outbound)); } else { double bias = this.FindNextBias(layer); IActivationFunction activationType; double[] param = new double[1]; if (layer.ActivationFunction == null) { activationType = new ActivationLinear(); param = new double[1]; param[0] = 1; } else { activationType = layer.ActivationFunction; param = layer.ActivationFunction.Params; } FlatLayer flatLayer = new FlatLayer(activationType, layer .NeuronCount, bias, param); regular2flat[layer] = flatLayer; flat2regular[flatLayer] = layer; flatLayers[index--] = flatLayer; } } // now link up the context layers foreach (ObjectPair<ILayer, ILayer> context in contexts) { // link the context layer on the FlatLayer ILayer layer = context.B; ISynapse synapse = this.network .Structure .FindPreviousSynapseByLayerType(layer, typeof(BasicLayer)); FlatLayer from = regular2flat[context.A]; FlatLayer to = regular2flat[synapse.FromLayer]; to.ContextFedBy = from; } this.flat = new FlatNetwork(flatLayers); // update the context indexes on the non-flat network for (int i = 0; i < flatLayerCount; i++) { FlatLayer fedBy = flatLayers[i].ContextFedBy; if (fedBy != null) { ILayer fedBy2 = flat2regular[flatLayers[i + 1]]; ISynapse synapse = FindPreviousSynapseByLayerType(fedBy2, typeof(ContextLayer)); if (synapse == null) throw new NeuralNetworkError("Can't find parent synapse to context layer."); ContextLayer context = (ContextLayer)synapse.FromLayer; // find fedby index int fedByIndex = -1; for(int j=0;j<flatLayerCount;j++) { if( flatLayers[j]==fedBy ) { fedByIndex = j; break; } } if (fedByIndex == -1) throw new NeuralNetworkError("Can't find layer feeding context."); context.FlatContextIndex = this.flat.ContextTargetOffset[fedByIndex]; } } // RBF networks will not train every layer if (isRBF) { this.flat.EndTraining = flatLayers.Length - 1; } FlattenWeights(); if (this.IsConnectionLimited) { } this.flatUpdate = FlatUpdateNeeded.None; } else this.flatUpdate = FlatUpdateNeeded.Never; }