@@ -99,86 +99,200 @@ public void Suggest(float rate, int userId, int bookId, bool isSuggestion)
99
99
Context . SaveChanges ( ) ;
100
100
101
101
}
102
+ public float PreditRating ( float [ ] UserFeatures , float [ ] BookFeatures , int features )
103
+ {
104
+ float sum = 0 ;
105
+ for ( int i = 0 ; i < features ; i ++ )
106
+ {
107
+ sum += UserFeatures [ i ] * BookFeatures [ i ] ;
108
+ }
109
+ return sum ;
110
+ }
102
111
public void Resuggest ( )
103
112
{
104
- var users = GetAll ( ) . ToList ( ) ;
105
- //int maxUserId =users.Select(x => x.User_ID).Max();
106
- int maxBookId = Context . Books . Select ( x => x . Book_ID ) . Max ( ) ;
107
- float [ , ] matrix = new float [ users . Count , maxBookId ] ;
108
- float [ , ] result = new float [ users . Count , maxBookId ] ;
109
-
110
- //int[,] korelation = new int[users.Count, users.Count];
111
- float [ , ] corelation = new float [ users . Count , users . Count ] ;
112
- //List<double> corelation = new List<double>();
113
- List < float > average = new List < float > ( ) ;
114
- List < float > diff = new List < float > ( ) ;
113
+ var books = Context . Books . ToList ( ) ;
114
+ var users = Context . Users . ToList ( ) ;
115
+ int MaxBookId = books . Count ;
116
+ int MaxUserId = users . Count ;
117
+ float init = 0.1f ;
118
+ int features = 5 , RateCounter = 0 ;
119
+ Rate [ ] [ ] matr = new Rate [ MaxUserId ] [ ] ;
115
120
foreach ( var user in users . Select ( ( x , i ) => new { Value = x , Index = i } ) )
116
121
{
117
- int userId = user . Value . User_ID ;
118
- float averageRate = 0 ;
119
- int countNonZero = 0 ;
120
- foreach ( var rate in GetRatedBooks ( userId ) )
122
+ var rates = GetRatedBooks ( user . Value . User_ID ) . Where ( x => x . IsSuggestion == false ) . ToList ( ) ;
123
+ matr [ user . Index ] = new Rate [ MaxBookId ] ;
124
+ int i = user . Index ;
125
+ for ( int j = 0 ; j < MaxBookId ; j ++ )
121
126
{
122
- int bookId = rate . Book . Book_ID ;
123
- matrix [ user . Index , bookId ] = rate . RateValue ;
124
- if ( rate . RateValue > 0 )
127
+ var rate = rates . FirstOrDefault ( x => x . Book . Book_ID == books [ j ] . Book_ID ) ;
128
+ if ( rate != null )
125
129
{
126
- averageRate += rate . RateValue ;
127
- countNonZero ++ ;
130
+ matr [ i ] [ j ] = rate ;
131
+ RateCounter ++ ;
132
+ }
133
+ else
134
+ {
135
+ matr [ i ] [ j ] = ( new Rate ( ) { User_ID = user . Value . User_ID , Book = new Book ( ) { Book_ID = books [ j ] . Book_ID } } ) ;
128
136
}
129
137
}
130
- average . Add ( ( float ) averageRate / countNonZero ) ;
131
-
132
- if ( user . Index > 0 )
138
+ }
139
+ float [ ] b_u = new float [ MaxUserId ] ;
140
+ float [ ] b_v = new float [ MaxBookId ] ;
141
+ float [ ] [ ] UserFeatures = new float [ MaxUserId ] [ ] ;
142
+ float [ ] [ ] BookFeatures = new float [ MaxBookId ] [ ] ;
143
+ for ( int i = 0 ; i < MaxUserId ; i ++ )
144
+ {
145
+ UserFeatures [ i ] = new float [ features ] ;
146
+ for ( int j = 0 ; j < features ; j ++ )
147
+ {
148
+ UserFeatures [ i ] [ j ] = init ;
149
+ }
150
+ }
151
+ for ( int i = 0 ; i < MaxBookId ; i ++ )
152
+ {
153
+ BookFeatures [ i ] = new float [ features ] ;
154
+ for ( int j = 0 ; j < features ; j ++ )
155
+ {
156
+ BookFeatures [ i ] [ j ] = init ;
157
+ }
158
+ }
159
+ int iter_no = 0 ;
160
+ float err = 0 ;
161
+ float rmse = 1f ;
162
+ float old_rmse = 0 ;
163
+ float threshold = 0.01f ;
164
+ float lRate = 0.001f ;
165
+ float K = 0.015f ;
166
+ float mu = 0 , eta = 0.1f , lambda2 = 0.015f , min_improvement = 0.0001f ;
167
+ while ( Math . Abs ( old_rmse - rmse ) > 0.00001 )
168
+ {
169
+ old_rmse = rmse ;
170
+ rmse = 0 ;
171
+ for ( int i = 0 ; i < matr . GetLength ( 0 ) ; i ++ )
133
172
{
134
- for ( int i = 1 ; i <= user . Index ; i ++ ) //ïî þçåðàì
173
+ for ( int j = 0 ; j < matr [ i ] . Length ; j ++ )
135
174
{
136
- double kor = 0 ;
137
- float sum = 0 , sumSquare1 = 0 , sumSquare2 = 0 ;
138
- for ( int j = 0 ; j < maxBookId ; j ++ ) //ïî êíèæêàì
175
+ if ( matr [ i ] [ j ] . RateValue != 0 )
139
176
{
140
- if ( matrix [ user . Index , j ] > 0 && matrix [ user . Index - i , j ] > 0 )
177
+ err = matr [ i ] [ j ] . RateValue -
178
+ ( mu + b_u [ i ] + b_v [ j ] + PreditRating ( UserFeatures [ i ] , BookFeatures [ j ] , features ) ) ;
179
+ rmse += err * err ;
180
+ mu += eta * err ;
181
+ b_v [ j ] += eta * ( err - lambda2 * b_v [ j ] ) ;
182
+ b_u [ i ] += eta * ( err - lambda2 * b_u [ i ] ) ;
183
+ for ( int k = 0 ; k < features ; k ++ )
141
184
{
142
- sum += ( matrix [ user . Index , j ] - average . ElementAt ( user . Index ) ) *
143
- ( matrix [ user . Index - i , j ] - average . ElementAt ( user . Index - i ) ) ;
144
- sumSquare1 += ( matrix [ user . Index , j ] - average . ElementAt ( user . Index ) ) *
145
- ( matrix [ user . Index , j ] - average . ElementAt ( user . Index ) ) ;
146
- sumSquare2 += ( matrix [ user . Index - i , j ] - average . ElementAt ( user . Index - i ) ) *
147
- ( matrix [ user . Index - i , j ] - average . ElementAt ( user . Index - i ) ) ;
185
+ var uprev = UserFeatures [ i ] [ k ] ;
186
+ var bprev = BookFeatures [ j ] [ k ] ;
187
+ UserFeatures [ i ] [ k ] += eta * ( err * bprev - lambda2 * uprev ) ;
188
+ BookFeatures [ j ] [ k ] += eta * ( err * uprev - lambda2 * bprev ) ;
148
189
}
149
190
}
150
- diff . Add ( sumSquare1 ) ;
151
- kor = sum / ( Math . Sqrt ( sumSquare1 ) * Math . Sqrt ( sumSquare2 ) ) ;
152
- //corelation.Add(kor);
153
- corelation [ user . Index , user . Index - i ] = corelation [ user . Index - i , user . Index ] = ( float ) kor ;
154
191
}
155
192
}
193
+ ++ iter_no ;
194
+ rmse = ( float ) Math . Sqrt ( rmse / RateCounter ) ;
195
+ //logger.Info("Iteration: " + iter_no + " RMSE:" + rmse.ToString("F"));
196
+
197
+ if ( rmse > old_rmse - threshold )
198
+ {
199
+ eta = eta * 0.66f ;
200
+ threshold = threshold * 0.5f ;
201
+ }
156
202
}
157
- float [ , ] SubMatrix = ( float [ , ] ) matrix . Clone ( ) ;
158
- for ( int i = 0 ; i < SubMatrix . GetLength ( 0 ) ; i ++ )
203
+
204
+ for ( int i = 0 ; i < MaxUserId ; i ++ )
159
205
{
160
- for ( int j = 0 ; j < SubMatrix . GetLength ( 1 ) ; j ++ )
206
+ for ( int j = 0 ; j < MaxBookId ; j ++ )
161
207
{
162
- if ( SubMatrix [ i , j ] == 0 )
208
+ if ( matr [ i ] [ j ] . RateValue == 0 )
163
209
{
164
- float sum = 0 ;
165
- float sumCor = 0 ;
166
- for ( int k = 0 ; k < SubMatrix . GetLength ( 0 ) ; k ++ )
167
- {
168
- if ( SubMatrix [ k , j ] != 0 )
169
- {
170
- sum += ( SubMatrix [ k , j ] - average [ k ] ) * corelation [ k , i ] ;
171
- sumCor += Math . Abs ( corelation [ k , i ] ) ;
172
- }
173
- }
174
- if ( sum != 0 )
175
- {
176
- Suggest ( average [ i ] + sum / sumCor , users [ i ] . User_ID , j , true ) ;
177
- result [ i , j ] = average [ i ] + sum / sumCor ;
178
- }
210
+ Rate rate = matr [ i ] [ j ] ;
211
+ float sug = mu + b_u [ i ] + b_v [ j ] + PreditRating ( UserFeatures [ i ] , BookFeatures [ j ] , features ) ;
212
+ rate . RateValue = sug ;
213
+ Suggest ( sug , rate . User_ID , rate . Book . Book_ID , true ) ;
179
214
}
180
215
}
181
216
}
217
+
218
+ //var users = GetAll().ToList();
219
+ ////int maxUserId =users.Select(x => x.User_ID).Max();
220
+ //int maxBookId = Context.Books.Select(x => x.Book_ID).Max();
221
+ //float[,] matrix = new float[users.Count, maxBookId];
222
+ //float[,] result = new float[users.Count, maxBookId];
223
+
224
+ ////int[,] korelation = new int[users.Count, users.Count];
225
+ //float[,] corelation = new float[users.Count, users.Count];
226
+ ////List<double> corelation = new List<double>();
227
+ //List<float> average = new List<float>();
228
+ //List<float> diff = new List<float>();
229
+ //foreach (var user in users.Select((x, i) => new { Value = x, Index = i }))
230
+ //{
231
+ // int userId = user.Value.User_ID;
232
+ // float averageRate = 0;
233
+ // int countNonZero = 0;
234
+ // foreach (var rate in GetRatedBooks(userId))
235
+ // {
236
+ // int bookId = rate.Book.Book_ID;
237
+ // matrix[user.Index, bookId] = rate.RateValue;
238
+ // if (rate.RateValue > 0)
239
+ // {
240
+ // averageRate += rate.RateValue;
241
+ // countNonZero++;
242
+ // }
243
+ // }
244
+ // average.Add((float)averageRate / countNonZero);
245
+
246
+ // if (user.Index > 0)
247
+ // {
248
+ // for (int i = 1; i <= user.Index; i++) //ïî þçåðàì
249
+ // {
250
+ // double kor = 0;
251
+ // float sum = 0, sumSquare1 = 0, sumSquare2 = 0;
252
+ // for (int j = 0; j < maxBookId; j++) //ïî êíèæêàì
253
+ // {
254
+ // if (matrix[user.Index, j] > 0 && matrix[user.Index - i, j] > 0)
255
+ // {
256
+ // sum += (matrix[user.Index, j] - average.ElementAt(user.Index)) *
257
+ // (matrix[user.Index - i, j] - average.ElementAt(user.Index - i));
258
+ // sumSquare1 += (matrix[user.Index, j] - average.ElementAt(user.Index)) *
259
+ // (matrix[user.Index, j] - average.ElementAt(user.Index));
260
+ // sumSquare2 += (matrix[user.Index - i, j] - average.ElementAt(user.Index - i)) *
261
+ // (matrix[user.Index - i, j] - average.ElementAt(user.Index - i));
262
+ // }
263
+ // }
264
+ // diff.Add(sumSquare1);
265
+ // kor = sum / (Math.Sqrt(sumSquare1) * Math.Sqrt(sumSquare2));
266
+ // //corelation.Add(kor);
267
+ // corelation[user.Index, user.Index - i] = corelation[user.Index - i, user.Index] = (float)kor;
268
+ // }
269
+ // }
270
+ //}
271
+ //float[,] SubMatrix = (float[,])matrix.Clone();
272
+ //for (int i = 0; i < SubMatrix.GetLength(0); i++)
273
+ //{
274
+ // for (int j = 0; j < SubMatrix.GetLength(1); j++)
275
+ // {
276
+ // if (SubMatrix[i, j] == 0)
277
+ // {
278
+ // float sum = 0;
279
+ // float sumCor = 0;
280
+ // for (int k = 0; k < SubMatrix.GetLength(0); k++)
281
+ // {
282
+ // if (SubMatrix[k, j] != 0)
283
+ // {
284
+ // sum += (SubMatrix[k, j] - average[k]) * corelation[k, i];
285
+ // sumCor += Math.Abs(corelation[k, i]);
286
+ // }
287
+ // }
288
+ // if (sum != 0)
289
+ // {
290
+ // Suggest(average[i] + sum / sumCor, users[i].User_ID, j, true);
291
+ // result[i, j] = average[i] + sum / sumCor;
292
+ // }
293
+ // }
294
+ // }
295
+ //}
182
296
}
183
297
}
184
298
}
0 commit comments