2009-05-24  遺伝的アルゴリズム事始め

遺伝的アルゴリズムは,最適化手法のひとつです。名前のとおり生物の進化に触発された方法らしく,人工知能と呼ばれるもののひとつだそうです。

上場投資信託(ETF,Exchange Traded Fund)の値動きを分析するために,遺伝的アルゴリズムに挑戦してみることにしました。最近,業界で流行っているみたいですし。(本当なの?)

要件

簡単にソフトウェアの要件を考えてみることにしました。

静的構造

「やりたいこと」がだいたい決まったところで,ソフトウェアの静的構造を考えてみることにしました。

静的構造

<画像の説明>ソフトウェアの静的構造です。遺伝的アルゴリズムのフレームワークと,上場投資信託を分析するための実装クラスを描きました。(全体構造ではありません。収まりを良くするために,主要なクラスを抜粋して記述しています。)

静的構造の説明を少々。はじめに,遺伝的アルゴリズム特有の事柄を抽象化することにしました。特有の事柄とは,「交叉」「突然変異」「適応度関数」のみっつです。「進化によって個体の状態が変わる」という性質と,個体が持たなければならない性質は細かく分けることにして,各々をEvolvableインターフェイスとAgentインターフェイスに追いやることにしました。

つぎに個体に実行時間を与える方法と,実行時文脈を渡す方法を考えました。これには,Agentインターフェイスの実装クラスのprocess(...)メソッドに実行時のコードを書くという,よく見かける方法を採用することにしました。Javaの世界だとinit(...)の方が好まれそうですが,あえてprocess(...)にしてみました。

今回はシーケンスがさほど複雑ではないので,静的構造が決まったら,9割はできたようなものでした。ほかの細かな点は,実装しながら考えることにしました。

実装

実装には,Visual J# .NET(Visual Studio .NET 2003)を使ってみました。Visual J# .NETを選んだ理由は,手持ちのPCにインストールされていたからです。最初は純粋なJavaを使おうと思っていたのですが,止めました。最近のJavaの開発には,Eclipseという開発ツールを使います。わざわざEclipseをインストールするのは面倒に感じたのと,Eclipseは過去に速度が遅いという評判があったので,軽快に動作するVisual Studio .NET 2003で済ませてしまうことにしました。

気になる実行結果は,「日経225連動型上場投資信託の取引パターン」でお話しています。

今回の目標のひとつは,遺伝的アルゴリズムのフレームワークを作ることでした。出来上がったものを見ると,フレームワークと呼べるほどの汎用性のある構造には仕上がっていないのかもしれません。

個体の表現はクラスであり,クラスを具象化したものがオブジェクトです。よって,「オブジェクトが進化する方法」を考えることになるのですが,オブジェクトが進化するって,どういうことなのでしょうか。

私は,「単純にオブジェクトの内部状態が書き換わること。進化の良し悪しは適応度関数の値が決めることであって,本質的な問題ではない」と考えました。オブジェクトの内部状態を決めるのは,変数です。変数の表現をどうすべきか,最後まで悩みました。実装クラス(Trader)にべったりくっついてしまう結果になりましたが,これが良いのか悪いのか,どうもすっきりしません。

»固定リンク

2008-11-08  Excel/Visioでニューラルネットワーク

連休中に多層パーセプトロン型のニューラルネットワークの実験をしました。

「唐突に何言ってるの?ニューラルネットワークって何?」と思った人がいるかもしれません。ニューラルネットワークは,生物の脳の神経細胞を数理的なモデルにしたものだそうです。説明しているサイトは山ほどあるので,興味のある人は検索してみてください。

ニューラルネットワークは,学術的には人工知能のひとつだとされています。人工知能ってコトバは何やら怪しげで,別世界の高度な処理を指しているかのように思えるかもしれません。なんてことはありません。細部を見れば数値を足したり・引いたり,メモリをコピーしたり,処理を条件分岐しているだけです。現在のコンピュータで実現できるのですから,当然なのです。

私は今後,人工知能サービスを整備していくつもりでいます。人工知能と呼ばれているものには数種類ありますが,「ニューラルネットワーク」「制約充足問題」「遺伝的プログラミング」の3本柱をぜひ習得したいと思っています。得られた成果物は,アルゴリズム株取引の売買判定や,アルゴリズム・アフィリエイトの商品の最適化などに使います。

第一弾として,Microsoft Officeにニューラルネットワークを実装してみました。経緯と実験結果をお話します。

準備

じつは私,ニューラルネットワークと無縁だったわけではないのです。学生時代,お向かいの研究室のお題がニューラルネットワークだったのです。何度かそのゼミの研究発表を見ていたので,どんなものなのかはだいたい知っていました。でも当時は大した興味はなくて,「これって何に使うんだろうね」くらいにしか思っていませんでした。

時は流れて2008年,私は自力でニューラルネットワークを実装してみることにしました。今回,主に参考にした本は「臼井支朗」先生らによる「基礎と実践ニューラルネットワーク」です。この本もそうなのですが普通の専門書では,ニューラルネットワークを数式で説明しています。見慣れない用語もいっぱい出てきて,私の能力で理解できるのか心配になってしまいました。以下に,遭遇した専門用語を並べてみますね。

最初の難関は「これらの要素が何に属するものなのか」を正確に理解することでした。ニューラルネットワークは,広義にはグラフ(度数分布表のことではなくて「頂点と辺の集合」のこと)です。要素は,「頂点」または「辺」のどれかに属するのです。数式の意味を紐解いて,グラフに当てはめていくことにしました。

つぎの難関は「何をどうやって作るのか,何ができれば良いのか,何をやらないのか」を決めることでした。この手のシステムは,目指すべき世界がはっきりしていないといけません。曖昧なままでは,できたものが役に立たなかったり構造が歪になったりしてしまうのです。要件を箇条書きにします。

Excel VBA/Visio VBAでニューラルネットワーク

ニューラルネットワークの数理的なモデルと,ソフトウェアの要件が分かったような気分になったところで,実装方法を詳しく検討することにしました。

巷には,C/C++言語で書かれたニューラルネットワークのサンプルプログラムが溢れています。これを活用しない手はありません。オライリージャパンの「ゲーム開発者のためのAI入門」と「集合知プログラミング」という本にニューラルネットワークのサンプルプログラムが載っていたので,VBAで実装する際はこれらのコードを参考にすることにしました。

つぎはデータ構造のお話です。たいていのニューラルネットワークのサンプルプログラムは,隣接行列表現(ようは2次元配列)で書かれているようです。私は隣接行列表現ではなくて,隣接リスト表現を採用することにしました。ニューロンとニューロン同士の関係をオブジェクトにして,モデルの抽象度をほどんと変えずに実装することにしました。しかし,データ構造を大胆に変えたがために,入手したサンプルプログラムはほとんど役に立たなくなってしまいました。

どうして,わざわざ遠回りしたのかというと「ニューロンに自律的な振る舞いをさせたい」という思惑があったのです。ニューロンを指して「あなたのいまの値は?」と尋ねれば,値が返ってくるようにしたかったのです。学習中にはニューロンオブジェクトが能動的に描画オブジェクトを書き換えて,ニューラルネットワークの様子をグラフィカルに構築するようにしたかったのです。

静的構造図

<画像の説明>ソフトウェアの静的構造です。UML風に描いてみましたが,UMLの細かい決まりを意識しているわけではありません。しかも,このままではVBAの言語仕様から逸脱しているのです。実際にはVBAに合わせながら実装しました。

静的構造が決まったところで,Excel VBAで実装してみることにしたのだが,大問題に気づきました。辺(Edge)を表現する描画オブジェクトに「コネクタ」を使っていたのだが,Excelのコネクタにはテキスト属性が存在しないのです。これでは辺の値を表示できません。いやはや調査不足でした。急遽,Visio VBAに載せ替えることにしました。

