Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Wie tendenzielle Entwicklung aus mehreren Zahlen herleiten?


galagher - Mo 21.01.08 19:31
Titel: Wie tendenzielle Entwicklung aus mehreren Zahlen herleiten?
Hallo!

Wie kann man aus einer "Liste" von Zahlen eine tendenzielle Entwicklung, ausgehend von .Line[0] bis .Line[9], ermitteln, Wobei mit Entwicklung entweder eine Verbesserung, eine Verschlechterung oder eine gleichbleibende Leistung gemeint ist?

Je höher die Zahlen, desto besser. Es sind immer 10 Zahlen, wobei 250 die beste erreichbare Zahl, 0 die schlechteste ist. So könnte die Liste aussehen:

225
250
100
250
225
200
125
25
0
24

Also so eine Art Statistik - wie gesagt, eine Tendenz besser/schlechter/gleich.


Moderiert von user profile iconChristian S.: Topic aus Sonstiges (Delphi) verschoben am Mo 21.01.2008 um 18:39


Jann1k - Mo 21.01.08 21:00

Ich würd sagen einfach den Durchschnitt der ersten 5 Zahlen mit em Durchschnitt der letten 5 vergleichen.


alzaimar - Mo 21.01.08 21:06

Hi galagheer,

Wie wäre es mit einer linearen Regression? Ist die Steigung negativ, wirds besser, sonst nicht.


galagher - Di 22.01.08 18:06

Erstmal danke für die Antworten!

user profile iconJann1k hat folgendes geschrieben:
Ich würd sagen einfach den Durchschnitt der ersten 5 Zahlen mit em Durchschnitt der letten 5 vergleichen.

Ist aber doch eher ungenau, oder? Ich meine, im Extremfall könnte unter den ersten 5 Zahlen 2x 125 und 3x 0 vorkommen, während in der 2. Zahlengruppe 1x 250 und 4x 0 vorkommt. 2x 125 ist zwar rechnerisch soviel wie 1x 250, muss aber dennoch als schlechtere Leistung bewertet werden, weil eben 250 nicht erreicht wurde.

user profile iconalzaimar hat folgendes geschrieben:
Wie wäre es mit einer linearen Regression? Ist die Steigung negativ, wirds besser, sonst nicht.

Was versteht man darunter und wie setzt man es um?


Jann1k - Di 22.01.08 21:03

Zitat:

Antworten mit Zitat
BeitragVerfasst am: Di 22.01.08 17:06 Titel:
Erstmal danke für die Antworten!

Jann1k hat folgendes geschrieben:
Ich würd sagen einfach den Durchschnitt der ersten 5 Zahlen mit em Durchschnitt der letten 5 vergleichen.

Ist aber doch eher ungenau, oder? Ich meine, im Extremfall könnte unter den ersten 5 Zahlen 2x 125 und 3x 0 vorkommen, während in der 2. Zahlengruppe 1x 250 und 4x 0 vorkommt. 2x 125 ist zwar rechnerisch soviel wie 1x 250, muss aber dennoch als schlechtere Leistung bewertet werden, weil eben 250 nicht erreicht wurde.


Berechne den Durchschnitt der Quadrate der Zahlen, dann passt auch sowas.


alzaimar - Di 22.01.08 22:45

user profile icongalagher hat folgendes geschrieben:
user profile iconalzaimar hat folgendes geschrieben:
Wie wäre es mit einer linearen Regression? Ist die Steigung negativ, wirds besser, sonst nicht.

Was versteht man darunter und wie setzt man es um?

Wie wäre es mit googeln? Oder mal bei Wikipedia reinschauen?


galagher - Di 22.01.08 23:01

user profile iconalzaimar hat folgendes geschrieben:
Wie wäre es mit googeln? Oder mal bei Wikipedia reinschauen?


Delphi-Quelltext
1:
2:
Google := True;  //Ohne brauchbares, d.h., verständliches Ergebnis
Wikepedia := False;  //hole ich aber morgen nach!


alzaimar - Di 22.01.08 23:33

user profile icongalagher hat folgendes geschrieben:

Delphi-Quelltext
1:
Google := True;  //Ohne brauchbares, d.h., verständliches Ergebnis                    


http://members.fortunecity.com/schutzenberger/download/de.html
http://www.delphipraxis.net/topic123901.html
http://www.unilim.fr/pages_perso/jean.debord/tpmath/dmath.zip
http://www.michael-grassmann.de/page3.htm
:roll:


Allesquarks - Mi 23.01.08 01:55

