![]() |
Prozentuale Ähnlichkeit (Mustererkennung)
So ich habe wieder ein Problem, mit dem ich mich schon länger beschäftige.
Gegeben ist ein Muster: (erste Zeile die Feldnamen)
Delphi-Quellcode:
In der Datei befinden sich weitere, sagen wir mal 1000 Zeilen mit solchen unterschiedlichen Zahlen.
Sta Proz GL1 GL2 Gl3 GL4
2 3,5 0,23 1,2 0,6 0,7 0 -0,5 0,24 1,3 0,7 0,73 1 1,2 0,25 1,4 0,8 0,85 Ich möchte wissen, a) wieviele gleiche Muster vorkommen - das ist kein Problem aber b) welche sind von 100% bis 90% ähnlich. Das ist aber insofern problematisch, da Sta 0,1,2 annehmen kann. Wenn sich dieser Wert verändert, habe ich ein Problem mit der Ähnlichkeit: Beispiel: 2 3,5 0,23 1,2 0,6 0,7 (Muster) 0 3,5 0,24 1,2 0,6 0,7 (Gefundenes oder besser zu prüfendes Muster) Wenn sich ein Wert von 0,23 auf 0,24 im Suchmuster in der ersten Zeile befindet, wird das das Muster als ähnlich erkannt. Ist jedoch unter Sta die 2 verändert auf 0, so habe ich eine große prozentuale Abweichung. Daher meine Frage, bevor ich überhaupt anfange das Programm zu schreiben: Wie löse ich das Problem? Muss ich eine Gewichtsmatrix über die Zahlen legen? Wie kann ich feststellen, dass die obigen 3 Datenzeilen mit drei anderen Datenzeilen in der Datei ähnlich sind. :gruebel: Hat jemand einen Link, eine Idee, oder einen Ansatz? |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Es wäre wohl Sinnvoll hier eine Metrik zu definieren, mit welcher du ein Maß für die Unterschiede der einzelnen Vektoren hast ( ich nenne deine Zeilen jetzt einfach mal so).
Zum Beispiel könntest du die Euklid Norm/ euklidischen Abstand nehmen. Eventuell könntest du auch noch zusätzliche gewichte einführen. |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Solange Du nicht den Begriff "Ähnlich" für die Parameter einzeln quantifizieren kannst, ist die Sache wohl kaum lösbar.
Klaus-Peter |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Vergleichst Du die Datensätze durch einen Text-Vergleich?
Das wäre sicher nicht sinnvoll. Da Du hier mit Zahlen arbeitest, solltest Du die Differenzen für jedes Feld zwischen zwei Datensätzen ermitteln. Die Differenz kannst Du dann hernehmen, um die Ähnlichkeit zu ermitteln. Wir können ja hier nicht einschätzen, ob 0,2 Differenz noch einen ähnliche Werte beinhalten. Dann ermittelst Du den Durchschnitt über alle Feld-Ähnlichkeiten und erhälst ein brauchbares Ergebnis. Stahli |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Danke für Eure Antworten, ich glaube ich erstmal einen Ansatz schreiben und dann hier als Source zur Diskussion reinstellen,
dann versteht man auch besser, wass ich meine. @Stahli Nein, kein Stringvergleich. Es sind die Floats wie oben. So weit, denke ich, ist mein Ansatz auch. Ich habe da noch irgendwie einen Denkfehler: Die Differenz von 1 auf 2 ist 100%, wobei bei den anderen Werten "bessere" Werte kommen. Daher auch die Überlegung mit einer Gewichtung. Aber ich glaube, ich bin noch auf dem Holzweg. Genau genommen kann es sein, das die Bedingungen unter Sta zu 100% zutreffend sein müssen, weil sonst zu viele Ähnlichkeiten in den 1000 Datensätzen vorhanden sind. Vielen Dank für Eure Mühe vorerst und gute Nacht! |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Delphi-Quellcode:
Ähnlichkeit durchschnittlich: 95,67%
Sta 1:1 -> Diff=0 -> Ähnlichkeit=100%
Proz 3,5:-0,5 -> Diff=-4 -> Ähnlichkeit=80% Gl1 0,23:0,24 -> Diff=0,01 -> Ähnlichkeit=99% Gl2 1,2:1,3 -> Diff=0,1 -> Ähnlichkeit=98% Gl3 0,6:0,7 -> Diff=0,01 -> Ähnlichkeit=98% Gl4 0,7:0,73 -> Diff=0,03 -> Ähnlichkeit=99% Bei Differenz=0 ist die Ähnlichkeit pro Feld 100%. Andernfalls musst Du einen Prozentwert pro Feld selbst festlegen (Z.B. Abhängig von den möglichen Maximal- und Minimalwerten pro Feld). Du kannst natürlich die Bewertungen der anderen Felder auch wiederum von der Ähnlichkeit von Sta abhängig machen... Stahli |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Liste der Anhänge anzeigen (Anzahl: 1)
So ich habe mal ein schmutziges schnelles Programm geschrieben:
Ich habe 1000 Zeilen in der Daten.txt (liegt bei) Damit es nicht zu kompliziert wird, habe ich mich auf die erste Zeile in der "Datenbank" beschränkt, die auf Ähnlichkeit mit den restlichen 999 Zeilen zu prüfen ist. Wir sehen ab der Zeile 2 bis 1000 nach, wie ähnlich sich die Zeilen sind. Ich verwende folgende Formel, Ergebnis[x,i]:=(daten[x,i]/daten[1,i])/5; wobei x von 2 nach 1000 alle Zeilen durchläuft i von 2 nach 6 alle Spalten, bis auf die erste Spalte, durchlaufen werden. (Mit der ersten Spalte habe ich noch ein Problem, sie verfälscht mein Ergebnis.) Die Ergebnisse speichere ich in das Array Ergebnis[1..1000,1..7], wobei die ich die Spaltenergebnisse in Ergebnis[1..1000,2..6] und die Summe/5 (5=Anzahl der Spalten) in Position 7 (Ergebnis[1..1000,7]) speichere. Vorgehensweise: Daten einlesen. Alle Nullen in 0.01 ändern, weil ich ein Problem mit Division mit 0 bekomme. Negative Ergebnisse unserer Berechnung werden in positive Zahlen mit *-1 überführt. Einzelergebnisse von Spalte 2 bis 6 in 7 speichern. Ausgabe der Ergebnisse beschränken auf Zahlen kleiner als 1 mit: if (ergebnis[x,7] < 1) then ...
Delphi-Quellcode:
Ach ja, Datensatz 94 und 905 entspricht fast dem ersten Datensatz.
program ReadDaten;
{$APPTYPE CONSOLE} uses math; var f:textfile; Feldnamen:string; Daten:Array[1..1000,1..6] of real; Ergebnis:Array[1..1000,1..7] of real; x,i:integer; h:real; AnzahlZeilen:integer; function Runden(x: Extended; Stellen: Byte): Extended; begin Result:= Round(x * IntPower(10, Stellen))/IntPower(10, Stellen); end; begin // DATEN in Array Daten einlese assignfile(f,'C:\Daten.txt'); Reset(f); readln(f,Feldnamen); for X:=1 to 1000 do begin for i:=1 to 6 do begin read(f,daten[x,i]); end; end; closefile(f); //Wir stellen sicher, dass keine 0 vorkommt und ersetzten diese durch 0.01; for x:=1 to 1000 do begin for i:=1 to 6 do if daten[x,i]=0 then daten[x,i]:=0.01; end; // Wir gehen alle Zeilen und Spalten in Muster durch und speichern das Ergebnis: for x:=2 to 1000 do begin for i:=2 to 6 do begin // Wir dividieren durch die Anzahl der Daten, hier 5: Ergebnis[x,i]:=(daten[x,i]/daten[1,i])/5; //<Negative Ergebnisse bringen nicht das resultat, daher *-1 if Ergebnis[x,i]< 0 then ergebnis[x,i]:=ergebnis[x,i]*-1; //Ursprünglich: { Ergebnis[x,i]:=(daten[x,i]/daten[1,i]); } end;//i.. //Ergebnis von Spalte 2 bis 6 in 7 speichern: ergebnis[x,7]:=0; for I:=2 to 6 do ergebnis[x,7]:=ergebnis[x,7]+ergebnis[x,i]; // Die Ausgabe wird beschränkt: if (ergebnis[x,7] < 1) then begin writeln('Datensatz: ',x); for i:=2 to 6 do write(daten[1,i]:2:2,' ');writeln; for i:=2 to 6 do write(daten[x,i]:2:2,' ');writeln; for i:=2 to 6 do write(ergebnis[x,i]:2:2,' ');writeln; writeln('Ergebnis: ',ergebnis[x,7]:2:2);writeln; writeln('Taste'); readln; end; end;//x.. writeln('Ende - ENTER'); readln; end. Wie könnte man es besser lösen? :gruebel: Nachtrag: Die Datei Daten.txt bitte als C:\daten.txt speichern. Ich habe keine Fehlerabfragen zu besseren Übersichtlichkeit eingebaut. |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
So, ich habe eine Ergänzung:
Wenn von die 5 Feldern ein Feld ein "Ausreisser" ist, dann prüfe, ob die Summe der restlichen 4 kleiner 1 ist. Ist das der Fall, dann wird die Zeile/Datensatz als ähnlich angezeigt. Ich verwende hierfür die Abfrage, an welcher Position der Aussreißer steht und weise den Index der Varibalen p zu und lösche dann das Ergebnis[x,p]. Die neue Summe zeigt mir dann, ob der Datensatz, bis auf den Ausreißer ähnlich meiner ersten Zeile in der Datenbank ist.
Delphi-Quellcode:
Der neue vollständige Code liegt bei. Bitte Daten.txt auf C:\ speichern.
// Wir prüfen, einen Aussreißer im Array Ergbnis[x,1.6] um zu sehen,
// ob 4 von 5 Werten unsere Bedingungen erfüllen. if ergebnis[x,7] > 1 then begin h:=ergebnis[x,2]; p:=0; // 2 haben wir schon, mit drei machen wir weiter: for i:=3 to 6 do If ergebnis[x,i] >h then p:=I; // Aussreißer gefunden? Dann... if p>0 then begin // Wir setzen den Ausreisser auf NUll Ergebnis[x,p]:=0; // und berechnen die Summen von Ergebnis neu: ergebnis[x,7]:=0; for I:=2 to 6 do ergebnis[x,7]:=ergebnis[x,7]+ergebnis[x,i]; end;
Delphi-Quellcode:
Programmanzeige nauch "unten" verlagert.
program ReadDaten;
{$APPTYPE CONSOLE} uses math; var f:textfile; Feldnamen:string; Daten:Array[1..1000,1..6] of real; Ergebnis:Array[1..1000,1..7] of real; x,i:integer; h:real; p:integer; Anzahl:integer; function Runden(x: Extended; Stellen: Byte): Extended; begin Result:= Round(x * IntPower(10, Stellen))/IntPower(10, Stellen); end; begin // DATEN in Array Daten einlese assignfile(f,'C:\Daten.txt'); Reset(f); readln(f,Feldnamen); for X:=1 to 1000 do begin for i:=1 to 6 do begin read(f,daten[x,i]); end; end; closefile(f); //Wir stellen sicher, dass keine 0 vorkommt und ersetzten diese durch 0.01; for x:=1 to 1000 do begin for i:=1 to 6 do if daten[x,i]=0 then daten[x,i]:=0.01; end; // Wir gehen alle Zeilen und Spalten in Muster durch und speichern das Ergebnis: for x:=2 to 1000 do begin for i:=2 to 6 do begin // Wir dividieren durch die Anzahl der Daten, hier 5: Ergebnis[x,i]:=(daten[x,i]/daten[1,i])/5; //<Negative Ergebnisse bringen nicht das resultat, daher *-1 if Ergebnis[x,i]< 0 then ergebnis[x,i]:=ergebnis[x,i]*-1; //Ursprünglich: { Ergebnis[x,i]:=(daten[x,i]/daten[1,i]); } end;//i.. //Ergebnis von Spalte 2 bis 6 in 7 speichern: ergebnis[x,7]:=0; for I:=2 to 6 do ergebnis[x,7]:=ergebnis[x,7]+ergebnis[x,i]; // Wir prüfen, einen Aussreißer im Array Ergbnis[x,1.6] um zu sehen, // ob 4 von 5 Werten unsere Bedingungen erfüllen. if ergebnis[x,7] > 1 then begin h:=ergebnis[x,2]; p:=0; // 2 haben wir schon, mit drei machen wir weiter: for i:=3 to 6 do If ergebnis[x,i] >h then p:=I; // Aussreißer gefunden? Dann... if p>0 then begin // Wir setzen den Ausreisser auf NUll Ergebnis[x,p]:=0; // und berechnen die Summen von Ergebnis neu: ergebnis[x,7]:=0; for I:=2 to 6 do ergebnis[x,7]:=ergebnis[x,7]+ergebnis[x,i]; end; end; end;//x.. //Kurze Anzeige aller Datensätze, die gefunden wurden: Anzahl:=0; for x:=2 to 1000 do if Ergebnis[x,7] <1 then inc(Anzahl); writeln('Anzahl der aehnlichen Datensaetze: ',Anzahl:2); writeln; // Anzeige aller Datensätze, die die Bedingungen erfüllen: writeln('Anzeige der gefundenen Datensätze'); for x:=2 to 1000 do begin // Die Ausgabe wird beschränkt: if (ergebnis[x,7] < 1) then begin writeln('Datensatz: ',x); for i:=2 to 6 do write(daten[1,i]:2:2,' ');writeln; for i:=2 to 6 do write(daten[x,i]:2:2,' ');writeln; for i:=2 to 6 do write(ergebnis[x,i]:2:2,' ');writeln; writeln('Ergebnis: ',ergebnis[x,7]:2:2);writeln; writeln('Taste'); readln; end; end; writeln('Ende - ENTER'); readln; end. Vorschläge, Verbesserungen? |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Zitat:
Nicht doch eher soetwas wie -114% (also: gar nicht ähnlich)? Ich würde mir eine Funktion schreiben, die zwei Tupel miteinander vergleicht, und den Ähnlichkeitsindex (0..1 oder 0..100) zurückliefert. Im Prinzip hast Du das ja gemacht, aber eine Funktion zentralisiert diese Entscheidungslogik und macht es imho übersichtlicher. Vielleicht solltest Du auch nicht von 'Ähnlichkeit' sprechen, sondern von einem 'Abstand', aber das ist Wortklauberei. Für den Zugriff auf die Tupel sowohl als Array als auch auf die individuellen Werte würde ich einen 'variant record' verwenden.
Delphi-Quellcode:
Und die Funktion selbst so deklarieren;
Type
TValues = Record Case Boolean Of False : (Sta, Proz, Gl1, Gl2, Gl3, Gl4 : Double); // Individueller Zugriff True : (Values : Array [0..5] Of Double); // Indizierter Zugriff End;
Delphi-Quellcode:
Function SimilarityIndex (Const A,B : TValues) : Double;
Begin .... End; |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Zitat:
Ich denke, wir meinen das Gleiche. Ähnlichkeit oder Abstand, in jedem Fall muss er das selbst für jeden Eintrag und Feld selbst festlegen (was immer die Werte auch bedeuten mögen) und die Ähnlichkeit der Datensätze dann über eine Funktion ermitteln... stahli |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Nur her mit der Wortklauberei... :wink:
Genaugenommen ist es der Abstand in eine positive Zahl überführt. (Siehe oben meinen Beitrag) Das mit dem varianten Record verstehe ich nicht. Ich brauche das Array "Daten" und das Array "Ergebnisse" so. Das Auslagern in Proceduren macht das ganze schon übersichtlicher. Vielleicht sogar einen Funktion bei dem der Schwellenwert dann eingestellt werden kann, oder sich automatisch justiert. Aber mit dem vorliegenden Umfang des "Programmes", wenn ich den Code mal so nennen darf, denke ich, ist es so legitim. |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Angenommen es gibt 2 Punkte in einem x/y Koordinatensystem und man möchte die "Abweichung" berechnen.
Ich würde es so machen:
Delphi-Quellcode:
Die einzelnen Fehler werden quadriert (SQR) und aufsummiert.
Abweichung2 := SQR((x2-x1) / x1) + SQR((y2-y1)/ y1); // Summe der Fehlerquadrate
Abweichung := SQRT(Abweichung2); // Wurzelziehen Wenn man anschliesend die Wurzel zieht, hat man ein gutes Mass zur Beurteilung wie weit sich die Punkte voreinander unterscheiden. Was hier mit 2 Dimensionen geht lässt sich auf beliebig viele Dimensionen erweitern.
Delphi-Quellcode:
Function SimilarityIndex (Const A,B : TValues) : Double;
var i : integer; abweichung2 : double; Begin abweichung2 := 0.0; for i := 0 to 5 do abweichung2 := abweichung2+ SQR((B.value[i]-A.value[i])/A.Value[i]); result := SQRT(abweichung2); end |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Danke shmia. Deinen Vorschlag baue ich morgen in den Code rein. Ich bin dann auf die Ergebnisse schon sehr gespannt.
|
Re: Prozentuale Ähnlichkeit (Mustererkennung)
So Code mal geändert:
Neues Array für die Ergebnisse mit der neuen Berechnung "angelegt": SqrArray[1..1000,1..7]; und die neue Berechnung so durchgeführt:
Delphi-Quellcode:
Zur besseren Übersicht speichere ich die Ergebnisse in eine Datei. Die Anzeige in der Console wird nun zu unübersichtlich. Den vollständigen Code reiche ich noch nach. (Wird hier sonst zu voll).for x:=2 to 1000 do begin for i:=2 to 6 do begin ... //2. Berechnung: Fehlerquadrat und Wurzelziehen. //Original: //abweichung2 := abweichung2+ SQR((B.value[i]-A.value[i])/A.Value[i]); //result := SQRT(abweichung2); //Umsetzung: sqrArray[x,i]:=0; sqrArray[x,i]:=sqrArray[x,i]+(SQR((Daten[x,i]-Daten[x,1]) / Daten[x,1])); sqrArray[x,i]:=Sqrt(sqrArray[x,i])/5; end;//i.. ... Das vorläufige Ergebnis: Die 1. Berechnung findet 25 Datensätze (< 1), die sich ähnlich sind. (Aber nur mit bereinigten Ausreißern) Die 2. Berechnung mit Fehlerquadrat findet 101 Datensätze (< 1) mit Außreißern. Inwieweit die 2. Berechnung sinnvoll ist, läßt sich erst ermitteln, wenn ich mir die vom Programm angezeigten Ergebnisse genau ansehe. Soweit ich das in der Console sehe, sind in der zweiten Berechnung die Aussreißer größer, bzw. die Ahnlichkeit mit dem ersten Datensatz geringer. Ich werde weiter berichten. |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Hallo Go2EITS,
was bedeuten denn eigentlich Deine Feldwerte? Wenn man z.B. Texte vergleicht oder Bilder muss man "abstrakte" Vergleiche anstellen. Z.B. Entfernungen von Koordinaten, Abstand von Farbwerten oder Helligkeiten, Anzahl übereinstimmender Buchstaben o.ä. Hinterher kann man schauen, ob die verwendete Formel schon Sinn macht... Wenn die Feldwerte dagegen "individuelle" Bedeutungen haben (das hatte ich bisher angenommen), kann man die Ähnlichkeit sicher besser ermitteln. Nehmen wir mal Patienten: Patient, Alter, Blutdruck, Insolin 1, 35, 120, 3.8 2, 40, 130, 3.5 Hier hat jedes Feld eine feste Bedeutung. Nun kannst Du abhängig vom Alter einen Gesundheitszustand je Patient berechnen und den vergleichen. Dazu musst Du aber jedes Feld unterschiedlich bewerten. In jedem Fall müssen die Kriterien ja Feld davon abhängig sein, was die Zahlen bedeuten, welche Maximal- und Minimalwerte möglich sind und wie wichtig ein Eintrag ist (Blutdruck 200 wäre schon mal nicht so gut). stahli |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Hallo Stahli,
Deine Zahlen kommen meinen Werten am nächsten: Patient, Alter, Blutdruck, Insolin 1, 35, 120, 3.8 2, 40, 130, 3.5 Wenn man dem noch Attribute wie "sehr gesund", "gesund", "noch gesund", "behandlungsbedürftig", "krank", "akut", beifügt, so kann man bei neuen Datensätzen aus den vorliegenden Datensätzen wohl eine gute Übersicht bekommen, was aus der Datenbank für Antworten kommen. Vielleicht erscheinen bei einer Eingabe eines Datensatzes dann folgende Antworten: 4 mit "sehr gesund" und 3 Datensätze mit "gesund" Hier meine erste Überarbeitung mit einer Übersicht der der zwei Berechnungen, wobei ich als Schwellen nachfolgende Werte gesetzt habe: Schelle Abstand =1 und Schwelle Sqr =0.5 Im Programm wie folgt deklariert: //Schwellen festlegen: Schwelle1:=1; Schwelle2:=0.5; Inwieweit die Berechnungen ähnliche Datensätze findet und ob die Datenbank sinnvolle Datensätze beinhaltet, wird sich zeigen. Bei meinem Beispiel zeigt sich, das an der 5 Positon der Datensätze in der ersten Berechnung sich die meisten Ausreißer (17 Zahlen) befinden. Wenn ich diese ignoriere, erscheinen diese Datensätze als ähnlich. Ich werde diese Berechung mit den Ausreißern auslagern müssen und separat anzeigen. Als nächstes suche ich eine Datenbank mit Patientendaten oder Sonnenfleckenprognose oder so ähnlich. Falls jemand einen Link zu einem Datensatz hat, bitte hier posten. Hier mein Delphicode, basierend auf die Datensätze der ersten Datenbank:
Delphi-Quellcode:
Das Ergebnis sollte ich wohl auch mal hier einfügen:
program ReadDaten;
{$APPTYPE CONSOLE} uses math; var f:textfile; Feldnamen:string; Daten:Array[1..1000,1..6] of real; Ergebnis:Array[1..1000,1..7] of real; x,i:integer; h:real; p:integer; Anzahl:integer; Genullt:Array[1..7] of integer; // Array für die Ergebnisse unserer Berechnung mit Fehlerquadraten und Wurzelziehen SqrArray:Array[1..1000,1..7] of Real; // Schwelle für die 1. Berechnung: Schwelle1:Real; // Schwelle für die 2. berechnung: Schwelle2:Real; function Runden(x: Extended; Stellen: Byte): Extended; begin Result:= Round(x * IntPower(10, Stellen))/IntPower(10, Stellen); end; // Nullen wird nur für die Berechung des Abstandes verwendet. Procedure NullenAnzeigen; Var x,i:integer; begin //Kurze Anzeige der Spalte bei den Datensätzen, die die Bedingung // Ergebnis[x,7] <1 erfüllen, um zu sehen, ob eine Spalte zum Ergenis nicht beiträgt. for i:=1 to 7 do Genullt[i]:=0; for x:=2 to 1000 do begin if ergebnis[x,7] <=Schwelle1 then begin for i:=1 to 7 do begin if Ergebnis[x,i] =0.00 then begin inc(Genullt[i]); end;//Ergebnis.. end;//i.. end; end;//x.. writeln('Genullt:'); for i:=2 to 6 do write(genullt[i],' ');writeln;writeln; end; Function ErgebnisAbstand:integer; begin Anzahl:=0; for x:=2 to 1000 do if Ergebnis[x,7] <=Schwelle1 then inc(Anzahl); result:=anzahl; end; Function ErgebnisSqr:integer; begin Anzahl:=0; for x:=2 to 1000 do if SqrArray[x,7] <=Schwelle2 then inc(Anzahl); result:=anzahl; end; Procedure AnzeigeBerechnung1; begin writeln; writeln('Ergebnisse der Berechnung (Berechnung 1) nach Abstand:'); writeln('Datensatz'); write('Zeile 1: ');for i:=2 to 6 do write(daten[1,i]:2:2,' ');writeln('hat Aehnlichkeit mit:');writeln; for x:=2 to 1000 do begin if (ergebnis[x,7] <= Schwelle1) then begin write('Zeile ',x,': ');for i:=2 to 6 do write(daten[x,i]:2:2,' ');Write('Summe Durchschnitt: ',ergebnis[x,7]:2:2);writeln; // Falls wir die Berechnung auch sehen wollen: // write('Ergebnis: ');for i:=2 to 6 do write(Ergebnis[x,i]:2:2,' '); // writeln('Taste');readln; end; end; end; procedure AnzeigeBerechnung2; Var x,i:integer; begin writeln; writeln('Ergebnisse der Berechnung (Berechnung 2) nach Fehlerquadrat und Wurzel:'); writeln('Datensatz'); write('Zeile 1: ');for i:=2 to 6 do write(daten[1,i]:2:2,' ');writeln('hat Aehnlichkeit mit:'); for x:=2 to 1000 do begin if (SqrArray[x,7] <= Schwelle2) then begin write('Zeile ',x,': ');for i:=2 to 6 do write(daten[x,i]:2:2,' ');write('Summe Durchschnitt: ',SqrArray[x,7]:2:2);writeln; // Falls wir die Berechnung auch sehen wollen: // for i:=2 to 6 do write(SqrArray[x,i]:2:2,' ');writeln; // ;writeln; // writeln('Taste');readln; end; end; end; Procedure Berechnung; VAr x,i:integer; begin //Wir stellen sicher, dass keine 0 vorkommt und ersetzten diese durch 0.01; for x:=1 to 1000 do begin for i:=1 to 6 do if daten[x,i]=0 then daten[x,i]:=0.01; end; for x:=2 to 1000 do begin for i:=2 to 6 do begin // 1. Berechnung // Wir dividieren durch die Anzahl der Daten: Ergebnis[x,i]:=(daten[x,i]/daten[1,i]); //Negative Ergebnisse bringen nicht das Resultat, daher *-1 if Ergebnis[x,i]< 0 then ergebnis[x,i]:=ergebnis[x,i]*-1; //2. Berechnung: Fehlerquadrat und Wurzelziehen. //abweichung2 := abweichung2+ SQR((B.value[i]-A.value[i])/A.Value[i]); //result := SQRT(abweichung2); sqrArray[x,i]:=0; sqrArray[x,i]:=sqrArray[x,i]+(SQR((Daten[x,i]-Daten[x,1]) / Daten[x,1])); sqrArray[x,i]:=Sqrt(sqrArray[x,i]); end;//i.. //1.Berechnung: Ergebnis von Spalte 2 bis 6 in 7 speichern: Ergebnis[x,7]:=0; for I:=2 to 6 do ergebnis[x,7]:=ergebnis[x,7]+ergebnis[x,i]/5; //2. Berechnung: Ergebnis vom Fehlerquadrat und Wurzelziehen: SqrArray[x,7]:=0; for I:=2 to 6 do SqrArray[x,7]:=SqrArray[x,7]+SqrArray[x,i]/5; //Ergänzung zur ersten Berechnung // Wir prüfen auf einen Ausreißer im Array Ergebnis[x,2..6], um zu sehen, // ob 4 von 5 Werten unsere Bedingungen erfüllen. if ergebnis[x,7] > Schwelle1 then begin p:=0; h:=Schwelle1; for i:=2 to 6 do If ergebnis[x,i] >h then begin p:=I; h:=ergebnis[x,i]; end; // Ausreißer gefunden? Dann... if p>0 then begin // Wir setzen den Ausreisser auf NUll Ergebnis[x,p]:=0; // und berechnen die Summen von Ergebnis neu: ergebnis[x,7]:=0; for I:=2 to 6 do ergebnis[x,7]:=ergebnis[x,7]+ergebnis[x,i]; // und setzen den Durchschnitt: ergebnis[x,7]:=ergebnis[x,7]/4; end; end; end; end; begin // DATEN in Array Daten einlese assignfile(f,'C:\Daten.txt'); Reset(f); readln(f,Feldnamen); for X:=1 to 1000 do begin for i:=1 to 6 do begin read(f,daten[x,i]); end; end; closefile(f); //Schwellen festlegen: Schwelle1:=1; Schwelle2:=0.5; // Berechnung von // a) Abstand // b) Fehlerquadrat Berechnung; ErgebnisAbstand; ErgebnisSQR; //Kurze Anzeige aller Datensätze, die gefunden wurden: writeln('Anzahl der aehnlichen Datensaetze Berechnung 1: ',ErgebnisAbstand); writeln('Anzahl der aehnlichen Datensaetze Berechnung 2: ',ErgebnisSqr); writeln; writeln('Weiter - ENTER');readln; //Anzeige, wie oft Ausreisser zur Berechnung "genullt" wurden. NullenAnzeigen; AnzeigeBerechnung1; AnzeigeBerechnung2; writeln('Ende - ENTER'); readln; end. Berechnung 1: 29 (Abstand ohne Aussreißer) Berechnung 2: 6 (Fehlerquadrat und Wuzelziehen) |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Hallo Go2EITS,
noch eine grundsätzliche Überlegung: Ein Patient mit hohem Blutdruck und niedrigem Insulin = ungesund Ein Patient mit normalem Blutdruck und hohem Insulin = ungesund Wenn man das Ergebnis vergleicht, sind diese natürlich übereinstimmend. Die Datensätze an sich sind aber nicht unbedingt ähnlich... stahli |
Re: Prozentuale Ähnlichkeit (Mustererkennung)
Ich glaube, ich habe da etwas Passendes gefunden:
![]() In der Spalte zwei befindet sich unser Output/die anderen Spalten sind unsere Inputs. Als nächste Überlegung wäre es, die Trainingsdaten und Testdaten zu trennen: Wir nehmen 10 oder 20 Datensätze vom Training raus und prüfen, welche Daten uns dann von der Datenbank angezeigt werden. Das neuronale Netz auf der Internetseite scheint 70 der 87 Fälle (Testmenge) richtig zu erkennen. Mal sehen, was das Programm erkennt, wenn ich es umgeschrieben habe. Vielleicht splitte ichn die Daten in zwei Dateien. Mal sehen, was schneller zu programmieren wäre. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:38 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz