La dernière fois, j'ai expliqué la théorie de Naive Bayes (formule mathématique) dans Les débutants en apprentissage automatique essayent de toucher Naive Bayes (1) - Théorie. fait.
Sur cette page, je vais essayer une implémentation simple en utilisant Python. Comme d'habitude, il est réalisé en imitant le site auquel j'ai fait référence, donc il vous sera expliqué & cette explication si vous êtes intéressé. Au fait, je n'ai pas du tout écrit Python, alors regardez avec des yeux chaleureux ...
L'exemple de code se trouve en bas.
La formule Naive Bayes pourrait être exprimée comme suit:
P(cat|doc) = \log P(cat) + \prod_{i=0}^k \log P(word_k|cat)
Je ne sais pas si c'est un programme ... J'organiserai d'abord ce dont j'ai besoin.
< P(cat) >
{'cat1': 1, 'cat2': 1, ...}
< P(word|cat) >
{'cat1': {'word1': 1, ...}, ...}
nb = NaiveBayes()
nb.train(data)
Je veux l'utiliser comme ci-dessus, donc je le conçois comme une classe. Si vous déclarez ce dont vous avez besoin ci-dessus avec init, le code jusqu'à __init__
sera ..
class NaiveBayes:
def __init__(self):
self.vocabularies = set() #Catégorie non dupliquée
self.categories = set() #Vocabulaire sans chevauchement
self.category_count = {} #Nombre d'occurrences de la catégorie, category_count[cat]
self.word_count = {} #Nombre d'occurrences de mot pour chaque catégorie, word_count[cat]
...
set ()
est un tableau unique. Utilisé pour les vocabulaires, les catégories.{}
Est un dictionnaire. Il est utilisé pour compter le nombre de catégories et le nombre de mots dans chaque catégorie.def train(self, data):
self.category_count = defaultdict(lambda: 0)
for d in data:
category = d[0]
self.categories.add(category) #Ajouter une catégorie
self.category_count[category] += 1
for word in d[1:]: #Ajouter du vocabulaire
self.vocabularies.add(word)
for category in self.categories:
self.word_count[category] = defaultdict(lambda: 0)
for d in data:
category = d[0]
for word in d[1:]:
self.word_count[category][word] += 1
Ceci est une préparation. Déjà ... c'est tout.
from collections import defaultdict
hash = {}
hash = defaultdict(lambda: 0)
Vous pouvez utiliser defaultdict
pour spécifier la valeur initiale quand il n'y a pas de valeur. J'étais inquiet pour le lissage de Laplace, mais j'ai décidé d'ajouter «+ 1» au calcul.
P(word|cat)
\prod_{i=0}^k \log P(word_k|cat)
Définissez une fonction appelée word_probability
pour calculer chaque terme de. Comment le trouver
P(word_k|cat) = \frac{Catégorie(cat)Mots dans(word)Nombre d'apparitions+ 1}{Catégorie(cat)Nombre total de mots qui apparaissent dans+Nombre total de mots}
C'était. Ici, nous appliquons «Laplace Smoothing».
def word_probability(self, word, category):
'''Probabilité d'être une catégorie lorsqu'un mot est donné, P(word|cat)'''
#Appliquer le lissage Laplace
word_count = self.word_count[category][word] + 1
vocabulary_count = sum(self.word_count[category].values()) + len(self.vocabularies)
return float(word_count) / float(vocabulary_count)
Calculez P (cat | doc)
.
P(cat|doc) = \log P(cat) + \prod_{i=0}^k \log P(word_k|cat)
Lorsqu'une phrase est donnée, la fonction ci-dessus est utilisée pour créer une fonction qui calcule le score car la probabilité totale de chaque mot doit être calculée.
Cependant, veuillez noter que la multiplication des journaux avec la même base est la somme de la somme et non la somme de la somme.
De plus, puisque la base de «log est 10», ce sera une valeur négative lors du calcul. Personnellement, je n'ai pas aimé, alors j'ai fait x (-1)
à la fin. Je pense que l'un ou l'autre est bien.
D'abord, mettez P (cat)
dans score
, puis ajoutez P (mot | chat)
dans une boucle.
def score(self, words, category):
'''des documents(mot)Probabilité d'être une catégorie donnée'''
documents_count = sum(self.category_count.values())
score = math.log(float(self.category_count[category]) / documents_count)
for word in words:
score += math.log(self.word_probability(word, category))
#Parce que le bas du journal est 10, il sera négatif+À
return score * (-1)
Eh bien, c'est finalement la classification. En réalité, je pense que vous appellerez cette fonction après l'entraînement.
def classify(self, words):
'''P(cat|doc)Renvoie la plus grande catégorie'''
best = None
value = 0
for category in self.categories:
v = self.score(words, category)
if v > value:
best = category
value = v
return best
La structure est simple, elle calcule le score de toutes les catégories passées en phase d'apprentissage et renvoie la plus élevée.
#coding:utf-8
from collections import defaultdict
import math
class NaiveBayes:
def __init__(self):
self.vocabularies = set() #Catégorie non dupliquée
self.categories = set() #Vocabulaire sans chevauchement
self.category_count = {} #Nombre d'occurrences de la catégorie, category_count[cat]
self.word_count = {} #Nombre d'occurrences de mot pour chaque catégorie, word_count[cat]
def train(self, data):
self.category_count = defaultdict(lambda: 0)
for d in data:
category = d[0]
self.categories.add(category) #Ajouter une catégorie
self.category_count[category] += 1
for word in d[1:]: #Ajouter du vocabulaire
self.vocabularies.add(word)
for category in self.categories:
self.word_count[category] = defaultdict(lambda: 0)
for d in data:
category = d[0]
for word in d[1:]:
self.word_count[category][word] += 1
def word_probability(self, word, category):
'''Probabilité d'être une catégorie lorsqu'un mot est donné, P(word|cat)'''
#Appliquer le lissage Laplace
word_count = self.word_count[category][word] + 1
vocabulary_count = sum(self.word_count[category].values()) + len(self.vocabularies)
return float(word_count) / float(vocabulary_count)
def score(self, words, category):
'''des documents(mot)Probabilité d'être une catégorie donnée'''
documents_count = sum(self.category_count.values())
score = math.log(float(self.category_count[category]) / documents_count)
for word in words:
score += math.log(self.word_probability(word, category))
#Parce que le bas du journal est 10, il sera négatif+À
return score * (-1)
def classify(self, words):
'''P(cat|doc)Renvoie la plus grande catégorie'''
best = None
value = 0
for category in self.categories:
v = self.score(words, category)
if v > value:
best = category
value = v
return best
if __name__ == "__main__":
data = [["yes", "Chinese", "Beijing", "Chinese"],
["yes", "Chinese", "Chinese", "Shanghai"],
["yes", "Chinese", "Macao"],
["no", "Tokyo", "Japan", "Chinese"]]
#Former le classificateur Naive Bayes
nb = NaiveBayes()
nb.train(data)
print "P(Chinese|yes) = ", nb.word_probability("Chinese", "yes")
print "P(Tokyo|yes) = ", nb.word_probability("Tokyo", "yes")
print "P(Japan|yes) = ", nb.word_probability("Japan", "yes")
print "P(Chinese|no) = ", nb.word_probability("Chinese", "no")
print "P(Tokyo|no) = ", nb.word_probability("Tokyo", "no")
print "P(Japan|no) = ", nb.word_probability("Japan", "no")
#
# #Prédire les catégories de données de test
test = ["Chinese", "Chinese", "Chinese", "Tokyo", "Japan"]
print "log P(yes|test) =", nb.score(test, "yes")
print "log P(no|test) =", nb.score(test, "no")
print nb.classify(test)
J'ai beaucoup parlé des pages suivantes. Merci beaucoup.
Recommended Posts