Hm warum es Regression heißt frag ich mich auch. Aber linear heißt ganz simpel du legst ne Gerade durch. Das kann man einmal Grafisch machen, dilettantisch (schlecht aber wie es die meisten machen würden), oder richtig. Die Formel dafür findest du häufig und überall. Der Grundgedanke bei denen ist (als Anstoß).

Die Gerade soll so nah wie möglich an allen Punkten sein. Also könnte man die Abstände der Punkte zur Geraden als Entscheidungskriterium nehmen. Allerdings braucht man dafür den Betrag und der ist zumindest in Formeln extrem unhandlich und man wollte sowas auch schon machen bevor es Computer gab. Deshalb verwendet man eigentlich immer das Kriterium der Abstandsquadrate, weil das Quadrat einer Zahl ja immer positiv ist.
Also ist die Gerade f(x)=mx+c die beste, für die die Summe der Abstandsquadrate minimal ist.

Das ganze ist natürlich nur dann sinnvoll wenn die Daten überhaupt den Trend einer Geraden haben. Das heißt ob es größer wird oder kleiner beantwortet dir dieses Verfahren mit ja und nein (Steigung größer kleiner Null). Aber wie schnell es größer wird also die Größe der Steigung ist nur aussagefähig, wenn der Trend linear ist. Das heißt bei Quadratischem Wachstum ist der Wert absolut daneben.


Hidden - Mi 23.01.08 09:53
Titel: Regression
Grafik:Da es eine Entwicklung seien soll, sollte es schon (wenns nicht besonders einfach sein soll) keine Gerade, sondern wohl eher eine Ausgleichskurve sein.
Übliche statistische Mittel verwenden, Extremwerte schwächer berücksichtigen, fertig.

Formel: Wenn du für ein Programm eine einfache Formel brauchst, um zur Laufzeit die Entwicklung zu bewerten - und keine Grafische Darstellung - würde ich abhänging vom Anwendungszweck eventuell neuere Werte stärker(quadratisch/exponentiell) berücksichtigen.
Man kann ja schlecht sagen: "Deutschland geht es gut" wenn die ersten 90 Jahre in der Messung gute Jahre waren und die letzten 10 schlecht^^


alzaimar - Mi 23.01.08 09:59
Titel: Re: Regression
user profile iconHidden hat folgendes geschrieben:

Man kann ja schlecht sagen: "Deutschland geht es gut" wenn die ersten 90 Jahre in der Messung gute Jahre waren und die letzten 10 schlecht^^

Politiker schon.

Eine (lineare) Regression zeigt den Trend. Wer will, kann die Punkt ha gewichten. Aber im Prinzip ist es natürlich nicht soooo einfach.


galagher - Mi 23.01.08 18:26
Titel: Re: Regression
user profile iconalzaimar hat folgendes geschrieben:
user profile iconHidden hat folgendes geschrieben:

Man kann ja schlecht sagen: "Deutschland geht es gut" wenn die ersten 90 Jahre in der Messung gute Jahre waren und die letzten 10 schlecht^^

Politiker schon.

Ok, aus 90 machen wir 9 und aus 10 1: Für meine Zwecke wäre das in der Tat eine Verbesserung, denn 1 schlechte Leistung macht 9 gute nicht zunichte. Erst wenn's mit den Werten weiter bergab geht, folgt zunächst "gleichbleibend" und dann "verschlechtert".
@user profile iconalzaimar": LÜGE ON: Ich bin ein Mathe-As, ich liebe Mathe, und Formeln machen mich echt an! War immer schon so! :mrgreen: LÜGE OFF.

