2014年11月29日土曜日

bag-of-wordsの次元削減法まとめ

bag-of-wordsはともかく次元が大きい。出現する単語の種類数分の次元がある。

1万次元などは余裕で行ってしまう。このままではまともに識別機を作ることは困難なので
何らかの手段で圧縮してやる必要性がある。

参考:Text Mining Handbook

単語頻度

単純に単語の出現頻度が低いものを考慮から外して次元の削減をするというもの。上位10パーセントの単語のみを使っても識別の精度は変わらないらしい。これは頻度が高い単語の重要度をあげるというTF/IDFの考えに真っ向から反しているが、低すぎる頻度の単語は意味がないのでこれでいいらしい。

Information Gain

\(\text{InformationGain}(x|w)=H(x)-H(x|w)\)
ここで\(x\)は特徴量すなわちbag-of-wordsで\(w\)はある単語。
\(H(x)\)は特徴量のエントロピーで\(H(x|w)\)はある単語\(w\)が発生したとき(わかったとき)特徴量のエントロピー。
つまり$\text{Infomation Gain}$とは、ある単語(次元)を知ることによって、どの程度エントロピーが下がったかという指標。
もっと噛み砕くと、文書を何個かのクラスに分類しようとするとき、単語\(w\)を知ることで、どれだけ分類の特定をすすめられたかの指標になる。

Latent Semantic Indexing

Latent Semantic Indexingとは、まんまSingular Value Decompositionのこと。
bag-of-wordsにSVDを適用して次元削減することをこんな風に呼ぶらしい
SVDに関しては、過去の記事を参照
http://satomemocho.blogspot.jp/2014/10/rsvd.html

なぜわざわざLatent Semantic Indexingと呼ぶかというと、なんか同義語とかを処理できるようだが、詳しくは不明。
以下のサイトをよもう!
http://chasen.org/~taku/blog/archives/2005/11/_tfidf_1.html

2014年11月23日日曜日

機械学習のためのpythonの設定(CentOS6.5)

機械学習のプログラムはRとpythonの2強のようなので、pythonも使かわないと

python2.7のインストール(centOS6.5はデフォルトで2.6)

yum install python27

easy_install およびpipのインストール

wget https://bootstrap.pypa.io/ez_setup.py -O - | python
easy_install pip

各種ライブラリに必要なライブラリのインストール

yum -y install gcc gcc-c++ kernel-devel
yum -y install python-devel
wget http://pypi.python.org/packages/source/d/distribute/distribute-0.6.27.tar.gz
cd  distribute-0.6.27
python2.7 setup.py install
yum install libpng-devel -y

各種機械学習系ライブラリのインストール

pip install numpy
pip install scipy
pip install matplotlib
pip install gensim

2014年11月13日木曜日

SublimetextでGithub Flavored Markdownを書く

Sublimetextを入れたらとりあえず行うべきこと

参考:https://github.com/revolunet/sublimetext-markdown-preview
参考:http://sonoshou.hatenablog.jp/entry/2013/12/20/Sublime_Text_%E3%81%A7_Markdown%EF%BC%8E

パッケージコントロールの導入

ctrl+@ を押してコンソールを出したのち以下のサイトのコマンドを入力してパッケージコントロールをインストールする。
https://sublime.wbond.net/installation

各種パッケージの導入

ctrl+shift+p をおして以下のパッケージをインストール

  • Markdown Preview マークダウンを書くため
  • IME Support 日本語入力をインラインにするため

フォントの変更

フォントは変えておこう。特にwindowsの人は
Preference ->Settings - Userに以下のように記載する。(当然対応するフォントをインストールしてから)

{
"font_face": "Source Code Pro",
}

Markdown previewのカスタム

プレビューへのキーバインド

デフォルトではプレビューするためにctrl+shift+pを押してからMarkdown previewを押さないといけないので、この動作をにキーをバインドする。
Preference ->Key Bindings - Userに以下のように記載することでalt+mでプレビュー

[
{ "keys": ["alt+m"], "command": "markdown_preview", "args": {"target": "browser"} }
]

Markdown previewでGithub Flavored Markdown、シンタックスハイライト、数式を使う

