def create_language_model(doc_ids: List[str, ], n: int = 3) -> MLE: sentences = [] # doc_id を 1つず処理していく for doc_id in doc_ids: # doc_id に紐づく単語を取得 all_tokens = datastore.get_annotation(doc_id, "token") # doc_id に紐づく文を取得 # find_xs_in_y を使用し, 文に含まれている単語のみを抽出し, sentences に格納 for sentence in datastore.get_annotation(doc_id, "sentence"): tokens = find_xs_in_y(all_tokens, sentence) sentences.append(["__BOS__"] + [token['lemma'] for token in tokens] + ["__EOS__"]) # ボキャブラリを作成 vocab = Vocabulary([word for sentence in sentences for word in sentence]) # n-gram を利用して, 1組 n 個の単語の組み合わせ作成 ngram = [ngrams(sentence, n) for sentence in sentences] # MLE というモデルを用いて, 言語モデルを作成 lm = MLE(order=n, vocabulary=vocab) lm.fit(ngram) return lm
def main(): datastore.connect() sentences = [] # :TODO 書籍と異なる方法で記載. 後ほど変更する # **** ここから **** for doc_id, in datastore.get_all_ids(limit=20): for sentence in datastore.get_annotation(doc_id, "sentence"): tokens = find_xs_in_y( datastore.get_annotation(doc_id, "token"), sentence ) sentences.append((doc_id, sentence, tokens)) # **** ここまで **** rule = ruleclassifier.get_rule() # 分類 feature = ruleclassifier.convert_into_feature_using_rules(sentences, rule) predict = ruleclassifier.classify(feature, rule) for predicted, (doc_id, sentence, tokens) in zip(predict, sentences): if predicted == 1: text = datastore.get(doc_id, ["content"])["content"] print(predicted, text[sentence["begin"]: sentence["end"]]) datastore.close() return
def find_child( parent, chunks_in_sentence, tokens_in_sentence, text, all_chunks, child_cond ) -> Tuple: for child in chunks_in_sentence: _, link = child["link"] if (link == -1 or all_chunks[link] != parent): continue child_tokens = find_xs_in_y(tokens_in_sentence, child) if text[child["begin"]: child["end"]] in child_cond.get("text", []): return child, child_tokens if (child_tokens[-1]["POS"] in child_cond.get("pos1", []) and child_tokens[-1]["lemma"] in child_cond.get("lemma1", []) and child_tokens[-2]["POS"] not in child_cond.get("pos2_ng", [])): return child, child_tokens return None, None
def extract_relation(doc_id: str): # 文章, 文, 文節, 単語を取得 text = datastore.get(doc_id, fl=["content"])["content"] all_chunks = datastore.get_annotation(doc_id, "chunk") all_tokens = datastore.get_annotation(doc_id, "token") annotation_id = 0 # 1文ずつ loop で処理を行う for sentence in datastore.get_annotation(doc_id, "sentence"): # 文中に出現する文節, 単語を取得 chunks = find_xs_in_y(all_chunks, sentence) tokens = find_xs_in_y(all_tokens, sentence) # 1文節ずつ loop で処理を行う for chunk in chunks: # 文節中に出現する単語を取得 chunk_tokens = find_xs_in_y(tokens, chunk) # 単語の原型が動詞の「与える」であるものを取得 # 該当するものがない場合は, 次の文節の処理へ check = [ chunk_token["lemma"] == "与える" for chunk_token in chunk_tokens ] if not any(check): continue # 「与える」の文節を「影響を」の文節が修飾しているか否かを探索する # 該当するものがない場合は, 次の文節の処理へ affect, affect_token = find_child( parent=chunk, chunks_in_sentence=chunks, tokens_in_sentence=tokens, text=text, all_chunks=all_chunks, child_cond={"text": ["影響を"]} ) if affect is None: continue # 影響元を取得 # 該当するものがない場合は, 次の文節の処理へ cause, cause_token = find_child( parent=chunk, chunks_in_sentence=chunks, tokens_in_sentence=tokens, text=text, all_chunks=all_chunks, child_cond={ "pos1": ["助詞"], "lemma1": ["は", "も", "が"], "pos2_ng": ["助詞"] } ) if cause is None: continue # 影響先を取得 # 該当するものがない場合は, 次の文節の処理へ effect, effect_token = find_child( parent=chunk, chunks_in_sentence=chunks, tokens_in_sentence=tokens, text=text, all_chunks=all_chunks, child_cond={ "pos1": ["助詞"], "lemma1": ["に"], "pos2_ng": ["助詞"] } ) if effect is None: continue # 影響元, 影響先を relation 変数に格納 # 該当する文とともに yield で呼び出し元に値を返す relation = { "cause": { "begin": cause["begin"], "end": cause["end"], "link": ("effect", annotation_id) }, "effect": { "begin": effect["begin"], "end": effect["end"] } } annotation_id += 1 yield sentence, relation return
def main(): # SQLite に接続 datastore.connect() # dic_id を1つずつ取得し, その doc_id 内の文章ごとに含まれる単語の原形を sentences に格納 sentences = [] for doc_id in datastore.get_all_ids(limit=-1): all_tokens = datastore.get_annotation(doc_id, "token") for sentence in datastore.get_annotation(doc_id, "sentence"): tokens = find_xs_in_y(all_tokens, sentence) sentences.append( [token["lemma"] for token in tokens if token.get("NE") == "O"]) # 分析に使用する記事が少ないため, 20文を 1つの文書として扱うように sentence を結合 n_sent = 20 docs = [ list(itertools.chain.from_iterable(sentences[i:i + n_sent])) for i in range(0, len(sentences), n_sent) ] # LDA の計算に使用する単語を選定 # - 出現頻度が 2つ未満の文書の場合, その単語は計算に使用しない( no_below=2 ) # - 出現頻度が 3割以上の文書の場合, その単語は計算に使用しない( no_above=0.3 ) dictionary = Dictionary(docs) dictionary.filter_extremes(no_below=2, no_above=0.3) # 単語の集まりを doc2bow method を用いて, 所定のデータ型に変換 corpus = [dictionary.doc2bow(doc) for doc in docs] # LDA モデルを作成 lda = LdaModel(corpus, num_topics=10, id2word=dictionary, passes=10) # 主題の確認 # Topic の一覧を出力 # Topic の一覧と合わせて, その Topic の中で確率値の大きい単語上位 10個を出力 for topic in lda.show_topics(num_topics=-1, num_words=10): print(f"Topic id: {topic[0]} Word: {topic[1]}") # 記事の主題分布の推定 # doc_id ごとに確率値の大きい Topic を出力 for doc_id in datastore.get_all_ids(limit=-1): meta_info = json.loads( datastore.get(doc_id=doc_id, fl=["meta_info"])["meta_info"]) title = meta_info["title"] print(title) doc = [ token["lemma"] for token in datastore.get_annotation(doc_id, "token") if token.get("NE") == "O" ] topics = sorted(lda.get_document_topics(dictionary.doc2bow(doc)), key=lambda x: x[1], reverse=True) for topic in topics: print(f" Topic id: {topic[0]} Prob: {topic[1]}") datastore.close() return