pelican でブログを作る

pelican でブログ作っているので手短にやったことを書く。このポスト自体が pelican のテストなのであまりちゃんと解説書く気ないですスイマセン。

インストール

まず github でリポジトリを作り gh-pages ブランチを作る。

$ git clone https://github.com/{username}/blog.git
$ cd blog

python 3.x のサポートが微妙なので(Fabric がインストールできない) 2.7 に切り替える。

$ pyenv local 2.7.6

必要なものをインストール。

$ pip install pelican
$ pip install Fabric
$ pip install Markdown
$ pip install ghp-import

pelican-quickstart して適当に質問に答えると色々ファイルが生成される。

日記を書く

content 以下に Markdown 形式で日記を書く。書式は以下からコピペして書き換える。

Getting started — Pelican 3.3.0 documentation

Title: My super title
Date: 2010-12-03 10:20
Category: Python
Tags: pelican, publishing
Slug: my-super-post
Author: Alexis Metaireau
Summary: Short version for index and feeds

This is the content of my super blog post.

早速ビルドしてみる。

$ fab build
$ fab reserve

ブラウザから localhost:8000 を開く。

Slug から URL が生成されるらしい。Slug を削ると Title を元に URL を生成するらしいのだが、これが日本語を中国語の翻訳機にかけたような謎の URL になる。

pelican で作るブログ

http://localhost:8000/pelican-dezuo-ruburogu.html

pelican dezuo ruburogu とは一体…

ブログなら URL は {year}/{month}/{date}/{slug}.html という構成にしたいですね。

Settings — Pelican 3.3.1.dev documentation

上の URL settings を見ればいいのだがちょっと把握しづらい。

とりあえず pelicanconf.py に以下を追加したらなんとなくいい感じになった。

ARTICLE_URL     = 'posts/{date:%Y}/{date:%m}/{date:%d}/{slug}/'
ARTICLE_SAVE_AS = 'posts/{date:%Y}/{date:%m}/{date:%d}/{slug}/index.html'

liquid tag による IPython Notebook の挿入

まず数式が使えないので pelican-plugins から latex パッケージを入れておく。これは mathjax の別名。

$ git clone https://github.com/getpelican/pelican-plugins

conf ファイルに以下を記述する(pelican から実行できれば名前は何でもいいっぽい? pelican-quickstart から作った場合デフォルトは pelicanconf.pypublishconf.py のどちらか)。

PLUGIN_PATH = '/path/to/pelican-plugins'
PLUGINS = ['liquid_tags.notebook', 'latex']

/path/to/ は絶対パスで。~ をなんとなしに使ったらダメだった。そりゃそうか。

数式はこれだけの設定でよい。liquid_tags.notebook というプラグインで IPython Notebook を記事の好きな場所に挟み込むことができるようになる。

{% notebook filename.ipynb %}

注意点は notebook を置く場所である。デフォルトでは content/ 以下に notebooks/ というフォルダを作ってそこに filename.ipynb を置く必要がある。そういう規約である。NOTEBOOK_DIR を変えればデフォルトの設定は変更できるが特に不満はないしそのままにしておく。

最後のステップとして _nb_header.html の設定をする必要がある。_nb_header.htmlliquid_tags.notebook を使っているとpelican プロジェクトのルートフォルダに自動で生成される。これを挿入すると notebook の表示が奇麗になる。

まず themetemplate に次のような文を書く。

{% if EXTRA_HEADER %}
{{ EXTRA_HEADER }}
{% endif %}

が、自分は pelipress テーマを使っておりそこには既に書かれていたので必要なかった。

conf に _nb_header.html を読みこむ設定を書く。

EXTRA_HEADER = open('_nb_header.html').read().decode('utf-8')

これにて準備は完成!

以前作ったノートを挟んでおく。

IJulia なのだが構文がカラーリングされておりませんな。

ランダムサーチ

