Programm Zweck: Integration. Ich implementiere einen adaptiven Quadraturalgorithmus (aka numerische Integration) für hohe Dimensionen (bis zu 100). Die Idee besteht darin, das Volumen nach dem Zufallsprinzip in kleinere Abschnitte aufzuteilen, indem Punkte mit einer Abtastdichte ausgewertet werden, die proportional zu einer Schätzung des Fehlers an diesem Punkt ist. Früh habe ich eine einheitliche Probe "eingebrannt" und dann zufällig Punkte nach einer Gauß-Verteilung über den geschätzten Fehler gewählt. Ähnlich wie beim simulierten Tempern "erniedrige" ich die Temperatur und reduziere im weiteren Verlauf die Standardabweichung meiner Gauß'schen Kurve, so dass zunächst fehlerarme Punkte eine gute Chance haben, ausgewählt zu werden, später aber mit stetig abnehmenden Werten gewählt werden Wahrscheinlichkeit. Dies versetzt das Programm in die Lage, auf Spitzen zu stolpern, die aufgrund von Fehlern in der Fehlerfunktion übersehen werden könnten. (Mein Algorithmus ist im Geiste ähnlich zu Markov-Kette Monte-Carlo-Integration.)definieren Ziel mit Microsoft Solution Foundation
Funktionsmerkmale. Die zu integrierende Funktion ist der geschätzte Verlust von Versicherungspolicen für mehrere Gebäude aufgrund einer Naturkatastrophe. Policy-Funktionen sind nicht glatt: Es gibt Selbstbehalte, Höchstbeträge, Schichten (z. B. null Auszahlung bis zu 1 Million Dollar Verlust, 100% Auszahlung von 1-2 Millionen Dollar, dann Null Auszahlung über 2 Millionen Dollar) und andere ungerade Politikbedingungen. Dies führt nichtlineares Verhalten und Funktionen ein, die in zahlreichen Ebenen nicht abgeleitet sind. Zusätzlich zur Policy-Funktion ist die Schadensfunktion, die je nach Gebäudetyp und Stärke des Hurrikans variiert und definitiv nicht glockenförmig ist.
Problem Kontext: Fehler Funktion. Die Schwierigkeit besteht darin, eine gute Fehlerfunktion zu wählen. Für jeden Punkt zeichne ich Maßnahmen auf, die sinnvoll erscheinen: die Größe der Funktion, wie stark sie sich aufgrund einer vorherigen Messung verändert hat (ein Proxy für die erste Ableitung), das Volumen der Region, in der der Punkt liegt (größere Volumina können Fehler besser ausblenden) und ein geometrischer Faktor, der sich auf die Form der Region bezieht. Meine Fehlerfunktion wird eine lineare Kombination dieser Maße sein, wobei jedem Maß ein anderes Gewicht zugewiesen wird. (Wenn ich schlechte Ergebnisse bekomme, werde ich nichtlineare Funktionen in Erwägung ziehen.) Um mich bei diesen Bemühungen zu unterstützen, entschied ich mich, eine Optimierung über eine große Bandbreite von möglichen Werten für jedes Gewicht durchzuführen, daher die Microsoft Solution Foundation.
Was zu optimieren: Fehler Rank. Meine Maße sind normalisiert, von Null bis Eins. Diese Fehlerwerte werden progressiv überarbeitet, wenn die Integration fortschreitet, um die jüngsten Durchschnittswerte für Funktionswerte, Änderungen usw. widerzuspiegeln. Als Ergebnis versuche ich nicht, eine Funktion zu erzeugen, die tatsächliche Fehlerwerte liefert, sondern stattdessen eine Zahl, die gleich sortiert der wahre Fehler, dh wenn alle abgetasteten Punkte nach diesem geschätzten Fehlerwert sortiert sind, sollten sie einen Rang erhalten, der dem Rang ähnlich ist, den sie erhalten würden, wenn sie nach dem wahren Fehler sortiert wären.
Nicht alle Punkte sind gleich. Es ist mir sehr wichtig, ob der Punktbereich mit dem wahren Fehler # 1 # 1000 ist (oder umgekehrt), aber sorge dich sehr wenig, wenn der # 500-Punkt # 1000 ist. Mein Maß für den Erfolg ist die Summe der folgenden über viele Regionen an einem Punkt teilweise in den Algorithmus der Ausführung möglichst gering zu halten:
ABS (Log2 (trueErrorRank) - Log2 (estimatedErrorRank))
Für Log2 Ich verwende ein Funktion, die die größte Potenz von zwei kleiner oder gleich der Zahl zurückgibt. Aus dieser Definition ergeben sich nützliche Ergebnisse. Der Austausch von # 1 und # 2 kostet einen Punkt, aber der Austausch von # 2 und # 3 kostet nichts. Dies bewirkt, dass Punkte in zwei Bereiche streichen. Punkte, die innerhalb eines Bereichs ausgetauscht werden, fügen der Funktion nicht hinzu.
Wie bewerte ich.Ich habe eine Klasse Rang genannt konstruiert, das dies tut:
Ranks alle Regionen von echten Fehlern einmal.
Für jeden separaten Satz von parametrierten Gewichtungen berechnet es den Testfehler (geschätzt) für diese Region.
Sortiert die Regionen nach diesem Testfehler.
Berechnet den Testrang für jede Region.
Addiert die absolute Differenz der Logs der beiden Ränge und ruft den Wert der Parametrierung auf, daher wird der Wert auf minimiert.
C# -Code. Nachdem ich all das getan habe, brauche ich nur noch einen Weg, Microsoft Solver Foundation einzurichten, um mir die besten Parameter zu finden. Die Syntax hat mich ratlos gemacht. Hier ist mein C# -Code, den ich bisher habe. Darin sehen Sie Kommentare für drei Probleme, die ich identifiziert habe. Vielleicht können Sie noch mehr entdecken! Irgendwelche Ideen, wie das funktioniert?
public void Optimize()
{
// Get the parameters from the GUI and figures out the low and high values for each weight.
ParseParameters();
// Computes the true rank for each region according to true error.
var myRanker = new Rank(ErrorData, false);
// Obtain Microsoft Solver Foundation's core solver object.
var solver = SolverContext.GetContext();
var model = solver.CreateModel();
// Create a delegate that can extract the current value of each solver parameter
// and stuff it in to a double array so we can later use it to call LinearTrial.
Func<Model, double[]> marshalWeights = (Model m) =>
{
var i = 0;
var weights = new double[myRanker.ParameterCount];
foreach (var d in m.Decisions)
{
weights[i] = d.ToDouble();
i++;
}
return weights;
};
// Make a solver decision for each GUI defined parameter.
// Parameters is a Dictionary whose Key is the parameter name, and whose
// value is a Tuple of two doubles, the low and high values for the range.
// All are Real numbers constrained to fall between a defined low and high value.
foreach (var pair in Parameters)
{
// PROBLEM 1! Should I be using Decisions or Parameters here?
var decision = new Decision(Domain.RealRange(ToRational(pair.Value.Item1), ToRational(pair.Value.Item2)), pair.Key);
model.AddDecision(decision);
}
// PROBLEM 2! This calls myRanker.LinearTrial immediately,
// before the Decisions have values. Also, it does not return a Term.
// I want to pass it in a lambda to be evaluated by the solver for each attempted set
// of decision values.
model.AddGoal("Goal", GoalKind.Minimize,
myRanker.LinearTrial(marshalWeights(model), false)
);
// PROBLEM 3! Should I use a directive, like SimplexDirective? What type of solver is best?
var solution = solver.Solve();
var report = solution.GetReport();
foreach (var d in model.Decisions)
{
Debug.WriteLine("Decision " + d.Name + ": " + d.ToDouble());
}
Debug.WriteLine(report);
// Enable/disable buttons.
UpdateButtons();
}
UPDATE: Ich beschloss, für eine andere Bibliothek als Ausweich zu suchen und fand DotNumerics (http://dotnumerics.com/). Ihre Nelder-Mead-Simplex-Solver war leicht zu nennen:
Simplex simplex = new Simplex()
{
MaxFunEvaluations = 20000,
Tolerance = 0.001
};
int numVariables = Parameters.Count();
OptBoundVariable[] variables = new OptBoundVariable[numVariables];
//Constrained Minimization on the intervals specified by the user, initial Guess = 1;
foreach (var x in Parameters.Select((parameter, index) => new { parameter, index }))
{
variables[x.index] = new OptBoundVariable(x.parameter.Key, 1, x.parameter.Value.Item1, x.parameter.Value.Item2);
}
double[] minimum = simplex.ComputeMin(ObjectiveFunction, variables);
Debug.WriteLine("Simplex Method. Constrained Minimization.");
for (int i = 0; i < minimum.Length; i++)
Debug.WriteLine(Parameters[i].Key + " = " + minimum[i].ToString());
Alles, was ich brauchte, war ObjectiveFunction als Methode zur Implementierung einer Doppel Array unter:
private double ObjectiveFunction(double[] weights)
{
return Ranker.LinearTrial(weights, false);
}
Ich habe es nicht gegen echte Daten versucht, aber Ich habe eine Simulation in Excel erstellt, um Testdaten einzurichten und zu bewerten. Die Ergebnisse, die aus ihrem Algorithmus kamen, waren nicht perfekt, aber sie ergaben eine sehr gute Lösung.
Ich fange an zu denken, die Menschen One-Click-Alternative zu "TLDNR" ist UpVote. Ich kann diese Theorie testen, indem ich eine Frage stelle, die unglaublich komplex klingt und einige hochentwickelte Buzz-Wörter und einen Spritzer Code-Schnipsel fallen lässt. Äh, vergiss es, ich werde stattdessen nur diesen aufwerten. :-) – kingdango