/// <summary> /// Constructs with the details of the function regression problem to be visualized. /// </summary> /// <param name="fn">The function being regressed.</param> /// <param name="generativeMode">Indicates that blacbox has no inputs; it will generate a waveform as a function of time.</param> /// <param name="paramSamplingInfo">Parameter sampling info.</param> /// <param name="genomeDecoder">Genome decoder.</param> public FnRegressionView2D(IFunction fn, ParamSamplingInfo paramSamplingInfo, bool generativeMode, IGenomeDecoder <NeatGenome, IBlackBox> genomeDecoder) { InitializeComponent(); InitGraph(string.Empty, string.Empty, string.Empty); _fn = fn; _paramSamplingInfo = paramSamplingInfo; _generativeMode = generativeMode; _genomeDecoder = genomeDecoder; // Determine the mid output value of the function (over the specified sample points) and a scaling factor // to apply the to neural netwkrk response for it to be able to recreate the function (because the neural net // output range is [0,1] when using the logistic function as the neurn activation function). double mid, scale; FnRegressionUtils.CalcFunctionMidAndScale(fn, paramSamplingInfo, out mid, out scale); if (generativeMode) { _blackBoxProbe = new GenerativeBlackBoxProbe(paramSamplingInfo, mid, scale); } else { _blackBoxProbe = new BlackBoxProbe(paramSamplingInfo, mid, scale); } _yArrTarget = new double[paramSamplingInfo._sampleCount]; // Pre-build plot point objects. _plotPointListTarget = new PointPairList(); _plotPointListResponse = new PointPairList(); double[] xArr = paramSamplingInfo._xArr; for (int i = 0; i < xArr.Length; i++) { double x = xArr[i]; _plotPointListTarget.Add(x, _fn.GetValue(x)); _plotPointListResponse.Add(x, 0.0); } // Bind plot points to graph. zed.GraphPane.AddCurve("Target", _plotPointListTarget, Color.Black, SymbolType.None); zed.GraphPane.AddCurve("Network Response", _plotPointListResponse, Color.Red, SymbolType.None); }
/// <summary> /// Evaluate the provided IBlackBox against the XOR problem domain and return its fitness score. /// </summary> public FitnessInfo Evaluate(IBlackBox box) { int sampleCount = _paramSamplingInfo._sampleCount; // TODO: We can avoid a memory allocation here by allocating at construction time, but this requires modification of // ParallelGenomeListEvaluator to utilise multiple evaluators (one per thread). double[] yArr = new double[sampleCount]; double[] gradientArr = new double[sampleCount]; // Probe the black box over the full range of the input parameter. _blackBoxProbe.Probe(box, yArr); // Calc gradients. FnRegressionUtils.CalcGradients(_paramSamplingInfo, yArr, gradientArr); // Calc y position mean squared error (MSE), and apply weighting. double yMse = FnRegressionUtils.CalcMeanSquaredError(yArr, _yArrTarget); yMse *= _yMseWeight; // Calc gradient mean squared error. double gradientMse = FnRegressionUtils.CalcMeanSquaredError(gradientArr, _gradientArrTarget); gradientMse *= _gradientMseWeight; // Calc fitness as the inverse of MSE (higher value is fitter). // Add a constant to avoid divide by zero, and to constrain the fitness range between bad and good solutions; // this allows the selection strategy to select solutions that are mediocre and therefore helps preserve diversity. double fitness = 20.0 / (yMse + gradientMse + 0.02); // Test for stopping condition (near perfect response). if (fitness >= 100000.0) { _stopConditionSatisfied = true; } _evalCount++; return(new FitnessInfo(fitness, fitness)); }