ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

ソフトマックス関数の式変形

ゼロから作るDeepLearningという本を読んでいるのですが、ソフトマックス関数でオーバーフローしないように式変形するときは次のように変形するとあります。

\displaystyle y_k = \frac{exp(a_k)} {\sum_{i=1}^n exp(a_i)}

\displaystyle = \frac{C exp(a_k)} {C \sum_{i=1}^n exp(a_i)}

\displaystyle = \frac{exp(a_k + log{C})} {\sum_{i=1}^n exp(a_i + log{C})}

\displaystyle = \frac{exp(a_k + C')} {\sum_{i=1}^n exp(a_i + C')}

のですが、2行目から3行目の変形で分子のところをC exp(a_k) = exp(a_k + log{C}) とやっているのですが、こんな公式あったっけ?と手が止まりました。 普通にありました(高校数学!)。

指数と対数の関係式

底をa(a>0)という条件で、\displaystyle x = a^{log_a{x}} が成り立つので、\displaystyle C = e^{log_e{C}}と変形できます。

よって、上記の2行目から3行目の分子の変形は、

 C exp(a_k) = exp(log_e{C}) exp(a_k)

 = exp(a_k + log{C})

ということですね。

Atomエディタのremote-ftpで"Sync local -> remote"をするとインジケータが固まるとき

"Sync local -> remote"をするとインジケータが固まってしまう現象が起きました。

これはおそらくパーミッションの問題で、アップロードしたいファイルに書き込み権限を付与していないせいで起きます。

固まった場合、一度Packagesメニュー > Remote FTP > disconnect で切断した後、再度接続し、ファイルのパーミッションを直したあとでSync local -> remoteするとうまくいきます。

という内容のissueを報告しましたけど、かなりissue溜まってるからレスポンスは当分後になりそう。自分でPRするのが一番いいんでしょうけど。

state machineの話(あるいはPython3での実装)

Statechart
このような記事を見つけました。
ステートマシン(state machine)実装のための本があることを初めて知りました。

ここで提案されている手法は、[* 状態変数を使うかわりに現在の状態を示す関数を使う]というものである。たとえば「あ」という状態は`あ()`という関数で表現し、「い」という状態は`い()`という関数で表現する。「あ」や「い」という状態の上位階層として「あ行」という状態が存在するので、それは`あ行()`のような関数で表現する。このように、[* あらゆる状態を関数として表現する]ところがミソである。

iPhoneフリック入力はこんな感じらしいです。はぇ~。

そういえば以前にPython3でstate machineを実装したことがあるので、そのときのやり方をメモって置きます。結構悩んで実装した記憶が…。

from enum import Enum

class StateMachine():
    class State(Enum):
        """ state machineの状態 """
        Start = 0 # 状態0(初期状態)
        S1    = 1 # 状態1
        S2    = 2 # 状態2
        S3    = 3 # 状態3
        S4    = 5 # 状態4

    def __init__(self):
        self.state = self.State.Start

    def update_state(self):
        """ state machineを更新する(状態遷移する) """

        if self.state is self.State.Start:
            """ 初期状態 """
            self.state = self.State.S1
            print("State: Start")
            return

        elif self.state is self.State.S1:
            """ 状態1 """
            self.state = self.State.S2
            print("State: S1")
            return

        elif self.state is self.State.S2:
            """ 状態2 """
            self.state = self.State.S3
            print("State: S2")
            return

        elif self.state is self.State.S3:
            """ 状態3 """
            self.state = self.State.S4
            print("State: S3")
            return

        elif self.state is self.State.S4:
            """ 状態4 """
            self.state = self.State.S1
            print("State: S4")
            return

実際に使うときは、ループを回して使います。

import time

if __name__ == "__main__":
    sm = StateMachine()
    while True:
        sm.update_state()
        time.sleep(1.0)

上記の実装の良いところを挙げると、
・state machineの実装がクラス内で完全に閉じている
・使うときはupdate_state()を呼び出すだけ
・引数を増やしやすい
・シンプル
くらいです。まあ特別なことはしていません。

実際に処理を実装するとわかるのですが、処理が長くなるとif文が長くなり可読性落ちるので、実際の処理はメソッド化するのが無難です。

