[PYTHON] Berechnen Sie tf-idf mit scikit-learn

** Dieser Beitrag ist der 4. Tagesartikel von Real Escape Advent Calendar 2013. ** **.

Artikel zu Tag 2 verwendet HTML, das mit der Bing-API abgerufen wurde, also Tag 2 Es ist einfacher zu verstehen, wenn Sie zuerst / items / 62291ba328de9d12bd30) lesen.

Fassen Sie diesen Artikel in 3 Zeilen zusammen

-Ich habe eine Python-Bibliothek namens [scikit-learn] überprüft (http://scikit-learn.org/stable/index.html).

Referenz

scikit-learn offizielles Dokument zur Extraktion der Textidentität

Tfidf-Berechnung von Wörtern in Tweet mit scikit-learn

Fertiges Produkt

https://github.com/katryo/tfidf_with_sklearn

Fork me!

Theorie

Definition von tfidf

--tf-idf ist der Wert von ** tf * idf **. Wird an ein Wort eines Dokuments in einer Reihe von Dokumenten angehängt. Wörter mit hohem tf-idf können als wichtig angesehen werden. Es kann verwendet werden, um Wörter beim Abrufen von Informationen zu gewichten. --tf (Termhäufigkeit) ist ** die Anzahl der Vorkommen des Wortes (Term) im Dokument / die Gesamtzahl aller Wörter, die im Dokument enthalten sind **. Es wächst, wenn das Wort im Dokument häufig verwendet wird. --idf (Inverse Document Frequency) ist die Umkehrung von df. In der Realität wird das Protokoll jedoch verwendet, um die Berechnung zu vereinfachen. So wird es ** log (1 / df) **. Der untere Rand des Protokolls ist normalerweise 2, kann aber e oder 10 sein. Sollte sein. --df (Dokumenthäufigkeit) ist ** die Anzahl der Dokumente, in denen das Wort vorkommt / die Gesamtzahl der Dokumente **. Es wächst, wenn das Wort in einer Vielzahl von Themen verwendet wird. "Ha" und "o" und auf Englisch "is" und "that" sind sehr groß. Der Wert, der einem Wort in einem Dokumentensatz zugeordnet ist.

Extraktion der Identität aus dem Text mit Scikit-Learn

Verstehen Sie Ihren eigenen Inhalt, während Sie den Inhalt von Dokument zum Extrahieren der Textidentität von scikit-learn offiziell teilweise übersetzen Zusätzlich wird es beschrieben.

Beim Extrahieren der Identität aus dem Text mit scikit-learn sind drei Prozesse erforderlich.

-Tokenisierung: Konvertieren Sie Text in eine Wortsammlung. Im Fall von Englisch ist es in Ordnung, durch Leerzeichen zu teilen und dann Rauschen wie Symbole zu entfernen. Verwenden Sie jedoch auf Japanisch einen morphologischen Analysator wie MeCab oder KyTea. Da scikit-learn keinen japanischen morphologischen Analysator enthält, ist dieser Prozess separat erforderlich. --counting: Zählt die Häufigkeit des Auftretens jedes Wortes für jedes Dokument.

Beim Scikit-Lernen werden die obigen drei Schritte zusammenfassend als ** Vektorisierung ** bezeichnet, dh als "Vektorisierung". Der spätere Tfidf Vectorizer kann alle drei Schritte ausführen. Wenn Sie den Vorgang bereits zur Hälfte abgeschlossen haben, können Sie aus der Mitte oder der Hälfte berechnen.

Übrigens kann scikit-learn nicht nur eine Menge Wörter, sondern auch eine tfidf-Berechnung mit n-Gramm durchführen, die sich auf die Fortsetzung von zwei oder mehr Wörtern konzentriert, aber ich werde es diesmal nicht tun.

CountVectorizer Der Count Vectorizer in sklearn.feature_extraction.text kann tokenisieren und zählen. Da das Ergebnis der Zählung durch einen Vektor dargestellt wird, Vectorizer.

Die offizielle Dokumentation erklärt es hier.

TfidfTransformer Der Tfidf-Transformator, ebenfalls in sklearn.feature_extraction.text, ist für die Normalisierung verantwortlich. Die Methode fit_transform berechnet tfidf nur anhand der "Häufigkeit des Auftretens von Wörtern für jedes Dokument" und normalisiert es sogar. Hier in der offiziellen Dokumentation.

TfidfVectorizer Existenz, die die Funktionen von Count Vectorizer und Tfidf Transformer hat. Dreifaltigkeitsform, genau die Dreifaltigkeit. Dies ist praktisch, wenn Sie die Identität aus dem Rohtext extrahieren.

Ich habe es tatsächlich benutzt

Schauen Sie sich die hohen Worte von tfidf an

Das Hauptthema ist von hier. 36934 Arten von Wörtern auf 400 Webseiten, die von 8 Abfragen abgerufen wurden. Drucken Sie aus diesen "Wörter mit tfidf größer als 0,1 im angezeigten Dokument".

Zunächst einmal ist die Berechnung von tfidf ziemlich teuer. Berechnen wir also tfidf und wählen Sie dann das Ergebnis aus.

set_tfidf_with_sklearn_to_fetched_pages.py


import utils
import constants
import pickle
import os
from sklearn.feature_extraction.text import TfidfVectorizer


def is_bigger_than_min_tfidf(term, terms, tfidfs):
    '''
    [term for term in terms if is_bigger_than_min_tfidf(term, terms, tfidfs)]Verwenden Sie in
Eine Funktion, die aus der Liste der tfidf-Werte von Wörtern in der richtigen Reihenfolge errät.
Der Wert von tfidf ist MIN_Gibt True zurück, wenn es größer als TFIDF ist
    '''
    if tfidfs[terms.index(term)] > constants.MIN_TFIDF:
        return True
    return False


def tfidf(pages):
    #analyzer ist eine Funktion, die eine Liste von Zeichenfolgen zurückgibt, wenn eine Zeichenfolge eingegeben wird.
    vectorizer = TfidfVectorizer(analyzer=utils.stems, min_df=1, max_df=50)
    corpus = [page.text for page in pages]

    x = vectorizer.fit_transform(corpus)

    #Von hier an hat down nichts mehr mit dem zurückgegebenen Wert zu tun. Ich wollte nur sehen, wie die hohen Worte von tfidf aussehen
    terms = vectorizer.get_feature_names()
    tfidfs = x.toarray()[constants.DOC_NUM]
    print([term for term in terms if is_bigger_than_min_tfidf(term, terms, tfidfs)])

    print('gesamt%Ich Arten von Wörtern%Gefunden von i Seite.' % (len(terms), len(pages)))

    return x, vectorizer  #x ist tfidf_Erhalten Sie hauptsächlich als Ergebnis

if __name__ == '__main__':
    utils.go_to_fetched_pages_dir()
    pages = utils.load_all_html_files()  #Seiten rufen HTML ab und setzen es auf Text
    tfidf_result, vectorizer = tfidf(pages)  # tfidf_Ergebnis ist das x der tfidf-Funktion

    pkl_tfidf_result_path = os.path.join('..', constants.TFIDF_RESULT_PKL_FILENAME)
    pkl_tfidf_vectorizer_path = os.path.join('..', constants.TFIDF_VECTORIZER_PKL_FILENAME)

    with open(pkl_tfidf_result_path, 'wb') as f:
        pickle.dump(tfidf_result, f)
    with open(pkl_tfidf_vectorizer_path, 'wb') as f:
        pickle.dump(vectorizer, f)

In der tfidf-Funktion

vectorizer = TfidfVectorizer(analyzer=utils.stems, min_df=1, max_df=50)

Es wird gesagt. Der Analysator fügt eine Funktion ein, die eine Liste von Zeichenfolgen zurückgibt, wenn Sie eine Zeichenfolge einfügen. Standardmäßig wird es durch Leerzeichen geteilt und nur ein Zeichensymbol wird entfernt. Wenn Sie dies jedoch auf Japanisch tun, müssen Sie eine Funktion mithilfe eines morphologischen Analysators selbst erstellen und festlegen. Die Funktion utils.stems ist eine Funktion, die mit MeCab eine morphologische Analyse durchführt, sie in einen Stamm konvertiert und als Liste zurückgibt. Sie wurde in utils.py geschrieben, was später beschrieben wird.

Was in der tfidf-Funktion gedruckt wird, ist ein Wort, dessen tfidf-Wert 0,1 oder mehr unter den Wörtern beträgt, die auf einer der Ergebnisseiten gefunden werden, die nach "Magenneigung" durchsucht werden. Das Ergebnis davon wird später beschrieben.

Die im Code angezeigten Dienstprogramme lauten wie folgt und sind eine Sammlung nützlicher Funktionen, die in verschiedenen Situationen verwendet werden können.

utils.py


import MeCab
import constants
import os
import pdb
from web_page import WebPage

def _split_to_words(text, to_stem=False):
    """
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(text)
    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
        if to_stem:
            #In Wortstamm konvertieren
            words.append(info_elems[6])
            continue
        #Wort wie es ist
        words.append(info_elems[0][:-3])
    return words


def words(text):
    words = _split_to_words(text=text, to_stem=False)
    return words


def stems(text):
    stems = _split_to_words(text=text, to_stem=True)
    return stems


def load_all_html_files():
    pages = []
    for query in constants.QUERIES:
        pages.extend(load_html_files_with_query(query))
    return pages


def load_html_files_with_query(query):
    pages = []
    for i in range(constants.NUM_OF_FETCHED_PAGES):
        with open('%s_%s.html' % (query, str(i)), 'r') as f:
            page = WebPage()
            page.html_body = f.read()
        page.remove_html_tags()
        pages.append(page)
    return pages

def load_html_files():
    """
Verwenden Sie diese Option unter der Annahme, dass sich die HTML-Datei im Verzeichnis befindet
    """
    pages = load_html_files_with_query(constants.QUERY)
    return pages


def go_to_fetched_pages_dir():
    if not os.path.exists(constants.FETCHED_PAGES_DIR_NAME):
        os.mkdir(constants.FETCHED_PAGES_DIR_NAME)
    os.chdir(constants.FETCHED_PAGES_DIR_NAME)

Und die Konstanten sind wie folgt.

constants.py


FETCHED_PAGES_DIR_NAME = 'fetched_pages'
QUERIES = 'Magen Pollinose lehnt Wurm Zahn Pollinose misst Depression mechanische Fraktur steife Schulter Dokumente'.split(' ')
NUM_OF_FETCHED_PAGES = 50
NB_PKL_FILENAME = 'naive_bayes_classifier.pkl'
DOC_NUM = 0
MIN_TFIDF = 0.1
TFIDF_RESULT_PKL_FILENAME = 'tfidf_result.pkl'
TFIDF_VECTORIZER_PKL_FILENAME = 'tfidf_vectorizer.pkl'

Wenn Sie sich die Reihenfolge der FRAGEN ansehen, können Sie sehen, dass die Kategorie "Magenneigung" an erster Stelle steht. Die DOC_NUM-Konstante wurde für dieses Experiment erstellt und verwendet, um die 0. Datei in der Kategorie "Magenneigung" anzugeben, dh die Datei mit dem Namen "Magenneigung_0.html".

Jetzt. Lassen Sie uns diesen Code ausführen.

$ python set_tfidf_with_sklearn_to_fetched_pages.py

Selbst wenn Sie scikit-learn verwenden, dauert die Berechnung von tfidf einige Zeit. In meiner Umgebung dauerte es 25,81 Sekunden. Ergebnis.

['gaJsHost', 'https', 'Tropfen', 'Brennen', 'Luft schlucken', 'Hyperazidität', 'Brust', 'Kochen', 'Nahrungsmittel', 'Ösophagus-Fissuren-Hernie']
Auf 400 Seiten wurden insgesamt 36934 Wörter gefunden.

Es ist ein Wort, das sich wie Bauchschmerzen anfühlt. Es wurde festgestellt, dass unter den Wörtern in Magenruhe_0.html die obigen 10 Arten von Wörtern tfidf größer als 0,1 haben.

gaJsHost und https scheinen Teil des JavaScript-Codes zu sein. Hmmm. Ich möchte all diesen Lärm loswerden, aber ich kann mir keinen guten Weg vorstellen. Besser noch, es kann besser sein, Wörter zu entfernen, die nur alphabetisch sind.

Übrigens sind Wörter wie "Ösophagusfissurenhernie" nicht in MeCabs IPADIC enthalten (siehe diesen Artikel für den Ursprung von IPADIC), also Wikipedia Es ist notwendig, es zu stärken, indem die Wörter des Hatena-Schlüsselworts in das Wörterbuch aufgenommen werden. Bitte googeln Sie, wie es geht.

Überprüfen Sie die Zuordnung zwischen Wörtern und tfidf-Werten

Ich habe die offizielle Seite gelesen, aber das Ergebnis der Berechnung von tfidf wird in der Art von csr_matrix von scipy ausgegeben. Dies ist eine spärliche (meistens 0) Matrix, die das Wort tf-idf in jedem Dokument als Bruch von 0 bis 1 darstellt.

(Pdb) type(x)
<class 'scipy.sparse.csr.csr_matrix'>

Ich wusste nicht, wie der tfidf-Wertesatz dem Wort zugeordnet wurde (ich habe es später herausgefunden), also habe ich ein einfaches Experiment mit pdb.set_trace () durchgeführt.

TfidfVectorizer verfügt über die zu verwendende Methode

Und scipy.sparse.csr_matrix hat

Ist.

Als ich die Webseite mit der Dokumentnummer 0 überprüfte, war es zunächst eine Seite namens Stomach leaning.com. Finden Sie heraus, wie die Wörter auf dieser Seite dargestellt werden.

Nach dem Beizen des Berechnungsergebnisses von tfidf wurde der folgende Code ausgeführt.

play_with_tfidf.py


# -*- coding: utf-8 -*-
import pickle
import constants
import pdb

def is_bigger_than_min_tfidf(term, terms, tfidfs):
    '''
    [term for term in terms if is_bigger_than_min_tfidf(term, terms, tfidfs)]Verwenden Sie in
Eine Funktion, die aus der Liste der tfidf-Werte von Wörtern in der richtigen Reihenfolge errät.
Der Wert von tfidf ist MIN_Gibt True zurück, wenn es größer als TFIDF ist
    '''
    if tfidfs[terms.index(term)] > constants.MIN_TFIDF:
        return True
    return False

if __name__ == '__main__':
    with open(constants.TFIDF_VECTORIZER_PKL_FILENAME, 'rb') as f:
        vectorizer = pickle.load(f)
    with open(constants.TFIDF_RESULT_PKL_FILENAME, 'rb') as f:
        x = pickle.load(f)

    pdb.set_trace()

    terms = vectorizer.get_feature_names()
    for i in range(3):
        tfidfs = x.toarray()[i]
        print([term for term in terms if is_bigger_than_min_tfidf(term, terms, tfidfs)])

Sie können pdb.set_trace als Haltepunkt verwenden und von dort aus Werte in einer interaktiven Umgebung ausgeben, um verschiedene Bestätigungsaufgaben auszuführen.

(Pdb) vectorizer.inverse_transform(x)[0]
> array(['Ösophagus-Fissuren-Hernie', 'Nahrungsmittel', 'Diät-Heilmittel', 'Operation', 'Reflux-Ösophagitis', 'Kochen', 'Brust', 'Hyperazidität', 'Magenschmerzen',
       'Magengeschwür', 'Magen-Ptosis', 'Magenkrebs', 'Luft schlucken', 'Chinesische Kräutermedizin', 'Konstruktion', 'Chronische Gastritis', 'Zwölffingerdarmgeschwür', 'Krankenversicherung',
       'Haftungsausschluss', 'Unternehmensinformationen', 'Polyp', 'Topf', 'Pflege', 'Amerikanische Familienlebensversicherungsgesellschaft', 'Aflac', 'gehen',
       'Brennen', 'Bezüglich', 'Tropfen', 'unescape', 'try', 'ssl', 'protocol',
       'javascript', 'inquiry', 'https', 'gaJsHost', 'ga', 'err',
       'comCopyright', 'analytics', 'Inc', 'Cscript', 'CROSSFINITY',
       '=\'"', "='", ':"', '.")', '."', ')\u3000', '(("', '("%', "'%",
       '"))'],
      dtype='<U26')

Der Begriff "Ösophagusfissurenhernie" ist selten und scheint auf anderen Seiten selten zu erscheinen. Deshalb habe ich mich entschieden, ihn als Marker zu verwenden.

(Pdb) vectorizer.get_feature_names().index('Ösophagus-Fissuren-Hernie')
36097

Es stellte sich heraus, dass es das 36097. Wort war. Was ist der Wert von tfidf für das 36097. Wort im 0. Dokument (dh Magenverstimmung.com)?

(Pdb) x.toarray()[0][36097]
0.10163697033184078

Ziemlich teuer. In Dokument Nummer 0 wurde festgestellt, dass das Wort mit der Wortnummer 36097 eine tfidf von 0,10163697033184078 hat. Ich glaube nicht, dass ein so hoher (in erster Linie ungleich Null) tfidf-Wert zufällig bei der Wortnummer 36097 erscheint. x.toarray () ist eine sehr spärliche Matrix, von der die meisten 0 sein sollten. Daher kann davon ausgegangen werden, dass die Reihenfolge der Wortliste, die von vectorizer.get_feature_names () verwendet werden kann, und die Reihenfolge der Wörter mit tfidf, die von x.toarray () verwendet werden können, identisch sind.

Auf diese Weise wurde bestätigt, dass die Wortliste in derselben Reihenfolge geführt wurde. Ich denke, irgendwo in der offiziellen Dokumentation steht, dass "die Reihenfolge der Wörter erhalten bleibt".

Danach habe ich pdb.set_trace () gelöscht und play_with_tfidf.py erneut ausgeführt.

['gaJsHost', 'https', 'Tropfen', 'Brennen', 'Luft schlucken', 'Hyperazidität', 'Brust', 'Kochen', 'Nahrungsmittel', 'Ösophagus-Fissuren-Hernie']
['Tropfen', 'Widerlich', 'Brennen', 'Magenschmerzen', 'Brust', 'Bestehen']
['TVCM', 'Gusuru', 'Tropfen', 'Nomu', 'もTropfen', 'Brennen', 'Brennenる', 'Ri', 'Aktion', 'Wissenschaft', 'Sacron', 'Cerbere', 'verdreifachen', 'Schleier', 'Kater', 'Schwach', 'Ordnen', 'Schleim', 'Magenschmerzen', 'Magenmedizin', 'Brust', 'Fülle']

Diese Wörter haben einen hohen tfidf (der sehr hoch zu sein scheint) und werden als nützlich angesehen, um die Ähnlichkeit zwischen Dokumenten und der Kategorie der Magenneigung zu berechnen.

Zusammenfassung

scikit-learn Bequem.

Ich habe den Code auf Github gepostet.

https://github.com/katryo/tfidf_with_sklearn

Vorschau beim nächsten Mal

Ich möchte die Berechnungsfunktion von tfidf implementieren und mit scicit-learn vergleichen.

Recommended Posts

Berechnen Sie tf-idf mit scikit-learn
DBSCAN mit Scikit-Learn
Clustering mit Scikit-Learn (1)
Clustering mit Scikit-Learn (2)
PCA mit Scikit-Learn
kmeans ++ mit scikit-learn
Kreuzvalidierung mit Scikit-Learn
Mehrklassen-SVM mit Scikit-Learn
Clustering mit scikit-learn + DBSCAN
Scikit-Lernen mit Chemoinfomatik
DBSCAN (Clustering) mit Scikit-Learn
Installieren Sie scikit.learn mit pip
Parallele Verarbeitung mit Parallel von Scikit-Learn
[Python] Lineare Regression mit Scicit-Learn
[MCMC] WAIC mit Pystan berechnen
Robuste lineare Regression mit Scikit-Learn
Berechnen Sie die Probenverteilung mit Scipy (diskrete Verteilung)
Rastersuche von Hyperparametern mit Scikit-learn
Berechnen Sie die CPU-Auslastung einer Domain mit libvirt
Erstellen eines bestimmten Baums mit Scikit-Learn
Bildsegmentierung mit Scikit-Image und Scikit-Learn
Identifizieren Sie Ausreißer mit dem Random Forest Classifier von scikit-learn
Laplace-Eigenkarten mit Scikit-Learn (persönliche Notizen)
Nicht negative Matrixfaktorisierung (NMF) mit Scikit-Learn
SVM versucht maschinelles Lernen mit Scikit-Learn
Scikit-learn DecisionTreeClassifier mit Datetime-Typwerten
So berechnen Sie das Datum mit Python
Berechnen Sie das Standardgewicht und zeigen Sie es mit Python an
Die grundlegendste Clusteranalyse mit Scikit-Learn
Lassen Sie uns die Hyperparameter des Modells mit scikit-learn abstimmen!
[Scikit-learn] Ich habe mit der ROC-Kurve gespielt
Probieren Sie SVM mit scikit-learn auf Jupyter Notebook aus
Multi-Label-Klassifizierung nach Random Forest mit Scikit-Learn
Clustering repräsentativer Schulen im Sommer 2016 mit Scikit-Learn
Implementieren Sie einen minimalen selbst erstellten Schätzer mit scikit-learn
Berechnen Sie die Fibonacci-Sequenz mit Generator und Iterator
Füllen Sie fehlende Werte mit Scikit-learn impute aus
Versuchen Sie, die β-Funktion von Godel mit SymPy zu berechnen
[Python] Ich habe versucht, TF-IDF stetig zu berechnen
Visualisieren Sie den Entscheidungsbaum von Scikit-Learn mit Plotlys Treemap