[PYTHON] 3.6 Textnormalisierung 3.7 Reguläre Ausdrücke zum Tokenisieren von Text

3.6 Normalisieren von Text Normalisierung von Text

In früheren Programmbeispielen war es üblich, Text in Kleinbuchstaben umzuwandeln, bevor etwas mit einem Wort getan wurde.

 set(w.lower()for w for text)
lower()

Ich habe den obigen Befehl verwendet, um den Text niedriger *** normalisiert *** zu machen, so dass The und the als gleich angesehen werden. In vielen Fällen gehen Sie darüber hinaus und entfernen Sie das Suffix, eine Aufgabe, die als Suffix bezeichnet wird. Ein weiterer Schritt besteht darin, sicherzustellen, dass die resultierende Form ein bekanntes Wort im Wörterbuch ist. Dies ist eine Aufgabe namens *** Headwordization ***. Diese werden der Reihe nach erklärt. Zunächst müssen Sie die in diesem Abschnitt verwendeten Daten definieren.

>>> raw = """DENNIS: Listen, strange women lying in ponds distributing swords
... is no basis for a system of government.  Supreme executive power derives from
... a mandate from the masses, not from some farcical aquatic ceremony."""
>>> tokens = word_tokenize(raw)

Stemmers

NLTK enthält mehrere handelsübliche Stemmer.

Stemmers ist die Wortstammverarbeitung << Suchmaschinen erkennen den Wortstamm aus dem Suchbegriff und der Suche einschließlich der Verwendungsform und der abgeleiteten Form >>

Wenn Sie einen Stemmer benötigen, verwenden Sie einen davon, um mithilfe regulärer Ausdrücke Vorrang vor Ihrer eigenen Kreation zu haben. Porter Stemmer und Lancaster Stemmer folgen ihren eigenen Regeln zum Entfernen von Verben.

• Porter-Stemming ist eine Methode zum Entfernen gängiger morphologischer und Flexionsendungen aus englischen Wörtern und der am häufigsten verwendete und einfachste Stemmer. -Lancaster Stemming ist die schnellste Berechnung, kann aber Probleme mit den Ergebnissen haben.

Der Porter Stemmer behandelt das falsche Wort korrekt, der Lancaster Stemmer jedoch nicht.

>>> porter = nltk.PorterStemmer()
>>> lancaster = nltk.LancasterStemmer()
>>> [porter.stem(t) for t in tokens]
['denni', ':', 'listen', ',', 'strang', 'women', 'lie', 'in', 'pond',
'distribut', 'sword', 'is', 'no', 'basi', 'for', 'a', 'system', 'of', 'govern',
'.', 'suprem', 'execut', 'power', 'deriv', 'from', 'a', 'mandat', 'from',
'the', 'mass', ',', 'not', 'from', 'some', 'farcic', 'aquat', 'ceremoni', '.']
>>> [lancaster.stem(t) for t in tokens]
['den', ':', 'list', ',', 'strange', 'wom', 'lying', 'in', 'pond', 'distribut',
'sword', 'is', 'no', 'bas', 'for', 'a', 'system', 'of', 'govern', '.', 'suprem',
'execut', 'pow', 'der', 'from', 'a', 'mand', 'from', 'the', 'mass', ',', 'not',
'from', 'som', 'farc', 'aqu', 'ceremony', '.']

Stemming ist kein genau definierter Prozess und wählt normalerweise den besten Stemmer für die Anwendung aus, an die Sie denken. Porter-Stemmers eignen sich, wenn Sie Text indizieren und die Suche mit alternativen Wortformen unterstützen möchten.

class IndexedText(object):

    def __init__(self, stemmer, text):
        self._text = text
        self._stemmer = stemmer
        self._index = nltk.Index((self._stem(word), i)
                                 for (i, word) in enumerate(text))

    def concordance(self, word, width=40):
        key = self._stem(word)
        wc = int(width/4)                # words of context
        for i in self._index[key]:
            lcontext = ' '.join(self._text[i-wc:i])
            rcontext = ' '.join(self._text[i:i+wc])
            ldisplay = '{:>{width}}'.format(lcontext[-width:], width=width)
            rdisplay = '{:{width}}'.format(rcontext[:width], width=width)
            print(ldisplay, rdisplay)

    def _stem(self, word):
        return self._stemmer.stem(word).lower()