デフォルトの設定ではGithub Flavored Markdownではなく普通のMarkdownなので表が書けなかったりする。
またコードのシンタックスハイライトにも対応していない。MathJaxもオフになっているので数式がプレビューで表示できない。
Preferences-> Package Settings -> Markdown Preview->Settings - Userに以下のように記載する。

{
"enable_mathjax": true,
"enable_highlight": true,
"enabled_parsers": ["markdown", "github"],
"github_mode": "gfm"
}

MathJaxの使い方は以前の記事参照
http://satomemocho.blogspot.jp/2014/11/mathjax.html



こんな感じでエスケープが必要
 \\(\mathcal{N}\\)

2014年11月5日水曜日

MathJaxによる数式の書き方

このブログに数式を書きたいのでMathJaxを使用することにした。

つかいかた

ヘッダに以下を追加
参考
<script type="text/javascript"
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML">
</script>

サンプル

\(\TeX\)風に書けます。

ベイズの定理


\(p(Y|X)=\frac{p(X|Y)p(Y)}{p(X)}\)
\(p(Y|X)=\frac{p(X|Y)p(Y)}{p(X)}\)

正規分布


\( \mathcal{N}(\mathbf{x}|\mathbf{\mu},\Sigma)= \frac{1}{(2\pi)^{D/2}|\Sigma|^{1/2}}\exp\left\{-\frac{1}{2}(\mathbf{x}-\mathbf{\mu})^T\Sigma^{-1} (\mathbf{x}-\mathbf{\mu}) \right\} \)
 \(
\mathcal{N}(\mathbf{x}|\mathbf{\mu},\Sigma)=
\frac{1}{(2\pi)^{D/2}|\Sigma|^{1/2}}\exp\left\{-\frac{1}{2}(\mathbf{x}-\mathbf{\mu})^T\Sigma^{-1} (\mathbf{x}-\mathbf{\mu}) \right\}
\)

ベイズ情報量基準


\(BIC=-2\ln(L)+k\ln(n)\)
\(BIC=-2\ln(L)+k\ln(n)\)

2014年10月19日日曜日

Rのsvd(特異値分解)で次元の圧縮

Rではsvdを使って次元の圧縮が可能
svdでは任意の行列を3つの行列に分解します。

> #適当な行列を作る。(2次元の特徴量が3個あるイメージ)
> x=matrix(1:6, nrow=2, ncol=3)
> 
> #中身はこんな感じ
> x
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> 
> #特異値分解
> svd=svd(x)
> 
> #次の3つの行列に分解される。
> A=diag(svd$d)
> U=svd$u
> V=svd$v
> 
> #上記の3つの行列の積は元の行列と一致する。
> U %*% A %*% t(V)
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
次元の圧縮をしたいときはこんな感じ
> #次元圧縮はこんな関数にしておくと便利
> reduce <- function(x,svd,reduced_dimension) {
+     result=t(svd$u[,1:reduced_dimension]) %*% x 
+     return(result)
+ }
> 
> x=matrix(1:6, nrow=2, ncol=3)
> svd=svd(x)
> 
> #2次元だったものを1次元に圧縮
> reduce(x,svd,1)
          [,1]      [,2]      [,3]
[1,] -2.189418 -4.998466 -7.807514


詳しい原理は下記参照
http://en.wikibooks.org/wiki/Data_Mining_Algorithms_In_R/Dimensionality_Reduction/Singular_Value_Decomposition

2014年10月15日水曜日

rubyでBag-of-Wordsの計算

Mecabという日本語の形態素解析機があります。

Mecab公式

Bag-of-Wordsをつかっていろいろやってみたかったので、いろいろライブラリを探していました。
Mecabを使ったBag-of-Wordsの計算はRでRmecabというライブラリが提供されていますが、Rでは大きなテキストに対応できないそうで、私の環境では数十M程度のテキストファイルでメモリ関連のエラーが頻発しました。公式サイトでも大きなファイルには対応できないと書いてあります。

RMecab公式

そこで、rubyでBag-of-Wordsを計算してみました。
(Mecabを使って作ったのでTororoっていう名前にしました。)

Tororo

