|
| 1 | +# User story 4: Popular recommendation |
| 2 | + |
| 3 | +Anderen kochten ook |
| 4 | + |
| 5 | +Op de productoage van het front-end staat een kopje: 'Anderen kochten ook'. Hier worden de producten geplaatst van profielen die hetzelfde koopgedrag als de user vertonen, |
| 6 | +in dezelfde geslachtscategorie zitten als de gebruiker en passen bij de categorie van de pagina. |
| 7 | + |
| 8 | +| _GP-V1A-Groep6_ |
| 9 | +| --- | |
| 10 | +| TAAI-V1GP-19_2020 | |
| 11 | +| TICT-AI-V1A | |
| 12 | +| 1778287 | |
| 13 | + |
| 14 | +# Onderbouwing algoritme |
| 15 | + |
| 16 | +Omdat de aanbevelingen zijn gebaseerd op eerdere aankopen van andere mensen, wordt gekeken naar mensen die eerder orders hebben gedaan. |
| 17 | + |
| 18 | + |
| 19 | + |
| 20 | +Het **U**niversum van het Venn-diagram hierboven bestaat uit klanten. Deze verzameling klanten kan **B**ekend zijn of (B̅) niet bekend zijn. |
| 21 | +Van alle profielen van bekende klanten, heeft een groep **E**vents. Daarnaast heeft een groep mensen met Events ook **O**rders. |
| 22 | +Voor elk **S**egment binnen deze verzameling wordt vervolgens gekeken naar de producten die door deze groep profielen zijn gekocht. |
| 23 | +Vervolgens wordt gekeken naar de verschillende **G**enders binnen ’n verzameling segment x waardoor de combinatie segment-gender ontstaat voor elke mogelijke gender binnen de verzameling van segment x. |
| 24 | +En om met elke **C**ategorie product pagina verschillende producten te tonen, verdelen we de verzameling van producten in segment x, gender y op categorieën. |
| 25 | + |
| 26 | +## Huidige user behoort tot B̅ |
| 27 | +/ |
| 28 | + |
| 29 | +## Huidige user behoort tot B |
| 30 | + |
| 31 | +Deze groep kan vervolgens verder worden onderverdeeld. Welke mensen vertonen hetzelfde koopgedrag als de user? Hiervoor wordt gekeken naar het segment dat bij een profiel hoort. |
| 32 | +Voor elke verzameling profielen bij ‘n segment geldt: _segment_ is een subset van _O_. Wat voor segmenten zijn er, en hoe vaak komen profielen met een bepaald segment voor? |
| 33 | + |
| 34 | +```sql |
| 35 | +select lower(segment), count(segment) as frequency |
| 36 | +from profile |
| 37 | +group by lower(segment) |
| 38 | +order by lower(segment); |
| 39 | +``` |
| 40 | + |
| 41 | + |
| 42 | + |
| 43 | +Als we hier zouden stoppen, dan zouden mensen die alleen vrouwelijke producten kopen ook mannelijke producten (of andersom, etc.) aangeboden krijgen. |
| 44 | +Daarom wordt voor alle aankopen van de profielen bij 'n segment x gekeken naar 'n gender y. |
| 45 | +Dus als we nu gaan kijken voor 'n segment: browser wat de distributie is van genders binnen de verzameling orders van dit segment dan krijgen we het volgende: |
| 46 | + |
| 47 | + |
| 48 | +```sql |
| 49 | +select lower(gender) as gender, count(*) as frequency from product |
| 50 | +natural join(select product_id from orders |
| 51 | +natural join(select * from sessions |
| 52 | +natural join(select browser_id from buids |
| 53 | +natural join profile where lower(segment)='browser') |
| 54 | +as _id) as __id) as ___id |
| 55 | +group by lower(gender) |
| 56 | +order by lower(gender); |
| 57 | +``` |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | +Als we nu gaan kijken naar de frequencies van producten voor elke mogelijke combinatie van gender-category binnen de verzameling orders van profielen met het segment browser, |
| 62 | +krijgen we de volgende uitkomst: |
| 63 | + |
| 64 | +```sql |
| 65 | +select lower(gender) as gender, lower(category) as category, count(*) as frequency from product |
| 66 | +natural join(select product_id from orders |
| 67 | +natural join(select * from sessions |
| 68 | +natural join(select browser_id from buids |
| 69 | +natural join profile where lower(segment)='browser') |
| 70 | +as _id) as __id) as ___id |
| 71 | +group by lower(gender), lower(category) |
| 72 | +order by lower(gender), lower(category); |
| 73 | +``` |
| 74 | + |
| 75 | + |
| 76 | + |
| 77 | +Hierboven is de tabel getoond met de eerste 29 rijen van de in totaal 70 rijen. |
| 78 | +Hier kun je zien dat elke verzameling van producten voor 'n segment browser met gender x alle producten zijn onderverdeeld in categorieën die voorkomen binnen de verzameling producten. |
| 79 | +Dan zie je ook dat verzamelingen als grootverpakking minder combinaties hebben. Blijkbaar komen binnen de verzameling van grootverpakking slechts twee categorieën voor. |
| 80 | + |
| 81 | +Ook zien we dat sommige combinaties, niet voorkomen of maar 1 product bevatten zoals; gender: gezin, category: kleding & sieraden. Dit betekent dat bij een user met |
| 82 | +het gedrag van een browser, gender kenmerk grootverpakking op de pagina van kleding & sieraden, maar 1 product krijgt aangeraden. Of soms geen enkel product als de category niet voorkomt |
| 83 | +in de gekochte producten. |
| 84 | + |
| 85 | +# Nuttigheid |
| 86 | + |
| 87 | +Door het sorteren op segment kenmerk, gender kenmerk en vervolgens per categoriepagina |
| 88 | +zou je kunnen zeggen dat mensen die dezelfde kenmerken als een user hadden statistisch gezien grotendeels hetzelfde gedrag zullen vertonen als de gebruiker. |
| 89 | +Neem bijvoorbeeld segment: browser en het gender kenmerk baby. Dan is de kans heel groot dat ze naar de categorie pagina van baby & kind kijken |
| 90 | +waar ook de meeste producten van zijn gekocht. En dus volgt dan indirect dat ze minder of vrijwel niet naar de pagina gezond & verzorging zullen kijken |
| 91 | +en dat het tonen van minder recommendations voor die pagina daarom gerechtvaardigd is. |
| 92 | + |
| 93 | +# Pseudocode |
| 94 | + |
| 95 | +```python |
| 96 | +Creëer tabel popular als deze nog niet bestond met de kolommen segment, gender, category, FK product_id1, FK product_id2, FK product_id3, FK product_id4, FK product_id5. |
| 97 | + Voor elk _segment in lijst met segments loop: |
| 98 | + Stop alle mogelijke gender-category combinaties binnen de verzameling met producten, de orders van profielen met segment _segment in een lijst seg. |
| 99 | + Voor elke _gender_category combinatie in seg loop: |
| 100 | + Stop de eerste vijf producten binnen de verzameling producten uit de orders van profielen met segment _segment, die voldoen aan de _gender_category combinatie in een lijst prodids. |
| 101 | + |
| 102 | + Voeg achtereenvolgens de volgende delen in de tabel in: segment, gender, category, prodids[0], prodids[1], prodids[2], prodids[3], prodids[4] |
| 103 | + |
| 104 | +``` |
| 105 | + |
| 106 | +# Relations |
| 107 | + |
| 108 | +_Product_ -- _Popular_ |
| 109 | + |
| 110 | +Een product kan bij **0 of 1** rij horen van popular. |
| 111 | + |
| 112 | +Een rij van popular hoort bij **meerdere** producten. |
| 113 | + |
| 114 | +# Logistiek Datamodel |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | +# DDL |
| 119 | + |
| 120 | +Hieronder volgt de query die wordt uitgevoerd in createRelationTables.py om de relatie tussen de tabel popular en product te maken. |
| 121 | + |
| 122 | +```sql |
| 123 | +DO $$ |
| 124 | +DECLARE |
| 125 | + _segment VARCHAR; |
| 126 | + i INT; |
| 127 | + index INT; |
| 128 | + r RECORD; |
| 129 | + clean_list VARCHAR[]; |
| 130 | + _combi VARCHAR[]; |
| 131 | + prod_freq_list VARCHAR[]; |
| 132 | + prod_freq VARCHAR[]; |
| 133 | + temp VARCHAR[]; |
| 134 | + temp2 INT[]; |
| 135 | + temp3 INT[]; |
| 136 | +BEGIN |
| 137 | + -- [ MAAK DE TABEL AAN OF UPDATE DE TABEL ] |
| 138 | + DROP TABLE IF EXISTS popular CASCADE; |
| 139 | + CREATE TABLE popular ( |
| 140 | + segment VARCHAR(255), |
| 141 | + gender VARCHAR(255), |
| 142 | + category VARCHAR(255), |
| 143 | + product_id1 VARCHAR(255), |
| 144 | + product_id2 VARCHAR(255), |
| 145 | + product_id3 VARCHAR(255), |
| 146 | + product_id4 VARCHAR(255), |
| 147 | + FOREIGN KEY (product_id1) |
| 148 | + REFERENCES product (product_id), |
| 149 | + FOREIGN KEY (product_id2) |
| 150 | + REFERENCES product (product_id), |
| 151 | + FOREIGN KEY (product_id3) |
| 152 | + REFERENCES product (product_id), |
| 153 | + FOREIGN KEY (product_id4) |
| 154 | + REFERENCES product (product_id) |
| 155 | + ); |
| 156 | + -- [ VUL DE TABEL ] |
| 157 | + ------------------------- || Voor elk segment bestaande binnen profielen |
| 158 | + foreach _segment in ARRAY(select array(select lower(segment) as segment |
| 159 | + from profile |
| 160 | + group by lower(segment) |
| 161 | + order by lower(segment))) loop |
| 162 | + ------------------------ || Groepeer elke mogelijk combinatie gender-categorie van producten |
| 163 | + ------------------------ || gekocht door profielen met het segment _segment |
| 164 | + foreach _combi slice 1 in ARRAY(select array(select array[lower(gender), lower(category)] from product |
| 165 | + natural join(select product_id from orders |
| 166 | + natural join(select * from sessions |
| 167 | + natural join(select browser_id from buids |
| 168 | + natural join profile where lower(segment)=_segment) |
| 169 | + as _id) as __id) as ___id |
| 170 | + group by lower(gender), lower(category) |
| 171 | + order by lower(gender), lower(category))) loop |
| 172 | + if _combi[1] is not Null and _combi[2] is not Null then -- || Als zowel het gender als de categorie niet Null zijn |
| 173 | + ----------------------- || Neem dan de producten |
| 174 | + prod_freq_list := array(select ARRAY[product_id, count(*)::varchar] from product |
| 175 | + natural join(select product_id from orders |
| 176 | + natural join(select * from sessions |
| 177 | + natural join(select browser_id from buids |
| 178 | + natural join profile where lower(segment)=_segment) |
| 179 | + as _id) as __id) as ___id |
| 180 | + where lower(gender)=_combi[1] and lower(category)=_combi[2] |
| 181 | + group by product_id |
| 182 | + order by product_id); |
| 183 | + else -- || Als het gender Null is en de categorie niet |
| 184 | + if _combi[1] is Null and _combi[2] is not Null then |
| 185 | + prod_freq_list := array(select ARRAY[product_id, count(*)::varchar] from product |
| 186 | + natural join(select product_id from orders |
| 187 | + natural join(select * from sessions |
| 188 | + natural join(select browser_id from buids |
| 189 | + natural join profile where lower(segment)=_segment) |
| 190 | + as _id) as __id) as ___id |
| 191 | + where lower(gender) is Null and lower(category)=_combi[2] |
| 192 | + group by product_id |
| 193 | + order by product_id); |
| 194 | + else -- || Categorie Null bestaat niet op de front-end en is dus overbodig voor de tabel |
| 195 | + continue; |
| 196 | + end if; |
| 197 | + end if; |
| 198 | + temp := ARRAY[Null]; |
| 199 | + temp2 := ARRAY[Null]; |
| 200 | + foreach prod_freq slice 1 in array(prod_freq_list) loop |
| 201 | + temp = array_append(temp, prod_freq[1]); |
| 202 | + temp2 = array_append(temp2, prod_freq[2]::int); |
| 203 | + end loop; |
| 204 | + temp3 = ARRAY(select distinct unnest(temp2) order by 1); |
| 205 | + if array_length(temp3, 1) > 1 then |
| 206 | + for i in 1..4 loop |
| 207 | + for r in select max(x) as f from unnest(temp2) as x loop |
| 208 | + index = array_position(temp2, r.f); |
| 209 | + clean_list[i] = temp[index]; |
| 210 | + temp = array_remove(temp, temp[index]); |
| 211 | + end loop; |
| 212 | + end loop; |
| 213 | + if clean_list[1] is not Null then |
| 214 | + INSERT INTO popular VALUES (_segment, _combi[1], _combi[2], clean_list[1], clean_list[2], clean_list[3], clean_list[4]); |
| 215 | + else |
| 216 | + continue; |
| 217 | + end if; |
| 218 | + end if; |
| 219 | + end loop; |
| 220 | + end loop; |
| 221 | +END $$; |
| 222 | +``` |
| 223 | + |
| 224 | +# Tabel Popular |
| 225 | + |
| 226 | + |
| 227 | + |
| 228 | +# Hoe werkt de recommendation? |
| 229 | + |
| 230 | + |
| 231 | + |
| 232 | +# Recommendations in de front-end |
| 233 | + |
| 234 | +_Gezond & verzorging_ |
| 235 | + |
| 236 | + |
| 237 | + |
| 238 | +_Wonen & vrije tijd_ |
| 239 | + |
| 240 | + |
0 commit comments