余談ですが,ExcelとVisioでは描画周りのフレームワークにほとんど共通点がないのですね。派生元の文化の違いを垣間見た気がしました。

XOR問題を解かせてみたら

ソフトウェアが仕上がったので,2入力のXOR(排他的論理和)をニューラルネットワークで解いてみることにしました。

XORのニューラルネットワーク 入出力の特性

<画像の説明>学習後のニューラルネットワークと,入出力の特性を図にしてみました(ニューラルネットワークはVisio上に半自動で描画されます)。

「普通,XORの入出力は2値なんだから,入出力が連続値(実数)なのはおかしい」と思った人がいるかもしれません。どんな形の関数なのか見たかったので,連続値を入力してみたのです。

「XOR演算できたからといって,何の意味があるの?ニューラルネットワークなんか使わなくても計算できるんじゃないの?」と思った人もいるかもしれません。XOR演算は,この業界の基本例題なのです。例題は例題であって,それ以上の意味はありません。

ついでにニューラルネットワークをVisual Basic相当の式に展開してExcel VBAの関数にしてみました(下のコード)。あまり見かけない形式かもしれません。

Public Function nnxor(i1 As Double, i2 As Double) As Double

    Dim h1, h2, o1 As Double

    h1 = 1 / (1 + Exp(-(i1 * 5.75629288124718 + i2 * 5.87868353255397 - 2.3117209662348)))
    h2 = 1 / (1 + Exp(-(i1 * 2.91199452973333 + i2 * 2.93085382671416 - 4.39555060504074)))
    o1 = 1 / (1 + Exp(-(h1 * -6.92972808917433 + h2 * 7.85290876041432 + 2.83947285639982)))

    nnxor = o1

End Function

最後に,気づいたことと残された課題を箇条書きにして終わりにします。

»固定リンク

2008-03-20  全文検索システムの導入

SQLiteで実装した日本語全文検索機能をスキャンティ・システムに組み込むことにしました。

全体ブロック

<画像の説明>索引付けをいつするか悩みました。今回は「DBデーモン内のモジュール」として動作させることにしました。インデックサは投稿文のクローラとは非同期に動作します。

「ディメンション(dimension)」という機能ブロックの存在に気付いた人がいるかもしれません。いま方式を検討している新機能なのです。日付ディメンション(date dimension)と位置ディメンション(location dimension)の実装を予定しています。実現すれば時間軸方向および空間方向に伸張圧縮した解析ができるようになります。でも,そのまえにN gramベースの全文検索機能を載せる必要があったのです。

さて,未だにこのシステムの正体が分からない人がいるかもしれません。大別するとOLAP(OnLine Analytical Processing,オンライン分析処理)に分類されます。所詮,SQLiteに載せているので本格的なOLAPの足元にも及ばないとは思いますが,本格的になったときに備えて日々,実験を重ねているのです。

»固定リンク

2008-01-23  不正クリックされているようです

「不正クリック?何それ?」と思った人は,さっさとウィンドウを閉じてくださいね(なぞ)。以下,読んでも意味が通じないと思います。

コンテンツマッチ型のネット広告を導入した「ジューシィ」の続報です。どうやら不正クリックされているようなのです。サーバのアクセスログを見てみたら,短期間に同じIPアドレスから何度もクリックされた痕跡が残されていました。悪質なドキュンって底なしなのですね。金額は大したことがないのですが,これでは広告の意味がありません。

通報しないとだめかしら」と思っていたのだが,いつの間にかクリックされなくなりました。どうも問題のサイトへの広告配信が停止したようなのです。偶然なのか不正クリックが疑われる場合は規制が掛かる仕組みになっているのか,不明ですが,ひとまず危機は回避されました。

»固定リンク

2007-09-04  高速パスワード・デコーダ―その後―

高速パスワード・デコーダの続報です。あれから試行錯誤を重ねることで,94%のパスワードを解くことに成功しました。当初は,ぜいぜい8割も解ければよいと思っていたのですが,面白かったのでつい張り切ってしまいました。

ここで,ひとまずパスワードの解読を止めようと思います。これ以上は,ちょっとやそっとでは解けないことが分かってきたのです。これまでの解法をまとめて,システムに組み込むことにしました。

全体ブロック図

<画像の説明>スキャンティ・システム(STEP1-3)の全体ブロック図です。ソフトウェアの仕組みを他人に説明するのは至難の業ですので,どんな機能があって,それらがどのような関係にあるのか図にしてみました。なお,英単語のような文字の羅列が見受けられますが,適当な語を当てただけなので英語として正しいかどうかは知りません。ラテン文字が使われているからといって,何でもかんでも英語ってわけではありません(←強引な言い訳)。

説明を少々。パスワードの解析は4段階に分けることにしました。1段階では,約50%のパスワードを解くことができます。2段階に進むと約75%のパスワードを解くことができます。段階が進むに連れて,解ける可能性が高くなるようにしたのです(「必ず解ける」というわけではありません)。

また1段階ではデータ取り込み時に,2段階から4段階では「DB Demon」がパスワードを解読するようにしました。「demon(デーモン)」って何かというと,裏で動いているプロセスのことです。定期的に起動するようになっており,データベースの中身を更新していきます。「寝かせておくと情報の質が洗練されていく」という動作をするわけです。

»固定リンク

2007-08-16  高速パスワード・デコーダの開発

※この記事では,パスワードを解読する手順を述べています。肝心なことは書かないように配慮していますが,注意してください。

スキャンティ・システム,先月の下旬に全体計画を説明しました。その後,STEP3の実装物にあたるパスワード・デコーダの試作に成功しました。デコーダ(<英>decoder,解読器)の正体はパスワードの一覧表です。現在のパスワード・デコーダは,投稿文の9割を1件当たり0.4秒の速さで解読することができます(プロセッサ:Mobile Athlon XP-M 1800+,クロック周波数:1.2GHzの場合)。

パスワードの解読っていかにも怪しい感じがするのです。業界の人であれば「パスワードを解読するってよく聞く話だけど,実際どうやるの?」と思ったはず。今回,私はパスワードの解読を経て,さまざまな発見をしました。分かったことをすべて書いてしまうと安全上,重大な問題を引き起こしそうです。

そこで内容を吟味し,解読の手順,パスワードの全体傾向,パスワードの望ましい扱い方をお話しすることにします。

解読の手順

世の中に存在する「問題」には,簡単なものから難しいものまでいろいろとあります。パスワードの解読は「難しい問題」のひとつでしょう。なぜ難しいのか。数学的に解釈すると,パスワードの解読は「組み合わせ問題」です。組み合わせの種類は限られているので,「全部試してみればいいじゃん」と思うかもしれませんが,それは無理です。なにしろ試さなければならない数が膨大なのです。「100通り」であるとか「1,000通り」なんて可愛いものではありません。

仮にパスワードが8桁の数字だったとします。1億通りを試さなければなりません。さらに今回,扱うパスワードって,何桁なのか分かりません。全桁が数字とも限らないわけです。そうなると,組み合わせの種類の単位は「億」では済まなくて,「兆」や「京」がつく世界になります。現在のコンピュータはとても高速ですが,それでも簡単に解ける量ではありません。

さて冒頭で,「パスワードの解読は組み合わせ問題だ」とお話しました。たしかにそうなのですが,だからといってすぐに組み合わせを作るための処理の手順を考えたり,プログラムを作ってしまったりするのは早合点というものです。まずパスワードの性質を整理することにします。パスワードを解く鍵は,いつ,だれが,どんな場面で,どのようにして扱うものなのかを把握しておくことなのです。