Clever Algorithms: Nature-Inspired Programming Recipes

This work is licensed under a CC BY-NC-SA 2.5 AU

ランダムサーチは確率的アルゴリズムのなかでも一番単純なものである.

数学的には解に収束性があるかなどを考えるらしいので簡単というわけではないらしいが,プログラムとして書くだけならとても簡単である.またランダムサーチは局所探索法や山登り法といったよりよい手法と組み合わせるための基本的な手法である.

実例

$ n = 2 $ における $ f = \sum_{i=1}^{n} x_i^2, -5.0 \leq x_i \leq 5.0 $ の最小値 $ \min f(x) $ を求める.パラボラ放物線の底を求める問題に過ぎないので数値的に解く意義は特にない.

まず位置ベクトルを受け取ったらコストを返す目的関数を定義する.

In [1]:
objective_function(vector) = sum(map(x -> x^2, vector))
Out[1]:
objective_function (generic function with 1 method)

続いて探索区間を受け取って(この問題では [-5 5; -5 5]),ランダムな位置ベクトルを返す関数を定義する.区間 [-5, 5] からランダムに 2 回選ぶだけなので今回は難しくないが,選ばれる点に偏りが出ていないかは常に考慮するべきである.

In [2]:
function random_vector(minmax :: Array{(Float64, Float64)})
  [mn + (mx - mn) * rand() for (mn, mx) = minmax]  # rand() は区間 [0, 1) の一様乱数を返す (Float64)
end
Out[2]:
random_vector (generic function with 1 method)

上2つの補助関数を用いて探索関数を記述すればよい.

探索関数 search は探索区間の配列と探索の試行回数を受け取り,返り値は最善の結果(コストとベクトルの情報)とする.

In [3]:
function search(search_space :: Array{(Float64, Float64)}, max_iter :: Int)
  best = Dict()
  for _ in 1:max_iter
    candidate = Dict()
    candidate[:vector] = random_vector(search_space)
    candidate[:cost]   = objective_function(candidate[:vector])
    best = !isempty(best) && best[:cost] < candidate[:cost] ? 
           best :
           candidate
  end
  best
end
Out[3]:
search (generic function with 1 method)

たんに書籍のRubyコードを移植しているだけなのだが,Julia特有の考察点がいくつか浮かび上がってくる.

まず引数の型を記述している.JuliaはRubyのように型を記述せずとも動くが,可能な限り書いたほうがよい.型はその関数の振る舞いを規定しているからである.型を書かないと,その関数はどんなデータ型に対しても適用される(ジェネリックな関数).これは動作が把握しづらい.

また Julia であれば search 関数をもっと短く書けるのではないだろうか.以下はシンタックスエラーで動かないが,vector を内包表記で一時的に蓄えたりすることはできないのだろうか(内包表記は内部の値を書き換えてはならなかった気がするので一時変数はだめか…).

function search(search_space, max_iter)
  minimum([(objective_function(vector), vector), vector = random_vector(search_space) for _ in 1:max_iter])
end

ところで,関数名 objective_functionrandom_vector もそのまま本から移植しただけであるが,Juliaでは関数名にスネークケース (名前を区切るのにアンダースコア_を使うこと) は推奨されていない.スネークケースで名前が区切られている場合,往々にして処理単位が 1 つに絞れていないということが起こっているので非推奨とされている.objective_functionrandom_vector はあまりよい関数名ではないかもしれないが,処理単位としてはこれ以上ないくらい小さく絞られていると思うのでこのままでよいだろう.

では最後に,実際に探索を行ってみよう.

In [4]:
search_space = [(-5.0, 5.0) (-5.0, 5.0)]
max_iter = 1000
best = search(search_space, max_iter)
println("Done. Best Solution: c=$(best[:cost]), v=$(best[:vector])")
Done. Best Solution: c=0.005268822282496379, v=[0.010556057732317825,-0.07181498400506925]