This code is a suggestion. It works nearly as the current spam.module rating. The difference is mainly in the SQL query, but should have some differences in the statistics as well. The total effect comes from clipping the query results to contain
only 'interesting' tokens and optionally limit the result with a hard shoulder ($max). The hard shoulder is probably an overkill,
since we are already filtering the 'unimportant' tokens, but might prove useful if the minimum drift is too small.
<code>
function _naiveBayes($tokens) {
$probs = array();
$drift = variable_get('spam_min_drift', 40);
$max = variable_get('spam_max_tokens', 40);
$num=0;
//a rewrite of the original - it should not reduce the quality of the
//predictions, while it has the potential to increase speed. Speed
//difference depends on the speed of execution of asort() and the
//number of interesting tokens considered the added comparison and
//evaluation in SQL
//$drift - minimal drift from the median - a soft-ish shoulder of the
// filter
//$max - maximum number of tokens to evaluate, a hard shoulder of the
// filter
foreach($tokens as $token){
//1. may be beneficial not to include $max or make it larger
//2. the sql syntax should be relatively portable to postgres,
// but haven't checked the details
$result = db_query("SELECT probability FROM {spam_tokens} WHERE
token='%s' AND (ABS(50 - probablility) >= %d) AND last >= %d SORT BY
(ABS(50 - probability) LIMIT %d)", $token,$drift, $max);
while($p=db_fetch_object($result)){
if( $p->probability ) {
$p->probability = variable_get('spam_unknown_probability',40);
}
$probs += $p->probability;
$num++;
}
}
$rating = ($probs + $weight) / $num;
if ($rating > 99)
$rating = 99;
else if ($rating < 1)
$rating = 1;
return $rating;
}
Comments
Comment #1
dikini commentedI'm stupid. Dit it again! I add the right fragment. The attached file should contain the function.
Comment #2
dikini commentedsome syntax errors were left - this is what happens when you cut, paste and adapt without actually running it.
Comment #3
(not verified) commentedIt's preferred that you attach patches rather than snippets.
In any case, a quick glance at your code and I notice you have more "%s/%d's" than you have variables in your db_query. Otherwise, it does appear to simplify things, and loads less into memory. I'll try and test it later this week.
-Jeremy
Comment #4
dikini commentedI corrected the code, added the proper variable_get for $max, wrapped all that in a patch. Sorry for the previous inconsistensies, but the code is copied from a classifier module I am working on. It is a bit heavier. So, I had to on the fly crop the code to fit into the spam.module conventions.
--
Vlado
Comment #5
dikini commentedanother small fix of the leftovers, removed the unnessesary while loop, it was used for looping over different classes, but we just
detect spam here. Hopefully the last omission. Apologies for the cruft.
--
Vlado
Comment #6
dikini commenteddoing the walk of shame, I update with the next installment of my stupid ommissions.
Comment #7
jeremy commentedA quick glance at that patch, and it seems to be making a lot of non-changes. That is, It changes "}" to "}", or " " to " ". Why? Is this intentional?
I hope to have time this weekend to review/test your changes. Thanks.
Comment #8
dikini commentedno, it is not, probaby added by my editor, spaces I suppose, I'll have a look at that.
Comment #9
jeremy commentedThis logic does not appear to work. Did you actually test it?
Assuming the default value for 'spam_min_drift' of 40, this will only look at tokens that have a probability of 1-10 or 80-99. I'm not sure this is desirable. I suppose perhaps if 'spam_min_drift' was derived from 'spam_threshold' it might work, as we primarily care if a message is greater than or less than this threshold. But then, if you only pay attention to those within a certain drift, you could completely offset the weight. For example, if a comment has three tokens, one with a probability of 60, one of 50, and one of 99, this should weight (60+50+99)/3 which is 70, not spam. But your method would ignore the 60 and 50, and thus would rate the comment 99, which would be spam. This is wrong.
More, the db_query is completely broken. "last" is unrelated to the drift. "last" is a timestamp from the last time a given token was matched.
I like the idea of improving efficiency, but this patch needs a lot of work before it will meet this goal.
Comment #10
dikini commented