――これからはすべて,パスワードは必ずしもデタラメというわけではなくて,何らかの規則性が存在することを示唆しています。しかしながら,あくまで仮説です。なんとなくそう思うだけです。どこまで有効なのか,まったく分からないわけですね。ところで,今回のように何から手を付ければ良いのか分からない問題の場合は,仮説を検証して新たな仮説を立てて,その仮説を検証して‥‥という作業の繰り返しになります。

パスワードの全体傾向

前節では「パスワードには何らかの規則性があるはず」という仮説を立てました。さっそく仮説を検証することにしましょう。

検証作業はなるべく簡単な方法を採用すべきです。ひとまず「4桁の数字」という足かせをして,実際にパスワードを解いてみることにしました。みんながみんな4桁の数字をパスワードにしているわけではないのでしょうけれど,何割かは解ける気がしたのです。「木を見て,森を見よう」というわけです。

パスワードが4桁の数字の場合,組み合わせは1万通りあります。今回は1万件の投稿文に対して解読してみることにしました。施行回数は最大で1億回です。実際には,パスワードが解けた投稿文は以後,解読の対象から外れますので施行回数はもっと少なくなります。それでも結果が得られるまで数時間掛かりました。

以下,結果発表です。

<画像の説明>4桁の数字を上位2桁と下位2桁に分けて,2次元平面上に頻度を描いてみることにしました。点の有無がパスワードの有無に対応します。点が多く集まっている個所と,ほとんどない個所があることが分かりました。対角線上に点が集まっていることに気づいた人がいるかもしれません。これらは「5555」や「7777」のような,ぞろ目の数字です。覚えやすくて,しかも入力しやすい数字の並びだと言えます。

<画像の説明>つぎに上位2桁と下位2桁の数字の出現頻度を,度数分布表にしてみることにしました。中央の目盛線と山の勾配に注目してください。上位2桁は偏りが大きく,下位2桁は偏りが小さいことが分かりました。なぜこんな結果が得られるのか。相変わらず生年月日をパスワードにしている人がいるからなのです。月は1から12,日は1から31。子どもが生まれる月は均一ではないので(真夏や真冬に生まれると育てるのが大変でしょ),パスワードもその影響を受けてしまっているのです。

<画像の説明>話は飛びますが,得られた結果から高速デコーダを作ってみました。画像は高速デコーダが出力するパスワードの候補関数の分布です。端折って説明すると,高速デコーダは図の左上の領域は丁寧に調べるけれど,右下はほとんど調べないという動作をします。現在の高速デコーダは,4桁から8桁のパスワードに適用できます。過去に解読したパスワードの一覧,ならびにパスワードの統計的な偏りを利用することで,高速にパスワードを解くことができます。

いま高速デコーダの性能を高めるための準備をしています。やるべきことはすでに見当がついていて,検証作業をしているところです。

パスワードの望ましい扱い方

最後に,破られにくいパスワードのお話をします。今回,解読したのはネット掲示板の削除パスワードなので,バレてしまったからといって実生活への影響はほとんどなさそうです。

ところで銀行のキャッシュカードの暗証番号も,携帯電話のロック番号も,mixiのパスワードも「全部同じ」なんて人はいませんか。そんな人は,掲示板の削除パスワードが解読されてしまっただけで,全財産が脅かされる事態になってしまうのかもしれません。以下,注意点をお話しますので,必要であればパスワードを変えてみてくださいね。私は刺されたいわけでもなければ,他人から呪われたいわけでもないのです。

――ちなみに「強力なパスワードがほしいけれど思いつかなくて困っている」という方は,「yumi-ii | パスワード文字列を作る」をお試しください。機械的なパスワードが得られます。携帯電話に辞書登録しておけば,複雑なパスワードでも簡単に呼び出すことができますよ。「パスワードをいくつも覚えられないから,つい同じパスワードを使ってしまう」という人は,パスワードを3種類くらい覚えて,サービスの重要度に応じて使い分けるという方法もあるようです。

»固定リンク

2007-06-25  エリス―その1―

「エリス(ELIS)」は現在,私が手がけている商品の開発名です。2007年8月の完成を目指しています。

エリスは個人向けのWebサービスです。エリスの肝は利用者管理です。「利用者がログインして何らかの処理後,ログアウトする」といった認証処理を含みます。私,今まで「ログインとログアウト」という仕掛けを手がけた経験がありません。あれこれ下調べに奔走しているのです。

認証と承認

よく「認証」であるとか「承認」という言葉を耳にします。どちらも似たような意味に感じていたのですが,だからといってどちらもはっきりとした意味を把握しておりませんでした。ここで整理しておきましょう。

エリスでは「承認」はありません。「管理者」「ユーザ」「ゲスト」という区別は存在しないわけです。あえていうなら,すべての利用者はユーザ権限です。

セキュリティ

「セキュリティ(<英>security)」とは,何でしょうか。ヨコ文字にしてしまうと意味が曖昧になってしまうのですが,ここでのセキュリティとは「あらかじめ決めたパスワードを知っている利用者だけが,サービスを使うことができる性質」とします。

実生活で喩えれば,鍵を掛ける行為と一致します。鍵にはいろんな種類があります。銀行の地下金庫からオートロックのマンション,物置の南京錠など,頼りになりそうな鍵から頼りない鍵まであるわけです。地下金庫と南京錠とでは,目指している安全性がまったく違うわけですが,インターネットの世界ではひと括りに「セキュリティ」と言ってしまっている気がします。(ゆえに話が噛み合っていない事例があるように感じます。)

エリスが目指すセキュリティは「南京錠型」です。強力な道具を使われると,壊されてしまう危険があります。しかし鍵の性能は,守らなければならないものの価値に見合ってさえいれば良いはずです。

現在,決まっていることを箇条書きにします。

Perl-Catalystによる認証

認証とCOOKIEを使ったセッション管理は,既存のフレームワーク(Catalyst-Plugin-Authenticationモジュール)で実装する予定です。すでにフレームワークの動作検証は済んでいます。

しかしながら,がありそうなのです。フレームワークって作者が想定したとおり(もっとはっきり言えばサンプルプログラムどおり)に使っているのなら,何の問題もなく動くことが多いのですが,ちょっと凝ったことをしようとするとたちまち機能不全に陥ることがあります。そもそもフレームワークの範囲内では,実現が不可能な動作も存在するのです。

気にしていることを挙げておきます。

»固定リンク

2006-11-20  クラスター分析ことはじめ―R言語によるシミュレーション―

「クラスター分析ことはじめ」の続報です。前回の話では「まずR言語でクラスター分析してみよう」ということになりました。この度,そのR言語で階層型クラスターを得ることができました。

注:R言語はもっぱら「R」って呼ばれるんですけれど,「R」だけだと何のことなのか分からないので「言語」をあえて添えています。

今回のお題

手掛けた問題を算数の文章題風に書くことにします。

便宜上,用語を整理しておきます。

MS-Excelでデータを用意する

領域と個体を表にしました。領域dの種類を列方向(横方向)に,個体iの種類を行方向(縦方向)に列記し,領域-個体に該当する値を入力しました。実際には手作業ではなくて表を機械的に作りました。

用意したデータの一部全体(容量注意)

<画像の説明>用意したシミュレーション用のデータの一部です。本番の1/10~1/20の規模です。セルの数値は指数形式になっています。

順位を付与する

領域ごとに個体に順位をつけました。以後は順位を元に解析を進めます。なぜそんなことをしなければならないのでしょうか。このあと個体間の距離を求めるのですが,距離を計算するときに発生頻度の数値を使ったのでは,おかしなことになるからなのです。

