sage/PRML - 混合密度ネットワーク
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[FrontPage]]
#contents
2011/06/20からのアクセス回数 &counter;
ここで紹介したSageワークシートは、以下のURLからダウンロー...
http://sage.math.canterbury.ac.nz/home/pub/104/
また、Sageのサーバを公開しているサイト(http://sage.math....
アップロードし、実行したり、変更していろいろ動きを試すこ...
* 第5章-混合密度ネットワークをSageで試す [#d7fb5911]
PRMLの第5章-混合密度ネットワークの例題、図5.19
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
のデータは、XとYを入れ替えただけで多峰性によりフィッティ...
(x=0.5のところで、yの値として3つの選択しがあります)
** テストデータ [#z43bbaa8]
区間(0, 1)に一様分布する変数$x_n$をサンプリングし、目的...
を\(x_n + 0.3 sin(2\pi x_n)\)に区間(-0.1, 0.1)の一様乱数を
加えたデータを200点生成します。
sageへの入力:
#pre{{
# PRML fig.5.19のデータ
#f = lambda x : x + 0.3*sin(2*pi*x) + random()*0.2 - 0.1
#X = [random() for i in range(200)]
#t = [f(x).n() for x in X]
}}
sageへの入力:
#pre{{
# データの保存
# save(X, DATA+'X')
# save(t, DATA+'t')
# リストアするには、以下のコメントを外す
X = load(DATA+'X')
t = load(DATA+'t')
print 'Done'
}}
sageからの出力:
#pre{{
Done
}}
*** グラフのプロット [#bb7ade87]
生成したデータとx,yを入れ替えたグラフをプロットします。
sageへの入力:
#pre{{
# データ生成
data_plt = list_plot(zip(X,t))
data_plt.show()
}}
&ref(sage0.png);
sageへの入力:
#pre{{
# X, tを入れ替えた図
data2_plt = list_plot(zip(t,X))
data2_plt.show()
}}
&ref(sage0-1.png);
** ニューラルネットワークでの回帰 [#wc37435e]
生成したデータをニューラルネットワークを使って、フィッテ...
以下に示します。(入力層1個、隠れ層6個、出力層1個で計算)
図5.19のbの様にx,tを入れ替えた場合には上手くフィッティン...
sageへの入力:
#pre{{
# 入力1点、隠れ層3個、出力1点
N_in = 1
N_h = 6
N_out = 1
# 隠れ層の活性化関数
h_1(x) = tanh(x)
# 出力層の活性化関数
h_2(x) = x
}}
sageへの入力:
#pre{{
# ニューラルネットワーク用のクラスのロード
attach "NeuralNetwork.sage"
# Scaled Conjugate Gradients(スケール共役勾配法)のロード
attach "SCG.sage"
}}
sageへの入力:
#pre{{
# 出力関数
def _f(x, net):
y = net.feedForward(x)
return y[0]
}}
sageへの入力:
#pre{{
# 定数設定
LEARN_COUNT = 500
RESET_COUNT = 50
beta = 0.5
# ニューラルネットワークの生成
net = NeuralNetwork(N_in, N_h, N_out, h_1, h_2, beta)
# wの初期値を保存
saved_w = net.getW()
# 逐次勾配降下法による学習
_learn_csg(net, X, t, LEARN_COUNT, RESET_COUNT)
}}
sageからの出力:
#pre{{
WARNING: Output truncated!
2 0.961554425907 3.77799819103
3 1.04117097273 2.41177356492
途中省略
499 1.14719236412 0.281449667896
500 0.626481765163 0.281421869851
}}
sageへの入力:
#pre{{
var('x')
g = lambda x : _f([x], net)
g_plt = plot(g, [x, 0, 1], rgbcolor='red')
(g_plt + data_plt).show()
}}
&ref(sage0-2.png);
sageへの入力:
#pre{{
# X, tを入れ替えた場合
# ニューラルネットワークの生成
net = NeuralNetwork(N_in, N_h, N_out, h_1, h_2, beta)
# wの初期値を保存
saved_w = net.getW()
# 逐次勾配降下法による学習
_learn_csg(net, t, X, LEARN_COUNT, RESET_COUNT)
}}
sageからの出力:
#pre{{
WARNING: Output truncated!
2 1.00671085821 5.493956126
3 0.983878474346 5.09315153282
途中省略
487 -19.5656631037 4.5870585875
488 -117.393981949 4.5870585875
489 -156.525310456 4.5870585875
}}
sageへの入力:
#pre{{
g2_plt = plot(g, [x, 0, 1], rgbcolor='red')
(g2_plt + data2_plt).show()
}}
&ref(sage0-3.png);
** 混合密度ネットワーク [#t943f5eb]
混合モデルの条件付き密度関数\(p(t|x)\)を式(5.148)
$$
p(t|x) = \sum_{k=1}^{K} \pi_k(x) \mathcal{N}(t|\mu_k(x), ...
$$
で表し、モデルパラメータ
- 混合係数 \(\pi_k(x)\)
- 平均 \(\mu_k(x)\)
- 分散 \(\sigma^2_k(x)\)
をニューラルネットワークの出力とします。
混合計数は、式(5.149)
$$
\sum_{k=1}^{K} \pi_k(x) = 1, 0 \le \pi_k(x) \le 1
$$
の制約を満たすために、ソフトマックス関数、式(5.150)
$$
\pi_k(x) = \frac{exp(a_k^{\pi})}{\sum_{k=1}^{K}}
$$
とし、分散$\sigma_k^2(x) \ge 0$を満たすように、式(5.151)
$$
\sigma_k(x) = exp(a_k^{\sigma})
$$
平均は、ニューラルネットワークの出力をそのまま使って、式(...
$$
\mu_{kj}(x) = a_{kj}^{\mu}
$$
とします。
誤差関数を式(5.153)
$$
E(w) = - \sum_{n=1}^{N} ln \left \{ \sum_{k=1}^K \pi_k(x_...
$$
とすると、事後分布式(5.154)
$$
\gamma_{nk}(t_n | x_n) = \frac{\pi_k \mathcal{N}_{nk}}{\s...
$$
を使って各係数の微分を求めます。
混合係数の微分は、式(5.155)
$$
\frac{\partial E_n}{\partial a_k^{\pi}} = \pi_k - \gamma_...
$$
平均の微分は、式(5.156)
$$
\frac{\partial E_n}{\partial a_{kl}^{\mu}} = \gamma_{nk} ...
$$
分散の微分は、式(5.157)
$$
\frac{\partial E_n}{\partial a_{k}^{\sigma}} = \gamma_{nk...
$$
重みwへの部分は、
$$
\frac{\partial E_n}{\partial w_{ji}^{1}} = \delta_j x_i
$$
ここで、\(\delta_j\)は、
$$
\delta_j = (1 - z_j^2) \sum_{k=1}^2 \left ( w_k^{pi} \fra...
$$
混合係数の重み\(w_{kj}^{\pi}\)微分は、
$$
\frac{\partial E_n}{\partial w_{kj}^{\pi}} = \frac{\parti...
$$
平均の微分の重み\(w_{kj}^{\pi}\)微分は、
$$
\frac{\partial E_n}{\partial w_{kj}^{\mu}} = \sum_{l=1}^{...
$$
分散の微分の重み\(w_{kj}^{\sigma}\)微分は、
$$
\frac{\partial E_n}{\partial w_{kj}^{\sigma}} = \frac{\pa...
$$
*** MixtureDensityNetworkクラスの定義 [#c47c1e89]
MixtureDensityNetworkクラスを以下のように定義します。
sageへの入力:
#pre{{
class MixtureDensityNetwork:
""" 混合密度ネットワーク用クラス(バイアス項を含む) ...
def __init__(self, N_in, N_h, K, L, h_1, dif_h_1, bet...
# N_in : 入力ユニットの数(バイアス項を除く)
# N_h : 隠れ層の数(バイアス項を除く)
# K : 混合密度の数
# L : 出力の次元
# h_1 : 隠れ層の活性化関数
# dif_h_1: 隠れ層の活性化関数の微分をz_jで表現し...
# beta0: w_1の初期分布β
# beta1: w_pi_kの初期分布β
# beta2: w_sig_kの初期分布β
# beta3: w_mu_kの初期分布β
self.N_in = N_in+1; self.N_h = N_h+1
self.K = K; self.L = L; self.h_1 = h_1
self.dif_h_1 = dif_h_1
self.w_1 = matrix(RDF, [[gauss(0,beta0) for i in ...
self.w_pi_k = matrix(RDF, [[gauss(0,beta1) for j ...
self.w_sig_k = matrix(RDF, [[gauss(0,beta2) for j...
self.w_mu_kl = [matrix(RDF, [[gauss(0,beta3) for ...
self.z_j = vector(RDF, self.N_h); self.z_j[0] = 1
self.a_pi_k = vector(RDF, self.K)
self.a_sig_k = vector(RDF, self.K)
self.a_mu_kl = matrix(RDF, self.L, self.K, 0)
self.d_k = vector(RDF, self.L)
self.gam_nk = vector(RDF, self.K)
self.Ident = identity_matrix(RDF,self.L)
self.N_nk = vector(RDF, self.K)
# ベクトルのガウス分布を定義
def gauss_v(self, v, mu, sigma):
d = len(v)
val = -(v - mu)*(v - mu)/(2*sigma)
a = n(2*pi*sigma)
c = n(a**(-d*0.5))
return n(c * (e**val))
# 予測分布
def getP(self, x, t):
self.feedForward(x)
self.backPropagate(t)
return n(self.pi_k*self.N_nk)
# フィードフォワード
def feedForward(self, x):
# x : 入力値
self.x_i = vector(RDF, flatten([1, x]))
# フィードフォワード処理
for j in range(1, self.N_h):
self.z_j[j] = self.h_1(self.w_1.row(j-1)*self...
self.a_pi_k = self.w_pi_k*self.z_j
self.a_sig_k = self.w_sig_k*self.z_j
for l in range(self.L):
self.a_mu_kl[l] = self.w_mu_kl[l]*self.z_j
# 微分係数用の変数セット
self.e_a_pi = vector(RDF, self.a_pi_k).apply_map(...
self.e_a_sig_k = vector(RDF, self.a_sig_k).apply_...
self.sig_k_sq = vector(RDF, self.e_a_sig_k).apply...
sum_e_a_pi_k = sum(self.e_a_pi.list())
self.pi_k = vector(RDF, self.e_a_pi).apply_map(la...
ret = flatten([self.pi_k.list(), self.a_mu_kl.lis...
return ret
# バックプロパゲート処理
def backPropagate(self, t):
# t : 観測値
v = vector(flatten([t]))
self.t = vector(RDF, flatten([t]))
mu_kl = matrix(RDF, self.a_mu_kl)
sum_pi_N = 0
for k in range(self.K):
self.N_nk[k] = self.gauss_v(v, mu_kl.column(k...
self.gam_nk[k] = self.pi_k[k]*self.N_nk[k]
sum_pi_N += self.gam_nk[k]
# avoid 0 devide.
if sum_pi_N == 0: sum_pi_N = 1
self.gam_nk = vector(RDF, self.gam_nk).apply_map(...
self.dEn_da_pi_k = self.pi_k - self.gam_nk
self.dEn_da_mu_k = matrix(RDF, self.K, self.L, 0)
self.dEn_da_sig_k = vector(RDF, self.K)
for k in range(self.K):
d = mu_kl.column(k) - v
self.dEn_da_mu_k[k] = self.gam_nk[k]*(d/self....
self.dEn_da_sig_k[k] = self.gam_nk[k]*(self.L...
# d_jを計算
self.d_j = vector(RDF, self.N_h)
for j in range(1, self.N_h):
self.d_j[j] += self.dEn_da_pi_k*self.w_pi_k.c...
self.d_j[j] += self.dEn_da_sig_k*self.w_sig_k...
for l in range(self.L):
self.d_j[j] += self.dEn_da_mu_k.column(l)...
self.d_j[j] *= self.dif_h_1(self.z_j[j])
# En(w)を返す
def En(self):
return -ln(n(self.pi_k*self.N_nk))
# ▽Enを返す
def gradEn(self):
dE_1 = [[self.d_j[j]*self.x_i[i] for i in range(s...
dE_pi = [[self.dEn_da_pi_k[k]*self.z_j[j] for j i...
dE_sig = [[self.dEn_da_sig_k[k]*self.z_j[j] for j...
dE_mu = [[[self.dEn_da_mu_k[k][l]*self.z_j[j] for...
return vector(RDF, flatten(dE_1 + dE_pi + dE_sig ...
# wを返す
def getW(self):
return vector(RDF, flatten(self.w_1.list() + self...
+ [self.w_mu_kl[l].list() for l in range(self.L)]))
# wをセットする
def setW(self, w):
s_pi = self.N_in*(self.N_h-1)
s_sig = self.N_in*(self.N_h-1)+self.N_h*self.K
s_mu = self.N_in*(self.N_h-1)+2*self.N_h*self.K
def index(l):
return s_mu+(l*self.N_h*self.K)
self.w_1 = matrix(RDF, self.N_h-1, self.N_in, w.l...
self.w_pi_k = matrix(RDF, self.K, self.N_h, w.lis...
self.w_sig_k = matrix(RDF, self.K, self.N_h, w.li...
self.w_mu_kl = [matrix(RDF, self.K, self.N_h, w.l...
}}
*** ランダムな重みを使った計算 [#c05dba7b]
MixtureDensityNetworkの計算にランダムな重みを使った結果を...
式(5.148)の分布が平均や分散に強く依存しているため、すべて...
なかなか収束しません。
sageへの入力:
#pre{{
# 定数設定
beta = 0.5
L=1
K=3
N_h = 5
LEARN_COUNT = 30
RESET_COUNT = 25
# ニューラルネットワークにバグあり、h'(x) = 1 -z^2を使え...
# もう一つh_1, dif_h_1の定義はlambda式を使う
h_1 = lambda x : tanh(x)
dif_h_1 = lambda z : 1 - z*z
}}
sageへの入力:
#pre{{
# ニューラルネットワークの生成
net = MixtureDensityNetwork(1, 5, 3, 1, h_1, dif_h_1, 0.5...
# wの初期値を保存
saved_w = net.getW()
# スケール共役勾配法による学習
_learn_csg(net, t, X, LEARN_COUNT, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 0.853606593211 220.691284013135
2 -1.02380954822 295.681734779221
4 49619.0430098 220.688261274285
途中省略
29 0.97008460868 -5.34286542507738
30 0.799581594259 -10.4327483758505
}}
sageへの入力:
#pre{{
# 結果のプロット 30回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-4.png);
&ref(sage1.png);
*** k-meansクラスター分析の結果を重みの初期値とする [#gf6...
収束をよくするために、重みのバイアス項の初期値をk-meansク...
使うことにします。
データをクラスタ分析した結果を以下に示します。
sageへの入力:
#pre{{
def euclid(x, y):
return sqrt(sum([(x[i]-y[i])**2 for i in range(len(x)...
# k-meansでデータを分類し、平均の重みを計算する
# 集合知から引用
def kcluster(rows,distance,k=3):
# Determine the minimum and maximum values for each p...
ranges=[(min([row[i] for row in rows]),max([row[i] fo...
for i in range(len(rows[0]))]
# Create k randomly placed centroids
clusters=[[random()*(ranges[i][1]-ranges[i][0])+range...
for i in range(len(rows[0]))] for j in range(k)]
sig = [[] for i in range(k)]
lastmatches=None
for t in range(100):
print 'Iteration %d' % t
bestmatches=[[] for i in range(k)]
# Find which centroid is the closest for each row
for j in range(len(rows)):
row=rows[j]
bestmatch=0
for i in range(k):
d=distance(clusters[i],row)
if d<distance(clusters[bestmatch],row):
bestmatch=i
bestmatches[bestmatch].append(j)
# If the results are the same as last time, this ...
if bestmatches==lastmatches: break
lastmatches=bestmatches
# Move the centroids to the average of their memb...
for i in range(k):
v = [0.0]*len(rows[0])
avgs=[0.0]*len(rows[0])
n = len(bestmatches[i])
if len(bestmatches[i])>0:
sumX = [0.0]*len(rows[0])
sumXX = [0.0]*len(rows[0])
for rowid in bestmatches[i]:
for m in range(len(rows[rowid])):
avgs[m]+=rows[rowid][m]
sumX[m] += rows[rowid][m]
sumXX[m] += rows[rowid][m]*rows[r...
for j in range(len(avgs)):
avgs[j]/= n
v[j] = sumXX[j]/n - (sumX[j]/n)*(sumX...
sig[i] = v
clusters[i]=avgs
print clusters
print sig
return bestmatches
data = zip(t,X)
group = kcluster(data, distance=euclid, k=3)
}}
sageからの出力:
#pre{{
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
Iteration 6
[[0.755995147678366, 0.906635821415391], [0.4894122687239...
[0.325834642861869, 0.133408609458438]]
[[0.0184016725675581, 0.00227560546930994], [0.0082271011...
[0.0280504201990768, 0.00434725503090522]]
}}
sageへの入力:
#pre{{
c_plt = Graphics()
r_grp = [ data[i] for i in group[0]]
b_grp = [ data[i] for i in group[1]]
g_grp = [ data[i] for i in group[2]]
for pt in b_grp:
c_plt += point(pt, rgbcolor="blue")
for pt in g_grp:
c_plt += point(pt, rgbcolor="green")
for pt in r_grp:
c_plt += point(pt, rgbcolor="red")
c_plt.show()
}}
&ref(sage0-5.png);
*** 初期値を変えて回帰分析 [#t7ffd506]
初期値を変えて回帰分析をし直します。
今回は、バイアス項を
- \(\pi_1 = 0.4, \pi_2 = 0.2, \pi_3 = 0.4\)の対数値
- \(\sigma_1 = 0.025, \sigma_2 = 0.125, \sigma_3 = 0.025\...
- \(\mu_1 = 0.13, \mu_2 = 0.53, \mu_3 = 0.91\)
とし、重みの分散も\(w_1 = 1, w_{\pi} = 0.25, w_{\sigma} =...
しました。
sageへの入力:
#pre{{
# ニューラルネットワークの生成
net = MixtureDensityNetwork(1, 5, 3, 1, h_1, dif_h_1, 1, ...
# wの初期値を保存
saved_w = net.getW()
tmp = saved_w
tmp[10] = -0.9 # pi_1 ln(0.4)
tmp[16] = -1.6 # pi_2 ln(0.2)
tmp[22] = -0.9 # pi_3 ln(0.4)
tmp[28] = -3.69 # sig_1 ln(0.025) Fig.5.21から4σ = 0.5と...
tmp[34] = -2.08 # sig_2 ln(0.125) Fig.5.21から4σ = 0.25と...
tmp[40] = -3.69 # sig_3 ln(0.025) Fig.5.21から4σ = 0.5と...
tmp[46] = 0.13 # mu_1
tmp[52] = 0.53 # mu_2
tmp[58] = 0.91 # mu_3
# スケール共役勾配法による学習
net.setW(tmp)
_learn_csg(net, t, X, LEARN_COUNT, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 1.00140531678 162.746607216641
3 0.978118009568 94.6561189652474
4 1.00006922311 74.3749728302636
途中省略
28 0.989452644705 -76.7534334638356
29 1.32320485458 -81.6847672263680
30 0.876928985373 -86.8153622565841
}}
sageへの入力:
#pre{{
# 結果のプロット 30回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show(ymax=1, ymin=-1)
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-6.png);
&ref(sage1-1.png);
sageへの入力:
#pre{{
tmp_w = net.getW()
save(tmp_w, DATA+'tmp_w')
}}
sageへの入力:
#pre{{
_learn_csg(net, t, X, 100, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 0.999254054027 -87.3044338521603
3 0.982374480725 -91.6889548386661
途中省略
99 1.01213525834 -188.881647537428
100 1.03434125073 -189.734542888085
}}
sageへの入力:
#pre{{
# 結果のプロット 130回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show(ymax=1, ymin=-1)
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-7.png);
&ref(sage1-2.png);
sageへの入力:
#pre{{
tmp_w = net.getW()
save(tmp_w, DATA+'tmp_w')
_learn_csg(net, t, X, 100, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 1.00010153793 -189.851273562036
3 1.00013157633 -190.041029348136
途中省略
99 0.962650552011 -206.426993641372
100 1.03840031165 -206.497416181699
}}
sageへの入力:
#pre{{
# 結果のプロット 230回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-8.png);
&ref(sage1-3.png);
sageへの入力:
#pre{{
var('x y')
contour_plot(lambda x, y : net.getP(x, y), [x, 0, 1], [y,...
}}
&ref(sage0-9.png);
sageへの入力:
#pre{{
w_230 = net.getW()
save(w_230, DATA+'w_230')
_learn_csg(net, t, X, 100, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 1.00024395346 -206.557574296743
3 1.00161969024 -206.711515824961
途中省略
99 1.03276294743 -212.624652019776
100 0.971359659233 -212.656180208402
}}
*** 最終結果 [#vec210c8]
最終結果は、PRMLの図5.21
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
の結果と良く似たものになりました。
sageへの入力:
#pre{{
# 結果のプロット 330回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-10.png);
&ref(sage1-4.png);
sageへの入力:
#pre{{
var('x y')
contour_plot(lambda x, y : net.getP(x, y), [x, 0, 1], [y,...
}}
&ref(sage0-11.png);
sageへの入力:
#pre{{
contour_plot(lambda x, y : net.getP(x, y), [x, 0, 1], [y,...
}}
&ref(sage0-12.png);
sageへの入力:
#pre{{
w_330 = net.getW()
save(w_330, DATA+'w_330')
}}
*** 予測値 [#tb0a7dba]
混合密度の平均として、PRMLでは条件付き密度の近似的な条件...
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
をプロットしていますが、ここでは本文の説明にある混合係数...
sageへの入力:
#pre{{
# π_kが最大の分布の平均
def probAve(net, x):
net.feedForward(x)
max_pi_index = [ k for k in range(net.K) if max(net.p...
return net.a_mu_kl[0][max_pi_index]
}}
sageへの入力:
#pre{{
# 最終的な解をプロット
N = 100
probAve_plt = list_plot([[x/N, probAve(net, x/N)] for x i...
(probAve_plt + data2_plt).show()
}}
&ref(sage0-13.png);
** プログラムのチェック [#y11969c3]
今回、プログラムが収束しない現象続き、とても悩みました!
そこで、5.3.3逆伝搬の効率で紹介されている
$$
\frac{\partial E_n}{\partial w_{ji}} = \frac{En(w_{ji} + ...
$$
を使って重みを近似計算してみました。これと手計算の値を比...
sageへの入力:
#pre{{
# ナブラを数値計算で求めて確認する
def grad_w(net, x, t):
eps = 1e-6
# 現在のwを保存
saved_w = net.getW()
grad = vector(RDF, len(saved_w))
work_w = vector(RDF, saved_w)
for i in range(len(work_w)):
w = work_w[i]
work_w[i] = w - eps
net.setW(work_w)
net.feedForward(x)
net.backPropagate(t)
E1 = net.En()
work_w[i] = w + eps
net.setW(work_w)
net.feedForward(x)
net.backPropagate(t)
E2 = net.En()
work_w[i] = w
grad[i] = (E2 - E1)/(2*eps)
net.setW(saved_w)
return grad
}}
sageへの入力:
#pre{{
# 入力1点、隠れ層3個、出力1点
N_in = 1
N_h = 6
N_out = 1
# 隠れ層の活性化関数
h_1(x) = tanh(x)
# 出力層の活性化関数
h_2(x) = x
dif_h_1 = lambda z : 1 - z*z
# mlpでチェック
mlp = NeuralNetwork(1, 1, 1, h_1, h_2, 0.1)
}}
*** ニューラルネットワークの場合 [#ua7f6763]
最初に単純なニューラルネットワークの場合について近似計算...
非常に良い一致を得ました。
sageへの入力:
#pre{{
mlp.feedForward(0)
mlp.backPropagate(1)
mlp.gradEn()
}}
sageからの出力:
#pre{{
(0.0668611517486, 0.0, 0.0207058923852, 0.0, -1.058114420...
}}
sageへの入力:
#pre{{
grad_w(mlp, 0, 1)
}}
sageからの出力:
#pre{{
(0.0, 0.0, 0.0207058923896, 0.0, -1.05811442086, 0.258067...
}}
*** 混合密度ネットワークの場合 [#bd405dc8]
次に混合密度ネットワークの場合についても近似計算とネット...
複雑な処理をしているにも関わらず、かなり一致することに驚...
sageへの入力:
#pre{{
# mdnでチェック
mdn = MixtureDensityNetwork(1, 1, 1, 1, h_1, dif_h_1, 0.5...
# テスト用の重み
w =vector(RDF, [-1.14339938022, 0.626829670558, 0.1476250...
-0.0395784292044, 0.0589154048316, 0.0677724926114])
mdn.setW(w)
}}
sageへの入力:
#pre{{
mdn.feedForward(0)
mdn.backPropagate(1)
mdn.gradEn()
}}
sageからの出力:
#pre{{
(-0.024679341566, -0.0, 0.0, -0.0, -0.199641572236, 0.162...
}}
sageへの入力:
#pre{{
grad_w(mdn, 0, 1)
}}
sageからの出力:
#pre{{
(-0.0246793415704, 0.0, 0.0, 0.0, -0.199641572274, 0.1628...
}}
** コメント [#cae22a30]
#vote(おもしろかった[9],そうでもない[0],わかりずらい[0])
皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha
終了行:
[[FrontPage]]
#contents
2011/06/20からのアクセス回数 &counter;
ここで紹介したSageワークシートは、以下のURLからダウンロー...
http://sage.math.canterbury.ac.nz/home/pub/104/
また、Sageのサーバを公開しているサイト(http://sage.math....
アップロードし、実行したり、変更していろいろ動きを試すこ...
* 第5章-混合密度ネットワークをSageで試す [#d7fb5911]
PRMLの第5章-混合密度ネットワークの例題、図5.19
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
のデータは、XとYを入れ替えただけで多峰性によりフィッティ...
(x=0.5のところで、yの値として3つの選択しがあります)
** テストデータ [#z43bbaa8]
区間(0, 1)に一様分布する変数$x_n$をサンプリングし、目的...
を\(x_n + 0.3 sin(2\pi x_n)\)に区間(-0.1, 0.1)の一様乱数を
加えたデータを200点生成します。
sageへの入力:
#pre{{
# PRML fig.5.19のデータ
#f = lambda x : x + 0.3*sin(2*pi*x) + random()*0.2 - 0.1
#X = [random() for i in range(200)]
#t = [f(x).n() for x in X]
}}
sageへの入力:
#pre{{
# データの保存
# save(X, DATA+'X')
# save(t, DATA+'t')
# リストアするには、以下のコメントを外す
X = load(DATA+'X')
t = load(DATA+'t')
print 'Done'
}}
sageからの出力:
#pre{{
Done
}}
*** グラフのプロット [#bb7ade87]
生成したデータとx,yを入れ替えたグラフをプロットします。
sageへの入力:
#pre{{
# データ生成
data_plt = list_plot(zip(X,t))
data_plt.show()
}}
&ref(sage0.png);
sageへの入力:
#pre{{
# X, tを入れ替えた図
data2_plt = list_plot(zip(t,X))
data2_plt.show()
}}
&ref(sage0-1.png);
** ニューラルネットワークでの回帰 [#wc37435e]
生成したデータをニューラルネットワークを使って、フィッテ...
以下に示します。(入力層1個、隠れ層6個、出力層1個で計算)
図5.19のbの様にx,tを入れ替えた場合には上手くフィッティン...
sageへの入力:
#pre{{
# 入力1点、隠れ層3個、出力1点
N_in = 1
N_h = 6
N_out = 1
# 隠れ層の活性化関数
h_1(x) = tanh(x)
# 出力層の活性化関数
h_2(x) = x
}}
sageへの入力:
#pre{{
# ニューラルネットワーク用のクラスのロード
attach "NeuralNetwork.sage"
# Scaled Conjugate Gradients(スケール共役勾配法)のロード
attach "SCG.sage"
}}
sageへの入力:
#pre{{
# 出力関数
def _f(x, net):
y = net.feedForward(x)
return y[0]
}}
sageへの入力:
#pre{{
# 定数設定
LEARN_COUNT = 500
RESET_COUNT = 50
beta = 0.5
# ニューラルネットワークの生成
net = NeuralNetwork(N_in, N_h, N_out, h_1, h_2, beta)
# wの初期値を保存
saved_w = net.getW()
# 逐次勾配降下法による学習
_learn_csg(net, X, t, LEARN_COUNT, RESET_COUNT)
}}
sageからの出力:
#pre{{
WARNING: Output truncated!
2 0.961554425907 3.77799819103
3 1.04117097273 2.41177356492
途中省略
499 1.14719236412 0.281449667896
500 0.626481765163 0.281421869851
}}
sageへの入力:
#pre{{
var('x')
g = lambda x : _f([x], net)
g_plt = plot(g, [x, 0, 1], rgbcolor='red')
(g_plt + data_plt).show()
}}
&ref(sage0-2.png);
sageへの入力:
#pre{{
# X, tを入れ替えた場合
# ニューラルネットワークの生成
net = NeuralNetwork(N_in, N_h, N_out, h_1, h_2, beta)
# wの初期値を保存
saved_w = net.getW()
# 逐次勾配降下法による学習
_learn_csg(net, t, X, LEARN_COUNT, RESET_COUNT)
}}
sageからの出力:
#pre{{
WARNING: Output truncated!
2 1.00671085821 5.493956126
3 0.983878474346 5.09315153282
途中省略
487 -19.5656631037 4.5870585875
488 -117.393981949 4.5870585875
489 -156.525310456 4.5870585875
}}
sageへの入力:
#pre{{
g2_plt = plot(g, [x, 0, 1], rgbcolor='red')
(g2_plt + data2_plt).show()
}}
&ref(sage0-3.png);
** 混合密度ネットワーク [#t943f5eb]
混合モデルの条件付き密度関数\(p(t|x)\)を式(5.148)
$$
p(t|x) = \sum_{k=1}^{K} \pi_k(x) \mathcal{N}(t|\mu_k(x), ...
$$
で表し、モデルパラメータ
- 混合係数 \(\pi_k(x)\)
- 平均 \(\mu_k(x)\)
- 分散 \(\sigma^2_k(x)\)
をニューラルネットワークの出力とします。
混合計数は、式(5.149)
$$
\sum_{k=1}^{K} \pi_k(x) = 1, 0 \le \pi_k(x) \le 1
$$
の制約を満たすために、ソフトマックス関数、式(5.150)
$$
\pi_k(x) = \frac{exp(a_k^{\pi})}{\sum_{k=1}^{K}}
$$
とし、分散$\sigma_k^2(x) \ge 0$を満たすように、式(5.151)
$$
\sigma_k(x) = exp(a_k^{\sigma})
$$
平均は、ニューラルネットワークの出力をそのまま使って、式(...
$$
\mu_{kj}(x) = a_{kj}^{\mu}
$$
とします。
誤差関数を式(5.153)
$$
E(w) = - \sum_{n=1}^{N} ln \left \{ \sum_{k=1}^K \pi_k(x_...
$$
とすると、事後分布式(5.154)
$$
\gamma_{nk}(t_n | x_n) = \frac{\pi_k \mathcal{N}_{nk}}{\s...
$$
を使って各係数の微分を求めます。
混合係数の微分は、式(5.155)
$$
\frac{\partial E_n}{\partial a_k^{\pi}} = \pi_k - \gamma_...
$$
平均の微分は、式(5.156)
$$
\frac{\partial E_n}{\partial a_{kl}^{\mu}} = \gamma_{nk} ...
$$
分散の微分は、式(5.157)
$$
\frac{\partial E_n}{\partial a_{k}^{\sigma}} = \gamma_{nk...
$$
重みwへの部分は、
$$
\frac{\partial E_n}{\partial w_{ji}^{1}} = \delta_j x_i
$$
ここで、\(\delta_j\)は、
$$
\delta_j = (1 - z_j^2) \sum_{k=1}^2 \left ( w_k^{pi} \fra...
$$
混合係数の重み\(w_{kj}^{\pi}\)微分は、
$$
\frac{\partial E_n}{\partial w_{kj}^{\pi}} = \frac{\parti...
$$
平均の微分の重み\(w_{kj}^{\pi}\)微分は、
$$
\frac{\partial E_n}{\partial w_{kj}^{\mu}} = \sum_{l=1}^{...
$$
分散の微分の重み\(w_{kj}^{\sigma}\)微分は、
$$
\frac{\partial E_n}{\partial w_{kj}^{\sigma}} = \frac{\pa...
$$
*** MixtureDensityNetworkクラスの定義 [#c47c1e89]
MixtureDensityNetworkクラスを以下のように定義します。
sageへの入力:
#pre{{
class MixtureDensityNetwork:
""" 混合密度ネットワーク用クラス(バイアス項を含む) ...
def __init__(self, N_in, N_h, K, L, h_1, dif_h_1, bet...
# N_in : 入力ユニットの数(バイアス項を除く)
# N_h : 隠れ層の数(バイアス項を除く)
# K : 混合密度の数
# L : 出力の次元
# h_1 : 隠れ層の活性化関数
# dif_h_1: 隠れ層の活性化関数の微分をz_jで表現し...
# beta0: w_1の初期分布β
# beta1: w_pi_kの初期分布β
# beta2: w_sig_kの初期分布β
# beta3: w_mu_kの初期分布β
self.N_in = N_in+1; self.N_h = N_h+1
self.K = K; self.L = L; self.h_1 = h_1
self.dif_h_1 = dif_h_1
self.w_1 = matrix(RDF, [[gauss(0,beta0) for i in ...
self.w_pi_k = matrix(RDF, [[gauss(0,beta1) for j ...
self.w_sig_k = matrix(RDF, [[gauss(0,beta2) for j...
self.w_mu_kl = [matrix(RDF, [[gauss(0,beta3) for ...
self.z_j = vector(RDF, self.N_h); self.z_j[0] = 1
self.a_pi_k = vector(RDF, self.K)
self.a_sig_k = vector(RDF, self.K)
self.a_mu_kl = matrix(RDF, self.L, self.K, 0)
self.d_k = vector(RDF, self.L)
self.gam_nk = vector(RDF, self.K)
self.Ident = identity_matrix(RDF,self.L)
self.N_nk = vector(RDF, self.K)
# ベクトルのガウス分布を定義
def gauss_v(self, v, mu, sigma):
d = len(v)
val = -(v - mu)*(v - mu)/(2*sigma)
a = n(2*pi*sigma)
c = n(a**(-d*0.5))
return n(c * (e**val))
# 予測分布
def getP(self, x, t):
self.feedForward(x)
self.backPropagate(t)
return n(self.pi_k*self.N_nk)
# フィードフォワード
def feedForward(self, x):
# x : 入力値
self.x_i = vector(RDF, flatten([1, x]))
# フィードフォワード処理
for j in range(1, self.N_h):
self.z_j[j] = self.h_1(self.w_1.row(j-1)*self...
self.a_pi_k = self.w_pi_k*self.z_j
self.a_sig_k = self.w_sig_k*self.z_j
for l in range(self.L):
self.a_mu_kl[l] = self.w_mu_kl[l]*self.z_j
# 微分係数用の変数セット
self.e_a_pi = vector(RDF, self.a_pi_k).apply_map(...
self.e_a_sig_k = vector(RDF, self.a_sig_k).apply_...
self.sig_k_sq = vector(RDF, self.e_a_sig_k).apply...
sum_e_a_pi_k = sum(self.e_a_pi.list())
self.pi_k = vector(RDF, self.e_a_pi).apply_map(la...
ret = flatten([self.pi_k.list(), self.a_mu_kl.lis...
return ret
# バックプロパゲート処理
def backPropagate(self, t):
# t : 観測値
v = vector(flatten([t]))
self.t = vector(RDF, flatten([t]))
mu_kl = matrix(RDF, self.a_mu_kl)
sum_pi_N = 0
for k in range(self.K):
self.N_nk[k] = self.gauss_v(v, mu_kl.column(k...
self.gam_nk[k] = self.pi_k[k]*self.N_nk[k]
sum_pi_N += self.gam_nk[k]
# avoid 0 devide.
if sum_pi_N == 0: sum_pi_N = 1
self.gam_nk = vector(RDF, self.gam_nk).apply_map(...
self.dEn_da_pi_k = self.pi_k - self.gam_nk
self.dEn_da_mu_k = matrix(RDF, self.K, self.L, 0)
self.dEn_da_sig_k = vector(RDF, self.K)
for k in range(self.K):
d = mu_kl.column(k) - v
self.dEn_da_mu_k[k] = self.gam_nk[k]*(d/self....
self.dEn_da_sig_k[k] = self.gam_nk[k]*(self.L...
# d_jを計算
self.d_j = vector(RDF, self.N_h)
for j in range(1, self.N_h):
self.d_j[j] += self.dEn_da_pi_k*self.w_pi_k.c...
self.d_j[j] += self.dEn_da_sig_k*self.w_sig_k...
for l in range(self.L):
self.d_j[j] += self.dEn_da_mu_k.column(l)...
self.d_j[j] *= self.dif_h_1(self.z_j[j])
# En(w)を返す
def En(self):
return -ln(n(self.pi_k*self.N_nk))
# ▽Enを返す
def gradEn(self):
dE_1 = [[self.d_j[j]*self.x_i[i] for i in range(s...
dE_pi = [[self.dEn_da_pi_k[k]*self.z_j[j] for j i...
dE_sig = [[self.dEn_da_sig_k[k]*self.z_j[j] for j...
dE_mu = [[[self.dEn_da_mu_k[k][l]*self.z_j[j] for...
return vector(RDF, flatten(dE_1 + dE_pi + dE_sig ...
# wを返す
def getW(self):
return vector(RDF, flatten(self.w_1.list() + self...
+ [self.w_mu_kl[l].list() for l in range(self.L)]))
# wをセットする
def setW(self, w):
s_pi = self.N_in*(self.N_h-1)
s_sig = self.N_in*(self.N_h-1)+self.N_h*self.K
s_mu = self.N_in*(self.N_h-1)+2*self.N_h*self.K
def index(l):
return s_mu+(l*self.N_h*self.K)
self.w_1 = matrix(RDF, self.N_h-1, self.N_in, w.l...
self.w_pi_k = matrix(RDF, self.K, self.N_h, w.lis...
self.w_sig_k = matrix(RDF, self.K, self.N_h, w.li...
self.w_mu_kl = [matrix(RDF, self.K, self.N_h, w.l...
}}
*** ランダムな重みを使った計算 [#c05dba7b]
MixtureDensityNetworkの計算にランダムな重みを使った結果を...
式(5.148)の分布が平均や分散に強く依存しているため、すべて...
なかなか収束しません。
sageへの入力:
#pre{{
# 定数設定
beta = 0.5
L=1
K=3
N_h = 5
LEARN_COUNT = 30
RESET_COUNT = 25
# ニューラルネットワークにバグあり、h'(x) = 1 -z^2を使え...
# もう一つh_1, dif_h_1の定義はlambda式を使う
h_1 = lambda x : tanh(x)
dif_h_1 = lambda z : 1 - z*z
}}
sageへの入力:
#pre{{
# ニューラルネットワークの生成
net = MixtureDensityNetwork(1, 5, 3, 1, h_1, dif_h_1, 0.5...
# wの初期値を保存
saved_w = net.getW()
# スケール共役勾配法による学習
_learn_csg(net, t, X, LEARN_COUNT, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 0.853606593211 220.691284013135
2 -1.02380954822 295.681734779221
4 49619.0430098 220.688261274285
途中省略
29 0.97008460868 -5.34286542507738
30 0.799581594259 -10.4327483758505
}}
sageへの入力:
#pre{{
# 結果のプロット 30回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-4.png);
&ref(sage1.png);
*** k-meansクラスター分析の結果を重みの初期値とする [#gf6...
収束をよくするために、重みのバイアス項の初期値をk-meansク...
使うことにします。
データをクラスタ分析した結果を以下に示します。
sageへの入力:
#pre{{
def euclid(x, y):
return sqrt(sum([(x[i]-y[i])**2 for i in range(len(x)...
# k-meansでデータを分類し、平均の重みを計算する
# 集合知から引用
def kcluster(rows,distance,k=3):
# Determine the minimum and maximum values for each p...
ranges=[(min([row[i] for row in rows]),max([row[i] fo...
for i in range(len(rows[0]))]
# Create k randomly placed centroids
clusters=[[random()*(ranges[i][1]-ranges[i][0])+range...
for i in range(len(rows[0]))] for j in range(k)]
sig = [[] for i in range(k)]
lastmatches=None
for t in range(100):
print 'Iteration %d' % t
bestmatches=[[] for i in range(k)]
# Find which centroid is the closest for each row
for j in range(len(rows)):
row=rows[j]
bestmatch=0
for i in range(k):
d=distance(clusters[i],row)
if d<distance(clusters[bestmatch],row):
bestmatch=i
bestmatches[bestmatch].append(j)
# If the results are the same as last time, this ...
if bestmatches==lastmatches: break
lastmatches=bestmatches
# Move the centroids to the average of their memb...
for i in range(k):
v = [0.0]*len(rows[0])
avgs=[0.0]*len(rows[0])
n = len(bestmatches[i])
if len(bestmatches[i])>0:
sumX = [0.0]*len(rows[0])
sumXX = [0.0]*len(rows[0])
for rowid in bestmatches[i]:
for m in range(len(rows[rowid])):
avgs[m]+=rows[rowid][m]
sumX[m] += rows[rowid][m]
sumXX[m] += rows[rowid][m]*rows[r...
for j in range(len(avgs)):
avgs[j]/= n
v[j] = sumXX[j]/n - (sumX[j]/n)*(sumX...
sig[i] = v
clusters[i]=avgs
print clusters
print sig
return bestmatches
data = zip(t,X)
group = kcluster(data, distance=euclid, k=3)
}}
sageからの出力:
#pre{{
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
Iteration 6
[[0.755995147678366, 0.906635821415391], [0.4894122687239...
[0.325834642861869, 0.133408609458438]]
[[0.0184016725675581, 0.00227560546930994], [0.0082271011...
[0.0280504201990768, 0.00434725503090522]]
}}
sageへの入力:
#pre{{
c_plt = Graphics()
r_grp = [ data[i] for i in group[0]]
b_grp = [ data[i] for i in group[1]]
g_grp = [ data[i] for i in group[2]]
for pt in b_grp:
c_plt += point(pt, rgbcolor="blue")
for pt in g_grp:
c_plt += point(pt, rgbcolor="green")
for pt in r_grp:
c_plt += point(pt, rgbcolor="red")
c_plt.show()
}}
&ref(sage0-5.png);
*** 初期値を変えて回帰分析 [#t7ffd506]
初期値を変えて回帰分析をし直します。
今回は、バイアス項を
- \(\pi_1 = 0.4, \pi_2 = 0.2, \pi_3 = 0.4\)の対数値
- \(\sigma_1 = 0.025, \sigma_2 = 0.125, \sigma_3 = 0.025\...
- \(\mu_1 = 0.13, \mu_2 = 0.53, \mu_3 = 0.91\)
とし、重みの分散も\(w_1 = 1, w_{\pi} = 0.25, w_{\sigma} =...
しました。
sageへの入力:
#pre{{
# ニューラルネットワークの生成
net = MixtureDensityNetwork(1, 5, 3, 1, h_1, dif_h_1, 1, ...
# wの初期値を保存
saved_w = net.getW()
tmp = saved_w
tmp[10] = -0.9 # pi_1 ln(0.4)
tmp[16] = -1.6 # pi_2 ln(0.2)
tmp[22] = -0.9 # pi_3 ln(0.4)
tmp[28] = -3.69 # sig_1 ln(0.025) Fig.5.21から4σ = 0.5と...
tmp[34] = -2.08 # sig_2 ln(0.125) Fig.5.21から4σ = 0.25と...
tmp[40] = -3.69 # sig_3 ln(0.025) Fig.5.21から4σ = 0.5と...
tmp[46] = 0.13 # mu_1
tmp[52] = 0.53 # mu_2
tmp[58] = 0.91 # mu_3
# スケール共役勾配法による学習
net.setW(tmp)
_learn_csg(net, t, X, LEARN_COUNT, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 1.00140531678 162.746607216641
3 0.978118009568 94.6561189652474
4 1.00006922311 74.3749728302636
途中省略
28 0.989452644705 -76.7534334638356
29 1.32320485458 -81.6847672263680
30 0.876928985373 -86.8153622565841
}}
sageへの入力:
#pre{{
# 結果のプロット 30回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show(ymax=1, ymin=-1)
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-6.png);
&ref(sage1-1.png);
sageへの入力:
#pre{{
tmp_w = net.getW()
save(tmp_w, DATA+'tmp_w')
}}
sageへの入力:
#pre{{
_learn_csg(net, t, X, 100, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 0.999254054027 -87.3044338521603
3 0.982374480725 -91.6889548386661
途中省略
99 1.01213525834 -188.881647537428
100 1.03434125073 -189.734542888085
}}
sageへの入力:
#pre{{
# 結果のプロット 130回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show(ymax=1, ymin=-1)
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-7.png);
&ref(sage1-2.png);
sageへの入力:
#pre{{
tmp_w = net.getW()
save(tmp_w, DATA+'tmp_w')
_learn_csg(net, t, X, 100, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 1.00010153793 -189.851273562036
3 1.00013157633 -190.041029348136
途中省略
99 0.962650552011 -206.426993641372
100 1.03840031165 -206.497416181699
}}
sageへの入力:
#pre{{
# 結果のプロット 230回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-8.png);
&ref(sage1-3.png);
sageへの入力:
#pre{{
var('x y')
contour_plot(lambda x, y : net.getP(x, y), [x, 0, 1], [y,...
}}
&ref(sage0-9.png);
sageへの入力:
#pre{{
w_230 = net.getW()
save(w_230, DATA+'w_230')
_learn_csg(net, t, X, 100, RESET_COUNT)
}}
sageからの出力:
#pre{{
2 1.00024395346 -206.557574296743
3 1.00161969024 -206.711515824961
途中省略
99 1.03276294743 -212.624652019776
100 0.971359659233 -212.656180208402
}}
*** 最終結果 [#vec210c8]
最終結果は、PRMLの図5.21
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
の結果と良く似たものになりました。
sageへの入力:
#pre{{
# 結果のプロット 330回目
var('x')
b_plt = plot(lambda x : net.feedForward(x)[0], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[1], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[2], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
b_plt = plot(lambda x : net.feedForward(x)[3], [x, 0, 1],...
g_plt = plot(lambda x : net.feedForward(x)[4], [x, 0, 1],...
r_plt = plot(lambda x : net.feedForward(x)[5], [x, 0, 1],...
(b_plt+g_plt+r_plt).show()
}}
&ref(sage0-10.png);
&ref(sage1-4.png);
sageへの入力:
#pre{{
var('x y')
contour_plot(lambda x, y : net.getP(x, y), [x, 0, 1], [y,...
}}
&ref(sage0-11.png);
sageへの入力:
#pre{{
contour_plot(lambda x, y : net.getP(x, y), [x, 0, 1], [y,...
}}
&ref(sage0-12.png);
sageへの入力:
#pre{{
w_330 = net.getW()
save(w_330, DATA+'w_330')
}}
*** 予測値 [#tb0a7dba]
混合密度の平均として、PRMLでは条件付き密度の近似的な条件...
&ref(http://research.microsoft.com/en-us/um/people/cmbish...
をプロットしていますが、ここでは本文の説明にある混合係数...
sageへの入力:
#pre{{
# π_kが最大の分布の平均
def probAve(net, x):
net.feedForward(x)
max_pi_index = [ k for k in range(net.K) if max(net.p...
return net.a_mu_kl[0][max_pi_index]
}}
sageへの入力:
#pre{{
# 最終的な解をプロット
N = 100
probAve_plt = list_plot([[x/N, probAve(net, x/N)] for x i...
(probAve_plt + data2_plt).show()
}}
&ref(sage0-13.png);
** プログラムのチェック [#y11969c3]
今回、プログラムが収束しない現象続き、とても悩みました!
そこで、5.3.3逆伝搬の効率で紹介されている
$$
\frac{\partial E_n}{\partial w_{ji}} = \frac{En(w_{ji} + ...
$$
を使って重みを近似計算してみました。これと手計算の値を比...
sageへの入力:
#pre{{
# ナブラを数値計算で求めて確認する
def grad_w(net, x, t):
eps = 1e-6
# 現在のwを保存
saved_w = net.getW()
grad = vector(RDF, len(saved_w))
work_w = vector(RDF, saved_w)
for i in range(len(work_w)):
w = work_w[i]
work_w[i] = w - eps
net.setW(work_w)
net.feedForward(x)
net.backPropagate(t)
E1 = net.En()
work_w[i] = w + eps
net.setW(work_w)
net.feedForward(x)
net.backPropagate(t)
E2 = net.En()
work_w[i] = w
grad[i] = (E2 - E1)/(2*eps)
net.setW(saved_w)
return grad
}}
sageへの入力:
#pre{{
# 入力1点、隠れ層3個、出力1点
N_in = 1
N_h = 6
N_out = 1
# 隠れ層の活性化関数
h_1(x) = tanh(x)
# 出力層の活性化関数
h_2(x) = x
dif_h_1 = lambda z : 1 - z*z
# mlpでチェック
mlp = NeuralNetwork(1, 1, 1, h_1, h_2, 0.1)
}}
*** ニューラルネットワークの場合 [#ua7f6763]
最初に単純なニューラルネットワークの場合について近似計算...
非常に良い一致を得ました。
sageへの入力:
#pre{{
mlp.feedForward(0)
mlp.backPropagate(1)
mlp.gradEn()
}}
sageからの出力:
#pre{{
(0.0668611517486, 0.0, 0.0207058923852, 0.0, -1.058114420...
}}
sageへの入力:
#pre{{
grad_w(mlp, 0, 1)
}}
sageからの出力:
#pre{{
(0.0, 0.0, 0.0207058923896, 0.0, -1.05811442086, 0.258067...
}}
*** 混合密度ネットワークの場合 [#bd405dc8]
次に混合密度ネットワークの場合についても近似計算とネット...
複雑な処理をしているにも関わらず、かなり一致することに驚...
sageへの入力:
#pre{{
# mdnでチェック
mdn = MixtureDensityNetwork(1, 1, 1, 1, h_1, dif_h_1, 0.5...
# テスト用の重み
w =vector(RDF, [-1.14339938022, 0.626829670558, 0.1476250...
-0.0395784292044, 0.0589154048316, 0.0677724926114])
mdn.setW(w)
}}
sageへの入力:
#pre{{
mdn.feedForward(0)
mdn.backPropagate(1)
mdn.gradEn()
}}
sageからの出力:
#pre{{
(-0.024679341566, -0.0, 0.0, -0.0, -0.199641572236, 0.162...
}}
sageへの入力:
#pre{{
grad_w(mdn, 0, 1)
}}
sageからの出力:
#pre{{
(-0.0246793415704, 0.0, 0.0, 0.0, -0.199641572274, 0.1628...
}}
** コメント [#cae22a30]
#vote(おもしろかった[9],そうでもない[0],わかりずらい[0])
皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha
ページ名:
SmartDoc