今はまだBag-of-Wordsの計算ぐらいにしか使えませんが、将来的にはMecabのラッパーとして、rubyからの日本語構文解析全般に使えるようにしたいです。 (あとgemの形にしたい) そのうち、READMEをもっとまともに書いて使える用にします。

githubのOVERVIEWに書かれている以下の文言は、これからこうしたい!という意気込みです。
Parse Japanese text with Mecab.
Simple ruby interface.

2014年10月4日土曜日

PostgreSQLでのレコードを返す関数の実行

PostgreSQLで関数は普通こんな形でselect以下に書いて実行します。
postgres=# select sqrt(144);
 sqrt 
------
   12
(1 row)
普通の関数は上のでOK
しかし、record型を返す関数の場合はこの形で指定するとレコードがすべて1カラムに入って帰ってくるのでみずらい
postgres=# select pg_get_keywords();
                         pg_get_keywords                          
------------------------------------------------------------------
 (abort,U,unreserved)
 (absolute,U,unreserved)
 (access,U,unreserved)
 (action,U,unreserved)
 (add,U,unreserved)
 (admin,U,unreserved)
 (after,U,unreserved)
 (aggregate,U,unreserved)
 (all,R,reserved)
 (also,U,unreserved)
where句に入れるとレコードで帰ってくるよ
みやすい!
postgres=# select * from pg_get_keywords();
       word        | catcode |                   catdesc                    
-------------------+---------+----------------------------------------------
 abort             | U       | unreserved
 absolute          | U       | unreserved
 access            | U       | unreserved
 action            | U       | unreserved
 add               | U       | unreserved
 admin             | U       | unreserved
 after             | U       | unreserved
 aggregate         | U       | unreserved
 all               | R       | reserved
 also              | U       | unreserved

rubyは文字列のインクリメントができる!

rubyは文字列のインクリメントができます。
こういう細かいところに配慮されているっていうところが素晴らしい
こういった動作はCであれば'x'を格納するアドレスをずらしていって実装するしかなかった。
str='x'
4.times{
   puts str
  str=str.next
}

実行結果

x
y
z
aa

ちゃんと桁上げまでされます。

2014年9月27日土曜日

rubyからMecabを使う

ruby-mecabのインストール

別途、Mecabのインストールが必要 参考:  Mecab公式
wget https://mecab.googlecode.com/files/mecab-ruby-0.996.tar.gz
tar zxf mecab-ruby-0.996.tar.gz 
cd mecab-ruby-0.996

ruby extconf.rb
su
make;make install

使ってみる。

require 'MeCab'
require 'csv'

class Parser
  @targger
  def parse(str)
    node=@targger.parseToNode(str)

    while node do
   #助動詞とかの情報はCSV形式だよ。
   #必要なのは1行目のみ
     feature=CSV.parse(node.feature)[0]
      puts node.surface+' '+feature[0].to_s
      node=node.next
    end
  end

  def initialize
    @targger=MeCab::Tagger.new()
  end

end

obj=Parser.new
obj.parse('今宵は月が綺麗ですね')

実行結果

[sato@localhost konbu]$ ruby parser.rb 
 BOS/EOS
今宵 名詞
は 助詞
月 名詞
が 助詞
綺麗 名詞
です 助動詞
ね 助詞
 BOS/EOS

これは便利!

2014年9月23日火曜日

RubyMineの最重要ショートカット

rubyやRoR用IDEのRubyMineの重要ショートカット
これぐらい知っておけば十分
  • command+/
  • コメントアウトを付加/削除
  • control+space
  • 入力補完
  • command+J
  • Live Templates呼びだし
  • F4
  • 選択したクラスやメソッド等にジャンプbr>
  • command+shift+.
  • <%= %>を挿入
  • option+enter
  • Quick Fix呼びだし
  • Ctrl+Alt+U
  • Model dependency diagrambr
  • Alt+enter
  • 正規表現の簡易チェック

rubyプロジェクトのフォルダ構成のベストプラクティス(?)

rubyのプロジェクトのフォルダ構成はこんな形がよいみたい
つーかgemはみんなこんな感じ

crawler/
  lib/
   crawler.rb #動作用モジュールCrawler
   crawler/
    database.rb #必要なクラス
    webpage.rb
    database_connection.yml #DBの接続情報
  bin/
   exec_crawler.rb #動作させるときに実際実行されるファイル