じつは領域は各々,規模が異なっており基準を合わせる処理が必要なのです。

順位を正規化する

式 ( r - 1 ) / N により順位を0~1に正規化しました。rは順位,Nは順位の総数です。ただし値が0の要素は特別扱いであり,順位の総数には数えないこととし正規化後は1とすることにしました。

正規化したデータの一部全体

<画像の説明>正規化したデータの一部です。

R言語でクラスター分析する

ようやくR言語の出番です。Excelで作成したデータをファイル保存し,R言語で読み込みました。以下のコマンドにより階層型クラスターを得ました。(R言語はWindows版を使用。バージョンは2.3.1)

library(stats)
x<-read.table("ファイル名",header = TRUE)
attach(x)
mat<-matrix(c(d1,d2,d3,d4,d5,d6,d7,d8,d9,
	d10,d11,d12,d13,d14,d15,d16,d17,d18,d19,
	d20,d21,d22,d23,d24,d25,d26,d27,d28,d29,
	d30,d31,d32,d33,d34,d35,d36,d37,d38,d39,
	d40,d41,d42,d43,d44,d45,d46,d47,d48,d49,
	d50,d51,d52,d53,d54,d55,d56,d57,d58,d59,
	d60,d61,d62,d63),nrow=66)
dis<-dist(mat,method="euclidean")
clus<-hclust(dis)
op<-par(ps=8)
plot(clus,INDIVIDUAL,xlab="",ylab="",sub="")
par(op)

コマンドは長々としています。もっと簡単にできるのかもしれませんが,まだ詳しく調べていないものでこれで勘弁してください。matrix関数は表示の都合で,本来1行で書くべきところを改行しているので注意してください。余談ですがWindowsの場合,ファイル名の指定に注意します。パスの区切り記号は,\ではなく\\を使います。

樹状図大きな画像

<画像の説明>得られたクラスターの樹状図です。縦軸の数値は個体間の距離(どれだけ似ているか)を表します。赤色の線はあとで付け足したものです。

今後の課題

大雑把にデータを作ったわりに,かなり期待どおりの結果が得られたと思います。しかしながら,まだまだ序の口なのです。検討しなければならないことがいくつかあります。

»固定リンク

2006-11-12  クラスター分析ことはじめ

いま某新製品の準備をしています。詳しい日程は決まっていませんが,来春から来夏あたりに投入できればよいなと思っています。今回のお題の中心(いちばん難しいところ)は「クラスター分析」です。

クラスター分析の正確な定義は知りませんが,「複数の個体から似たもの同士を発見する学問」のようです。その手の業界に足を突っ込んでいる人なら「ああ,あれね」(by 桜庭あつ子←知らない人いるかも)と思ったはずです(ふめい)。

具体的には,数千から数万の個体を階層化したいのです。階層を作るときにクラスター分析が必要というわけです。さて「個体,個体」ってたびたび言いましたが,個体って何のことなのか気になった人がいるかもしれません。扱う個体の正体はヒミツです。

いつものことですが,大学時代の研究とはまったく関係がありません。身近に相談できるような人もいません。大苦戦が予想されるのです。でも既存の技術を丁寧に調べて,実用化にこぎつけられればそれでよいので,道を踏み外さなければ大丈夫な気がします。

これからやることと「思っていること」を少々。

»固定リンク

2006-10-21  ジューシィ2―アフィリエイト崖っぷち―

「ジューシィ」は,アフィリエイトを収益源としたWWWサービスの開発名です。2005年12月下旬から1か月半を掛けて開発,運用を開始しました(現在も運用中)。

ジューシィのその後なのですが,話にならない段階にまで苦戦しています。WWWサーバの運用費分は稼いでいるし,更新は自動なので手間も掛からず赤字にはならないものの,さっぱり売上が伸びないのです。

このままでは,開発費用を回収するだけで何年も掛かってしまいます。アフィリエイトは儲からないって最初から知ってはいましたが,あまりの成績の悪さに「キィーーー」って感じなのです。(実際に「キィーーー」って言っているわけではありませんが←ふめい。)

今後のテコ入れのために問題点を整理しておきます。

サイトの特殊性と商品単価の低さ

WWWサイトというもの,知られていないものはだれも見ません。

ジューシィと似たような内容のサイトがいくつかあるのですが,どこも閑散としているように見えます。そもそも市場規模が小さいようなのです。

普通,アフィリエイトではサイトの内容と掲載する商品の傾向を合わせます。ジューシィの場合,商品単価がかなり低く,売れたとしても利益は1件あたり10円とか20円という世界です。単価が低くてしかも数が出ないのです。

これでは話しになりません。「参入する前に分析しておけよ」と言われてしまいそうなのですが,まったくそのとおりです。いやはや,後の祭りです。

広告配信の問題

ジューシィはPCサイトと携帯サイトのふたつを運用しています。利用数は携帯サイトの方が多いです。PCサイトの3倍くらいあります。

PCサイトの動向は予想の範囲内なので良いとして,問題は携帯サイトです。最初は好調な滑り出しでした。ところが,あれよあれよという間にクリック率が減少していきました。一体,何が起きたのでしょうか。調べてみたら利用者のほとんどがリピータでした。利用者が広告を見慣れてしまったらしく,クリック率が落ちてしまったのです。

リピータの存在はなんら悪いことではありません。まずいのは現在,使っている某社の広告配信システムです。利用者の嗜好を分析して,広告を取っ換え引っ換え配信し続けなければならないのですが,この嗜好の分析の精度が非常に悪いです。どれくらい悪いのか数値化できないくらい悪いです。私はいつも「このヘタレが」と文句を言っています。

アフィリエイトの問題というよりも某社のシステムの限界によるものなのだが,なんとかしたいものです。

今後の対応

»固定リンク

2006-09-20  サラサーティ2―その4―

サラサーティ2の作業を再開しました。なんだかんだ言って6か月間,作業を放置してしまいました。どうも状況が芳しくなかったので,しばらく寝かせてみることにしたのです。味噌や漬物ではありませんが放置しておくと,いい味が出せるものなのです。

時間を置いてみて,いくつか分かったことがあります。諸問題と解決方法の案を整理することにします。

ボトムアップの弊害

まず「設定項目が多すぎる」のをなんとかすることにしました。なぜ複雑になってしまったのでしょうか。しばらく原因に気づけなかったのですが,寝かせてみたら「ボトムアップの弊害なのかも」と気づきました。

サラサーティ2は古いものを土台に,あとから上部をくっつけた格好になっているのです。

サラサーティ2の前にはサラサーティ1がありました。サラサーティ1の前に,さらに原始サラサーティとも言うべき実装物が存在していたのです。サラサーティ開発の動機は,原始サラサーティの動作を表にしたりグラフにしたりして,見やすくすることですので当然といえば当然です。

原始サラサーティは,すでに1年以上の運用実績があります。当初は必要だと思っていたけれど,実際に使ってみたらいらない機能がちらほら。サラサーティ2から,そのいらない機能を取り除き簡略化を図ることにします。

誤った操作に対する耐性の向上

「壊れにくくすること。壊れても修復しやすいこと」をより意識することにします。従来は内部状態が壊れたまま,ずるずると使い続けられるようになっていました。

いちばん気になっていたのは,レコードの識別値にMD5(Message Digest Algorithm 5)を使用していたことでした。MD5の詳しい説明は省略しますが,「3434EF0BCD678D56E9AB78915ACF0122」みたいな文字の羅列を識別値にしていたのです。

一意な値を作るのに便利だったのですが,元のデータが変わると識別値もコロっと変わってしまう性質がありました。元のデータを変えるという操作は通常ではありえないのですが,途中で書き換えられた方が便利なこともあり,そのままにはできなくなりました。

