Je résous 100 coups sur le traitement du langage lors d'une session d'étude centrée sur les membres de l'entreprise, mais le code de réponse et la solution Ceci est un résumé des astuces que j'ai trouvées utiles dans le processus. La plupart du contenu a été étudié et vérifié par moi-même, mais il contient également des informations partagées par d'autres membres du groupe d'étude.
Jusqu'au chapitre 3, le contenu était utilisable pour toute la programmation Python, mais comme ce chapitre est une analyse morphologique, il devient finalement davantage un traitement de langage.
Mettez neko.txt
dans le même répertoire que le fichier ipynb (ou Python)
!mecab neko.txt -o neko.txt.mecab
Ensuite, le résultat de l'analyse morphologique est enregistré dans neko.txt.mecab
.
import re
import itertools
def parse_text(flat=True):
with open('neko.txt.mecab') as file:
morphs = []
sentence = []
for line in file:
if re.search(r'EOS', line):
continue
surface, rest = line.split('\t')
arr = rest.split(',')
sentence.append({
'surface': surface,
'base': arr[6],
'pos': arr[0],
'pos1': arr[1],
})
if surface == ' ': #Les blancs ne sont pas considérés comme des éléments morphologiques
sentence.pop(-1)
if surface in [' ', '。']: #Considérez les blancs et la ponctuation comme la fin d'une phrase
morphs.append(sentence)
sentence = []
if flat:
return list(itertools.chain.from_iterable(morphs))
else:
return morphs
parse_text(flat=False)[:10]
résultat
[[{'surface': 'je', 'base': 'je', 'pos': 'nom', 'pos1': '代nom'},
{'surface': 'Est', 'base': 'Est', 'pos': 'Particule', 'pos1': '係Particule'},
{'surface': 'Chat', 'base': 'Chat', 'pos': 'nom', 'pos1': 'Général'},
{'surface': 'alors', 'base': 'Est', 'pos': 'Verbe auxiliaire', 'pos1': '*'},
{'surface': 'y a-t-il', 'base': 'y a-t-il', 'pos': 'Verbe auxiliaire', 'pos1': '*'},
{'surface': '。', 'base': '。', 'pos': 'symbole', 'pos1': 'Phrase'}],
[{'surface': 'Nom', 'base': 'Nom', 'pos': 'nom', 'pos1': 'Général'},
Ce problème nécessite «d'exprimer une phrase comme une liste d'éléments morphologiques (type de mappage)», mais lors de l'utilisation de cette fonction dans les problèmes 31 et suivants, la valeur de retour a été aplatie (non imbriquée). ) Est plus facile à gérer, j'ai donc décidé de préparer un argument formel appelé flat
. La valeur par défaut de ce «flat» est «True», mais dans ce numéro, je passe l'argument «flat = False» car je veux une liste non aplatie.
La dernière ligne dit «[: 10]» parce que c'était juste que le nombre d'éléments à afficher pour confirmation était d'environ 10, donc il n'y a pas de nécessité particulière.
import numpy as np
def extract_surface():
verbs = list(filter(lambda morph: morph['pos'] == 'verbe', parse_text()))
return [verb['surface'] for verb in verbs]
print(extract_surface()[:100])
résultat
['Née', 'Tsuka', 'Shi', 'Pleurs', 'Shi', 'Est', 'début', 'Vous voyez', 'Ecoutez', 'Capture', 'Bouilli', 'Manger', 'Pensées', 'Chargement', 'Être', 'Ascenseur', 'Être', 'Shi', 'Ah', 'Calmez-vous', 'Vous voyez', 'Vous voyez', 'Pensées', 'Restant', 'Est', 'Sa', 'Ré', 'Shi', 'Rencontrer', 'Rencontrer', 'Shi', 'seulement', 'Si', 'Shi', 'Est', 'Coup', 'Ensemble', 'Faible', 'boire', 'Connaître', 'Asseyez-vous', 'Oh', 'Faire', 'Shi', 'début', 'Bouge toi', 'Bouge toi', 'Comprendre', 'Faire le tour', 'Devenir', 'De l'assistant', 'Pensées', 'Est', 'Saり', 'Shi', 'En dehors', 'Shi', 'Est', 'PenséesEn dehorsそ', 'Comprendre', 'Avec', 'Vous voyezる', 'je', 'Oh', 'Vous voyezえ', '隠Shi', 'Shiまっ', 'Différent', '明je', 'je', 'Être', '這jeEn dehorsShi', 'Vous voyezる', 'Désinvolte', 'Être', '這jeEn dehorsす', 'y a-t-il', 'Asseyez-vous', 'Shi', 'Pensées', 'Vous voyez', 'En dehors', 'Shi', 'Pleurs', 'À venir', 'くRéる', 'PenséesAvec', 'finalement', 'Vous voyez', 'À venir', 'Franchi', 'Prendre', 'Diminué', 'À venir', 'Pleurs', 'En dehors', 'y a-t-il', 'y a-t-il', 'Shi', 'Il est temps']
La valeur de retour peut également être créée comme list (map (lambda morph: morph ['surface'], verbs))
, mais l'utilisation de la notation d'inclusion comme ci-dessus est un code plus concis.
En outre, cela dépend de la façon dont vous interprétez l'énoncé du problème, mais si vous ne souhaitez pas autoriser les éléments en double dans la liste de retour, mettez la dernière ligne de la fonction.
return set([verb['surface'] for verb in verbs])
Il existe des méthodes telles que.
def extract_base():
verbs = list(filter(lambda morph: morph['pos'] == 'verbe', parse_text()))
return [verb['base'] for verb in verbs]
print(extract_base()[:100])
résultat
['Être né', 'Tsukuri', 'Faire', 'cri', 'Faire', 'Est', 'début', 'à voir', 'Ecoutez', 'Capturer', 'Ébullition', 'Manger', 'pense', 'Mettre', 'Être', 'ascenseur', 'Être', 'Faire', 'y a-t-il', '落ちTsukuri', 'à voir', 'à voir', 'pense', 'Rester', 'Est', 'Faire', 'Être', 'Faire', 'Rencontrer', 'rencontrer', 'Faire', 'Nomu', 'Devenir', 'Faire', 'Est', 'Coup', 'Faire', 'Faible', 'boire', 'connaître', 'Asseyez-vous', 'Oru', 'Faire', 'Faire', 'début', 'Bouge toi', 'Bouge toi', 'Comprendre', 'Faire le tour', 'Devenir', 'Être sauvé', 'pense', 'Est', 'Saru', 'Faire', 'Sortez', 'Faire', 'Est', 'Montez', 'Comprendre', 'Attacher', 'à voir', 'Est', 'Oru', 'apparaître', 'cacher', 'Finir', 'Faux', 'Pour être clair', 'Est', 'Être', 'Ramper', 'à voir', 'Jeter', 'Être', 'Ramper', 'y a-t-il', 'Asseyez-vous', 'Faire', 'Pense', 'à voir', 'Sortez', 'Faire', 'cri', 'viens', 'くÊtre', '考えAttacher', 'faire', 'à voir', 'viens', 'Traverser', 'Prendre', 'diminution', 'viens', 'cri', 'Sortez', 'y a-t-il', 'y a-t-il', 'Faire', 'Se raser']
Presque le même que 31.
def extract_sahens():
return list(filter(lambda morph: morph['pos1'] == 'Changer de connexion', parse_text()))
extract_sahens()[:20]
résultat
[{'surface': 'S'inscrire', 'base': 'S'inscrire', 'pos': 'nom', 'pos1': 'Changer de connexion'},
{'surface': 'Mémoire', 'base': 'Mémoire', 'pos': 'nom', 'pos1': 'Changer de connexion'},
{'surface': 'Parler', 'base': 'Parler', 'pos': 'nom', 'pos1': 'Changer de connexion'},
{'surface': 'Décoration', 'base': 'Décoration', 'pos': 'nom', 'pos1': 'Changer de connexion'},
{'surface': 'Saillie', 'base': 'Saillie', 'pos': 'nom', 'pos1': 'Changer de connexion'},
...
Presque le même que 31.
def extract_noun_phrases():
morphs = parse_text()
phrases = []
for i, morph in enumerate(morphs):
if morph['surface'] == 'de' and morphs[i - 1]['pos'] == 'nom' \
and morphs[i + 1]['pos'] == 'nom':
phrases.append(
morphs[i - 1]['surface'] + 'de' + morphs[i + 1]['surface'])
return phrases
print(extract_noun_phrases()[:100])
résultat
['Sa paume', 'Sur la paume', 'Visage de l'élève', 'Devrait faire face', 'Au milieu du visage', 'Dans le trou', 'Palmier de calligraphie', 'L'arrière de la paume', 'Quoi', 'Mère essentielle', 'Sur la paille', 'À Sasahara', 'Devant l'étang', 'Sur l'étang', 'Trou dans la clôture', 'Trois voisins', 'Passage du temps', 'À l'intérieur de la maison', 'Son élève', 'Humains autres que', 'Étudiant précédent', 'Ta chance', 'Trois d'entre vous', 'Des démangeaisons thoraciques', 'Gouvernante', 'Maître', 'Sous le nez', 'Mon visage', 'Ma maison', 'Mon mari', 'Trucs pour la maison', 'Les notres', 'Son étude', 'Sur le livre', 'Couleur de peau', 'Sur le livre', 'Son tous les soirs', 'Autre que', 'À côté de mon mari', 'Son genou', 'Sur le genou', 'Sur l'expérience', 'Sur le bol de riz', 'Sur le 炬 燵', 'D'ici', 'Lit accompagné', 'Entre eux', 'Un compagnon', 'Exemple de nerf', 'Maître sexuel', 'Chambre voisine', 'Égoïste', 'Pour moi', 'Entre les planches de la cuisine', 'Respect pour moi', 'Mukai blanc', 'Comme une balle', 'Maison là', 'Étudiant à domicile', 'Bassin arrière', 'L'amour parent-enfant', 'Plus de discussion', 'Tête de couteau', 'Parapluie de 鰡', 'Pour eux', 'Maison militaire', 'Maître du remplaçant', 'Maison du professeur', 'Temps de chat', 'Ma maison', 'Gouvernante', 'Plein d'anglais', 'Faible habitude d'estomac', 'Dans le rack arrière', 'Hira no Sect', 'Salaire mensuel', 'Pour le moment', 'Comme ci-dessous', 'Comme maintenant', 'Mémoire du maître', 'Son ami', 'Lunettes à monture dorée', 'Le visage du maître', 'L'imagination à l'intérieur', 'Traduit', 'Bailleur d'intérêt', 'Derrière le bord d'or', 'Derrière moi', 'Son ami', 'Mon cercle', 'Autour du visage', 'Le résultat de l'ajout', 'Caractéristiques du visage', 'Autres chats', 'Serviteur maladroit', 'Mon mari', 'Chat de la même production', 'Peau tachetée', 'Coloration du maître', 'Muscles relatifs']
En utilisant ʻenumerate () , vous pouvez gérer les informations dans lesquelles
morph se trouve dans
morphs` comme une variable, qui est un code soigné.
def extract_continuous_nouns():
morphs = parse_text()
continuous_nouns = []
for i, morph in enumerate(morphs):
if morph['pos'] == 'nom' and morphs[i + 1]['pos'] == 'nom':
continuous_noun = morph['surface'] + morphs[i + 1]['surface']
j = 1
while morphs[i + 1 + j]['pos'] == 'nom':
continuous_noun += morphs[i + 1 + j]['surface']
j += 1
continuous_nouns.append(continuous_noun)
return continuous_nouns
print(extract_continuous_nouns()[:100])
résultat
['Chez l'homme', 'Opportun', 'Puis chat', 'Puupuu et fumée', 'À l'intérieur du manoir', 'Trois cheveux', 'Autre que étudiant', 'Quarante-cinq poule', 'Gohen', 'L'autre jour', 'Mima', 'Votre cuisine', 'Maman de retour', 'Maison d'habitation', 'Étude d'une journée', 'Bosseur', 'Bosseur', 'Diligent', 'Quelques pages', 'Trois pages', 'Autre que mon mari', 'Autant que je suis', 'Maître du matin', 'Deux personnes', 'Dernier dur', '--Chat', 'Faiblesse neurogastrique', 'Faiblesse de l'estomac', 'Doigt', 'Terrible cul', 'Pause linguistique', 'Ma femme', 'Global', 'Direction musculaire', 'Shiro', 'À chaque fois', 'Shiro', 'Le bal de l'autre jour', 'Quatre', 'troisième jour', 'journée', 'Quatre', 'Shiro', 'Nos chats', 'Etc.', 'Chats', 'La vie de famille', 'La vie', 'Trois cheveux君', 'Mao', 'La possession', 'Entre nous', 'Entre la même famille', 'Coup d'œil', 'Ils humains', 'nous', 'je', 'Shiro', 'Trois cheveux君', 'Mao', 'Plein d'erreurs', 'M. Hoshi', 'Munemori', 'Munemori', 'Date du salaire mensuel', 'Peinture aquarelle', 'Chaque jour, chaque jour d'étude', 'Etude quotidienne', 'personne', 'Brossez vous-même', 'Sur des lunettes', 'Itari', 'Propriétaire Andrea del Salt', 'Rosée', 'Froid 鴉', 'Cette largeur', 'Peinture en direct', 'Le jour suivant', 'Bâton épicé', 'Maintenant je', 'Maintenant je', 'Produit Wave', 'Merveille', 'Chat aveugle', 'Secret dans mon coeur', 'Combien Andrea del Salt', 'Un autre grand', 'Pause', 'Mec stupide', 'Mec stupide', 'Bâton épicé', 'Mec stupideAppel', 'Appelez un bâtard', 'Appel', 'Hirai', 'Mec stupide', 'Tout le monde grandit', 'Où aller', 'Plusieurs fois', '10 tsubo']
import pandas as pd
def sort_by_freq():
words = [morph['base'] for morph in parse_text()]
return pd.Series(words).value_counts()
sort_by_freq()[:20]
résultat
9194
。 7486
6868
、 6772
Est 6420
...
Comme solution alternative, importez la bibliothèque standard collections
comme indiqué ci-dessous.
from collections import Counter
Vous pouvez également utiliser la méthode most_common ()
de l'objet Counter ()
(au lieu de value_counts ()
des pandas
).
return Counter(words).most_common()
résultat
[('de', 9194),
('。', 7486),
('main', 6868),
('、', 6772),
('Est', 6420),
...
La différence entre ces deux solutions est que value_counts ()
renvoie Series
, tandis que most_common ()
renvoie un tableau de tapples, donc lequel doit être utilisé pour un traitement ultérieur plus facile. N'est-ce pas bon?
import japanize_matplotlib
def draw_bar_graph():
sort_by_freq()[:10].plot.bar()
draw_bar_graph()
L'affichage du japonais prend du temps, mais il était facile d'utiliser la bibliothèque appelée japanize_matplotlib
présentée dans l'article ici.
Aussi, en ce qui concerne le contenu de la fonction, je voulais l'écrire brièvement, j'ai donc utilisé .plot.bar ()
pour l'objet Series
.
import matplotlib.pyplot as plt
Après avoir importé matplotlib
en tant que, cela fonctionne même si vous écrivez comme suit.
morph_freqs = sort_by_freq()[:10]
plt.bar(morph_freqs.index, morph_freqs)
import matplotlib.pyplot as plt
def draw_hist():
plt.xlabel('Fréquence d'apparition')
plt.ylabel('Nombre de types de mots')
plt.hist(sort_by_freq(), bins=200)
draw_hist()
Si vous voulez afficher le tout, ce sera un tel code, mais c'est un peu difficile à voir, il peut donc être plus réaliste de limiter la plage d'affichage comme suit.
def draw_hist_2():
plt.xlabel('Fréquence d'apparition')
plt.ylabel('Nombre de types de mots')
plt.title('Fréquence d'apparence 20 ou moins')
plt.hist(sort_by_freq(), bins=20, range=(1, 20))
draw_hist_2()
def draw_log_graph():
plt.xscale('log')
plt.yscale('log')
plt.xlabel('Classement de fréquence d'apparence')
plt.ylabel('Fréquence d'apparition')
plt.scatter(range(1, len(sort_by_freq()) + 1), sort_by_freq(), s=10)
draw_log_graph()
Lors de l'appel de la méthode «scatter», vous pouvez spécifier la taille des points avec l'option «s». La valeur par défaut est 20, mais c'était un peu gros, donc je l'ai réglé sur 10
.
MeCab est un logiciel open source, mais il était intéressant de savoir qu'il peut encore faire tant de choses.
D'un autre côté, j'ai également estimé que la précision de l'analyse n'était pas parfaite avec cela seul (par exemple, "Puuputo" renvoyé car le résultat de sortie à 35 n'est pas une nomenclature mais un complément). Afin de résoudre ce problème, je pense qu'il est nécessaire d'essayer différents dictionnaires et de les personnaliser par vous-même.
C'est tout pour ce chapitre, mais si vous faites une erreur, veuillez commenter.
Recommended Posts