[JAVA] Sortie d'une API qui peut utiliser Phrase Piece comme l'analyse morphologique

Post-scriptum 2017/4/13: J'ai reçu des conseils de M. taku910 lui-même. Voir la section des commentaires pour plus de détails. Cet article sera révisé ultérieurement. PostScript 2017/4/18: L'API publique a été modifiée. Unigram est toujours en train de construire un modèle (cela ne se termine pas même après 5 jours). 2017/4/26 postscript: Unigram a également été fait (il était finalement terminé après avoir tourné pendant 12 jours). Des détails à ce sujet ont été publiés dans Un autre article.

introduction

API

Exemple de code

Article associé

Détails d'implémentation

Pour expliquer brièvement

  1. Appliquer une phrase aux articles de Wikipedia japonais
  2. Formatez le fichier vocal qui est la sortie de SentencePiece au format dictionnaire de mecab-ipadic.
  3. Compilez le dictionnaire entier avec kuromoji

Laissez-moi vous expliquer un peu plus en détail.

1. Appliquer une phrase aux articles de Wikipedia japonais

Les données de Wikipedia japonais que j'avais étaient un peu anciennes avec le vidage de 20160915, mais je les ai utilisées comme données d'origine. Je le façonne avec quelques modifications. Si vous listez ce que vous avez fait

  1. Le vidage est converti en texte avec wp2txt, et tous sont rassemblés dans un seul fichier.
  2. Supprimez les lignes de 40 caractères ou moins
  3. Supprimez «Image», «Fichier», «Image» et «Fichier» au début de la ligne.
  4. Permutation aléatoire des lignes dans le fichier
  5. Exécutez Phrase Piece en utilisant les 1 700 000 premières lignes (environ 600 Mo)

La raison pour laquelle je fais cela est que SentencePiece semble nécessiter beaucoup de mémoire et que je ne pouvais pas entrer le texte intégral (environ 2 Go) sur mon PC (16 Go de mémoire). Après de nombreux essais et erreurs, il semble qu'environ 600 Mo soit la limite pour un PC de 16 Go. Au lieu de cela, le processus est rapide tant que les données sont en mémoire.

PhrasePiece s'exécute avec la commande suivante. En ce qui concerne l'environnement d'exécution, j'ai mis Cygwin dans Windows 10 et l'ai exécuté. La bibliothèque nécessaire qui était dans le README original était Cygwin et j'ai mis quelque chose comme ça (certaines versions ne correspondent pas, mais cela a fonctionné).

$ ./spm_train --input=input.txt --model_prefix=output --vocab_size=8000 --model_type=bpe

La sortie est un fichier vocal et un fichier modèle. Le fichier de vocabulaire est un fragment de mot de 8000 lignes.

2. Formatez le fichier vocal qui est la sortie de SentencePiece au format dictionnaire de mecab-ipadic.

Maintenant, préparez-vous à publier avec l'API Web. La réponse de l'API Web renverra un ensemble de "fragment de mot" et "ID de fragment de mot" sous forme de tableau. Utilisez "Word Fragment ID", par exemple, lors de la création d'un vecteur One-Hot dans l'apprentissage automatique. Bien sûr, vous n'êtes pas obligé de l'utiliser.

Maintenant, considérons l'implémentation. Le marché de l'API Web Apitore que j'exécute est entièrement implémenté en Java, mais Sentence Piece est écrit en C ++. "C'est un problème d'écrire un wrapper, et je ne comprends pas vraiment WebAPI en C ++ ... donc je dois le réaliser de force! SentencePiece est comme une analyse morphologique, n'est-ce pas?" J'ai décidé d'utiliser l'analyseur morphologique Java kuromoji. kuromoji est la version Java du célèbre mecab. Et mecab est la technologie de recherche de M. Kudo qui a créé Sentence Piece. Vous êtes connecté!

Donc, cette fois, j'ai pris la forme d'ajouter la sortie de Sentence Piece en tant que nouveau dictionnaire au kuromoji existant. Au lieu de cela, voici quelques astuces. Le format du dictionnaire ressemble à ceci.

#Type de surface,ID de contexte gauche,ID de contexte correct,Coût,Partie,Partie細分類1,Partie細分類2,Partie細分類3,Type d'utilisation,Type d'utilisation,Prototype,en train de lire,prononciation
Être terminé,1,1,1,SPWORD,1,*,*,*,*,*,*,*

La «forme de surface» est le «fragment de mot» qui est la sortie de la phrase Piece. Le but est de régler le «coût» sur «1». Si "Coût" est réglé sur "1", le fragment de mot du fragment de phrase sera presque certainement sélectionné lors de l'analyse morphologique. Pour être sûr, modifiez le coût de connexion de toutes les pièces à 1 dans `` matrice.def '', qui définit le coût de connexion du contexte. En faisant cela, vous pouvez "relier les fragments de mots de la phrase Piece sans tenir compte du contexte". Vous n'avez pas à vous soucier du contexte, donc l '"ID de contexte" peut être n'importe quoi. Cette fois, l '"ID de contexte" est défini sur "1".

