Recommender: Unterschied zwischen den Versionen

Aus Callooh Wiki
Zur Navigation springen Zur Suche springen
 
(145 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
= BUGS =
* mehrere USER-Relationen von Mandant-User-Ref zu User Knoten, User selber gibts aber nur einmal
= TODO =
* RECOMMENDED Beziehung mit Datum:
** um nicht dauernd die gleichen items zu recommenden
** um periodisch items (auch geratete) recommenden zu können
* Multiple Rating Dimensions: z.b. zusätzliches TYPE Property bei Rating (e.g. Story, Acting, Special Effects - s. Herlocker p.16)
* Neuzuteilung Mandant<->Workgroup<->Worker nur bei geänderter Konfiguration, nicht bei jedem check
* ELECTION: Property des Koordinator-Knotens mit Zufallszahl initialisieren, in Singleton speichern. In regelmäßigen Zeitintervallen überprüft dieser Worker ob die Zufallszahlen übereinstimmen, und beendet gegebenenfalls die Koordinator-Dienste.
* Eigener SchedulerQListener für jeden Mandanten
* Concurrency Problem: Enfernen von JobGroup (mach letzter Job)
* Lösung für Concurrency Probs ab V1.6: putIfAbsent
* Input-Daten für Methoden: neben alle auch "alle neuen" - timestamp setzen nachdem methode ausgeführt worden ist, und diesen jeweils mit den rating-timestamps der user-nodes vergleichen
* check bzw. abfrage, ob client einer workgroup idle ist, möglichkeit einen job zu verweigern wenn das nicht der fall ist, andere clients aber idle wären
* Predictions: eventuell sind von vorherigen läufen noch predictions gesetzt - z.b. wenn bei voherigen lauf bestimmter user berücksichtigt wurde, beim aktuellen aber nicht. beim aggregieren der predictions sollten daher nur jene mit der aktuellen jobgroupID betrachtet werden -> zu prediction also noch jobGroupID mitspeichern!
== AIS ==
* IDEE: alles auf items betrachtet (statt auf user), also z.b. item-clustering
=== MARIA ===
TODO: Parallelisieren: FAB, BC, MEM Layer parallel
= Ergebnisse =
== Movielens ==
100,000 ratings (1-5) from 943 users on 1682 movies,
avg commonrate=19
avg pearson korrelation k=0,1220 (normalisiert mit pk<=0 ? 0 : pk)
                        k=0,5382 (normalisiert mit pk+1)/2.0)
=== Hammock ===
==== ml-100k ====
* predictcount: 420.000 - 455.913
* runtime: 7 min Similarity, 22 min Prediction (3min / 4min bei standalone)
* cardinality: 17439, 17341
* Accuracy
u1  15.86
u2
u3  15.39
u4  15.42
u5  15.48
==== ml-1m ====
* predictcount: 9.036.721
* runtime: 146.5 min Similarity, 89 min Prediction
* cardinality: 159.671
* accuracy: 14.68
=== IBCF ===
* predictcount: 195912
* runtime: 0.96 min Similarity, 1.03 min prediction
* cardinality: 11.421
* Accuracy
u1  15.52
u2
u3  14.43
u4
u5  15.28
==== ml-1m ====
* predictcount: 2.514.592
* runtime: 39 min Similarity, 15.11 min prediction
* cardinality: 139.732
* accuracy: 13.46
=== AINE ===
* Berechnen der durchschnittlichen Affinität (zwischen allen Usern): 21.9 min
* AINE Tests:
NAT = 0.8;
bcellcount = 1500;
cloneConstant = 3;
bcellAllocConstant = 10;
consideredEqual = 0.9
ARBs stabil bei ~265, avg sl=0.76, aber nur 0.11 links
* runtime 2 Gens: 255 min
* predictions: 307.864
* cardinality: 12.779
* accuracy: 17.2
=== Enhanced AINE ===
==== 100k ====
* runtime: 35-50 sec clustering, predict: 30 min
* cardinality:  12088
* predictcount: 234143
u1: 15.94
u2: 15.85
u3: 15.76
u4: 15.94
u5: 16.02
generations=2
nat="0.7"
bcells=800
kclone=5
kbcell=100
equal="0.9"
fixedrate="0.01"
STAT[0/1]: ARBs=92; bcells=0; clonesCrt=0; clonesAdd=0; added=92; removed=0;
STAT[0/2]: a_sl=0,00; a_sAg=0,00; a_links=5,67; a_linkAff=0,75; unconnctd=10; a_repr=0,00; dangl=0
STAT[1/1]: ARBs=28; bcells=2310; clonesCrt=84; clonesAdd=0; added=0; removed=64;
STAT[1/2]: a_sl=0,53; a_sAg=534,15; a_links=5,64; a_linkAff=0,75; unconnctd=0; a_repr=33,68; dangl=0
STAT[2/1]: ARBs=28; bcells=698; clonesCrt=69; clonesAdd=0; added=0; removed=0;
STAT[2/2]: a_sl=0,50; a_sAg=1068,29; a_links=5,64; a_linkAff=0,75; unconnctd=0; a_repr=33,68; dangl=0
u3, nach update:
STAT[0/1]: ARBs=87; bcells=0; clonesCrt=0; clonesAdd=0; added=87; removed=0;
STAT[0/2]: a_sl=0,00; a_sAg=0,00; links=288; clusterCoeff=0,08; a_linkAff=0,75; unconnctd=7; a_repr=0,00; dangl=0
STAT[1/1]: ARBs=38; bcells=2185; clonesCrt=84; clonesAdd=10; added=10; removed=59;
STAT[1/2]: a_sl=0,39; a_sAg=398,76; links=190; clusterCoeff=0,27; a_linkAff=0,77; unconnctd=0; a_repr=24,82; dangl=0
STAT[2/1]: ARBs=31; bcells=952; clonesCrt=0; clonesAdd=0; added=0; removed=7;
STAT[2/2]: a_sl=0,50; a_sAg=545,02; links=128; clusterCoeff=0,28; a_linkAff=0,77; unconnctd=0; a_repr=55,61; dangl=0
STAT[3/1]: ARBs=21; bcells=952; clonesCrt=0; clonesAdd=0; added=9; removed=0;
STAT[3/2]: a_sl=0,29; a_sAg=311,74; links=67; clusterCoeff=0,32; a_linkAff=0,75; unconnctd=0;
===== u1 =====
AINE_CLUSTER_01: 4 ARBS; 248 Users; avgAff=0,76
AINE_CLUSTER_02: 5 ARBS; 329 Users; avgAff=0,75
AINE_CLUSTER_03: 5 ARBS; 287 Users; avgAff=0,79
AINE_CLUSTER_04: 6 ARBS; 343 Users; avgAff=0,75
AINE_CLUSTER_05: 4 ARBS; 257 Users; avgAff=0,74
===== u2 =====
AINE_CLUSTER_01: 4 ARBS; 288 Users; avgAff=0,75
AINE_CLUSTER_02: 4 ARBS; 284 Users; avgAff=0,74
AINE_CLUSTER_03: 2 ARBS; 191 Users; avgAff=0,76
AINE_CLUSTER_04:10 ARBS; 491 Users; avgAff=0,75
AINE_CLUSTER_05: 3 ARBS; 188 Users; avgAff=0,75
===== u3 =====
AINE_CLUSTER_00: 4 ARBS; 497 Users; avgAff=0,76
AINE_CLUSTER_01: 1 ARBS; 155 Users; avgAff=0,75
AINE_CLUSTER_02: 1 ARBS; 71 Users;  avgAff=0,74
AINE_CLUSTER_03: 1 ARBS; 232 Users; avgAff=0,76
AINE_CLUSTER_04: 4 ARBS; 380 Users; avgAff=0,75
AINE_CLUSTER_05: 1 ARBS; 61 Users;  avgAff=0,73
===== Stabilität =====
nach 20 Generationen: Anzahl ARBs stabil (~40), nach Merge allerdings nur noch 6 über, nach Clustering: 1 Cluster mit avgAff=0.66
* predictcount: 224060
* cardinality: 11881
* accuracy: 15.65
==== 1m ====
* predictcount: 1.858.024
* cardinality: 90.154
* runtime:  18.5 min
* accuracy: 15.11
=== MARIA ===
==== 100k ====
* predictCount: 233466
* cardinality:  12124 (- 12797)
* Laufzeit Variante 1: 2.36 - 3.95 min Clustering, 10.59 Prediction
* Laufzeit Variante 2: 58 min
* Accuracy: 16.15
            BA-1    BA-2
u1  0.815  16.3
u2        16.3
u3        16.05  15.99
u4        16.48
u5        16.52
train_always_all="false"
fl_death_threshold=6
bl_death_threshold=6
ml_death_threshold=2
ml_retain_threshold="0.5"
distribute="false"
pk_max_corates=12
presentation_percentage=50
affinity_threshold="0.7"
stimulation_threshold=10
memcell_affinity_threshold="0.8"
connection_threshold="0.52"
mutation_probability="0.02"
clone_factor=6
STAT[ 1]: freeABCells=  289, BCells=1403, MemCells=  30; avg_affinity=0,76; represent= 777; links=187; avg_link_aff=0,58, dangling=166
STAT[ 2]: freeABCells=  649, BCells=1451, MemCells=  39; avg_affinity=0,77; represent= 838; links=312; avg_link_aff=0,58, dangling=105
STAT[ 3]: freeABCells=  769, BCells=1487, MemCells=  50; avg_affinity=0,77; represent= 886; links=459; avg_link_aff=0,57, dangling=57
STAT[ 4]: freeABCells=  861, BCells=1501, MemCells=  62; avg_affinity=0,77; represent= 913; links=640; avg_link_aff=0,57, dangling=30
STAT[ 5]: freeABCells=  922, BCells= 257, MemCells=  65; avg_affinity=0,77; represent= 920; links=692; avg_link_aff=0,57, dangling=23
STAT[ 6]: freeABCells=  868, BCells= 232, MemCells=  67; avg_affinity=0,77; represent= 930; links=737; avg_link_aff=0,57, dangling=13
STAT[ 7]: freeABCells=  894, BCells= 210, MemCells=  66; avg_affinity=0,77; represent= 934; links=707; avg_link_aff=0,57, dangling=9
STAT[ 8]: freeABCells=  919, BCells= 208, MemCells=  66; avg_affinity=0,77; represent= 940; links=707; avg_link_aff=0,57, dangling=3
STAT[ 9]: freeABCells=  840, BCells= 173, MemCells=  66; avg_affinity=0,77; represent= 941; links=707; avg_link_aff=0,57, dangling=2
STAT[10]: freeABCells=  730, BCells= 145, MemCells=  64; avg_affinity=0,77; represent= 937; links=666; avg_link_aff=0,57, dangling=6
STAT[11]: freeABCells=  619, BCells= 125, MemCells=  63; avg_affinity=0,77; represent= 939; links=644; avg_link_aff=0,57, dangling=4
STAT[12]: freeABCells=  559, BCells= 103, MemCells=  63; avg_affinity=0,77; represent= 941; links=644; avg_link_aff=0,57, dangling=2
STAT[13]: freeABCells=  520, BCells=  96, MemCells=  63; avg_affinity=0,77; represent= 941; links=644; avg_link_aff=0,57, dangling=2
STAT[14]: freeABCells=  485, BCells=  86, MemCells=  63; avg_affinity=0,77; represent= 940; links=643; avg_link_aff=0,57, dangling=3
STAT[15]: freeABCells=  446, BCells=  77, MemCells=  63; avg_affinity=0,77; represent= 941; links=645; avg_link_aff=0,57, dangling=2
STAT[16]: freeABCells=  432, BCells=  71, MemCells=  63; avg_affinity=0,77; represent= 943; links=645; avg_link_aff=0,57, dangling=0
[FINAL]: freeABCells=  432, BCells=  71, MemCells=  63; avg_affinity=0,79; represent= 943; links=645; avg_link_aff=0,57
u3:
STAT[ 1]: freeABCells=  473, BCells= 833, MemCells=  31; links=213; clusterC=0,46; avg_link_aff=0,59, dangling=146
STAT[ 2]: freeABCells=  762, BCells= 877, MemCells=  37; links=281; clusterC=0,42; avg_link_aff=0,59, dangling=89
STAT[ 3]: freeABCells=  876, BCells= 903, MemCells=  50; links=464; clusterC=0,38; avg_link_aff=0,58, dangling=49
STAT[ 4]: freeABCells=  956, BCells= 910, MemCells=  66; links=774; clusterC=0,36; avg_link_aff=0,57, dangling=26
STAT[ 5]: freeABCells=  982, BCells= 226, MemCells=  71; links=893; clusterC=0,36; avg_link_aff=0,57, dangling=11
STAT[ 6]: freeABCells= 1000, BCells= 186, MemCells=  71; links=894; clusterC=0,36; avg_link_aff=0,57, dangling=9
STAT[ 7]: freeABCells=  997, BCells= 169, MemCells=  71; links=891; clusterC=0,36; avg_link_aff=0,57, dangling=5
STAT[ 8]: freeABCells=  997, BCells= 166, MemCells=  71; links=895; clusterC=0,36; avg_link_aff=0,57, dangling=1
STAT[ 9]: freeABCells=  770, BCells= 125, MemCells=  71; links=895; clusterC=0,36; avg_link_aff=0,57, dangling=1
STAT[10]: freeABCells=  534, BCells=  98, MemCells=  71; links=903; clusterC=0,36; avg_link_aff=0,57, dangling=0
''mit Variante 2:''
STAT[ 1]: freeABCells=  226, BCells=1395, MemCells=  31; links=199; clusterC=0,43; avg_link_aff=0,58, dangling=171
STAT[ 2]: freeABCells=  202, BCells=2163, MemCells=  37; links=274; clusterC=0,41; avg_link_aff=0,58, dangling=119
STAT[ 3]: freeABCells=  263, BCells=2950, MemCells=  41; links=311; clusterC=0,38; avg_link_aff=0,58, dangling=94
STAT[ 4]: freeABCells=  258, BCells=3746, MemCells=  44; links=370; clusterC=0,39; avg_link_aff=0,58, dangling=79
STAT[ 5]: freeABCells=  237, BCells=3302, MemCells=  49; links=437; clusterC=0,37; avg_link_aff=0,57, dangling=61
STAT[ 6]: freeABCells=  205, BCells=3342, MemCells=  52; links=470; clusterC=0,35; avg_link_aff=0,57, dangling=53
STAT[ 7]: freeABCells=  255, BCells=3368, MemCells=  53; links=487; clusterC=0,35; avg_link_aff=0,57, dangling=48
STAT[ 8]: freeABCells=  191, BCells=3419, MemCells=  51; links=437; clusterC=0,34; avg_link_aff=0,58, dangling=46
STAT[ 9]: freeABCells=  195, BCells=3435, MemCells=  60; links=611; clusterC=0,35; avg_link_aff=0,57, dangling=34
STAT[10]: freeABCells=  222, BCells=3444, MemCells=  60; links=604; clusterC=0,34; avg_link_aff=0,57, dangling=33
STAT[11]: freeABCells=  203, BCells=3457, MemCells=  58; links=566; clusterC=0,34; avg_link_aff=0,57, dangling=30
STAT[12]: freeABCells=  197, BCells=3439, MemCells=  58; links=576; clusterC=0,35; avg_link_aff=0,57, dangling=25
STAT[13]: freeABCells=  193, BCells=3446, MemCells=  58; links=560; clusterC=0,34; avg_link_aff=0,57, dangling=23
STAT[14]: freeABCells=  168, BCells=3465, MemCells=  57; links=546; clusterC=0,34; avg_link_aff=0,57, dangling=19
STAT[15]: freeABCells=  225, BCells=3473, MemCells=  56; links=531; clusterC=0,34; avg_link_aff=0,57, dangling=19
STAT[16]: freeABCells=  222, BCells=3482, MemCells=  56; links=533; clusterC=0,35; avg_link_aff=0,57, dangling=16
STAT[17]: freeABCells=  194, BCells=3501, MemCells=  55; links=510; clusterC=0,34; avg_link_aff=0,57, dangling=14
STAT[18]: freeABCells=  233, BCells=3511, MemCells=  55; links=507; clusterC=0,34; avg_link_aff=0,57, dangling=11
STAT[19]: freeABCells=  215, BCells=3528, MemCells=  55; links=525; clusterC=0,35; avg_link_aff=0,57, dangling=9
STAT[20]: freeABCells=  201, BCells=3549, MemCells=  54; links=485; clusterC=0,34; avg_link_aff=0,57, dangling=9
STAT[21]: freeABCells=  195, BCells=3554, MemCells=  54; links=498; clusterC=0,35; avg_link_aff=0,57, dangling=8
STAT[22]: freeABCells=  182, BCells=3558, MemCells=  54; links=489; clusterC=0,34; avg_link_aff=0,57, dangling=6
STAT[23]: freeABCells=  204, BCells=3566, MemCells=  51; links=447; clusterC=0,35; avg_link_aff=0,58, dangling=6
STAT[24]: freeABCells=  197, BCells=3561, MemCells=  51; links=433; clusterC=0,34; avg_link_aff=0,58, dangling=5
STAT[25]: freeABCells=  179, BCells=3568, MemCells=  51; links=446; clusterC=0,35; avg_link_aff=0,58, dangling=4
STAT[26]: freeABCells=  221, BCells=3575, MemCells=  51; links=448; clusterC=0,35; avg_link_aff=0,57, dangling=3
STAT[27]: freeABCells=  201, BCells=3577, MemCells=  51; links=443; clusterC=0,35; avg_link_aff=0,58, dangling=3
STAT[28]: freeABCells=  197, BCells=3584, MemCells=  51; links=441; clusterC=0,35; avg_link_aff=0,57, dangling=3
STAT[29]: freeABCells=  154, BCells=3586, MemCells=  51; links=446; clusterC=0,35; avg_link_aff=0,58, dangling=1
STAT[30]: freeABCells=  241, BCells=3587, MemCells=  51; links=458; clusterC=0,36; avg_link_aff=0,58, dangling=0
  [FINAL]: avg_affinity=0,78;
