RSSフィードから単一品詞の単語別出現数を取得してみた.
今回はOreilly集合知プログラミングの第3章を参考に
単一品詞の単語別出現数を取得するPythonコードを作成してみました.
- 作者: Toby Segaran,當山仁健,鴨澤眞夫
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/07/25
- メディア: 大型本
- 購入: 91人 クリック: 2,220回
- この商品を含むブログ (277件) を見る
RSSフィードから,各記事のタイトル,リンク,エントリ等を取り出すのには
Universal Feed Parserというpythonのモジュールを用います.
また,形態素解析には前回の記事で利用したMeCabを使います.
作成コード
日本語をcsvファイルへ出力する部分はココを参考にさせてもらいました.
また,extractKeyword関数やcsvモジュールについてはそれぞれ過去の記事(クリックすれば飛ぶ)で扱っています.
#coding:utf-8 import re import csv import MeCab import feedparser from extractKeyword import extractKeyword # ////////////////////// # ----- set URLs ----- # ////////////////////// URLs = ['http://news.livedoor.com/topics/rss/dom.xml', 'http://dailynews.yahoo.co.jp/fc/rss.xml', 'http://news.google.com/news?hl=ja&ned=us&ie=UTF-8&oe=UTF-8&output=atom&topic=h&hl=ja', 'http://sankei.jp.msn.com/rss/news/points.xml'] # ///////////////////////////////// # ----- category selection ----- # ///////////////////////////////// class_num = 0 word_classes = [u'名詞',u'動詞',u'形容詞',u'副詞',u'助詞',u'助動詞'] word_class = word_classes[class_num] # /////////////////////////////// # ----- defined functions ----- # /////////////////////////////// def getwordcounts(url): """RSSフィードのタイトルと、単語の頻度のディクショナリを返す""" # フィードをパースする d = feedparser.parse(url) wc={} # すべてのエントリをループする for e in d.entries:# RSSの種類によって,記事に相当する部分が異なることに対応する if 'summary' in e: summary = e.summary elif 'description' in e: summary = e.description else: summary = e.link # 単語のリストを取り出す words = getwords(e.title+' '+summary) # extractKeywordを用いるため,単語を連結してテキスト化 txt = '' for i in range(len(words)): txt += words[i] words_sub = extractKeyword(txt,word_class) for word in words_sub: wc.setdefault(word,0)# dict型のkeyにwordがなければ,value=0として新設 wc[word] += 1 return d.feed.title,wc def getwords(html): """すべてのHTMLタグを取り除き,単語リストを返す""" txt = re.compile(r'<[^>]+>').sub('',html)# htmlから'<[^>]+>'を''に置き換える tagger = MeCab.Tagger('-Owakati') return tagger.parse(str(txt)).split(' ') def main(): apcount = {} wordcounts = {} feedlist = [line for line in URLs] for feedurl in feedlist: wc = {} try: title,wc_ini = getwordcounts(feedurl) for w,bc in wc_ini.items(): wc.setdefault(w.encode('sjis'),bc)# csvで日本語を表示させるため,Shift_JIS化 wordcounts[title] = wc for word,count in wc.items(): apcount.setdefault(word,0) if count>1: apcount[word]+=1# それぞれの単語が出現するフィードの数を数える except: print 'Failed to parse feed %s' % feedurl# urlが認識できなければエラー表示 # でたらめな単語が存在するフィードがあることや一般的な単語の除外を考慮し,単語の出現率に敷居値を設定する wordlist = [] for w,bc in apcount.items(): frac = float(bc)/len(feedlist) if frac>0.1 and frac<0.5: wordlist.append(w) # csvへの書き込み用リストを生成 header = ['Feed_name']+wordlist rows = [] for blog,wc in wordcounts.items(): row = [blog.encode('sjis')] for word in wordlist: if word in wc: row.append(wc[word]) else: row.append('0') rows.append(row) # csvへ書き込み csv_writer = csv.writer(open('rss_data.csv','w'),lineterminator='\n') csv_writer.writerow(header) csv_writer.writerows(rows) if __name__ == "__main__": main()
- -
[注] csvへの書き込みようリストを生成する部分で
# wordlistのkeyはShift-JIS化済みで,wordcountのはutf-8形式として... for blog,wc in wordcounts.items(): for word in wordlist: if word in wc: row.append(wc[word].encode('sjis')) else: row.append('0')
だと'wc'がの日本語の場合,条件分岐'if word in wc:'において,その'else:'部分しか実行されなくなる.
形態素解析エンジンMeCab-pythonを使ってみた.
これから自然言語処理をかじっていこうと思うので,
今回は日本語を単語ごとに分解してくれる「形態素解析エンジン」をPythonで使ってみました.
フリーで使える形態素解析エンジンとしては,
Yahoo!JapanのAPIとMeCab(めかぶ)というもの
が一般的らしく,今回はオフラインでも使えるMeCabを利用します.
Windowsにおけるmecab-pythonのインストール方法
MeCabの導入はココを参考にさせてもらいました.
具体的には以下の手順で行います.
- まずmecab-0.98.exeをインストール.(辞書の形式はutf-8を選択)
- そしてlibmecab-1.dll、MeCab.py、MeCab.pydをパッケージフォルダにコピーする.
[注]パッケージフォルダはPython2.6ならC:\Python26\Lib\site-packages
テストコード
#coding:utf-8 import MeCab # /////////////////////////// # ----- set sentence ----- # /////////////////////////// test_sentence = 'すもももももももものうち' # //////////////////////////////////// # ----- Choose test_number ----- # //////////////////////////////////// test_num = 1 # /////////////////////////////// # ----- defined functions ----- # /////////////////////////////// def test01(s): tagger = MeCab.Tagger('-Ochasen') result = tagger.parse(s) print result def test02(s): tagger = MeCab.Tagger('mecabrc') result = tagger.parse(s) print result def test03(s): tagger = MeCab.Tagger('-Owakati') result = tagger.parse(s) print result def test04(s): tagger = MeCab.Tagger('-Oyomi') result = tagger.parse(s) print result def test05(s): tagger = MeCab.Tagger('-Ochasen') node = tagger.parseToNode(s) while node: print "%s %s" % (node.surface, node.feature) node = node.next def main(): if test_num == 1: test01(test_sentence) elif test_num == 2: test02(test_sentence) elif test_num == 3: test03(test_sentence) elif test_num == 4: test04(test_sentence) else: test05(test_sentence) if __name__ == "__main__": main()
関数test01~04はMeCab.Tagger()の引数が
'-Ochasen'(茶筌),'mecabrc'(?),'-Owakati'(分かち書き),'-Oyomi'(読み)
と異なり,それぞれの出力結果は以下のようになっています.
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
>>test01[MeCab.Tagger()の引数が'-Ochasen'](ChaSen互換モード)
すもも スモモ すもも 名詞-一般 も モ も 助詞-係助詞 もも モモ もも 名詞-一般 も モ も 助詞-係助詞 もも モモ もも 名詞-一般 の ノ の 助詞-連体化 うち ウチ うち 名詞-非自立-副詞可能 EOS
>>test02[MeCab.Tagger()の引数が'mecabrc'](後述のtagger.parseToNode()と同じ機能?)
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ の 助詞,連体化,*,*,*,*,の,ノ,ノ うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ EOS
>>test03[MeCab.Tagger()の引数が'-Owakati'](単語ごとに分割)
すもも も もも も もも の うち
>>test04[MeCab.Tagger()の引数が'-Oyomi](漢字の読みでもOK)
スモモモモモモモモノウチ
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
また関数test05ではインスタンスtaggerにメソッド:.parseToNode(引数)を用いて
MeCab.nodeというクラスを出力しています.この出力フォーマットは
表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音
であり,表層形はnode.surface,各性質はnode.featureでコンマ区切りのリストとして取得できます.
>>test05
BOS/EOS,*,*,*,*,*,*,*,* すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ の 助詞,連体化,*,*,*,*,の,ノ,ノ うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ BOS/EOS,*,*,*,*,*,*,*,*
文章から特定の品詞を抽出する
またまたココを参考にさせてもらいました.
#coding:utf-8 import MeCab # ///////////////////// # ----- set text ----- # ///////////////////// test_txt = u'PythonからMeCabの形態素解析機能を使ってみました。' # //////////////////////////////// # ----- category selection ----- # //////////////////////////////// class_num = 0 word_classes = [u'名詞',u'動詞',u'形容詞',u'副詞',u'助詞',u'助動詞'] word_class = word_classes[class_num] # //////////////////////////////// # ----- defined functions ----- # //////////////////////////////// def extractKeyword(text,word_class): """textを形態素解析して、名詞のみのリストを返す""" tagger = MeCab.Tagger('-Ochasen') node = tagger.parseToNode(text.encode('utf-8'))#textがu''形式⇒『.encode()』が必要 keywords = [] while node: if node.feature.split(",")[0] == word_class: keywords.append(node.surface) node = node.next return keywords def main(): keywords = extractKeyword(test_txt) for w in keywords: print w, if __name__ == "__main__": main()
上記のコードでは'class_num = 0'としているので,名詞を
「PythonからMeCabの形態素解析機能を使ってみました。」から取り出しています.
>>実行結果
Python MeCab 形態素 解析 機能
東電消費電力データのベイズ曲線回帰
今回は東電の消費電力データにベイズ曲線回帰を適用してみました.
学習データは東電が公開しているcsvデータで,
入力は時刻 [時],出力は消費電力 [万kW]です.
(ほんとは気温とか,平日or休日かのダミー変数も入力しないと消費電力予測には使えないけど...)
理論式はPRML第1章を参考に以下のPythonコードを作成しました.
#coding:utf-8 ''' Purpose:Bayesian Curve_fitting ''' import numpy as np import input_csv import matplotlib.pyplot as plt # ////////////////////////// # ----- set data_set ----- # ///////////////////////// path = 'C:\Documents and Settings\User\My Documents\python_csv' read_file = path+'\\juyo-j.csv' head_num = 5 ; req_col = [2] # //////////////////////////// # ----- set parameters ----- # //////////////////////////// M = 10 alpha = 0.001 beta = 11.1 # ////////////////////////////// # ----- defined functions ----- # ////////////////////////////// def scale(X): # For Normalization mu = np.mean(X, axis=0) sigma = np.std(X, axis=0,ddof=1) X = (X-mu)/sigma return X,mu,sigma def phi(x,M): # This is one-column vector. return np.matrix([x**i for i in range(0,M+1)]).reshape(M+1,1) def S_inv(xlist,alpha,beta,M): tmp1 = sum([phi(x,M)*phi(x,M).T for x in xlist]) tmp2 = alpha*np.identity(M+1)+beta*tmp1 return np.matrix(tmp2) def mean(phi_x,S,xlist,tlist,beta,M): tmp_list = list(np.vstack((xlist,tlist)).transpose()) return beta*phi_x.T*S*sum([phi(xi,M)*ti for [xi,ti] in tmp_list]) def variance(phi_x,S,beta): return beta**(-1.)+phi_x.T*S*phi_x def main(): #>>----- get data_set ----- data = np.array(input_csv.method_01(read_file,head_num,req_col)) tlist,mu,sigma = scale(data[:,0]) xlist = np.array(range(0,len(tlist)))*0.1 #>>----- learn mean and variance ----- S = S_inv(xlist,alpha,beta,M).I xs = np.linspace(0, xlist[-1], 500) means = np.array([mean(phi(xi,M),S,xlist,tlist,beta,M)[0,0] for xi in xs]) s = np.sqrt([variance(phi(xi,M),S,beta)[0,0] for xi in xs]) plt.title('2011/4/5') plt.xlabel('Time[H]',style='italic',fontsize=15) plt.ylabel('power consumption [e4 kW]',style='italic',fontsize=15) plt.plot(xlist,tlist*sigma+mu,'ro') plt.plot(xs,means*sigma+mu,'b-') plt.plot(xs,(means+s)*sigma+mu,'g--') plt.plot(xs,(means-s)*sigma+mu,'g--') plt.xlim(0.0, xlist[-1]) plt.xticks(xlist, range(0,len(tlist))) plt.grid(True) plt.show() if __name__ == "__main__": main()
で,結果を描写したものがこれです.(赤点が学習データで緑の破線は分散による幅)
コード上にある'input_csv'モジュールは前回の記事で紹介したもので,
東電のcsv(juyo-j.csv)でヘッダが5行,用いた消費電力データが3列目だったので
"head_num = 5 ; req_col = [2]"としています.
なお,用いた多項式関数の次数Mやハイパーパラメータalpha,betaの値はテキトーです.
てか,東京電力電力供給状況APIで過去の消費電力取得できるけど,気温はどー取得すればいいんやろ?
ブログ再開&Pythonでのcsvの入出力
半年くらい放置してたんですけど,ソースコードの備忘録をつけたいので再開します!
当面はPython+機械学習(あと,できればMATLAB/Simulinkでの制御シミュレータ)をネタとして書いていきます.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
今回は,データ形式としてメジャーなcsv形式のファイルのPythonでの入出力を行います.
csvファイルの入力
下記に2通りのcsv入力関数(method_01,02)を載せています.
#coding:utf-8 ''' Purpose: input csv_file ''' import csv import numpy as np def method_01(read_file,head_num,req_col): # read_file <- filename you wanna use # head_num <- number of header's rows # req_col <- list which has column's number reader = csv.reader(file(read_file)) data = [] row_count = 0 for row in reader: if row_count >= head_num: row_sub = [] col_count = 0 for elem in row: if col_count in req_col: row_sub.append(float(elem)) col_count += 1 data.append(row_sub) row_count += 1 return data # this object type is "list". def method_02(read_file,req_col,skip_header=True): # read_file <- filename you wanna use # req_col <- list which has column's number # skip_header <- True or False data_src = np.genfromtxt(read_file,skip_header=skip_header,delimiter=',') data = data_src[:,req_col] return data # this object type is "numpy.array".
"method_01"はcsv.readerで各行をパースすることで,各要素に対して操作を加えることや(上記ではfloat(elem)で浮動小数点型にしています)
1行以上のヘッダにも対応させています.
また,"method_02"ではnumpyの組み込み関数genfromtxtを用いて簡潔化しています.
csvファイルの出力
# ----- sample01_writer = csv.writer(open('sample01.csv','w'),lineterminator='\n') sample01_writer.writerow(header) sample01_writer.writerow(row) # "row" is a list_object . # ----- sample02_writer = csv.writer(open('sample02.csv','w'),lineterminator='\n') sample02_writer.writerow(header) sample02_writer.writerows(rows) # "rows" is a list of rows .
基本的にはcsv.writerでインスタンスを作成し,それにメソッドで書きこんでいきます.
その際に".writerow"でリスト(1行),".writerows"で複数行(列数は各行とも同数に制限)を書き込めます.