Haitena だいありー RSSフィード

May 23(Sat), 2009

L-System #1 - NodeBox

|

今回はL-Systemの第1回.果たして何回まで続くのか……


参考

公式:NodeBox | L-system

Wikipedia:L-system - Wikipedia

その他,いろいろ(解説はけっこう充実している)

とにかく,自分で何か描いてみるのがイチバン!


L-Systemと言えば,木

……なんだけれど,パラメトリックL-Systemの置換規則は直感的に分かり難い.

なので,セグメントが描かれる順に番号をふってみた.

colorsライブラリにも依存します.segment関数は関数外部にも依存する.

size(450, 450)

colors = ximport("colors")
clr = colors.rgb(0.1, 0.095, 0.075)
p = rect(0, 0, WIDTH, HEIGHT, draw=False)
colors.gradientfill(p, clr, clr.lighten(0.25))

lsystem = ximport("lsystem")

count = 0
def segment(length, generation, time=None, id=None):
    global count
    count += 1
    font("Helvetica", 20)
    colors.shadow(dx=10, dy=10, alpha=0.45, blur=4.0)
    fill(0.9, 0.9, 0.9, 0.4)
    push()
    stroke(0.9, 0.9, 0.9, 0.4)
    line(0, 0, 0, -length)
    scale(0.65)
    push()
    rotate(90)
    translate(length*2, length/2)
    arrow(-length, -length/2, length/1.5)
    translate(-length*2, length/2)
    rotate(-90)
    fill(colors.gold())
    text(count, -length/0.95, -length/1.8)
    pop()
    pop()

tree = lsystem.create(angle=45)
tree.segmentlength = 120
tree.segment = segment

tree.rules["1"] = "F[-1]F[+1]1"
tree.draw(WIDTH/2, HEIGHT, 2)

で,こんなのが出力される.

f:id:moch-lite:20090524031307p:image

さらに,tree.drawの数字を2から4にすると……

f:id:moch-lite:20090524031418p:image

これ以上再帰させると数字が読めなくなる.本当は再帰に合わせてフォントサイズ・位置もアジャストしないといけないんだけれども.

tree.rules["1"]に設定する置換規則を変更してやれば,いろんな図形を描画出来る.

木っぽくするにはセグメントを変更して,アングルは20〜26°くらいに設定すればよいはず.

ちなみに,数字の表示位置や矢印の大きさは微調整したため分かりにくい値になってます.

May 10(Sun), 2009

カラー1 - NodeBox ――の続き

|

カラー1 - NodeBox - Haitena だいありー

の続き.

上では,previewやswarmといった既存メソッドを使ったけれど,この関数に似た描画をする関数を自作してみた.ちなみにpreviewではsize()に合わせた描画は出来なかったけれど,自作版ではその辺配慮してみた.色テーマの取得は前回同様.


自作関数による色テーマの描画デモサンプル

f:id:moch-lite:20090510092307p:image

import math as m
def demo_colors(clr_list,
                n=int(m.floor(3*m.sqrt((WIDTH+HEIGHT)/2))),
                colorbar=None):
    sz = min(WIDTH, HEIGHT)
    div = 2.4
    div_extra = div if not colorbar else div/0.6
    for i in xrange(n):
        r = random(sz/20, sz/10)
        coord_x = WIDTH/2 + random(-WIDTH/div, WIDTH/div)
        coord_y = HEIGHT/2 + random(-HEIGHT/div, HEIGHT/div_extra)
        clr1 = choice(clr_list)
        fill(clr1.r, clr1.g, clr1.b, random(0.5, 1.0))
        oval(coord_x-r, coord_y-r, r*2, r*2)
        r *= random(0.6, 1.0)
        clr2 = choice(clr_list)
        fill(clr2.r, clr2.g, clr2.b, random(0.5, 1.0))
        oval(coord_x-r, coord_y-r, r*2, r*2)
        
    if colorbar:
        x = y = 0
        w = h = sz/10
        for c in clr_list:
            push()
            translate(w/2, HEIGHT-(h*1.5))
            fill(c)
            rect(x, y, w, h)
            pop()
            x += w