>>> porter = nltk.PorterStemmer()
>>> grail = nltk.corpus.webtext.words('grail.txt')
>>> text = IndexedText(porter, grail)
>>> text.concordance('lie')
r king ! DENNIS : Listen , strange women lying in ponds distributing swords is no
 beat a very brave retreat . ROBIN : All lies ! MINSTREL : [ singing ] Bravest of
       Nay . Nay . Come . Come . You may lie here . Oh , but you are wounded !
doctors immediately ! No , no , please ! Lie down . [ clap clap ] PIGLET : Well
ere is much danger , for beyond the cave lies the Gorge of Eternal Peril , which
   you . Oh ... TIM : To the north there lies a cave -- the cave of Caerbannog --
h it and lived ! Bones of full fifty men lie strewn about its lair . So , brave k
not stop our fight ' til each one of you lies dead , and the Holy Grail returns t

Abbildung 3.6: Indizieren von Text mit Stemmern

Lemmatisierung

Der WordNet-Lemmatizer entfernt das Suffix nur, wenn sich das resultierende Wort im Wörterbuch befindet.

WordNet ist ein englisches Konzeptwörterbuch (semantisches Wörterbuch) Lemmatizer ist in ein Stichwort umzuwandeln. Beispiel treffen, treffen) Ich werde an der Besprechung teilnehmen. Nach der Konvertierung - Treffen Ich habe ihn letzte Nacht getroffen. Nach der Bekehrung - treffen

Dieser zusätzliche Überprüfungsprozess macht den Lemmatizer langsamer als die oben genannten Stemmers. Lüge nicht, sondern ändere wom * e * n in wom * a * n.

>>> wnl = nltk.WordNetLemmatizer()
>>> [wnl.lemmatize(t) for t in tokens]
['DENNIS', ':', 'Listen', ',', 'strange', 'woman', 'lying', 'in', 'pond',
'distributing', 'sword', 'is', 'no', 'basis', 'for', 'a', 'system', 'of',
'government', '.', 'Supreme', 'executive', 'power', 'derives', 'from', 'a',
'mandate', 'from', 'the', 'mass', ',', 'not', 'from', 'some', 'farcical',
'aquatic', 'ceremony', '.']

Der WordNet-Lemmatizer eignet sich, wenn Sie das Vokabular einiger Texte bearbeiten möchten und eine Liste gültiger Lemmas benötigen.

Ein Lemma ist ein Wort in Form eines Stichworts oder Wörterbuchs.

3.7 Reguläre Ausdrücke zum Tokenisieren von Text

** Tokenisierung ** ist die Aufgabe, eine Zeichenfolge in identifizierbare Spracheinheiten zu schneiden, die Teil der Sprachdaten sind. Dies ist eine grundlegende Aufgabe, die sich jedoch bisher verzögern könnte, da viele Korpora bereits ** tokenisiert ** sind und NLTK einige Tokenisierungen enthält. .. Wenn Sie mit kanonischen Ausdrücken vertraut sind, können Sie lernen, wie Sie sie verwenden, um Text zu "tokenisieren" und mehr Kontrolle über den Prozess zu erlangen.

Ein Token ist ein Zeichen oder eine Zeichenfolge, die bei der Analyse einer natürlichen Sprache als kleinste Einheit eines Satzes behandelt wird.

Ein einfacher Ansatz zur Tokenisierung

Der einfachste Weg, Text zu "tokenisieren", besteht darin, ihn mit Leerzeichen zu teilen. Betrachten Sie den folgenden Text von Alice's Adventures in Wonderland.

>>> raw = """'When I'M a Duchess,' she said to herself, (not in a very hopeful tone
... though), 'I won't have any pepper in my kitchen AT ALL. Soup does very
... well without--Maybe it's always pepper that makes people hot-tempered,'..."""

