<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Não Aqui! &#187; Programing</title>
	<atom:link href="http://www.chokkan.org/blog/archives/category/programing/feed" rel="self" type="application/rss+xml" />
	<link>http://www.chokkan.org/blog</link>
	<description>Blog presented by Naoaki Okazaki</description>
	<lastBuildDate>Sun, 13 Jun 2010 15:22:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SimString (類似文字列検索ライブラリ) 1.0 released</title>
		<link>http://www.chokkan.org/blog/archives/285</link>
		<comments>http://www.chokkan.org/blog/archives/285#comments</comments>
		<pubDate>Sun, 07 Mar 2010 14:28:38 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Programing]]></category>
		<category><![CDATA[Research]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=285</guid>
		<description><![CDATA[SimStringという類似文字列検索ライブラリをBSDライセンスでリリースしました．類似文字列検索とは，文字列集合（データベース）の中から，クエリ文字列と似ているものを見つけ出す処理です．コンピュータは，正確に一致する文字列を探すのは得意ですが，表記揺れに出くわすと，途端に対応できなくなります．例えば，「スパゲティ」に対して，レストラン情報などを返すサービスにおいて，「スパゲッティ」や「スパゲティー」などの表記揺れが検索クエリに与えられると，通常のデータベースでは情報を提示することが出来ません．類似文字列検索を用いると，表記揺れが検索クエリに与えられても，「スパゲティ」という既知語を代替クエリとして提案したり，「スパゲティ」の情報をダイレクトに引き出すことができるようになります．
似てる語を探す技術って，文字列処理の基本中の基本で，自然言語処理では当たり前のように使われていてもおかしくないと思うのですが，研究ではほとんど見かけません．２つの文字列が与えられたときに，似てるか似てないかの識別する研究は，色々あるのですが，ある文字列が与えられたときに，どの文字列が近いかを高速に収集する方法は，あまり見かけません．検索エンジンを提供している会社では，検索クエリログに基づくクエリ訂正などを行っていますが，検索クエリログは誰でも入手できるわけではありません．類似文字列検索は，データベースやデータマイニングの分野で盛んに研究がされていますが，単語や用語レベルの文字列が簡単に扱えるツールが見つからなかったので，自分で作ってみました．
SimStringは，「文字列集合の中で，検索文字列との類似度がある閾値以上のものをすべて返す」という処理を高速に行えるように設計されています．類似度関数としては，コサイン係数，ジャッカード係数，ダイス係数，オーバーラップ係数をサポートしています．類似度を計算するときの文字列の特徴として，文字Nグラムを採用しています．
例えば，3グラム（N=3）を用いたとき，「スパゲティ」は「＄＄ス」「＄スパ」「スパゲ」「パゲテ」「ゲティ」「ティ＄」「ィ＄＄」と表現されます．このとき，文字列の先頭と末尾を表す特殊な記号「＄」が挿入されていますが，これを用いるか用いないかはカスタマイズ可能です（デフォルトでは用いないことになっている）．また，Nグラムの単位（すなわちNの値）も，自由に設定できます．また，日本語などのマルチバイト文字でも正確にNグラムが計算できるように，ユニコードをサポートしています．
SimStringは，類似文字列検索を正確に，かつ高速に行えるように設計されています．Google Web 1Tコーパス の英単語（13,588,391文字列）から，コサイン類似度が0.7以上の文字列を検索するのに必要な時間は，１クエリあたり平均 1.10 [ms] 程度です．
実装はC++で，ヘッダファイルをインクルードするだけで他のアプリケーションに組み込めるようになっています．また，PythonとRubyのSimStringモジュールも，ビルドできるようになっています．他言語のモジュールはSWIGを用いてラッパを自動生成しているので，Perlなどの言語にも対応できるはずです（ビルド報告，サンプルプログラムなど歓迎致します）．Pythonで類似文字列が一瞬で検索出来るなんて，楽しい世界が広がると思いませんか？
$ python
Python 2.5.1 (r251:54863, Oct 15 2007, 23:38:19)
[GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import simstring
>>> db = simstring.reader('web1tuni/web1tuni.db')
>>> db.measure = simstring.cosine
>>> db.threshold = 0.9
>>> db.retrieve('approximate')
('approximat', 'pproximate', 'approximate', 'approximated', 'approximatel',
'approximates', 'approximatey', 'anapproximate', 'approximatelt', 'approxima
tely', 'reapproximate', 'toapproximate')
>>> db = simstring.reader('web1tja/unigrams.db')
>>> db.measure [...]]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/285/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SQLite3のINSERT文を高速化</title>
		<link>http://www.chokkan.org/blog/archives/250</link>
		<comments>http://www.chokkan.org/blog/archives/250#comments</comments>
		<pubDate>Wed, 07 Oct 2009 14:04:53 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[Programing]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=250</guid>
		<description><![CDATA[こちらのFAQを参照．小ネタですが，以前に１回調べて，また忘れていたので，メモ．
]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/250/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Classias 1.0 released</title>
		<link>http://www.chokkan.org/blog/archives/246</link>
		<comments>http://www.chokkan.org/blog/archives/246#comments</comments>
		<pubDate>Sat, 26 Sep 2009 17:49:52 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Programing]]></category>
		<category><![CDATA[Research]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=246</guid>
		<description><![CDATA[Classiasという分類のための機械学習アルゴリズムの実装を公開しました．今のところ，L1/L2正則化ロジスティック回帰（最大エントロピー法），L1/L2正則化L1損失線形カーネルサポートベクトルマシン（SVM），平均化パーセプトロンをサポートしています．学習アルゴリズムとしては，平均化パーセプトロン，L-BFGS法，OWL-QN法，Pegasos，Truncated Gradient（L1-FOLOS）を実装してあります．カーネルは使えませんが，線形識別モデルを高速に学習できるようになっています．二値分類，多クラス分類，候補選択（明示的に与えられた候補の中からスコア最大のものを選ぶタスク）をサポートしています（SVMは今のところ二値分類のみ）．
このツールはもともと，最大エントロピー法を自分で使うために実装したもので，作り始めてからもう２年くらい経過しています．去年のColingやEMNLPの論文の機械学習の箇所は，このツールで実験しています．文字列による素性，自動分割交叉検定など，自然言語処理の実験に便利な機能に重点を置いて作ったつもりです．詳しくは，使い方を参照してください．
ソースコードも，インスタンスのデータ構造，損失関数，学習アルゴリズムなどのコンポーネントを，C++テンプレートクラスとして実装するという設計になっています．L-BFGS法を実装しているlibLBFGSを除けば，ヘッダファイルをインクルードするだけでClassiasを利用したプログラムが書けるようになっています．クラスリファレンスやサンプルコードはドキュメントを参照してください．新しい学習アルゴリズムも，簡単に追加できるようになっているのですが，ドキュメントをもう少し充実させていかなければなりません･･･．
LIBLINEARやLIBSVMと一緒にrcv1.binaryでパフォーマンスを測ってみました．まず，分類精度に関してはロジスティック回帰とL1損失SVMに大差がなく，平均化パーセプトロンはちょっと悪いという予想通りの結果で，Classias，LIBLINEAR，LIBSVMのどれも同程度の分類精度を出しています．
学習速度に関しては，LIBLINEAR速すぎです．L1正則化のロジスティック回帰ではそれほどスピードの差はありませんが，L2正則化のロジスティック回帰では，LIBLINEARの方が４倍くらい速くなっています．アルゴリズム的には，L-BFGS法と信頼空間ニュートン法の戦いで，後者はヘッシアンを使っているので，速くなるのも頷けます．ただ，収束の判定条件が違うと思うので，後できちんと検証してみようと考えています．
SVMに関しては，LIBLINEARの圧勝（LIBLINEARの方が10～20倍高速）でした．ClassiasのPegasosも健闘していますが，学習率や収束判定の調整で10～20倍の速度差を埋められるかは疑問です．Dual coordinate descentはやっぱり強いですね．こちらも後で実装して遊んでみたいです．
実装するといろいろ分かることがあるので，これからも実験しながら育てていきたいと考えています．
]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/246/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CRFsuite 0.9 released</title>
		<link>http://www.chokkan.org/blog/archives/234</link>
		<comments>http://www.chokkan.org/blog/archives/234#comments</comments>
		<pubDate>Thu, 24 Sep 2009 10:55:38 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Programing]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=234</guid>
		<description><![CDATA[CRFsuite 0.9をリリースしました．libLBFGS 1.8と組み合わせてビルドすることが出来なくなっていたので，その問題の修正のみです．また，試験的にLinuxバイナリの配布を始めてみました．libLBFGSと静的にリンクしてあるので，このバイナリを落として実行するだけで動くはずです．
いろいろやっていたら，もう２ヶ月も経っていた･･･．
]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/234/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CDB++ 1.1 released</title>
		<link>http://www.chokkan.org/blog/archives/229</link>
		<comments>http://www.chokkan.org/blog/archives/229#comments</comments>
		<pubDate>Mon, 13 Jul 2009 17:05:48 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Programing]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=229</guid>
		<description><![CDATA[CDB++のバージョン1.1をリリースしました．こちらも，libLBFGSで大変お世話になっている今道様からパッチを頂きました．
一つ目はgotoを使っていたためのコンパイルエラーの修正です．よく「gotoは読みづらくなるから使うな」という主張を見かけますが，私はエラー時の終了処理など，用途がはっきりしている場合は積極的に使うべきだと考えています．error_exitみたいなラベルを付ければ，エラー時の処理内容が分かりやすくなりますし，何重にもネストしたループから脱出する場合も，gotoを使わないとロジックが分かりづらくなります．
ただ，C++では変数の宣言が関数内の何処にでも書けるという仕様から，gotoの使い方が難しくなります．具体的には，次のようなコードの場合です．
    // Processing #1...
    if (error_condition_1) {
        goto error_exit;
    }

    // Processing #2...
    if (error_condition_2) {
        goto error_exit;
    }

    // [...]]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/229/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>libLBFGS 1.8 released</title>
		<link>http://www.chokkan.org/blog/archives/227</link>
		<comments>http://www.chokkan.org/blog/archives/227#comments</comments>
		<pubDate>Mon, 13 Jul 2009 14:50:45 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Programing]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=227</guid>
		<description><![CDATA[libLBFGSのバージョン1.8をリリースしました．今回のリリースでは，backtracking法による線形探索でステップ長を選ぶときに，Armijo (sufficient decrease) 条件，regular Wolfe (sufficient decrease + curvature)条件，strong Wolfe条件の３つの基準を選べるようにしました．これらの基準の詳細に関しては，libLBFGSのドキュメンテーションもしくは『Numerical optimization』の本を参照してください．
今回のアップデートでは，いつもお世話になっている今道様から頂いたパッチをそのまま採用させて頂きました．
]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/227/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CDB++ 1.0 released</title>
		<link>http://www.chokkan.org/blog/archives/224</link>
		<comments>http://www.chokkan.org/blog/archives/224#comments</comments>
		<pubDate>Thu, 09 Jul 2009 14:07:29 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Programing]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=224</guid>
		<description><![CDATA[CDB++という，静的ハッシュデータベースライブラリをリリースしました．ライセンスは修正BSDです．
静的ハッシュデータベースなので，いったんデータベースを構築したら，要素の追加や削除は行えません．その代わり，コンパクトなデータベース，高速な構築，高速な検索ができるようになっています．データ構造は，Constant Databaseを採用しています．Constant Databaseの実装はいくつかありますが，クロスプラットフォームでお手軽に使えるものがなかったので，作ってみました．また，このライブラリはcdbpp.hというインクルードファイルのみで構成されているので，このファイルをインクルードするだけでアプリケーションに組み込めます．
ハッシュデータベースには，Oracle DBやTokyo Cabinetなど，優れた実装がたくさんあります．しかし，単にキーと値のペアをファイルに書き出し，後で簡単な検索を行うだけであれば，CDB++でも十分だと思います．

Tokyo Cabinet

]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/224/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>gccにおけるstd::tr1::regex</title>
		<link>http://www.chokkan.org/blog/archives/215</link>
		<comments>http://www.chokkan.org/blog/archives/215#comments</comments>
		<pubDate>Mon, 22 Jun 2009 17:34:22 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[Programing]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=215</guid>
		<description><![CDATA[とあるプログラムで，C++からregexを使いたい状況が発生．boostにあるのは知っているけど，出来るだけboostを使わないコーディングをしているので，あれこれ調査していたら，tr1に盛り込まれる予定だったことを思い出す．
Visual Studio 2008 SP1では，tr1のサポートが追加され，すんなりregexが使えるようになっている．コードはこんな感じ．すごく便利．
#include < iostream>
#include < regex>

int main(int argc, char *argv[])
{
    std::tr1::regex rx("abc");
    std::cout
        ]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/215/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10行強で書けるロジスティック回帰モデル学習</title>
		<link>http://www.chokkan.org/blog/archives/149</link>
		<comments>http://www.chokkan.org/blog/archives/149#comments</comments>
		<pubDate>Wed, 01 Apr 2009 16:03:23 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[Programing]]></category>
		<category><![CDATA[Research]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=149</guid>
		<description><![CDATA[ロジスティック回帰（logistic regression）の学習が，確率的勾配降下法（SGD: stochastic gradient descent）を使って，非常に簡単に書けることを示すPythonコード．コメントや空行を除けば十数行です．

リストの内包表記，条件演算子（Cで言う三項演算子），自動的に初期化してくれる辞書型（collections.defaultdict）は，Python以外ではあまり見ないかも知れません．
リストの内包表記は，Haskell, OCaml, C#にもあるようなので，結構メジャーかも知れません．
[W[x] for x in X]
と書くと，「Xに含まれるすべてのxに対し，それぞれW[x]を計算した結果をリストにしたもの」という意味になります．sum関数はリストの値の和を返すので，変数aにはXとWの内積が計算されます．
Pythonでは，三項演算子を条件演算子と呼びます．書き方もちょっと変わっていて「真の時の値 if 条件 else 偽の時の値」という形式で書きます．C言語では，「条件 ? 真の時の値 : 偽の時の値」なので，最初は違和感があるかも知れません．「x = 通常の値  if 通常の条件 else 異常な場合の値」と書けば，xと「通常の値」がソースコード上で隣接するので，慣れてくると分かりやすい気もします．
g = ((1. / (1. + math.exp(-a))) - l) if -100. < a else (0. - l)
では，内積の値aが-100よりも大きければ事例Xが正例になる確率をシグモイド関数で計算し，-100以下ならexp(-a)がオーバーフローする恐れがあるので，0と近似します．この確率値から実際のラベル (0または1)を減算することで，誤差gが計算されます．
collections.defaultdictは，辞書（マップ型）オブジェクトにキーが登録されていないとき，値をデフォルト値として自動的に登録してくれる便利なオブジェクトです．
W = collections.defaultdict(float)
に対して，W['hoge'] += 1.0とすると，'hoge'というキーがWに登録されていれば，その値を1.0増やし，'hoge'というキーがWに登録されていなければ，自動的にW['hoge'] = 0.と初期化し，さらにその値を1.0増やします．通常の辞書型では登録されていないキーにアクセスすると例外が発生するので，setdefaultというメソッドを使う必要があって，コードが読みづらくなります．defaultdictを使うと，スッキリしますね．
ロジスティック回帰について説明しませんでしたが，ざっくり言うと事例Xが正例もしくは負例に分類される確率が計算できることがウリの，二値分類器です．確率的勾配降下法は，名前こそ難しそうですが，素性の勾配を少量（このサンプルコードでは1個）の事例で近似して，降下させる方法です．こんな簡単な方法でも，news20データセットにおいて95.50%の精度（1/10のholdout評価）が出せます．libsvm（またエイプリルフールリリースしてますね）で線形SVMを回した場合の精度は，97%弱なので，こんなシンプルな方法でも善戦していることが分かります．
上のコードは，PRML本の第４章の輪読をするときに，数式を追うだけでは眠くなるので，書いてみました（そのときの輪読の資料と全体のサンプルコード）．分かりやすさ最優先なので，バイアス項，正則化，実数値素性，多クラスロジスティック回帰，複数回の反復，収束判定，学習率の自動調節など，いろいろなトピックをカバーしていませんが，機械学習の入門用，またPythonの学習の教材として，いろいろ遊べると思います．
]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/149/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CRFsuite 0.8 released</title>
		<link>http://www.chokkan.org/blog/archives/136</link>
		<comments>http://www.chokkan.org/blog/archives/136#comments</comments>
		<pubDate>Mon, 16 Mar 2009 17:55:25 +0000</pubDate>
		<dc:creator>chokkan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Programing]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.chokkan.org/blog/?p=136</guid>
		<description><![CDATA[CRFsuiteのバージョン0.8をリリースしました．モデルファイルのフォーマットを改良し，異なるアーキテクチャにおけるモデルファイルの互換性を確保しました．つまり，x86のアプリケーション・サーバーでCRFのモデルを学習し，SPARCやPowerPCのマシンでモデルを読み込んで，タグ付けをする，といったことが可能になりました．
バージョン0.7をリリースした直後に，Ultra SPARC IIIi上のサーバーで，モデルの読み込み時にクラッシュする問題が報告されました．この問題をデバッグしてみると，４バイトでアライメントされていないメモリアドレスからDWORDの値を読み出すところで，プロセッサ例外が発生することを突き止めました．x86のプロセッサはどんなアドレスからでもDWORDの値を読み出せるという，至れり尽くせりの環境なので，この問題を見逃していました．
そもそも，CRFsuiteのモデルファイルでは，DWORDの値のバイトオーダーすら実行環境依存で，big endianもしくはlittle endianのいずれかに統一する取り決めをしていませんでした．そこで，今回の問題を修正するにあたって，モデルファイル内の数値のバイトオーダーをlittle endianに統一する改訂を行いました．このため，モデルファイルの互換性は失われ，バージョン0.8で0.7以前で作られたモデルファイルを読み込むことは出来ません．
ちなみに，バイトオーダーに依存せずにDWORDの値を読み書きするコードは，以下のようになります．
static void write_uint32(FILE *fp, uint32_t value)
{
    uint8_t buffer[4];
    buffer[0] = (uint8_t)(value &#38; 0xFF);
    buffer[1] = (uint8_t)(value >> 8);
    buffer[2] = (uint8_t)(value >> 16);
    buffer[3] = (uint8_t)(value >> 24);
    fwrite(buffer, sizeof(uint8_t), 4, fp);
}

static [...]]]></description>
		<wfw:commentRss>http://www.chokkan.org/blog/archives/136/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