# main
size(300, 200)

web = ximport("web")
themes = web.kuler.search("sea")

clr = ximport("colors")
sea = clr.list(themes[0])

background(sea.darkest.darken(0.35))
demo_colors(sea, colorbar=True)

size()に指定するサイズが小さい場合と大きい場合で,単調な比例関係にしてしまうと,円の密度みたいなのがちょっと微妙だったので,分かりにくいけれど,描画する円の数を以下で指定することにした(デフォルトの場合):

floor ¥biggl(3 ¥cdot ¥sqrt{¥frac{width + height}{2}} ¥biggr)

ルート取ってサイズの大小での差を小さくする.本当はlog取るのが常套かもしれないが,ルートでもいいかなーという感じで.

これでsize()に依らない描画が可能.


また,demo_colors()のcolorbarを指定すると左下にカラーバーを表示する.

colorbarと円が重ならないように配慮……したことでdemo_colors()自体が分かりにくくなってしまったけれど(ぇ


前回はbananaを検索した結果の色テーマを取得したが,今回はseaで検索してみた.

もちろん,demo_colors()にはcolorオブジェクトのリストを渡せばおkなので,自作色リストをデモすることも出来る.

これは楽しい.

May 08(Fri), 2009

カラー1 - NodeBox

|

NodeBoxのライブラリの使い方を勉強する.

今回は『カラー』をテーマに.

今更言うまでもない話だが,俺は『ロストカラーズ』が大好きだ(※全く関係ない).



参考

web.kulerを使う:

web.kuler.search()

web.kulerはここから色テーマを取得する:

kuler

colorsライブラリのドキュメント:

NodeBox | Colors

色の名前など(named_colorに渡せる名称)一覧(|のエスケープが分からないので直接書き下し):

ttp://nodebox.net/code/index.php/Colors_|_named_colors


web.kulerサンプル(ほぼ公式のと同じ)

f:id:moch-lite:20090508200616p:image:h400

size(480, 600)

web = ximport("web")

themes = web.kuler.search("banana")
for r, g, b in themes[0]:
    print r, g, b

# The kuler.preview() command gives you an idea of the theme's colors. 
web.kuler.preview(themes[0])

previewが便利すぎて泣いた(つω≦ )


似たことをcolors.swarmでも出来るみたい――のサンプル

背景を同系色にするために,clr_list.darkest.darken(0.5),bananaテーマの一番暗い色をさらに暗くしてbackgroundに設定してみた.この方が見た目良い気がする.

f:id:moch-lite:20090508200725p:image:h400

size(480, 600)

web = ximport("web")

themes = web.kuler.search("banana")
for r, g, b in themes[0]:
    print r, g, b

clr = ximport("colors")
banana = clr.list(themes[0])

background(banana.darkest.darken(0.5))
banana.swarm(WIDTH/2, HEIGHT/2, r=180)

こういったアブストっぽい描画は好きなのだけどswarmって辞書で引くと「(昆虫,蜂,動物,人などの)群れ,群衆」とあるが昆虫の群っていうのはちょっと怖い感じがする……もちろん昆虫想定してる描画ではないと思うけれども:-(


colors, webともに便利過ぎる使い方が出来る.自分のアイデアを具現するのに最適なメソッドを探すのにライブラリを当たるという使い方のほかにも,どういったことが出来るか理解しておくのも新しいアイデアに繋がるはずなので重要――というモチベーションで,表現したい自己を持たない俺が,試したことをメモった次第.


追記:

カラー1 - NodeBox ――の続き - Haitena だいありー

に続く.

April 19(Sun), 2009

PySmellでTextMateにPythonコードの補完機能を付与する.

|

pysmell - Google Code


PySmellはVimやEmacs, TextMateでPythonスクリプトを書く際に補完機能を提供してくれる.ほとんどのIDEは関数等の補完機能を有しているが,TextMateにはこの機能がなかった.スニペットは強力だが,補完機能使いたさにIDEに環境を移行せざるを得ないというのは悩みどころ.しかし,PySmellによってTextMateに補完機能が付与されることでIDEに優るとも劣らない開発環境となったのではないだろうか……と素人な俺が言ってみる.短かいスクリプトしか書いたことがないのでIDEほどのごつい環境(多機能性)の恩恵を受ける必要性を感じずIDEを使わないので,軽量エディタ指向というのはあるかもしれない.


インストール〜設定

Macにインストールする際には easy_install を用いて,

sudo easy_install pysmell

またソースから入れる場合は:

Python Package Index : pysmell

からソースをダウンロードしてインストールする.

設定等は上のGoogle Codeページやソースを解凍したフォルダにあるREADMEに書かれている(両者とも同じもの).TextMateの場合はeasy_installでインストールしたとしても,PySmell.tmbundleも必要なため,ソースコードの圧縮ファイルもダウンロードする必要がある.READMEと共に同梱されており,PySmell.tmbundleをダブルクリックすればおk.


そして Preference -> Advanced -> Shell Variables に TM_PYTHON を追加する.

TM_PYTHONの値はpysmellをインストールしたpythonインタプリタのパスを入力する.

今回は,

/usr/bin/python

デフォルトでは Alt + Esc でコード補完となるが,Bundle Editorから変更可.


使い方

ちょっと説明が前後してしまうが,PySmellを使用する際には予めタグ情報ファイルを作っておかないといけない.


まず,補完を行いたいコードの(を含むプロジェクトのルート)階層で,

pysmell .

としてPYSMELLTAGSファイルを作成する.

次に,標準ライブラリの関数を補完出来るようにする.

標準ライブラリのフォルダに移動してpysmellを実行する.

cd /opt/local/lib/python2.5
pysmell . -x site-packages test -o ~/PYSMELLTAGS.stdlib

とすることでホームディレクトリにsite-packagesとtestフォルダを除くファイルを解析した結果がPYSMELLTAGS.stdlibとして出力される.これを先に作成したPYSMELLTAGSと同じ場所にコピーすればおk.


簡単に使ってみた感じとしては,標準ライブラリ全部はちょっと補完候補が多くなりすぎかな……という気がする.それに多少もっさり感もある.これが問題になるなら,標準ライブラリの中でも必要なもの(インポートするもの)のみ解析しておく方がいい気がする:-P


そういえば,ビルトイン関数のソースコードってどこにあるんだろう……?

理想的にはIPythonのような補完で候補をリアルタイムにリストアップしてくれる機能が欲しい.

April 14(Tue), 2009

集合知プログラミングを読む - 2章

|

データマイニングについての勉強とLaTeXの練習を兼ねて,集合知プログラミングを写経しながら読んでみようと思う.他の文法事項とか解説してある類の入門書は実際に打ち込む気がわかないが,本書については実際に手を動かしながら読むのがよい.


集合知プログラミング


目次:

1章 集合知への招待

2章 推薦を行う

3章 グループを見つけ出す

4章 検索とランキング

5章 最適化

6章 ドキュメントフィルタリング

7章 決定木によるモデリング

8章 価格モデルの構築

9章 高度な分類手法:カーネルメソッドとSVM

10章 特徴を発見する

11章 進化する知性

12章 アルゴリズムのまとめ

写経というのは,プログラムを実際に打ち込んで挙動を確認するだけでなく,読んだ内容をLaTeXでまとめ直す行為も含む……ので,1つの章をこなすのでも結構時間がかかる.で,とりあえず2章まで終えたので,ここまでの感想など.


まず,本書はデータマイニングの話題を扱っているが,データマイニングに用いる理論(アルゴリズム)をどのようにコードに落とし込むかを示してくれる.理論的にはわかるが,実際にはどうすればよいのかわからないときの指南となる.まだ序盤も序盤なのでアレだが,数式の詳細には触れず,あまり知識は要求されない感じだろうか.また,Pythonコードで例を示しており,他言語使用者も疑似コードとして読むことができる.しかも,実際にインタラクティブ・シェルで動くわけだからCやJavaで書かれているよりも,試しやすいし,紙面的にもコンパクトで読みやすい.ただ,ページにまたがったコードのインデントレベルがわかりにくいかもしれない.もちろん,やっていることが理解できていればあまり問題にはならないとは思うが.


というよりそれ以上に問題があって.それはコードが間違っていたり,示されている実行結果と異なった結果が得られたりすること.そして,コーディング規則?が統一的でないのが疑問だったりする.

例えば,本書で最初に実装する類似性スコアを算出する関数はユークリッド距離を用いるもので,以下のようになっている.

from math import sqrt

def sim_distance(prefs, person1, person2):
    # 二人とも評価しているアイテムのリストを得る
    si={}
    for item in prefs[person1]:
        if item in prefs[person2]:
            si[item]=1

    # 両者共に評価しているものが一つもなければ0を返す
    if len(si)==0: return 0
    
    # すべての差の平方を足し合わせる
    sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2)
                        for item in prefs[person1] if item in prefs[person2]])
    
    return 1/(1+sum_of_squares)

