public static void Calibrate(List <CalibrationLine> points, bool isSecondOrder) { double m2 = 0; double m = 0; double q = 0; var centroids = points.Select(x => x.Centroid).ToArray(); var energies = points.Select(x => x.Energy).ToArray(); var areas = points.Select(x => x.Area); var totalWeight = areas.Sum(); var weights = areas.Select(x => x / totalWeight).ToArray(); var fittedModel = Fit.PolynomialWeighted(centroids, energies, weights, isSecondOrder ? 2 : 1); q = fittedModel[0]; m = fittedModel[1]; if (isSecondOrder) { m2 = fittedModel[2]; } using (StreamWriter writetext = new StreamWriter(String.Format("data/{0}.calibration", "last"))) { writetext.WriteLine("{0} {1} {2}", q, m, m2); } }
// HELPER METHODS private static double[] FitWeightedPolynomial( Dictionary <double, double> xy, Dictionary <double, double> weights, int polynomialDegree) { double[] xs = xy.Keys .OrderBy(x => x) .ToArray(); double[] ys = xs .Select(x => xy[x]) .ToArray(); double[] ws = xs .Select(x => weights[x]) .ToArray(); try { double[] polynomial = Fit.PolynomialWeighted( x: xs, y: ys, w: ws, order: polynomialDegree); return(polynomial); } catch (Exception e) { string filename = @"C:\Users\EBJ\Desktop\FitPolynomialWeighted.csv"; File.Delete(filename); using (TextWriter tw = File.AppendText(filename)) { tw.WriteLine("xs;ys;ws"); xs .ForEach((x, index) => { tw.WriteLine($"{x};" + $"{ys[index].ToString(CultureInfo.InvariantCulture)};" + $"{ws[index].ToString(CultureInfo.InvariantCulture)}"); }); tw.Flush(); tw.Close(); } throw; } }
public void Add(Vector2 point, DateTime time) { if (AddTimeSeriesPoint(point, time)) { IsReady = true; var timeMatrix = ConstructTimeDesignMatrix(); var x = ConstructTargetMatrix(Axis.X); var y = ConstructTargetMatrix(Axis.Y); try { this.xCoeff = new Polynomial(Fit.PolynomialWeighted(timeMatrix, x, this.weights, Complexity)); this.yCoeff = new Polynomial(Fit.PolynomialWeighted(timeMatrix, y, this.weights, Complexity)); } catch { Log.Write("MLCore", "Error in calculation", LogLevel.Error); IsReady = false; } } }
public void FitsToOrder2PolynomialWeighted() { // Mathematica: LinearModelFit[{{1,4.986},{2,2.347},{3,2.061},{4,-2.995},{5,-2.352},{6,-5.782}}, {1, x, x^2}, x, Weights -> {0.5, 1.0, 1.0, 1.0, 1.0, 0.5}] // -> 7.01451 - 2.12819 x + 0.0115 x^2 var x = Enumerable.Range(1, 6).Select(Convert.ToDouble).ToArray(); var y = new[] { 4.986, 2.347, 2.061, -2.995, -2.352, -5.782 }; var respUnweighted = Fit.PolynomialWeighted(x, y, new[] { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }, 2); Assert.AreEqual(3, respUnweighted.Length); Assert.AreEqual(6.9703, respUnweighted[0], 1e-4); Assert.AreEqual(-2.05564, respUnweighted[1], 1e-4); Assert.AreEqual(-0.00426786, respUnweighted[2], 1e-6); var resp = Fit.PolynomialWeighted(x, y, new[] { 0.5, 1.0, 1.0, 1.0, 1.0, 0.5 }, 2); Assert.AreEqual(3, resp.Length); Assert.AreEqual(7.01451, resp[0], 1e-4); Assert.AreEqual(-2.12819, resp[1], 1e-4); Assert.AreEqual(0.0115, resp[2], 1e-6); }
public static AnalysisResults AnalyzeSurroundingHouses(List <House> houses, BovetaSearch search) { var results = new AnalysisResults(); // Should always be the case. Extra check just to make sure. houses = houses.Where(house => house.livingArea > 0).ToList(); // Should we use listing price or sold price? Better if possible. bool useSoldPrice = false; if (houses.Where(house => house.soldPrice > 0).Count() >= houses.Where(house => house.listPrice > 0).Count()) { useSoldPrice = true; houses = houses.Where(house => house.soldPrice > 0).ToList(); } else { houses = houses.Where(house => house.listPrice > 0).ToList(); } // For convenience int numHouses = houses.Count(); // At least MIN_RESULTS houses in big initial radius if (numHouses < MIN_RESULTS) { return(results); } // Optimize the number of houses/search radius houses = houses.OrderBy(w => w.distanceToReferencePoint).ToList(); double bestRadius = 0; double bestScore = Double.MinValue; for (double radius = 100; radius < 10000; radius = radius * 2) { int s = houses.Where(w => w.distanceToReferencePoint <= radius).Count(); double order = Math.Log(s, LOG_BASE); double score = order - radius / RADIUS_W; Console.WriteLine(" Radius: " + radius + "Score: " + score); if (score > bestScore & s > MIN_RESULTS) { bestRadius = radius; bestScore = score; } } results.SearchRadius = bestRadius; houses = houses.Where(w => w.distanceToReferencePoint < bestRadius).ToList(); if (houses.Count < MIN_RESULTS) { return(results); } List <double> xdata = new List <double>(); List <double> ydata = new List <double>(); List <double> weights = new List <double>(); foreach (var house in houses) { int housePrice = house.listPrice; if (useSoldPrice) { housePrice = house.soldPrice; } weights.Add(1 + POL_WEIGHT_NUM / (POL_WEIGHT_DENOM + house.distanceToReferencePoint)); xdata.Add(house.livingArea); ydata.Add(housePrice); } var p = Fit.PolynomialWeighted(xdata.ToArray(), ydata.ToArray(), weights.ToArray(), 1); double estimation = p[0] + p[1] * search.Size; if (search.Condition != HouseCondition.Average) { // Adjust weights to accomodate for condition List <double> modelerr = new List <double>(); // 1. Find error in current model. Use this as measure for over/under valuation for (int i = 0; i < ydata.Count; ++i) { double modelError = ydata[i] - (p[0] + p[1] * xdata[i]); modelerr.Add(modelError); } // 2. Adjust weights so that overvalued houses are worth more. for (int i = 0; i < modelerr.Count; i++) { if (modelerr[i] < 0) // Model price > real price. Probably bad condition { if (search.Condition == HouseCondition.AboveAverage) { weights[i] = weights[i] * 0.5; // Less representive of true house price } else if (search.Condition == HouseCondition.BelowAverage) { weights[i] = weights[i] * 2; // More representive of true house price } } else // Model price < real price. Probably good condition { if (search.Condition == HouseCondition.AboveAverage) { weights[i] = weights[i] * 2; // More representive of true house price } else if (search.Condition == HouseCondition.BelowAverage) { weights[i] = weights[i] * 0.5; // Less representive of true house price } } } // Recalculate polynomial p = Fit.PolynomialWeighted(xdata.ToArray(), ydata.ToArray(), weights.ToArray(), 1); } results.Intercept = p[0]; results.BetaSize = p[1]; results.NumDatapointsUsed = houses.Count(); results.EstimatedValue = (int)(results.Intercept + results.BetaSize * search.Size); if (search.Condition == HouseCondition.BelowAverage & results.EstimatedValue > estimation) { // Oops. Our advanced searched failed. Reduce cost by 10% for now..... results.EstimatedValue = results.EstimatedValue * 0.9; } if (search.Condition == HouseCondition.AboveAverage & results.EstimatedValue < estimation) { // Oops. Our advanced searched failed. Increase cost by 10% for now..... results.EstimatedValue = results.EstimatedValue * 1.1; } results.ConfidenceScore = 0.6; return(results); }