
Outline
機械学習初心者です。機械学習やディープラーニングでは、「確率的勾配降下法」というアルゴリズムがよく出てきますが、そのメリットがいまいちピンとこなかったので考えてみました。素人のポエムなのでトンチンカンなこと書いていると思います(そこそこ長いよ!)。
二次関数の最小値
全てはここから始まります。今回の確率的勾配降下法も、それのもととなった最急降下法も全てこれの応用です。
例:$ y=x^2-4x$ の最小値とそのときの$x$を求めなさい
数学的解法(1)~平方完成~
高校数学でおなじみ(?)の平方完成をします。
$$y = (x^2-4x+4)-4 = (x-2)^2-4 $$
したがって、x=2のときに最小値-4です。簡単ですね。
しかし、次数や次元が増えていくと簡単に平方完成できなくなります。もう少し一般的に使える方法を考えます。
数学的解法(2)~微分して=0となる点を求める~
微分はグラフの接線の傾き(勾配)で、最小値となる点では必ず接線は真横になる(微分係数が0になる)という性質を使います。この性質は確率的勾配降下法までずっとベースになるのでぜひ覚えてください。
\begin{align}
y'=\frac{\partial y}{\partial x} = 2x-4 &=0 \\
x &=2
\end{align}
結果は(1)の場合と同じです。1変数の微分はギリシャ文字のではなくて、英数のdを使うことがほとんどですが(∂と書いた場合は偏微分を表します)、1変数の偏微分は微分と同じなのであえて∂で書きます。
グラフにするとわかりやすいですね。x=2では接線は真横(微分=0)となります。
ただし、最小値→微分=0は成り立ちますが、微分=0→最小値は成り立ちません。これは少し補足します。
微分=0は必ずしも最小値とならない
4次関数$y=x^4-4x^3-36x^2$のグラフです。
\begin{align}
y'=4x^3-12x^2-72x &= 0 \\
x(x^2-3x-18) &= 0 \\
(x+3)x(x-6) &= 0 \\
x &= -3, 0, 6
\end{align}
実際微分して=0と解くと、$x=-3, 0, 6$のときに最小値を取る可能性があります。グラフを見ると、global minimumという意味での最小値はx=6のときだけで、x=-3のときはlocal minimumつまり極小値でしかありません。x=0は極大値です。
機械学習でなにかの関数を最小化するときに、本当にほしいのはこの例でいうx=6のような値です。よく「局所解に陥る」という言い回しを見るのですが、概念的にはx=-3のような値が最小値として求められたということだと思います。
※専門的には、x=-3の場合を局所的最適(local optimal)、x=6の場合は大域的最適(global optimal)と言うそうです。以下の講義資料がわかりやすいです。
最急降下法(直線探索)
これまで数学的(理論的と言ったほうが正しいかも)解法で最小値を求めましたが、ディープラーニングのように何十、何百次元の関数をいくつもネットワーク上につなぎ合わせた目的関数を最小化する場合、もはや目的関数がどんなグラフをしているかもよくわからなく、平方完成のように理論的に解くことはほぼ不可能です。そこで数値計算の出番です。
荒っぽい言い方ですが、理論的な解法が神様の手法だとするなら、アルゴリズムで数値計算をしていくのは人間的な手法です。神様はその全貌を知っていたとしても、人間が容易に観測することができるのはほんのその一部の量です。その一部として、微分(勾配)があります。例えばですが、雨の強さ(1時間に何ミリ降ったか)というのはアメダスを見ればすぐわかっても、1ヶ月間の累積雨量を時間を変数とした関数、つまり時間でどういう推移で累積雨量が変化していていったかを見たいというのはすぐわからないですよね。雨の場合はただ足し合わせるだけなので、今回の最小化とはちょっと違うかもしれませんが、いずれにしても木を見て森を見ずならぬ、木を見て森を推測すると言うべきでしょうか。森の全貌を知っているのは神様ぐらいなので。
理論
若干脱線してしまいましたが、機械学習ではない普通の最適化問題での最急降下法について。以下の資料にとても詳しく載っているのでさらっと。例も同じです。
例:$f(x,y)=x^2-2x+4y^2$の最小値を最急降下法で求めなさい
勾配ベクトルは、
$$\nabla f(x,y) = \biggl(\frac{\partial f}{\partial x},\frac{\partial f}{\partial y}\biggr)=(2x-2, 8y) $$
- $(x_0,y_0)=(0,1)$からスタート(初期値を適当に設定)
- $\nabla f(0,1)=(-2,8)$
- $f[(x_0,y_0)-\alpha\nabla f(x_0,y_0)]=f(0+2\alpha,1-8\alpha)$を最小にするステップ$\alpha$を選ぶと、$\alpha=0.13$
- 次の点は$(x_1,y_1)=(x_0,y_0)-\alpha\nabla f(x_0,y_0)=(0.26, -0.04)$
- 1に戻る…を繰り返すと最小値の点$(x,y)=(1,0)$に収束する
コード
Pythonで書くと次の通り。
import numpy as np
def steepest_descent(w0):
# w0 : 初期値のベクトル
w_before = w0
i = 1
while True:
# 勾配ベクトル
grad = w_before * np.array([2,8]) + np.array([-2,0])
# ステップ
alpha = (w_before[0]*grad[0]-grad[0]+4*w_before[1]*grad[1])/(grad[0]**2+4*grad[1]**2)
# 次の点へ
w_after = w_before - alpha * grad
# 収束したら終了
if (np.abs(w_after-w_before)<1e-6).all():
print("探索終了", np.round(w_before,6))
return w_before
# 繰り返し
print(i, w_before, "->", w_after)
i += 1
w_before = w_after
steepest_descent(np.array([0,1]))
1 [0 1] -> [ 0.26153846 -0.04615385]
2 [ 0.26153846 -0.04615385] -> [ 0.88923077 0.11076923]
3 [ 0.88923077 0.11076923] -> [ 0.91820118 -0.00511243]
4 [ 0.91820118 -0.00511243] -> [ 0.98773018 0.01226982]
5 [ 0.98773018 0.01226982] -> [ 9.90939208e-01 -5.66299499e-04]
6 [ 9.90939208e-01 -5.66299499e-04] -> [ 0.99864088 0.00135912]
7 [ 0.99864088 0.00135912] -> [ 9.98996343e-01 -6.27285599e-05]
8 [ 9.98996343e-01 -6.27285599e-05] -> [ 9.99849451e-01 1.50548544e-04]
9 [ 9.99849451e-01 1.50548544e-04] -> [ 9.99888826e-01 -6.94839433e-06]
10 [ 9.99888826e-01 -6.94839433e-06] -> [ 9.99983324e-01 1.66761464e-05]
11 [ 9.99983324e-01 1.66761464e-05] -> [ 9.99987685e-01 -7.69668295e-07]
12 [ 9.99987685e-01 -7.69668295e-07] -> [ 9.99998153e-01 1.84720391e-06]
13 [ 9.99998153e-01 1.84720391e-06] -> [ 9.99998636e-01 -8.52555650e-08]
14 [ 9.99998636e-01 -8.52555650e-08] -> [ 9.99999795e-01 2.04613356e-07]
探索終了 [ 1. 0.]
問題点
ただしこれにはいくつか問題点があります。
- この例の場合、唯一の極小値が大域的な最適解となったが、極小値が複数ある場合は収束結果が初期値に依存する
- 次のステップの計算そのものが、fについて最小化しているのと同然なので、目的関数の最小化を理論的に解けないと(微分=0とおいて数式で解けないと)最適なステップを計算することができない
- 機械学習の場合、fの最小化を数式で解けないからこういう計算をしているのであって、ステップ(学習率)をアドホックに導入してあげないといけない。そのため、初期値だけでなくステップの設定が大きく収束結果に影響を与える(最悪発散して収束しない)。
ただし、機械学習での最急降下法も確率的勾配降下法もこれとほぼ発想は同じなので、この例題を最急降下法で解ければ機械学習の確率的勾配降下法もほぼマスターできるはずです。
ラグランジュ未定乗数法
余談ですが、この例題も理論的にきれいに解くことができます(もちろん平方完成でも解けます)。制約条件のないラグランジュ未定乗数法と捉えられます。
ラグランジアンは、
$$L = x^2 -2x+4y^2$$
xとyで偏微分すると、
\begin{align}
\frac{\partial L}{\partial x} &= 2x-2 =0 \\
\frac{\partial L}{\partial y} &= 8y = 0
\end{align}
よって$x=1, y=0$となります。ラグランジュ未定乗数法結構なんでもいけるので自分は好きです。ここでも(偏)微分=0を使っているのを再確認できますね。
機械学習の最急降下法と確率的勾配降下法
2変数関数の最急降下法とほぼ同じです。機械学習の場合はステップが目的関数について解かないでもいけます。
機械学習の最急降下法も確率的勾配降下法も、和の形の目的関数を最小化する問題を扱います。確率的勾配降下法そのものについてはもっと良い説明がいっぱいあるので軽くさらうだけにします。
$$Q(w) = \sum_{i=1}^n Q_i(w) $$
これをループごとにバカまじめに
$$w := w-\eta\sum_{i=1}^n \nabla Q_i(w) $$
Σの中を全部計算するのを最急降下法(バッチ学習)、英語ではtotal gradient descentといいます。
対して、Qiをループごとにシャッフルして(ここがポイント)、シャッフルしたQiに対して
$$w := w-\eta \nabla Q_i(w) $$
とアップデートしながら反復するのを確率的勾配降下法、英語ではstochastic gradient descentといいます。どちらの降下法についても、ηを学習率といい、収束の有無や発散を決める最重要パラメーターです。
シャッフルすることが確率的で、シャッフルによって局所解にハマりにくくなるのが売り(らしい)。
確率的勾配降下法が局所解に陥らないことを保証するものではない
さて、確率的勾配降下法のWikipediaにこのようなことが書いてあります。
確率的勾配降下法の収束性は凸最適化と確率近似の理論を使い解析されている。目的関数が凸関数もしくは疑似凸関数であり、学習率が適切な速度で減衰し、さらに、比較的緩い制約条件を付ければ、確率的勾配降下法はほとんど確実に最小解に収束する。目的関数が凸関数でない場合でも、ほとんど確実に局所解に収束する
なぜこの点が気になったのかというと、ネットで探していると、大域的な最適解に収束する条件をすっ飛ばして「最急降下法は局所解に陥るが、確率的勾配降下法なら陥らない(極端な意訳)」というのを見て、自分は「???」となったからです。確かにこのWikipediaの表記もよく知らないで見ると、自分のように曲解するリスクはあるかもしれません。
実際前述の4次関数
$$y=x^4-4x^3-36x^2 \tag{1}$$
に対して、学習率を0.0001として、最急降下法と確率的勾配降下法のどちらで計算しても、初期値のxをプラスにするとx=6の大域的な最適解に収束しました。しかし、初期値のxをマイナスにしてしまうとx=-3の局所解に収束してしまいました(学習率の設定によっても変わるかもしれません)。なぜこれが確率的勾配降下法で計算できるかというと、確率的勾配降下法では、
$$Q(w) = \sum_{i=1}^n Q_i(w) $$
のように和の形で表される目的関数の最小化を行いますが、この4次関数は多項式なので、
\begin{align}
Q_1(w)&=w^4, Q_2(w)=-4w^3, Q_3(w)=-36w^2 \\
Q(w) &= Q_1(w) + Q_2(w) + Q_3(w)
\end{align}
とおいてしまえば、ループのたびに関数をシャッフルして確率的勾配降下法と同等のアプローチが使えたからです。局所解に収束した理由は単純で、(1)の4次関数が凸関数でないからです。関数fが凸関数であるとは、任意の$a,b$、$0\leq\lambda\leq1$を満たす任意の実数$\lambda$に対して以下の不等式を満たすものです。
$$\lambda f(a) +(1-\lambda)f(b)\geq f(\lambda a+(1-\lambda)b)$$
より直感的に捉えるなら、グラフ上の2点を通る直線を引いて、グラフがその直線の常に下にあるなら凸関数ということです。
x=-5→x=-2で引いた直線に対してグラフは常に下にありますが、x=-2→x=2ではグラフは直線の上にあります。x全体で見ればこの4次関数は凸関数ではありません。
つまり、極小値を探していけば結果的に大域的な最小値が見つかるというのは、目的関数が凸関数であるからというのが大前提にあるためで、勾配降下法が確率的かそうでないかというのが決定づけているのではありません。
確率的勾配降下法が最小解に収束する条件というのを探していましたが、原著の論文を当たらないとよくわかりませんでした(課金がいる)。AT&T研究所が出している論文は無料で読むことができ、最急降下法の局所解についてWikipediaより丁寧な説明がありました。
L´eon Bottou, “Stochastic Gradient Learning in Neural Networks” p.4より
The total gradient (3) converges to a local minimum of the cost function. The algorithm then cannot escape this local minimum, which is sometimes a poor solution of the problem.
In practical situations, the gradient algorithm may get stuck in an area where the cost is extremely ill conditionned, like a deep ravine of the cost function. This situation actually is a local minimum in a subspace defined by the largest eigenvalues of the Hessian matrix of the cost.
The stochastic gradient algorithm (4) usually is able to escape from such bothersome situations, thanks to its random behavior (Bourrely, 1989).
ここでいうThe total gradientとはバッチ学習での最急降下法です。『最急降下法では、局所解から逃げることはできないが、確率的勾配降下法(stochastic gradient)は乱数の挙動のおかげで局所解から脱出することができる』と書かれています。確かに、「確率的勾配降下法が局所解に陥らないことを断言はできないが、それでも脱出できる可能性はある」ぐらいの言い回しなら納得できます。
確率的勾配降下法のメリットとは?~最小二乗法で考える~
では確率的勾配降下法の具体的なメリットは何でしょうか?例えば収束の際の精度がよくなるとか、最急降下法では越えられなかった局所解を乗り越えて別の最適解にたどり着くとか、収束までのループが少なくなるとかそういう具体的な指標が欲しいのです。
ここでは単回帰分析の最小二乗法の例に取ります。最小二乗法についてはなんとなく理解している人が多そうなので説明は省略します。
参考:最小二乗法
回帰分析の最小二乗法
単回帰分析では、
$$ \hat{y_i} = \alpha x_i + \beta + \epsilon\qquad \epsilon\sim N(0,\sigma)$$
とyをxで推定。ここでεは正規分布に従う誤差項です(ただのノイズなので気にしなくて良い)。ここで目的関数は、訓練データの実測値$y_i$と推定値$\hat{y_i}$の差の2乗和ですから、
$$ Q = \sum_{i=1}^n (y_i-\alpha x_i-\beta)^2 $$
を最小化するαとβを選びます。これを展開すると次のようになります。
$$ Q = \sum_{i=1}^n (x_i^2\alpha^2 + \beta^2+2x_i\alpha\beta-2x_i y_i\alpha -2y_i\beta+y_i^2) $$
ぱっと見怖い式が出てきましたが恐れることはありません。$\sum x_i$や$\sum y_i$は全てデータから計算できるので、ただの数値です。そう考えるとこれはαとβの2次関数です。Σの中身はただの数値なのでこう置き換えましょう。
\begin{align}
\sum x_i&=s_x, \sum y_i=s_y \\
\sum x_i y_i &= s_{xy} \\
\sum x_i^2 &= s_{xx}, \sum y_i^2 = s_{yy}
\end{align}
すると
$$ Q = s_{xx}\alpha^2+n\beta^2+2s_x\alpha\beta-2s_{xy}\alpha-2s_y\beta+s_{yy}$$
αとβで偏微分し、
\begin{align}
\frac{\partial Q}{\partial\alpha} &= 2s_{xx}\alpha+2s_x\beta-2s_{xy} \\
\frac{\partial Q}{\partial\beta} &= 2n\beta+2s_x\alpha-2s_y
\end{align}
勾配ベクトルを行列表記すると、
\frac{\nabla Q}{2} = \begin{pmatrix} s_{xx} & s_x \\ s_x & n \end{pmatrix}\begin{pmatrix} \alpha \\ \beta \end{pmatrix} - \begin{pmatrix} s_{xy} \\s_y \end{pmatrix}
となります。これは先程のラグランジュ未定乗数法を使えば理論的に求まります(Qをαとβで偏微分して=0の連立方程式を解く)。暇な方は解いてみてください。
最小二乗法は凸関数
α=2、β=1(つまりy=2x+1)、ノイズは標準正規分布N~(0,1)に従う乱数としたときに、データ数10の場合の目的関数の3次元グラフを書くと次のようになります。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
np.random.seed(114514)
# y = 2x + 1 + e, e~N(0,1)とする
# α=2, β=1を推定する(実際はこのα、βは未知の値)
x = np.arange(10)
y = 2*x + 1 + np.random.standard_normal(10)
s_x = np.sum(x)
s_y = np.sum(y)
s_xy = np.sum(x*y)
s_xx = np.sum(x**2)
s_yy = np.sum(y**2)
def ols(a, b):
global x
global s_x, s_y, s_xx, s_xy, s_yy
return s_xx*a**2 + len(x)*b**2 + 2*s_x*a*b - 2*s_xy*a - 2*s_y*b + s_yy
alpha = np.arange(-5,7,0.1)
beta = np.arange(-5,5,0.1)
A, B = np.meshgrid(alpha, beta)
L = ols(A, B)
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(A, B, L, rstride=1, cstride=1, cmap=cm.coolwarm)
plt.show()
グラフの断面が2次関数であることに注目してください。やっていることは最初に出した2次関数の最小値を求めることの延長線上で、2変数に拡張しただけです。
グラフを見た感じ凸関数っぽいですよね。数値解法に行く前に最小二乗法の目的関数Qが凸関数であることを示しておきましょう。非常に美しい証明で、解いていて「おっ!?」となったのでぜひ味わってください。
関数Qが凸関数であるとは、ヘッセ行列$\nabla^2 Q$が半正定値であることと同値です。ヘッセ行列とは勾配ベクトルをもう一度偏微分したものです(なので∇の次数が2になっています)。
この関数Qのヘッセ行列は、
\nabla^2Q=\begin{pmatrix}\frac{\partial^2 Q}{\partial\alpha^2} & \frac{\partial^2 Q}{\partial\alpha\partial\beta} \\ \frac{\partial^2 Q}{\partial\beta\partial\alpha} & \frac{\partial^2 Q}{\partial\beta^2}\end{pmatrix}=2\begin{pmatrix}s_{xx} & s_x \\ s_x & n\end{pmatrix}
ある行列が半正定値行列であることを示すには、以下のリンクで記されている4つの性質のうち1つを満たせばよいです。
ここでは2次形式が負ではないことを示します。2次形式を使って書くと、
\begin{align}
& 2\begin{pmatrix}\alpha & \beta\end{pmatrix}\begin{pmatrix}s_{xx} & s_x \\ s_x & n\end{pmatrix}\begin{pmatrix}\alpha \\ \beta\end{pmatrix} \\
&= 2\begin{pmatrix}s_{xx}\alpha+s_x\beta & s_x\alpha+n\beta \end{pmatrix} \begin{pmatrix}\alpha \\ \beta\end{pmatrix} \\
&= 2(s_{xx}\alpha^2 +2s_x\alpha\beta +n\beta^2)
\end{align}
ここで$\sum_{i=1}^{n} x_i=s_x, \sum_{i=1}^{n} x_i^2=s_{xx}$とおいたことを思い出します。
\begin{align}
&= 2(\alpha^2\sum_{i=1}^nx_i^2+2\alpha\beta\sum_{i=1}^nx_i+n\beta^2) \\
&= 2\sum_{i=1}^n(\alpha^2x_i^2+2\alpha\beta x_i+\beta^2) \\
&= 2\sum_{i=1}^n(\alpha x_i+\beta)^2 \geq 0
\end{align}
したがって、最小二乗法の目的関数Qのヘッセ行列は半正定値、つまりQは凸関数となります。つまり、最小二乗法の局所解は大域的最適解としてよいことがわかります。
続いて、数値的に最急降下法、確率的勾配降下法を使っても解いて、結果を比較してみましょう。
最急降下法(TGD)の実装
def tgd(w0):
global x, y
global s_x, s_y, s_xx, s_xy, s_yy
# η=0.01とする
eta = 0.01
# 極小値を求める関数は Q(x,z) = s_xxα^2 + nβ^2 + 2s_xαβ - 2s_xyα - 2s_yβ + s_yy
# δQ/δα = 2s_xxα + 2s_xβ - 2s_xy
# δQ/δβ = 2nβ + 2s_xα - 2s_y
i = 1
w_before = w0
while True:
# 勾配ベクトル
grad = np.dot(np.array([[2*s_xx, 2*s_x], [2*s_x, 2*len(x)]]), w_before) - np.array([2*s_xy, 2*s_y])
#print(grad)
# 最急降下法でxを更新
w_after = w_before - eta / i * grad
# 収束したら(w_t+1 - w_t が十分小さくなったら)終了
if (np.abs(w_before - w_after) < 1e-5).all():
#print("反復終了")
return w_before, i
# 反復継続する場合
#print(i, "回目 w = ", w_before, "->", w_after)
i += 1
w_before = w_after
初期のηはサンプルにあわせて調整してください(収束速度が変わります)。和の部分は行列内積で計算しているので結構速いです。収束判定は「α,βの変化量がともに一定値(1e-5)未満になったら」で判定しています。この閾値を小さくすると精度は良くなりますが、収束に時間がかかります。
確率的勾配降下法(SGD)の実装
def sgd(w0):
global x, y
# η=0.01とする
eta = 0.01
# 極小値を求める関数は Q(x,z) = s_xxα^2 + nβ^2 + 2s_xαβ - 2s_xyα - 2s_yβ + s_yy
# δQ/δα = 2s_xxα + 2s_xβ - 2s_xy
# δQ/δβ = 2nβ + 2s_xα - 2s_y
i = 1
w_before = w0
indexes = np.arange(len(x))
np.random.seed(114514)
while True:
# インデックスをシャッフルする
np.random.shuffle(indexes)
w_tmp = w_before
for j in indexes:
# 勾配ベクトル
grad = np.dot(np.array([[2*x[j]**2, 2*x[j]], [2*x[j], 2]]), w_tmp) - np.array([2*x[j]*y[j], 2*y[j]])
#print(grad)
# 最急降下法でxを更新
w_after = w_tmp - eta / i * grad
w_tmp = w_after
# 収束したら(w_t+1 - w_t が十分小さくなったら)終了
if (np.abs(w_before - w_after) < 1e-5).all():
#print("反復終了")
return w_before, i
# 反復継続する場合
#print(i, "回目 w = ", w_before, "->", w_after)
i += 1
w_before = w_after
基本的にはTGDと変わりませんがシャッフルしているのがポイント。シャッフル以下のループ部分をforで書いているのでTGDより遅いです。ここを最適化するか、scikit-learnの組み込みのSGDを使ってください(あくまで理解用なので)。
TGDvsSGDの比較
解(α=2、β=1)の近傍で初期値を変化させてTGDとSGDの結果を比較します。$-1\leq\alpha_0\leq5, -2\leq\beta_0\leq4$でそれぞれ1刻みで動かしています。結果のシリアライズ用にMessagePackを使っています。
import umsgpack
result = {}
for m in range(2):
method = {}
method["param"] = []
method["ans"] = []
method["length"] = []
method["iter"] = []
for a0 in np.arange(-1,6):
for b0 in np.arange(-2,5):
print(a0, b0)
if(m == 0): itemv, itemi = tgd([a0, b0])
else: itemv, itemi = sgd([a0,b0])
method["param"].append((int(a0), int(b0) ))
method["ans"].append([float(itemv[0]), float(itemv[1])])
method["length"].append(float(ols(*itemv) ))
method["iter"].append(int(itemi))
if(m == 0): result["tgd"] = method
else: result["sgd"] = method
with open("regression.msg", "wb") as fp:
fp.write(umsgpack.packb(result))
比較するのは次の3点です。学習率や収束判定はTGD、SGDともに共通です。
-
推定値:真の値α=2,β=1に近いほどよい -
距離:推定値を目的関数に代入したときの値。誤差の大きさを示す。 -
繰り返し回数:収束までに要した反復回数。少ないほどよい
結果
グラフは以下の通りです。
左上から、推定値をα(横軸)、β(縦軸)でプロットしたものです。真の値(α=2,β=1)が中心とはなりませんでしたが、SGDのほうがTGDよりも密になっている(点がぎゅっと集まっている)ので、SGDのほうがより精度が高いことがわかります。
右上は繰り返し回数を示します。見づらいかもしれませんが、SGD>TGDとなる点もTGD>SGDとなる点もある一方で、若干SGDのほうがトータルでは低いように見えます。サンプル単位で繰り返し回数をTGD,SGDで比較したところ、49サンプル中、繰り返し回数がTGDのほうがSGDより少なかったのが21サンプル、逆にSGDのほうがTGDより少なかったのが28サンプルとなりました。この例の場合は、1.3倍ほどSGDのほうが優勢となりました。
左下は同様に距離を示します。距離と繰り返し回数は全く同じで、距離が大きいところでは繰り返し回数も多かったです(なので収束判定において、目的地に近づいたことよりも、反復数が増えて学習率が減衰していったために1回のステップが限りなく小さくなったことのほうが支配的かもしれません)。49サンプル中、SGDのほうがTGDより距離が小さかったのは28サンプル、逆は21サンプルでした。また、距離の平均はTGD=8.471、SGD=8.421でSGDのほうが平均的に距離が小さくなりました。
右下は距離について、SGD÷TGDの比率を計算したものです。1より低ければその初期値に対する収束結果の距離についてSGDのほうが良い結果を出している、1より大きければTGDのほうが良い結果を出していると言えます。0.925、1、1.075に補助線を引いてみましたが、全般的に下に寄っていますよね。なのでここからも、この例の場合はSGDが優勢であったことが確認できます。
以下のコードで確認できます。
with open("regression.msg", "rb") as fp:
result = umsgpack.unpack(fp)
ans_tgd = np.array(result["tgd"]["ans"])
ans_sgd = np.array(result["sgd"]["ans"])
len_tgd = np.array(result["tgd"]["length"])
len_sgd = np.array(result["sgd"]["length"])
iter_tgd = np.array(result["tgd"]["iter"])
iter_sgd = np.array(result["sgd"]["iter"])
print(len_tgd)
print(len_sgd)
print(len_tgd - len_sgd > 0)
print(np.bincount((len_tgd - len_sgd) > 0))
print(np.bincount((iter_tgd - iter_sgd) > 0))
print(np.mean(len_tgd), np.mean(len_sgd))
全てにおいて確率的勾配降下法が有利?→そうとも限らない
なら全部の最適化で確率的勾配降下法のほうが最急降下法より有利かと言ったらそうでもありません。深くは触れませんが凸関数の制約を外して、
$$ \hat{y_i} = \alpha^2 x_i + \beta^2 + \epsilon$$
$$ Q = s_{xx}\alpha^4+n\beta^4+2s_x\alpha^2\beta^2-2s_{xy}\alpha^2-2s_y\beta^2+s_{yy}$$
このように$\alpha^2, \beta^2$についての最小二乗法で解いてみると、TGDのほうが良い結果を出しました(単に収束まで至っていないのかもしれない)。この関数のグラフとサマリーだけ張っておきます。αもβも-4~4まで1刻みで動かしました。初期の学習率は0.00001としました(通常の最小二乗法と同じ初期値を使うと発散してしまいました)。
この場合は明らかに凸関数ではない(cf.最初の例の4次関数が凸関数ではない)ので、最小二乗法の最適化とはまた違うのかもしれません。確率的勾配降下法のほうが明らかに有利になる具体例というのがあれば興味がありますね(前節の最小二乗法の場合は1反復=全てのシャッフルされたサンプルを反映し終わったで見ているので、繰り返し回数が減らなければ計算量面でのメリットはありません)。
まとめ
冒頭の疑問は「確率的勾配降下法の具体的なメリットはなんだろう」でしたが、最小二乗法を通じて最急降下法(TGD)と確率的勾配降下法(SGD)の両方のアルゴリズムで比較を行うことで、SGDのほうが数値的に良い結果を出すことがあるというのが確認できました。全ての最適化において言えるまでは至っていませんが、具体的に良くなる例を確認できたことは有意義だったと思います。
そもそも数値計算自体、大域的な最適解(best)を出すものではなく、最適解に近いより良い局所解(more better)を出すものと考えれば、局所解自体が悪いわけではないのかと思います(局所解から出られなくなることや、局所解を最適解と誤検出することが問題)。凸関数?なにそれおいしいの?というレベルで複雑な1モデルで局所解が100や200ある場合は、その中から最良のものを選ぶのではなく、よりよいものを選ぶほうが現実的かと思います。あくまで人間的な手法なので。
理論的に数式変形をして解くのが神様の視点であるのに対して、コンピューターを使った数値計算が人間的な視点であると述べましたが、「神はサイコロを振らない(振らなくてもよい)のかもしれないが、人間はサイコロを振ったほうが有利になることがある」というのはなかなか面白い結論だと思います。
-
あまり縁がなさそうに思えるが、正規分布の元になっているガウス関数を足し算で組み合わせれば1変数関数でも大量に局所解のあるグラフを簡単に作り出すことができる。 ↩
- JuliaでPyPlot.jl (matplotlib) を使ったヒストグラムのアニメーションを効率的に作成する
- 栄養素多次元ベクトル間の類似度を計算する
- Kerasのbackendが、思い通りならない時のメモ
- scikit-learnでSVMのパラメータを調節してみた話
- matplotlibでよく使う手続き
- Djangoのモジュールをインタープリタで読み込む
- PythonでRandom Forestを使う
- 文字と濁点・半濁点が分かれていて,それらを結合したい時
- NLTKを使って情報利得を計算
- PythonとTkinterを使ってプログラミング
- pythonのunix-time <-> datetime の変換
- Pythonの-mオプションを使えばフィルターの管理が楽
- doctest.testfile()を使ってドキュメント兼テストコードを作成
- カレントディレクトリをwebサーバで公開
- ニコニコ生放送のコメントを取得する
- tkinterを使ったアプリケーションをcx_freezeで実行ファイルにする
- ネスト解消のためのポリモーフィズムについて
- Google+で見かけたコメントに,「Pythonでリストの何番目の要素が最大/最小か求める簡単な方法は?」というのがあった.真っ先に思いついたのが1行目のコードなのだけれど,2行目の方がより良いかな?
- 日本語を含むUnicodeのJSON文字列を得る.
- Pythonでテストする際には何を使っているか?
- JSON変換するクラス
- FlaskでBlueprintを使ってControllerを別に分けてみる
- Pyramidで遊ぶ
- Pythonでconstant
- プログラミングの師匠募集
- ドミニオン圧縮プレイをモンテカルロ法で分析
- Pythonでテストを書いてプロファイル取ったりカバレッジ調べたり
- Pythonにおける例外のメッセージ
- 使ってないポートを取得する Python版
- 文字から Unicode を算出する
- どうやって情報収集してますか?
- Google App Engineのwebapp.RequestHandlerはputとdeleteを受けるときパラメータを取得できない
- 空のディレクトリに.gitkeepを配置するコマンドラインツール
- php でも ruby でも python でも perl でも動く Hello World
- amazon linux上で、python2.7用にMySQL-pythonをコンパイル・インストール
- # 文字列の文字コードを返す関数
- ImportError: cannot import nameを解消する
- JSON の整形
- pythonインタプリタ起動時に良く使うmoduleをimportする
- IPython起動時にスクリプトを自動的に読み込む
- UNIXでPython,Ruby,Perl,Node.jsのバージョン管理環境構築
- unicodeとdecodeとencodeについて実験した
- エロ動画フォルダからサムネイルをopencvで楽に作る
- appcfg.pyでデプロイしたファイルをダウンロードする
- OS X LionでPython開発環境を作成
- Django+MongoDB開発環境整備 (書き途中)
- List 操作メモ書き
- 引数のデフォルト値はimmutableなものにする
- すっと頭に再帰が浮かぶようになりたい
- Google App Engineのpythonのバージョンが噛み合わない問題について
- Pythonで数値計算
- 辞書のキーにタプルを使って、複数キー項目
- Pythonでflatten
- Xcode用自動ビルドバージョンインクリメントスクリプト
- Pythonでtest.pyを作るな!
- ファイル監視にwatchdogがかなり便利な件
- Flask on dotCloud でハマったところ
- easy_installでインストールしたパッケージを削除する方法
- pythonbrewでの複数バージョン&ライブラリ管理メモ
- Python de BDD (Lettuceで)
- CentOS 5.4 に Python 2.7.3 を install
- pip のコマンド/オプションのタブ補完を有効にする
- boto で S3 アップローダー
- 「オープンソースで学ぶ社会ネットワーク分析」におけるpythonコマンド
- 一度だけ評価するプロパティ
- SQLAlchemy ORM でクエリ生成の高速化
- Django の django-admin.py でパスを通しても command not found の時
- Django でデコレータを使って View への preprocess を実装してみる
- Pythonで関数合成
- Sublime Text で pythonbrew
- Paver を使ったスクリプティング – コマンド定義編
- Paver 応用編 – プロジェクトに組み込む
- Paver を使ったスクリプティング – ファイル操作編
- Paver を使ったスクリプティング – 外部コマンド編
- VPC with a Single Public Subnet Only を boto で自作
- 指定時間内に関数が終了しなかったら何かするデコレータ
- はじめてのDjangoで躓いた箇所まとめ
- BitbucketのOAuth:access token取得まで
- python でモック – mox の使い方
- Djangoのコマンド補完設定
- Python の Singleton
- すごく簡単なアルゴリズムがphpで書けなくてつらい
- Unix Domain Socket サーバーを作る
- プログラミングの学習に役立つウェブサイト
- DMMのAPIを叩くクラス
- letを作ってLet’s 1行プログラミング
- Setup modern Python environment with Homebrew
- Pygments.rb を使う
- Mailmanのwithlistコマンドによる一括設定変更
- ハイフン区切り形式の MAC アドレスを取得する -1 liner 編-
- Zsh上で使用頻度の高いコマンド一覧を表示する
- Python で複素数を扱う
- PyQt4導入
- 重み付け乱択
- Pythonのキーワード引数も含めてmemoizeしたい
- Ubuntuで個人環境にpythonパッケージをインストール
- pythonでUTF8のテキスト処理
- NLTKを使って文書分類用データをサクッと作る
- 最速最強Webサーバーアーキテクチャ
- 「Sublime Text 2で全角スペースをハイライト表示するプラグインを作る」に設定でオンオフ出来るようにしてみた。
- SublimeLinterにD言語(他の任意の言語)を追加してハイライト出来るようにする
- pythonの文法チェック
- defaultdictを使って,ネストされた辞書を作る
- SQLAlchemy BaseModel
- Python で Amazon CloudFront の Signed URL を発行する
- PyOpenCL Version 2012.2の話 第1弾
- TortoiseHgのファイルビューをもう少し改造してみる
- Docutils と Ruby で快適ドキュメント生活
- numpyの練習1
- スクリプト言語で実行可能なファイルを作る
- パラメトリックとノンパラメトリックの狭間
- bing search apiの使い方
- Flaskのカスタマイズについて
- PyOpenCLでアプリケーション(PIL & PyOpenGL)
- pytestを実戦投入してみた
- いとも簡単にMac OS XにSciPyをインストールする
- 実務でRandomForestを使ったときに聞かれたこと
- gaffer + fabric で簡単デプロイ環境
- Theano の 基本メモ
- 実行スクリプトからの相対パスでファイルにアクセスする.
- CoffeeScriptとJavaScriptやPythonやRubyの文法の比較
- これ知らないプログラマって損してんなって思う汎用的なツール
- 【まとめ】これ知らないプログラマって損してんなって思う汎用的なツール 100超
- Python での shift_jis と shift_jis_2004 について
- リストの中のインスタンスのもつ値で検索
- 日時 ⇔ 文字列
- ファイルの更新を検知して、自動的にCoffeeやSassをコンパイルしたり、ブラウザをリロードしたりするスクリプト
- curlを捨ててhttpieを使おう
- 都道府県のリストをサクッと出力するだけのCLIツール
- Python でホスト名を取得する
- MinGWでVimをビルド。(+lua,+python)
- 複数の辞書のマージ方法いろいろ
- LinuxでPythonをビルドするときの –enable-shared オプションについて
- pythonで二分探索
- Qiita API の Python ラッパーを作った
- Haskellソース編集後、保存と同時にghciにロードするSublime Text 2プラグイン
- botの一部の機能として自動フォローやランダムツイート
- kobitonote.py – Kobitoで編集したアイテムをEvernoteに同期保存
- Command Line で使用しているツールまとめ vol.5
- Flaskを1ヶ月間使ってみた感想
- Pythonのfeedparserをつかってみる。
- Pythonで文字列 <-> 日付(date, datetime) の変換
- Qiitaの投稿をGitHubにバックアップ
- Pythonプログラムのプロセス名を設定する
- Xcodeプロジェクト内のクラスの依存関係を図示する
- Python スクリプト実行中にシェルを起動する
- SQLAlchemyでINNER JOINする方法
- pymongoで正規表現
- Windows + Python 3.3 で watchdog をインストールする
- プログレスバー表示させたいなぁ
- Pythonでconfig.iniを使う
- Twistedを利用してお手軽にDNSサーバーを構築する
- 今流行りのエディタSublimeText2を使って、AOJで競技プログラミングを楽しもう
- PythonでN-Gram
- Parse.com REST APIを使ったAPN(remote notification)を試した
- Apache + mod_wsgi で複数の WSGIPythonPath を設定する
- クラスにバインディングしてYAMLの読み書き
- SublimeText2とSublimeLinter – Python3の構文チェック –
- Pinaxの概要について簡単なまとめ #djangoja
- アクセサを一つのメソッドにまとめる
- PythonのPILで書き出したGIF画像をつなげて動画GIFを作る
- Pythonで画像をWavelet変換するサンプル
- TheanoをMac OS Xにhomebrewでinstallする方法
- BitbucketのPrivate repositoryをタダでCIする
- Python3.3 + mod_wsgi3.4 をさくらVPS(CentOS)にインストールした時に少しハマったので振り返りメモ
- [Python2]日付文字列→UnixTime→日付文字列
- Install Theano on Ubuntu 12.04
- Vim (with python) で json を整形
- tweepy2導入
- PyramidのテンプレートをMakoに切り替える
- propertyを使うときはobjectを継承したクラス (new-style class) を使う
- redis-pyの使い方 辞書とか
- コマンドラインからtwitter投稿
- 標準入力の受け取りのその1
- Python – MP3ファイルにタグづけ
- ファイルを保存した瞬間ユニットテストを実行
- Python – Django css・jsをコンプレス
- requestsが便利
- リスト内に特定の要素があるかでif分岐
- Pythonの辞書 初心者向けガイド
- fabricのお役立ちコンテキストマネージャ
- FlaskでLast-Modifiedを設定する最も簡単な方法
- Flaskのrequest.argsでパラメータの処理について
- ブラウザでPython:Brythonのすすめ
- MeCab解析済みの結果を読み取るcorpus readerを書いた
- PythonでCIDR表記を変換
- multiprocessingで並列処理
- ログ監視スクリプト
- Ubuntu12.04にPython3.3をインストール
- 今更 virtualenv を使ってみる
- lxmlでブロークンなXMLをパースする
- 永続性が必要な時は hash() を使うな!
- Fabricタスクの途中で実行ユーザーを切り替えたいときはsettingsコンテキストマネージャ
- pythonからfluentdを使う
- Vimのpython3で日本語表示するの面倒くさすぎワロタwww
- MochaでブラウザテストをするためのWebサーバ
- 行数あたりの価値が高いコード
- Python で日付の計算
- コマンドラインで XLSX を CSV に変換する
- ファイルの中身を簡単な暗号化(Python)
- Pythonで文字列からさくっと文字の出現頻度を数えるには?
- GAE/Pyのdev_appserver.pyで外部(localhost以外)から接続可能にするには
- RubyとPythonじゃデフォルト引数の値が評価されるタイミングが違うんだぜ
- Python 3の print() で UnicodeEncodeError を回避するデコレータ
- Google Calendar から日報を生成する
- MeCab 使ってよみがなを取ってくる
- PyCharm での type hinting を使いこなす
- Django – Apache mod_wsgi virtualhost デプロイ
- ブラウザで保存したファイルをダウンロード元サイト別にフォルダ分け
- BitBucket に Sphinx ドキュメントを push したら自動的にウェブサーバーに反映するようにしてみた
- Sublime Text 2でPythonの開発環境を整える
- SciPyとmatplotlibのインストール(Python)
- Twistedを利用してメールサーバーを立てる
- SciPy+matplotlibで3D散布図を作成(Python)
- CentOS 6.x x86_64 Python-2.7.4 rpmパッケージ作成
- pythonの例外でstack traceを表示する
- lambdaでif-elifを楽に書く
- Python, SciPy, matplotlibのインストール(Windows)
- Python 3の正規表現で \d を使うな!
- CentOS6.4でPython2.7.3でApacheでmod_wsgiでDjango
- f2pyを使ってfortranでpythonのモジュールを書く
- ネットワークインタフェースに振られた IPv4 アドレスをコードで取得する (Linux)
- sphinx+mathjaxでマクロをusepackageみたいに読み込む
- iPythonでオートフォーマットされた出力の改行場所を変える
- Python3.3.1 in BottleでGoogle Custom Search APIを使って検索するだけのアプリケーションを作る
- Pythonでリフレクション
- pythonでhtml中の相対リンクを絶対リンクに書き換える(lxml)
- Pythonスクリプトからjarファイル中のクラスを直接importする
- class sklearn.naive_bayes.MultinomialNB(alpha=1.0, fit_prior=True, class_prior=None)のメモ
- pythonの軽量framework, Bottle
- GAE上でのTwilio
- リプ爆撃
- Twilogから過去ツイートを取ってきてbotを作り、昔の自分をTLに再現させるでござるの巻(その1)
- Macを使うにあたっての落とし穴回避(Linuxユーザ向け?)
- PyQCheckというPythonでQuickCheckが行えるライブラリをPyPIに登録した。
- multiprocessing vs threading
- MacにPythonをインストールするときのメモ
- Webアプリケーションのパフォーマンス測定ツールFunkload…
- python データーを圧縮してsqliteへ書き込む
- Zabbix APIをたたく (1.8, 2.0)
- emacs-jediのinstall
- Twilogから過去ツイートを取ってきてbotを作り、昔の自分をTLに再現させるでござるの巻(その2)
- テストデータはsetUpで宣言するべき幾つかの理由
- pythonをはじめるためのリンク
- a()とa.__call__()は等価ではない
- Python で簡易 SMTP サーバを立てる
- ログを色つけて見やすくする君
- 【LDAP環境構築:7】 Pythonでユーザー追加・検索・変更・削除まで
- classの__str__を、lambdaを使ってもっと簡単に書こう!
- MacにDjangoをインストール
- ChaSenのインストール
- CPythonからJavaのクラスを呼び出す(Py4J)
- テキストファイルのエンコーディングを自動判定して処理する
- pythonのsqlite3 に日本語(マルチバイト文字列)を格納する
- pythonのsqlite3でインメモリDBをセーブ/ロードする
- Python+FlaskなwebアプリをJenkinsでウイーン
- pyramidチュートリアル メモ (bankaccount)
- ローカルのipアドレスを取得
- macbook air Mid2013 にインストールしたアプリや開発環境のメモ(php,ruby,node.js,python など)
- PySideのスロットを定義する際の注意
- はてなブックマークのお気に入りユーザーで、既にアクティヴではないユーザーを調べる
- フォーマット文字列内での波括弧のエスケープ
- Pythonの数値計算ライブラリ NumPy入門
- PySideのスロットを定義する際の注意(2)
- vim7.3(+python2.4)をソースからインストール(Gundo.vimに対応)
- PythonからMySQLを使う
- コンソールへの出力を上書きしてゆく方法
- Pythonzとvirtualenvでクリーンなpython環境
- WEBブラウザからコマンドを実行する君作った
- ATND APIをPythonで叩くときのtips
- pytestを使ってカバレージとか取りながら分割実行してテスト実行時間を短縮する
- Pythonのクラス定義のファイルの場所を知る。
- encodeするのがめんどくさい
- はじめてのpython① pythonbrewで環境構築&HelloWorld!!
- Google Cloud Messaging for Chrome を使ってサーバからChrome拡張にメッセージを送る
- Pythonでコマンドライン引数にサブコマンドを指定する
- WEBブラウザから検索やコマンド実行をする君2
- 多重ループを一気に抜ける
- Pythonでgitのコミットログをパースしてみよう!
- Pythonで再帰的にファイル・ディレクトリを探して出力する
- 『Macで日本語ファイルをgitにコミットするのやめて><』とりあずMacとLinuxで互換性のない日本語ファイルを探すスクリプト書いた
- Flaskで大きいアプリケーションを作るときのTips
- 1分でVim+Pythonのテスト環境をつくる
- 深イイ意味など全くない並列処理 in Python
- 電波状況が悪い時にiPadにファイルを転送する
- matplotlibでstacked histogram (積み上げヒストグラム) を書く
- pipでtweepyをインストールしてAPI1.1に対応させて使う
- python2.7.3のcsvモジュールを使う時の文字エンコード
- Pythonで”coding: utf-8″ 書くの面倒くさいのでShellscriptでなんとかする
- Pythonで関数合成と適用的な
- pythonでフォルダ内のファイル名をrenameして整理したメモ
- 【作業メモ】Amazon Linuxにmatplotlibとnumpy入れるまで
- Appiumを使ってスマートフォンアプリのテストを自動化する – Python編
- matplotlibで欲しいグラフの書き方がわからない時はgalleryを見ると便利
- web2pyのadminのpassword
- PIL(Python Imaging Library)で、点を描画するサンプル。
- Mac OS Marvericks にHomebrewを使ってpyenv,pythonの環境設定を行うメモ
- PIL(Python Imaging Library)で、画像をセピア調に変換する
- PySide – モードレスダイアログを表示中にバックグラウンドで何らかの処理を行う
- Python用ケムインフォマティクスツールRDKitのインストール
- バックアップにBakthatいいんじゃね?
- Pythonのreduceを使うとちょうはかどる話
- Pythonにおける継承の基本的なお話(初心者向け)
- Pythonの古いクラスと新しいクラスの話
- unittest.mock
- MySQL Workbench の mwb ファイルから sql ファイルに自動変換
- ipythonの便利な使い方
- Propertyデコレータを使う?
- MySQLの全DBに対してmysqldumpするスクリプト
- pyramidチュートリアル メモ (single_file_tasks)
- Sublime Text 2で任意のテキストを常にハイライト表示するプラグインを作る
- 時間計測
- [python] lassieでWebページのメタデータをサクっととってくる
- オブジェクトの属性を取得
- classをクロージャーっぽく動的に宣言する
- MySQLdbの優雅な使い方
- PythonのiteratorとRubyのEnumeratorを比較してみた
- ImportError: No module named と言われた時の対応方法
- LXCをブラウザで操作できるLXC Web Panelが素晴らしかった件
- 非エンジニア向けのMercurial入門
- blogの更新を監視して結果をtwitterに投げたり、interviewsの回答を催促したり
- Pythonのモジュール例外の表示を分かりやすくする
- CentOS 6.4 で python から MySQL につなぐ
- EmacsのPython開発環境構築メモ
- Pythonでオブジェクトの内部構造を知る方法
- HMAC 方式を使用してハッシュ値を生成する。
- MySQLdbでイテレータ
- Bottle を使用したウェブアプリケーション(1)
- IPythonのデバッガー(ipdb)の使い方
- Pythonの例外クラスのインスタンスを直接、例外クラスの引数にするな!
- lambdaを使う例
- ベータ分布をPythonで書く
- Python 3のsorted関数と比較関数
- Pythonでバイナリファイルを作成する
- AKBメンバーのGoogle+ IDを一気に取得する
- サクラエディタでスクリプトをデバッグする
- Python3.3.1 + Bottle でWebアプリケーション(1) – テンプレートエンジンをjinja2に変更する
- botで天気予報をtweet
- 値が空だったら初期化したい(python)
- 【失敗】Stack OverflowのClone AskbotをCentOS6.4にインストール
- redis.pyのConnectionPoolの実装よんだ
- リスト内包表記でifの判定
- Gmailの件名をtwitterに投稿
- 標準入力で受け取ったりとかコマンドライン操作からGmailの送信
- python 現在時刻取得
- scikit-learnのParallelで並列処理
- 時系列顧客ロイヤリティの算出
- matplotlibでグラフを動的に生成して、reporlabでPDFに埋め込む
- Pythonで逆アセンブラする
- OpenCV2.4(+python)を手っ取り早くOS Xにインストールしてサンプルを試してみる
- AKB48 Google+投稿をゲットする
- eggパッケージのインストールとアンインストール
- すぐにできるページランク計算(全行コメント解説つき)
- MeCabをPython3上から使えるようにする
- matplotlibやpylabで論文向きの白黒のグラフをプロットする
- pythonモジュールの一覧表示
- djangoコマンドの二重起動を防止する
- Scipyでの疎行列の扱い
- OptParserの使い方
- pycharmのショートカット
- Pythonで単語の数え上げとかするならCounterを使うと便利なはなし
- 1分でPython&CSSセレクタによるスクレイピングを実現する
- web アプリケーションで matplotlib の図を表示する
- MacでPython環境構築メモ
- pythonのfluentdではまりどこ??
- pythonのSimpleHTTPServer
- fabric でエラー時のロールバック処理をする
- RubyとPythonとPerlで正規表現の速さを比べてみた(2013年版)
- ランダム文字列生成(Python)
- Python for Data Analysis Chapter 2
- Python for Data Analysis Chapter 3
- Python for Data Analysis Chapter 4
- virtualenvごとにPYTHONPATHを切り替える
- Mac(Mountain Lion)にPython環境を構築
- matplotlibのインストール(Python 3.3.2)
- py2exeとsetuptoolsの連携
- Mountain Lion環境への「virtualenv」と「pythonz」のインストール手順 + 利用方法
- urllib.parse.quote関数使用時の注意
- GoogleAppEngine/PythonでDjangoを使う方法
- 三角関数とか使ったメモ
- OSXでのCython実行方法メモ
- 今どきのPythonのライブラリ自作からPyPIへの登録
- 実行時間とかメモリ使用量とか気にしてみようと思ったから
- pythonbrewでPythonインストールしてFlaskをWSGIサーバで動かすまで
- Python で画像フォーマット
- Pythonのクラスで__eq__などを汎用的に実装する
- Mac に matplotlib をインストールする手順
- Python3をさくらサーバー(FreeBSD)にインストール
- ファイルの削除にrmコマンドは使わないようにした
- ruby は インスタンス変数の確認に instance_variable_defined? を使う
- twitter利用時間をを基準にざっくりと推定睡眠時間を計算する
- Djangoのモデルでchoice属性で値を限定しているフィールドの「名前」を取得する方法
- watchmedo(watchdog)を使ってエディタでファイルを保存する度にテストを実行する時の設定
- Celeryの非同期処理中に起きたエラーをメールで通知
- Pythonライブラリのダウンロード数表示バッジを生成
- virtualenvでpython
- randintに気をつけよう
- Pythonで日本語メールを送る方法をいろいろ試した
- MarvericksにしてPILのインストールがコケる件
- Django管理サイトのチューニング
- AnacondaでPython3.3
- MacOSX Mavericks(10.9)にhomebrewを使ってDjangoの開発環境を整える
- Python 3.3でmatplitlibとpylabを使おうとしたら RuntimeError: Python is not installed as a frameworkというエラーが発生したときの解決方法
- GensimPy3を使って小説家になろうのトピックモデルを解析
- `return self`でメソッドチェーン
- Python3.3.1でcChardetとpython3-chardetを使ったメモ
- pythonのデフォルトエンコーディングをutf-8に変更する
- utf-8を含む文字列を含む配列をprintしたときに文字化けする問題
- importについて
- TOPIX の時系列を表示する
- zip関数の挙動を少し試した
- django の dumpdata コマンドの代替
- scikit-learnでCross Validation
- TOPIXの時系列を pickle, csv, Excel形式で保存する
- 機械学習ライブラリ SHOGUN入門
- Python初歩からの学習メモ1
- Python初歩からの学習メモ2
- #python pythonの日本語のシンタックスエラー回避
- python-sphinxで表を書く時は csv-table を使った方が便利
- リスト操作とか競技プログラミングで使ったりした私用メモ
- Python3.4からpipが標準インストーラに!?
- rauthでTwitterAPIにアクセスするのが簡単すぎて、僕にも彼女が…
- ダミーデータファイルを作る
- Mac OS Xで複数バージョンのPythonを利用する(1)複数Verインストール編
- Mac OS Xで複数バージョンのPythonを利用する(2)利用編
- 不均衡データにおけるsampling
- “__slots__“を使ってメモリを節約
- pythonで日時の差分を秒単位で出す方法
- PythonでStateモナド
- 【募集】プログラミングのスキル交換をしませんか
- Supervisorで簡単にデーモン化
- Pythonでlet式を使う
- AWS コマンドラインインターフェイス(Python/awscli)をMac OS Xで利用する手順
- Pythonのパッケージ管理ツールez_setupの覚書
- sitecustomize.py を使わず usercustomize.py を使おうね
- ローカルのGAEを同一LAN内のiPhoneのブラウザから確認する方法
- はじめてのPython 素数に0, 1をくっつけて返すスクリプト
- PythonでCSVの読み書き
- easy_installのインストール
- Pelican ブログのインストール方法
- PythonでNetCDFの読み書き
- テキストファイルから指定した文字列を含む行を出力する
- pythonメモ:easy_installが使えないとき
- ベイズ線形回帰(PRML§3.3)の図版再現
- ラテン語文解析プログラムを書くことを目的としたラテン語学習(前編)
- MongoEngineでMongoDBを触ってみる基礎編
- Translate Toolkitで翻訳ツールを作る
- Pythonでカバレッジを調べる
- たぶん1分くらいでできる形態素解析とtfidf(テストコードつき)
- ChatWork API を叩く PHP と Python のサンプル
- LXCをPythonから操作する
- sympyで運動方程式
- APSchedulerで少し進んだジョブスケジューリング
- IntelliJ IDEAのPythonプラグインからもvirtualenvが使える
- Pythonのクラスメンバのスコープまとめ
- Keynoteに美しくスニペットを貼る
- ラテン語文を合成音声で読み上げる技術
- SphinxでPythonドキュメントを自動的にビルド
- b-Bit MinHashを使ったサイトのカテゴリ分類
- とにかく簡単に JSON データを確認したい
- 第16回オフラインリアルタイムどう書くの問題をPythonで解いてみた
- DJangoメモ:はじめから(準備編)
- Pythonでニュース速報(嫌儲)のスレッド一覧を取得してみる。
- scipyとか使ってみる
- scipyでフィルタ作成
- numpyでハミング符号
- ὑμήνπτερόν
- feedparserで自動的にねこ画像を拾ってくる
- pyOpenGLでシェーダープログラミング
- DJangoメモ:はじめから(モデル設定編)
- DJangoメモ:はじめから(管理画面を使う編) myハマりポイント
- pythonのunittestのassertXXX一覧
- 秒速でねこ画像を集めてネコヒルズ族を目指す
- ScipyでICA
- Docker で Google AppEngine 開発
- 最小お釣問題について考える
- DJangoメモ:はじめから(管理画面をもっと編集編)
- Python でテスト
- AnsibleのPython APIを試す。
- Pythonのインストール(Windows)
- DJangoメモ:はじめから(ビューを作る編)
- ConfigParserモジュールの使い方
- [Python] virtualenvとは何か
- Python の subprocess で出力を受け取るときは communicate() を使おう
- はてブのホッテントリのタイトルを要約してWebの今を見つめる
- DJangoメモ:はじめから(テンプレートからビューを作る編)
- Python3.3でナイーブベイズを実装する
- Python3.3でナイーブベイズを実装する
- 犬派と猫派の勢力図をGoogleChartAPIでグラフ化して決着をつける
- Python3.3で実装したナイーブベイズをBing APIで取得したWebページで学習。文章を分類させる
- 【cocos2d-x 3.0】binding-generatorでScript Bindingを自動化する方法
- iOS実機のSSL通信をプロキシによって傍受したり改ざんする方法
- DJangoメモ:はじめから(エラー画面設定編)
- 少しのコードでWebPayを導入する Python Ver.
- カレントディレクトリをドキュメントルートとしてHTTPサーバを立てる
- DJangoメモ:はじめから(URLConfの単純化と分割)
- AnsibleでPython(正確にはJinja2)の文法を生かしたスマートな条件文の書き方集
- MacOSXにSphinxをインストール
- Ansibleを導入したい人の為のくどきポイント
- DJangoメモ:はじめから(フォーム処理)
- DJangoメモ:はじめから(汎用ビューの使用)
- FlaskとPILImageを使ってリサイズした画像をResponseする
- Python3.3で実装したナイーブベイズ分類器を利用して、文章と文字列中の語の共起頻度から、類似度を計算する
- herokuでDJangoページを公開:準備編 myハマりポイント
- Pythonライブラリ・Botoで素敵にAWSを管理する
- Pythonメモ:pipコマンドが使えないとき
- FlaskからWebPayを導入する
- SublimeTextに実績機能をつけた
- pythonでもっとも簡単に音声合成する方法
- Python Jinja2
- PythonでLeapMotionを使ってみる
- 今週のアルゴリズム:最短経路の計算!(Ruby/Python/C#/VB/Goでpermutation iterator)
- 今週のアルゴリズム:最短経路の計算!(PHP/Python/Ruby/HSPでnext_permutation、Perlでpermutation iterator)
- scikit-learnでtf-idfを計算する
- CMake+SWIGで簡単にC/C++の多言語バインディングを実現する
- JavaScriptでもジェネレーター関数
- Mac OS X 開発環境構築メモ
- pandasメモ
- herokuでDJangoページを公開:実践編
- 30C3 CTF オンライン予選大会の PyExec 問題紹介
- wxPythonをMacOSXにインストールする際に「”〜.pkg”は壊れているため開けません。」のメッセージが出たときの対処法
- python3でtwitter
- Twitterでつぶやく
- Twitter-Pythonの使い方
- numpyで行列の斜めのやつを取得する
- python の map オブジェクトを list にした後は何も残らない
- PythonとPHPで文字列分割をして配列の最後の要素を取得
- Google App Engine for PythonでTweet(API1.1)
- pythonでmarkdownを扱う
- Matplotlibによるヒストグラム透明重ね書き
- Pythonで標準出力をnon-blockingにする
- 1分で実現できる!関数の実行結果をmemcachedにキャッシュするデコレータ
- pythonクイズ
- ワンライナーWebサーバを集めてみた
- X-SendFileを用いて静的ファイルをサーブ
- herokuでDjangoブログ:ログイン実装
- Command Line で使用しているツールまとめ vol.8
- APIでできること vol.1
- 変数の変数名を文字列で取得する。
- pyrtm と RTM CLI を使う
- スコープでリソースを破棄するいろいろなやりかた
- Django:参考資料
- どうやってコードを書けばいいのかな? というときに役立つかもしれない howdoi
- SQLAlchemy で独自の Composite Value を作る
- networkxでグラフを描く
- Twitter の OAuth ログインを自動化するスクリプト
- ファイルをzip圧縮して別のサーバにバックアップする
- boto を使って Amason S3 に指定のフォルダをアップロードするスクリプト
- argparseの使い方とoptparseとの違い
- Coverallsで “coverage unknown” になった時の対処法
- pythonでflatten
- Python 再帰の上限の参照と変更
- pythonでホームディレクトリの取得
- Pythonのスタイルを自動で整形させるVimプラグイン
- Tornado + nginx の時のIPの取得方法
- Python3でImportError: No module named ‘xxxxx’
- ScraperWikiを使ってWEBサイトからデータを定期的に取得する
- Scikit-learnでPCA
- Scikit-learnでIsomap
- メモ:Vagrant環境でCGI(試行錯誤中)
- Python 3.4 から標準ライブラリに入る Enum 型が今からでも便利
- SQLAlchemy で Enum を使う
- Django Templateのif-elseを短く書く
- Macでpyenv+virtualenv
- LINQのPython実装 “linqish”の紹介
- Numpyで行列の連結
- Scipyでデータをnormarizeする
- reportlabで画像追加メモ
- django-celery で Amazon SQS を使ってみた
- 環境構築手順書: Ubuntu + Apache2 + Python + Pyramid
- Path API を叩く PHP / Python / Ruby のサンプル
- Pythonメモ(自分用):配列
- 【python】web開発準備(仮想環境の構築)
- Python版のConfluence API用モジュールを使ってみます。
- PythonでYouTubeの動画を自動的に検索&ダウンロードする
- Pythonメモ:現在の月を取得
- sqlalchemyでgroup_byしてsum
- 僕とcpとSubprocessと
- Pythonの進化計算ライブラリDeap
- Scikit-learnでハイパーパラメータのグリッドサーチ
- 泥沼の記憶(CSV)をワンライナーで処理する
- pipで既にインストールされているパッケージをuser環境(非su)でアップデートする
- 2D plot in matplotlib
- 今日の株式取引は?
- 東証1部上場銘柄の名前と証券コードを取得する
- python で redmine の更新を hipchat へ流す
- Bottle0.13+jPlayer2.5で自分だけのミュージックプレイヤーを作ろう!
- Ruby と Python の仮想環境操作を統一する
- CentOS に Python2.7, Python3を入れたメモ
- anyenvで開発環境を整える
- pythonで文字列ゼロ埋め、文字列からある文字をカウントする
- Pythonで正規表現使うとき
- pythonにおける相対urlの処理
- pythonで文字列が数字かどうかを確認する
- pythonにswitchはないけれど
- Python と node.js のテストライブラリを簡単に比較してみた
- Webアプリ開発実践:Djangoでシフト作成ページを作ろう!(はじめに)
- numpyで作成した行列の可視化
- Pythonメモ:オブジェクトの持つ属性を知りたいとき
- supervisorでulimitを設定する

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。