if文の数が多くなると可読性が落ちたり、無駄な評価がされて遅いというデメリットが考えられるので、if文をディクショナリに書き換えればもっと良くなるかもしれません。試してないですけど。

あと、これはstate machineを実装する上で一般的に言える注意点だと思うのですが、状態を変更した後は(self.stateを変更した後は)すぐにreturnしなければいけません。さもなければ状態を追いかけることが難しくなります。以前、状態が変更された後も処理が続き、条件によってはさらに状態が上書きされ、そしてまた条件によっては上書きされ…というのが続き、最後にreturnされるstate machineを見たことがあるのですが(そしてそのプログラムのバグを追いかけていたのですが)、恐ろしくしんどいです。リーダブルコード7.5章にも書いてありますが、できることなら関数から早く返しましょう。

関数で複数のreturn文を使ってはいけないと思っている人がいる。アホくさ。

ちなみにPythonには既にstate machineを扱うライブラリがあるようです。独自実装で特殊なことする必要がなければこれを使うという手もあります。便利世の中~。
transitionsでステートマシンを扱う [Python]

ゲン、Gitに切れる

addコマンドの名前がむかつくんじゃ

おどりゃクソ森。「ステージする」んだからstageって名前のコマンドにせんか。

resetコマンドの名前がむかつくんじゃ

おどりゃクソ森。 「アンステージする」んだからunstageって名前のコマンドにせんか。
このresetコマンドが「ステージの取り消し」と「コミットの取り消し」を担当してるから初学者(わし)が混乱するんじゃ。--hard --softってなんじゃ。unstageコマンドとresetコマンドにわけんか。

checkoutコマンドで2つの異なった操作ができるのがむかつくんじゃ

・ブランチの切り替え
・ファイルを特定コミットの状態に戻す
この2つの操作が同じcheckoutでできるのが納得いかんのじゃ。
ブランチの切り替えはbranchコマンドでできると思ったんじゃがのう。ちがうんか。
というかgit reset --hard [commit]とgit checkout [commit]は何が違うんじゃ なにっ インデックスに追加したファイルが元に戻るかどうか? バカタレーッ それこそオプションで挙動を変えるべきで、コマンドを変えることないじゃないか 落ち着けあんちゃん 確かに混同しやすいがそもそもcheckoutとresetは別々の意味のコマンドで、たまたま似たような操作ができるだけじゃ やかましいっ! ヒッ おどりゃトサカにきたぞ隆太 わしはもうGitは使わん なにっそれは本当か 正気じゃないんじゃないか アホウわしゃ正気じゃ そもそもGitなんてものはアメリカがわしら日本人から和の心を奪うために戦後に導入した制度なんじゃ バージョン管理は昔ながらのコピーアンドペーストで良かったんじゃ わしはフォルダに日付を付けて管理する方法に戻すぞ よさんかゲン やめてーっ さよならGitまた来てコピペ ジャンジャンジャガイモサツマイモ…

Gitの勉強の仕方

Gitを初めて触ったのが2014年の1月なので、それから4年が経過しました。毎日Gitに触っているわけではないのでGit歴を単純計算できませんが、大体そのくらい触っているというわけです。

その間に、Gitは何回も挫折しました。重要なファイルを何回も消しました。エラーが修正できなくてリポジトリを何回も作り直しました。最近になってようやくGitを人並み程度に扱えるようになりました。

どうしてGitを習得するのにここまで時間がかかったのかと回顧してみると、おそらく勉強の仕方がまずかったのだなと思います。習うより慣れろの精神で使ってたらわかる様になると思っていましたが、そういうわけでもありませんでした。というかわかってないのに使うので、結果ファイルを消したりしてしまうわけです。そしてやる気が無くなるわけです。Gitはクソとか言い始めるわけです。

これはGitが苦手な人のための記事です。私は今でもGitが苦手なので偉そうなことは書けませんが、ここに書いてあることを意識して勉強しています、という自戒を込めての文章です。

Gitは難しいことを認める

Gitは難しい。
Gitは便利ではありますが、簡単ではない。

Gitチートシートの図を覚える

