Currently, bogofilter offers a choice of three classification methods:
the original as proposed by Paul Graham and implemented in bogofilter
by Eric S. Raymond, a variation proposed by Gary Robinson and
implemented in bogofilter by Greg Louis, and a further variation, also
proposed by Gary Robinson, which uses Fisher's method of combining
probabilities; for bogofilter, Greg Louis has implemented this one too.

Both of Gary Robinson's proposed classification methods work better
than the original; however, they require some tuning.  If the user does
not take the time to do the tuning, the results may be _worse_ than
those obtained with Paul Graham's original method.

With Robinson's changes as implemented in bogofilter, there are four
things to tune:

SPAM_CUTOFF is the threshold of "spamicity" above which the message is
deemed spam.  You move this up or down till you have the balance you
want between false positives and false negatives.  As the training set
grows and discrimination improves, you can edge SPAM_CUTOFF up a bit
since we usually want the absolute minimum false positives compatible
with not getting a flood of false negatives.

ROBS and ROBX (which Gary just calls s and x, and I will too to save
typing) work together.  A good starting value for x is the average of
  p(w) = badcount / (goodcount + badcount)
for every word in your training set that appears at least 10 times in
both bad and good wordlists (ie badcount >= 10 and goodcount >= 10).

Ok, I oversimplified: you have to scale the counts somehow.  If you had
exactly the same number of messages contributing to your good and bad
wordlists, the formula for p(w) given above would be ok; but we
actually have to use
  scalefactor = badlist_msgcount / goodlist_msgcount
  p(w) = badcount / (badcount + goodcount * scalefactor)
and average those p(w) values.

A good starting value for s is 0.001 (determined empirically), but you
might want to take the time to get a feel for what happens if you move
s up and down through a couple of orders of magnitude.  The value of x
is the f(w) value that a token will get if it has zero occurrences in
the training set.  The formula is
  f(w) = (s * x + badcount) / (s + badcount + goodcount * scalefactor)
and you can see that if both counts are 0, you get x; if both counts
are small, x will have an influence on f(w) that varies with the
magnitude of s.

The thought behind this calculation is that x is really a "first guess"
at what the presence of an unknown token means in terms of
spammishness.  With counts of zero, we have only that guess to go on,
so that's what we use.  But with counts that are small though nonzero,
the Graham p(w) (defined above) is likely to be unreliable, so we ought
to (and f(w) does) compromise between our "first guess" and what the
counts say.  Once the counts get to a decent size, x becomes
insignificant and f(w) becomes, in effect, the Graham p(w).

So s and x are only important when the counts are small, and the value
of s reflects what we think of as "small."  If s is large, then when
counts are small we trust our x value more than we do the p(w); if s is
small, we give more weight to p(w) and less to x.  But obviously,
tuning s and x is going to be of little use when your training set is
large enough that your messages have few new or little-known tokens.

MIN_DEV is the last of the four things you might want to play with.  By
default, it's zero; every token in the message contributes its
spammishness value f(w) to the final calculation.  We might save time
and even improve discrimination a bit if we ignore tokens with f(w)
values near 0.5, since those tokens obviously aren't making a great
difference to the outcome of the calculation.  MIN_DEV specifies how
different a value of f(w) has to be from 0.5 in order for that value to
be included in the calcualation of S, the "spamicity" of the message.
I've played with MIN_DEV values of up to 0.4, where only words with
f(w) less than 0.1 or greater than 0.9 are taken into account.  For a
time, it seemed best to use all the words in the message; why throw
away information?  On the other hand, words like "you" or "there" don't
really contribute that much to the decision, and processing them takes
time; I'm now using MIN_DEV=0.1 and it seems to work well for me.