また,本書の付録Bに数式という項があり,B.1に数式と実装コードが書かれている.


ユークリッド距離は次のように表現される(一部改).


{¥it Euclidean} = ¥sqrt{¥sum^n_{i=1} (p_i - q_i)^2}


と共に,明快な実装が示されている.

def euclidean(p,q):
  sumSq=0.0
  # 差の平方を足し合わせる
  for i in range(len(p)):
    sumSq+=(p[i]-q[i])**2
  
  # 平方根をとる
  return (sumSq**0.5)

これらを見てまず,sim_distanceは値を返すときに平方根をとっていないし,また,math.sqrtをインポートしているが,euclideanでは0.5乗(**0.5)になっているし,powerだったり2乗(**2)だったり,何故表記に統一性を与えないのか.それに変数も小文字+アンダーバーなのとキャメルスタイルなのが混在.略称だったりそうでなかったりも……これは微妙ー.


他言語使用者がPythonの特徴をおさえるときに便利なPython チュートリアルの9.10 ジェネレータ式にも書かれているように,sum()ではわざわざ角括弧で囲む必要はない.というのも含めて書き直すとこう書けるのではないだろうか:

from math import sqrt

def sim_distance(prefs, person1, person2):
    si = {}
    for item in [i for i in prefs[person1] if i in prefs[person2]] : si[item] = 1
    
    if len(si) == 0 : return 0
    
    sum_of_squares = \
        sum((prefs[person1][item] - prefs[person2][item])**2 for item in si)
    
    return 1 / (1 + sqrt(sum_of_squares))

とか勝手に修正しつつLaTeXにまとめ直してみた.この調子でやってると1冊終えるのにどれだけかかるだろうかと不安になるが,そこは辛抱.本書自体のテーマは興味深いし,LaTeXも出来るだけ使うようにしていかないと.3章以降も続けてみようと思う.ちなみにまとめ直すことによって2章は約60%のページ数圧縮を実現(ぇ


集合知プログラミング
Toby Segaran
オライリージャパン
売り上げランキング: 1894
おすすめ度の平均: 4.5
4 プログラムはいまいち
4 ようこそ、Web 2.0の世界へ
5 知的好奇心が刺激された!!
5 機械学習の現実世界での応用
3 私には敷居が高かったかも・・・


Pythonチュートリアル
Pythonチュートリアル
posted with amazlet at 09.04.14
Guido van Rossum
オライリー・ジャパン
売り上げランキング: 196745
おすすめ度の平均: 4.5
3 買ってはみたものの...
5 Python作者による解説書
5 中級者以上のための本