** Dieser Beitrag ist der zweite Tagesartikel von Real Escape Advent Calendar 2013. ** ** **
Zuletzt implementiert Naive Bayes. Da ich es mit großer Anstrengung gemacht habe, habe ich es mit dem Code geschrieben, den ich bisher geschrieben habe, um es zu einem praktischen System zu machen.
Ich habe den gesamten Code außer dem API-Schlüssel auf Github hochgeladen. Verwenden Sie ihn daher bitte so, wie er ist, wenn Sie möchten. https://github.com/katryo/bing_search_naive_bayes
Durch die Kombination der oben genannten drei Funktionen haben wir ein System geschaffen, das Lerndaten erfassen, lernen und klassifizieren kann.
Basierend auf http://o-tomox.hatenablog.com/entry/2013/09/25/191506 von @ o-tomox habe ich einen verbesserten Wrapper geschrieben, der mit Python 3.3 funktioniert.
Schreiben Sie den Bing-API-Schlüssel im Voraus in eine Datei mit dem Namen my_api_keys.py.
my_api_keys.py
BING_API_KEY = 'abcdefafdafsafdafasfaafdaf'
Bitte ignorieren Sie es mit .gitignore. Andernfalls wird der API-Schlüssel veröffentlicht.
Das Folgende ist ein Wrapper für die Bing-API.
bing.py
# -*- coding: utf-8 -*-
import urllib
import requests
import sys
import my_api_keys
class Bing(object):
#Auf der gleichen Ebene meine_api_keys.Erstellen Sie dort eine Datei mit dem Namen py und BING_API_Schreiben Sie den SCHLÜSSEL.
# my_api_keys.Halten Sie py gitignore.
def __init__(self, api_key=my_api_keys.BING_API_KEY):
self.api_key = api_key
def web_search(self, query, num_of_results, keys=["Url"], skip=0):
"""
in Schlüsseln'ID','Title','Description','DisplayUrl','Url'Kann betreten
"""
#Grundlegende URL
url = 'https://api.datamarket.azure.com/Bing/Search/Web?'
#Maximale Anzahl, die gleichzeitig zurückgegeben wird
max_num = 50
params = {
"Query": "'{0}'".format(query),
"Market": "'ja-JP'"
}
#Von json empfangenes Format
request_url = url + urllib.parse.urlencode(params) + "&$format=json"
results = []
#Häufigkeit, mit der die API mit maximaler Anzahl wiederholt wird
repeat = int((num_of_results - skip) / max_num)
remainder = (num_of_results - skip) % max_num
#Wiederholen Sie den Vorgang, indem Sie die API mit der maximalen Anzahl treffen
for i in range(repeat):
result = self._hit_api(request_url, max_num, max_num * i, keys)
results.extend(result)
#verbleibend
if remainder:
result = self._hit_api(request_url, remainder, max_num * repeat, keys)
results.extend(result)
return results
def related_queries(self, query, keys=["Title"]):
"""
in Schlüsseln'ID','Title','BaseUrl'Kann betreten
"""
#Grundlegende URL
url = 'https://api.datamarket.azure.com/Bing/Search/RelatedSearch?'
params = {
"Query": "'{0}'".format(query),
"Market": "'ja-JP'"
}
#Von json empfangenes Format
request_url = url + urllib.parse.urlencode(params) + "&$format=json"
results = self._hit_api(request_url, 50, 0, keys)
return results
def _hit_api(self, request_url, top, skip, keys):
#Endgültige URL für das Aufrufen der API
final_url = "{0}&$top={1}&$skip={2}".format(request_url, top, skip)
response = requests.get(final_url,
auth=(self.api_key, self.api_key),
headers={'User-Agent': 'My API Robot'}).json()
results = []
#Holen Sie sich die angegebenen Informationen aus den zurückgegebenen Artikeln
for item in response["d"]["results"]:
result = {}
for key in keys:
result[key] = item[key]
results.append(result)
return results
if __name__ == '__main__':
# bing_api.Wenn py alleine verwendet wird, wird es zu einem Werkzeug, um 50 Elemente mit dem eingegebenen Wort zu suchen und das Ergebnis anzuzeigen.
for query in sys.stdin:
bing = Bing()
results = bing.web_search(query=query, num_of_results=50, keys=["Title", "Url"])
print(results)
Mit diesem Bing-API-Wrapper habe ich ein Skript geschrieben, das 50 Suchergebnisseiten lokal speichert.
fetch_web_pages.py
from bing_api import Bing
import os
import constants
from web_page import WebPage
if __name__ == '__main__':
bing = Bing()
if not os.path.exists(constants.FETCHED_PAGES_DIR_NAME):
os.mkdir(constants.FETCHED_PAGES_DIR_NAME)
os.chdir(constants.FETCHED_PAGES_DIR_NAME)
results = bing.web_search(query=constants.QUERY, num_of_results=constants.NUM_OF_FETCHED_PAGES, keys=['Url'])
for i, result in enumerate(results):
page = WebPage(result['Url'])
page.fetch_html()
f = open('%s_%s.html' % (constants.QUERY, str(i)), 'w')
f.write(page.html_body)
f.close()
Erstellen Sie außerdem eine Datei mit dem Namen constants.py und schreiben Sie den Namen des Verzeichnisses, in dem der HTML-Code der Abfrage- und Suchergebnisse gespeichert ist. Dieses Mal werde ich zuerst nach der Abfrage "defekt" suchen.
constants.py
FETCHED_PAGES_DIR_NAME = 'fetched_pages'
QUERY = 'Fraktur'
NUM_OF_FETCHED_PAGES = 50
NB_PKL_FILENAME = 'naive_bayes_classifier.pkl'
Ich habe eine Klasse namens WebPage erstellt, um die Handhabung der erfassten Webseite zu vereinfachen. Rufen Sie basierend auf der von der Bing-API erhaltenen URL HTML ab, überprüfen Sie den Zeichencode mit cChardet und löschen Sie das störende HTML-Tag mit einem regulären Ausdruck.
web_page.py
import requests
import cchardet
import re
class WebPage():
def __init__(self, url=''):
self.url = url
def fetch_html(self):
try:
response = requests.get(self.url)
self.set_html_body_with_cchardet(response)
except requests.exceptions.ConnectionError:
self.html_body = ''
def set_html_body_with_cchardet(self, response):
encoding_detected_by_cchardet = cchardet.detect(response.content)['encoding']
response.encoding = encoding_detected_by_cchardet
self.html_body = response.text
def remove_html_tags(self):
html_tag_pattern = re.compile('<.*?>')
self.html_body = html_tag_pattern.sub('', self.html_body)
Legen Sie nun den obigen Code in dasselbe Verzeichnis.
$ python fetch_web_pages.py
Ausführen. Es dauert einen Moment, bis die Bing-API aufgerufen wird, um 50 URLs abzurufen. Es dauert jedoch etwas, bis eine HTTP-Anforderung an jede der 50 URLs gesendet und der HTML-Code abgerufen wird. Ich denke, es wird ungefähr 30 Sekunden dauern.
Wenn Sie fertig sind, schauen Sie sich das Verzeichnis fetched_pages an. Sie sollten eine HTML-Datei von Fraktur_0.html bis Fraktur.49.html haben.
Jetzt kommt endlich die letzte Implementierung von Naive Bayes ins Spiel.
naive_bayes
#coding:utf-8
# http://gihyo.jp/dev/serial/01/machine-learning/Python3 mit der Basilian-Filter-Implementierung von 0003.Verbessert, um für 3 lesbar zu sein
import math
import sys
import MeCab
class NaiveBayes:
def __init__(self):
self.vocabularies = set()
self.word_count = {} # {'Maßnahmen gegen Pollinose': {'Sugi Pollen': 4, 'Medizin': 2,...} }
self.category_count = {} # {'Maßnahmen gegen Pollinose': 16, ...}
def to_words(self, sentence):
"""
Eingang: 'Alles für mich'
Ausgabe: tuple(['alles', 'mich selber', 'von', 'Wie', 'Was'])
"""
tagger = MeCab.Tagger('mecabrc') #Sie können einen anderen Tagger verwenden
mecab_result = tagger.parse(sentence)
info_of_words = mecab_result.split('\n')
words = []
for info in info_of_words:
#Wenn Sie durch Macab teilen, steht "" am Ende des Satzes davor'EOS'Kommt
if info == 'EOS' or info == '':
break
# info => 'Nana\t Assistent,Letzte Hilfe,*,*,*,*,Nana,N / a,N / a'
info_elems = info.split(',')
#Sechstens gibt es Wörter, die nicht verwendet werden. Wenn der sechste ist'*'Wenn ja, geben Sie die 0 ein
if info_elems[6] == '*':
# info_elems[0] => 'Van Rossam\t Substantiv'
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):
#Berechnung des Bayes'schen Gesetzes
numerator = self.num_of_appearance(word, category) + 1 # +1 ist die Laplace-Methode zur additiven Glättung
denominator = sum(self.word_count[category].values()) + len(self.vocabularies)
#In Python3 wird die Division automatisch verschoben
prob = numerator / denominator
return prob
def score(self, words, category):
score = math.log(self.prior_prob(category))
for word in words:
score += math.log(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 ist eine Open-Source-Programmiersprache, die vom Niederländer Guido Van Rossam entwickelt wurde.
Es ist eine Art objektorientierte Skriptsprache und wird in Europa und den USA zusammen mit Perl häufig verwendet. Benannt nach der Comedy-Show "Flying Monty Python" des britischen Fernsehsenders BBC.
Python bedeutet auf Englisch Reptilien-Nishiki-Schlange und wird manchmal als Maskottchen oder Symbol in der Python-Sprache verwendet. Python ist eine allgemeine Hochsprache. Es wurde mit dem Fokus auf Programmiererproduktivität und Codezuverlässigkeit entwickelt und verfügt über eine große, praktische Standardbibliothek mit minimaler Kernsyntax und Semantik.
Es unterstützt Zeichenfolgenoperationen mit Unicode, und die japanische Verarbeitung ist standardmäßig möglich. Es unterstützt viele Plattformen (Arbeitsplattformen) und verfügt über zahlreiche Dokumente und Bibliotheken, sodass seine Verwendung in der Branche zunimmt.
''',
'Python')
nb.train('''Ruby ist eine objektorientierte Skriptsprache, die von Yukihiro Matsumoto (allgemein bekannt als Matz) entwickelt wurde.
Realisiert objektorientierte Programmierung in Bereichen, in denen traditionell Skriptsprachen wie Perl verwendet wurden.
Ruby wurde ursprünglich am 24. Februar 1993 geboren und im Dezember 1995 auf fj angekündigt.
Der Name Ruby ist, weil die Programmiersprache Perl dasselbe ausspricht wie Pearl, der Geburtsstein des Juni.
Es wurde nach dem Rubin des Geburtssteins von Matsumotos Kollegen (Juli) benannt.
''',
'Ruby')
doc = 'Open Source von Guido Van Rossam'
print('%s =>Geschätzte Kategorie: %s' % (doc, nb.classify(doc))) #Geschätzte Kategorie:Sollte Python sein
doc = 'Eine reine objektorientierte Sprache.'
print('%s =>Geschätzte Kategorie: %s' % (doc, nb.classify(doc))) #Geschätzte Kategorie:Sollte Ruby sein
Trainieren Sie mithilfe dieser Naive Bayes-Implementierung und der heruntergeladenen HTML-Datei den Klassifizierer, bei dem es sich um ein Naive Bayes-Objekt handelt.
Es ist eine Verschwendung, das trainierte Naive Bayes-Objekt jedes Mal wegzuwerfen. Speichern Sie es also mithilfe der Gurkenbibliothek.
Klicken Sie hier, um ein Skript zum Lernen und Speichern zu erhalten.
train_with_fetched_pages.py
import os
import pickle
import constants
from web_page import WebPage
from naive_bayes import NaiveBayes
def load_html_files():
"""
Verwenden Sie diese Option unter der Annahme, dass sich die HTML-Datei im Verzeichnis befindet
"""
pages = []
for i in range(constants.NUM_OF_FETCHED_PAGES):
with open('%s_%s.html' % (constants.QUERY, str(i)), 'r') as f:
page = WebPage()
page.html_body = f.read()
page.remove_html_tags()
pages.append(page)
return pages
if __name__ == '__main__':
#Wenn Sie es wieder an einem anderen Ort verwenden möchten, machen Sie es zu einer Funktion
if not os.path.exists(constants.FETCHED_PAGES_DIR_NAME):
os.mkdir(constants.FETCHED_PAGES_DIR_NAME)
os.chdir(constants.FETCHED_PAGES_DIR_NAME)
pages = load_html_files()
pkl_nb_path = os.path.join('..', constants.NB_PKL_FILENAME)
#Wenn Sie bereits ein Naive Bayes-Objekt eingelegt haben, trainieren Sie es
if os.path.exists(pkl_nb_path):
with open(pkl_nb_path, 'rb') as f:
nb = pickle.load(f)
else:
nb = NaiveBayes()
for page in pages:
nb.train(page.html_body, constants.QUERY)
#Ich habe es so viel gelernt, also lass es uns retten
with open(pkl_nb_path, 'wb') as f:
pickle.dump(nb, f)
Legen Sie den obigen Quellcode in dasselbe Verzeichnis und machen Sie dasselbe wie zuvor
$ python train_with_fetched_web_pages.py
Führen Sie das Lernen durch und speichern Sie den Klassifikator unter. Dieses Mal dauert es nicht lange, da es nicht über HTTP mit der Außenwelt kommuniziert. In meinem Fall dauerte es weniger als 5 Sekunden.
Mit dem obigen Verfahren konnten wir eine Abfrage = eine Kategorie namens "Fraktur" lernen. Es kann jedoch nicht nur einer Kategorie zugeordnet werden. Daher werde ich den obigen Vorgang mehrmals mit verschiedenen Abfragen wiederholen.
Schreiben Sie zuerst QUERY in constants.py neu.
constants.py
QUERY ="Magen lehnen"#Umgeschrieben von 'gebrochen'
Rufen Sie dann den HTML-Code mit der Bing-API ab.
$ python fetch_web_pages.py
Trainieren Sie den unter dem Namen naive_bayes_classifier.pkl gespeicherten Naive Bayes-Klassifikator mit 50 abgerufenen HTML-Dateien.
$ python train_with_fetched_web_pages.py
Wiederholen Sie die obige Arbeit mehrmals, indem Sie die Konstanten neu schreiben. Fragen Sie nach "Gegenmaßnahmen gegen Pollinose" und "Wurmzähne".
Nun, das Lernen ist vorbei. Endlich beginnt die Produktion von hier. Nehmen Sie eine Zeichenfolge aus der Standardeingabe und lassen Sie den Klassifizierer kategorisieren, welcher Kategorie die Zeichenfolge zugewiesen werden soll.
Das zu klassifizierende Skript ist wie folgt einfach. Laden Sie zuerst das eingelegte Naive Bayes-Objekt und entfernen Sie es aus dem Salz. Führen Sie dann jedes Mal, wenn sys.stdin eingegeben wird, einfach die classify () -Methode des NaiveBayes-Objekts aus und zeigen Sie das Ergebnis an.
classify.py
# -*- coding: utf-8 -*-
import pickle
import constants
import sys
if __name__ == '__main__':
with open(constants.NB_PKL_FILENAME, 'rb') as f:
nb = pickle.load(f)
for query in sys.stdin:
result = nb.classify(query)
print('Die abgeleitete Kategorie ist%s' % result)
Machen wir das.
$ python classify_inputs.py
Es funktioniert als Terminal-Tool. Geben Sie also die Zeichenfolge so ein, wie sie ist. Zunächst die [Allergien] von Wikipedia (http://en.wikipedia.org/wiki/%E3%82%A2%E3%83%AC%E3%83%AB%E3%82%AE%E3%83%BC) ) Seite "Allergie" bedeutet, dass eine Immunreaktion übermäßig gegen ein bestimmtes Antigen auftritt. Die Immunreaktion eliminiert fremde Fremdsubstanzen (Antigene). Es ist eine unverzichtbare physiologische Funktion für den lebenden Körper. "
Erfolg! Es wurde in die Kategorie "Gegenmaßnahmen gegen Pollinose" eingestuft.
Als nächstes der Text auf der Seite von Lion's Clinica "Nach einer Mahlzeit oder einem Snack metabolisieren die Bakterien in der Plaque Zucker. Die Oberfläche der mit Plaque bedeckten Zähne wird sauer, weil sie Säure produziert. "
Dies ist auch erfolgreich. Es wurde vermutet, dass es sich um die Kategorie "Wurmzahn" handelt.
Dieses Mal habe ich Naive Bayes verwendet, das ich selbst implementiert habe, um überwachtes Lernen mithilfe von Web-Suchergebnissen durchzuführen. Ich habe es mehrmals versucht, aber es funktioniert ziemlich gut.
Diese Implementierung zählt die Anzahl der Vorkommen aller angezeigten Wörter, einschließlich übermäßig häufiger Wörter wie "ha" und "o". Ursprünglich sollten wir tf-idf verwenden, um den Wert von Wörtern zu verringern, die zu häufig vorkommen, ihre Eigenschaften zu verringern und die Berechnungskosten zu senken, diesmal jedoch nicht. Dies liegt daran, dass die für das Training verwendeten Daten klein waren und die Berechnung nicht lange dauerte. Als zukünftige Aufgabe möchte ich Methoden wie tf-idf und LSA (Latent Meaning Analysis) verwenden, um die Berechnungskosten zu reduzieren oder die Genauigkeit zu verbessern.
Wenn Sie eine Bibliothek wie scikit-learn verwenden, sollte es einfacher und bequemer sein, Hochleistungsglättung und tfidf zu verwenden, daher würde ich dies gerne beim nächsten Mal tun.
Pushed to Github, schauen Sie also bitte vorbei, wenn Sie möchten. Bitte gib mir noch einen Stern.
Hinzufügen einer Funktion zur Berechnung der Ähnlichkeit aus der Häufigkeit des gleichzeitigen Auftretens von Wörtern, die einmal von Naive Bayes entfernt waren. Nächstes Mal werden Sie die Tränen der Zeit sehen. http://qiita.com/katryo/items/b6962facf744e93735bb
Recommended Posts