[PYTHON] Ich habe eine Bibliothek erstellt, um japanische Sätze schön zu brechen

Einführung

In den letzten Jahren war die Entwicklung der Verarbeitungstechnologie für natürliche Sprachen bemerkenswert, und ihre Anwendung wird in verschiedenen Bereichen gefördert. Ich arbeite oft mit natürlicher Sprachverarbeitungstechnologie und KI, aber die mühsamste (aber wichtigste) Arbeit hängt mit verschiedenen Vorverarbeitungen zusammen.

Einige der wichtigsten Vorprozesse, die Sie für die meisten Aufgaben ausführen müssen, sind:

Ich benutze hauptsächlich Python, aber ich hatte keine geeignete Bibliothek für ** japanische Satzumbrüche **, so dass ich jedes Mal ähnlichen Code schrieb. Ich bin mir sicher, dass es auf der Welt ungefähr 100 Menschen gibt, die ähnliche Probleme haben. Deshalb habe ich beschlossen, meine eigene Bibliothek zu schreiben und als OSS zu veröffentlichen, aber es war Anfang 2019. Es ist Zeit. Ich konnte mir jedoch nicht genügend Zeit und Motivation sichern und es verzögerte sich, aber ich konnte endlich damit beginnen, das Limit für das Schreiben von Artikeln im Adventskalender festzulegen.

Spezifische Satzbruchprobleme

Ich denke, die folgenden werden häufiger als einfache Satzbegrenzer verwendet.

Es gibt jedoch viele tatsächliche Dokumente, die durch die oben genannten einfachen Regeln nicht gut getrennt werden können.

Es gibt Satzzeichen und Ausrufezeichen in "" und ()

Zum Beispiel antwortete ich: "Ja, das ist richtig." Wenn Sie Text wie `einfach durch Interpunktion trennen, wird er wie folgt aufgeteilt:

Ich denke, es gibt einige gute Situationen, aber ich antwortete: "Ja, das ist richtig." Vielleicht möchten Sie es als einen Satz behandeln, `.

Es gibt eine Pause in der Mitte des Satzes

Beispielsweise kann es aus Gründen, die nicht auf einen Bildschirm passen, zu einer Unterbrechung in der Mitte eines Satzes kommen, wie unten gezeigt (insbesondere bei Dokumenten in einem Unternehmen).

In der Verarbeitung natürlicher Sprache ~ weggelassen ~
Es wird häufig verwendet.