そこで識別値をMD5ではなくて,時間由来の連番値に置き換えることにしました。

ActiveXを積極的に導入

Macintoshプラットフォームの完全な切り捨てを意味します。

ActiveXとはWindows特有のソフトウェアの再利用技術です。当初はMac対応を前提としており,ActiveXを一切使わないで開発を進めていました。ところが後々の調査でMac版のExcel VBAは(Windows版と比べると)性能が低く,関わっていると生産性を損なうことが分かりました。

Mac版のExcelをもっと早い段階で分析しておくべきでした。反省しています。

»固定リンク

2006-08-22  ウィスパー3―その5―

ウィスパー3,ただいま試作品(α版あたり)を運用しています。またしてもいろんな問題に遭遇しています。いずれもDBの問題です。

性能が出ない

DBの性能がどうも出なくて困っています。要件では「要求してから応答するまでの時間は3秒以内であること」としています。実際,このとおり動いているのだが,どうも使ってみるとスカッとした使い心地ではないのです。

容量の効率を犠牲にすれば高速化できそうなのですが,そうなると下位サービスを修正しなければいけません。でもすでに稼動しているものを修正するのは嫌なのです。だからといって,このままでいいのかと言うとそれも不満で,両者の板ばさみに遭っております。

特定のクエリで全抽出が発生

ここでの全抽出とは,レコードを抽出する際の条件が機能せず,すべてのレコードを出力してしまう状態を指します。

いろんなクエリを投げてみたのだが,さっぱり応答が返って来ないクエリがあることに気づきました。原因は察しが付いています。特定のクエリでは,抽出条件が空になってしまうはずなのです。全体件数は数百万件あるので,それらをすべて出力しようとすると,とんでもないことになるのです。

この動作は仕様漏れです。仕様はこれから考えることにします。

システムを階層化することの難しさ

諸問題は,ウィスパー3がウィスパー2を土台にしたサービスであることに因ります。ウィスパー2とウィスパー3はDBを兼用しているのです。

実際に稼動させてみると,何やらかみ合わせの悪い歯車のようでお世辞にもうまく行っておりません。ウィスパー2ができた当初,ウィスパー3の仕様はほとんど白紙の状態でしたので後々,不都合が起きるのは当然という気がします。

DBを兼用せずに,独立させるのもひとつの手ですが,そこまではしないつもりです。今の段階では最適ではないというだけで,致命的な不都合は発生していないのです。

私,RDBMSと呼ばれるものを使い始めてまだ日が浅いのですが,この業界はかなり奥が深いと思います。深いどころか底なしなのかもしれませんね。

»固定リンク

2006-07-24  ウィスパー3―その4―

ウィスパー3の開発,ようやく終盤戦になってきました。読んでいる人はたぶん一人か二人だと思うので説明がいい加減になってしまいそうですが,はりきっていきましょう。

差の扱いを変更

大掛かりな仕様変更をしました。式の書換えを考えているうちに,どうも現状の仕様ではうまく処理できないことに気づいたのです。

問題は「差」の扱いでした。いままで式が云々という話を散々してきましたが,最終的に何が出力されるのかというと,SQL文が出てくるのです。SQLではそのまんまEXCEPTという演算子が「差」の意味なので,素直に関連付けられると思って何の疑いもなく「差」という演算子を考慮していました。

ところがどうも論理積,論理和,否定で式を処理するのが理に適う気がしてきました。論理演算で差のようなものは,論理積(∩)と否定(¬)で表すことができるはずだからです。そこで「A-B」があったとしたら「A∩¬B」とすることにしました。

書換え規則

論理積(∩),論理和(∪),否定(¬)で表した式をなるべく短くする規則を考えました。以下は書換え規則の一覧です。

入力出力備考
X∪XXR1
X∩XXR2
X∪(X∩Y)XR3(未実装)
X∩(X∪Y)XR4(未実装)
(X∩Y)∪(X∩Z)X∩(Y∪Z)R5(未実装)
(X∪Y)∩(X∪Z)X∪(Y∩Z)R6(未実装)
φ∪XXR7
φ∩XφR8
X∪¬XXR9
X∩¬XφR10

※φは空集合

論理演算の教科書に載っている公式とよく似ています。一部はまったく同じです。おそらく見たことがある人もいると思います。

現在,実装しているのはR1~R2,R7~R10です。R3~R6は実装していません。仕様上,存在するだけです。たぶん出現頻度が低いからです。稼動させてみて頻発するなら実装するつもりです。式の書換えは実行効率をよくするためのものなので,抜けがあっても致命傷にはなりません。

式の書換え

書換え規則を並べてみたところで,これを実際にやるにはちょっとした工夫が必要です。人間の脳みそで考えると「こことここが一緒だから,まとめられる」とか「消せる」と式を見ただけで気づくのですが,現在のコンピュータではそうもいきません。

式は2分木で表しているので,実際にやることは木の枝を切ったりノードを付け替えたりすることです。2分木を使わない方法もありそうですが,思いつきませんでした。

最初に照合元のノード(書換え規則の一覧でいう変数X)を選びます。つぎにX以外のノードについて,おのおの書換え規則と一致するか照合していきます。一致するノードを見つけたら書換え規則に沿って木を書き換えます。

動作概要

<画像の説明>R2の適用例です。例にしては簡単すぎるのですが,図がないとさっぱり意味が分からないのでつけました。

問題はパターン照合の手間です。今回は「式の長さは最大15項」という制限があるので,木はそれほど大きくなりません。実用的な速さで解けるのですが,どうも小奇麗じゃない気がします。本当にこれで良いのかというと腑に落ちないところがあります。

»固定リンク

2006-07-12  ウィスパー3―その3―

だんだんと小難しい話しになってきました。廃刊になったOh!Xに載っていそうな内容になってきましたが,気にしないでください。

式の表現

前回は字句解析と構文解析により,式を表す文字列を因子(<英>factor)に分解しました。もちろん,ただバラバラにしただけではだめです。コンピュータで「式」として扱えるように,なんらかの決まりに則ってデータを格納しなければなりません。

今回は2分木で式を表すことにしました。この方法は定番中の定番です。ちょっと厚めのアルゴリズムの教科書になら,必ず載っています。

A+B-C*D(後置記法ではAB+CD*-)の2分木表現

<画像の説明>A+B-C*D(後置記法ではAB+CD*-)の2分木表現。

本来なら2分木の性質や,木を組み立てる前に中置記法で表した式を後置記法に変換する方法にも触れた方がよいのでしょうけれど,細かな説明は省略することにします。業界の人であればだいたい察しが付くはずなのと,目眩がしそうな話しなのでやっぱり触れないでおきます。

BNodeクラスとFactorクラス

データ構造のお話しです。今回は2分木を表すためにBNodeクラスを導入しました(BNodeのBにはBinaryという意味を込めています)。また因子を表現するためにFactorクラスを導入しました。

BNodeクラスならびにFactorクラスには,等価判定とオブジェクトをコピーするための便利なメソッドを付けました。「妙にJavaっぽいな。実装はPerlなんですよね?」と思った人がいるかもしれません。それは何かの錯覚でしょう(ふめい)。

BNodeクラスとFactorクラス

<画像の説明>クラスの定義のようなものです。Microsoft Visioでちょこちょこっと描いてみました。

余談ですが,BNodeのvalueはFactorオブジェクトでなければなりません。クラス間の結びつきが強すぎるのかなと思いましたが,BNodeは汎用的なクラスではないので今回は「良し」としました。

宿題の進み具合

»固定リンク

2006-07-01  ウィスパー3―その2―

