Angenommen, Sie möchten einen Bereich [min,max]
auf skalieren [a,b]
. Sie suchen eine (kontinuierliche) Funktion, die erfüllt
f(min) = a
f(max) = b
In Ihrem Fall a
wäre 1 und b
30, aber beginnen wir mit etwas Einfacherem und versuchen, [min,max]
den Bereich abzubilden [0,1]
.
Das Setzen min
einer Funktion und das Herausholen von 0 könnte mit erreicht werden
f(x) = x - min ===> f(min) = min - min = 0
Das ist fast das, was wir wollen. Aber das Einfügen max
würde uns geben, max - min
wann wir tatsächlich wollen 1. Also müssen wir es skalieren:
x - min max - min
f(x) = --------- ===> f(min) = 0; f(max) = --------- = 1
max - min max - min
Welches ist, was wir wollen. Wir müssen also eine Übersetzung und eine Skalierung durchführen. Wenn wir stattdessen willkürliche Werte von a
und erhalten wollen b
, brauchen wir etwas Komplizierteres:
(b-a)(x - min)
f(x) = -------------- + a
max - min
Sie können sicherstellen , dass bei der Umsetzung min
für x
jetzt gibt a
, und setzen in max
gibt b
.
Möglicherweise stellen Sie auch fest, dass dies (b-a)/(max-min)
ein Skalierungsfaktor zwischen der Größe des neuen Bereichs und der Größe des ursprünglichen Bereichs ist. Wir übersetzen also wirklich zuerst, x
indem wir -min
es auf den richtigen Faktor skalieren und dann wieder auf den neuen Mindestwert von übersetzen a
.
Hoffe das hilft.
max != min
ansonsten sind die Funktionsergebnisse unbestimmt :)min
es negativ undmax
positiv ist, oder müssen beide positiv sein?Hier ist etwas JavaScript zum einfachen Kopieren und Einfügen (dies ist die Antwort von irritate):
Wird so angewendet und skaliert den Bereich 10-50 auf einen Bereich zwischen 0-100.
Bearbeiten:
Ich weiß, dass ich das vor langer Zeit beantwortet habe, aber hier ist eine sauberere Funktion, die ich jetzt benutze:
So angewendet:
quelle
[1, 1, 1]
,[100, 100, 100]
oder sogar[50.5, 50.5, 50.5]
. Sie könnten in den Fall setzen:if (max-min == 0) return this.map(num => (scaledMin+scaledMax)/2);
Der Einfachheit halber ist hier der Irritate-Algorithmus in einer Java-Form. Fügen Sie nach Bedarf Fehlerprüfung, Ausnahmebehandlung und Optimierung hinzu.
Prüfer:
quelle
So verstehe ich es:
Wie viel Prozent
x
liegen in einem Bereich ?Nehmen wir an, Sie haben einen Bereich von
0
bis100
. In welchem "Prozent" aus diesem Bereich liegt eine beliebige Zahl aus diesem Bereich? Dies sollte ziemlich einfach sein,0
wäre0%
,50
wäre50%
und100
wäre100%
.Nun, was ist, wenn Ihr Angebot war
20
zu100
? Wir können nicht dieselbe Logik wie oben anwenden (durch 100 teilen), weil:gibt uns nicht
0
(20
sollte0%
jetzt sein). Dies sollte einfach zu beheben sein, wir müssen nur den Zähler0
für den Fall von machen20
. Wir können das tun, indem wir subtrahieren:Dies funktioniert jedoch nicht
100
mehr, weil:gibt uns nicht
100%
. Auch dies können wir beheben, indem wir vom Nenner abziehen:Eine allgemeinere Gleichung, um herauszufinden, wie viel Prozent
x
in einem Bereich liegen, wäre:Skalieren Sie den Bereich auf einen anderen Bereich
Nachdem wir nun wissen, wie viel Prozent einer Zahl in einem Bereich liegen, können wir sie anwenden, um die Zahl einem anderen Bereich zuzuordnen. Lassen Sie uns ein Beispiel durchgehen.
Wenn wir eine Nummer im alten Bereich haben, welche wäre die Nummer im neuen Bereich? Nehmen wir an, die Nummer ist
400
. Stellen Sie zunächst fest, wie viel Prozent400
im alten Bereich liegen. Wir können unsere obige Gleichung anwenden.Liegt also
400
im25%
alten Bereich. Wir müssen nur herausfinden, welche Nummer25%
aus dem neuen Bereich stammt. Überlegen Sie, was50%
von[0, 20]
ist. Es wäre10
richtig? Wie sind Sie zu dieser Antwort gekommen? Nun, wir können einfach tun:Aber was ist mit von
[10, 20]
? Wir müssen10
jetzt alles verschieben . z.B:Eine allgemeinere Formel wäre:
Zum Original Beispiel dafür , was
25%
der[10, 20]
ist:Also,
400
in der Reichweite[200, 1000]
würde12.5
in der Reichweite abgebildet[10, 20]
TLDR
So ordnen Sie den
x
alten Bereich dem neuen Bereich zu:quelle
Ich bin auf diese Lösung gestoßen, aber das passt nicht wirklich zu meinen Bedürfnissen. Also habe ich ein bisschen im d3-Quellcode gegraben. Ich persönlich würde empfehlen, es so zu machen, wie es d3.scale tut.
Hier skalieren Sie die Domain auf den Bereich. Der Vorteil ist, dass Sie Zeichen in Ihren Zielbereich drehen können. Dies ist nützlich, da die y-Achse auf einem Computerbildschirm von oben nach unten zeigt, sodass große Werte ein kleines y haben.
Und hier ist der Test, bei dem Sie sehen können, was ich meine
quelle
Ich habe die Antwort von Irritate genommen und überarbeitet, um die Rechenschritte für nachfolgende Berechnungen zu minimieren, indem ich sie in die wenigsten Konstanten zerlege. Die Motivation besteht darin, einem Scaler zu ermöglichen, an einem Datensatz zu trainieren und dann mit neuen Daten (für ein ML-Algo) ausgeführt zu werden. Tatsächlich ähnelt es SciKits Vorverarbeitung von MinMaxScaler für Python in der Verwendung.
Somit wird
x' = (b-a)(x-min)/(max-min) + a
(wobei b! = A),x' = x(b-a)/(max-min) + min(-b+a)/(max-min) + a
was in der Form auf zwei Konstanten reduziert werden kannx' = x*Part1 + Part2
.Hier ist eine C # -Implementierung mit zwei Konstruktoren: einer zum Trainieren und einer zum erneuten Laden einer trainierten Instanz (z. B. zur Unterstützung der Persistenz).
quelle
Basierend auf der Antwort von Charles Clayton habe ich einige JSDoc- und ES6-Optimierungen aufgenommen und Vorschläge aus den Kommentaren in die ursprüngliche Antwort aufgenommen.
quelle