Klappt so auch sehr gut, muss sich nur im Echtbetrieb noch beweisen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
   a := 0;  {bad}
   b := 0;  {naja}
   c := 0;  {good}

   for i := 0 to L.Count-1 do
   begin
    if (StrToInt(L[i]) < 100then Inc(a)
    else
    if (StrToInt(L[i]) < 125then Inc(b)
    else                           Inc(c);
   end;

   L4.Caption := 'Gleichbleibende Leistung';

   if (a+b > c) and (a > b+c) then
    L4.Caption := 'Verschlechtere Leistung'
   else
   if (a+b < c) and (a < b+c) then
    L4.Caption := 'Verbesserte Leistung';


//Edit:
Der Link in http://members.fortunecity.com/schutzenberger/download/de.html funktioniert nicht:
http://www.fortunecity.com/banners/interstitial.html?http://members.fortunecity.com/schutzenberger/download/ConnectFour3D.zip


alzaimar - Mi 23.01.08 21:41
Titel: Re: Regression
user profile icongalagher hat folgendes geschrieben:

@user profile iconalzaimar": LÜGE ON: Ich bin ein Mathe-As, ich liebe Mathe, und Formeln machen mich echt an! War immer schon so! :mrgreen: LÜGE OFF.

Wer so dezent lügt ....
Die Links funktionieren eigentlich, aber egal. Hier deine Routine zur ermittlung der linearen Koeffizienten (f(x) = Ax+B) sowie des Korrelationskoeffizienten R.

A ist die Steigung (>0 steigend, <0 fallend), B der Versatz der Geraden auf der Y-Achse bei X=0. R ist der Korrelationskoeffizient. Wenn R=1, liegen alle Punkte auf der Gerade, bei R=0 ist kein linearer Zusammenhang.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
  Procedure LinearRegression(x, y: Array Of Double; Var a, b, r: Double);
  Var
    i,n: Integer;
    xq, yq,
      sxy, sx2, sy2: Extended;

  Begin
    n := Length(x);
    xq := 0;
    yq := 0;
    For i := 0 To n - 1 Do Begin
      xq := xq + x[i];
      yq := yq + y[i];
    End;
    xq := xq / n;
    yq := yq / n;
    sxy := 0;
    sx2 := 0;
    sy2 := 0;
    For i := 0 To n - 1 Do Begin
      sxy := sxy + (x[i] - xq) * (y[i] - yq);
      sx2 := sx2 + sqr(x[i] - xq);
      sy2 := sy2 + sqr(y[i] - yq);
    End;
    a := sxy / sx2;
    b := yq - a * xq;
    r := sqr((1/n)*sxy / (sqrt (sx2/n)*sqrt (sy2/n)));
  End;

X wäre hier die Punktnummer (1..10) und Y deine Werte.


galagher - Mi 23.01.08 22:38
Titel: Re: Regression
user profile iconalzaimar hat folgendes geschrieben:
Die Links funktionieren eigentlich, aber egal.

Ich komme beim Anklicken von [url]http://www.fortunecity.com/...ad/ConnectFour3D.zip[/url] auf eine völlig leere Seite!

user profile iconalzaimar hat folgendes geschrieben:
Hier deine Routine zur ermittlung der linearen Koeffizienten (f(x) = Ax+B) sowie des Korrelationskoeffizienten R.

A ist die Steigung (>0 steigend, <0 fallend), B der Versatz der Geraden auf der Y-Achse bei X=0. R ist der Korrelationskoeffizient. Wenn R=1, liegen alle Punkte auf der Gerade, bei R=0 ist kein linearer Zusammenhang.


:gruebel: :nixweiss: :?!?:

Ich habe also 10 Zahlen und eine Prozedur LinearRegression, die erwartet 2 Arrays und 3 Doubles. Woraus sollen denn die Arrays und die Doubles bestehen, wenn ich nur 10 Integers habe?

user profile iconalzaimar hat folgendes geschrieben:
X wäre hier die Punktnummer (1..10) und Y deine Werte.

Ok, Y sind also meine Werte - die 10 Integers. Was aber ist dann X? Es gibt nur 10 Integers, das sind die Werte.

Sorry, aber würde die Funktion (die nebenbei - für mich - verwirrend ist!) einfach die 10 Zahlen verlangen, dann würde mir das ja einleuchten, aber so... Was ist x, y: Array Of Double und was ist Var a, b, r: Double?

Mit anderen Worten: nachdem ich meine 10 Zahlen ermittelt habe, was mache ich mit denen mit deiner Prozedur?


alzaimar - Do 24.01.08 00:07

Hi galagher,

steht doch da:

Y-Werte, deine 'Integer'
X-Werte die Zahlen 1 bis 10 (ich hab 0 bis 9 genommen, Du kannst auch 10,20,30,40 nehen, egal)

A,B und R werden BERECHNET

Nimm Dir mal ein Blatt Papier.

X-Achse 0..9, Y-Achse 0..250
So,
bei X=0, Y=225 den ersten Wert,
bei x=1, Y=250 den zweiten Wert,
bei X=2, Y=100 den dritten Wert,
...
bei X=9, Y=24 den zehnten Wert aufzeichnen. Da hätten wir dann eine 2D-Punktegrafik.
Durch die wollen wir eine Ausgleichsgerade von links nach rechts zeichnen. Dazu dient meine Routine. Die Geradengleichung solltest Du schon drauf haben (Y=A*X+B). Wenn nicht, dann lies nach.

Du berechnest Dir A und B (so ca. -26 und 260 oder so). Dann:
Der linke Punkt der Ausgleichsgeraden liegt bei : Y=f(0) = -26*0 + 260, also bei (0,260)
Der rechte Punkt der Ausgleichsgeraden liegt bei Y=f(9)= -26*9 + 260, also bei (9,26)

Und das R gibt eben an ... hab ich ja schon geschrieben.

Wenn Du z.B. für die X- und Y-Koordinaten sowas eingibts X= (1,2,3,4,5), Y=(1,2,3,4,5). Dann kommt für A=1 und B=0 sowie R=1 heraus.
Die Geradengleichung ist also f(x)=1*x+0 (prüf mal nach) und R=1, die gerade trifft also alle Punkte!

Spiel doch mal damit ein wenig rum.


galagher - Do 24.01.08 19:01

X und Y ist klar, A,B,R mittlerweile auch. Woran's scheitert, ist jetzt bloss noch der praktische Einsatz!
Das führt zu einem "Zugriffsfehler bei Adresse [...]":

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var
  i: Integer;
  xx: Array [0..9of Double;  //Ist ja nun 0-9  -  xx[0] = 0, xx[1] = 1  -  oder?)
  yy: Array of Double;
  aa, bb, cc: Double;
begin
//...
//Und in dieser for-Schleife kracht's auch schon:
 for i := 0 to 9 do  //L ist eine StringList und, nein, die ist hier NICHT leer!
  yy[i] := StrToFloat(L[i]);  //Irgendwie müssen die Zahlen ins Array yy ja reinkommen!

 LinearRegression(xx, yy, aa, bb, cc);
 caption:=floattostr(aa);  //wollte nur mal sehen, was aa so ist

user profile iconalzaimar hat folgendes geschrieben:
Spiel doch mal damit ein wenig rum.

Ich habe keinen Schimmer, wie...


delfiphan - Do 24.01.08 19:32
Titel: Re: Regression
user profile icongalagher hat folgendes geschrieben:
Was aber ist dann X? Es gibt nur 10 Integers, das sind die Werte.

user profile icongalagher hat folgendes geschrieben:
tendenzielle Entwicklung

Du sprichst von einer tendenziellen Entwicklung. Also z.B. tendenzielle Entwicklung in der Zeit. Dann wäre X die Zeit. Wenn der zeitliche (oder örtliche) Abstand konstant ist, kannst du X einfach durchnummerieren.

user profile icongalagher hat folgendes geschrieben:
X und Y ist klar, A,B,R mittlerweile auch. Woran's scheitert, ist jetzt bloss noch der praktische Einsatz!
Das führt zu einem "Zugriffsfehler bei Adresse [...]":

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var
  i: Integer;
  xx: Array [0..9of Double;  //Ist ja nun 0-9  -  xx[0] = 0, xx[1] = 1  -  oder? nein.)
  yy: Array of Double;
  aa, bb, cc: Double;
begin
//...
//Und in dieser for-Schleife kracht's auch schon:
 for i := 0 to 9 do  //L ist eine StringList und, nein, die ist hier NICHT leer!
  yy[i] := StrToFloat(L[i]);  //Irgendwie müssen die Zahlen ins Array yy ja reinkommen!

 LinearRegression(xx, yy, aa, bb, cc);
 caption:=floattostr(aa);  //wollte nur mal sehen, was aa so ist


Die Werte für xx sind bei der Deklaration nicht automatisch gesetzt. Am einfachsten erweiterst du einfach deine for-Schleife und setzst xx[i] := i, falls eine Durchnummerierung in Frage kommt (siehe oben)


galagher - Do 24.01.08 19:45
Titel: Re: Regression
user profile icondelfiphan hat folgendes geschrieben:
Die Werte für xx sind bei der Deklaration nicht automatisch gesetzt. Am einfachsten erweiterst du einfach deine for-Schleife und setzst xx[i] := i, falls eine Durchnummerierung in Frage kommt (siehe oben)

Also so:

Delphi-Quelltext
1:
 for i := 0 to 9 do xx[i] := i;                    

Nützt aber auch nichts, der Zugriffsfehler bleibt.
Andere Frage: Was ist an meiner Lösung (siehe oben) so schlecht? Sie ist jedenfalls wesentlich einfacher.


Hidden - Do 24.01.08 20:19
Titel: Re: Regression
user profile icongalagher hat folgendes geschrieben:


Delphi-Quelltext
1:
 for i := 0 to 9 do xx[i] := i;                    


wohl eher

Delphi-Quelltext
1:
2:
for i := 0 to high(meinArray) do  //immer schön variabel bleiben^^
  xx[i] := i;


Ich kann zwar wie so viele Menschen auch nicht hellsehen aber ich tät' sagen du musst die Werte erst in ein Array schreiben

Delphi-Quelltext
1:
2:
3:
4:
5:
meinArray[0] := 56;
meinArray[1] := 35;
{...}
{und dann das array einlesen}
myProcedure(meinArray);


diese Form wird also leider nicht unterstützt:
myProc([56;35]) oder so ähnlich, meines Wissens kann man das array an dieser Stelle leider nicht einfach einzeln einlesen.
Sollte ich mich irren, fände ich das toll, da ich schon immer eine unbekannte Anzahl an Werten gleichen Datentyps einlesen wollte ohne eine dieser :puke: Möglichleiten zu nutzen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
myProc(pZahl1: Double);overload;
myProc(pZahl1,pZahl2: Double);overload;
myProc(pZahl1,pZahl2,pZahl3: Double);overload;
{...}

meinArray[0] := ...;
meinArray[1] := ...;
meinArray[2] := ...;
{...}
myPorc(meinArray);


Das gleiche gilt für sets und records...


Woran es auch liegen könnte ist, dass beim Einlesen ja steht(stehen muss) myPorc(X: TIntegerArray(*selbstdefinierter typ*)) statt einfach myProc(X: array of Integer).
Dann musst du beim deklarieren deiner Arrayvariable auch diesen Typ verwenden.

Edit: Wozu eig. das 2. Array, die Werte sind doch identisch mit dem Indexwert des ersten... :P


delfiphan - Do 24.01.08 22:44
Titel: Re: Regression
user profile icongalagher hat folgendes geschrieben:
user profile icondelfiphan hat folgendes geschrieben:
Die Werte für xx sind bei der Deklaration nicht automatisch gesetzt. Am einfachsten erweiterst du einfach deine for-Schleife und setzst xx[i] := i, falls eine Durchnummerierung in Frage kommt (siehe oben)

Also so:

Delphi-Quelltext
1:
 for i := 0 to 9 do xx[i] := i;                    

Nützt aber auch nichts, der Zugriffsfehler bleibt.
Andere Frage: Was ist an meiner Lösung (siehe oben) so schlecht? Sie ist jedenfalls wesentlich einfacher.

yy musst du gleich deklarieren wie xx, mit den eckigen Klammern und dem Definitionsbereich.


delfiphan - Do 24.01.08 23:44


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
function Tendenz(const x: array of Double): Double;
var
  i, n: Integer;
  a, b: Double;
begin
  n := length(x);
  a := 0;
  b := 0;
  for i := 0 to n-1 do
  begin
    a := a + x[i];
    b := b + i*x[i];
  end;
  Result := 2*arctan(6*(2*b-a*(n-1))/(sqr(n)*n-n))/pi;
end;

Rückgabewert ist zwischen -1 und 1:
< 0  Tendenz fallend
= 0  Konstant
> 0  Tendenz steigend

Macht dasselbe wie der Code von alzaimar: Berechnet Least-Squares Lösung der linearen Regression mit implizit x[i]=i. Die Steigung wird noch in einen Winkel umgewandelt und in den Bereich [-1..1] gedrückt.

Mit dem Vorzeichen kannst du also herausfinden, ob die Tendenz zu oder abnehmend ist. Die Werte an sich haben in diesem Fall keine reale Bedeutung. Sie können lediglich benützt werden, um verschiedene Tendenz-Werte miteinander zu vergleichen.

Wenn du Steigungen als Rückgabe willst, nimmst du nur den Ausdruck in arctan. Da x[i]=i angenommen wird, haben die Werte weiterhin keine reale Bedeutung, jedoch bedeutet dann ein doppelt so hoher Wert ein doppelt so hohe Zunahme.

x[] ist in deinem Code L[].


galagher - Sa 26.01.08 10:45

user profile icondelfiphan hat folgendes geschrieben:
Mit dem Vorzeichen kannst du also herausfinden, ob die Tendenz zu oder abnehmend ist. Die Werte an sich haben in diesem Fall keine reale Bedeutung. Sie können lediglich benützt werden, um verschiedene Tendenz-Werte miteinander zu vergleichen.

Klappt vorzüglich und ist genauer als meine simple Lösung, aber ich muss, um die Werte miteinander vergleichen zu können, SimpleRoundTo verwenden, weil ohne zwei völlig identische Doubles im Vergleich als grösser bzw. kleiner erkannt werden. Liegt das am "E", mit dem die Zahlen "verkürzt" werden?

Ich mache das so: der aktuelle Wert wird mit deiner Funktion berechnet, der Vergleichswert wird aus einer Datei ausgelesen. Beim Speichern wird der aktuell errechnete Wert in der Datei hinterlegt.

Danke!