今回のお話は,役に立つ人がいそうなので詳しく書きました。意味が分からない人には,怪しげな暗号のように見えるかもしれませんが,気にしないでください。

Perlでyaccを使うには

今回はkmyacc(多言語対応LALRパーサー生成系)を使わせていただきました。kmyaccはPerlにも対応しているのです。

kmyaccを使うには,まずソースファイルをコンパイルして実行ファイルを得なければなりません。WindowsではCygwin環境(Windowsで動作するUNIX系OSの擬似環境)を導入してmakeすれば,実行ファイルを得ることができます。

私,Perlのyacc以前に,素のyaccをまともに使ったことがありませんでした。参考書としてオライリーの「lex&yaccプログラミング」のお世話になりました。いつもの動物本シリーズです。

この本に書かれている例はC言語なのですが,今回使う処理系はPerlです。Perlのお約束と照らし合わせるのにやや苦戦しました。最初はまったくわけが分からなかったので,Cのyaccをまず使ってみて,Perl版との相違を調べることからはじめました。

kmyaccを使ってみて,気づいたことを箇条書きにします。

詳しくはkmyaccのサンプルプログラムを見れば分かるはず。

ちなみに「Perlのyaccがあるのは分かったけれど,Perlのlexは何処に?」と思った人がいるかもしれません。Perlのlexはどうもなさそうです。今回は字句の解析を自前ですることにしました。

どこまでが字句解析で,どこまでが構文解析か

以下は字句と構文の一般的な話です。kmyaccの話ではありません。

作ってみて,役割分担が曖昧になってしまうのが気になりました。

例えば「1 AND 1」を還元する式を考えてみます。数値と演算子の間には「空白」があるので(また空白で区切らなければいけない,という決まりにしたので),構文は「NUMBER SPACE AND SPACE NUMBER」としても良さそうだし,空白(SPACE)を前処理で取り除いて「NUMBER AND NUMBER」としても良さそうです。

最初は前者の方法を採用していました。でも「空白が2文字以上続いた場合」「前後と末尾に空白がある場合」なども字句と構文で意識しなければならなくなってしまって,どうも「これではうまくいきそうない」と思いました。

参考書(前出の動物本)を読んでみたところ,空白は字句解析の前に処理してしまった方がよいのだそうです。処理手順は「字句解析」「構文解析」の2段階でよいのかと思ったら,どうも字句の解析の前にもう1段階必要だったのです。

文脈の保持

文脈をどうやって扱うのか悩みました。

仮に「2006」という文字の並びがあったとします。これを数値として解釈させるのか,文字列として解釈させるのか,はたまた日付として解釈させるのかは,前後の文脈に依るわけです。

字句解析のコード中に,文脈を保持する変数を導入して,値で場合分けしたらうまく書けました。

今後の課題

以前もお話しましたが,ウィスパー3では集合演算をDB中のレコードに適用します。まだまだ未解決の問題が山積みなのです。

関連リンク

»固定リンク

2006-06-23  ウィスパー3―その1―

ウィスパー3は,ウィスパー2の上位層に位置するアプリケーションです。ウィスパー3の肝は「表の集合演算」と「字句と構文の解析」です。まだ要求仕様と実装仕様のどちらも,はっきりしていません。

表の集合演算

ウィスパー3で定義している集合演算の種類はみっつです。各々,演算子として「+(和)」「*(積)」「-(差)」を使うことにします。例えば以下のように集合A,B,Cがあるとします。

A = { a, b, c, d, e, f }
B = { a, c, d, f }
C = { f }

このとき「A * B - C」は{ a,c,d }です。

(注意:上の例はあくまで考え方を説明するためのものであって,実際にABCやabcdefが出てくるわけではありません。以後もそうです。)

何をやりたいのかというと, SQLのSELECT文で抽出したレコードに対して集合演算したいのです。いったいどうすればよいのでしょうか。

テンポラリテーブルを使った方法

最初に実験したのは,すべて2項演算にしてしまうことでした。A * B - CだったらA * B → Zとして,まずZを求めます。つぎにZ - Cを計算して解を得ます。原理上どんなに長い式でも扱えますし,1回計算するごとに式が短くなるので,数学的に扱いやすいと思いました。以下は擬似コードです。

Clear() ;
Calculate( A ) ;
Calculate( B, 'AND' ) ;
Calculate( C, 'EXCEPT' ) ;
Result() ;

(偶然にも命令文の並びは,電子式卓上計算機を操作する手順と似ています。)

2項演算の結果Zは,どこかに残しておかなければいけません。前の計算結果を知らなければ,つぎの計算ができないからです。テンポラリテーブルを作って,途中の計算結果を格納することにしてみたのだが,この方法には問題がありました。

式が長くなると演算回数も増えるので,目に見えて遅くなってしまいました。レコードが数万件のとき,5項の演算で遅い感じがして,15項を超えると使い物にならないという気がしました。要求仕様では,現実的な速さで最大15項の演算ができなければいけません。どうやら考え方が「素直」というだけでは,役に立たないようです。

なぜ遅くなるのでしょうか。項数が増えるとテンポラリテーブルの作成と破棄を何度も繰り返してしまうのと,途中計算のために使いもしないレコードを保持しなければいけないのが原因だと思いました。テンポラリテーブルは1回の演算で使い捨てるので,インデックスとの相性が悪そうなのも気になりました(正確にはインデックスをつけたときの性能を調べていないので不明)。

差の演算回数を1回にした方法

テンポラリテーブルをなるべく使わないで計算する方法を考えたいと思います。以下の案はこれから実験します。

ひとつ目は,例えば「SELECT … WHERE p = α OR p = β AND p = γ AND p = δ」のように,和と積を多項演算してしまいます。

残りのふたつは,同じことを言っています。この方法では,差の演算回数が1回しかありません。仮に「A + B - C - D」という式があったら,変形して「(A + B) - (C + D)」としてしまうのです。

さて何の気なしに「式を変形して」なんて言ってしまいました。コンピュータの世界でこれをするには,まず文字列を字句解析して「演算子」「シンボル(演算されるもの)」に分けなければいけません。つぎに字句の並びを決められた構文に当てはめて,「式」として解釈させなければいけません。簡単にできそうな気もしますが,難しい気もします。

何やらこの先とんでもないが待ち構えていそうです。

»固定リンク

2006-06-17  ウィスパー2―その5―

ウィスパー2の開発記録,今回が最終回です。

解決した問題点

運転計画の関数を修正

ウィスパー2には時刻に応じて,サーバホストに掛かる負荷を調節する機能があります。計画段階では時刻を離散値で計算する予定でしたが,連続値で処理することにしました。ただ1次関数で近似しただけですが。実際に動かしてみると適切というか,つなぎ目がなくて滑らかになりました。

運転計画関数の出力値

<画像の説明>ウィスパー2で使っている運転計画関数の出力値。上が離散値,下が連続値による算出結果。

ウィスパー3の一部を先行

ウィスパー2の作業は6月末までやるつもりでいました。ちょっと開発を急ぐことにして,6月中にウィスパー3の一部も実装してしまうことにしました。

»固定リンク

2006-06-06  ウィスパー2―その4―

DBに試験用のデータを挿入し終えました。ただいま運用時とほぼ同じ環境で,動作検証しています。いつものように,わけの分からない現象に遭遇しています。

運用サーバの性能に難点

実際に運用するサーバで動作試験してみました。思ったほど性能が出ないことが分かったので(開発環境の1.5倍速程度),高速化を図ることにしました。

初回起動直後のクエリに時間が掛かる

DBの容量増大に比例し,DBファイルを開いた直後に発行するクエリに時間が掛かるようになりました。しかも悪いことに減速の度合いは,O(N)ではなくてO(N^2)のように感じます。どういうことかというと,だんだんと遅くなるのではなくて,坂道を転げ落ちるかのように急激に遅くなっていくのです。

