====== HanDicの出力結果をPythonで利用する:TF-IDFの計算 ====== ===== はじめに ===== [[https://ja.osdn.net/projects/handic/|HanDic]]を使ったMeCabの出力結果をPythonで利用する例として,文書中に現れる単語の重要度を示す,TF-IDFの計算を行ってみます.今回は中期朝鮮語の資料である『석보상절(釈譜詳節)』(1447年刊)を,中期朝鮮語のMeCab用解析辞書「[[https://ja.osdn.net/pkg/handic/mkhandic-mecab|MkHanDic]]」で解析した結果を使います.解析結果については,MeCabの出力そのままではなく,テキストファイルに出力した結果を手作業で修正したものを利用します.辞書構築の際の学習用データとして用いているものです. 上記資料の原刊本のうち,巻6,9,13,19,23,24の本文のみ解析して修正した巻次ごとのテキストファイルが,スクリプトと同じディレクトリ下の''sekbo_texts''というディレクトリにあるものとします.巻6のファイル(ファイル名は''c_sekbo_06_main_v03.txt''とする)の冒頭は以下の通りとなっています: 世尊 Noun,固有名詞,人名,*,*,世尊,世尊,世尊,*,NNP 'i Ending,助詞,主格,*,*,이,이,*,*,JKS 象頭山 Noun,固有名詞,地名,*,*,象頭山,象頭山,象頭山,*,NNP 'ai Ending,助詞,処格,*,*,애,애,*,*,JKB ga Verb,自立,*,語基2,*,가다01,가,*,*,VV sia Prefinal,尊敬,*,語基3,*,시,샤,*,*,EP 龍 Noun,普通,*,*,*,龍,龍,龍,*,NNG goa Ending,助詞,接続助詞,*,*,과,과,*,*,JC 鬼神 Noun,普通,*,*,*,鬼神,鬼神,鬼神,*,NNG goa Ending,助詞,接続助詞,*,*,과,과,*,*,JC 'uih@'ia Verb,自立,*,語基3,*,위다,위야,*,*,VV 說法 Noun,普通,動作,*,*,說法,說法,說法,*,NNG h@ Suffix,動詞派生,*,語基1,*,다80,,*,*,XSV de Prefinal,回想,*,語基2,*,더,더,*,*,EP si Prefinal,尊敬,*,語基1,*,시,시,*,*,EP da Ending,語尾,終止形,*,1接続,다,다,*,*,EF . Symbol,ピリオド,*,*,*,.,.,*,*,SF EOS 中期朝鮮語に固有の文字は,表示されていないかと思います.表層形(各行の冒頭)にアルファベット転写を用いていますが,この表記については[[https://ja.osdn.net/projects/handic/wiki/MkHanDicAlphabet|mecab-k2alphaのアルファベット転写表]]を参照してください. ===== やること ===== 上述の『釈譜詳節』のそれぞれの巻次について,名詞類(普通名詞,固有名詞,語根)のTF-IDFを計算します.その上で,各巻次のTF-IDF上位10語を列挙します.基本的には[[korean:mecab:python_tfidf|]]のやり方と同じです. ===== 準備 ===== 今回はMeCabを呼び出したりしないので,必要最低限のモジュールだけ呼び出します. import glob, os from sklearn.feature_extraction.text import TfidfVectorizer import pandas as pd ===== 読み込んだファイルの処理 ===== 読み込んだファイルについて処理する関数を定義します.出力結果は各行「表層形[タブ文字]コンマ区切りの素性」という形式なので,まず''split('\t')''で表層形と素性とを区切った後,素性に当たる部分を''split(',')''で個別の素性に分け,配列に入れます. 素性のうち「世宗タグ」がNNG(普通名詞),NNP(固有名詞),XR(語根)に該当するものを抽出し,スペース区切りの配列にします. def extract(file): words = [] with open(file, mode='rt', encoding='utf-8') as fi: for line in fi: mecab_features = [] line = line.rstrip('\n') if line == 'EOS': continue mecab_features = line.split('\t')[1].split(',') if mecab_features[9] in ['NNG', 'NNP', 'XR']: words.append(mecab_features[5]) text_result = ' '.join(words) return text_result こちらも[[korean:mecab:python_tfidf|]]と同じく,普通名詞と固有名詞,語根に限定しました. ===== ファイルの読み込みとその処理 ===== ディレクトリ''sekbo_texts''内にあるファイルをそれぞれ読み込み,前節の処理を行います. # sekbo_texts フォルダ内のテキスト読み込み all_files = glob.glob("sekbo_texts/*.txt") docs = [] titles = [] for i in all_files: text = extract(i) titles.append(os.path.split(i)[1]) docs.append(text) それぞれのファイル名を取り出して,別途配列に入れます. ===== TF-IDFの計算と上位10語の表示 ===== ここから後は,[[korean:mecab:python_tfidf|]]と同じ手順です.scikit-learnでTF-IDFを計算します. [2021/11\09 追記] ''TfidfVectorizer()''の''token_pattern''を書いておかないと,古ハングルが無視されて計算されてしまいます.Unicodeの私用領域(PUA)に含まれる古ハングルを,文字コードで指定することにしました(参照:[[https://ja.wikipedia.org/wiki/%E5%8F%A4%E3%83%8F%E3%83%B3%E3%82%B0%E3%83%AB|古ハングル(Wikipedia)]]).これで合っているか分かりませんが,ともかく古ハングルが含まれた項目も計算に入るようになります. # モデルを作成 vectorizer = TfidfVectorizer(smooth_idf=False, token_pattern='(?u)[\\w\\ue0bc-\\uefff\\uf100-\\uf66e\\uf784-\\uf800\\uf806-\\uf864\\uf86a-\\uf8f7]+') values = vectorizer.fit_transform(docs).toarray() feature_names = vectorizer.get_feature_names_out() df = pd.DataFrame(values, columns = feature_names, index=titles) 今回はファイル数が少ないので,全てのファイルについてTF-IDFで上位の10語を表示するようにしました. for num in range(len(df)): temp_df = [] temp_df = df[num:num+1].T temp_df = temp_df.sort_values(by=titles[num], ascending=False) print(temp_df.head(10)) 結果は以下の通り([2021/11/09 追記] ''token_pattern''を変えたことで,計算結果に違いが出ましたので変更しておきます.傾向にあまり変わりはありません): c_sekbo_06_main_v03.txt 須達 0.688172 舍利弗 0.260852 精舍 0.233487 부텨 0.233296 耶輸 0.159754 太子 0.149058 六師 0.147465 사 0.145260 目連 0.122888 舍衛國 0.120090 c_sekbo_09_main_v03.txt 有情 0.475275 藥師瑠璃光如來 0.398618 橫死 0.245303 大願 0.199309 일훔 0.197701 來世 0.183978 菩提 0.183978 惡趣 0.137983 病 0.123366 文殊師利 0.120877 c_sekbo_13_main_v03.txt 부텨 0.454087 舍利弗 0.321053 佛道 0.236824 菩薩 0.224191 諸佛 0.219559 法 0.189619 사 0.179639 衆生 0.149699 일훔 0.129739 佛乘 0.111446 c_sekbo_19_main_v03.txt 소리 0.354649 사 0.231608 香 0.213933 부텨 0.209894 經 0.172931 菩薩 0.171147 隨喜 0.161648 法華經 0.161648 得大勢 0.161648 得 0.159230 c_sekbo_23_main_v03.txt 부텨 0.322129 舍利 0.289234 棺 0.231640 供養 0.219634 拘尸城 0.204388 金棺 0.204388 大衆 0.178889 如來 0.165945 사 0.165945 一切 0.161065 c_sekbo_24_main_v03.txt 王 0.605065 尊者 0.305280 阿育王 0.280858 부텨 0.209953 사 0.139969 夫人 0.137691 善容 0.134323 놈 0.134323 太子 0.133305 塔 0.129287 須達と舎利仏のストーリーが中心的な巻6,『薬師瑠璃光如来本願功徳経』の翻訳である巻9,『法華経』の翻訳である巻13,19,釈迦入滅後,舎利の扱いを論じる巻23,阿育王の話が出てくる巻24と,それぞれの特徴が示されています. ===== 終わりに ===== 取得したデータをMeCabで処理しながら,その結果を利用するということが多いかと思いますが,既に出力結果がある場合,また出力結果を修正した正解ファイルがある場合も,簡単に処理することができます.形態素解析の結果には誤りも含まれることがあるため,正解ファイルを利用する,ということもニーズがあると思われます. {{indexmenu_n>206}}