Commit 8a5b273cbe0b6b86390d5f40b92e867e1bfcb54d
1 parent
842edc0b
Exists in
master
and in
1 other branch
Added ranking to RecommendationResults and small fixes for strategies.
Showing
2 changed files
with
85 additions
and
21 deletions
Show diff stats
src/recommender.py
... | ... | @@ -28,12 +28,14 @@ class RecommendationResult: |
28 | 28 | """ |
29 | 29 | Class designed to describe a recommendation result: items and scores. |
30 | 30 | """ |
31 | - def __init__(self,item_score): | |
31 | + def __init__(self,item_score,ranking=0): | |
32 | 32 | """ |
33 | 33 | Set initial parameters. |
34 | 34 | """ |
35 | 35 | self.item_score = item_score |
36 | 36 | self.size = len(item_score) |
37 | + if ranking: | |
38 | + self.ranking = ranking | |
37 | 39 | |
38 | 40 | def __str__(self): |
39 | 41 | """ |
... | ... | @@ -64,13 +66,13 @@ class Recommender: |
64 | 66 | """ |
65 | 67 | Set initial parameters. |
66 | 68 | """ |
69 | + self.cfg = cfg | |
67 | 70 | self.items_repository = xapian.Database(cfg.axi) |
68 | 71 | self.set_strategy(cfg.strategy) |
69 | 72 | if cfg.weight == "bm25": |
70 | 73 | self.weight = xapian.BM25Weight() |
71 | 74 | else: |
72 | 75 | self.weight = xapian.TradWeight() |
73 | - self.cfg = cfg | |
74 | 76 | |
75 | 77 | def set_strategy(self,strategy_str): |
76 | 78 | """ |
... | ... | @@ -83,10 +85,10 @@ class Recommender: |
83 | 85 | if strategy_str == "cbd": |
84 | 86 | self.strategy = strategy.ContentBasedStrategy("desc") |
85 | 87 | if strategy_str == "col": |
86 | - self.strategy = strategy.CollaborativeStrategy(20) | |
87 | 88 | self.users_repository = data.PopconXapianIndex(self.cfg) |
89 | + self.strategy = strategy.CollaborativeStrategy(20) | |
88 | 90 | |
89 | - def get_recommendation(self,user,result_size=20): | |
91 | + def get_recommendation(self,user,result_size=100): | |
90 | 92 | """ |
91 | 93 | Produces recommendation using previously loaded strategy. |
92 | 94 | """ | ... | ... |
src/strategy.py
... | ... | @@ -42,6 +42,26 @@ class PkgMatchDecider(xapian.MatchDecider): |
42 | 42 | """ |
43 | 43 | return doc.get_data() not in self.pkgs_list |
44 | 44 | |
45 | +class AppMatchDecider(xapian.MatchDecider): | |
46 | + """ | |
47 | + Extend xapian.MatchDecider to not consider only applications packages. | |
48 | + """ | |
49 | + def __init__(self, pkgs_list, axi): | |
50 | + """ | |
51 | + Set initial parameters. | |
52 | + """ | |
53 | + xapian.MatchDecider.__init__(self) | |
54 | + self.pkgs_list = pkgs_list | |
55 | + self.axi = axi | |
56 | + | |
57 | + def __call__(self, doc): | |
58 | + """ | |
59 | + True if the package is not already installed. | |
60 | + """ | |
61 | + tags = axi_search_pkg_tags(self.axi,doc.get_data()) | |
62 | + return (("XTrole::program" in tags) and | |
63 | + (doc.get_data() not in self.pkgs_list)) | |
64 | + | |
45 | 65 | class UserMatchDecider(xapian.MatchDecider): |
46 | 66 | """ |
47 | 67 | Extend xapian.MatchDecider to match similar profiles. |
... | ... | @@ -73,7 +93,32 @@ class PkgExpandDecider(xapian.ExpandDecider): |
73 | 93 | True if the term is a package. |
74 | 94 | """ |
75 | 95 | # [FIXME] return term.startswith("XP") |
76 | - return not term.startswith("XT") | |
96 | + #return not term.startswith("XT") | |
97 | + return term.startswith("XP") | |
98 | + | |
99 | +class AppExpandDecider(xapian.ExpandDecider): | |
100 | + """ | |
101 | + Extend xapian.ExpandDecider to consider applications only. | |
102 | + """ | |
103 | + def __init__(self,axi): | |
104 | + xapian.ExpandDecider.__init__(self) | |
105 | + self.axi = axi | |
106 | + | |
107 | + def __call__(self, term): | |
108 | + """ | |
109 | + True if the term is a package. | |
110 | + """ | |
111 | + if not term.startswith("XT"): | |
112 | + package = term.lstrip("XP") | |
113 | + print package | |
114 | + tags = axi_search_pkg_tags(self.axi,package) | |
115 | + if "XTrole::program" in tags: | |
116 | + print tags | |
117 | + return True | |
118 | + else: | |
119 | + return False | |
120 | + else: | |
121 | + return False | |
77 | 122 | |
78 | 123 | class TagExpandDecider(xapian.ExpandDecider): |
79 | 124 | """ |
... | ... | @@ -100,7 +145,7 @@ class ContentBasedStrategy(RecommendationStrategy): |
100 | 145 | self.content = content |
101 | 146 | self.profile_size = profile_size |
102 | 147 | |
103 | - def run(self,rec,user,limit): | |
148 | + def run(self,rec,user,recommendation_size): | |
104 | 149 | """ |
105 | 150 | Perform recommendation strategy. |
106 | 151 | """ |
... | ... | @@ -113,35 +158,40 @@ class ContentBasedStrategy(RecommendationStrategy): |
113 | 158 | enquire.set_query(query) |
114 | 159 | try: |
115 | 160 | # retrieve matching packages |
116 | - mset = enquire.get_mset(0, limit, None, PkgMatchDecider(user.items())) | |
161 | + mset = enquire.get_mset(0, recommendation_size, None, | |
162 | + PkgMatchDecider(user.items())) | |
163 | + #AppMatchDecider(user.items(), | |
164 | + # rec.items_repository)) | |
117 | 165 | except xapian.DatabaseError as error: |
118 | 166 | logging.critical("Content-based strategy: "+error.get_msg()) |
119 | 167 | # compose result dictionary |
120 | 168 | item_score = {} |
169 | + ranking = [] | |
121 | 170 | for m in mset: |
171 | + #[FIXME] set this constraint somehow | |
172 | + #tags = axi_search_pkg_tags(rec.items_repository,m.document.get_data()) | |
173 | + #if "XTrole::program" in tags: | |
122 | 174 | item_score[m.document.get_data()] = m.weight |
123 | - return recommender.RecommendationResult(item_score) | |
175 | + ranking.append(m.document.get_data()) | |
176 | + | |
177 | + return recommender.RecommendationResult(item_score,ranking) | |
124 | 178 | |
125 | 179 | class CollaborativeStrategy(RecommendationStrategy): |
126 | 180 | """ |
127 | 181 | Colaborative recommendation strategy. |
128 | 182 | """ |
129 | - def __init__(self,k,clustering=1): | |
183 | + def __init__(self,k): | |
130 | 184 | self.description = "Collaborative" |
131 | - self.clustering = clustering | |
132 | 185 | self.neighbours = k |
133 | 186 | |
134 | - def run(self,rec,user,result_size): | |
187 | + def run(self,rec,user,recommendation_size): | |
135 | 188 | """ |
136 | 189 | Perform recommendation strategy. |
137 | 190 | """ |
138 | - profile = user.pkg_profile | |
191 | + profile = ["XP"+package for package in user.pkg_profile] | |
139 | 192 | # prepair index for querying user profile |
140 | 193 | query = xapian.Query(xapian.Query.OP_OR,profile) |
141 | - if self.clustering: | |
142 | - enquire = xapian.Enquire(rec.clustered_users_repository) | |
143 | - else: | |
144 | - enquire = xapian.Enquire(rec.users_repository) | |
194 | + enquire = xapian.Enquire(rec.users_repository) | |
145 | 195 | enquire.set_weighting_scheme(rec.weight) |
146 | 196 | enquire.set_query(query) |
147 | 197 | try: |
... | ... | @@ -155,27 +205,39 @@ class CollaborativeStrategy(RecommendationStrategy): |
155 | 205 | rset.add_document(m.document.get_docid()) |
156 | 206 | logging.debug(m.document.get_data()) |
157 | 207 | # retrieve most relevant packages |
158 | - eset = enquire.get_eset(result_size,rset,PkgExpandDecider()) | |
208 | + #eset = enquire.get_eset(recommendation_size,rset, | |
209 | + # AppExpandDecider(rec.items_repository)) | |
210 | + eset = enquire.get_eset(recommendation_size,rset,PkgExpandDecider()) | |
159 | 211 | # compose result dictionary |
160 | 212 | item_score = {} |
161 | - for package in eset: | |
162 | - item_score[package.term.lstrip("XP")] = package.weight | |
213 | + for e in eset: | |
214 | + package = e.term.lstrip("XP") | |
215 | + tags = axi_search_pkg_tags(rec.items_repository,package) | |
216 | + #[FIXME] set this constraint somehow | |
217 | + #if "XTrole::program" in tags: | |
218 | + item_score[package] = e.weight | |
163 | 219 | return recommender.RecommendationResult(item_score) |
164 | 220 | |
165 | 221 | class DemographicStrategy(RecommendationStrategy): |
166 | 222 | """ |
167 | 223 | Recommendation strategy based on demographic data. |
168 | 224 | """ |
225 | + #def __init__(self, result): | |
226 | + #self.result = result | |
169 | 227 | def __init__(self): |
170 | 228 | self.description = "Demographic" |
171 | 229 | logging.debug("Demographic recommendation not yet implemented.") |
172 | 230 | raise Error |
173 | 231 | |
174 | - def run(self,user,items_repository): | |
232 | + def run(self,rec,user,recommendation_size): | |
175 | 233 | """ |
176 | 234 | Perform recommendation strategy. |
177 | 235 | """ |
178 | - pass | |
236 | + ordered_result = self.result.get_prediction() | |
237 | + | |
238 | + for item,weight in ordered_result: | |
239 | + pass | |
240 | + | |
179 | 241 | |
180 | 242 | class KnowledgeBasedStrategy(RecommendationStrategy): |
181 | 243 | """ | ... | ... |