If you use something like rspamd, then doing ML is not terribly hard. Then it becomes a problem of providing a proper teaching set. Combining RBL's (be it URI, IP or domain WL's or BL's) will help with that.
In the end it's still a hard problem, so takes a bunch of work.
Honestly, the best filter in my experience is Spamhaus Zen; it spots most spam with very few FPs. It's an IP blocklist.