はてなダイアリーのCSSを編集

タイトル部分の空白が気になったので,余白を小さくするようCSSを設定.

・[管理]→[デザイン編集]→[詳細設定]のスタイルシート部分に

h1 {/* タイトルの設定 */
padding: 1.8em 0% 0.7em 0%; /* ブログタイトル上,右,下,左のスペース調整 */
font-size:150%; 
}

を追加.

あと,下記のコードも加えて記事での行間も小さくした.

div.body {/* 本文の設定 */
line-height : 1em ; /* 行間の設定 */
}

この記事を参考にさせて頂きました.

RSSフィードから単一品詞の単語別出現数を取得してみた.

今回はOreilly集合知プログラミングの第3章を参考に

指定した日本語のRSSフィード形態素解析して,

単一品詞の単語別出現数を取得するPythonコードを作成してみました.

集合知プログラミング

集合知プログラミング

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:'部分しか実行されなくなる.

出力結果(csvファイルの中身から抜粋)

上記のコードでは,各ニュースサイトのRSSフィードから名詞を抽出しています.

Feed_name all 議長 雇用 野菜 原発 知事 大使館 公開 カジノ 職員 ...
livedoor NEWS - 国内トピックス 0 0 0 0 1 0 0 0 0 0 ...
Top Stories - Google News 8 0 4 3 13 3 0 4 0 4 ...
[注目] - MSN産経ニュース 0 3 0 0 0 0 2 0 2 0 ...
Yahoo!ニュース・トピックス - トップ 0 0 0 0 0 0 0 0 0 1 ...

形態素解析エンジンMeCab-pythonを使ってみた.

これから自然言語処理をかじっていこうと思うので,

今回は日本語を単語ごとに分解してくれる「形態素解析エンジン」をPythonで使ってみました.

フリーで使える形態素解析エンジンとしては,

Yahoo!JapanのAPIMeCab(めかぶ)というもの

が一般的らしく,今回はオフラインでも使えるMeCabを利用します.

Windowsにおけるmecab-pythonのインストール方法

MeCabの導入はココを参考にさせてもらいました.
具体的には以下の手順で行います.

  1. まずmecab-0.98.exeをインストール.(辞書の形式はutf-8を選択)
  2. そして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"で複数行(列数は各行とも同数に制限)を書き込めます.

上京&現在の状況

お盆で帰省してた大阪から,東京の下宿先へ戻ってきた.

なんかダラダラと飲み会をやってたせいか,少し風邪の症状が...

富士登山,明日(19日)なのに...

しかも,右足の付け根が痛いってことで,非常にまずい状況です.

                                                                                                                                                        • -

でも,晩は走らないとってことで,風邪のことを考慮して20分くらい歩くことにしました.

そしたら,知り合いが楽しそうに〇〇〇〇〇〇してる場面を目撃!

マジかよ!って,少しイラついたら,体調が良くなった感じです.笑

明日は勉強会やから,朝から大学に行かないとな!