上記の例だと、exec_crawler.rbを実際に叩いて使う
exec_crawler.rbはcrawler.rbにあるメソッドを使う。
exec_crawler.rbが行うのはコマンドライン引数の解釈など
lib/をインクルードするとAPI的に使える。

exec_crawler.rbではこんな感じでロードパスにlib/を追加してreuireする
$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
require 'crawler'
include Cralwer
この場合、カレントディレクトリがbin/の状態で実行するのでlib/内でのファイルの読み込みはこんな感じ
YAML::load_file(File.join(__dir__, 'database_connection.yml'))

2014年9月21日日曜日

rubyからPostgreSQLへのアクセス その1

pgというgemでPostgreSQLへrubyからアクセスできます。
rubyには史上最強のO/R mapperであるActiveRecordが存在するため、PostgreSQLとのインターフェイスとしてはそちらを先に想定すべきです。
しかし、ちょっとSQLを投げたいだけの場合にはむしろこちらのほうが便利です。


基本:行数を表示するだけ


$LOAD_PATH << "."
require 'pg'

#接続する
db = PG::connect("127.0.0.1",5432 ,"","","mydb","sato","password")

#クエリの定義
sql="select count(*) from tbl";

#クエリの実行
result=@db.exec(sql)

#行数の表示
p result[0]["count"].to_i

注意していただきたいのはSELETしてきた結果の取り出しです。
pgでは結果はレコードを表すハッシュの配列として帰ってきます。
id,name.ageというテーブルがある場合、結果として帰ってくるのは次のような配列です。
result[0]['id']=>1
result[0]['name']=>sato
result[0]['age']=>26


result[1]には次の結果の行が入っています。
select max(id),max(age) のようなクエリを使った場合結果として帰ってくる行の名前が
同名であるため、maxというキーが2つ帰ってきます。
これでハッシュが上書きされるため正常に取り出せません。
AS 句をうまく使いましょう

rubyのopenuriやnet/http でエラーが出ちゃうときの対処

rubyのopenuriやnet/http で503とかのエラーがでるとき、何度かリトライしたいということがあります。 単純にアクセス繰り返すとDOSってると思われてしまいます。 次のようにGETを行うコードのラッパーとなるメソッドを作り、これを呼ぶとよさそう アクセス前の待機時間を引数にとっておき、503エラーが出た場合などは同じメソッドを待機時間を延ばしてリトライします。 400秒待ってダメなような場合はあきらめます。
     def carefulGet(url,waittime)
    begin
      sleep waittime
      charset = nil
      html = open(url, :proxy => nil) do |f|
        charset = f.charset
        f.read
      end
      return html
    rescue => evar
      puts evar
      if waittime<400 then
        puts 'GET error!! retry '
       #ここで同じメソッドを待機時間を上げて再起呼び出し
    carefulGet(url,waittime+20)
      else
        puts 'GET error!! QUIT'
      end
    end
  end

Mongodbへのリモートアクセス

最初にユーザーを作る
Mongodbはデフォルトでユーザーはいないので認証をONにする前に作っておく
ユーザーはDBに所属するので、使用したいDBに切り替えてから作る
use mydb
db.addUser('sato','password')
/etc/mongodb.confの以下の行をコメント解除
auth=true

以下の行をコメントにする
#bind_ip = 0.0.0.0

mongodの再起動
service mongod restart

IPTABLESを設定
iptables -A INPUT -p tcp --dport 27017 -j ACCEPT
iptables -A INPUT -p tcp --sport 27017 -j ACCEPT

IPTABLESの設定を保存
/etc/init.d/iptables save

再起動
service iptables restart


接続
mongo [host_IP]/ -u sato -p password

2014年9月20日土曜日

CentOSでrubyにnokogiri

普通にgem install nokogiriだといろんな依存ライブラリが足りない

こんな感じで
yum install libxslt libxslt-devel libxml2 libxml2-devel -y
gem install nokogiri --use-system-libraries

2014年9月19日金曜日

ブログ開始

いままで、技術的なメモはローカルにに書いてたけど、Webにうつすよ