特定秘密保護法案のコメントを簡易テキストマイニング
特定秘密保護法案が先週の金曜日(12/6)可決された。いろいろな問題が指摘されているが、ここでは、ネットで公開されているアンケート結果を元に、簡易的なテキストマイニングを試みてみた。
分析対象
某有名新聞社 A新聞のHPでは、特定秘密保護法案のトピックスの中で、投稿マップというイベントを行っていた。これは、
- 横に、この法案に賛成 or 反対の軸
- 縦に、"日本の安全が脅かされていると感じるか"どうか、の軸
のマップがセルボタンで構成されていて、その中で自分の意見に一致する場所をクリックし自分のコメントを残せる、という仕組みである。投稿されたコメントは、すべて閲覧することができるので、マッピングの意見と、それに対応するコメントの傾向を調べることができる。テキストマイニングでは、コメントなり何なりの単語の数を数えたりする。(文の論旨、論理の把握というのはとても難しい)ので、マッピング軸に対応するコメントの議題(論旨ではなく)を、単語の分布傾向によって推し量ってみよう、というのが今回の主旨である。
マッピングはタテヨコに10段階 ... 100個のボックスに意見を記入できる仕組みだったのだが、ここでは、"法案に賛成・反対"の軸(横軸)に絞る。法案に対する意見とそれに対応する"コメントの中の単語分布"がどうなるか? ... 今回調査するデータは、法案成立直前、2013/12/06 20:19 更新時のものを利用する。(特に理由は無く、ちょうどそのタイミングでデータを取ったから。)
ちなみに、僕の意見をあらかじめ言っておく。科学的調査をするにあたっては、客観性が最も重要なので、僕もそのようにおこなうつもりだが、人間である以上、完全に客観的になれるものでもないと思う。だから、調査者は、先に自分の立ち居地について事前に表明していたほうがよいという考えである。僕は、この法案についてどちらかというと慎重論者である。
データ抽出方法
さて、ではどう分析するか?まずデータがなければ始まらない。データを集めて精製するのはそんなに難しくない。
- 事前にツール環境を作る。簡易DB ... sqliteを導入
- python でHTMLを扱うので、HTML分析用Beautifulsoup導入
- 日本語の形態素解析...Mecab を導入 & python-mecabドライバ
- A新聞社からコメントのHTMLをファイルにして保存(webブラウザでできる)
- Beautifulsoupでコメント抽出(by python)
- Mecabで分かち書き、単語単位に分ける
- sqliteにデータベースとしてぶっこむ。
- あとはSQLをたたいて平均なり何なりを確認
以上。これには虎の巻(というかカンペ)があって、
- 作者: Toby Segaran,當山仁健,鴨澤眞夫
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/07/25
- メディア: 大型本
- 購入: 91人 クリック: 2,220回
- この商品を含むブログ (273件) を見る
先の手順のうち、2と6の日本語形態素解析関連以外は、この本にやり方が載っているのでお勧め。Mecabまわりについてもそんなに難しくない。たとえばこんな感じ。
import MeCab as mc stoppos=[u'助詞',u'助動詞',u'副詞',u'接続詞',u'連体詞',u'記号'] stopwrd=[u'する',u'いる',u'ある',u'てる',u'思う',u'こと',u'これ',u'あれ',u'それ',u'れる',u'なる'] LANG_MODE='utf-8' def getWordsList(text): pttrn=re.compile('[a-z]+$') tmc=mc.Tagger() wl=[ ] parse_str=tmc.parse(text) if isinstance(parse_str,str): for w in parse_str.split('\n'): v=w.split(',') word=unicode(v[0].split('\t')[0],LANG_MODE) pos=unicode(v[0].split('\t')[-1],LANG_MODE) if pttrn.match(word)==None and len(v)>=3 and pos not in stoppos: k1=unicode(v[1],LANG_MODE) k2=unicode(v[2],LANG_MODE) uw=unicode(v[-3],LANG_MODE) if len(uw)>=2 and k1 not in stoppos and k2 not in stoppos: if (uw,pos) not in wl and uw not in stopwrd: wl.append( (uw,pos) ) return wl
textで入力された文を形態素解析して、stopposとstopwrdで調査対象としない品詞と単語を外し、そのtextに含まれていた単語のリストを返す。(同じ単語で違う品詞の場合も有りうるので品詞と組にして返している)
今回の分析では、一つのコメントの中で同一単語の数は数えないことにする。つまり、あるコメントにその単語が含まれるか否か、"有無"をDB化した。コメント自体が短いのと、後の分析する指標の見通しを良くするためである。
分析-評価の方法
さあDBができた。じゃ平均とって見るか...って何の平均を取るんだっけ?
説明し忘れていることがある。対象のコメントは、それぞれ縦と横に10段階、100セルのマッピングで意見が表現されているのであった。このマッピングを数値化しておかねばならない。ここでは単純に、-1~1 までの区間で数値化する。今回は横軸についての調査なので、マップの左側、もっとも反対が-1 、以降0.2ずつ増えて、右側のもっとも賛成が1になる。この数値(インデクスと呼ぼう)で、実際のコメント数の分布状況を確認してみると、
意見 | 反対 | ← | ← | ← | ← | → | → | → | → | 賛成 |
数値(インデクス) | -1.0 | -0.8 | -0.6 | -0.4 | -0.2 | 0.2 | 0.4 | 0.6 | 0.8 | 1.0 |
コメント数合計 | 2788 | 121 | 43 | 23 | 39 | 62 | 44 | 100 | 205 | 4879 |
賛成意見のほうがかなり多いことがわかる。ここで、各コメント数とインデクスを掛け合わせ、インデクスとしての平均を取る。
コメント数合計 | インデクスの平均 | インデクスの分散 |
8304 | 0.26558 | 0.88586 |
賛成意見のほうが多いので、インデクスの平均は正の数になる。0.26という数値は、全体の大体26%増しで賛成意見のが多い、という解釈ができる。(分散はとりあえず気にしないこと)
さて、コメントの単語の有無に対するデータベース化をすでに行っているので、「ある単語が含まれるコメントについてのコメント数合計・インデクス平均・分散」を、上記で全体に対して行ったのと同じように、計算することができる。各単語のインデクス平均を調べて、それが1.0に近ければ、賛成のコメントにより多く使われている単語で、-1.0に近ければ、反対のコメントにより多く使われている単語、というわけである。(単語のインデクス平均は、-1.0~1.0の間を取る)
ただし、この評価の注意点として、単語の数が非常に少ない場合がある。たとえば、一回しか出現しない単語で、その一回が数値インデクス-1.0の反対コメントであれば、その単語のインデクス平均は-1.0で、"反対のコメントに多く使われる単語"となってしまう。これを避けるために、全体の単語の出現数がある一定以上のものを調査対象とする。
結果
さて、後は計算してリスト化するだけだ。単語の出現数の閾値は、ここでは、100コメント以上のものを調査対象にする。(全体コメント数が8000超なのでこれで十分か)
まず「賛成派側のコメントにより多く使われる単語」を20個リストしよう。
単語 | 品詞 | 含まれるコメント数 | インデクス平均 | 母集団平均値との差(標準偏差単位) |
スパイ | 名詞 | 915 | 0.856 | 18.988 |
必要 | 名詞 | 1496 | 0.672 | 16.682 |
賛成 | 名詞 | 905 | 0.783 | 16.530 |
マスコミ | 名詞 | 742 | 0.811 | 15.771 |
朝日新聞 | 名詞 | 301 | 0.923 | 12.117 |
報道 | 名詞 | 589 | 0.706 | 11.364 |
防止 | 名詞 | 343 | 0.821 | 10.929 |
天国 | 名詞 | 272 | 0.878 | 10.730 |
機密 | 名詞 | 581 | 0.682 | 10.654 |
反日 | 名詞 | 202 | 0.950 | 10.343 |
当たり前 | 名詞 | 193 | 0.950 | 10.106 |
朝日 | 名詞 | 214 | 0.915 | 10.093 |
国益 | 名詞 | 219 | 0.847 | 9.135 |
無い | 形容詞 | 422 | 0.671 | 8.851 |
偏向 | 名詞 | 116 | 0.972 | 8.088 |
中国 | 名詞 | 546 | 0.572 | 7.611 |
早い | 形容詞 | 143 | 0.856 | 7.501 |
不思議 | 名詞 | 113 | 0.927 | 7.475 |
普通 | 名詞 | 176 | 0.795 | 7.469 |
日本人 | 名詞 | 262 | 0.682 | 7.156 |
つぎは、「反対派側のコメントにより多く使われる単語」20個。
単語 | 品詞 | 含まれるコメント数 | インデクス平均 | 母集団平均値との差(標準偏差単位) |
国民 | 名詞 | 1666 | -0.261 | 22.820 |
秘密 | 名詞 | 1688 | -0.219 | 21.172 |
主義 | 名詞 | 430 | -0.687 | 20.987 |
政府 | 名詞 | 451 | -0.610 | 19.761 |
民主 | 名詞 | 356 | -0.675 | 18.861 |
戦前 | 名詞 | 261 | -0.764 | 17.672 |
安倍 | 名詞 | 255 | -0.740 | 17.068 |
政治 | 名詞 | 314 | -0.612 | 16.524 |
憲法 | 名詞 | 220 | -0.748 | 15.976 |
権力 | 名詞 | 186 | -0.827 | 15.830 |
戦争 | 名詞 | 348 | -0.521 | 15.595 |
政権 | 名詞 | 420 | -0.447 | 15.509 |
隠す | 動詞 | 213 | -0.716 | 15.227 |
しまう | 動詞 | 295 | -0.555 | 14.967 |
悪法 | 名詞 | 137 | -0.917 | 14.704 |
廃案 | 名詞 | 173 | -0.754 | 14.245 |
自民党 | 名詞 | 163 | -0.780 | 14.188 |
維持 | 名詞 | 185 | -0.703 | 13.993 |
治安 | 名詞 | 164 | -0.759 | 13.934 |
官僚 | 名詞 | 147 | -0.780 | 13.464 |
いかがだろうか?割といろいろな傾向が見えてきていると思う。マスコミ関連の単語が多いのは、このアンケートの主催自体が新聞社だからか...
この結果の細かい分析については、ここでは見送ろうと思う。
補足
※それぞれの順位は、インデクス平均ではなく、"どれだけ母集団(全体のコメント)から偏っているか"の基準を示す"母集団平均値との差*1"で、20個をリストしている。これについての詳細は脚注に記す。
最後に
せっかくなので、得られた単語のリストを使い、勉強中のD3.jsで単語雲(word-cloud)を作ってみた。言及しているコメントが多いほど文字を大きく、賛成派は赤、反対派は青で表示している。(D3.jsはIE8と古いブラウザでは表示できませんあしからず)
*1:母集団の平均を $ m $ 、母分散を$\sigma^2$であるとする。そこから、ランダムに十分多い$n$個データを取得して標本としたとき、この標本の平均は、平均 $ m $ (母集団と同じ)、分散$\sigma^2/n$で表される。そこで、この標本分散による標準偏差$\sigma/\sqrt{n}$をつかって\[母集団平均値との差=\frac{|m-標本平均|\sqrt{n}}{\sigma} \]として計算している。つまり1で、標準偏差程度の差がある、ということ。