読者です 読者をやめる 読者になる 読者になる

ばぐばぐわーるど

Pythonなどなど

【Python】 for break else の挙動

breakは直後のelseごと破壊します。

for i in range(10):
    print(i)
    if i == 5:
        break
else:
    print("Hi")

実行結果

0
1
2
3
4
5


最後まで、breakされなければ、else以降が実行されます。

for i in range(10):
    print(i)
    if i == 15:
        break
else:
    print("Hi")

実行結果

0
1
2
3
4
5
6
7
8
9
Hi

Pythonでビット演算

AND ・・・ &
OR ・・・ |
XOR ・・・ ^
反転・・・ ~
左シフト・・・<<
右シフト・・・>>

bin(0b1100 & 0b1011)
bin(0b1100 | 0b1100)
bin(0b1100 ^ 0b1011)
bin(~0b1100)
bin(0b1100 << 1)
bin(0b1100 >> 1)

実行結果

0b1000
0b1100
0b111
-0b1101
0b11000
0b110
format(数字, 'b')

でも2進数表示できますが、この場合は頭の0bがつきません。



メモ用のブログだったことを忘れてました。
更新していこうと思います。

ポアソン分布の覚え方

ポアソン分布の確率関数

P(X=k)=\frac{\lambda^k}{k!} e^{-\lambda

これ、なかなか覚えられません。どういう風に解釈すればいいんだろう。


こんなのを見つけた。
ポアソン分布の公式がなかなか覚えれません。なにかウマイ語呂合わせや暗記法を教... - Yahoo!知恵袋

p[0]+p[1]+...+p[n]+...=1とe^λ=1+λ+(1/2)λ^2+...+(1/n!)λ^n+...を比較してみてはどうでしょうか。
それでも不安になったら、2項分布B(N,λ/N)に戻って考え、N→∞としてもよいでしょう。

ふむふむ。

ポアソン分布のすべての確率を足したものと、e^\lambdaテイラー展開を比較せよとな。


左の式は確率なのだから合計1になるでしょう。
P(X=0)+P(X=1)+\dots+P(X=n)+\dots = 1

右の式もちゃんと書いてみます。e^xテイラー展開と同じです。
e^\lambda=1+\lambda+\frac{1}{2}\lambda^2+\dots+\frac{1}{n!}\lambda^n+\dots

比較ってことは両辺にe^{-\lambda}かけろってことでしょうか。
1=(1+\lambda+\frac{1}{2}\lambda^2+\dots+\frac{1}{n!}\lambda^n+\dots)e^{-\lambda}

ほうほう。つまり、こういうことですね。

P(X=0)+P(X=1)+\dots+P(X=n)+\dots =(1+\lambda+\frac{1}{2}\lambda^2+\dots+\frac{1}{n!}\lambda^n+\dots)e^{-\lambda}

P(X=0)+P(X=1)+\dots+P(X=n)+\dots =e^{-\lambda}+\lambda e^{-\lambda}+\frac{1}{2}\lambda^2 e^{-\lambda}+\dots+\frac{1}{n!}\lambda^n e^{-\lambda}+\dots

なるほど。最初のP(X=k)=\frac{\lambda^k}{k!} e^{-\lambdaでkに適当に値を入れてみても、確かに対応していることがわかります。

ポアソン分布はe^xテイラー展開風だってこと覚えておけば忘れることはなさそうです。

対角化とかで使うP^-1APは何をやっているのか

対角化でとか使う P^{-1}APの解説です。
証明したからOKって終わってたり、謎の図で説明とかよくあるんですが、そういうのに納得がいかない人向けです。
例によって正しさは保証しません。定義とは違うことを言い切ってるため結構危険かもしれません。

最初に、そもそも各記号が何を表しているのかを確認しておくと、
A・・・表現行列
 P・・・基底の取り替え行列
です。

表現行列とは何か

表現行列はある基底のもとでの座標を、別のある基底のもとでの座標に変換するような行列です。
 
\left(
\begin{array}{r}
b_{1} \\
b_{2} \\
b_{3} 
\end{array}
\right)_\beta = A
\left(
\begin{array}{r}
a_{1} \\
a_{2} \\
a_{3}
\end{array}
\right)_\alpha
上の数式で言うとA(大きさ3×3)が表現行列になります。
そもそも座標っていうのは基底によってとる値が異なります。下に\alpha, \betaってついてるのは、それぞれの座標が基底が\alpha\betaに関してのものだよってことを強調してます。標準基底によるものではないってことです。

基底の取り替え行列とは何か

基底を取り替えてくれる行列です。そのまんまです。
例えば基底を次のようにすると
\alpha=\{\vec{\alpha_1},\vec{\alpha_2},\vec{\alpha_3}\}
\beta=\{\vec{\beta_1},\vec{\beta_2},\vec{\beta_3}\}
基底の取り替え行列は
 
\left(
\begin{array}{r}
\vec{\beta_{1}} ,
\vec{\beta_{2}} ,
\vec{\beta_{3}} 
\end{array}
\right) = 
\left(
\begin{array}{r}
\vec{\alpha_{1}} ,
\vec{\alpha_{2}} ,
\vec{\alpha_{3}} 
\end{array}
\right)P
のP(大きさ3×3)です。

で、このPなんですが真の目的はこういうことをするためにあります。
 
\left(
\begin{array}{r}
x_{1}\\
x_{2}\\
x_{3} 
\end{array}
\right)_\alpha = P
\left(
\begin{array}{r}
x'_{1} \\
x'_{2} \\
x'_{3}
\end{array}
\right)_\beta
つまり表現行列と化します。
こういう操作でこの式は出せます。
 x_1\vec{\alpha _1}+x_2\vec{\alpha _2}+x_3\vec{\alpha _3}=x'_1\vec{\beta _1}+x'_2\vec{\beta _2}+x'_3\vec{\beta _3}
 (\vec{\alpha _1},\vec{\alpha _2},\vec{\alpha _3})\left(
\begin{array}{r}
x_{1}\\
x_{2}\\
x_{3} 
\end{array}
\right)=
(\vec{\beta _1},\vec{\beta _2},\vec{\beta _3})\left(
\begin{array}{r}
x'_{1} \\
x'_{2} \\
x'_{3}
\end{array}
\right)
 (\vec{\alpha _1},\vec{\alpha _2},\vec{\alpha _3})\left(
\begin{array}{r}
x_{1}\\
x_{2}\\
x_{3} 
\end{array}
\right)=
\left(
\begin{array}{r}
\vec{\alpha_{1}} ,
\vec{\alpha_{2}} ,
\vec{\alpha_{3}} 
\end{array}
\right)P\left(
\begin{array}{r}
x'_{1} \\
x'_{2} \\
x'_{3}
\end{array}
\right)
 \left(
\begin{array}{r}
x_{1}\\
x_{2}\\
x_{3} 
\end{array}
\right)=
P\left(
\begin{array}{r}
x'_{1} \\
x'_{2} \\
x'_{3}
\end{array}
\right)
そして、基底を意識するとこうなります。
 
\left(
\begin{array}{r}
x_{1}\\
x_{2}\\
x_{3} 
\end{array}
\right)_\alpha = P
\left(
\begin{array}{r}
x'_{1} \\
x'_{2} \\
x'_{3}
\end{array}
\right)_\beta
この基底の取り替え行列は表現行列として使えば、\alphaの元での座標を\betaの元での座標に変えてくれるってことです。

P^{-1}APとは何か

再び表現行列を考えてみます。
 
\left(
\begin{array}{r}
y_{1} \\
y_{2} \\
y_{3} 
\end{array}
\right)_\alpha = A
\left(
\begin{array}{r}
x_{1} \\
x_{2} \\
x_{3}
\end{array}
\right)_\alpha
よく見ると、今回は左辺の座標ベクトルと右辺の座標ベクトルの基底はどっちも \alphaになっています。
P^{-1}APはそういう条件であらわれます。
ここで基底の取り替え行列
 
\left(
\begin{array}{r}
\vec{\beta_{1}} ,
\vec{\beta_{2}} ,
\vec{\beta_{3}} 
\end{array}
\right) = 
\left(
\begin{array}{r}
\vec{\alpha_{1}} ,
\vec{\alpha_{2}} ,
\vec{\alpha_{3}} 
\end{array}
\right)P
として、左辺と右辺の座標ベクトルを基底\betaの元での座標に書きなおしてみましょうか。
 
P\left(
\begin{array}{r}
y'_{1} \\
y'_{2} \\
y'_{3} 
\end{array}
\right)_\beta = AP
\left(
\begin{array}{r}
x'_{1} \\
x'_{2} \\
x'_{3}
\end{array}
\right)_\beta
両辺からP^{-1}をかけると・・・
 
\left(
\begin{array}{r}
y'_{1} \\
y'_{2} \\
y'_{3} 
\end{array}
\right)_\beta = P^{-1}AP
\left(
\begin{array}{r}
x'_{1} \\
x'_{2} \\
x'_{3}
\end{array}
\right)_\beta
無事、P^{-1}APがでました。
つまり、P^{-1}APとは表現行列に別の基底の座標を入れて使いたくなったときに、P^{-1}APとすると、みごと別の基底の座標が出力されるようにしてくれるものです。


ちなみに、
 
\left(
\begin{array}{r}
y_{1} \\
y_{2} \\
y_{3} 
\end{array}
\right)_\beta = A
\left(
\begin{array}{r}
x_{1} \\
x_{2} \\
x_{3}
\end{array}
\right)_\alpha
みたいに左右の基底がことなる表現行列の場合、
 
\left(
\begin{array}{r}
y'_{1} \\
y'_{2} \\
y'_{3} 
\end{array}
\right)_\gamma = Q^{-1}AP
\left(
\begin{array}{r}
x_{1} \\
x_{2} \\
x_{3}
\end{array}
\right)_\xi
みたいな形になります。やってることは同じなので意味はわかると思います。

畳み込みのお話 ~なぜ、あんな式なのか~

唐突に畳み込みの話をします。

まずはこの式を見てもらいます。

(f*g)(t)= \int f(\tau)g(t-\tau)d\tau

すごく・・・意味不明です・・・

これはWikipedia畳み込み - Wikipediaの説明で一番最初に出てくる式です。

まあ、意味不明なのは置いといてそういう計算があるものだとしましょう。

次にWikipediaの畳み込みの記事のGIFアニメを見てください。

f:id:jum12:20140205211101g:plain

なんか四角いのが左から走ってきてます。
wikipediaの解説によると下が畳み込みの結果みたいです。

じーっと5分くらいみてるとなんとなくわかってきます。
畳み込みの結果がtの関数になってるので、下の三角形の横軸はtだなー
てことは上は\tau軸なんだなー
確かに重なった面積がその瞬間の畳み込みの値になってるんだなーって。

で、もっかい式を見てみます。

あれ? なんか変じゃね?

なんというかこのアニメーションを見る限り直感的にこういう式であってほしいんです。

(f*g)(t)= \int f(\tau)g(\tau-t)d\tau
これならg(\tau)がだんだん右に行くっていうのが分かる気がするけど、畳み込みの式をみたらg(t-\tau)になってます。

これってわざわざg(\tau)を左右反転させてるってことですよね。今は正方形だから関係ないけど、本当は反転してるってことですよね? 謎過ぎる。
というわけで、テーマはなんで畳み込みは反転させたやつを掛けるのかって話です。

総和の畳み込み

連続の畳み込みを考えても難しそうなので、まずは離散の畳み込みを考えてみます。
wikiによると、畳み込みってこんな定義です。
(f*g)(m)=\sum_{n=0}^{} f(n)g(m-n)
※勝手にn=0から始めることにしてます。

これは具体的に書くとこんな感じです。
m=0のとき
(f*g)(0)=f(0)g(0)
m=1のとき
(f*g)(1)=f(0)g(1)+f(1)g(0)
m=2のとき
(f*g)(2)=f(0)g(2)+f(1)g(1)+f(2)g(0)
m=3のとき
(f*g)(3)=f(0)g(3)+f(1)g(2)+f(2)g(1)+f(3)g(0)
m=4のとき
(f*g)(4)=f(0)g(4)+f(1)g(3)+f(2)g(2)+f(3)g(1)+f(4)g(0)
要するに足してmになるような2つの自然数の組を集めてきて、それをf,gに入れ、足してるってことですね。
どっかで見たことあるような計算です。
これとか\sum_{k=0}^{n} {}_n\mathrm{C}_k{p^k}{q^{n-k}}

インテグラルのほうの畳み込みも考えてみる

(f*g)(t)= \int f(\tau)g(t-\tau)d\tau
0.01より下は小さすぎるから無視できることにします。あと負の範囲は考えてません。
t=0のとき
(f*g)(0)=f(0)g(0)d\tau
t=0.1のとき
(f*g)(0.1)=f(0)g(0.1)d\tau+f(0.01)g(0.09)d\tau+f(0.02)g(0.98)d\tau+\dots+f(0.09)g(0.01)d\tau+f(0.1)g(0)d\tau
こんな感じのノリでしょう。


次にこんな感じの関数を考えてみます。線が見えてる部分以外は0と思ってくださいf:id:jum12:20140205222119g:plain
とっても図が見難くて申し訳ないのですが、言いたいことが伝わるでしょうか。上記の例から掛け合わされる部分は下図のような対応関係にあるはずです。
f:id:jum12:20140205223816g:plain
例えばf(0.02)のとき、f(0.02)g(0.08)d\tauを考えるのでg(0.08)が対応しています。
矢印で対応しているところを掛けて足すってことを繰り返しまくればt=0.1の畳み込みが求まるはずです。

もし、この矢印のねじれをとればもっと楽にこの図を書けそうなんですが、どうしたらいいでしょうか。
そうですね。右に0.1平行移動させて反転させれば良さそうです。
f:id:jum12:20140205225526g:plain
この図なら垂直に対応してくれてます。そのまんま掛けたf(\tau)g(0.1-\tau)積分すればt=0.1での畳み込みが求まります。
今はt=0.1でやりましたが、t=0.2のときは0.2右に動かして反転させればOKです。
あとはあらゆるtについて計算(tを増やす。すなわちg(-\tau)が右に動いていくたびに同じことする)するだけです。
つまり、これが反転させたやつを掛ける理由です。



最後に断っておきますが、この解釈で正しいかは保障しません。ただ、こんだけグダグダ考えれば、定義を忘れることはないかも

sympyをインストール

sympyはMathematicaみたいに代数計算をしてくれるモジュールです。
中高生に与えてはいけないツールですね。

from sympy import *

x, y, z = symbols('x y z')

for i in range(5):
    print(expand((x+y+z)**i))

結果

1
x + y + z
x**2 + 2*x*y + 2*x*z + y**2 + 2*y*z + z**2
x**3 + 3*x**2*y + 3*x**2*z + 3*x*y**2 + 6*x*y*z + 3*x*z**2 + y**3 + 3*y**2*z + 3*y*z**2 + z**3
x**4 + 4*x**3*y + 4*x**3*z + 6*x**2*y**2 + 12*x**2*y*z + 6*x**2*z**2 + 4*x*y**3 + 12*x*y**2*z + 12*x*y*z**2 + 4*x*z**3 + y**4 + 4*y**3*z + 6*y**2*z**2 + 4*y*z**3 + z**4

でもまあ今どきの高校生はWolfram Alphaとか使うのかな。

【Windows】いかにしてファイルを隠すか

あなたはちょっとPCを貸してって言われた時困りませんか?
困らずに貸せたら気持ちがいいですよね。

逆に貸し渋ってる人を見ると、見られたくないものがあるんだろうなー
きっとあんなものやこんなものだろうなーと邪推してしまうものです。

やっぱり人には見られたくないファイルはあります。
ただ人に見られる、貸すときもあるので、そんなときのために僕がどうやってファイルを隠してきたかを書きます。

またブックマークや履歴なんかも見られたくないですね。それらについても書きましょう。

1. 見られたくないファイルは外付けHDDやUSBメモリ

一番てっとり早い方法です。普通はこれで問題ないと思います。ただ僕はUSBをつなぐことやHDDを隠す?のが面倒くさいのであまりすきじゃないです。あとファイルの閲覧するとPC側にファイル名の履歴等が残ったりもしますからね。

Dropbox等、クラウド上で管理するという手もありますが、僕はあまり個人情報をクラウドサービスに預けまくるのが好きじゃないので却下です。

2. 仮想マシンで見られたくないファイルを管理

若干面倒ですが有効な方法です。一時期これが最強だと思ってました。Linuxかなんかの仮想マシンに見られたくないファイル全部ぶち込んで、その中でブラウジングすれば見られたくない情報はすべて隠せます。

もちろん、その気になれば暗号化されてるわけでもないので(たぶん)情報は完全に隠せてるというわけではないと思いますが、他人のPCを一時的に借りるときにそんな失礼なことする人はいないです。

ただやはりいちいち仮想マシンを立ち上げるのが面倒なのと普段使いするには重いのが欠点です。

3. 隠しファイル+隠しフォルダ+Cygwin

現在の僕の方法です。問題は多々あると思いますけど、上記2つの方法に比べて楽なのが良いです。

やり方 (Cygwinインストール済みが前提)

1.見られたくないファイルをまとめます
2. 見られたくないファイルを隠しファイル化

フォルダを右クリック、プロパティから隠しファイル、変更をこのフォルダー、サブフォルダーおよびファイルに対して適用をします
これによってエクスプローラや検索によって見つからないようにします。

3. Cygwinの.bshrcや.zshrcに適当な設定を書く

一番面倒なところですが、これが重要です。
まずエイリアスでopenコマンドを用意します。

alias open='cygstart'
alias o='cygstart'
alias o.='o .'

僕のopen周りはこんな感じです。面倒なのでoでファイルを開けるようにしてます。ほかにもよく使うのはアルファベット1文字で設定してます。o(スペース).でカレントディレクトリを開きますが、o.と打ち間違えるのでo.で定義しています。

エイリアスを追加しまくります。

alias secret='cd ~/secret/'

こんな風にで移動したいファイル名でcdできるようにしておきます。

alias chrome='open chrome'
alias c='open chrome'

Chromeを私的な目的で使う用にする場合こんな感じのエイリアスを用意しておきます。
そしてデスクトップ、ホーム等のChromeという単語の出てくるあらゆるものを削除します。代わりにデスクトップのわかりやすいところにFirefoxでも置いときましょう。

4. Cygwin上から隠しファイルにアクセス

ターミナルからlsをすれば隠しファイルは見ることができるので、そのファイルを

open ファイル名

とかで開けばOKです。

この方法の問題点は勝手にCygwinのターミナルを開いて、人の.bshrcや.zshrcを勝手に覗くような不躾な輩に使わせると一貫の終わりということでしょうか。ただたくさん設定書いとけば大丈夫でしょう。わーたくさん書いてるなーくらいの感想で終わってくれるはずです。

あとはファイルを追加する際、いちいち隠しファイル化するのが面倒ということでしょうか。これはそのうちなんとかしたいですね。隠しフォルダにいれたら自動で隠しファイルにする設定とか無いんでしょうか。

個人的にターミナル上でVimを普段使いしたいのでこの方法はかなり気に入ってます。最初に設定を書くところは面倒ですけど、出来上がったらかなり楽です。


全然関係ないけどCygwin+Pythonの設定

そんなこんなで最近の僕はターミナル上で色々操作しているんですが、一応PythonブログなのでPythonの設定に触れときます。
Cygwin上でPython動かそうとすると、Cygwinに内蔵されてるPythonが動作します。

Python 2.7.5 (default, Oct  2 2013, 22:34:09)
[GCC 4.8.1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.

こんな感じで。on cygwinってなってますね。
これでどうやってWindowsの方にインストールしたPythonを動かせばいいかちょっと悩みました。

結論を言うと以下のエイリアスを追加すればOKです。

alias py='/cygdrive/c/Python33/python.exe'
alias ipy='/cygdrive/c/Python33/Scripts/ipython3.exe qtconsole --pylab'
alias pynote='/cygdrive/c/Python33/Scripts/ipython3.exe notebook --pylab inline'

pyでpython33 on windowsが実行できるようになります。
ipyはqtconsoleでのipython、pynoteはipython notebookです。