「吾輩は猫である」のテキストを分析してみる (4)
「吾輩は猫である」のテキストを分析してみる (1)
「吾輩は猫である」のテキストを分析してみる (2)
「吾輩は猫である」のテキストを分析してみる (3)
前回、何も工夫せずに頻出単語を取りだすと、記号や助詞・助動詞ばかりがでてきました。作品の特徴を捉えた頻出単語帳を作ろうと思うと、品詞を絞ったほうがよさそうです。そこで今回は、名詞 (の一部) のみの頻出単語を並べてみました。
吾輩・寒月・先生・猫・細君などの単語が見えます。「吾輩は猫である」の特徴を捉えた単語帳になってきたでしょうか。コードは下の通りです。
% 形態素分析結果 result の読込 load('neko.mat') % 名詞を抽出 idx1 = strcmp(result(:,2),'名詞'); idx2 = strcmp(result(:,3),'非自立'); idx3 = strcmp(result(:,3),'数'); result_noun = result(idx1 & ~idx2 & ~idx3,:); % セル配列からカテゴリカル配列を作成 cat_array = categorical(result_noun(:,1)); % 単語カテゴリーを作成 category = categories(cat_array); % 各カテゴリの出現回数 counts = countcats(cat_array); % 出現回数を出現パーセントに変換 prct = counts/sum(counts)*100; % 出現パーセントに従って降順でソート [~,I] = sort(prct,'descend'); prct_sorted = prct(I); category_sorted = category(I); % グラフ表示 figure(1); clf x = 1:length(prct_sorted); y = prct_sorted; plot(x,y,'o-') xmax = 20; axis([0 xmax 0 prct_sorted(1)+0.2]) text(x(1:xmax),y(1:xmax)+0.1,category_sorted(1:xmax)) title('「吾輩は猫である」形態素分析') xlabel('名詞出現ランク') ylabel('名詞出現パーセント')
- 作者: 夏目漱石
- 出版社/メーカー: 新潮社
- 発売日: 2003/06
- メディア: 文庫
- 購入: 5人 クリック: 55回
- この商品を含むブログ (85件) を見る
「吾輩は猫である」のテキストを分析してみる (3)
「吾輩は猫である」のテキストを分析してみる (1)
「吾輩は猫である」のテキストを分析してみる (2)
前回までで、「吾輩は猫である」を形態素分析にかけたセル配列が手に入りました。今回は、単語の出現頻度を調べてみようと思います。前回のコードで、
in = txt(1:1000);
として、最初の1000文字だけを取り出し、下のコードで出現頻度をプロットしてみました。
% セル配列からカテゴリカル配列を作成 cat_array = categorical(result(:,1)); % 単語カテゴリーを作成 category = categories(cat_array); % 各カテゴリの出現回数 counts = countcats(cat_array); % 出現回数を出現パーセントに変換 prct = counts/sum(counts)*100; % 出現パーセントに従って降順でソート [~,I] = sort(prct,'descend'); prct_sorted = prct(I); category_sorted = category(I); % データを保存 save('neko.mat','result','category_sorted','prct_sorted') % グラフ表示 figure(1); clf x = 1:length(prct_sorted); y = prct_sorted; plot(x,y) title('「吾輩は猫である」形態素分析') xlabel('出現ランク') ylabel('出現パーセント') xmax = max(x); axis([0 xmax 0 prct_sorted(1)+1])
結果は下のようになりました。もとの単語数が少ないのでグラフがガタガタしています。
次に、全文を突っ込んでみると次のようになりました。軸に張りついていて分かりにくいですが、単語数が増えてグラフが滑らかになりました。
同じデータを、両対数グラフでプロットしてみると、下のように広い範囲でほぼ直線になりました。
loglog(x,y)
両対数グラフ上で直線になる関係を冪乗則 (べきじょうそく) といいます。これは、単語の出現頻度分布をふくめて、自然界のさまざまな状況で現れる関係性だそうです。「吾輩は猫である」の文章も例外ではなく、冪乗則に従うことがわかります。
さて、上位に出現するのはどんな言葉でしょうか?下のようにトップ50位を表示してみました。
plot(x,y,'o-') xmax = 50; axis([0 xmax 0 prct_sorted(1)+1]) text(x(1:xmax),y(1:xmax)+0.5,category_sorted(1:xmax))
すると、当然と言えば当然ですが、最上位は「の」「。」「て」「、」「は」…となっていて、文章に必ず登場するような助詞・助動詞や記号ばかりです。意味のある名詞としては「吾輩」がかなり多いはずと思い見てみたら、47位にランクインしていました。
xlim([45 50])
文章を特徴付ける単語を抽出してこようと思うと、記号・助詞・助動詞などは除いて名詞などに焦点を当てたほうが良さそうです。次回以降、やってみようと思います。
- 作者: 夏目漱石
- 出版社/メーカー: 新潮社
- 発売日: 2003/06
- メディア: 文庫
- 購入: 5人 クリック: 55回
- この商品を含むブログ (85件) を見る
「吾輩は猫である」のテキストを分析してみる (2)
コードはこちら。neko.txtの全文をいきなり投入すると時間がかかるので、ここでは最初の100文字だけにしています。
% 「吾輩は猫である」のテキストを読込 fileID = fopen('neko.txt'); txt = fread(fileID,'*char')'; fclose(fileID); % MeCab DLLを読込 [notfound,warnings] = loadlibrary('libmecab.dll','mecab.h'); mecab = calllib('libmecab','mecab_new',1,libpointer('stringPtrPtr',{'MeCab'})); % MeCabで形態素分析 in = txt(1:100); mecab_result = calllib('libmecab','mecab_sparse_tostr',mecab,in);
そうすると下のような結果が出てきます。
この分析結果は、ズラズラッとつらなったテキスト形式でこのままでは扱いにくいので、下のようにセル配列に代入することにします。
ここで、MeCabの結果のフォーマットは「表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音」という10要素なのですが、改行記号などの場合は、strsplitで要素を分割したときに10要素に満たないことがあって扱いにくく、まぁ記号はいらないだろうということで消しています。
% MeCabの結果をセル配列に代入 row = strsplit(mecab_result,'\n'); % MeCabの結果をまず行ごとに分割 n = length(row)-2; % 行数を取得 (最後の2行は'EOS'等なので不要) result = cell(n,10); % 結果を格納する空配列を用意 idx = false(n,1); % あとで消去する行のインデックス for ii=1:n % 空白と「,」で要素ごとに分割 str = strsplit(row{ii},{' ',','}); if length(str)<10 % 記号などの場合は要素数が10に満たないので消去 idx(ii) = true; else % 結果を格納 result(ii,:) = str; end end % いらない行を消去 result(idx,:)=[]; % DLLの開放 clear mecab unloadlibrary('libmecab')
これで、下のような結果が得られました。
「吾輩は猫である」のテキストを分析してみる (1)
青空文庫から夏目漱石の「吾輩は猫である」の全文をダウンロードして遊んでみます。テキストファイルをダウンロードして開いてみると下のようになっていました。
ヘッダと (上の画像では見えていませんが) フッタと、本文中にたくさんルビなどの注釈がついています。これらはテキスト分析にはいらないので除きます。
ヘッダ・フッタは1箇所だけなのでメモ帳で手動で消しました。本文中の注釈は膨大な量なので、Matlab で正規表現を使って消すことにしました。コードはこちら。
% load text data fileID = fopen('wagahaiwa_nekodearu.txt'); txt = fread(fileID,'*char')'; fclose(fileID); % remove annotations pat = '《[^》]*》'; txt = regexprep(txt, pat, ''); pat = '[#[^]]*]'; txt = regexprep(txt, pat, ''); pat = '|'; txt = regexprep(txt, pat, ''); % save text data fileID = fopen('neko.txt','w'); fprintf(fileID,txt); fclose(fileID);
これで、下のように注釈がとれたテキストneko.txtができました。
形態素分析エンジンMeCabをMatlab (64bit)で使う
形態素分析エンジンMeCabをMatlabから使ってテキストをササッと解析できるようにしたい!、ということでやってみました。ちょっと手間だったので書き残しておきます。
下のページにまさにこれを実現するためのツールがあるのですが、「現在配布されている MeCab の dll は 32bit version であるため、64bit 版のMATLABと一緒に使うためには、dll のビルドが必要となります」という不穏な忠告が。自分の場合は64 bit版Matlabなので、まさにこれにあたります…。
Simple Text Miner for Japanese - File Exchange - MATLAB Central
仕方がないので、dllをビルドするという自分には難易度の高い旅に出ました。
上のブログ記事の中盤以降にある "What about Japanese Text?" という項目を探して、そのとおりにおこないます。
- Matlab 64 bit版を持っている
- Matlab に適合した (たぶんC++) コンパイラを持っている → 自分の場合は、無料のVisual studio 2013 Communityがインストールしてあったので、これを使いました。
- Takuya's instructionに従いなさい
という3ステップで、あら簡単、と思いきやTakuya's instructionがヘビーでした。以下、インストラクションのPDFを見つつ読んでください。
- MeCab 0.966のバイナリパッケージをインストール → インストール時に、文字のエンコーディングを聞いてきますが、デフォルトのSHIFT-JISで自分はうまくいきました。
- MeCab 0.966のソースファイルをダウンロード&解凍 → Windows環境では.tar.gzファイルを解凍するにはソフトウェアが必要です。自分はLhaplusを使いました。
- 解凍されたなかの"src"というフォルダを見つけます。
- このフォルダのなかにあるいろんなファイルの内容を、インストラクションの通りに修正します。
- Visual studioのコマンドプロンプト (いろいろあるが、自分はVS2013 x64 Native Tools Command Promptでうまくいきました) を起動します。
- フォルダをさきほどの"src"にもっていきます。フォルダを変更するコマンドはcd。
- "Make"とタイプ。
- すると、ずらずらっとビルドが始まり、"libmecab.dll"が生成されます。
- このdllファイルと、"mecab.h"ファイルを、Matlabのスクリプトを置くフォルダにコピー。これで、MatlabでMecabを使う準備完了です。ふぅ。
では、Matlabを起動してサンプルコードをコピペしてみます。まずは下のコードでDLLを読み込み。僕の環境では"警告: データ型 'mecab_node_tPtr' (構造体 mecab_node_t で使用) は存在しません…"というエラーが出ましたが、これは無視して良いらしい。
%% Loading DLL fname_lib = 'libmecab.dll'; fname_header = 'mecab.h'; [notfound, warnings] = loadlibrary(fname_lib, fname_header);
下のコードで「ライブラリlibmecabdeの関数」がたくさん表示されればDLLを読み込めているということのようです。
%% (optional) view available functions of the DLL libfunctionsview('libmecab')
あと、下のように2,3行おまじないを書いてから、
%% Calling MeCab morphological analyzer argv = libpointer('stringPtrPtr', {'MeCab'}); argc = 1; mecab = calllib('libmecab', 'mecab_new', argc, argv);
日本語のテキストを与えると形態素分析の結果が返ってきます。すばらしい。
%% test MeCab functionality input = '太郎は次郎が持っている本を花子に渡した。'; result = calllib('libmecab', 'mecab_sparse_tostr', mecab,input);
result =
太郎 名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
次郎 名詞,固有名詞,人名,名,*,*,次郎,ジロウ,ジロー
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
持っ 動詞,自立,*,*,五段・タ行,連用タ接続,持つ,モッ,モッ
て 助詞,接続助詞,*,*,*,*,て,テ,テ
いる 動詞,非自立,*,*,一段,基本形,いる,イル,イル
本 名詞,一般,*,*,*,*,本,ホン,ホン
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
花 名詞,一般,*,*,*,*,花,ハナ,ハナ
子 名詞,接尾,一般,*,*,*,子,コ,コ
に 助詞,格助詞,一般,*,*,*,に,ニ,ニ
渡し 動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。 記号,句点,*,*,*,*,。,。,。
EOS
最後にDLLを開放します。
%% Release DLL from the memory clear unloadlibrary('libmecab')
テキストデータを単語に分割して品詞などを判別する形態素解析
テキストデータ (文章) をパソコンで分析する場合、英語だと単語同士のあいだにスペースがあるので、どれが単語か見分けるのは簡単です。でも日本語の場合はスペースがないので、そう簡単にはいきません。
テキストデータを、言語的に意味を持つ最小の単位に分割して、品詞などを判別する作業を形態素解析というそうです。これをおこなってくれるオープンソースの MeCab というソフトウェアがあったので、インストールしてみました。
MeCab: Yet Another Part-of-Speech and Morphological Analyzer
インストールして起動するとウィンドウがあらわれるので、テキストを入力してみましょう。「すもももももももものうち」を正しく認識して分析してくれます。すごい。
でも平仮名だらけのテキストはやはり難しいようで、「何だか分かるか若旦那」はきちんと分解してくれますが、「なんだかわかるかわかだんな」は最後の「だんな」が1文字ずつにばらされてしまいました。
ちなみに、「なんだか…」は始めから読んでも終わりから読んでも読みが同じ回文になっています (意味はないです…)。
- 作者: Steven Bird,Ewan Klein,Edward Loper,萩原正人,中山敬広,水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/11/11
- メディア: 大型本
- 購入: 20人 クリック: 639回
- この商品を含むブログ (44件) を見る