Wenn dies durch einen Zeilenumbruch getrennt ist, wird es in zwei Sätze unterteilt, aber bei der Verarbeitung natürlicher Sprache ist es üblich, ~ weggelassen ~ zu verwenden. Vielleicht möchten Sie es als einen einzigen Satz trennen, `.

Wenn Sie im obigen Beispiel die Zeilenumbrüche entfernen und sie dann durch Satzzeichen trennen, können Sie etwas dagegen tun, aber ** enthält Sätze ohne Satzzeichen **, was es viel schwieriger macht. (~~ Bitte einige Satzzeichen hinzufügen ... ~~)

Angebotsblock für E-Mails usw.

>>Ich hatte vor, morgen in den Friseurladen zu gehen, aber "in Eile"
>>Ändern Sie den Zeitplan. Daher des Treffens
>>Lassen Sie mich den Zeitplan ändern. ".

Ich habe bestätigt.

Fälle, in denen am Anfang von Zeilen unnötige Symbole und in der Mitte eines Satzes Zeilenumbrüche stehen. Es gibt eine Theorie, dass dies der häufigste Fall in Unternehmensdokumenten ist (subjektiv). Am einfachsten ist es, zuerst die Symbole und Zeilenumbrüche zu entfernen und sie dann zu verarbeiten. Es ist jedoch selten, dass Sie sie kombinieren möchten, während Sie unnötige Symbole entfernen und die Information hinterlassen, dass es sich um einen Anführungszeichenblock handelt.

Verwandte Techniken

GiNZA GiNZA ist eine Bibliothek, mit der japanische Sätze in Python getrennt werden können. Satzpausen mit GiNZA können wie folgt durchgeführt werden.

import spacy
nlp = spacy.load('ja_ginza')
doc = nlp('Mir wurde gesagt: "Ich kann deine Gedanken nicht beantworten. Ich möchte, dass du andere schlägst." Betäubt\n Ich hatte keine andere Wahl, als dort zu stehen, aber ich möchte immer noch glauben!')
for sent in doc.sents:
  print(sent)
Ich sagte: "Ich kann deine Gedanken nicht beantworten.
Ich möchte, dass du den anderen schlägst.
"Sie sagten!
Ich war fassungslos und hatte keine andere Wahl, als dort zu stehen
Trotzdem möchte ich glauben!

Der Vorteil der Verwendung von GiNZA besteht darin, dass Satzumbrüche mit hoher Genauigkeit erkannt werden können, selbst wenn ein Zeilenumbruch in der Mitte eines Satzes vorliegt oder ein Satzzeichen weggelassen wird, da die Abhängigkeitsanalyse ordnungsgemäß durchgeführt wird. .. Obwohl es sich um eine Schwergewichtsklasse handelt, halte ich es für eine gute Option, wenn Sie auch andere Funktionen von GiNZA verwenden.

sentence-splitter Es ist ein Tool von Node.js, aber es gibt auch ein Tool namens Satzteiler.

echo -e "Sagte: "Ich kann deine Gedanken nicht beantworten. Ich möchte, dass du andere schlägst." Betäubt\n Ich hatte keine andere Wahl, als dort zu stehen, aber ich möchte immer noch glauben!" | sentence-splitter 
Sentence 0:Mir wurde gesagt: "Ich kann deine Gedanken nicht beantworten. Ich möchte, dass du andere schlägst."
Sentence 1:Betäubt
Ich hatte keine andere Wahl, als dort zu stehen, aber ich möchte immer noch glauben!

Dieses Tool verwendet auch den in textlint verwendeten Parser für erweiterte Analysen, sodass er auch dann korrekt ist, wenn in der Mitte des Satzes eine Unterbrechung vorliegt. Es ist hoch geteilt. Es ist auch attraktiv, dass ich die Handhabung von "" usw. mag und dass die Verarbeitungsleistung ziemlich schnell ist. (Wenn es nicht Node.js wäre, hätte ich es übernommen)

Pragmatic Segmenter Obwohl es sich um eine Ruby-Bibliothek handelt, gibt es einen Pragmatic Segmenter. Es handelt sich um eine regelbasierte Satzbegrenzungsbibliothek, deren Hauptvorteil darin besteht, dass sie ** mehrere Sprachen ** unterstützt. Es ist auch attraktiv, weil es keine komplizierten Analysen durchführt und schnell zu verarbeiten ist.

Da die japanischen Satzbruchregeln meinem Geschmack sehr nahe kommen, besteht das Ziel dieser Werkzeugentwicklung darin, "japanische Sätze gleich oder besser als den pragmatischen Segmentierer zu machen".

Für dieses Tool ist eine Live-Demo (https://www.tm-town.com/natural-language-processing) verfügbar. Die Ergebnisse, die ich dort ausprobiert habe, sind unten aufgeführt.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wrapper>
<s>Mir wurde gesagt: "Ich kann deine Gedanken nicht beantworten. Ich möchte, dass du andere schlägst."</s>
<s>Betäubt</s>
<s>Ich hatte keine andere Wahl, als dort zu stehen, aber ich möchte immer noch glauben!</s>
</wrapper>

Ein Python-Port dieses Pragmatic Segmenter wurde übrigens als [pySBD] entwickelt (https://github.com/nipunsadvilkar/pySBD). Leider scheinen die Regeln für Japanisch noch nicht portiert worden zu sein.

Was ich gemacht habe

Die Bibliothek, die ich dieses Mal erstellt habe, ist also unter ↓ für die Öffentlichkeit zugänglich. https://github.com/wwwcojp/ja_sentence_segmenter

Bei der Erstellung der Bibliothek habe ich sie mit den folgenden Zielen entwickelt.

Wie benutzt man

Installation

Es ist In PyPI veröffentlichen, sodass Sie es problemlos mit pip installieren können. Es unterstützt Python 3.6 und höher und es gibt bisher keine abhängigen Bibliotheken.

$ pip install ja-sentence-segmenter

Lauf

Es gibt Satzzeichen und Ausrufezeichen in "" und () und Zeilenumbrüche in der Mitte des Satzes

import functools

from ja_sentence_segmenter.common.pipeline import make_pipeline
from ja_sentence_segmenter.concatenate.simple_concatenator import concatenate_matching
from ja_sentence_segmenter.normalize.neologd_normalizer import normalize
from ja_sentence_segmenter.split.simple_splitter import split_newline, split_punctuation

split_punc2 = functools.partial(split_punctuation, punctuations=r"。!?")
concat_tail_te = functools.partial(concatenate_matching, former_matching_rule=r"^(?P<result>.+)(Hand)$", remove_former_matched=False)
segmenter = make_pipeline(normalize, split_newline, concat_tail_te, split_punc2)

text1 = """
Mir wurde gesagt: "Ich kann deine Gedanken nicht beantworten. Ich möchte, dass du andere schlägst." Betäubt
Ich hatte keine andere Wahl, als dort zu stehen, aber ich möchte immer noch glauben!
"""
print(list(segmenter(text1)))
['Mir wurde gesagt: "Ich kann deine Gedanken nicht beantworten. Ich möchte, dass du andere schlägst."!', 'Ich war fassungslos und hatte keine andere Wahl, als dort zu stehen, aber ich möchte immer noch glauben!']

E-Mail-Angebotsblock

import functools

from ja_sentence_segmenter.common.pipeline import make_pipeline
from ja_sentence_segmenter.concatenate.simple_concatenator import concatenate_matching
from ja_sentence_segmenter.normalize.neologd_normalizer import normalize
from ja_sentence_segmenter.split.simple_splitter import split_newline, split_punctuation

split_punc2 = functools.partial(split_punctuation, punctuations=r"。!?")
concat_mail_quote = functools.partial(concatenate_matching,
  former_matching_rule=r"^(\s*[>]+\s*)(?P<result>.+)$",
  latter_matching_rule=r"^(\s*[>]+\s*)(?P<result>.+)$",
  remove_former_matched=False,
  remove_latter_matched=True)
segmenter = make_pipeline(normalize, split_newline, concat_mail_quote, split_punc2)

text2 = """
>>Ich hatte vor, morgen in den Friseurladen zu gehen, aber "in Eile"
>>Ändern Sie den Zeitplan. Daher des Treffens
>>Lassen Sie mich den Zeitplan ändern. ".

Ich habe bestätigt.
"""

print(list(segmenter(text2)))
['>>Ich hatte vor, morgen in den Friseurladen zu gehen, aber er sagte: "Ich werde meinen Zeitplan in Eile ändern. Bitte lassen Sie mich den Zeitplan des Treffens ändern."', 'Ich habe bestätigt.']

Zukünftige Aufgaben

Ich bin fast erschöpft, also werde ich abschließend zukünftige Probleme angeben.

Impressionen

~~ Warum hast du so etwas Nüchternes im Adventskalender-Artikel gemacht ... ~~

Recommended Posts

Ich habe eine Bibliothek erstellt, um japanische Sätze schön zu brechen
Ich habe eine Python-Bibliothek erstellt, die einen rollierenden Rang hat
Ich habe eine Bibliothek erstellt, die Konfigurationsdateien mit Python einfach lesen kann
Ich habe ein Skript erstellt, um Piktogramme anzuzeigen
Ich habe eine Bibliothek für versicherungsmathematische Versicherungen erstellt
PyPi-Debüt Ich habe versucht, eine Pip-Installation zu ermöglichen, um japanische Feiertage zu überprüfen
Ich habe eine Bibliothek konoha gemacht, die den Tokenizer auf ein schönes Gefühl umstellt
Ich habe ein Tool erstellt, um Hy nativ zu kompilieren
Ich habe ein Tool erstellt, um neue Artikel zu erhalten
Ich habe eine Bibliothek zum Betreiben des AWS CloudFormation-Stacks über CUI (Python Fabric) erstellt.
Ich habe ein Skript erstellt, um ein Snippet in README.md einzufügen
Ich habe ein Python-Modul erstellt, um Kommentare zu übersetzen
Ich habe einen Code erstellt, um illustration2vec in ein Keras-Modell zu konvertieren
Ich habe einen Befehl zum Markieren des Tabellenclips gegeben
Ich habe einen Python-Text gemacht
Ich habe einen Zwietrachtbot gemacht
Ich habe ein Paket erstellt, um Zeitreihen mit Python zu filtern
Ich habe eine Schachtel gemacht, um mich auszuruhen, bevor Pepper müde wird
Ich habe einen Befehl zum Generieren eines Kommentars für eine Tabelle in Django eingegeben
Ich habe ein Tool erstellt, um eine Wortwolke aus Wikipedia zu erstellen
Ich habe eine Funktion erstellt, um das Modell von DCGAN zu überprüfen
[Titan Craft] Ich habe ein Werkzeug gemacht, um einen Riesen nach Minecraft zu rufen
Ich habe Sie dazu gebracht, Befehle über einen WEB-Browser auszuführen
Ich habe ein Drehbuch gemacht, um bei meinem Koshien Hallo zu sagen
Ich habe eine C ++ - Lernseite erstellt
Ich habe versucht, ein Programm zu erstellen, um die Fehlersuche von Saiseriya zu lösen (Hinweis)
Ich habe einen Line-Bot mit Python gemacht!
Ich habe ein CUI-basiertes Übersetzungsskript erstellt (2)
Ich habe einen Wikipedia Gacha Bot gemacht
Ich habe mit Razpai einen Webserver erstellt, um Anime zu schauen
Ich habe eine Python-Bibliothek erstellt, um die API von LINE WORKS aufzurufen
Ich habe meine eigene Python-Bibliothek erstellt
Ich habe mit Python eine Lotterie gemacht.
Ich habe ein CUI-basiertes Übersetzungsskript erstellt
Ich habe einen verstümmelten Generator erstellt, der Ihre Lieblingssätze von UTF-8 bis Shift-JIS (cp932) in Python codiert
Ich habe den Befehl gegeben, einen farbenfrohen Kalender im Terminal anzuzeigen
Ich habe mit Python einen Daemon erstellt
Ich habe eine Python-Wrapper-Bibliothek für die Docomo-Bilderkennungs-API erstellt.
Ich habe einen Docker-Container erstellt, um JUMAN ++, KNP, Python (für pyKNP) zu verwenden.
[Python] Ich habe einen Dekorateur gemacht, der keinen Nutzen zu haben scheint.
Ich habe einen Passwortgenerator erstellt, um Kindern Python3 beizubringen (Bonus) * Vollständig neu erstellt
Ich habe ein Tool zum automatischen Durchsuchen mehrerer Websites mit Selenium (Python) erstellt.
[Ver1.3.1 Update] Ich habe DataLiner erstellt, eine Datenvorverarbeitungsbibliothek für maschinelles Lernen.
Ich habe eine Webanwendung in Python erstellt, die Markdown in HTML konvertiert
Erstellt Go-Bibliothek nzargv, die Befehlszeilenargumente gut anordnet
[Django] Erstellt ein Feld zur Eingabe von Daten mit 4-stelligen Zahlen
Ich habe einen Küchentimer erstellt, der in der Statusleiste angezeigt wird!
Ich habe ein CLI-Tool erstellt, um Bilder in jedem Verzeichnis in PDF zu konvertieren
Ich habe ein Programm erstellt, um Sie per LINE zu benachrichtigen, wenn Schalter eintreffen
Ich habe ein Netzwerk erstellt, um Schwarzweißbilder in Farbbilder umzuwandeln (pix2pix)
Ich habe ein Skript in Python erstellt, um MDD-Dateien in das Scrapbox-Format zu konvertieren
Ich habe ein Programm erstellt, um einzugeben, was ich gegessen habe, und um Kalorien und Zucker anzuzeigen
Ich habe ein Tool erstellt, um Jupyter py mit VS Code in ipynb zu konvertieren
Ich habe ein Programm erstellt, um die Größe einer Datei mit Python zu überprüfen
Ich habe eine Funktion erstellt, um die Bewegung eines zweidimensionalen Arrays (Python) zu sehen.
Ich habe ein Dash-Docset für Holoviews erstellt
Ich möchte in der Einschlussnotation drucken
Ich habe versucht, einen Linebot zu erstellen (Vorbereitung)