public Bitmap AutoContourPlot(IFunctionWithDerivative funcition, List <Tuple <Color, List <Vector <double> > > > pointGroups, float marginPerc, int xDimIndex, int yDimIndex, int imgWidth, int imgHeight, int contoursCount, double scalePower) { double minX = double.PositiveInfinity, minY = double.PositiveInfinity, maxX = double.NegativeInfinity, maxY = double.NegativeInfinity; foreach (var group in pointGroups) { foreach (var pt in group.Item2) { minX = Math.Min(minX, pt[xDimIndex]); minY = Math.Min(minY, pt[yDimIndex]); maxX = Math.Max(maxX, pt[xDimIndex]); maxY = Math.Max(maxY, pt[yDimIndex]); } } double w = maxX - minX; double h = maxY - minY; var origin = new DenseVector(funcition.DimensionsCount); origin[xDimIndex] = minX + w / 2; origin[yDimIndex] = minY + h / 2; double stepPerPixel = Math.Max(w / imgWidth, h / imgHeight) * (1 + marginPerc); return(ContourPlot(funcition, origin, xDimIndex, yDimIndex, imgWidth, imgHeight, stepPerPixel, contoursCount, scalePower, pointGroups)); }
public bool Optimize(Vector <double> resultAndInitPos, IFunctionWithDerivative function, double minDerivCompMaxMagn, Action <int, Func <Vector <double> > > iterationCallback, CancellationToken ct) { Contract.Requires(resultAndInitPos.Count == function.DimensionsCount); Contract.Requires(minDerivCompMaxMagn > 0); double minStep = minDerivCompMaxMagn / 100; int[] prevStepSigns = new int[function.DimensionsCount]; var stepSize = new DenseVector(function.DimensionsCount); var derivative = new DenseVector(function.DimensionsCount); for (int i = 0; i < stepSize.Count; ++i) { stepSize[i] = initialStep; } for (int iter = 0; iter < maxIters; ++iter) { if (ct.IsCancellationRequested) { break; } // Compute current derivative. function.Derivate(derivative, resultAndInitPos); if (derivative.AbsoluteMaximum() < minDerivCompMaxMagn) { return(true); } // Update step sizes and step weights. for (int i = 0; i < prevStepSigns.Length; ++i) { int currSign = Math.Sign(derivative[i]); int sign = currSign * prevStepSigns[i]; if (sign > 0) { stepSize[i] = Math.Min(maxStep, stepSize[i] * stepUpMult); } else if (sign < 0) { stepSize[i] = Math.Max(minStep, stepSize[i] * stepDownMult); currSign = 0; } resultAndInitPos[i] -= currSign * stepSize[i]; prevStepSigns[i] = currSign; } if (iterationCallback != null) { iterationCallback(iter, resultAndInitPos.Clone); } } return(false); }
private ActionResult plot(IFunctionWithDerivative f, PlotViewModel model) { List <Tuple <Color, List <Vector <double> > > > points = new List <Tuple <Color, List <Vector <double> > > >(); double minDeriv = model.MinDerivCompMaxMagn; var result = new DenseVector(f.DimensionsCount); { result[0] = model.InitialX; result[1] = model.InitialY; var ps = new List <Vector <double> >(); points.Add(new Tuple <Color, List <Vector <double> > >(Color.Lime, ps)); var sdImpl = new SteepestDescentBasicOptmizer(model.BasicStep, model.MaxIters); sdImpl.Optimize(result, f, model.MinDerivCompMaxMagn, (i, pFunc) => ps.Add(pFunc()), CancellationToken.None); } { result[0] = model.InitialX; result[1] = model.InitialY; var ps = new List <Vector <double> >(); points.Add(new Tuple <Color, List <Vector <double> > >(Color.Red, ps)); var sdImpl = new SteepestDescentBasicOptmizer(model.MomentumStep, model.MomentumStart, model.MomentumEnd, model.MaxIters); sdImpl.Optimize(result, f, model.MinDerivCompMaxMagn, (i, pFunc) => ps.Add(pFunc()), CancellationToken.None); } { result[0] = model.InitialX; result[1] = model.InitialY; var ps = new List <Vector <double> >(); points.Add(new Tuple <Color, List <Vector <double> > >(Color.Blue, ps)); var sdImpl = new SteepestDescentAdvancedOptmizer(model.MomentumStep, model.MomentumStart, model.MomentumEnd, model.MaxIters); sdImpl.Optimize(result, f, model.MinDerivCompMaxMagn, (i, pFunc) => ps.Add(pFunc()), CancellationToken.None); } { result[0] = model.InitialX; result[1] = model.InitialY; var ps = new List <Vector <double> >(); points.Add(new Tuple <Color, List <Vector <double> > >(Color.Magenta, ps)); var sdImpl = new RpropPlusOptmizer(model.BasicStep, 10, 1.2, 0.5, model.MaxIters); sdImpl.Optimize(result, f, model.MinDerivCompMaxMagn, (i, pFunc) => ps.Add(pFunc()), CancellationToken.None); } { result[0] = model.InitialX; result[1] = model.InitialY; var ps = new List <Vector <double> >(); points.Add(new Tuple <Color, List <Vector <double> > >(Color.Cyan, ps)); var sdImpl = new ImprovedRpropMinusOptmizer(model.BasicStep, 10, 1.2, 0.5, model.MaxIters); sdImpl.Optimize(result, f, model.MinDerivCompMaxMagn, (i, pFunc) => ps.Add(pFunc()), CancellationToken.None); } var fp = new FunctionPlotter(); var img = fp.AutoContourPlot(f, points, 0.1f, 0, 1, model.Width, model.Height, model.ContoursCount, model.ScalePower); var ms = new MemoryStream(); img.Save(ms, ImageFormat.Png); ms.Seek(0, SeekOrigin.Begin); return(File(ms, "image/png")); }
//private void performTrainTestWithPlots(Net net, Matrix<double> inputs, int[] outputIndices, // double learningRate, double regularizationLambda, int maxIters, double stepPerPixel) { // var optimizer = new SteepestDescentAdvancedOptmizer(learningRate, 0.6, 0.99, 1e-4, maxIters); // var trainer = new NetTrainer(net, optimizer, regularizationLambda); // var cf = new NetCostFunction(net, inputs, outputIndices, regularizationLambda); // trainer.InitializeCoefs(net); // double costBefore = cf.Evaluate(net.Coefficients.Pack()); // var optimizationSteps = new List<Vector<double>>(); // bool result = trainer.Train(inputs, outputIndices, p => optimizationSteps.Add(p)); // new FunctionPlotter() // .FunctionPlot(optimizationSteps.Select(pt => cf.Evaluate(pt)).ToArray(), 1024, 512, 0, 2) // .Save("err.png", ImageFormat.Png); // int dims = cf.DimensionsCount; // var plotOrigin = net.Coefficients.Pack(); // for (int dx = 0; dx < dims; ++dx) { // for (int dy = dx + 1; dy < dims; ++dy) { // plotOptimization(cf, plotOrigin, dx, dy, stepPerPixel, optimizationSteps); // } // } // double costAfter = cf.Evaluate(net.Coefficients.Pack()); // Assert.IsTrue(costAfter < costBefore); // var actualOutputIndices = trainer.Predict(inputs); // CollectionAssert.AreEqual(outputIndices, actualOutputIndices); // Assert.IsTrue(result); //} private void plotOptimization(IFunctionWithDerivative fun, Vector <double> origin, int xDimIndex, int yDimIndex, double stepPerPixel, List <Vector <double> > points) { var plotter = new FunctionPlotter(); var img = plotter.ContourPlot(fun, origin, xDimIndex, yDimIndex, 512, 512, stepPerPixel, 10, 0.5, new List <Tuple <Color, List <Vector <double> > > >() { new Tuple <Color, List <Vector <double> > >(Color.DarkGreen, points) }); img.Save(string.Format("x={0};y={1}.png", xDimIndex, yDimIndex), ImageFormat.Png); }
public static void PerformDerivativeTest(IFunctionWithDerivative func, params double[][] points) { var nd = new NumericDerivator(func.Evaluate, COMPUTE_EPSILON); var actual = new DenseVector(points[0].Length); var expected = new DenseVector(points[0].Length); foreach (var point in points) { var pt = new DenseVector(point); nd.ComputeDerivative(expected, pt); func.Derivate(actual, pt); for (int i = 0; i < expected.Count; ++i) { Assert.IsTrue(Math.Abs(expected[i] - actual[i]) < CHECK_EPSILON); } } }
public bool Optimize(Vector <double> resultAndInitPos, IFunctionWithDerivative function, double minDerivCompMaxMagn, Action <int, Func <Vector <double> > > iterationCallback, CancellationToken ct) { Contract.Requires(resultAndInitPos.Count == function.DimensionsCount); Contract.Requires(minDerivCompMaxMagn > 0); var derivative = new DenseVector(function.DimensionsCount); var prevStep = new DenseVector(function.DimensionsCount); var position = new DenseVector(function.DimensionsCount); for (int iter = 0; iter < maxIters; ++iter) { if (ct.IsCancellationRequested) { break; } resultAndInitPos.CopyTo(position); double momentum = momentumStart + (momentumEnd - momentumStart) * ((double)iter / maxIters); // Compute derivative take step to point + momentum * prevStep and compute derivative there. prevStep.Multiply(momentum, prevStep); prevStep.Add(position, resultAndInitPos); function.Derivate(derivative, resultAndInitPos); if (derivative.AbsoluteMaximum() < minDerivCompMaxMagn) { return(true); } // Scale derivative and subtract from result to take "correction" step. derivative.Multiply(step, derivative); resultAndInitPos.Subtract(derivative, resultAndInitPos); // Conpute prevStep as (result - point). resultAndInitPos.Subtract(position, prevStep); if (iterationCallback != null) { iterationCallback(iter, resultAndInitPos.Clone); } } return(false); }
public bool Optimize(Vector <double> resultAndInitPos, IFunctionWithDerivative function, double minDerivCompMaxMagn, Action <int, Func <Vector <double> > > iterationCallback, CancellationToken ct) { Contract.Requires(resultAndInitPos.Count == function.DimensionsCount); Contract.Requires(minDerivCompMaxMagn > 0); var derivative = new DenseVector(function.DimensionsCount); var prevStep = new DenseVector(function.DimensionsCount); for (int iter = 0; iter < maxIters; ++iter) { if (ct.IsCancellationRequested) { break; } function.Derivate(derivative, resultAndInitPos); if (derivative.AbsoluteMaximum() < minDerivCompMaxMagn) { return(true); } derivative.Multiply(step, derivative); double momentum = momentumStart + (momentumEnd - momentumStart) * ((double)iter / maxIters); prevStep.Multiply(momentum, prevStep); prevStep.Add(derivative, prevStep); resultAndInitPos.Subtract(prevStep, resultAndInitPos); if (iterationCallback != null) { iterationCallback(iter, resultAndInitPos.Clone); } } return(false); }
public Bitmap ContourPlot(IFunctionWithDerivative funcition, Vector <double> origin, int xDimIndex, int yDimIndex, int imgWidth, int imgHeight, double stepPerPixel, int contoursCount, double scalePower, List <Tuple <Color, List <Vector <double> > > > pointGroups) { var point = new DenseVector(origin.Count); origin.CopyTo(point); double xOrigin = origin[xDimIndex] - stepPerPixel * imgWidth / 2; double yOrigin = origin[yDimIndex] - stepPerPixel * imgHeight / 2; double min, max; min = max = funcition.Evaluate(origin); double[,] values = new double[imgHeight, imgWidth]; for (int y = 0; y < imgHeight; ++y) { point[yDimIndex] = yOrigin + (imgHeight - y - 1) * stepPerPixel; for (int x = 0; x < imgWidth; ++x) { point[xDimIndex] = xOrigin + x * stepPerPixel; double value = funcition.Evaluate(point); values[y, x] = value; if (value < min) { min = value; } else if (value > max) { max = value; } } } double range = max - min; var img = new Bitmap(imgWidth, imgHeight, PixelFormat.Format24bppRgb); var imgData = img.LockBits(new Rectangle(0, 0, imgWidth, imgHeight), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); int[,] contours = new int[imgHeight, imgWidth]; unsafe { byte *imgPtr = (byte *)imgData.Scan0; int imgStride = imgData.Stride; // Image colors. for (int y = 0; y < imgHeight; ++y) { int stride = y * imgStride; for (int x = 0; x < imgWidth; ++x) { int contour = (int)(contoursCount * Math.Pow((values[y, x] - min) / range, scalePower)); if (contour >= contoursCount) { contour = contoursCount - 1; // Fox for values that are equa to max. } Contract.Assert(contour >= 0 && contour < contoursCount); contours[y, x] = contour; byte color = (byte)(55 + 200 * contour / (contoursCount - 1)); int baseI = stride + x * 3; imgPtr[baseI] = color; imgPtr[baseI + 1] = color; imgPtr[baseI + 2] = color; } } // Contours in x direction. for (int y = 0; y < imgHeight; ++y) { int stride = y * imgStride; for (int x = 1; x < imgWidth; ++x) { if (contours[y, x] == contours[y, x - 1]) { continue; } int baseI = stride + x * 3; imgPtr[baseI] = 0; imgPtr[baseI + 1] = 0; imgPtr[baseI + 2] = 0; } } // Contours in y direction. for (int x = 0; x < imgWidth; ++x) { int offset = x * 3; for (int y = 1; y < imgHeight; ++y) { if (contours[y, x] == contours[y - 1, x]) { continue; } int baseI = y * imgStride + offset; imgPtr[baseI] = 0; imgPtr[baseI + 1] = 0; imgPtr[baseI + 2] = 0; } } } img.UnlockBits(imgData); // Points. if (pointGroups != null) { using (var g = Graphics.FromImage(img)) { g.SmoothingMode = SmoothingMode.HighQuality; int labelY = 10; int labelYSpace = 20; g.FillRectangle(new SolidBrush(Color.FromArgb(192, Color.White)), 8, labelY - 4, 40, labelYSpace * pointGroups.Count); foreach (var tuple in pointGroups) { var points = tuple.Item2; if (points.Count < 2) { continue; } Pen arrowPen = new Pen(Color.FromArgb(128, tuple.Item1), 1); arrowPen.EndCap = LineCap.ArrowAnchor; PointF previousPt = new PointF( (float)((points[0][xDimIndex] - xOrigin) / stepPerPixel), imgHeight - (float)((points[0][yDimIndex] - yOrigin) / stepPerPixel) - 1); const int margin = 1024; // Arrows. for (int i = 1; i < points.Count; ++i) { PointF pt = new PointF( (float)((points[i][xDimIndex] - xOrigin) / stepPerPixel), imgHeight - (float)((points[i][yDimIndex] - yOrigin) / stepPerPixel) - 1); if (pt.X < -margin || pt.Y < -margin || pt.X >= imgHeight + margin || pt.Y >= imgHeight + margin) { continue; } g.DrawLine(arrowPen, previousPt, pt); previousPt = pt; } string steps = points.Count.ToString(); g.DrawString(steps, SystemFonts.DefaultFont, new SolidBrush(tuple.Item1), 10, labelY); labelY += labelYSpace; } } } return(img); }