variante 2, u3, clone_factor=12, presentation_percentage=30:
STAT[ 1]: freeABCells=  658, BCells=1477, MemCells=  33; links=223; clusterC=0,42; avg_link_aff=0,59, dangling=139
STAT[ 2]: freeABCells=  705, BCells=2264, MemCells=  39; links=295; clusterC=0,40; avg_link_aff=0,58, dangling=100
STAT[ 3]: freeABCells=  705, BCells=3068, MemCells=  43; links=351; clusterC=0,39; avg_link_aff=0,58, dangling=78
STAT[ 4]: freeABCells=  717, BCells=3883, MemCells=  47; links=406; clusterC=0,38; avg_link_aff=0,58, dangling=62
STAT[ 5]: freeABCells=  753, BCells=3360, MemCells=  49; links=426; clusterC=0,36; avg_link_aff=0,57, dangling=55
STAT[ 6]: freeABCells=  627, BCells=3394, MemCells=  52; links=458; clusterC=0,35; avg_link_aff=0,57, dangling=45
STAT[ 7]: freeABCells=  694, BCells=3419, MemCells=  55; links=524; clusterC=0,35; avg_link_aff=0,57, dangling=39
STAT[ 8]: freeABCells=  677, BCells=3460, MemCells=  54; links=500; clusterC=0,35; avg_link_aff=0,57, dangling=36
STAT[ 9]: freeABCells=  727, BCells=3480, MemCells=  55; links=536; clusterC=0,36; avg_link_aff=0,57, dangling=34
STAT[10]: freeABCells=  727, BCells=3492, MemCells=  56; links=557; clusterC=0,36; avg_link_aff=0,58, dangling=32
STAT[11]: freeABCells=  722, BCells=3517, MemCells=  57; links=569; clusterC=0,36; avg_link_aff=0,58, dangling=21
STAT[12]: freeABCells=  693, BCells=3510, MemCells=  57; links=572; clusterC=0,36; avg_link_aff=0,58, dangling=19
STAT[13]: freeABCells=  714, BCells=3530, MemCells=  57; links=582; clusterC=0,36; avg_link_aff=0,58, dangling=15
STAT[14]: freeABCells=  723, BCells=3558, MemCells=  55; links=535; clusterC=0,36; avg_link_aff=0,58, dangling=12
STAT[15]: freeABCells=  723, BCells=3555, MemCells=  55; links=550; clusterC=0,37; avg_link_aff=0,58, dangling=11
STAT[16]: freeABCells=  743, BCells=3558, MemCells=  55; links=538; clusterC=0,36; avg_link_aff=0,58, dangling=11
STAT[17]: freeABCells=  728, BCells=3563, MemCells=  53; links=510; clusterC=0,37; avg_link_aff=0,58, dangling=10
STAT[18]: freeABCells=  642, BCells=3564, MemCells=  54; links=554; clusterC=0,39; avg_link_aff=0,58, dangling=7
STAT[19]: freeABCells=  672, BCells=3571, MemCells=  54; links=538; clusterC=0,38; avg_link_aff=0,58, dangling=7
STAT[20]: freeABCells=  669, BCells=3582, MemCells=  53; links=527; clusterC=0,38; avg_link_aff=0,58, dangling=7
STAT[21]: freeABCells=  622, BCells=3580, MemCells=  53; links=519; clusterC=0,38; avg_link_aff=0,58, dangling=6
STAT[22]: freeABCells=  659, BCells=3580, MemCells=  54; links=556; clusterC=0,39; avg_link_aff=0,58, dangling=6
STAT[23]: freeABCells=  621, BCells=3590, MemCells=  52; links=513; clusterC=0,39; avg_link_aff=0,58, dangling=4
STAT[24]: freeABCells=  616, BCells=3594, MemCells=  52; links=514; clusterC=0,39; avg_link_aff=0,58, dangling=4
STAT[25]: freeABCells=  672, BCells=3605, MemCells=  52; links=514; clusterC=0,39; avg_link_aff=0,58, dangling=2
STAT[26]: freeABCells=  594, BCells=3614, MemCells=  52; links=524; clusterC=0,40; avg_link_aff=0,58, dangling=2
STAT[27]: freeABCells=  550, BCells=3619, MemCells=  52; links=522; clusterC=0,39; avg_link_aff=0,58, dangling=2
STAT[28]: freeABCells=  740, BCells=3627, MemCells=  52; links=525; clusterC=0,40; avg_link_aff=0,58, dangling=2
STAT[29]: freeABCells=  725, BCells=3631, MemCells=  52; links=508; clusterC=0,38; avg_link_aff=0,58, dangling=1
STAT[30]: freeABCells=  658, BCells=3634, MemCells=  52; links=503; clusterC=0,38; avg_link_aff=0,58, dangling=1
STAT[31]: freeABCells=  681, BCells=3634, MemCells=  53; links=539; clusterC=0,39; avg_link_aff=0,58, dangling=1
STAT[32]: freeABCells=  713, BCells=3636, MemCells=  53; links=552; clusterC=0,40; avg_link_aff=0,58, dangling=1
STAT[33]: freeABCells=  623, BCells=3639, MemCells=  53; links=527; clusterC=0,38; avg_link_aff=0,58, dangling=1
STAT[34]: freeABCells=  675, BCells=3642, MemCells=  53; links=545; clusterC=0,40; avg_link_aff=0,58, dangling=1
STAT[35]: freeABCells=  698, BCells=3642, MemCells=  53; links=538; clusterC=0,39; avg_link_aff=0,58, dangling=1
STAT[36]: freeABCells=  729, BCells=3640, MemCells=  53; links=542; clusterC=0,39; avg_link_aff=0,58, dangling=0
  [FINAL]: avg_affinity=0,78;
u1:
MARIA_CLUSTER_00: MemCells=3, Users=73, avg=0,77, rates=426
MARIA_CLUSTER_01: MemCells=10, Users=102, avg=0,79, rates=246
MARIA_CLUSTER_02: MemCells=17, Users=398, avg=0,78, rates=308
MARIA_CLUSTER_03: MemCells=9, Users=93, avg=0,79, rates=215
MARIA_CLUSTER_04: MemCells=4, Users=66, avg=0,79, rates=313
MARIA_CLUSTER_05: MemCells=8, Users=104, avg=0,80, rates=357
MARIA_CLUSTER_06: MemCells=2, Users=33, avg=0,78, rates=405
MARIA_CLUSTER_07: MemCells=3, Users=32, avg=0,79, rates=300
MARIA_CLUSTER_08: MemCells=7, Users=42, avg=0,85, rates=300
u3:
MARIA_CLUSTER_00: MemCells=14, Users=174, avg=0,80, rates=281
MARIA_CLUSTER_01: MemCells=12, Users=207, avg=0,78, rates=376
MARIA_CLUSTER_02: MemCells=14, Users=153, avg=0,80, rates=248
MARIA_CLUSTER_03: MemCells=12, Users=157, avg=0,81, rates=178
MARIA_CLUSTER_04: MemCells=7, Users=136, avg=0,79, rates=291
MARIA_CLUSTER_05: MemCells=10, Users=89, avg=0,81, rates=379
MARIA_CLUSTER_06: MemCells=2, Users=27, avg=0,81, rates=678
''mit Variante 2:''
MARIA_CLUSTER_00: MemCells=4, Users=104, avg=0,78, rates=350
MARIA_CLUSTER_01: MemCells=6, Users=100, avg=0,77, rates=304
MARIA_CLUSTER_02: MemCells=4, Users=47, avg=0,76, rates=372
MARIA_CLUSTER_03: MemCells=21, Users=396, avg=0,79, rates=284
MARIA_CLUSTER_04: MemCells=2, Users=57, avg=0,78, rates=369
MARIA_CLUSTER_05: MemCells=7, Users=133, avg=0,77, rates=282
MARIA_CLUSTER_06: MemCells=2, Users=11, avg=0,85, rates=591
MARIA_CLUSTER_07: MemCells=3, Users=69, avg=0,76, rates=296
MARIA_CLUSTER_08: MemCells=2, Users=26, avg=0,83, rates=536
u3, variante 2, clone_factor=12, presentation_percentage=30
MARIA_CLUSTER_00: MemCells=9, Users=156, avg=0,76, rates=397
MARIA_CLUSTER_01: MemCells=25, Users=455, avg=0,78, rates=267
MARIA_CLUSTER_02: MemCells=2, Users=32, avg=0,76, rates=396
MARIA_CLUSTER_03: MemCells=6, Users=111, avg=0,79, rates=306
MARIA_CLUSTER_04: MemCells=7, Users=133, avg=0,80, rates=294
MARIA_CLUSTER_05: MemCells=2, Users=28, avg=0,78, rates=431
MARIA_CLUSTER_06: MemCells=2, Users=28, avg=0,77, rates=392
==== 1M ====
* predictcount: 1.797.247, Betriebsart 1: 1.852.146
* cardinality:  88.056, B1: 87.853
* runtime: Betriebsart 2: 8.44 min ; Betriebsart 1: 213 min
* accuracy: 15.22, B2: 15.17
MARIA_CLUSTER_00: MemCells=3, Users=53, avg=0,93, rates=370
MARIA_CLUSTER_01: MemCells=12, Users=1261, avg=0,78, rates=408
MARIA_CLUSTER_02: MemCells=16, Users=727, avg=0,79, rates=139
MARIA_CLUSTER_03: MemCells=8, Users=659, avg=0,78, rates=608
MARIA_CLUSTER_04: MemCells=7, Users=741, avg=0,78, rates=349
MARIA_CLUSTER_05: MemCells=8, Users=425, avg=0,78, rates=285
MARIA_CLUSTER_06: MemCells=3, Users=162, avg=0,79, rates=637
MARIA_CLUSTER_07: MemCells=5, Users=442, avg=0,78, rates=325
MARIA_CLUSTER_08: MemCells=8, Users=1104, avg=0,77, rates=234
MARIA_CLUSTER_09: MemCells=4, Users=304, avg=0,77, rates=372
MARIA_CLUSTER_10: MemCells=6, Users=162, avg=0,85, rates=802
= Architektur =
= Architektur =
== Server ==
== Server ==
Server Dienste werden in Form eines Clusters zur Verfügung gestellt.  
Server Dienste werden in Form eines Clusters zur Verfügung gestellt.  
Auf Server, der als Cluster-Member vorgesehen ist, laufen ein oder mehrere Instanzen der Applikation in einem Applikationsserver, die Kommunikation zwischen den Member-Knoten erfolgt mit Messaging. Eine Instanz der Applikation wird im weitern als Member-Knoten bezeichnet.
Auf Servern die als Clusterknoten vorgesehen sind laufen ein oder mehrere Instanzen der Applikation in einem Applikationsserver. Die Kommunikation zwischen den einzelnen Instanzen der Applikation erfolgt mit Messaging.
 
