Symfoware

Symfowareについての考察blog

Mecab PythonでTF・IDFによるBlogの重要単語抽出

FreeBSD 10にMecabとPythonバインディングをインストールしてみました。
FreeBSD 10 に MeCab + Pythonバインディングをインストールする

せっかくなので、多少実用的な例を試してみたいと思います。


重要単語抽出



Mecab Pythonを使ったTF・IDFによるWikipediaの重要単語抽出
こちらで試されている内容が面白そうです。

抽出元データとして、このBlogの記事を使用してみることにしました。




Blogのバックアップデータ



FC2 Blogのバックアップデータの形式はこんなかんじです。


AUTHOR: symfo
TITLE: Symfowareブログ
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: default
ALLOW PINGS: 1
PRIMARY CATEGORY: 備忘録
CATEGORY: 備忘録

DATE: 05/31/2009 13:26:15
-----
BODY:
主に、富士通製データベース「Symfoware」についての記事を書こうと思います。

投稿のテストを兼ねて。。。
-----
EXTENDED BODY:

-----
EXCERPT:

-----
KEYWORDS:

-----


--------




どうやら

-----
BODY:


から

-----
EXTENDED BODY:



までを切り出した箇所が記事の内容ですね。




解析プログラム



あってるか自信ないですが、適当にプログラムを書いて実行してみます。


  1. # -*- coding:utf-8 -*-
  2. import MeCab
  3. import sys, codecs, re, math
  4. sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
  5. class Article(object):
  6.     
  7.     def __init__(self, article_index):
  8.         self.article_indexs = set()
  9.         self.article_indexs.add(article_index)
  10.         self.count = 1
  11.     
  12.     def append(self, article_index):
  13.         self.article_indexs.add(article_index)
  14.         self.count += 1
  15.     
  16.     def get_article_count(self):
  17.         return len(self.article_indexs)
  18.     
  19.     def get_count(self):
  20.         return self.count
  21.     
  22. def get_article():
  23.     """ ログから1記事分の内容を切り出し """
  24.     
  25.     with codecs.open('symfoware.txt', 'r', 'utf-8') as f:
  26.         
  27.         is_article = False
  28.         befor_line = ''
  29.         article = ''
  30.         
  31.         for line in f:
  32.             
  33.             line = line.strip()
  34.             if line == 'BODY:' and befor_line == '-----':
  35.                 is_article = True
  36.                 continue
  37.             
  38.             if line == 'EXTENDED BODY:' and befor_line == '-----':
  39.                 is_article = False
  40.                 yield article[:-5]
  41.                 article = ''
  42.                 continue
  43.                 
  44.             befor_line = line
  45.             
  46.             if is_article:
  47.                 article += line
  48. def set_token(article, tokens, article_index):
  49.     """ 名詞データを抽出し、辞書に詰める """
  50.     
  51.     #symbol = re.compile( "[!-/:-@[-`{-~<>#]" )
  52.     symbol = re.compile( "[!-/:-@[-`{-~<>#a-zA-Z0-9]" )
  53.     m = MeCab.Tagger('-Owakati')
  54.     
  55.     encoded_text = article.encode('utf-8')
  56.     node = m.parseToNode(encoded_text)
  57.     while True:
  58.         
  59.         node = node.next
  60.         if not node:
  61.             break
  62.         
  63.         surface = node.surface.decode('utf-8')
  64.         feature = node.feature.decode('utf-8')
  65.         
  66.         if feature.split(',')[0] != u'名詞':
  67.             continue
  68.             
  69.         # 適当に記号を抜く
  70.         token = re.sub( symbol, '', surface )
  71.         if token == '':
  72.             continue
  73.         
  74.         if token in tokens:
  75.             tokens[token].append(article_index)
  76.         else:
  77.             tokens[token] = Article(article_index)
  78. def main():
  79.     
  80.     tokens = {}
  81.     article_index = 0
  82.     
  83.     # ドキュメントから名詞の抽出
  84.     for article in get_article():
  85.         print article_index
  86.         set_token(article, tokens, article_index)
  87.         article_index += 1
  88.     
  89.     # TFIDF計算
  90.     # TF:単語の出現数(Term Frequency)
  91.     # IDFは総文書数 / 単語が出現する文書の総数の対数(Inverted Document Frequency)
  92.     # TFIDFはその積
  93.     
  94.     tfidf_list = []
  95.     for token in tokens:
  96.         arc = tokens[token]
  97.         
  98.         tf = arc.get_count()
  99.         idf = math.log( article_index / arc.get_article_count() )
  100.         tfidf = tf * idf
  101.         
  102.         tfidf_list.append({'token':token, 'tfidf':tfidf})
  103.     
  104.     top_tfidf_list = sorted(tfidf_list, key=lambda x:x['tfidf'], reverse=True)[:100]
  105.     
  106.     for item in top_tfidf_list:
  107.         print item['token'], item['tfidf']
  108.     
  109. if __name__ == '__main__':
  110.     main()




ちなみに、英数字を抜かずに実行すると、htmlタグのノイズが入ります。