«ID de fragment de mot» a été attribué à «Partie de la sous-catégorie de mots 1». "Word Fragment ID" est un identifiant unique que j'ai donné à la sortie 8000 mots de la phrase Piece (c'est-à-dire 8000 identifiants au total, les numéros 1 à 8000 sont utilisés). La «partie du mot» de la phrase est «SPWORD». Cette partie du mot est utilisée pour rechercher des mots qui ne sont pas couverts par le fragment de phrase. Pour expliquer un peu, les fragments de mot de Sentence Piece sont basés sur des données d'entraînement. Bien sûr, il n'existe aucun moyen de gérer des caractères qui ne sont jamais apparus dans les données d'entraînement. J'ai décidé de détecter le caractère inconnu avec le kuromoji conventionnel. (Je pense que les caractères inconnus sont presque certainement classés comme "mots inconnus") Lorsque les paroles de la partie ne sont pas "SPWORD", l'ID de fragment de mot est mis à "0". Cela peut gérer des caractères inconnus.

3. Compilez le dictionnaire entier avec kuromoji

Tout ce que vous avez à faire est de compiler. Compilez kuromoji comme d'habitude. Le code de test inclus dans kuromoji ne passera jamais, supprimez donc le test.

En fait utiliser

L'API est disponible sur ici. Veuillez consulter ici pour les préparatifs des appels d'API (enregistrement d'API, émission de jetons d'accès, exemple d'exécution).

Les spécifications telles que les entrées / sorties API sont publiées sur ici. Si vous l'écrivez également ici, les spécifications de réponse de l'API sont comme ça. L'entrée est du texte.

{
  "endTime": "string",
  "log": "string",
  "processTime": "string",
  "startTime": "string",
  "tokens": [
    {
      "token": "string",
      "wid": 0
    }
  ]
}

Voyons un exemple d'utilisation réel. J'ai entré "Je suis un chat. Je n'ai pas encore de nom". Certes, c'est un peu différent de l'analyse morphologique normale.

"tokens": [
  {
    "wid": 5578,
    "token": "je"
  },
  {
    "wid": 5386,
    "token": "Employé"
  },
  {
    "wid": 472,
    "token": "Est"
  },
  {
    "wid": 5643,
    "token": "Chat"
  },
  {
    "wid": 11,
    "token": "Est"
  },
  {
    "wid": 3796,
    "token": "。"
  },
  {
    "wid": 2002,
    "token": "Nom"
  },
  {
    "wid": 472,
    "token": "Est"
  },
  {
    "wid": 1914,
    "token": "encore"
  },
  {
    "wid": 26,
    "token": "Absent"
  },
  {
    "wid": 3796,
    "token": "。"
  }
]

Puis, "WRYYYYYYYYYY! Le plus élevé est Aaaa". Il a été démonté en morceaux.

"tokens": [
  {
    "wid": 829,
    "token": "W"
  },
  {
    "wid": 589,
    "token": "R"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 3032,
    "token": "Y"
  },
  {
    "wid": 0,
    "token": "!"
  },
  {
    "wid": 799,
    "token": "Meilleur"
  },
  {
    "wid": 2689,
    "token": "À"
  },
  {
    "wid": 646,
    "token": "Oui"
  },
  {
    "wid": 9,
    "token": "Quoi"
  },
  {
    "wid": 3880,
    "token": "Ou"
  },
  {
    "wid": 3888,
    "token": "Un"
  },
  {
    "wid": 3914,
    "token": "Est"
  },
  {
    "wid": 1726,
    "token": "UNE"
  },
  {
    "wid": 1726,
    "token": "UNE"
  },
  {
    "wid": 1726,
    "token": "UNE"
  }
]

Enfin, entrez "Vaincre la" peur ", c'est" vivre "". C'est un segment très caractéristique.

"tokens": [
  {
    "wid": 648,
    "token": "「"
  },
  {
    "wid": 5092,
    "token": "Effrayant"
  },
  {
    "wid": 5725,
    "token": "Effrayant"
  },
  {
    "wid": 3846,
    "token": "」"
  },
  {
    "wid": 2163,
    "token": "À"
  },
  {
    "wid": 5711,
    "token": "Katsu"
  },
  {
    "wid": 4840,
    "token": "vêtements"
  },
  {
    "wid": 543,
    "token": "Faire"
  },
  {
    "wid": 648,
    "token": "「"
  },
  {
    "wid": 2859,
    "token": "Vivre"
  },
  {
    "wid": 3798,
    "token": "Ru"
  },
  {
    "wid": 3846,
    "token": "」"
  },
  {
    "wid": 12,
    "token": "chose"
  }
]

en conclusion

J'ai défini la phrase Piece sur Web API. Cela semble être Mochiron à utiliser dans la traduction, et comme il peut être utilisé pour sec2sec, il semble que la conversion standard langue-dictionnaire puisse également être effectuée. Je pense l'utiliser pour le jugement de polarité. En ce moment, je fais RNN + LSTM pour les résultats Word2Vec, mais RNN + LSTM n'est-il pas quelque chose de bon pour créer un vecteur unique avec les fragments de mots de Sentence Piece?

Recommended Posts

Sortie d'une API qui peut utiliser Phrase Piece comme l'analyse morphologique
Suite - Publication d'une API Web qui peut utiliser des morceaux de phrase comme l'analyse morphologique
Analyse morphologique en Java avec Kuromoji
NLP4J [001b] Analyse morphologique en Java (utilisant kuromoji)
Obtenez des résultats détaillés de l'analyse morphologique avec Apache Solr 7.6 + SolrJ (japonais)
Sortie d'une API qui peut utiliser Phrase Piece comme l'analyse morphologique
J'ai essayé l'analyse morphologique avec MeCab
Suite - Publication d'une API Web qui peut utiliser des morceaux de phrase comme l'analyse morphologique