Sie können raw.split () verwenden, um diesen Rohtext in Leerzeichen aufzuteilen. Das Übereinstimmen des Leerzeichens in der Zeichenfolge ** [1] ** reicht nicht aus, um dasselbe mit regulären Ausdrücken zu tun. Dies liegt daran, dass ein Token generiert wird, das das Zeilenvorschubzeichen \ n enthält. Stattdessen müssen Sie eine beliebige Anzahl von Leerzeichen, Tabulatoren oder Zeilenumbrüchen zuordnen ** [2] **:

>>> re.split(r' ', raw) [1]
["'When", "I'M", 'a', "Duchess,'", 'she', 'said', 'to', 'herself,', '(not', 'in',
'a', 'very', 'hopeful', 'tone\nthough),', "'I", "won't", 'have', 'any', 'pepper',
'in', 'my', 'kitchen', 'AT', 'ALL.', 'Soup', 'does', 'very\nwell', 'without--Maybe',
"it's", 'always', 'pepper', 'that', 'makes', 'people', "hot-tempered,'..."]
>>> re.split(r'[ \t\n]+', raw) [2]
["'When", "I'M", 'a', "Duchess,'", 'she', 'said', 'to', 'herself,', '(not', 'in',
'a', 'very', 'hopeful', 'tone', 'though),', "'I", "won't", 'have', 'any', 'pepper',
'in', 'my', 'kitchen', 'AT', 'ALL.', 'Soup', 'does', 'very', 'well', 'without--Maybe',
"it's", 'always', 'pepper', 'that', 'makes', 'people', "hot-tempered,'..."]

Der reguläre Ausdruck «[\ t \ n] +» entspricht einem oder mehreren Leerzeichen, Tabulatoren (\ t) oder Zeilenumbrüchen (\ n). Andere leere Zeichen wie Wagenrückläufe und Formularvorschübe müssen tatsächlich enthalten sein.

Wagenrücklauf ist ein Steuerzeichen, das angibt, dass der Cursor an den Anfang eines Satzes im Zeichencodesystem zurückgesetzt wird.

Verwenden Sie stattdessen die integrierte Abkürzung \ s. Dies bedeutet jedes leere Zeichen. Die obige Anweisung kann als re.split (r '\ s +', raw) umgeschrieben werden.

Wichtig: Vergessen Sie nicht, dem regulären Ausdruck den Buchstaben r voranzustellen. Dies weist den Python-Interpreter an, die Zeichenfolge als Literal zu behandeln, anstatt das enthaltene Backslash-Zeichen zu behandeln.

Das Teilen mit Weißen ergibt Token wie '(nicht', 'sich selbst' usw. Stattdessen stellt Python eine Zeichenklasse \ w für Wortzeichen bereit, die [a-zA-Z0-9_] entsprechen. Sie können auch Fakten verwenden. Sie können auch \ W als Ergänzung zu dieser Klasse \ W verwenden, dh alle Zeichen außer Buchstaben, Zahlen oder Unterstrichen definieren. Verwenden Sie \ W in einem einfachen regulären Ausdruck, um das Wortzeichen zu verwenden. Sie können andere Eingänge als teilen.

Unterstrich bedeutet "_". Gleich wie Unterleiste.

>>> re.split(r'\W+', raw)
['', 'When', 'I', 'M', 'a', 'Duchess', 'she', 'said', 'to', 'herself', 'not', 'in',
'a', 'very', 'hopeful', 'tone', 'though', 'I', 'won', 't', 'have', 'any', 'pepper',
'in', 'my', 'kitchen', 'AT', 'ALL', 'Soup', 'does', 'very', 'well', 'without',
'Maybe', 'it', 's', 'always', 'pepper', 'that', 'makes', 'people', 'hot', 'tempered',
'']

Beachten Sie, dass Sie am Anfang und am Ende eine leere Zeichenfolge erhalten. Holen Sie sich das gleiche Token, aber verwenden Sie re.findall (r '\ w +', raw), verwenden Sie ein Muster, das mit dem Wort übereinstimmt, anstelle eines Leerzeichens und verwenden Sie keine leere Zeichenfolge. Nachdem wir die Wörter gefunden haben, sind wir in der Lage, den kanonischen Ausdruck auf ein breiteres Spektrum von Fällen auszudehnen. Der reguläre Ausdruck «\ w + | \ S \ w *» versucht zunächst, eine Folge von Wortbuchstaben abzugleichen.