span 446953.93046
class 172451.552787
pun 97032.2875122
li 90573.991527
pln 86051.0047345
L 45382.5750326
45 27527.7958664
typ 22273.0112702
kwd 19695.0839884
tag 14908.3686164
td 12415.562501
str 9030.59301285
lt 8942.98492358
atv 7172.8674951
atn 7142.68545538
lit 6843.33000367
51 5323.87515089
00 4657.93618677
8 4320.38637643
import 4279.09486436
java 4089.5817355
tr 3907.07766104
7 3767.25492634
6 3746.46051093
key 3368.50780215
36 3337.5036744
9 3326.41331951
String 3265.54952433
new 3227.72290411
pre 3221.13123037
ol 3215.63816893
name 3153.81967155
500 3112.3686138
php 3097.9521223
sqlalchemy 3085.88870975
public 2951.42069482
id 2909.83186399
redis 2860.7381453
value 2764.68486102
db 2654.24728942
インストール 2611.08542917
test 2600.85166649
u 2522.41381478
i 2490.54566223
sample 2469.68042493
data 2449.56450272
62 2353.22752233
v 2346.76763976
xml 2304.88858163
sql 2303.50846435
27 2274.76896425
using 2264.85028264
con 2261.21524225
org 2254.35241635
client 2241.38579811
thrift 2189.44087355
x 2173.40423617
usr 2168.02895777
apache 2151.92915872
49 2131.77382092
doc 2120.32171713
02 2112.63143111
private 2089.56057305
A 2088.44467935
sb 2082.12385949
return 2077.78434495
銀座 2055.86818585
script 2051.60331786
print 2050.9892971
01 2046.86362419
self 2033.95445142
c 2028.14865032
データ 2006.66108772
text 1997.81180819
var 1969.26107084
at 1966.25006078
System 1958.39309987
string 1953.33264925
py 1924.76872975
接続 1923.67011746
google 1920.37428059
ファイル 1885.36033112
append 1882.5877424
type 1877.76392375
row 1869.84808159
to 1849.24416139
検索 1844.41584765
map 1842.2613022
t 1828.32146853
strong 1816.466761
item 1812.71925354
query 1811.68558454
データベース 1810.50043562
C 1809.41443944
04 1807.7278469
県 1805.29442563
03 1793.86490329
local 1780.00195968
市 1756.34194238
15 1755.04866118




sqlalchemyやredisはちゃんとしたキーワードとして残すべきですね。
htmlタグだけ選別して抜くのが面倒だったので、
英数字は除外しました。


結果は以下のとおり。


インストール 2611.08542917
銀座 2055.86818585
データ 2006.66108772
接続 1923.67011746
ファイル 1885.36033112
検索 1844.41584765
データベース 1810.50043562
県 1805.29442563
市 1756.34194238
追加 1722.62406863
列 1699.59688673
選択 1651.21426987
画面 1542.45165329
テーブル 1499.99613439
起動 1498.50716174
登録 1478.48293613
番号 1397.572386
サーバー 1390.84315745
取得 1359.95476826
目 1335.62766695
画像 1319.48543104
値 1307.34862352
イン 1293.13809151
設定 1278.85654813
処理 1277.52450156
入力 1267.07304606
クリック 1265.01819917
文字 1244.72772306
キー 1243.48107164
出力 1236.04831675
テスト 1229.6105651
秒 1225.69568212
プラグ 1216.84651007
名 1214.39386034
郵便 1211.15975891
エラー 1208.8486829
¥ 1191.60236209
オブジェクト 1177.27564018
ボタン 1177.18597128
ダウンロード 1168.64614642
変更 1119.48592215
証明 1119.11087468
パスワード 1107.22287481
スプライト 1087.66800268
プログラム 1086.52755349
町 1085.13995662
ユーザー 1071.4721626
バイト 1058.29192551
日本語 1054.27686163
座標 1047.07958542
次 1010.72700901
アプリケーション 1008.76058118
コード 992.634745952
こと 991.200468201
削除 990.468265869
定義 974.71715126
結果 967.877426317
の 967.633464062
書 963.960332327
ここ 947.003792832
描画 937.525879953
コマンド 932.721833079
ソース 923.93293477
フォルダ 922.756126652
以下 914.954278339
用 910.795395256
生成 908.422050899
行 902.477629089
時 896.467627553
更新 884.823355663
確認 875.593994068
1 872.833879299
終了 870.795102045
プロジェクト 863.868014152
変換 859.114809738
管理 852.308645286
保存 851.392655678
ビルド 848.99823732
「 828.353665656
情報 826.001115314
完了 824.032211166
住所 818.107772181
サービス 815.141084338
編集 806.823318172
リスト 803.294916387
機能 793.931340815
一覧 793.45289083
ポート 790.200314633
ログ 783.220768458
必要 782.211949532
ビット 774.076567542
ドライバ 773.552253505
ロード 771.366006153
環境 756.435818844
メソッド 752.945325409
サンプル 751.371543727
項目 750.441808236
2 748.340155223
クラス 748.340155223
とき 748.154968583




「インストール」は確かにソフトのインストール記事が多い気がするので納得。
「銀座」は、データベースのlike検索のサンプルとしてよく使用していたので、
その結果が出ているのだと思います。
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/11/03(月) 16:59:09|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<MeCabのPythonバインディングでユーザー辞書を使用する | ホーム | FreeBSD 10 に MeCab + Pythonバインディングをインストールする>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1529-c360ce22
この記事にトラックバックする(FC2ブログユーザー)