遅いのは最初のクエリだけで,2回目以降のクエリは高速です。またDBファイルを開く回数が2回以上のときは,クエリの発行回数に係わらず,どのクエリも高速でした。

この問題は,ディスクキャッシュの影響で発生していると推測しています。回避する方法があるのかないのか,いまのところ不明です。

UNIQUE制約でエラー

DBのテーブルには,「諸条件を満たさないレコードが挿入されようとしたらエラーを返す」という制約をつけています。変なレコードが挿入されて,DBが壊れるのを防ぐためです。

ウィスパー2の一部のテーブル(のカラム)には,UNIQUE制約をつけているのだが,試験運用中に何度かこの制約に引っ掛かり強制停止してしまいました。

テーブルにつけている制約は,実際には未使用です。上位層(アプリケーション側)で重複を調べているので原理上,発生しないエラーのはずなのです。なぜ発生したのでしょうか。「レコードは存在しないけれど,その存在しないレコードのためのインデックスは存在する」みたいな状態になっていたらしい。(詳細な分析はしていないので正確な原因は不明。)

高速化のために同期機能を切っていたのが原因だったようです。DBアクセス中に何度かCTRL+Cで中断していたのだが,あれはやっぱりやってはいけないことだったようです。CTRL+Cを控えるようにしたら,エラーが出なくなりました。

ドキュメントには,同期を切った状態でアプリケーションがクラッシュしてもDBは壊れないと書かれていたのですが,どんな動作を「クラッシュ」としているのか細かく書かれていませんでした。CTRL+Cは想定外のクラッシュなのかもしれません。あるいはOSによって挙動が違うのかも。

»固定リンク

2006-05-27  ウィスパー2―その3―

DB層のクラスライブラリはだいたい完成しました。ただいまDBに試験用のデータを挿入しています。かれこれ30時間くらい処理しているはずなのだが,一向に終わる気配がありません。いったいいつになったら終わるのでしょうか。いかんせん試作品なもので,あとどれくらい残っていて,いつ終わるのか表示する機能をつけていないのです。

いつものことですが,量が多すぎて困ってしまいます。途切れることなくディスク・アクセスしているので,HDDが過労で突然死するのではないかと心配してしまいます。(HDDは不定期に交換しているので大丈夫だと思いますが。)

さて「その2」からの進展具合を少々。

なにやら順調すぎますね。どこかに罠が仕掛けられているのかもしれません。いつもの勘です(ふめい)。

»固定リンク

2006-05-21  ウィスパー2―その2―

ドキュン生活中盤戦,ただいま作業しているのは「ウィスパー2」のII(DB層)です。先週は混沌とした状況でしたが,細かく分析してみたら「すべきこと」が明らかになってきました。

クラスライブラリ

まずクラスライブラリを整備することにしました。DBとDBを使うアプリケーションとのインターフェイスをどうしようか悩みましたが,アプリケーションからはオブジェクトを介してDBを使うことにしました。

オブジェクトを生成してメソッドをがちゃがちゃ呼び出すだけで,DB内のデータを追加・更新・削除できるようにするわけです。

方針は「便利に使えること」を優先するものとします。「アプリケーションからDBの存在を完全に隠蔽する」という考え方もありそうですけれど,DBを隠す必要など最初からないのと,懲りすぎると性能が出なくてハマる気がするので軽く使うことにします。

Perlでオブジェクト指向プログラミング

PerlでOOPです。「ジューシィ」のとき部分的に導入したのですが,ウィスパー2ではもっと積極的に導入することにしました。

Perlでは「@ISA」や「bless」といったキーワードを使って,継承やクラスとクラスのメンバの関連付けをします。

気になったことを少々。

SQLのトリガ文

トリガ(TRIGGER)は,ある表のある列が追加・変更・削除される前,あるいはされた後,自動的に実行させるSQL文らしいです。表の整合性を保つために使うと便利そうです。

いままでトリガを使ったことがありませんでした。今回,初導入です。どうなることやら。

関連リンク

»固定リンク

2006-04-24  ジューシィ2―その6―

運用中に気づいたことがあったので,またまた手直ししました。

携帯サイトの対象ユーザエージェントを追加

つぎのユーザエージェント(User Agent)を携帯サイトにリダイレクトすることにしました。以下UA名とUAの概要。

.htaccessを修正

ジューシィ2では機種判定を二段階に分けています。まずApacheのMOD_REWRITEを使って,携帯電話やPDAでアクセスしたときは携帯サイトに無理やり誘導します。つぎに「DoCoMo」「AU」「Vodafone」「ほか」のよっつに分けてページ容量と文字コードを変えてページを出力します。

今回の変更は機種判定の第一段階目のみです。.htaccessファイルを修正しました。以下コードです。

RewriteEngine on
RewriteCond	%{HTTP_USER_AGENT} DoCoMo	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} KDDI-	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} UP\.Browser	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} J-PHONE	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} Vodafone	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} MIDP-	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} DDIPOCKET	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} WILLCOM	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} KYOCERA	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} Mozilla/3	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} "jig browser"	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} "PlayStation Portable"	[NC,OR]
RewriteCond	%{HTTP_USER_AGENT} NetFront	[NC]
RewriteRule	!mobile	http://www.example.com/mobile/ [R,L]

余談ですが「REWRITE(書換え),CONDITION(制約),RULE(規則)」というのは,グラフ理論の業界で見かける学術用語だった気がします。

気になることをまとめて

関連リンク

»固定リンク

2006-03-28  CANDY☆GIRL JAPAN(仮称)

これからある携帯サイトの実験的な試みをしてみようと思います。

ミカのCANDY☆GIRL JAPAN

「ミカちゃん」とは紙媒体による宣伝の実験です。紙媒体という言い方をすると聞こえが良いのですが,早い話がピンクチラシです。チラシをいろんなところにばら撒いてみて,どれほどの効果があるものなのか検証します。

事の発端は「ジューシィ2」の不調にあります。どうもインターネットだけの宣伝では不足であり,ほかの媒体にも手を広げなければならない気がしてきたのです。なおミカちゃんはあくまで実験です。ミカちゃんとジューシィ2には何の関係もありません。

CANDY☆GIRL JAPANの試作品

<画像の説明>チラシの試作品です。無味乾燥なチラシに見えるかもしれませんが,実際のチラシではミカちゃんの一言を手書きにして柔らかい雰囲気にします。

検証内容と予定

チラシにより大雑把に検証したい内容を以下に挙げます。

「CANDY☆GIRL JAPAN」はシリーズ化されており毎号ミカちゃんの一言が違います。4月号から7月号の予定を少々。

ミカちゃんのプロフィール

仮想人物の設定を挙げておきます。仮想人物の人格を固定しておかないと,一貫した仕上がりにならないのです(そういう問題ではない気がしますが←なぞ)。

»固定リンク

2006-02-27  ジューシィ2―その5―

ジューシィ2の作業は2月上旬で閉じたのですが一部を手直しすることにしました。携帯サイトで問題が出たのです。

「徳」の旧字が文字化け

「徳」の旧字(Unicode 0x5FB7)が文字化けすることが分かりました。「どうしてかな」と思って調べてみたらSHIFT-JISでは表現できない文字だったのですね。UTF-8からSHIFT-JISに変換できないのが原因でした。なんでも「容易に解決することができない既知の問題」なのだそうです。⇒ http://support.microsoft.com/default.aspx?scid=kb;ja;JP170559

さてどうするか考えました。

キャッシュコントロールの挙動を変更

