========== Classifier ========== Le module classifier fournit un outil de classification par `inférence bayésienne`_. La probabilité est calculée par la méthode `Robinson-Fisher`_, décrite par Gary Fisher et basée sur le caclul de Fisher, utilisé initialement dans `PopF`. Let's work in a special database:: >>> db_file = 'test.db' >>> import settings >>> settings.SQLURI = 'sqlite:///%s' % db_file Cette implémentation est construite avec une chaîne de tokenizers et un objet de storage:: >>> from tokenizer.filters import AllFilters >>> from storage import SQLStorage >>> from classifier import BayesClassifier >>> backend = SQLStorage('tarek') >>> tokenizer = AllFilters() >>> classifier = BayesClassifier('fr', backend, tokenizer) Le backend doit être vide au début:: >>> backend.word_count() 0 Le classificateur fait deux choses: apprendre et deviner, pour une langue donnée. Apprentissage:: >>> classifier.learn('Achetez du savon KIMOUSS', 'spam') >>> classifier.learn('Salut, savon, comment tu vas ?', 'friend') >>> classifier.learn('KIMOUSS', 'spam') Le storage doit être rempli:: >>> backend.word_count() 6 Et les catégories créées automatiquement:: >>> cats = list(backend.list_categories()) >>> cats.sort() >>> cats [u'friend', u'spam'] Pour gérer la phase de reconnaissance, le classifier doit donner quelques informations:: >>> classifier.corpusSize() 6 >>> classifier.categorySize('spam') 3 Le classifier calcul la propabilité pour chaque mot d'une catégorie, de faire partie du calcul (pour les mots qui sont dans n catégories:: >>> sorted(classifier._buildCategoryWordProbabilities('spam').items()) #1 [(u'achetez', 0.99...), (u'kimouss', 0.99...)] >>> classifier.learn('savon kipouss par-ci, savon par-la, savon toujours', ... 'song') >>> sorted(classifier._buildCategoryWordProbabilities('spam').items()) #2 [(u'achetez', 0.99...), (u'kimouss', 0.99...), (u'savon', 0.14...)] >>> classifier.categorySize('song') 4 >>> sorted(classifier._buildCategoryWordProbabilities('song').items()) [(u'kipouss', 0.99...), (u'par', 0.99...), (u'toujours', 0.99...)] Ce calcul est fait pour toutes les catégories:: >>> sorted(classifier._buildWordProbabilities().items()) [(u'friend', {...}), (u'song', {...}), (u'spam', {...})] La reconnaissance se base sur ce filtrage de mots, puis applique l'algo de Robinson-fisher:: >>> classifier.guess('achetez mon savon KIPOUSS') [(u'song', 0.99...), (u'spam', 0.70...), (u'friend', 0.16...)] We lower default treshold first:: >>> classifier.options['treshold'] = 1 Reprenons un exemple concret pour vérifier que le classificateur marche bien, soit l'exemple de divmod pour Reverend:: >>> classifier = BayesClassifier('fr', backend, tokenizer, treshold=1) >>> classifier.learn('le la les du un une je il elle de en', 'french') >>> classifier.learn('der die das ein eine', 'german') >>> classifier.learn('el uno una las de la en', 'spanish') >>> classifier.learn('the rain in spain falls mainly on the plain', 'english') >>> classifier.learn('the it she he they them are were to', 'english') Résultats:: >>> classifier.guess('they went to el cantina') [(u'english', 0.999...), (u'spanish', 0.999...)] >>> classifier.guess('they were flying planes') [(u'english', 0.999...)] Plus d'exemples, pour le plaisir :), un outil de reconnaissance de texte, qui sait faire la différence entre un fichier texte de type doctest et un fichier de code python:: >>> import classifier >>> import os >>> root = os.path.dirname(classifier.__file__) >>> root = os.path.split(os.path.realpath(root))[0] >>> file = os.path.join(root, 'classifier', 'classifier.py') >>> source = open(file).read() >>> file = os.path.join(root, 'classifier', 'storage.py') >>> source2 = open(file).read() >>> file = os.path.join(root, 'classifier', 'doc', 'storage.txt') >>> texte = open(file).read() >>> backend = SQLStorage('tarek') >>> classifier = BayesClassifier('en', backend, tokenizer, treshold=2) >>> classifier.learn(source, 'python') >>> classifier.learn(texte, 'doctest') >>> classifier.learn(source2, 'python') Saura-t-il reconnaitre `classifier.py` comme étant du code python ? :: >>> file = os.path.join(root, 'classifier', 'classifier.py') >>> source2 = open(file).read() >>> classifier.guess(source2) [(u'python', ...), ...] Le classificateur doit aussi savoir `désapprendre`:: >>> classifier.unlearn(source, 'python') >>> classifier.unlearn(source2, 'python') >>> classifier.guess(source2) [(u'doctest', ...), ...] Définitions ___________ _`inférence bayésienne`: On nomme inférence bayésienne la démarche logique permettant de calculer ou réviser la probabilité d'une hypothèse. Cette démarche est régie par l'utilisation de règles strictes de combinaison des probabilités, desquelles dérive le théorème de Bayes. Dans la perspective bayésienne, une probabilité n'est pas interprétée comme le passage à la limite d'une fréquence, mais plutôt comme la traduction numérique d'un état de connaissance (le degré de confiance accordé à une hypothèse, par exemple; (Wikipédia) Let's remove the test db:: >>> import os >>> os.remove(db_file) .. _`PopF`: http://christophe.delord.free.fr/fr/popf/index.html