Eine Sequenz besteht aus einer Reihe von Daten und Prozeduren, die in der Reihenfolge angeordnet sind, und einer Verarbeitungsmethode, die Daten und Prozeduren in der Reihenfolge behandelt, in der sie angeordnet sind.

Wenn keine Übereinstimmung gefunden wird, wird versucht, ein nicht leeres Zeichen (\ S ist das Komplement von \ s), gefolgt von einem anderen Wortzeichen, abzugleichen. Das heißt, die Interpunktion wird nach nachfolgenden Zeichen (z. B.) gruppiert, aber Sequenzen von zwei oder mehr Interpunktionszeichen werden getrennt.

>>> re.findall(r'\w+|\S\w*', raw)
["'When", 'I', "'M", 'a', 'Duchess', ',', "'", 'she', 'said', 'to', 'herself', ',',
'(not', 'in', 'a', 'very', 'hopeful', 'tone', 'though', ')', ',', "'I", 'won', "'t",
'have', 'any', 'pepper', 'in', 'my', 'kitchen', 'AT', 'ALL', '.', 'Soup', 'does',
'very', 'well', 'without', '-', '-Maybe', 'it', "'s", 'always', 'pepper', 'that',
'makes', 'people', 'hot', '-tempered', ',', "'", '.', '.', '.']