HTTPの応答ヘッダで「Cache-control : no-cache」を送るようにしました。この応答を解釈できるブラウザはページをキャッシュしなくなります。

いままでキャッシュ制御していませんでした。試用段階ではキャッシュ制御しなくても使い心地が悪いとは思わなかったのだが,日常的に使ってみると違和感がありました。

ページ容量を変更

1ページの最大容量を縮小することにしました。私が所持している携帯電話(au)の都合なのですが,どうも最大容量ぎりぎりにしてしまうと表示に時間が掛かってイライラしてしまうのです(オラオラではありません←ふめい)。

auのEZwebは絵文字が多いと,表示に時間が掛かる気がします。仕様上,絵文字はローカルリソースの画像として扱っているようなので処理が嵩むのかもしれません。

»固定リンク

2006-02-04  ジューシィ―その4―

「ジューシィ」後半は携帯サイトのお話です。すべての機能の実装,公開作業が終わりましたので今回でジューシィのお話は最後です。

動的サイト

ジューシィ携帯版は動的サイトにしました。一般にCGIスクリプトを使ったサイトのことを動的サイトと言います。

試作品では静的サイトだったのだが,どうも作り難いなと思いました。理由はいくつかあります。各社の携帯電話に対応しなければならなかったのと,最短で15分おきに内容を更新しなければならなかったからなのです。でもいちばんの理由は,静的サイトではうまく広告に視線誘導させることができなかったからです。

ページ容量

標準2KB,最大5KBとしました。DoCoMoが推奨しているページ容量と同じです。最近の機種は100KBまで扱えるそうですが,機種を細かく場合分けするのは大変ですし,1ページの文章量が多すぎると読むのが大変になってしまいます。そこで5KBに統一してしまうことにしました。

auとVodafoneはおのおの推奨容量が違うのですが,DoCoMoより5KB多いくらいで大きな違いはありません。

キャッシュの導入

携帯サイトのひとつの山は,ページの分割処理ではないかと思います。携帯サイトでは普通,情報を小分けにして出力しなければなりません。1ページが長すぎると容量過多で受信そのものができなかったり,読む人がうんざりしたりしてしまうからです。

「ページを分ける」というときに,全体を作ってから一部分を切り出すのか,全体が分からなくても一部分を切り出すことができるのかで,性能が大きく違います。(後者の方が性能面で有利です。)

今回の場合,全体を作らなければ一部分を切り出すことができませんでした。このままではいわゆる「重いスクリプト」になってしまいアクセスが増えると500番台のエラーが発生して,サービスが停止してしまう心配がありました。

そこで全体量の計算結果をキャッシュすることで,再計算の回数を減らす工夫をしました。キャッシュ導入以前,実験環境ではひとつのリクエストが完了するまで2秒掛かっていました。キャッシュ導入後は1秒以下になりました。作戦,大成功だったのです。

»固定リンク

2006-01-09  ジューシィ―その2―

SQLiteを導入

ジューシィは6時間おきにあるデータを再計算し,HTMLファイルを出力します。いまのところ機能はそれだけですが,将来は何らかのサービスを追加したいと思います。またDB中のレコードは日々,増え続けるため定期的に古いレコードを削除しなければいけません。

いままではデータの管理にBerkley DBを使っていましたが,SQLiteに替えることにしました。「今後の拡張のためにもSQLで操作できるDBを導入した方がよい」という判断をしたためです。

SQLiteはデーモンプロセスが不要なDBです。ひとつのDBはひとつのファイルで完結します。Microsoft Accessが扱うDBのファイルに「mdb」ってありますけれど,あれと発想は同じようです。

SQLiteの第一印象

相変わらず苦戦中

SQLでも何でもそうですが,しばらく使っていないと忘れてしまうものです。

表を正規化したら,いつつの表に分かれました。DBに表を追加したまでは良かったのだがその後,思考が止まってしまいました。表にレコードを追加するときにサブクエリが必要だったのだが,どうやってSQL文を書けば良いのか分からなくなってしまったのです。

それでもレコードの追加をなんとか終えたのだが,今度は表の結合という最大の難関にぶちあたりました。私どうも表の結合が苦手なのです。いつつの表に用事があったのだが,それらをどうやって組み合わせるか悩んでしまいました。

まず複数のサブクエリが出力した複数の表を結合してみたのだが,とっても性能が悪くなってしまいました。どうやらサブクエリの結果はキャッシュされないようです。結果的にいつつの表を立て続けにガチャガチャ内部結合すれば良いだけでした。いやはやヨコ漏れです。

この先どうなることやら。もちろん何とかしますが(なぞ)。

»固定リンク

2006-01-09  ジューシィ―その1―

2005年12月下旬よりサラサーティの開発をお休みしています。替わりに複線の商品を開発しております。11月ごろに思いついたネタです。開発名はなかったのですがさっき決めました。開発名は「ジューシィ」です。

はじめは「ゴージャス」という名前にしようと思いました。でも名前負けすると困るのでやめにしました。勉強嫌いな「マナブ」くん,軟弱な「ツヨシ」くん,恵まれない「メグミ」さんのようではあまりに惨めです。

ジューシィの特徴

アフィリエイトは儲からない

ジューシィは昨今,流行りのアフィリエイト(<英>affiliate)を導入したウェブサービスです。(ここではアフィリエイトの詳しい説明は省略します。興味のある人は自分で調べてみてください。)

アフィリエイトというのは,簡単にさまざまな商品を取り揃えることができる反面,収益性は高くありません。簡単であるがゆえに効果もそれなりなのです。一般的なバナー広告の場合,クリック率は0.3%だそうで(3%ではありません)購買に結びつくのはもっと低い確率でしかありません。

早い話がアフィリエイトは儲からないのです。ジューシィではアフィリエイトの特徴を考慮し,利用料金の安価なサーバで大量のアクセスを裁けるように工夫しています。サイト立ち上げとその後の運用に余計な費用を掛けてはいけません。

現在の課題

ジューシィにはPC向けサイトと携帯サイトのふたつがあります。すでにPC向けのサイトはほぼ完成しております。一部の自動化と携帯サイト構築のための調査,設計,実装作業を終えればジューシィの開発はオシマイです。

まだある課題を箇条書きにします。

»固定リンク

2005-12-19  サラサーティ2―その2―

いろいろ困っています。本当に困っているかどうかはさておき(なぞ)。

Excel2004 for Macにも未対応

Excel2004 for MacのVBA(VBE)もWindowsのExcel97相当なのですね。

ヨドバシの展示機でExcel2004 for Macを弄ってみました。ヘルプにenumが存在しなかったのでまず間違いありません。「Excel2003相当になっているのでは」と期待していたのですが,まったくの見当違いでした。

こうしてサラサーティは晴れてMac非対応となりました。

【追記 24 DEC 2005】Excel 2004のApplication.VBE.Versionを調べてみました。値は「5.0」でした。Excel v. Xも5.0ですので,やっぱりExcel v. XとExcel 2004のVBEは同じものです。

キャッシュが不整合

サラサーティ2ではExcelシートとオブジェクトの変換層にキャッシュを設け,高速化を図っています。どうもこのキャッシュが挙動不審で困っています。Excelブックの読み込み直後と,そのあとでキャッシュの整合が取れていないようなのです。

状態遷移の作り込みが甘いのだと思います。

Excelの仕様に遭遇

TabStripコントロールのchangeイベントハンドラ内で「時間の掛かるある処理」をするとExcel2000が強制終了してしまいました。Excelのバージョンによって動作に違いがありExcel2003では発生しませんでした。

これはExcel2000の仕様なのだと思います。仕様どおりできているのなら,その動作はバグではないのです(ふめい)。どう対処するか考えました。

»固定リンク