function recommender_prediction_slopeone in Recommender API 5
Same name and namespace in other branches
- 6 recommender.module \recommender_prediction_slopeone()
- 6.2 recommender.module \recommender_prediction_slopeone()
This is the implementation of slope-one algorithm, which is supposed to be faster than other algrithms. From the original research paper, the author argues slope-one support incremental update. But this is quite hard to implement. The incremental update doesn't work for now. Missing data is just treated as missing. For slope-one, we don't automatically expand the matrix to have zeros. The responsibility of handling missing data is on the caller functions.
Parameters
$app_name the application name that uses this function.:
$table_name the input table name:
$field_mouse the input table field for mouse:
$field_cheese the input table field for cheese:
$field_weight the input table field weight:
$options an array of options: 'extention': whether to use 'basic', 'weighted', or 'bipolar' extensions of the algorithm. Please refer to the original research paper. Usually it could just be 'weighted'. 'duplicate': how to handle predictions that already exists in mouse-cheese evaluation. 'preserve' or 'eliminate' 'incremental': whether to 'rebuild' or to 'update'. CAUTION: 'update' doesn't work now.
Return value
null {recommender_prediction} will be filled with prediction data
File
- ./
recommender.module, line 452 - Providing generic recommender system algorithms.
Code
function recommender_prediction_slopeone($app_name, $table_name, $field_mouse, $field_cheese, $field_weight, $options = array()) {
// get param values
$app_id = recommender_get_app_id($app_name);
$extension = isset($options['extension']) ? $options['extension'] : 'weighted';
// could be 'weighted', 'bipolar'
$incremental = isset($options['incremental']) ? $options['incremental'] : 'rebuild';
// could be 'update'
$duplicate = isset($options['duplicate']) ? $options['duplicate'] : 'eliminate';
// or 'preserve'
$created = time();
db_query("DELETE FROM {recommender_slopeone_dev} WHERE app_id=%d", $app_id);
// create dev(i,j)
db_query("INSERT INTO {recommender_slopeone_dev}(app_id, cheese1_id, cheese2_id, count, dev)\n SELECT %d, n1.{$field_cheese}, n2.{$field_cheese},\n COUNT(*), AVG(n1.{$field_weight}-n2.{$field_weight}) FROM {{$table_name}} n1\n INNER JOIN {{$table_name}} n2 ON n1.{$field_mouse}=n2.{$field_mouse}\n AND n1.{$field_cheese} <> n2.{$field_cheese}\n GROUP BY n1.{$field_cheese}, n2.{$field_cheese}", $app_id);
// create P(u,j)
if ($extension == 'basic') {
$extension_sql = "AVG(t.{$field_weight}+p.dev)";
}
else {
if ($extension == 'weighted') {
// the 'weighted slope one'
$extension_sql = "SUM((t.{$field_weight}+p.dev)*p.count)/SUM(p.count)";
}
}
// haven't implemented the "bipolar" extension of Slope One.
// generate predictions.
db_query("INSERT INTO {recommender_prediction}(app_id, mouse_id, cheese_id, prediction, created)\n SELECT %d, t.{$field_mouse}, p.cheese1_id, {$extension_sql}, %d\n FROM {recommender_slopeone_dev} p INNER JOIN {{$table_name}} t ON p.cheese2_id=t.{$field_cheese}\n GROUP BY t.{$field_mouse}, p.cheese1_id", $app_id, $created);
// remove duplicate prediction
if ($duplicate == 'eliminate') {
db_query("DELETE FROM {recommender_prediction} WHERE app_id=%d AND created=%d AND (mouse_id, cheese_id)\n IN (SELECT {$field_mouse}, {$field_cheese} FROM {{$table_name}})", $app_id, $created);
}
db_query("DELETE FROM {recommender_prediction} WHERE app_id=%d AND created<>%d", $app_id, $created);
}