Verallgemeinern Sie \ w + in der obigen Formel, um Bindestriche und Apostolophien in Wörtern zuzulassen: «\ w + ([- '] \ w +) *». Dieser Ausdruck bedeutet, dass auf \ w + null oder mehr Instanzen von [- '] \ w + folgen. Es passt zum heißen Temperament. Fügen Sie außerdem ein Muster hinzu, das dem in Anführungszeichen gesetzten Zeichen entspricht, damit es vom Text, den das in Anführungszeichen gesetzte Zeichen enthält, getrennt bleibt.

>>> print(re.findall(r"\w+(?:[-']\w+)*|'|[-.(]+|\S\w*", raw))
["'", 'When', "I'M", 'a', 'Duchess', ',', "'", 'she', 'said', 'to', 'herself', ',',
'(', 'not', 'in', 'a', 'very', 'hopeful', 'tone', 'though', ')', ',', "'", 'I',
"won't", 'have', 'any', 'pepper', 'in', 'my', 'kitchen', 'AT', 'ALL', '.', 'Soup',
'does', 'very', 'well', 'without', '--', 'Maybe', "it's", 'always', 'pepper',
'that', 'makes', 'people', 'hot-tempered', ',', "'", '...']

Die obige Formel lautet «[-. (] + »Ist auch enthalten, um doppelte Bindestriche, Auslassungspunkte und offene Klammern separat zu kennzeichnen. Listet die in diesem Abschnitt von 3.4 gezeigten kanonischen Zeichenklassensymbole und andere nützliche Symbole auf. Es ist gewesen.

Tabelle 3.4: Symbole für reguläre Ausdrücke

Symbol Function
\b Wortgrenze (Nullbreite)
\d Beliebige Dezimalzahl ([0-9]Gleichwertig)
\D Andere Zeichen als Zahlen ([^ 0-9]Gleichwertig)
\s Leeres Zeichen ([\ t \ n \ r \ f \ v]Gleichwertig)
\S Nicht leere Zeichen ([^ \ t \ n \ r \ f \ v]Gleichwertig)
\w Beliebige alphanumerische Zeichen ([a-zA-Z0-9_]Gleichwertig)
\W Alle nicht alphanumerischen ([^ a-zA-Z0-9_]Gleichwertig)
\t Tabulatorzeichen
\n Charakter brechen

NLTK-Tokenizer für reguläre Ausdrücke

Die Funktion nltk.regexp_tokenize () ähnelt re.findall () (da sie für die Tokenisierung verwendet wird). Nltk.regexp_tokenize () ist jedoch für diese Aufgabe effizienter und vermeidet die Notwendigkeit einer speziellen Behandlung von Klammern. Teilen Sie den regulären Ausdruck zur besseren Lesbarkeit in mehrere Zeilen auf und fügen Sie für jede Zeile einen Kommentar hinzu. Ein spezielles "ausführliches Flag" weist Python an, eingebettete Leerzeichen und Kommentare zu entfernen.

>>> text = 'That U.S.A. poster-print costs $12.40...'
>>> pattern = r'''(?x)     # set flag to allow verbose regexps
...     (?:[A-Z]\.)+       # abbreviations, e.g. U.S.A.
...   | \w+(?:-\w+)*       # words with optional internal hyphens
...   | \$?\d+(?:\.\d+)?%? # currency and percentages, e.g. $12.40, 82%
...   | \.\.\.             # ellipsis
...   | [][.,;"'?():-_`]   # these are separate tokens; includes ], [
... '''
>>> nltk.regexp_tokenize(text, pattern)
['That', 'U.S.A.', 'poster-print', 'costs', '$12.40', '...']

Wenn Sie das Detail-Flag verwenden, können Sie "" nicht mehr verwenden, um das Leerzeichen zu finden. Verwenden Sie stattdessen \ s. Die Funktion regexp_tokenize () verfügt über einen optionalen Lückenparameter. Wenn True festgelegt ist, gibt der reguläre Ausdruck die Lücke zwischen Token an, ähnlich wie bei re.split ().

Andere Probleme mit der Tokenisierung

Die Tokenisierung erwies sich als viel schwieriger als erwartet. Es gibt keine einzige Lösung, die einwandfrei funktioniert. Abhängig von Ihrer Anwendungsdomäne müssen Sie entscheiden, was als Token gezählt werden soll.

Bei der Entwicklung eines Tokenizers ist es hilfreich, auf manuell tokenisierten Rohtext zuzugreifen, um die Tokenizer-Ausgabe mit hochwertigen Token (oder "Goldstandard" -Token) zu vergleichen. Die NLTK Corpus Collection enthält Beispiele für Penn Treebank-Daten, einschließlich Rohtext des Wall Street Journal (nltk.corpus.treebank_raw.raw ()) und tokenisierter Versionen (nltk.corpus.treebank.words ()). Ich werde.

Das letzte Problem bei der Tokenisierung ist das Vorhandensein von Kontraktionen. Wenn Sie die Bedeutung einer Anweisung analysieren, ist es wahrscheinlich bequemer, dieses Formular in zwei separate Formulare zu normalisieren: did und n't (oder nicht). Sie können dies mit einer Nachschlagetabelle tun.

Eine Nachschlagetabelle besteht aus Daten wie einem Array oder einem assoziativen Array, die den Berechnungsprozess zu einem Array-Referenzprozess machen. Wenn Sie beispielsweise ein Element in einer Datenbank auswählen und die diesem Element entsprechenden Daten abrufen möchten, können Sie die dem Element entsprechenden Daten im Voraus als Nachschlagetabelle speichern und auf den dem Element entsprechenden Wert aus der Nachschlagetabelle verweisen. Dadurch können die dem Artikel entsprechenden Daten angefordert werden. Da es nicht erforderlich ist, die Berechnung jedes Mal durchzuführen, wenn eine Anforderung gestellt wird, kann die Berechnungslast auf dem Computer reduziert und die Verarbeitung effizient durchgeführt werden.

Recommended Posts

3.6 Textnormalisierung 3.7 Reguläre Ausdrücke zum Tokenisieren von Text
Nach Sprache: Reguläre Ausdrücke für Passwörter
[Python] Reguläre Ausdrücke Reguläre Ausdrücke
Python-Pandas: Suchen Sie mit regulären Ausdrücken nach DataFrame
Rufen Sie die Python-Bibliothek zur Textnormalisierung in MATLAB auf
Text Mining (für Memo)
Verwenden Sie reguläre Ausdrücke in C.
Zahlen mit regulären Ausdrücken extrahieren
Über Python und reguläre Ausdrücke