** Ceci est l'article du premier jour de Real Escape Advent Calendar 2013 **
Commençons par l'apprentissage automatique Implémentons le 3ème filtre basilien Implémentation des baies naïves introduites dans.
Cependant, le code de cet article est un peu déroutant. Plus précisément, il existe de nombreux pièges, tels que le nom de la variable est un mot singulier appelé mot, mais le type est liste. De plus, j'ai trouvé une erreur courante dans la Liste 7 à la page 3 que l'opérateur de comparaison
Donc, le filtre basilien introduit dans cet article
--En Python 3.3 --Utilisation de MeCab au lieu de l'analyse morphologique japonaise de Yahoo! Developers Network --Plus lisible
Réimplémenté.
À l'aide du filtre Basian créé dans cet article, nous avons appris et classé à l'aide de la page Web acquise à l'aide de l'API Bing. http://qiita.com/katryo/items/62291ba328de9d12bd30
naive_bayes.py
#coding:utf-8
# http://gihyo.jp/dev/serial/01/machine-learning/Python3 avec l'implémentation du filtre basilien de 0003.Amélioré pour être lisible pendant 3
import math
import sys
import MeCab
class NaiveBayes():
def __init__(self):
self.vocabularies = set()
self.word_count = {} # {'Mesures contre la pollinose': {'Pollen Sugi': 4, 'médicament': 2,...} }
self.category_count = {} # {'Mesures contre la pollinose': 16, ...}
def to_words(self, sentence):
"""
contribution: 'Tout à moi'
production: tuple(['tout', 'moi même', 'de', 'Comment', 'Quoi'])
"""
tagger = MeCab.Tagger('mecabrc') #Vous pouvez utiliser un autre Tagger
mecab_result = tagger.parse(sentence)
info_of_words = mecab_result.split('\n')
words = []
for info in info_of_words:
#Si vous divisez par macab, "" est à la fin de la phrase, avant cela'EOS'Arrive
if info == 'EOS' or info == '':
break
# info => 'Nana\t assistant,Aide finale,*,*,*,*,Nana,N / a,N / a'
info_elems = info.split(',')
#Sixièmement, il y a des mots qui ne sont pas utilisés. Si le sixième est'*'Si tel est le cas, entrez le 0e
if info_elems[6] == '*':
# info_elems[0] => 'Van Rossam\t substantif'
words.append(info_elems[0][:-3])
continue
words.append(info_elems[6])
return tuple(words)
def word_count_up(self, word, category):
self.word_count.setdefault(category, {})
self.word_count[category].setdefault(word, 0)
self.word_count[category][word] += 1
self.vocabularies.add(word)
def category_count_up(self, category):
self.category_count.setdefault(category, 0)
self.category_count[category] += 1
def train(self, doc, category):
words = self.to_words(doc)
for word in words:
self.word_count_up(word, category)
self.category_count_up(category)
def prior_prob(self, category):
num_of_categories = sum(self.category_count.values())
num_of_docs_of_the_category = self.category_count[category]
return num_of_docs_of_the_category / num_of_categories
def num_of_appearance(self, word, category):
if word in self.word_count[category]:
return self.word_count[category][word]
return 0
def word_prob(self, word, category):
#Calcul de la loi bayésienne. Généralement une fraction très proche de zéro.
numerator = self.num_of_appearance(word, category) + 1 # +1 est la méthode de Laplace de lissage additif
denominator = sum(self.word_count[category].values()) + len(self.vocabularies)
#Dans Python3, la division est automatiquement flottante
prob = numerator / denominator
return prob
def score(self, words, category):
#C'est un mot pour prendre le journal_prob vaut 0.000....Parce que cela devient un petit nombre d'environ 01
score = math.log(self.prior_prob(category))
for word in words:
score += math.log(self.word_prob(word, category))
return score
#Si vous ne vous connectez pas, la valeur est peut-être trop petite et insuffisante.
def score_without_log(self, words, category):
score = self.prior_prob(category)
for word in words:
score *= self.word_prob(word, category)
return score
def classify(self, doc):
best_guessed_category = None
max_prob_before = -sys.maxsize
words = self.to_words(doc)
for category in self.category_count.keys():
prob = self.score(words, category)
if prob > max_prob_before:
max_prob_before = prob
best_guessed_category = category
return best_guessed_category
if __name__ == '__main__':
nb = NaiveBayes()
nb.train('''Python est un langage de programmation open source créé par le Néerlandais Guido Van Rossam.
C'est un type de langage de script orienté objet et est largement utilisé en Europe et aux États-Unis avec Perl. Nommé d'après la comédie "Flying Monty Python" produite par la chaîne de télévision britannique BBC.
Python signifie reptile Nishiki snake en anglais et est parfois utilisé comme mascotte ou icône dans le langage Python. Python est un langage de haut niveau à usage général. Conçu avec un accent sur la productivité du programmeur et la fiabilité du code, il dispose d'une grande bibliothèque standard pratique avec une syntaxe et une sémantique de base minimales.
Il prend en charge les opérations de chaîne en utilisant Unicode, et le traitement japonais est également possible en standard. Il prend en charge de nombreuses plates-formes (plates-formes de travail), et dispose de documents abondants et de bibliothèques abondantes, de sorte que son utilisation augmente dans l'industrie.
''',
'Python')
nb.train('''Serpent (serpent) est un terme général pour les reptiles qui sont classés dans l'ordre Serpentes.
Il se caractérise par son corps élancé et sans membres. Cependant, des animaux de forme similaire existent également dans d'autres groupes.
''', 'Snake')
nb.train('''Ruby est un langage de script orienté objet développé par Yukihiro Matsumoto (communément appelé Matz).
Réalise la programmation orientée objet dans les domaines où les langages de script tels que Perl ont été traditionnellement utilisés.
Ruby est né le 24 février 1993 et a été annoncé le fj en décembre 1995.
Le nom Ruby est dû au fait que le langage de programmation Perl prononce la même chose que Pearl, la pierre de naissance de juin.
Il a été nommé d'après le rubis de la pierre de naissance du collègue de Matsumoto (juillet).
''',
'Ruby')
nb.train('''Ruby (anglais:Ruby, Kodama) est une variante du Corindon (bille d'acier). C'est un bijou avec une couleur rouge caractéristique.
Les rubis naturels sont produits en Asie et ne peuvent être obtenus en Europe et aux États-Unis.
Même dans la zone de production, les endroits où les belles pierres pouvant être utilisées comme bijoux peuvent être obtenues sont extrêmement limités.
Les grosses pierres de plus de 3 carats ont également un faible rendement.
''', 'Gem')
doc = 'Open source réalisé par Guido Van Rossam'
print('%s =>Catégorie estimée: %s' % (doc, nb.classify(doc))) #Catégorie estimée:Devrait être Python
print('Probabilité d'être dans la catégorie Python: %s' % nb.score_without_log(['Guido Van Rossam', 'Mais', 'Avait fait'], 'Python'))
print('Probabilité d'être dans la catégorie Ruby: %s' % nb.score_without_log(['Guido Van Rossam', 'Mais', 'Avait fait'], 'Ruby'))
doc = 'Le langage de programmation Ruby est un pur langage orienté objet.'
print('%s =>Catégorie estimée: %s' % (doc, nb.classify(doc))) #Catégorie estimée:Devrait être Ruby
print('Probabilité d'être dans la catégorie Ruby: %s' % nb.score_without_log(['Langage de programmation', 'de', 'Ruby', 'Est', 'pur', 'Nana', 'Langage orienté objet', 'est', '。'], 'Ruby'))
print('Probabilité d'être dans la catégorie Python: %s' % nb.score_without_log(['Langage de programmation', 'de', 'Ruby', 'Est', 'pur', 'Nana', 'Langage orienté objet', 'est', '。'], 'Python'))
doc = 'corindon'
print('%s =>Catégorie estimée: %s' % (doc, nb.classify(doc))) #Catégorie estimée:Devrait être un bijou
print('Probabilité d'être dans la catégorie Gem: %s' % nb.score_without_log(['corindon'], 'Gem'))
print('Probabilité d'être dans la catégorie Ruby: %s' % nb.score_without_log(['corindon'], 'Ruby'))
Nous expliquerons ce que fait ce code, le divisant en formation et le classer.
La méthode train (self, doc, category) de NaiveBayes entre la chaîne doc et la catégorie à laquelle appartient la chaîne, et place le document avec ce mot dans cette catégorie dans l'objet NaiveBayes. "Devrais-je?"
Ce qui suit est un résumé.
Parmi les catégories saisies jusqu'à présent dans la phase d'apprentissage, «Quelle est la plus plausible pour inclure le texte saisi?» Est calculée.
En d'autres termes, la méthode du score est utilisée pour chaque catégorie pour calculer la probabilité (le log est pris pour faciliter le calcul).
Celle avec le score le plus élevé parmi toutes les catégories est considérée comme la catégorie avec la probabilité la plus élevée, et cette catégorie est finalement sortie. A ce moment, la méthode de Laplace de lissage par addition est utilisée.
Pourquoi utilisez-vous log dans la fonction score et calculez-vous la probabilité calculée avec prior_prob et word_prob de manière logarithmique?
Comme indiqué dans Article original de la revue technique, la probabilité calculée par la formule de la loi de Bayes La valeur de est très proche de 0. Le nombre total de mots qui apparaissent dans un document est énorme, et le nombre de fois qu'un mot particulier (tel que "Python", "pur" ou "fait") apparaît est très petit en comparaison. Par conséquent, le logarithme est pris avec e afin qu'il puisse être calculé même s'il est proche de 0.
Alors que faire si nous calculons cette probabilité sans journalisation? Essayons.
def score(self, words, category):
#C'est un mot pour prendre le journal_prob vaut 0.000....Parce que cela devient un petit nombre d'environ 01
score = math.log(self.prior_prob(category))
for word in words:
score += math.log(self.word_prob(word, category))
return score
#Si vous ne vous connectez pas, la valeur est peut-être trop petite et insuffisante.
def score_without_log(self, words, category):
score = self.prior_prob(category)
for word in words:
score *= self.word_prob(word, category)
return score
score_without_log est une version qui calcule la probabilité sans prendre le logarithmique. Prendre le logarithme de a * b * c donne log (a) + log (b) + log (c). Dans la méthode de score, le résultat du calcul de word_prob a été ajouté à plusieurs reprises pour marquer dans la boucle pour mot dans les mots, mais dans la méthode score_without_log, il est multiplié à plusieurs reprises.
Si vous exécutez le code dans naive_bayes.py tel quel, vous pouvez voir l'effet de la journalisation.
À propos, cette partie du code forme quatre catégories de "Python, Snake, Gem, Ruby".
naive_bayes.py
if __name__ == '__main__':
nb = NaiveBayes()
nb.train('''Python est un langage de programmation open source créé par le Néerlandais Guido Van Rossam.
C'est un type de langage de script orienté objet et est largement utilisé en Europe et aux États-Unis avec Perl. Nommé d'après la comédie "Flying Monty Python" produite par la chaîne de télévision britannique BBC.
Python signifie reptile Nishiki snake en anglais et est parfois utilisé comme mascotte ou icône dans le langage Python. Python est un langage de haut niveau à usage général. Conçu avec un accent sur la productivité du programmeur et la fiabilité du code, il dispose d'une grande bibliothèque standard pratique avec une syntaxe et une sémantique de base minimales.
Il prend en charge les opérations de chaîne en utilisant Unicode, et le traitement japonais est également possible en standard. Il prend en charge de nombreuses plates-formes (plates-formes de travail), et dispose de documents abondants et de bibliothèques abondantes, de sorte que son utilisation augmente dans l'industrie.
''',
'Python')
nb.train('''Serpent (serpent) est un terme général pour les reptiles qui sont classés dans l'ordre Serpentes.
Il se caractérise par son corps élancé et sans membres. Cependant, des animaux de forme similaire existent également dans d'autres groupes.
''', 'Snake')
nb.train('''Ruby est un langage de script orienté objet développé par Yukihiro Matsumoto (communément appelé Matz).
Réalise la programmation orientée objet dans les domaines où les langages de script tels que Perl ont été traditionnellement utilisés.
Ruby est né le 24 février 1993 et a été annoncé le fj en décembre 1995.
Le nom Ruby est dû au fait que le langage de programmation Perl prononce la même chose que Pearl, la pierre de naissance de juin.
Il a été nommé d'après le rubis de la pierre de naissance du collègue de Matsumoto (juillet).
''',
'Ruby')
nb.train('''Ruby (anglais:Ruby, Kodama) est une variante du Corindon (bille d'acier). C'est un bijou avec une couleur rouge caractéristique.
Les rubis naturels sont produits en Asie et ne peuvent être obtenus en Europe et aux États-Unis.
Même dans la zone de production, les endroits où les belles pierres pouvant être utilisées comme bijoux peuvent être obtenues sont extrêmement limités.
Les grosses pierres de plus de 3 carats ont également un faible rendement.
''', 'Gem')
doc = 'Open source réalisé par Guido Van Rossam'
print('%s =>Catégorie estimée: %s' % (doc, nb.classify(doc))) #Catégorie estimée:Devrait être Python
print('Probabilité d'être dans la catégorie Python: %s' % nb.score_without_log(['Guido Van Rossam', 'Mais', 'Avait fait'], 'Python'))
print('Probabilité d'être dans la catégorie Ruby: %s' % nb.score_without_log(['Guido Van Rossam', 'Mais', 'Avait fait'], 'Ruby'))
doc = 'Le langage de programmation Ruby est un pur langage orienté objet.'
print('%s =>Catégorie estimée: %s' % (doc, nb.classify(doc))) #Catégorie estimée:Devrait être Ruby
print('Probabilité d'être dans la catégorie Ruby: %s' % nb.score_without_log(['Langage de programmation', 'de', 'Ruby', 'Est', 'pur', 'Nana', 'Langage orienté objet', 'est', '。'], 'Ruby'))
print('Probabilité d'être dans la catégorie Python: %s' % nb.score_without_log(['Langage de programmation', 'de', 'Ruby', 'Est', 'pur', 'Nana', 'Langage orienté objet', 'est', '。'], 'Python'))
doc = 'corindon'
print('%s =>Catégorie estimée: %s' % (doc, nb.classify(doc))) #Catégorie estimée:Devrait être un bijou
print('Probabilité d'être dans la catégorie Gem: %s' % nb.score_without_log(['corindon'], 'Gem'))
print('Probabilité d'être dans la catégorie Ruby: %s' % nb.score_without_log(['corindon'], 'Ruby'))
C'est le résultat de l'exécution.
Open source réalisé par Guido Van Rossam=>Catégorie estimée: Python
Probabilité d'être dans la catégorie Python: 5.05740150710565e-08
Probabilité d'être dans la catégorie Ruby: 2.592066486298008e-08
Le langage de programmation Ruby est un pur langage orienté objet. =>Catégorie estimée: Ruby
Probabilité d'être dans la catégorie Ruby: 1.0568043348436783e-20
Probabilité d'être dans la catégorie Python: 1.4013428667584096e-21
corindon=>Catégorie estimée: Gem
Probabilité d'être dans la catégorie Gem: 0.0018248175182481751
Probabilité d'être dans la catégorie Ruby: 0.0008143322475570033
** 1.0568043348436783e-20 ** …… (゚ Д ゚;)
10 moins 20 puissance. C'est un nombre très proche de 0.
Plus la chaîne d'entrée est longue, moins elle est susceptible de tomber dans une catégorie particulière. Au contraire, le dernier exemple consiste à raccourcir la chaîne de caractères d'entrée et à calculer la probabilité d'entrer dans une catégorie spécifique uniquement par "corindon". Mais quand même, la probabilité d'être dans la catégorie la plus probable «Gem» n'est que de ** 0,0018248175182481751 **. 0,18%. C'est beaucoup plus grand que la probabilité de 0,0008143322475570033 d'être dans la catégorie "Ruby", mais c'est encore très petit. Vous pouvez voir que c'est un nombre difficile à calculer.
Article japonais sur Naive Bays http://aidiary.hatenablog.com/entry/20100613/1276389337
À l'aide du filtre Basian créé dans cet article, nous avons appris et classé à l'aide de la page Web acquise à l'aide de l'API Bing. Cliquez ici pour la suite http://qiita.com/katryo/items/62291ba328de9d12bd30
Recommended Posts