文章の要約2020年12月26日 | |
はじめにsumy による文章の要約について。 環境
セットアップconda を使う。仮想環境を作る。 (base) $ conda create -n text python=3.7 sumy、janome、numpy、tinysegmenter をインストール。 (base) $ conda activate text (text) $ pip install sumy (text) $ pip install janome (text) $ conda install numpy (text) $ pip install tinysegmenter sumy による文章の要約文章の要約の方法として、抽出 (extract) と抽象 (abstract) 型とあるらしい。抽出型は、もとの文章から文を取り出して要約を構成する。文を選ぶだけなので比較的簡単なようだが、もとの文章に依存する。たとえば、アンケートの自由記述をこれで整理すると、様々な文体が混ざることになる。一方の抽象型は、ちゃんと要約するやつで、やはり難しいらしい。sumy は抽出型の要約モジュールである。 モジュールの準備。 import re from janome.tokenizer import Tokenizer as JanomeTokenizer from janome.charfilter import UnicodeNormalizeCharFilter, RegexReplaceCharFilter from janome.tokenfilter import POSKeepFilter, ExtractAttributeFilter from janome.analyzer import Analyzer from sumy.parsers.plaintext import PlaintextParser from sumy.nlp.tokenizers import Tokenizer from sumy.summarizers.lex_rank import LexRankSummarizer from sumy.utils import get_stop_words 要約の処理は以下のようになる。 def summrize(filename, sentences_count, encoding="utf-8"): contents = [] with open(filename, encoding=encoding) as f: for line in f: line = line.strip().strip("\r\n") if line != "" and line[-1] == "。": contents.append(line) contents = "".join(contents) #print("contents =") #print(contents) #print() contents = contents.replace("\n", "") contents = contents.replace("\"", "") text = re.findall("[^。]+。?", contents) #print("text =") #print(text) #print() text_len = [] for t in text: text_len.append(len(t)) print("average length = ", sum(text_len)/len(text_len)) tokenizer = JanomeTokenizer("japanese") char_filters = [UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r"[(\)「」、。]", " ")] token_filters = [POSKeepFilter(["名詞", "形容詞", "副詞", "動詞"]), ExtractAttributeFilter("base_form")] analyzer = Analyzer( char_filters=char_filters, tokenizer=tokenizer, token_filters=token_filters ) corpus = [" ".join(analyzer.analyze(sentence)) + "。" for sentence in text] #print("corpus =") #print(corpus) #print(len(corpus)) #print() parser = PlaintextParser.from_string("".join(corpus), Tokenizer("japanese")) summarizer = LexRankSummarizer() summarizer.stop_words = get_stop_words("japanese") summary = summarizer(document=parser.document, sentences_count=sentences_count) summary_text = "".join([text[corpus.index(sentence.__str__())] for sentence in summary]) print("summary =") print(summary_text) print("length =", len(summary_text)) ファイル名を与えたら、それを読み込んで要約を表示する。やりかたは色々ありそうだが、ここでは余計なタイトルなどを取り除くために "。" で終わる文だけを取り出すようにしている。LexRank という手法を用いている。 サンプル 1自分が書いた長めの記事 (OpenFOAM 情報) を要約してみる。 とりあえず 1 文だけ取り出してみる。 summrize("sample.txt", 1) 結果 average length = 47.03404255319149 summary = OpenFOAM は Linux 用に開発されているので、Linux マシンを用意するのが素直である。 length = 51 十分に内容を含みそうで、読んで苦痛でない長さとして 300 文字を目安としてみる。1 文が 50 文字程度なので、6 文取り出してみる。 summrize("sample.txt", 6) 結果 average length = 47.03404255319149 summary = Linux ユーザーで、CFD コードを自分で書くような人ならよいかも。適当な機能を備えたソルバーが標準ソルバーの中にない場合は、自分でソルバーを開発する必要がある。OpenFOAM は Linux 用に開発されているので、Linux マシンを用意するのが素直である。本来は Linux 用の OpenFOAM だが、Windows 版もあるにはある。ソルバーを使うだけなら必要ないが、ソースコードを理解したいのなら、それ専用のツールを使ったほうがよい。OpenFOAM Foundation 版 OpenFOAM と OpenCFD (ESI) 版 OpenFOAM (OpenFOAM+) の違いは、OpenFOAM v3.0+ ?? にあるように、RHEL と Fedora の違いのようなものとのことであるが、よくわからない。 length = 367 なんでこんな結果なのかはわからないが、いい線はいっている気がする。 サンプル 2比較的短い作品だが、中島敦の 名人伝 を要約してみる。 summrize("sample2.txt", 1) 結果 average length = 42.82142857142857 summary = その四十年の間、彼は絶えて射を口にすることが無かった。 length = 27 300 文字目安で 8 文選んでみる。 summrize("sample2.txt", 8) 結果 average length = 42.82142857142857 summary = 毎日毎日彼は窓にぶら下った虱を見詰める。ある日ふと気が付くと、窓の虱が馬のような大きさに見えていた。傍で見ていた師の飛衛も思わず「善し!」と言った。弓? と老人は笑う。弓矢の要いる中はまだ射之射じゃ。九年たって山を降りて来た時、人々は紀昌の顔付の変ったのに驚いた。これでこそ初めて天下の名人だ。その四十年の間、彼は絶えて射を口にすることが無かった。 length = 174 なんかこんな話だった気もするが、ちょっと説明不足な感じである。 意外と短かったので、300 文字になるように文を増やしてみる。 summrize("sample2.txt", 13) 結果 average length = 42.82142857142857 summary = 趙ちょうの邯鄲かんたんの都に住む紀昌きしょうという男が、天下第一の弓の名人になろうと志を立てた。それを聞いて飛衛がいう。毎日毎日彼は窓にぶら下った虱を見詰める。初め、もちろんそれは一匹の虱に過ぎない。ある日ふと気が付くと、窓の虱が馬のような大きさに見えていた。傍で見ていた師の飛衛も思わず「善し!」と言った。※(「にんべん+爾」、第3水準1-14-45)の師と頼むべきは、今は甘蠅師の外にあるまいと。弓? と老人は笑う。弓矢の要いる中はまだ射之射じゃ。不射之射には、烏漆うしつの弓も粛慎しゅくしんの矢もいらぬ。九年たって山を降りて来た時、人々は紀昌の顔付の変ったのに驚いた。これでこそ初めて天下の名人だ。その四十年の間、彼は絶えて射を口にすることが無かった。 length = 329 「にんべん+爾」となっているのは、「なんじ」である。よくまとまっているような気もしなくもない。 | |
PENGUINITIS |