2017-05-31 20 views
0

オランダのテキストからsubject-verb-objectトリプルを抽出する必要があります。このテキストは、オランダのNLPツールFrogによって解析され、トークン化され、解析され、タグ付けされ、lemmatizedされます。 Frogは、FoLiA XMLまたはタブ区切りの列形式の出力をトークンごとに1行生成します。 XMLファイルに関するいくつかの問題のために、私は列形式で作業することを選択しました。この例は1つの文を表しています。 enter image description here今私は文ごとにSVOトリプルを抽出する必要があるので、依存関係である最後の列が必要です。ですから、私はROOT要素と、ROOTに属するsuとobj1要素を取得する必要があります。残念ながら、例文にはobj1がありません。それは持っているふりをしましょう。私の考えは、最初に文ごとにリストを入れ子にしたリストを作成することでした。前処理されたテキストからSVOトリプルを抽出する

import csv 
    with open('romanfragment_frogged.tsv','r') as f: 
     reader = csv.reader(f,delimiter='\t') 
     tokens = [] 
     sentences = [] 
     list_of_sents = [] 
     for line in reader: 
      tokens.append(line) 
      #print(tokens) 
      for token in tokens: 
       if token == '1': 
        previous_sentence = list_of_sents 
        sentences.append(previous_sentence) 
     list_of_sents = [] 
     list_of_sents.append(tokens) 
     print(list_of_sents) 

「トークン」を印刷すると、すべてのトークンを含む1つのリストが得られます。それは正しいですが、私はまだ文ごとに1つのリスト(トークンのリスト)を入れ子にしたリストを作成しようとしています。 誰かがこの問題を手伝ってくれますか?

(PSは第二の問題は、私はネストされたリストを得れば継続する方法を、私はよく分からないということです)

+1

私はまず、入力形式について混乱があると思います。リンク先のツールのウェブサイトには、出力がXMLであることが示されています。しかし、イメージと '" \ t "'で分割しようとすると、それがTSV(タブで区切られたプレーンテキスト)ファイルであることが示唆されます。それでも、Word文書であると主張しています。おそらく古いバイナリの ".doc"バージョンで、これはすべてのオプションの中で最悪のものです。これを整理して質問を更新してください。 – lenz

+0

@lenzウェブサイトには2つの出力オプションがあると言われているので、FrogはFoLiA XML、タブ区切りのカラムフォーマット出力、トークンごとに1行を生成します。 XMLファイルに関するいくつかの問題のために、私は列形式で作業することを選択しました。しかし、あなたが言ったように.docとして保存しました。.txtファイルとして保存する方がいいですか? – Bambi

+0

私はあなたが実際にはWord文書として保存していないと思いますが、ファイル名を ".doc"で終わらせて保存しました。条約は ".tsv"または時には ".csv"を使用することです。 – lenz

答えて

1

たぶん、このような何かが、仕事ができる:

def iter_sentences(fn): 
    with open(fn, 'r') as f: 
     reader = csv.reader(f,delimiter='\t') 
     sentence = [] 
     for row in reader: 
      if not row: 
       # Ignore blank lines. 
       continue 
      if row[0] == '1' and sentence: 
       # A new sentence started. 
       yield sentence 
       sentence = [] 
      sentence.append(row) 
     # Last sentence. 
     if sentence: 
      yield sentence 

def iter_triples(fn): 
    for sentence in iter_sentences(fn): 
     # Get all subjects and objects. 
     subjects = [tok for tok in sentence if tok[-1] == 'su'] 
     objects = [tok for tok in sentence if tok[-1] == 'obj1'] 
     # Now try to map them: find pairs with a head in the same position. 
     for obj in objects: 
      for subj in subjects: 
       # row[-2] is the position of the head. 
       if subj[-2] == obj[-2]: 
        # Matching subj-obj pair found. 
        # Now get the verb (the head of both subj and obj). 
        # Its position is given in the second-to-last column. 
        position = int(subj[-2]) 
        # Subtract 1, as the positions start counting at 1. 
        verb = sentence[position-1] 
        yield subj, verb, obj 

for subj, verb, obj in iter_triples('romanfragment_frogged.tsv'): 
    # Only print the surface forms. 
    print(subj[1], verb[1], obj[1]) 

クイック説明: iter_sentences文章を繰り返します。 各文はネストされたリストです。 トークンのリストであり、各トークンはリスト自体です(行番号、表面形式、補題、POS、依存関係などを含みます)。 iter_triples関数は、 のトリプルを繰り返し処理します。 これらのトリプルの各要素は、トークン(つまり、リスト)を表します。

コードの最後の3行は、iter_triples関数の使用例の単なる例です。 それぞれのトリプルからどれだけの情報が必要なのか分かりません...

+0

ありがとう!しかし、このコードの ''行の読者: 行[0] == '1'と文章 'が私に索引エラーを与えます:リスト索引が範囲外です – Bambi

+1

おそらく空白行。そのチェックの前に 'if not row:continue'を追加して、空白行をスキップします。 – lenz

+0

実際、問題は解決しました。あなたのコードを編集しました。今私はまだ2つの小さな質問があります。 1.私は、この行がどのように動詞=文[int(subj [-2]) - 1]を使っているか完全に理解していません。 2.私は別のテキストで作業するためにこれが必要です。 SVOトリプルは、機械学習のための機能として役立つ。 iter_triplesからの出力として、文ごとのトリプルではなく、トークン名とリレーションのみのネストされたリストを得ることは可能ですか?だから、要素2と10はリストごとにトークンごとにありますか? – Bambi

関連する問題