「習うより慣れろ」は大事ですが、最低限の知識は必要です。
最低限の知識とは何かを具体的に言うと、Gitチートシートに載っているものすべてです。
GitチートシートというのはGit Commands and Best Practices Cheat SheetAtlassian Git コマンド チートシート の日本語版をダウンロードしようなどです。私はGit ポケットリファレンスチートシートを使っています(改訂新版より以前のものはチートシート載ってない?)。

「共有リポジトリ」「ローカルリポジトリ」「インデックス」「作業ツリー」は必須の知識です。これらの用語と意味は覚えます。図のフローはしっかり覚えます。

代表的なコマンドが何をするものなのかも覚えます。addコマンドなら「作業ツリーの変更をインデックスに保存する」といったような理解です。当然ですが、自分が打ったコマンドが何をしているのか頭の中でイメージできるようになる必要があります。イメージしながらコマンドを打つ必要があります。慣れないうちはチートシートを見ながら、「今自分はここの操作をしてるんだ」とイメージしながらコマンドを打ちます。さもなければ、ファイルは雲散霧消するものと心得ます。

ブランチを切ったらどういう流れになるのか。mergeやrebaseしたらどういうコミット状態になるのか。これも最低限把握します。細かいfast-forwardやNon-fast-forwardなどは後で良いと思います。
チートシートに掲載されているコマンドは全て理解しているようになりましょう。

暗記するのは大変です。なので実際に手を動かして覚えるのが重要です。適当なリポジトリを作成し、消えても困らないファイルに対して思う存分addしてcommitしてbranch切ってfetchしてmergeまたはrebaseしてpushしましょう。イメージしたとおりのファイルの状態になっているか、コミットの流れになっているかを確認しながらやります。

本を買う

適当なサイトを参考にするのも良いですが、個人的にはGitポケットリファレンスをおすすめします。序文で「私はGitが嫌いでした」で始まる本書は私に合っていた気がします。技術評論社の回し者みたいですが、ポケットリファレンスの良いところを以下に示します。

ポケットリファレンスの良いところはコマンドの説明が充実しているので、「このコマンドって何するコマンドなの」「どんな書き方すればいいの」「こういうとき何のコマンド使えばいいの」というときに辞書的に参照しやすく、非常に便利です。

もうひとつ良いところは、情報ソースが統一されているということです。つまり、わからないときにポケットリファレンスを参照するようにすれば、以前参照した情報と、今回参照した情報が一致するので、記憶に残りやすいという点です。適当にググってもコマンドの使い方は出てきますが、人によってコマンドの書き方は様々だったり、以前参照したサイトがヒットしなかったりします。「以前となんかやり方違うような?まいっか」だとあまり記憶に残らないので、そういう「情報ソースを統一する」という意味で適当な本を買うというのは有用でした。

自分でまとめる

ポケットリファレンスがあれば良いかというとそうでもなくて、例えばド忘れしたときに毎回ポケットリファレンスを参照するのは面倒くさく感じます。まれによく使うコマンドなどは、自分なりにQiitaなりブログなりGmailの下書きなりにまとめておくと良いです。「こういうとき何のコマンド使うんだっけ」というとき、都度ググるよりかは、自分のやり方をメモしたものを参照したほうが、頭に残りやすくて良いです。


以上です。

Raspbian, Apache2でダイジェスト認証

Raspbian 8.0
Apache 2.4.10(Raspbian)

ダイジェスト認証に必要なモジュールを有効化する

$ sudo a2enmod auth_digest
$ sudo a2enmod authn_file
$ sudo a2enmod authz_user

Apache2の設定をする

$ sudo vi /etc/apache2/apache2.conf

(以下を適当なところに追加)

# Digest Authentication

<Directory /myproject/www/>

        AuthType Digest

        AuthName "DigestZone"

        AuthUserFile /myproject/www/.htdigest

        Require valid-user

</Directory>

ダイジェスト認証のファイルを作成する

$ sudo htdigest -c /myproject/www/.htdigest "DigestZone" root

Adding password for root in realm DigestZone.

New password:root

Re-type new password:root

Apache2の再起動

$ sudo service apache2 restart
$ sudo systemctl daemon-reload