Ik ben op het moment bezig met een cluster analyse en wil zien wat het verschil is bij het toepassen van verschillende similarity algoritmes t.o.v. de cluster resultaten. Om te zien wat de verschillen zijn heb ik zeven natuurlijke clusters gedefinieerd (bv, 10 instanties van voertuigen, 10 instanties van dierren etc). Dus ik weet wat de correcte clusters zijn nu wil ik alleen kijken of ik met een script kan berekenen of de clusters overeenkomen met wat ik voor ogen heb. Om dit te berekenen maak ik gebruik van de Rand Index, zodat ik een cijfer heb om te te kunnen vergelijken. Mede gebruik ik deze methode om de true positive (TP), false positive (FP), true negative (TN) & false negative (FN) te berekenen. De method Rand Index geeft echter een andere naam aan deze namen, dus hier de vertaalslag:
Om te testen of mijn function overeenkomst met de werkelijkheid heb ik eerste gekeken naar een voorbeeld en deze precies overgenomen om te kijken of ik dezelfde resultaten krijg. Het voorbeeld is hier te vinden: http://www.otlet-institut...s.html#toc-Subsection-4.1
In dit voorbeeld maak ik gebruik van een class lijst en een cluster lijst. De class lijst bevat de clusters zoals ze horen te zijn en de cluster lijst bevat de clusters als die uit een cluster algoritme kan komen. Als eerste de class lijst:
En dan de class en cluster lijst.
Om de output te tonen gebruik ik de volgende drie regels:
Als ik het voorbeeld van de pagina één-op-één overneem dan krijg ik de het volgende resultaat: 0.8056, dus 0.81. Precies zelfde als in het voorbeeld.
Vanaf dit punt ga ik er mee spelen om te kijken of mijn verwachtingspatroon overeenkomt met wat ik uit de functie krijg. Als eerste een simpele:
De output van de clustering is identiek aan dat van wat ik vooraf wil hebben, dus de output zou 1 moeten zijn en dit zie ik ook terug.
Dan het volgende:
Verwacht: TP: 7; TN: 24; FN: 2; FP; 3. En dit krijg ik ook precies uit het programma, maar wanneer ik nu o5 achter o4 plaats dan komt er een verschil in verwacht en uitkomst. Dus:
Verwacht: TP: 6; TN: 21; FN: 2: FP; 3, want:
En het programma geeft mij het volgende resultaat: TP: 7; TN: 21; FN: 2: FP; 6. Één TP is verkeerd berekend dit had een FP moeten zijn. Als je de echo's aanzet in de functie dan worden de resultaten wel getoond en waar het misgaat is het paartje (o4,o5). Deze de class index is #1 en cluster index is 0 voorbeide. Dus de conditie voor een true positive (the number of pairs of elements in S that are in the same set in X and in the same set in Y) gaat wel op, maar eigenlijk hebben we het over andere clusters.
Ik zie even niet wat ik moet gaan aanpassen. Ik kan de volgende conditie nog toevoegen aan de TP if-statement:
Dan haalt hij de TP dit teveel wordt berekent er wel uit, maar de FP statement zal hem nog keihard negeren.
Tevens zit ik kan ik de extra FP niet vinden. De TP zijn namelijk de volgende paartjes:
Als ik dit bij de FP doe dan kom ik op de volgende paartjes:
Ik mis er eentje, maar ik weet niet welke wat ik zoek er nog één waarde de volgende conditie opgegaat: decision assigns two dissimilar objects to the same cluster.
Disclaimer:
Ik weet dat er nog een kleine bug inzit als het gaat om dezelfde index nummering. Toevallig is het in deze situatie goed, maar hoe weet de functie dat cluster #1 gelijk is aan class #1? Dat probleem heb ik herkend en heb een idee om dat op te lossen. Voor nu geef ik goede input aan het programma dus hoef ik mij daar nu geen zorgen om te maken.
code:
1
2
3
4
| TP = A TN = B FN = C FP = D |
Om te testen of mijn function overeenkomst met de werkelijkheid heb ik eerste gekeken naar een voorbeeld en deze precies overgenomen om te kijken of ik dezelfde resultaten krijg. Het voorbeeld is hier te vinden: http://www.otlet-institut...s.html#toc-Subsection-4.1
In dit voorbeeld maak ik gebruik van een class lijst en een cluster lijst. De class lijst bevat de clusters zoals ze horen te zijn en de cluster lijst bevat de clusters als die uit een cluster algoritme kan komen. Als eerste de class lijst:
- o1 o2 o3
- o4 o5 o6
- o7 o8 o9
- o1 o2
- o3 o4 o5 o6
- o7 o8
- o9
PHP:
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
| class RandIndex { public static function Calculate($classList, $clusterList) { // first get one dimensional list with all object $objectList = array(); foreach ($clusterList as $cluster) { foreach ($cluster as $object) { $objectList[] = $object; } } // define true and false positive and negative list (will contain object pairs) $tpList = array(); $tnList = array(); $fnList = array(); $fpList = array(); // for ( (int) $i = 0; $i < count($objectList); $i++ ) { for ( (int) $j = $i + 1; $j < count($objectList); $j++ ) { // get two objects that create a pair $k1 = $objectList[$i]; $k2 = $objectList[$j]; // find the class index to which the objects belong $classIndexK1 = self::__FindIndex($classList, $k1); $classIndexK2 = self::__FindIndex($classList, $k2); // find the cluster index to which the objects belong $clusterIndexK1 = self::__FindIndex($clusterList, $k1); $clusterIndexK2 = self::__FindIndex($clusterList, $k2); //echo "<hr>"; //echo $k1 . "," . $k2 . "<br>"; //echo "Class: " . $classIndexK1 . "," . $classIndexK2 . "<br>"; //echo "Cluster: " . $clusterIndexK1 . "," . $clusterIndexK2 . "<br>"; //var_dump(( $classIndexK1 != $classIndexK2 && $clusterIndexK1 == $clusterIndexK2 && $classIndexK1 != $clusterIndexK1 )); if ( $classIndexK1 == $classIndexK2 && $clusterIndexK1 == $clusterIndexK2 ) { // a, pairs are in the same set in X and in the same set in Y $tpList[] = sprintf("(%s,%s)", $k1, $k2); } else if ( $classIndexK1 != $classIndexK2 && $clusterIndexK1 != $clusterIndexK2 ) { // b, pairs are in different sets in X and in different sets in Y $tnList[] = sprintf("(%s,%s)", $k1, $k2); } else if ( $classIndexK1 == $classIndexK2 && $clusterIndexK1 != $clusterIndexK2 ) { // c, pairs are in the same set in X and in different sets in Y $fnList[] = sprintf("(%s,%s)", $k1, $k2); } else if ( $classIndexK1 != $classIndexK2 && $clusterIndexK1 == $clusterIndexK2 ) { // d, are in different sets in X and in the same set in Y $fpList[] = sprintf("(%s,%s)", $k1, $k2); } } } // calculate the rand index: formula is: (a+b)/(a+b+c+d) $index = (count($tpList) + count($tnList)) / (count($tpList) + count($tnList) + count($fnList) + count($fpList)); // return everything, TP, FP, FN, TN and RandIndex return array( 'tp' => count($tpList), // a 'tn' => count($tnList), // b 'fn' => count($fnList), // c 'fp' => count($fpList), // d 'index' => $index, ); } private static function __FindIndex($haystack, $needle) { for ( (int) $i = 0; $i < count($haystack); $i++ ) { if ( in_array($needle, $haystack[$i]) === true ) { return $i; } } // not found throw new Exception("Object kan niet gevonden worden in de haystack (waar haystack, classList of clusterList kan zijn)."); } } |
En dan de class en cluster lijst.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
| $classList = array( array('o1', 'o2', 'o3'), array('o4', 'o5', 'o6'), array('o7', 'o8', 'o9'), ); $clusterList = array( array('o1', 'o2'), array('o3', 'o4', 'o5', 'o6'), array('o7', 'o8'), array('o9'), ); |
Om de output te tonen gebruik ik de volgende drie regels:
PHP:
1
2
3
| $res = RandIndex::Calculate($classList, $clusterList); echo "<pre>"; print_r($res); |
Als ik het voorbeeld van de pagina één-op-één overneem dan krijg ik de het volgende resultaat: 0.8056, dus 0.81. Precies zelfde als in het voorbeeld.
Vanaf dit punt ga ik er mee spelen om te kijken of mijn verwachtingspatroon overeenkomt met wat ik uit de functie krijg. Als eerste een simpele:
PHP:
1
| $clusterList = $classList; |
De output van de clustering is identiek aan dat van wat ik vooraf wil hebben, dus de output zou 1 moeten zijn en dit zie ik ook terug.
Dan het volgende:
PHP:
1
2
3
4
5
| $clusterList = array( array('o1', 'o2', 'o3', 'o4'), array('o5', 'o6'), array('o7', 'o8', 'o9'), ); |
Verwacht: TP: 7; TN: 24; FN: 2; FP; 3. En dit krijg ik ook precies uit het programma, maar wanneer ik nu o5 achter o4 plaats dan komt er een verschil in verwacht en uitkomst. Dus:
PHP:
1
2
3
4
5
| $clusterList = array( array('o1', 'o2', 'o3', 'o4', 'o5'), array('o6'), array('o7', 'o8', 'o9'), ); |
Verwacht: TP: 6; TN: 21; FN: 2: FP; 3, want:
code:
1
2
3
| TP+FP = (5 ncr 2) + (1 ncr 2) + (3 ncr 2) = 10 + 0 + 3 = 13. Waar TP = (3 ncr 2) + (1 ncr 2) + (3 ncr 2) = 3 + 0 + 3 = 6. Dus FP = (TP+FP) - TP = 13 - 6 = 7. |
En het programma geeft mij het volgende resultaat: TP: 7; TN: 21; FN: 2: FP; 6. Één TP is verkeerd berekend dit had een FP moeten zijn. Als je de echo's aanzet in de functie dan worden de resultaten wel getoond en waar het misgaat is het paartje (o4,o5). Deze de class index is #1 en cluster index is 0 voorbeide. Dus de conditie voor een true positive (the number of pairs of elements in S that are in the same set in X and in the same set in Y) gaat wel op, maar eigenlijk hebben we het over andere clusters.
Ik zie even niet wat ik moet gaan aanpassen. Ik kan de volgende conditie nog toevoegen aan de TP if-statement:
PHP:
1
| $classIndexK1 == $clusterIndexK1 |
Dan haalt hij de TP dit teveel wordt berekent er wel uit, maar de FP statement zal hem nog keihard negeren.
Tevens zit ik kan ik de extra FP niet vinden. De TP zijn namelijk de volgende paartjes:
code:
1
| {(o1,o2),(o1,o3),(o2,o3),(o7,o8),(o7,o9),(o8,o9)}. |
Als ik dit bij de FP doe dan kom ik op de volgende paartjes:
code:
1
| {(o1,o4),(o1,o5),(o2,o4),(o2,o5),(o3,o4),(o5,o6)} |
Ik mis er eentje, maar ik weet niet welke wat ik zoek er nog één waarde de volgende conditie opgegaat: decision assigns two dissimilar objects to the same cluster.
Disclaimer:
Ik weet dat er nog een kleine bug inzit als het gaat om dezelfde index nummering. Toevallig is het in deze situatie goed, maar hoe weet de functie dat cluster #1 gelijk is aan class #1? Dat probleem heb ik herkend en heb een idee om dat op te lossen. Voor nu geef ik goede input aan het programma dus hoef ik mij daar nu geen zorgen om te maken.