"""
## 46.Extraction d'informations sur le cadre de la casse des verbes[Permalink](https://nlp100.github.io/ja/ch05.html#46-Extractiond'informationssurlecadredelacassedesverbes)
Modifiez 45 programmes et affichez les termes (les clauses liées aux prédicats eux-mêmes) au format délimité par des tabulations en suivant les prédicats et les modèles de cas. En plus des 45 spécifications, répondez aux spécifications suivantes.
-Le terme est une chaîne de mots de la clause liée au prédicat (il n'est pas nécessaire de supprimer le verbe de fin)
-S'il existe plusieurs clauses liées au prédicat, disposez-les dans le même standard et dans le même ordre que les mots auxiliaires, séparés par des espaces.
Une phrase d'exemple disant "J'ai vu un être humain pour la première fois ici".txt.Prenons la huitième phrase de cabocha). Cette phrase contient deux verbes, «commencer» et «voir», et la phrase liée à «commencer» est analysée comme «ici», et la phrase liée à «voir» est analysée comme «je suis» et «chose». Devrait produire la sortie suivante.
Commencez ici
Regarde ce que je vois
"""
from collections import defaultdict
from typing import List
def read_file(fpath: str) -> List[List[str]]:
"""Get clear format of parsed sentences.
Args:
fpath (str): File path.
Returns:
List[List[str]]: List of sentences, and each sentence contains a word list.
e.g. result[1]:
['* 0 2D 0/0 -0.764522',
'\u3000\symbole t,Vide,*,*,*,*,\u3000,\u3000,\u3000',
'* 1 2D 0/1 -0.764522',
'je\t substantif,Synonyme,Général,*,*,*,je,Wagahai,Wagahai',
'Est\t assistant,Assistance,*,*,*,*,Est,C,sensationnel',
'* 2 -1D 0/2 0.000000',
'Chat\t substantif,Général,*,*,*,*,Chat,chat,chat',
'alors\t verbe auxiliaire,*,*,*,Spécial,Type continu,Est,De,De',
'y a-t-il\t verbe auxiliaire,*,*,*,Cinq étapes, La ligne Al,Forme basique,y a-t-il,Al,Al',
'。\symbole t,Phrase,*,*,*,*,。,。,。']
"""
with open(fpath, mode="rt", encoding="utf-8") as f:
sentences = f.read().split("EOS\n")
return [sent.strip().split("\n") for sent in sentences if sent.strip() != ""]
class Morph:
"""Morph information for each token.
Args:
data (dict): A dictionary contains necessary information.
Attributes:
surface (str):Surface
base (str):Base
pos (str):Partie (base)
pos1 (str):Sous-classification des pièces détachées 1 (pos1)
"""
def __init__(self, data):
self.surface = data["surface"]
self.base = data["base"]
self.pos = data["pos"]
self.pos1 = data["pos1"]
def __repr__(self):
return f"Morph({self.surface})"
def __str__(self):
return "surface[{}]\tbase[{}]\tpos[{}]\tpos1[{}]".format(
self.surface, self.base, self.pos, self.pos1
)
class Chunk:
"""Containing information for Clause/phrase.
Args:
data (dict): A dictionary contains necessary information.
Attributes:
chunk_id (str): The number of clause chunk (Numéro de phrase).
morphs List[Morph]: Morph (morphème) list.
dst (str): The index of dependency target (Numéro d'index de la clause de contact).
srcs (List[str]): The index list of dependency source. (Numéro d'index de la clause d'origine).
"""
def __init__(self, chunk_id, dst):
self.id = chunk_id
self.morphs = []
self.dst = dst
self.srcs = []
def __repr__(self):
return "Chunk( id: {}, dst: {}, srcs: {}, morphs: {} )".format(
self.id, self.dst, self.srcs, self.morphs
)
def get_surface(self) -> str:
"""Concatenate morph surfaces in a chink.
Args:
chunk (Chunk): e.g. Chunk( id: 0, dst: 5, srcs: [], morphs: [Morph(je), Morph(Est)]
Return:
e.g. 'je suis'
"""
morphs = self.morphs
res = ""
for morph in morphs:
if morph.pos != "symbole":
res += morph.surface
return res
def validate_pos(self, pos: str) -> bool:
"""Return Ture if 'nom' or 'verbe' in chunk's morphs. Otherwise, return False."""
morphs = self.morphs
return any([morph.pos == pos for morph in morphs])
def convert_sent_to_chunks(sent: List[str]) -> List[Morph]:
"""Extract word and convert to morph.
Args:
sent (List[str]): A sentence contains a word list.
e.g. sent:
['* 0 1D 0/1 0.000000',
'je\t substantif,Synonyme,Général,*,*,*,je,Wagahai,Wagahai',
'Est\t assistant,Assistance,*,*,*,*,Est,C,sensationnel',
'* 1 -1D 0/2 0.000000',
'Chat\t substantif,Général,*,*,*,*,Chat,chat,chat',
'alors\t verbe auxiliaire,*,*,*,Spécial,Type continu,Est,De,De',
'y a-t-il\t verbe auxiliaire,*,*,*,Cinq étapes, La ligne Al,Forme basique,y a-t-il,Al,Al',
'。\symbole t,Phrase,*,*,*,*,。,。,。']
Parsing format:
e.g. "* 0 1D 0/1 0.000000"
|colonne|sens|
| :----: | :----------------------------------------------------------- |
| 1 |La première colonne est`*`.. Indique qu'il s'agit d'un résultat d'analyse des dépendances.|
| 2 |Numéro de phrase (entier à partir de 0)|
| 3 |Numéro de contact +`D` |
| 4 |Adresse principale/Position du mot de fonction et nombre illimité de colonnes d'identité|
| 5 |Score d'engagement. En général, plus la valeur est élevée, plus il est facile de s'engager.|
Returns:
List[Chunk]: List of chunks.
"""
chunks = []
chunk = None
srcs = defaultdict(list)
for i, word in enumerate(sent):
if word[0] == "*":
# Add chunk to chunks
if chunk is not None:
chunks.append(chunk)
# eNw Chunk beggin
chunk_id = word.split(" ")[1]
dst = word.split(" ")[2].rstrip("D")
chunk = Chunk(chunk_id, dst)
srcs[dst].append(chunk_id) # Add target->source to mapping list
else: # Add Morch to chunk.morphs
features = word.split(",")
dic = {
"surface": features[0].split("\t")[0],
"base": features[6],
"pos": features[0].split("\t")[1],
"pos1": features[1],
}
chunk.morphs.append(Morph(dic))
if i == len(sent) - 1: # Add the last chunk
chunks.append(chunk)
# Add srcs to each chunk
for chunk in chunks:
chunk.srcs = list(srcs[chunk.id])
return chunks
def get_predicate_frame(chunks: List[Chunk]) -> List[dict]:
"""Get edges from sentence chunks.
Terms:
-prédicat(predicate)
-Article(argument)
-Cas(case)
Args:
chunks (List[Chunk]): A sentence contains many chunks.
e.g. [Chunk( id: 0, dst: 5, srcs: [], morphs: [Morph(je), Morph(Est)] ),
Chunk( id: 1, dst: 2, srcs: [], morphs: [Morph(ici), Morph(alors)] ),
Chunk( id: 2, dst: 3, srcs: ['1'], morphs: [Morph(début), Morph(main)] ),
Chunk( id: 3, dst: 4, srcs: ['2'], morphs: [Morph(Humain), Morph(Cette)] ),
Chunk( id: 4, dst: 5, srcs: ['3'], morphs: [Morph(chose), Morph(À)] ),
Chunk( id: 5, dst: -1, srcs: ['0', '4'], morphs: [Morph(Vous voyez), Morph(Ta), Morph(。)] )]
Returns:
List[dict]: Predicate frame.
e.g. [{'pred': 'début', 'case': ['alors'], 'arg': ['ここalors']},
{'pred': 'à voir', 'case': ['Est', 'À'], 'arg': ['吾輩Est', 'ものÀ']}]
"""
patterns = []
for chunk in chunks:
# Skip if not valid
if len(chunk.srcs) == 0 or all([morph.pos != "verbe" for morph in chunk.morphs]):
continue
# Initialize
pred_frame = {"pred": None, "case": [], "arg": []}
# Get predicate
for morph in chunk.morphs:
if morph.pos == "verbe":
pred_frame["pred"] = morph.base
break
# Get case
for src in chunk.srcs:
src_chunk = chunks[int(src)]
for morph in src_chunk.morphs:
if morph.pos == "Particule":
pred_frame["case"].append(morph.base)
pred_frame["arg"].append(src_chunk.get_surface())
# Add to patterns
patterns.append(pred_frame)
return patterns
def write_to_file(sents, path):
"""Write patterns to file.
Args:
pattern_sents ([type]): predicate-case patterns.
e.g. [[{'pred': 'Née', 'case': ['alors'], 'arg': ['どこalors']},
{'pred': 'Tsukuri', 'case': ['Ou', 'Mais'], 'arg': ['生れたOu', '見当Mais']}],
[{'pred': 'cri', 'case': ['alors'], 'arg': ['所alors']},
{'pred': 'Faire', 'case': ['main', 'Seulement', 'Est'], 'arg': ['泣いmain', 'いた事SeulementEst', 'いた事SeulementEst']}]]
"""
# convert_frame_to_text
lines = []
for sent in sents:
for frame in sent: # pattern: {'pred': 'cri', 'case': ['alors'], 'arg': ['所alors']}
case_text = " ".join(frame["case"])
arg_text = " ".join(frame["arg"])
lines.append((frame["pred"], case_text, arg_text))
# write_to_file
with open(path, "w") as f:
for line in lines:
f.write(f"{line[0]}\t{line[1]}\t{line[2]}\n")
fpath = "neko.txt.cabocha"
sentences = read_file(fpath)
sentences = [convert_sent_to_chunks(sent) for sent in sentences] # ans41
# ans46
pattern_sents = [get_predicate_frame(sent) for sent in sentences]
pattern_sents = list(filter(lambda x: len(x) != 0, pattern_sents))
write_to_file(pattern_sents, "predicate_frame.txt")
# "predicate_frame.txt":
#Où naître
#Je ne sais pas s'il est né
#Où pleurer
#La seule chose que je pleurais était la seule chose que je pleurais
#Commencez ici
#Regarde ce que je vois
#Écoutez plus tard
#Attrapez-nous
Recommended Posts