Jeder Member-Knoten ist hinsichtlich Konfiguration ident. Der einzige Unterschied ist die ID des Member-Knotens, die aus Hostname und einer Zufallszahl, für den Fall dass mehrere Instanzen auf einem physischen Server laufen, generiert wird.  


Auf genau einem der Member-Knoten läuft eine Koordinator Komponente (Singleton).
Jeder Clusterknoten ist hinsichtlich Konfiguration ident. Der einzige Unterschied ist die ID jeder Instanz, die aus Hostname und einer Zufallszahl, für den Fall dass mehrere Instanzen auf einem physischen Server laufen, generiert wird.  


Jeder Member-Knoten aktualisiert in regelmässigen Abständen die [[#Status-Map|Statusmap]]
Auf genau einer Instanz läuft eine Koordinator Komponente (Singleton).
Auf jeder Instanz wird in regelmäßigen Abständen die [[#Status-Map|Statusmap]] aktualisiert.


=== Applikationsserver ===
=== Applikationsserver ===
Als Applikationsserver kommt [http://www.jboss.org/as7 JBoss AS7] in der aktuellen Version zum Einsatz.
Glassfish + OpenMQ
 
JBoss' integrierte Cluster-Fähigkeit wird nicht verwendet. Ein Grund hierfür ist, dass derzeit noch keine Dokumentation für die aktuelle Version vorliegt. Ausserdem ist die Applikation dadruch nicht an JBoss als Applikationsserver gebunden, es ist lediglich ein Messaging Provider erforderlich.
 
Als Messaging System kommt [http://hornetq.sourceforge.net/ HornetQ] zum Einsatz. HornetQ lässt sich nahtlos in JBoss integrieren, bzw. ist bereits in manchen Versionen integriert.
HornetQ Server werden im Cluster Modus betrieben, somit wird einerseits Ausfallsicherheit, andererseits Skalierbarkeit gewährleistet.


=== Datenbank ===
=== Datenbank ===
Als Datenbank kommt [http://neo4j.org/ neo4j] in der Enterprise Edition zum Einsatz. Diese Version ermöglicht es, neo4j Instanzen als Cluster zu betreiben. Neo4j benötigt dafür laufende [http://zookeeper.apache.org/ Zookeeper] Instanzen.
Als Datenbank kommt [http://neo4j.org/ neo4j] in der Enterprise Edition zum Einsatz. Diese Version ermöglicht es, neo4j Instanzen als Cluster zu betreiben. Neo4j benötigt dafür laufende [http://zookeeper.apache.org/ Zookeeper] Instanzen.
Lesevorgänge können auf allen Instanzen ausgeführt werden. Bei Schreibvorgängen werden Daten zuerst auf einem Master gespeichert. Sobald auf einer Slave Instanz ein Schreibvorgang stattfindet, werden die Daten mit dem Master abgeglichen. Das Konsistenzmodell ist also in diesem Fall Eventually Consistent.


==== Sharding ====
Eine Datenbank in [http://docs.neo4j.org/chunked/milestone/capabilities-capacity.html neo4j] kann 32 Milliarden Nodes, 32 Milliarden Relations und 64 Milliarden Properties umfassen.
Eine Datenbank in [http://docs.neo4j.org/chunked/milestone/capabilities-capacity.html neo4j] kann 32 Milliarden Nodes, 32 Milliarden Relations und 64 Milliarden Properties umfassen.


Das bedeutet für den Fall dass jedes Item allen anderen Item in einer Beziehung steht eine maximale Obergrenze von ca. 250.000 Items.
Das bedeutet für den Fall dass jedes Item allen anderen Item in einer Beziehung steht eine maximale Obergrenze von ca. 250.000 Items.


Partitionierung der Daten (Sharding) wäre daher erforderlich, wird aber von den meisten Graphdatenbanken nicht unterstützt.


Daten der unterschiedlichen Domänen werden daher in jeweils eigenen Datenbanken gespeichert.  
Partitionierung der Daten (Sharding) wäre daher erforderlich, wird aber von den meisten Graphdatenbanken, so auch von neo4j, nicht unterstützt.
 


Nachteil dabei ist dass es nicht mehr ohne weiteres möglich ist, Domän-Übergreifende Beziehungen festzustellen.
Ein weiterer Aspekt ist Performance: Neo4j versucht Graphen soweit wie möglich im Cache zu halten. Lesevorgänge von Daten die sich im Cache befinden sind extrem schnell.
Sobald eine Datenbank zu groß wird, können sie nicht mehr zur Gänze im Cache gehalten werden, worunter die Lese-Performance leidet.
Jim Webber schlägt als Lösung hier das Pattern [http://jim.webber.name/2011/02/23/abe72f61-27fb-4c1b-8ce1-d0db7583497b.aspx Cache Sharding] vor. Statt Sharding wird hier ein Consistent Routing implementiert - Zugriffe auf gleiche Datensätze werden immer auf dieselbe Serverinstanz geroutet. Jim Webber schlägt vor Abgrenzungen domän-spezifisch zu implementieren.


Pro Datenbank werden die Graphen eines oder mehrerer Mandanten gespeichert,
wobei der Knoten, welcher den Mandaten bezeichnet, die Quelle ist.


TODO: Routing
Um beide Aspekte zu berücksichtigen, werden Daten pro Mandaten (=Domäne) in unterschiedlichen Datenbanken gespeichert, bzw. Daten von wenigen Mandaten in einer Datenbank zusammengefasst.
Datenzugriffe werden pro Mandaten an immer dieselben zugeordneten Applikationsinstanzen geroutet. Dies zu gewährleisten ist Aufgabe des Koordinators.
 
 
Nachteil dieser Lösung ist dass es nicht mehr ohne weiteres möglich ist, Domän-übergreifende Beziehungen festzustellen.
 


== Client ==
== Client ==
Zeile 55: Zeile 419:
* '''Item-Merkmal hinzufügen''': Ein Merkmal, z.B. ein Schlagwort oder ein Wortvektor wird hinzugefügt
* '''Item-Merkmal hinzufügen''': Ein Merkmal, z.B. ein Schlagwort oder ein Wortvektor wird hinzugefügt
* '''Recommendations für User abfragen''': Das Recommender System liefert dem Client eine Liste mit Namen oder IDs von Items
* '''Recommendations für User abfragen''': Das Recommender System liefert dem Client eine Liste mit Namen oder IDs von Items


= Design =
= Design =
== Datenstruktur ==
== Datenbanken und Datenstruktur ==
=== Datenbanken der Mandaten ===
=== Datenbanken der Mandaten ===
User, Items und deren Beziehungen werden pro Mandaten in jeweils einer Datenbank gespeichert.  
User, Items und deren Beziehungen werden pro Mandaten in jeweils einer Datenbank gespeichert.  
Zeile 65: Zeile 428:
Diese Datenbank enthält folgende Knoten-Arten:
Diese Datenbank enthält folgende Knoten-Arten:


* Mandant: Repräsentiert eine Mandanten, hat Kanten zu Item, User und Profil-Knoten
* Mandant: Repräsentiert einen Mandanten, hat Kanten zu Item und User-Knoten
[[Datei:Db mandant.png|thumb|250px|left]]
[[Datei:Db mandant.png|thumb|250px|left]]
<br style="clear:both" />
<br style="clear:both" />
* Item:  
* Item:  
** similiar_to Kanten zu anderen Items (diese Kanten sind als ungerichtete Kanten zu verstehen)
** ''similiar_to'' Kanten zu anderen Items (diese Kanten sind als ungerichtete Kanten zu verstehen)
** Profil-Kanten zu verscheidenen Profile-Knoten, wie Wordverktor-Knoten oder Keyword-Knoten
** Profil-Kanten zu verscheidenen Profile-Knoten, wie Wordverktor-Knoten oder Keyword-Knoten
[[Datei:Db nodetype item.png|thumb|250px|left]]
[[Datei:Db nodetype item.png|thumb|250px|left]]
Zeile 78: Zeile 441:
** ''rate'' Kanten zu Items. Diese Kanten besitzen eine ''weight'' Property, die den Wert des Ratings in Prozent enthält.
** ''rate'' Kanten zu Items. Diese Kanten besitzen eine ''weight'' Property, die den Wert des Ratings in Prozent enthält.
** ''predict'' Kanten zu Items. Diese Kanten haben mehrere Properties:
** ''predict'' Kanten zu Items. Diese Kanten haben mehrere Properties:
*** ''weight'': Angenommener Rating Wert des Users für dieses Item
*** ''weight'': Ermittelter Rating Wert des Users für dieses Item
*** ''config_version'': Versionsnummer der verwendeten Konfiguration (siehe [[#Konfigurations Datenbank|Konfigurations Datenbank]])
*** ''conf_vers'': Versionsnummer der verwendeten Konfiguration (siehe [[#Konfigurations Datenbank|Konfigurations Datenbank]])
*** Methoden-Namen: Verwendete Methode, mit zugehörigem Vorhersagewert
*** Methoden: Verwendete Methode mit zugehörigen Vorhersage-werten
[[Datei:Db nodetype user.png|thumb|250px|left]]
[[Datei:Db nodetype user.png|thumb|250px|left]]
<br style="clear:both" />
<br style="clear:both" />


=== Konfigurations Datenbank ===
=== Datenbank für Konfigurations- und Statusinformationen ===
[[Datei:Config db.png|thumb|400px|right]]
[[Datei:Config db.png|thumb|400px|right|Konfigurations-Graph]]


In der Konfigurationsdatenbank befindet sich:
Der Graph, der Daten bezüglich Konfiguration enthält besteht aus:


* Datenbanken: Welche Datenbanken gibt es, und welchen Mandanten sind sie zugeordnet
* Datenbanken: Welche Datenbanken gibt es, und welchen Mandanten sind sie zugeordnet
Zeile 108: Zeile 471:
<br style="clear:both" />
<br style="clear:both" />


=== Status-Map ===
==== Status-Map ====
Jeder Knoten ist als Graph-Node in der Statusmap vertreten.
[[Datei:Statusmap.png|thumb|400px|right|Status-Map]]
Jeder Knoten aktualisiert in regelmässigen Abständen die ''Heartbeat'' Property seines entsprechenden Nodes in der Statusmap.
Jede Instanz der Applikation ist in der [[#Status-Map|Status-Map]] vertreten und aktualisiert in regelmäßigen Abständen die ''Heartbeat'' Property des entsprechenden ''Member''-Knotens.
Dieser Schreibvorgang bewirkt eine synchronisation mit dem Master, wodurch die Statusmap unmittelbar nach jedem Schreibvorgang konsistent ist.
Dieser Schreibvorgang bewirkt eine Synchronisation mit dem Master, wodurch die [[#Status-Map|Status-Map]] unmittelbar nach jedem Schreibvorgang konsistent ist.


Je nach Rolle erfolgt zusätzlich zum Update der Statusmap ein zusätzlicher Schritt:
Je nach Rolle erfolgt zusätzlich zum Update der [[#Status-Map|Status-Map]] ein zusätzlicher Schritt:
* der Koordinator prüft ob eine ''Heartbeat'' Property eines Kontens nicht aktualisiert wurde. In diesem Fall gilt der Knoten als ausgefallen, und wird aus der Statusmap entfernt. Zugeordnete Mandanten und Jobs werden neu verteilt.
* der Koordinator prüft ob eine ''Heartbeat'' Property eines Kontens nicht aktualisiert wurde. In diesem Fall gilt der Knoten als ausgefallen, und wird aus der [[#Status-Map|Status-Map]] entfernt. Zugeordnete Mandanten und Jobs werden neu verteilt.
* jeder Knoten prüft ob der Koordinator dessen ''Heartbeat'' Property aktualisiert hat. Ist dies nicht der Fall, gilt der Koordinator als ausgefallen, und der Knoten startet eine [[#Election|Election]].
* jeder Knoten prüft ob der Koordinator dessen ''Heartbeat'' Property aktualisiert hat. Ist dies nicht der Fall, gilt der Koordinator als ausgefallen, und der Knoten startet eine [[#Election|Election]].
In der [[#Status-Map|Status-Map]] sind auch alle aktive Mandaten-Knoten enthalten. Mittels Consistent-Hashing Algorithmus sind Mandanten ein oder mehreren Applikationsinstanzen zugeordnet. Diese Zuordnung steuert das [[#Message-Routing|Message Routing]]. Betreffende Instanzen erhalten Rating-Requests und Jobs, die den jeweiligen Mandaten betreffen.
Diese Jobs, sowie allfällige Abhängigkeiten zu anderen Jobs sind ebenfalls in der [[#Status-Map|Status-Map]] enthalten.
<br style="clear:both" />


== Kommunikation ==
== Kommunikation ==
Zeile 121: Zeile 488:
Client kommunizieren mit dem Server über ein Restful Webservice.
Client kommunizieren mit dem Server über ein Restful Webservice.


Der Vorgang, am Beispiel Rate-Request läuft wie folgt ab: Der Client übermittelt ein Rating an einen der Server des Clusters. Der Antwortende Member-Knoten generiert eine Nachricht und sendet diese an eine konfigurierte Queue, die Kommunikation zwischen Cleint und Server wird daraufhin beendet.
Der Vorgang, am Beispiel Rate-Request läuft wie folgt ab: Der Client übermittelt ein Rating an einen Clusterknoten. Der antwortende Clusterknoten generiert eine Nachricht und sendet diese an eine konfigurierte Queue, die Kommunikation zwischen Client und Server wird daraufhin beendet.


=== Messaging ===
=== Messaging ===


Kommunikation findet grösstenteils über Messaging statt.
Kommunikation findet größtenteils über Messaging statt.
Vorteile sind:
Vorteile sind:
* Einfachere Kommunikaton: Jeder Member-Knoten ist hinsichtlich Konfiguration ident. Anstatt wissen zu müssen wie andere Knoten kontaktiert werden müssen, beschränkt sich bei Messaging das erforderliche Wissen drauf, an welche Queues oder Topics versendet werden muss.
* Einfachere Kommunikaton: Jeder Clusterknoten ist hinsichtlich Konfiguration ident. Anstatt wissen zu müssen wie andere Knoten kontaktiert werden müssen, beschränkt sich bei Messaging das erforderliche Wissen drauf, an welche Queues oder Topics versendet werden muss.
* Skalierbarkeit: Es ist nicht erforderlich dass jeder Member-Knoten an jeden anderen Member-Knoten Nachrichten versenden kann. Es muss auch nicht jedem Member-Knoten bekannt sein welche anderen Knoten verfügbar sind.
* Skalierbarkeit: Es ist nicht erforderlich dass jeder Clusterknoten an jeden anderen Clusterknoten Nachrichten versenden kann. Es muss auch nicht jedem Clusterknoten bekannt sein welche anderen Clusterknoten verfügbar sind.
* Entkoppelung von Cleint und  Server, und Entkoppelung der Member-Knoten, asynchroner Nachrichtenaustausch
* Entkoppelung von Client und  Server, und Entkoppelung der Clusterknoten, asynchroner Nachrichtenaustausch
* Einfachere Parallelverarbeitung: Pro Knoten sind mehrere Instanzen vorhanden, die Nachrichten erhalten und gegebenenfalls parallel verarbeiten können
* Einfachere Parallelverarbeitung: In jedem Clusterknoten können mehrere Instanzen Nachrichten erhalten und gegebenenfalls parallel verarbeiten
 
Es gibt außer dem [[#Koordinator|Koordinator]] zwei Arten von Message Consumer:
* Empfänger von [[#Rate-Jobs|Rate-Jobs]]: Der entsprechende ''User'' und ''Item'' Knoten wird in der entsprechenden Datenbank gesucht, Rating Kante zwischen ''User'' und ''Item'' gesetzt und gewichtet, und daraufhin eine Nachricht an die [[#Scheduler-Queue|Scheduler Queue]], deren Empfänger der [[#Koordinator|Koordinator]] ist, gesendet.
* Empfänger der [[#Job-Queue|Job Queue]]: In der [[#Status-Map|Status Map]] wird der entsprechende Job anhand der sich in der Nachricht befindlichen Job-ID nachgeschlagen. Daraufhin wird der Job an eine Instanz delegiert, die die entsprechende Methode verarbeitet, und daraufhin der Job in der [[#Status-Map|Status Map]] gelöscht. In der [[#Status-Map|Status Map]] können auch Abhängigkeiten notiert sein, beispielsweise kann ein Job erst nach Beendigung eines anderen Jobs gestartet werden. In diesem Fall wird nach einiger Zeit erneut geprüft ob der Job gestartet werden kann. Ist dies nicht der Fall wird die Nachricht zurückgewiesen, was entweder zu eine neuerlichen Zustellversuch führt, oder die Nachricht wird als nicht zustellbar betrachtet und demgemäß an die [[#Dead Letter Queue|Queue für nicht zustellbare Nachrichten]] zugestellt.


Es gibt ausser dem [[#Koordinator|Koordinator]] zwei Arten von Message Consumer:
* Empfänger von [[#Rate-Jobs|Rate-Jobs]]: Der entsprechde User und Item Node wird in der entsprechenden Datenbank gesucht, Rating Kante zwischen User und Item gesetzt und gewichtet, und daraufhin eine Nachricht an die [[#Scheduler-Queue|Scheduler Queue]], deren Emfpänger der [[#Koordinator|Koordinator]] ist, gesendtet.
* Emfänger der [[#Job-Queue|Job Queue]]: In der [[#Status-Map|Status Map]] wird der entsprechende Job anhand der sich in der Nachricht befindlichen Job-ID nachgeschlagen. Daraufhin wird der Job an eine Instanz der jeweilgen Methodenverabeitung delegiert, und daraufhin der Job in der [[#Status-Map|Status Map]] gelöscht. In der [[#Status-Map|Status Map]] könne auch Abhängigkeiten notiert sein, beispielsweise kann ein Job erst nach Beendigung eines anderen Jobs gestartert werden. In diesem Fall wird nach einiger Zeit erneut geprüft ob der Job gestartet werden kann. Ist dies nicht der Fall wird die Nachricht zurückgewiesen, was entweder zu eine neuerlichen Zustellversuch führt, oder die Nachricht wird als nicht zustellbar betrachtet und demgemäss an die [[#Dead Letter Queue|Queue für nicht zustellbare Nachrichten]] zugestellt.


==== Queues und Topics ====
==== Queues und Topics ====
[[Datei:Recommender_queues.png|right]]
===== Rate-Requests =====
===== Rate-Requests =====
An Queue werden von Clients gemeldete Ratings übermittelt.
An diese Queue werden von Clients gemeldete Ratings übermittelt.
Relevante Informationen sind hier: Mandant, User, Item, Rating als Prozentwert (bei Ratingmöglichkeit von 1 bis 7 und Wahl 3 würde dies 42.86% entsprechen).
Relevante Informationen sind hier: Mandant, User, Item, Rating als Prozentwert (bei Ratingmöglichkeit von 1 bis 7 und Wahl 3 würde dies 42.86% entsprechen).
Consumer der Queue ist der Koordinator.
Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.
[[Datei:Recommender_queues.png|right]]
 
===== Item-Requests =====
An diese Queue werden von Clients gemeldete Items übermittelt.
Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.
 
===== User-Requests =====
An diese Queue werden von Clients gemeldete User übermittelt.
Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.
 
===== Profile-Requests =====
An diese Queue werden von Clients gemeldete Profile und Änderungen an Profilen übermittelt.
Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.


===== Rate-Jobs =====
===== Recommendation-Requests =====
An diese Queue werden vom Koordinator Nachrichten der Rate-Request Queue gesendet, ergänzt mit Filter Information, die einem de-facto Routing dienen (siehe oben).
An diese Queue werden Recommendation Anforderungen von Clients übermittelt.
Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.


===== Scheduler-Queue =====
===== Scheduler-Queue =====
Zeile 151: Zeile 533:


===== Job-Queue =====
===== Job-Queue =====
An diese Queue sendet der Koordinator Nachrichten mit Job IDs. Nachrichten sind mit Filter Informationen versehen, daher erhalten Consumer nur Nachrichten anhand enstprechnder Message Selektoren. Consumer schlagen Jobs in der Status-Map nach, und verarbeiten diese.
An diese Queue sendet der Koordinator Nachrichten mit Job IDs. Nachrichten sind mit Filter Informationen versehen, daher erhalten Consumer nur Nachrichten anhand enstprechender Message Selektoren. Consumer schlagen Jobs in der Status-Map nach, und verarbeiten diese.


===== Dead Letter Queue =====
===== Dead Letter Queue =====
An diese Queue stellt der Messaging Provider nicht zustellbare Nachrichten zu.  
An diese Queue stellt der Messaging Provider nicht zustellbare Nachrichten zu.  
Consumer dieser Queue ist der Koordinator, der enstprechend der Nachricht weitere Aktionen setzt, so werden beispielsweise Nachrichten mit Job IDs erneut an die Job Queue gesendet.
Consumer dieser Queue ist der Koordinator, der entsprechend der Nachricht weitere Aktionen setzt, so werden beispielsweise Nachrichten mit Job IDs erneut an die Job Queue gesendet.
 
=== Message Routing ===
 
Anhand der [[#Status-Map|Statusmap]] werden mittels [http://en.wikipedia.org/wiki/Consistent_hashing Consistent Hashing Algorithmus] jedem Clusterknoten zu betreuende Mandaten zugeteilt.
Hintergrund dieser Zuteilung ist die [[#Sharding|fehlende Sharding Möglichkeit]] bei Neo4j.
Die Routing Funktionalität des Cache Sharding Patterns wird durch Messaging implementiert. Der Message Producer versieht Nachrichten mit Filter Information, bevor eine Zustellung an eine Queue erfolgt. Der Consumer verwendet Message Selektoren um Nachrichten zu filtern.
 
Clusterknoten erhalten mittels gesetztem Message Selektor ausschließlich für sie bestimmte Nachrichten.
Es ist Aufgabe des [[#Koordinator|Koordinators]], die entsprechende Header Property bei Nachrichten entsprechend zu setzen, wobei die [[#Status-Map|Statusmap]] vor dem Setzen der Property konsultiert wird, um ausgefallene Clusterknoten, neue hinzugekommene Clusterknoten, neue Mandanten, etc. berücksichtigen zu können.


=== Koordinator ===
=== Koordinator ===


Der Koordinator startet folgende Dienste:
Der Koordinator startet folgende Dienste:
* Rating Scheduler
* Workgroup Allocator
* Job Scheduler
* Job Dispatcher
* Message Re-Dispatcher


Wenn ein Koordinator feststellt dass er nicht länger Koordinator ist, beendet er diese Dienste.
Wenn ein Koordinator feststellt dass er nicht länger Koordinator ist, beendet er diese Dienste.


Die Aufgabe beider Schedulern ist das Verteilen, bzw. das Routen von Nachrichten, die Aufgaben für andere Member Nodes beinhalten.
Die Aufgabe dieser Dienste ist das Verteilen, bzw. das Routen von Nachrichten, die Aufgaben für andere Clusterknoten beinhalten.


Anhand der Statusmap werden mittels [http://en.wikipedia.org/wiki/Consistent_hashing Consistent Hashing Algorithmus] jedem Member-Knoten zu betreuende Mandaten zugeteilt.
Für nicht zustellbare Nachrichten, falls beispielsweise ein Clusterknoten ausgefallen ist nachdem der Koordinator eine Nachricht für diesen erstellt hat, ist eine eigene Queue vorgesehen.  
Hintergrund dieser Zuteilung ist die fehlende Sharding Möglichkeit (siehe [[#Routing]]) bei gängigen Graphdatenbanken.
 
Member-Knoten erhalten mittels gesetzem Message Selektor ausschliesslich für sie bestimmte Nachrichten.
Es ist Aufgabe des Koordinators, die entsprechende Header Property bei Nachrichten entsprechend zu setzen, wobei die Status-Map vor dem Setzen der Property konsultiert wird, um ausgefallene Member-Knoten, neue hinzugekommene Member-Knoten, neue Mandanten, etc. berücksichten zu können.
 
Für nicht zustellbare Nachrichten, falls beispielsweise ein Member-Knoten ausgefallen ist nachdem der Koordinator eine Nachricht für diesen erstellt hat, ist eine eigene Queue vorgesehen.  
Der Koordinator verteilt Nachrichten aus dieser Queue erneut.
Der Koordinator verteilt Nachrichten aus dieser Queue erneut.


==== Rating Scheduler ====
==== Message Re-Dispatcher ====
Der Koordinator liest in einer Endlosschleife Nachrichten aus der [[#Rate-Requests|Rate-Requests]] Queue (und der Queue für nicht zustellbare Nachrichten).
Der Koordinator liest in einer Endlosschleife Nachrichten aus der [[#Rate-Requests|Rate-Requests]] Queue (und der Queue für nicht zustellbare Nachrichten).
Folgend den Informationen aus der Statusmap wird die Rating Nachricht mit einem entsprechendem Filter Information versehen und an die [[#Rate-Jobs|Rate-Jobs]] Queue zugestellt.
Folgend den Informationen aus der Status-Map wird die Rating Nachricht mit einem entsprechendem Filter Information versehen und an die [[#Rate-Jobs|Rate-Jobs]] Queue zugestellt.


==== Job Scheduler ====
==== Job Scheduler ====
Der Koordinator liest in einer Endlosschleife Nachrichten aus der [[#Scheduler-Queue|Scheduler-Queue]] und generiert entsprechden Jobs.
Der Koordinator liest in einer Endlosschleife Nachrichten aus der [[#Scheduler-Queue|Scheduler-Queue]] und generiert entsprechene Jobs.
Beispielsweise werden mehrere Rating-Nachrichten eines Mandaten aus der Scheduler-Queue zusammengefasst und entsprechende Jobs generiert.
Beispielsweise werden mehrere Rating-Nachrichten eines Mandaten aus der Scheduler-Queue zusammengefasst und entsprechende Jobs generiert.


Aufgrund der Information der [[#Dependency-Map|Dependency-Map]] werden aus Ratings, und den für den entsprechnden Mandanten konfigurierten Methoden, mehrere Jobs erzeugt. Diese Jobs können untereinander Abhängigkeiten besitzen. Jobs und deren Abhängigkeiten werden in die Status-Map eingetragen. Danach wird eine Nachricht erzeugt, in der neben der Job-ID auch ein entsprechender Message Selektor gesetzt ist und diese an die  [[#Job-Queue|Job-Queue]] gesendet.
Aufgrund der Information der [[#Dependency-Map|Dependency-Map]] werden aus Ratings, und den für den entsprechenden Mandanten konfigurierten Methoden, mehrere Jobs erzeugt. Diese Jobs können untereinander Abhängigkeiten besitzen. Jobs und deren Abhängigkeiten werden in die Status-Map eingetragen. Danach wird eine Nachricht erzeugt, in der neben der Job-ID auch ein entsprechender Message Selektor gesetzt ist und diese an die  [[#Job-Queue|Job-Queue]] gesendet.


=== Election ===
=== Election ===
Eine Election findet statt, sobald ein Member-Knoten feststellt dass der Koordinator ausgefallen ist.
Eine Election findet statt, sobald ein Member-Knoten feststellt dass der Koordinator ausgefallen ist.


Dies erfolgt indem jeder Member-Konten prüft ob er derjenige mit der niedrigsten ID ist, in diesem Fall wird dieser Knoten neuer Koordinator.
Dies erfolgt indem jeder Clusterknoten prüft ob er derjenige mit der niedrigsten ID ist, in diesem Fall wird dieser Knoten neuer Koordinator.
 
Falls weitere Clusterknoten  mit niedrigeren IDs vorhanden sind wird geprüft ob einer dieser Knoten verfügbar ist. In diesem Fall muss keine weitere Aktion erfolgen.
Sind alle Konten mit niedrigeren IDs ausgefallen, erklärt sich betreffender Clusterknoten  als neuer Koordinator.
 
Ein neuer Koordinator setzt eine Kante vom ''Koordinator''-Knoten zum entsprechenden Clusterknoten .
 
 
 
== Predictions ==
 
Ablauf:
* Clients melden neue Ratings, Items oder Profil Information
* Im Falle von Ratings werden entsprechende Kanten gesetzt
* der Kommunikator erstellt pro Mandant entsprechend den konfigurierten Methoden Jobs
* der Kommunikator erstellt den Prediction-Job, der von den Methoden-Jobs, sowie vorherigen Prediction-Jobs des jeweiligen Mandanten abhängt.
* Worker Instanzen ermitteln Predictions für einzelne Methoden, entsprechend den Jobs
* eine Worker Instanz ermittelt Predictions für Items indem die Predictions der einzelnen Methoden gewichtet werden
 
== Recommendations ==
 
Ablauf:
* ein Client fordert für einen bestimmten User Recommendations an, und kommuniziert hierfür über ein Webservice mit einer Instanz des Systems
* der Request wird via Messaging an den Kommunikator gesendet
* der Kommunikator sendet den Request an einen Clusterknoten, der für Datenzugriffe auf den entsprechenden Mandanten vorgesehen ist
* eine Worker-Instanz ermittelt Recommendations
* die mit dem Client kommunizierende Instanz erhält die Recommendations und liefert diese an den Client
 
== Anwendung von Metriken ==
 
Um die Treffsicherheit des Systems beurteilen zu können werden Metriken eingesetzt.
Vorerst wird ausschließlich Accuracy, das ist der durchschnittliche Fehler (Mean Absolute Error - [http://en.wikipedia.org/wiki/Mean_absolute_error MAE]), also die durchschnittliche Abweichung von Prediction und Rating betrachtet.


Falls weitere Member-Konten mit niedrigeren IDs vorhanden sind wird geprüft ob einer dieser Knoten verfügbar ist. In diesem Fall muss keine weitere Aktion erfolgen.
Diese Abweichungen wird in weiterer Folge benutzt um die Gewichtungen der Methoden anzupassen.
Sind alle Konten mit niedrigeren IDs ausgefallen, erklärt sich betreffender Member-Knoten als neuer Koordinator.  


Ein neuer Koordinator setzt eine Kante vom ''Koordinator''-Node zum entsprechenden Member-Knoten.
Für die Ermittlung der Accuracy erzeugt der Koordinator einen eigenen Job, der von der Beendigung des Prediction Jobs abhängig ist.
Diese Job ermittelt die MAE gesamt sowie die MAE jeder Methode und aktualisiert die ''Accurcy'' Properties in der [[#Konfigurations Datenbank|Konfigurations Datenbank]] der aktuellen ''Configuration''.


Falls das Verhältnis von Ratings zu Predictions einen konfigurierbaren Wert übersteigt, und die Accuracy einer Methode überdurchschnittlich von der Gesamt-Accuracy abweicht, wird eine neue Version der Configuration erstellt, bei der das ''Weight'' Property betreffender Methoden um eine gewissen Betrag gesenkt wird.


[[Kategorie:FH]]
[[Kategorie:FH]]

Aktuelle Version vom 10. Mai 2012, 14:56 Uhr

BUGS

  • mehrere USER-Relationen von Mandant-User-Ref zu User Knoten, User selber gibts aber nur einmal

TODO

  • RECOMMENDED Beziehung mit Datum:
    • um nicht dauernd die gleichen items zu recommenden
    • um periodisch items (auch geratete) recommenden zu können
  • Multiple Rating Dimensions: z.b. zusätzliches TYPE Property bei Rating (e.g. Story, Acting, Special Effects - s. Herlocker p.16)
  • Neuzuteilung Mandant<->Workgroup<->Worker nur bei geänderter Konfiguration, nicht bei jedem check
  • ELECTION: Property des Koordinator-Knotens mit Zufallszahl initialisieren, in Singleton speichern. In regelmäßigen Zeitintervallen überprüft dieser Worker ob die Zufallszahlen übereinstimmen, und beendet gegebenenfalls die Koordinator-Dienste.
  • Eigener SchedulerQListener für jeden Mandanten
  • Concurrency Problem: Enfernen von JobGroup (mach letzter Job)
  • Lösung für Concurrency Probs ab V1.6: putIfAbsent
  • Input-Daten für Methoden: neben alle auch "alle neuen" - timestamp setzen nachdem methode ausgeführt worden ist, und diesen jeweils mit den rating-timestamps der user-nodes vergleichen
  • check bzw. abfrage, ob client einer workgroup idle ist, möglichkeit einen job zu verweigern wenn das nicht der fall ist, andere clients aber idle wären
  • Predictions: eventuell sind von vorherigen läufen noch predictions gesetzt - z.b. wenn bei voherigen lauf bestimmter user berücksichtigt wurde, beim aktuellen aber nicht. beim aggregieren der predictions sollten daher nur jene mit der aktuellen jobgroupID betrachtet werden -> zu prediction also noch jobGroupID mitspeichern!


AIS

  • IDEE: alles auf items betrachtet (statt auf user), also z.b. item-clustering

MARIA

TODO: Parallelisieren: FAB, BC, MEM Layer parallel

Ergebnisse

Movielens

100,000 ratings (1-5) from 943 users on 1682 movies, 
avg commonrate=19
avg pearson korrelation k=0,1220 (normalisiert mit pk<=0 ? 0 : pk)
                        k=0,5382 (normalisiert mit pk+1)/2.0)

Hammock

ml-100k

  • predictcount: 420.000 - 455.913
  • runtime: 7 min Similarity, 22 min Prediction (3min / 4min bei standalone)
  • cardinality: 17439, 17341
  • Accuracy
u1  15.86
u2
u3  15.39
u4  15.42
u5  15.48

ml-1m

  • predictcount: 9.036.721
  • runtime: 146.5 min Similarity, 89 min Prediction
  • cardinality: 159.671
  • accuracy: 14.68

IBCF

  • predictcount: 195912
  • runtime: 0.96 min Similarity, 1.03 min prediction
  • cardinality: 11.421
  • Accuracy
u1  15.52
u2
u3  14.43
u4
u5  15.28

ml-1m

  • predictcount: 2.514.592
  • runtime: 39 min Similarity, 15.11 min prediction
  • cardinality: 139.732
  • accuracy: 13.46

AINE

  • Berechnen der durchschnittlichen Affinität (zwischen allen Usern): 21.9 min
  • AINE Tests:
NAT = 0.8;
bcellcount = 1500;
cloneConstant = 3;
bcellAllocConstant = 10;
consideredEqual = 0.9

ARBs stabil bei ~265, avg sl=0.76, aber nur 0.11 links

  • runtime 2 Gens: 255 min
  • predictions: 307.864
  • cardinality: 12.779
  • accuracy: 17.2

Enhanced AINE

100k

  • runtime: 35-50 sec clustering, predict: 30 min
  • cardinality: 12088
  • predictcount: 234143
u1: 15.94
u2: 15.85
u3: 15.76
u4: 15.94
u5: 16.02

generations=2
nat="0.7"
bcells=800
kclone=5
kbcell=100
equal="0.9"
fixedrate="0.01"
STAT[0/1]: ARBs=92; bcells=0; clonesCrt=0; clonesAdd=0; added=92; removed=0;
STAT[0/2]: a_sl=0,00; a_sAg=0,00; a_links=5,67; a_linkAff=0,75; unconnctd=10; a_repr=0,00; dangl=0
STAT[1/1]: ARBs=28; bcells=2310; clonesCrt=84; clonesAdd=0; added=0; removed=64;
STAT[1/2]: a_sl=0,53; a_sAg=534,15; a_links=5,64; a_linkAff=0,75; unconnctd=0; a_repr=33,68; dangl=0
STAT[2/1]: ARBs=28; bcells=698; clonesCrt=69; clonesAdd=0; added=0; removed=0;
STAT[2/2]: a_sl=0,50; a_sAg=1068,29; a_links=5,64; a_linkAff=0,75; unconnctd=0; a_repr=33,68; dangl=0

u3, nach update:

STAT[0/1]: ARBs=87; bcells=0; clonesCrt=0; clonesAdd=0; added=87; removed=0;
STAT[0/2]: a_sl=0,00; a_sAg=0,00; links=288; clusterCoeff=0,08; a_linkAff=0,75; unconnctd=7; a_repr=0,00; dangl=0
STAT[1/1]: ARBs=38; bcells=2185; clonesCrt=84; clonesAdd=10; added=10; removed=59;
STAT[1/2]: a_sl=0,39; a_sAg=398,76; links=190; clusterCoeff=0,27; a_linkAff=0,77; unconnctd=0; a_repr=24,82; dangl=0
STAT[2/1]: ARBs=31; bcells=952; clonesCrt=0; clonesAdd=0; added=0; removed=7;
STAT[2/2]: a_sl=0,50; a_sAg=545,02; links=128; clusterCoeff=0,28; a_linkAff=0,77; unconnctd=0; a_repr=55,61; dangl=0
STAT[3/1]: ARBs=21; bcells=952; clonesCrt=0; clonesAdd=0; added=9; removed=0;
STAT[3/2]: a_sl=0,29; a_sAg=311,74; links=67; clusterCoeff=0,32; a_linkAff=0,75; unconnctd=0; 
u1
AINE_CLUSTER_01: 4 ARBS; 248 Users; avgAff=0,76
AINE_CLUSTER_02: 5 ARBS; 329 Users; avgAff=0,75
AINE_CLUSTER_03: 5 ARBS; 287 Users; avgAff=0,79
AINE_CLUSTER_04: 6 ARBS; 343 Users; avgAff=0,75
AINE_CLUSTER_05: 4 ARBS; 257 Users; avgAff=0,74
u2
AINE_CLUSTER_01: 4 ARBS; 288 Users; avgAff=0,75
AINE_CLUSTER_02: 4 ARBS; 284 Users; avgAff=0,74
AINE_CLUSTER_03: 2 ARBS; 191 Users; avgAff=0,76
AINE_CLUSTER_04:10 ARBS; 491 Users; avgAff=0,75
AINE_CLUSTER_05: 3 ARBS; 188 Users; avgAff=0,75
u3
AINE_CLUSTER_00: 4 ARBS; 497 Users; avgAff=0,76
AINE_CLUSTER_01: 1 ARBS; 155 Users; avgAff=0,75
AINE_CLUSTER_02: 1 ARBS; 71 Users;  avgAff=0,74
AINE_CLUSTER_03: 1 ARBS; 232 Users; avgAff=0,76
AINE_CLUSTER_04: 4 ARBS; 380 Users; avgAff=0,75
AINE_CLUSTER_05: 1 ARBS; 61 Users;  avgAff=0,73


Stabilität

nach 20 Generationen: Anzahl ARBs stabil (~40), nach Merge allerdings nur noch 6 über, nach Clustering: 1 Cluster mit avgAff=0.66

  • predictcount: 224060
  • cardinality: 11881
  • accuracy: 15.65

1m

  • predictcount: 1.858.024
  • cardinality: 90.154
  • runtime: 18.5 min
  • accuracy: 15.11

MARIA

100k

  • predictCount: 233466
  • cardinality: 12124 (- 12797)
  • Laufzeit Variante 1: 2.36 - 3.95 min Clustering, 10.59 Prediction
  • Laufzeit Variante 2: 58 min
  • Accuracy: 16.15
           BA-1    BA-2
u1  0.815  16.3
u2         16.3
u3         16.05   15.99
u4         16.48
u5         16.52
train_always_all="false"
fl_death_threshold=6
bl_death_threshold=6
ml_death_threshold=2
ml_retain_threshold="0.5"
distribute="false"
pk_max_corates=12
presentation_percentage=50
affinity_threshold="0.7"
stimulation_threshold=10
memcell_affinity_threshold="0.8"
connection_threshold="0.52"
mutation_probability="0.02"
clone_factor=6
STAT[ 1]: freeABCells=  289, BCells=1403, MemCells=  30; avg_affinity=0,76; represent= 777; links=187; avg_link_aff=0,58, dangling=166 
STAT[ 2]: freeABCells=  649, BCells=1451, MemCells=  39; avg_affinity=0,77; represent= 838; links=312; avg_link_aff=0,58, dangling=105
STAT[ 3]: freeABCells=  769, BCells=1487, MemCells=  50; avg_affinity=0,77; represent= 886; links=459; avg_link_aff=0,57, dangling=57
STAT[ 4]: freeABCells=  861, BCells=1501, MemCells=  62; avg_affinity=0,77; represent= 913; links=640; avg_link_aff=0,57, dangling=30
STAT[ 5]: freeABCells=  922, BCells= 257, MemCells=  65; avg_affinity=0,77; represent= 920; links=692; avg_link_aff=0,57, dangling=23
STAT[ 6]: freeABCells=  868, BCells= 232, MemCells=  67; avg_affinity=0,77; represent= 930; links=737; avg_link_aff=0,57, dangling=13
STAT[ 7]: freeABCells=  894, BCells= 210, MemCells=  66; avg_affinity=0,77; represent= 934; links=707; avg_link_aff=0,57, dangling=9
STAT[ 8]: freeABCells=  919, BCells= 208, MemCells=  66; avg_affinity=0,77; represent= 940; links=707; avg_link_aff=0,57, dangling=3
STAT[ 9]: freeABCells=  840, BCells= 173, MemCells=  66; avg_affinity=0,77; represent= 941; links=707; avg_link_aff=0,57, dangling=2
STAT[10]: freeABCells=  730, BCells= 145, MemCells=  64; avg_affinity=0,77; represent= 937; links=666; avg_link_aff=0,57, dangling=6
STAT[11]: freeABCells=  619, BCells= 125, MemCells=  63; avg_affinity=0,77; represent= 939; links=644; avg_link_aff=0,57, dangling=4
STAT[12]: freeABCells=  559, BCells= 103, MemCells=  63; avg_affinity=0,77; represent= 941; links=644; avg_link_aff=0,57, dangling=2
STAT[13]: freeABCells=  520, BCells=  96, MemCells=  63; avg_affinity=0,77; represent= 941; links=644; avg_link_aff=0,57, dangling=2
STAT[14]: freeABCells=  485, BCells=  86, MemCells=  63; avg_affinity=0,77; represent= 940; links=643; avg_link_aff=0,57, dangling=3
STAT[15]: freeABCells=  446, BCells=  77, MemCells=  63; avg_affinity=0,77; represent= 941; links=645; avg_link_aff=0,57, dangling=2
STAT[16]: freeABCells=  432, BCells=  71, MemCells=  63; avg_affinity=0,77; represent= 943; links=645; avg_link_aff=0,57, dangling=0
[FINAL]: freeABCells=  432, BCells=  71, MemCells=  63; avg_affinity=0,79; represent= 943; links=645; avg_link_aff=0,57

u3:

STAT[ 1]: freeABCells=  473, BCells= 833, MemCells=  31; links=213; clusterC=0,46; avg_link_aff=0,59, dangling=146
STAT[ 2]: freeABCells=  762, BCells= 877, MemCells=  37; links=281; clusterC=0,42; avg_link_aff=0,59, dangling=89
STAT[ 3]: freeABCells=  876, BCells= 903, MemCells=  50; links=464; clusterC=0,38; avg_link_aff=0,58, dangling=49
STAT[ 4]: freeABCells=  956, BCells= 910, MemCells=  66; links=774; clusterC=0,36; avg_link_aff=0,57, dangling=26
STAT[ 5]: freeABCells=  982, BCells= 226, MemCells=  71; links=893; clusterC=0,36; avg_link_aff=0,57, dangling=11
STAT[ 6]: freeABCells= 1000, BCells= 186, MemCells=  71; links=894; clusterC=0,36; avg_link_aff=0,57, dangling=9
STAT[ 7]: freeABCells=  997, BCells= 169, MemCells=  71; links=891; clusterC=0,36; avg_link_aff=0,57, dangling=5
STAT[ 8]: freeABCells=  997, BCells= 166, MemCells=  71; links=895; clusterC=0,36; avg_link_aff=0,57, dangling=1
STAT[ 9]: freeABCells=  770, BCells= 125, MemCells=  71; links=895; clusterC=0,36; avg_link_aff=0,57, dangling=1
STAT[10]: freeABCells=  534, BCells=  98, MemCells=  71; links=903; clusterC=0,36; avg_link_aff=0,57, dangling=0


mit Variante 2:
STAT[ 1]: freeABCells=  226, BCells=1395, MemCells=  31; links=199; clusterC=0,43; avg_link_aff=0,58, dangling=171
STAT[ 2]: freeABCells=  202, BCells=2163, MemCells=  37; links=274; clusterC=0,41; avg_link_aff=0,58, dangling=119
STAT[ 3]: freeABCells=  263, BCells=2950, MemCells=  41; links=311; clusterC=0,38; avg_link_aff=0,58, dangling=94
STAT[ 4]: freeABCells=  258, BCells=3746, MemCells=  44; links=370; clusterC=0,39; avg_link_aff=0,58, dangling=79
STAT[ 5]: freeABCells=  237, BCells=3302, MemCells=  49; links=437; clusterC=0,37; avg_link_aff=0,57, dangling=61
STAT[ 6]: freeABCells=  205, BCells=3342, MemCells=  52; links=470; clusterC=0,35; avg_link_aff=0,57, dangling=53
STAT[ 7]: freeABCells=  255, BCells=3368, MemCells=  53; links=487; clusterC=0,35; avg_link_aff=0,57, dangling=48
STAT[ 8]: freeABCells=  191, BCells=3419, MemCells=  51; links=437; clusterC=0,34; avg_link_aff=0,58, dangling=46
STAT[ 9]: freeABCells=  195, BCells=3435, MemCells=  60; links=611; clusterC=0,35; avg_link_aff=0,57, dangling=34
STAT[10]: freeABCells=  222, BCells=3444, MemCells=  60; links=604; clusterC=0,34; avg_link_aff=0,57, dangling=33
STAT[11]: freeABCells=  203, BCells=3457, MemCells=  58; links=566; clusterC=0,34; avg_link_aff=0,57, dangling=30
STAT[12]: freeABCells=  197, BCells=3439, MemCells=  58; links=576; clusterC=0,35; avg_link_aff=0,57, dangling=25
STAT[13]: freeABCells=  193, BCells=3446, MemCells=  58; links=560; clusterC=0,34; avg_link_aff=0,57, dangling=23
STAT[14]: freeABCells=  168, BCells=3465, MemCells=  57; links=546; clusterC=0,34; avg_link_aff=0,57, dangling=19
STAT[15]: freeABCells=  225, BCells=3473, MemCells=  56; links=531; clusterC=0,34; avg_link_aff=0,57, dangling=19
STAT[16]: freeABCells=  222, BCells=3482, MemCells=  56; links=533; clusterC=0,35; avg_link_aff=0,57, dangling=16
STAT[17]: freeABCells=  194, BCells=3501, MemCells=  55; links=510; clusterC=0,34; avg_link_aff=0,57, dangling=14
STAT[18]: freeABCells=  233, BCells=3511, MemCells=  55; links=507; clusterC=0,34; avg_link_aff=0,57, dangling=11
STAT[19]: freeABCells=  215, BCells=3528, MemCells=  55; links=525; clusterC=0,35; avg_link_aff=0,57, dangling=9
STAT[20]: freeABCells=  201, BCells=3549, MemCells=  54; links=485; clusterC=0,34; avg_link_aff=0,57, dangling=9
STAT[21]: freeABCells=  195, BCells=3554, MemCells=  54; links=498; clusterC=0,35; avg_link_aff=0,57, dangling=8
STAT[22]: freeABCells=  182, BCells=3558, MemCells=  54; links=489; clusterC=0,34; avg_link_aff=0,57, dangling=6
STAT[23]: freeABCells=  204, BCells=3566, MemCells=  51; links=447; clusterC=0,35; avg_link_aff=0,58, dangling=6
STAT[24]: freeABCells=  197, BCells=3561, MemCells=  51; links=433; clusterC=0,34; avg_link_aff=0,58, dangling=5
STAT[25]: freeABCells=  179, BCells=3568, MemCells=  51; links=446; clusterC=0,35; avg_link_aff=0,58, dangling=4
STAT[26]: freeABCells=  221, BCells=3575, MemCells=  51; links=448; clusterC=0,35; avg_link_aff=0,57, dangling=3
STAT[27]: freeABCells=  201, BCells=3577, MemCells=  51; links=443; clusterC=0,35; avg_link_aff=0,58, dangling=3
STAT[28]: freeABCells=  197, BCells=3584, MemCells=  51; links=441; clusterC=0,35; avg_link_aff=0,57, dangling=3
STAT[29]: freeABCells=  154, BCells=3586, MemCells=  51; links=446; clusterC=0,35; avg_link_aff=0,58, dangling=1
STAT[30]: freeABCells=  241, BCells=3587, MemCells=  51; links=458; clusterC=0,36; avg_link_aff=0,58, dangling=0
 [FINAL]: avg_affinity=0,78;
variante 2, u3, clone_factor=12, presentation_percentage=30:
STAT[ 1]: freeABCells=  658, BCells=1477, MemCells=  33; links=223; clusterC=0,42; avg_link_aff=0,59, dangling=139
STAT[ 2]: freeABCells=  705, BCells=2264, MemCells=  39; links=295; clusterC=0,40; avg_link_aff=0,58, dangling=100
STAT[ 3]: freeABCells=  705, BCells=3068, MemCells=  43; links=351; clusterC=0,39; avg_link_aff=0,58, dangling=78
STAT[ 4]: freeABCells=  717, BCells=3883, MemCells=  47; links=406; clusterC=0,38; avg_link_aff=0,58, dangling=62
STAT[ 5]: freeABCells=  753, BCells=3360, MemCells=  49; links=426; clusterC=0,36; avg_link_aff=0,57, dangling=55
STAT[ 6]: freeABCells=  627, BCells=3394, MemCells=  52; links=458; clusterC=0,35; avg_link_aff=0,57, dangling=45
STAT[ 7]: freeABCells=  694, BCells=3419, MemCells=  55; links=524; clusterC=0,35; avg_link_aff=0,57, dangling=39
STAT[ 8]: freeABCells=  677, BCells=3460, MemCells=  54; links=500; clusterC=0,35; avg_link_aff=0,57, dangling=36
STAT[ 9]: freeABCells=  727, BCells=3480, MemCells=  55; links=536; clusterC=0,36; avg_link_aff=0,57, dangling=34
STAT[10]: freeABCells=  727, BCells=3492, MemCells=  56; links=557; clusterC=0,36; avg_link_aff=0,58, dangling=32
STAT[11]: freeABCells=  722, BCells=3517, MemCells=  57; links=569; clusterC=0,36; avg_link_aff=0,58, dangling=21
STAT[12]: freeABCells=  693, BCells=3510, MemCells=  57; links=572; clusterC=0,36; avg_link_aff=0,58, dangling=19
STAT[13]: freeABCells=  714, BCells=3530, MemCells=  57; links=582; clusterC=0,36; avg_link_aff=0,58, dangling=15
STAT[14]: freeABCells=  723, BCells=3558, MemCells=  55; links=535; clusterC=0,36; avg_link_aff=0,58, dangling=12
STAT[15]: freeABCells=  723, BCells=3555, MemCells=  55; links=550; clusterC=0,37; avg_link_aff=0,58, dangling=11
STAT[16]: freeABCells=  743, BCells=3558, MemCells=  55; links=538; clusterC=0,36; avg_link_aff=0,58, dangling=11
STAT[17]: freeABCells=  728, BCells=3563, MemCells=  53; links=510; clusterC=0,37; avg_link_aff=0,58, dangling=10
STAT[18]: freeABCells=  642, BCells=3564, MemCells=  54; links=554; clusterC=0,39; avg_link_aff=0,58, dangling=7
STAT[19]: freeABCells=  672, BCells=3571, MemCells=  54; links=538; clusterC=0,38; avg_link_aff=0,58, dangling=7
STAT[20]: freeABCells=  669, BCells=3582, MemCells=  53; links=527; clusterC=0,38; avg_link_aff=0,58, dangling=7
STAT[21]: freeABCells=  622, BCells=3580, MemCells=  53; links=519; clusterC=0,38; avg_link_aff=0,58, dangling=6
STAT[22]: freeABCells=  659, BCells=3580, MemCells=  54; links=556; clusterC=0,39; avg_link_aff=0,58, dangling=6
STAT[23]: freeABCells=  621, BCells=3590, MemCells=  52; links=513; clusterC=0,39; avg_link_aff=0,58, dangling=4
STAT[24]: freeABCells=  616, BCells=3594, MemCells=  52; links=514; clusterC=0,39; avg_link_aff=0,58, dangling=4
STAT[25]: freeABCells=  672, BCells=3605, MemCells=  52; links=514; clusterC=0,39; avg_link_aff=0,58, dangling=2
STAT[26]: freeABCells=  594, BCells=3614, MemCells=  52; links=524; clusterC=0,40; avg_link_aff=0,58, dangling=2
STAT[27]: freeABCells=  550, BCells=3619, MemCells=  52; links=522; clusterC=0,39; avg_link_aff=0,58, dangling=2
STAT[28]: freeABCells=  740, BCells=3627, MemCells=  52; links=525; clusterC=0,40; avg_link_aff=0,58, dangling=2
STAT[29]: freeABCells=  725, BCells=3631, MemCells=  52; links=508; clusterC=0,38; avg_link_aff=0,58, dangling=1
STAT[30]: freeABCells=  658, BCells=3634, MemCells=  52; links=503; clusterC=0,38; avg_link_aff=0,58, dangling=1
STAT[31]: freeABCells=  681, BCells=3634, MemCells=  53; links=539; clusterC=0,39; avg_link_aff=0,58, dangling=1
STAT[32]: freeABCells=  713, BCells=3636, MemCells=  53; links=552; clusterC=0,40; avg_link_aff=0,58, dangling=1
STAT[33]: freeABCells=  623, BCells=3639, MemCells=  53; links=527; clusterC=0,38; avg_link_aff=0,58, dangling=1
STAT[34]: freeABCells=  675, BCells=3642, MemCells=  53; links=545; clusterC=0,40; avg_link_aff=0,58, dangling=1
STAT[35]: freeABCells=  698, BCells=3642, MemCells=  53; links=538; clusterC=0,39; avg_link_aff=0,58, dangling=1
STAT[36]: freeABCells=  729, BCells=3640, MemCells=  53; links=542; clusterC=0,39; avg_link_aff=0,58, dangling=0
 [FINAL]: avg_affinity=0,78; 


u1:

MARIA_CLUSTER_00: MemCells=3, Users=73, avg=0,77, rates=426
MARIA_CLUSTER_01: MemCells=10, Users=102, avg=0,79, rates=246
MARIA_CLUSTER_02: MemCells=17, Users=398, avg=0,78, rates=308
MARIA_CLUSTER_03: MemCells=9, Users=93, avg=0,79, rates=215
MARIA_CLUSTER_04: MemCells=4, Users=66, avg=0,79, rates=313
MARIA_CLUSTER_05: MemCells=8, Users=104, avg=0,80, rates=357
MARIA_CLUSTER_06: MemCells=2, Users=33, avg=0,78, rates=405
MARIA_CLUSTER_07: MemCells=3, Users=32, avg=0,79, rates=300
MARIA_CLUSTER_08: MemCells=7, Users=42, avg=0,85, rates=300

u3:

MARIA_CLUSTER_00: MemCells=14, Users=174, avg=0,80, rates=281
MARIA_CLUSTER_01: MemCells=12, Users=207, avg=0,78, rates=376
MARIA_CLUSTER_02: MemCells=14, Users=153, avg=0,80, rates=248
MARIA_CLUSTER_03: MemCells=12, Users=157, avg=0,81, rates=178
MARIA_CLUSTER_04: MemCells=7, Users=136, avg=0,79, rates=291
MARIA_CLUSTER_05: MemCells=10, Users=89, avg=0,81, rates=379
MARIA_CLUSTER_06: MemCells=2, Users=27, avg=0,81, rates=678


mit Variante 2:
MARIA_CLUSTER_00: MemCells=4, Users=104, avg=0,78, rates=350
MARIA_CLUSTER_01: MemCells=6, Users=100, avg=0,77, rates=304
MARIA_CLUSTER_02: MemCells=4, Users=47, avg=0,76, rates=372
MARIA_CLUSTER_03: MemCells=21, Users=396, avg=0,79, rates=284
MARIA_CLUSTER_04: MemCells=2, Users=57, avg=0,78, rates=369
MARIA_CLUSTER_05: MemCells=7, Users=133, avg=0,77, rates=282
MARIA_CLUSTER_06: MemCells=2, Users=11, avg=0,85, rates=591
MARIA_CLUSTER_07: MemCells=3, Users=69, avg=0,76, rates=296
MARIA_CLUSTER_08: MemCells=2, Users=26, avg=0,83, rates=536
u3, variante 2, clone_factor=12, presentation_percentage=30
MARIA_CLUSTER_00: MemCells=9, Users=156, avg=0,76, rates=397
MARIA_CLUSTER_01: MemCells=25, Users=455, avg=0,78, rates=267
MARIA_CLUSTER_02: MemCells=2, Users=32, avg=0,76, rates=396
MARIA_CLUSTER_03: MemCells=6, Users=111, avg=0,79, rates=306
MARIA_CLUSTER_04: MemCells=7, Users=133, avg=0,80, rates=294
MARIA_CLUSTER_05: MemCells=2, Users=28, avg=0,78, rates=431
MARIA_CLUSTER_06: MemCells=2, Users=28, avg=0,77, rates=392

1M

  • predictcount: 1.797.247, Betriebsart 1: 1.852.146
  • cardinality: 88.056, B1: 87.853
  • runtime: Betriebsart 2: 8.44 min ; Betriebsart 1: 213 min
  • accuracy: 15.22, B2: 15.17
MARIA_CLUSTER_00: MemCells=3, Users=53, avg=0,93, rates=370
MARIA_CLUSTER_01: MemCells=12, Users=1261, avg=0,78, rates=408
MARIA_CLUSTER_02: MemCells=16, Users=727, avg=0,79, rates=139
MARIA_CLUSTER_03: MemCells=8, Users=659, avg=0,78, rates=608
MARIA_CLUSTER_04: MemCells=7, Users=741, avg=0,78, rates=349
MARIA_CLUSTER_05: MemCells=8, Users=425, avg=0,78, rates=285
MARIA_CLUSTER_06: MemCells=3, Users=162, avg=0,79, rates=637
MARIA_CLUSTER_07: MemCells=5, Users=442, avg=0,78, rates=325
MARIA_CLUSTER_08: MemCells=8, Users=1104, avg=0,77, rates=234
MARIA_CLUSTER_09: MemCells=4, Users=304, avg=0,77, rates=372
MARIA_CLUSTER_10: MemCells=6, Users=162, avg=0,85, rates=802

Architektur

Server

Server Dienste werden in Form eines Clusters zur Verfügung gestellt. Auf Servern die als Clusterknoten vorgesehen sind laufen ein oder mehrere Instanzen der Applikation in einem Applikationsserver. Die Kommunikation zwischen den einzelnen Instanzen der Applikation erfolgt mit Messaging.

Jeder Clusterknoten ist hinsichtlich Konfiguration ident. Der einzige Unterschied ist die ID jeder Instanz, die aus Hostname und einer Zufallszahl, für den Fall dass mehrere Instanzen auf einem physischen Server laufen, generiert wird.

Auf genau einer Instanz läuft eine Koordinator Komponente (Singleton). Auf jeder Instanz wird in regelmäßigen Abständen die Statusmap aktualisiert.

Applikationsserver

Glassfish + OpenMQ

Datenbank

Als Datenbank kommt neo4j in der Enterprise Edition zum Einsatz. Diese Version ermöglicht es, neo4j Instanzen als Cluster zu betreiben. Neo4j benötigt dafür laufende Zookeeper Instanzen. Lesevorgänge können auf allen Instanzen ausgeführt werden. Bei Schreibvorgängen werden Daten zuerst auf einem Master gespeichert. Sobald auf einer Slave Instanz ein Schreibvorgang stattfindet, werden die Daten mit dem Master abgeglichen. Das Konsistenzmodell ist also in diesem Fall Eventually Consistent.

Sharding

Eine Datenbank in neo4j kann 32 Milliarden Nodes, 32 Milliarden Relations und 64 Milliarden Properties umfassen.


Das bedeutet für den Fall dass jedes Item allen anderen Item in einer Beziehung steht eine maximale Obergrenze von ca. 250.000 Items.


Partitionierung der Daten (Sharding) wäre daher erforderlich, wird aber von den meisten Graphdatenbanken, so auch von neo4j, nicht unterstützt.


Ein weiterer Aspekt ist Performance: Neo4j versucht Graphen soweit wie möglich im Cache zu halten. Lesevorgänge von Daten die sich im Cache befinden sind extrem schnell. Sobald eine Datenbank zu groß wird, können sie nicht mehr zur Gänze im Cache gehalten werden, worunter die Lese-Performance leidet. Jim Webber schlägt als Lösung hier das Pattern Cache Sharding vor. Statt Sharding wird hier ein Consistent Routing implementiert - Zugriffe auf gleiche Datensätze werden immer auf dieselbe Serverinstanz geroutet. Jim Webber schlägt vor Abgrenzungen domän-spezifisch zu implementieren.


Um beide Aspekte zu berücksichtigen, werden Daten pro Mandaten (=Domäne) in unterschiedlichen Datenbanken gespeichert, bzw. Daten von wenigen Mandaten in einer Datenbank zusammengefasst. Datenzugriffe werden pro Mandaten an immer dieselben zugeordneten Applikationsinstanzen geroutet. Dies zu gewährleisten ist Aufgabe des Koordinators.


Nachteil dieser Lösung ist dass es nicht mehr ohne weiteres möglich ist, Domän-übergreifende Beziehungen festzustellen.


Client

Clients dienen dazu, mit dem Recommender System zu interagieren.

Wie Clients mit dem jeweiligen Zielsystemen zusammenspielen bleibt der Implementierung des Clients überlassen.

Auch der Umgang mit anonymen Usern obliegt dem Client, so kann beispielsweise einen anonymen User pro Session ein eigener User kreiert werden.

Clients interagieren mit dem Server über ein Restful Webservice. In weiterer Zukunft wird es auch möglich sein einen Client als native Java-Applikation zu implementieren, die über eine Proxy-Klasse mit dem Recommender System kommuniziert.

Aktionen

Folgende Aktionen können von Clients ausgeführt werden:

  • Rate: Ein Rating eines Users für ein Item wird übermittelt
  • User hinzufügen: Ein neuer User wird angelegt
  • User-Merkmal hinzufügen: Eine Merkmal, z.B. ein Schlagwort oder eine Eigenschaft, wie Alter, Gender, etc. wird hinzugefügt.
  • Item hinzufügen: Ein neues Item wird angelegt
  • Item-Merkmal hinzufügen: Ein Merkmal, z.B. ein Schlagwort oder ein Wortvektor wird hinzugefügt
  • Recommendations für User abfragen: Das Recommender System liefert dem Client eine Liste mit Namen oder IDs von Items

Design

Datenbanken und Datenstruktur

Datenbanken der Mandaten

User, Items und deren Beziehungen werden pro Mandaten in jeweils einer Datenbank gespeichert. Für Mandaten mit kleineren Datenmengen werden die Daten mehrerer Mandaten in einer Datenbank zusammengefasst.

Diese Datenbank enthält folgende Knoten-Arten:

  • Mandant: Repräsentiert einen Mandanten, hat Kanten zu Item und User-Knoten


  • Item:
    • similiar_to Kanten zu anderen Items (diese Kanten sind als ungerichtete Kanten zu verstehen)
    • Profil-Kanten zu verscheidenen Profile-Knoten, wie Wordverktor-Knoten oder Keyword-Knoten


  • User:
    • similiar_to Kanten zu anderen User-Knoten (diese Kanten sind als ungerichtete Kanten zu verstehen)
    • rate Kanten zu Items. Diese Kanten besitzen eine weight Property, die den Wert des Ratings in Prozent enthält.
    • predict Kanten zu Items. Diese Kanten haben mehrere Properties:
      • weight: Ermittelter Rating Wert des Users für dieses Item
      • conf_vers: Versionsnummer der verwendeten Konfiguration (siehe Konfigurations Datenbank)
      • Methoden: Verwendete Methode mit zugehörigen Vorhersage-werten


Datenbank für Konfigurations- und Statusinformationen

Konfigurations-Graph

Der Graph, der Daten bezüglich Konfiguration enthält besteht aus:

  • Datenbanken: Welche Datenbanken gibt es, und welchen Mandanten sind sie zugeordnet
    • Properties: Name der Datenbank und Dateiname
  • Mandanten: Name des Mandanten, Authentifizierungsdaten, etc.
  • Methoden: Verfügbare Methoden (e.g. Item-Based CF) zum Ermitteln von Predictions
    • Properties: Name der Methode
  • Profile: Profile umfassen eine Reihe verschiedener Methoden, und wie jede Methode für eine Prediction zu gewichten ist. Ein Profil kann von beliebig vielen Configurations verschiedener Mandanten verwendet werden.
  • Configuration: Entspricht einer Version eines Profiles, inklusive der Möglichkeit Default-Gewichtungen zu überschreiben. Unterhält eine Beziehung zu genau einem Profil. Ist genau einem Mandanten zugeordnet. Jeder Mandant kann allerdings mit mehreren Configuration Knoten verbunden sein, wobei genau eine Configuration aktiv sein muss. Die aktive Configuration wird mittels active Property der Mandant->Configuration Kante gekennzeichnet. Properties:
    • Versionsnummer: Diese Versionsnummer wird als Property der predict Kante übernommen. Damit kann festgestellt werden ob Berechnungen auf der momentan aktive Konfiguration beruhen oder alle Predictions erneut ermittelt werden müssen.
    • Accuracy: Ermittelte Gesamt-Accuracy (Mean Absolute Error Abweichung von Ratings zu Predictions)
  • Properties der Kante Configuration->Profile:
    • Weight: Tatsächlich bei der Ermittlung der Predictions vewendetes Gewicht.
    • Accuracy: Ermittelte Accuracy (Mean Absolute Error Abweichung von Ratings zu Predictions) der betreffenden Methode

Dependency-Map

Zwischen Methoden können Abhängigkeiten bestehen. So ist die Methode Content Boosted CF von der Methode Content Based Filtering abhängig, diese muss also zuerst beendet werden bevor Content Boosted CF' gestartet werden darf. Diese Abhängigkeiten sind als depends_on Kanten zwischen Method Knoten modelliert.


Status-Map

Status-Map

Jede Instanz der Applikation ist in der Status-Map vertreten und aktualisiert in regelmäßigen Abständen die Heartbeat Property des entsprechenden Member-Knotens. Dieser Schreibvorgang bewirkt eine Synchronisation mit dem Master, wodurch die Status-Map unmittelbar nach jedem Schreibvorgang konsistent ist.

Je nach Rolle erfolgt zusätzlich zum Update der Status-Map ein zusätzlicher Schritt:

  • der Koordinator prüft ob eine Heartbeat Property eines Kontens nicht aktualisiert wurde. In diesem Fall gilt der Knoten als ausgefallen, und wird aus der Status-Map entfernt. Zugeordnete Mandanten und Jobs werden neu verteilt.
  • jeder Knoten prüft ob der Koordinator dessen Heartbeat Property aktualisiert hat. Ist dies nicht der Fall, gilt der Koordinator als ausgefallen, und der Knoten startet eine Election.

In der Status-Map sind auch alle aktive Mandaten-Knoten enthalten. Mittels Consistent-Hashing Algorithmus sind Mandanten ein oder mehreren Applikationsinstanzen zugeordnet. Diese Zuordnung steuert das Message Routing. Betreffende Instanzen erhalten Rating-Requests und Jobs, die den jeweiligen Mandaten betreffen. Diese Jobs, sowie allfällige Abhängigkeiten zu anderen Jobs sind ebenfalls in der Status-Map enthalten.

Kommunikation

Client kommunizieren mit dem Server über ein Restful Webservice.

Der Vorgang, am Beispiel Rate-Request läuft wie folgt ab: Der Client übermittelt ein Rating an einen Clusterknoten. Der antwortende Clusterknoten generiert eine Nachricht und sendet diese an eine konfigurierte Queue, die Kommunikation zwischen Client und Server wird daraufhin beendet.

Messaging

Kommunikation findet größtenteils über Messaging statt. Vorteile sind:

  • Einfachere Kommunikaton: Jeder Clusterknoten ist hinsichtlich Konfiguration ident. Anstatt wissen zu müssen wie andere Knoten kontaktiert werden müssen, beschränkt sich bei Messaging das erforderliche Wissen drauf, an welche Queues oder Topics versendet werden muss.
  • Skalierbarkeit: Es ist nicht erforderlich dass jeder Clusterknoten an jeden anderen Clusterknoten Nachrichten versenden kann. Es muss auch nicht jedem Clusterknoten bekannt sein welche anderen Clusterknoten verfügbar sind.
  • Entkoppelung von Client und Server, und Entkoppelung der Clusterknoten, asynchroner Nachrichtenaustausch
  • Einfachere Parallelverarbeitung: In jedem Clusterknoten können mehrere Instanzen Nachrichten erhalten und gegebenenfalls parallel verarbeiten

Es gibt außer dem Koordinator zwei Arten von Message Consumer:

  • Empfänger von Rate-Jobs: Der entsprechende User und Item Knoten wird in der entsprechenden Datenbank gesucht, Rating Kante zwischen User und Item gesetzt und gewichtet, und daraufhin eine Nachricht an die Scheduler Queue, deren Empfänger der Koordinator ist, gesendet.
  • Empfänger der Job Queue: In der Status Map wird der entsprechende Job anhand der sich in der Nachricht befindlichen Job-ID nachgeschlagen. Daraufhin wird der Job an eine Instanz delegiert, die die entsprechende Methode verarbeitet, und daraufhin der Job in der Status Map gelöscht. In der Status Map können auch Abhängigkeiten notiert sein, beispielsweise kann ein Job erst nach Beendigung eines anderen Jobs gestartet werden. In diesem Fall wird nach einiger Zeit erneut geprüft ob der Job gestartet werden kann. Ist dies nicht der Fall wird die Nachricht zurückgewiesen, was entweder zu eine neuerlichen Zustellversuch führt, oder die Nachricht wird als nicht zustellbar betrachtet und demgemäß an die Queue für nicht zustellbare Nachrichten zugestellt.


Queues und Topics

Rate-Requests

An diese Queue werden von Clients gemeldete Ratings übermittelt. Relevante Informationen sind hier: Mandant, User, Item, Rating als Prozentwert (bei Ratingmöglichkeit von 1 bis 7 und Wahl 3 würde dies 42.86% entsprechen). Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.

Item-Requests

An diese Queue werden von Clients gemeldete Items übermittelt. Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.

User-Requests

An diese Queue werden von Clients gemeldete User übermittelt. Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.

Profile-Requests

An diese Queue werden von Clients gemeldete Profile und Änderungen an Profilen übermittelt. Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.

Recommendation-Requests

An diese Queue werden Recommendation Anforderungen von Clients übermittelt. Nachrichten werden mit Filter Information versehen, die aus der Status-Map bezogen wird.

Scheduler-Queue

An diese Queue werden Nachrichten gesendet die entweder infolge eines bereits durchgeführten Ratings erstellt werden, oder Nachrichten infolge Anlage eines neuen Users oder Items, oder Nachrichten infolge Änderung von Eigenschaften von Item oder User Knoten. Erstellt werden Rating Nachrichten von Workern die erfolgreich ein Rating eingetragen habe, und von den via Webservice kontaktierten Services nach der Durchführung der entsprechenden Aktion.

Job-Queue

An diese Queue sendet der Koordinator Nachrichten mit Job IDs. Nachrichten sind mit Filter Informationen versehen, daher erhalten Consumer nur Nachrichten anhand enstprechender Message Selektoren. Consumer schlagen Jobs in der Status-Map nach, und verarbeiten diese.

Dead Letter Queue

An diese Queue stellt der Messaging Provider nicht zustellbare Nachrichten zu. Consumer dieser Queue ist der Koordinator, der entsprechend der Nachricht weitere Aktionen setzt, so werden beispielsweise Nachrichten mit Job IDs erneut an die Job Queue gesendet.

Message Routing

Anhand der Statusmap werden mittels Consistent Hashing Algorithmus jedem Clusterknoten zu betreuende Mandaten zugeteilt. Hintergrund dieser Zuteilung ist die fehlende Sharding Möglichkeit bei Neo4j. Die Routing Funktionalität des Cache Sharding Patterns wird durch Messaging implementiert. Der Message Producer versieht Nachrichten mit Filter Information, bevor eine Zustellung an eine Queue erfolgt. Der Consumer verwendet Message Selektoren um Nachrichten zu filtern.

Clusterknoten erhalten mittels gesetztem Message Selektor ausschließlich für sie bestimmte Nachrichten. Es ist Aufgabe des Koordinators, die entsprechende Header Property bei Nachrichten entsprechend zu setzen, wobei die Statusmap vor dem Setzen der Property konsultiert wird, um ausgefallene Clusterknoten, neue hinzugekommene Clusterknoten, neue Mandanten, etc. berücksichtigen zu können.

Koordinator

Der Koordinator startet folgende Dienste:

  • Workgroup Allocator
  • Job Dispatcher
  • Message Re-Dispatcher

Wenn ein Koordinator feststellt dass er nicht länger Koordinator ist, beendet er diese Dienste.

Die Aufgabe dieser Dienste ist das Verteilen, bzw. das Routen von Nachrichten, die Aufgaben für andere Clusterknoten beinhalten.

Für nicht zustellbare Nachrichten, falls beispielsweise ein Clusterknoten ausgefallen ist nachdem der Koordinator eine Nachricht für diesen erstellt hat, ist eine eigene Queue vorgesehen. Der Koordinator verteilt Nachrichten aus dieser Queue erneut.

Message Re-Dispatcher

Der Koordinator liest in einer Endlosschleife Nachrichten aus der Rate-Requests Queue (und der Queue für nicht zustellbare Nachrichten). Folgend den Informationen aus der Status-Map wird die Rating Nachricht mit einem entsprechendem Filter Information versehen und an die Rate-Jobs Queue zugestellt.

Job Scheduler

Der Koordinator liest in einer Endlosschleife Nachrichten aus der Scheduler-Queue und generiert entsprechene Jobs. Beispielsweise werden mehrere Rating-Nachrichten eines Mandaten aus der Scheduler-Queue zusammengefasst und entsprechende Jobs generiert.

Aufgrund der Information der Dependency-Map werden aus Ratings, und den für den entsprechenden Mandanten konfigurierten Methoden, mehrere Jobs erzeugt. Diese Jobs können untereinander Abhängigkeiten besitzen. Jobs und deren Abhängigkeiten werden in die Status-Map eingetragen. Danach wird eine Nachricht erzeugt, in der neben der Job-ID auch ein entsprechender Message Selektor gesetzt ist und diese an die Job-Queue gesendet.

Election

Eine Election findet statt, sobald ein Member-Knoten feststellt dass der Koordinator ausgefallen ist.

Dies erfolgt indem jeder Clusterknoten prüft ob er derjenige mit der niedrigsten ID ist, in diesem Fall wird dieser Knoten neuer Koordinator.

Falls weitere Clusterknoten mit niedrigeren IDs vorhanden sind wird geprüft ob einer dieser Knoten verfügbar ist. In diesem Fall muss keine weitere Aktion erfolgen. Sind alle Konten mit niedrigeren IDs ausgefallen, erklärt sich betreffender Clusterknoten als neuer Koordinator.

Ein neuer Koordinator setzt eine Kante vom Koordinator-Knoten zum entsprechenden Clusterknoten .


Predictions

Ablauf:

  • Clients melden neue Ratings, Items oder Profil Information
  • Im Falle von Ratings werden entsprechende Kanten gesetzt
  • der Kommunikator erstellt pro Mandant entsprechend den konfigurierten Methoden Jobs
  • der Kommunikator erstellt den Prediction-Job, der von den Methoden-Jobs, sowie vorherigen Prediction-Jobs des jeweiligen Mandanten abhängt.
  • Worker Instanzen ermitteln Predictions für einzelne Methoden, entsprechend den Jobs
  • eine Worker Instanz ermittelt Predictions für Items indem die Predictions der einzelnen Methoden gewichtet werden

Recommendations

Ablauf:

  • ein Client fordert für einen bestimmten User Recommendations an, und kommuniziert hierfür über ein Webservice mit einer Instanz des Systems
  • der Request wird via Messaging an den Kommunikator gesendet
  • der Kommunikator sendet den Request an einen Clusterknoten, der für Datenzugriffe auf den entsprechenden Mandanten vorgesehen ist
  • eine Worker-Instanz ermittelt Recommendations
  • die mit dem Client kommunizierende Instanz erhält die Recommendations und liefert diese an den Client

Anwendung von Metriken

Um die Treffsicherheit des Systems beurteilen zu können werden Metriken eingesetzt. Vorerst wird ausschließlich Accuracy, das ist der durchschnittliche Fehler (Mean Absolute Error - MAE), also die durchschnittliche Abweichung von Prediction und Rating betrachtet.

Diese Abweichungen wird in weiterer Folge benutzt um die Gewichtungen der Methoden anzupassen.

Für die Ermittlung der Accuracy erzeugt der Koordinator einen eigenen Job, der von der Beendigung des Prediction Jobs abhängig ist. Diese Job ermittelt die MAE gesamt sowie die MAE jeder Methode und aktualisiert die Accurcy Properties in der Konfigurations Datenbank der aktuellen Configuration.

Falls das Verhältnis von Ratings zu Predictions einen konfigurierbaren Wert übersteigt, und die Accuracy einer Methode überdurchschnittlich von der Gesamt-Accuracy abweicht, wird eine neue Version der Configuration erstellt, bei der das Weight Property betreffender Methoden um eine gewissen Betrag gesenkt wird.