<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 コブ・ダクラス型生産関数と課題文で例に出された関数を用いる。
いずれも定義域は0≤x≤1である。
<P>コブ・ダグラス型生産関数は以下の通りである。</P>
<P>z = x_1**0.5*x_2*0.5</P>
Step1:  <P>課題の例で使われた関数は以下の通りである。</P>
<P>z = (1+np.sin(4*math.pi*x_1))*x_2*1/2</P>
NNのクラスはすでにNN.pyからimportしてある。
Step2:  以下に使い方を説明する。
初めに、このコブ・ダグラス型生産関数を用いる。
Step3:  入力層、中間層、出力層を作る関数を実行する。引数には層の数を用いる。
Step4:  <p>nn.set_hidden_layer()は同時にシグモイド関数で変換する前の中間層も作る。</p>
<p>set_output_layer()は同時にシグモイド関数で変換する前の出力層、さらに教師データを入れる配列も作る。</p>
nn.setup()で入力層ー中間層、中間層ー出力層間の重みを入れる配列を作成する。
nn.initialize()で重みを初期化する。重みは-1/√d ≤ w ≤ 1/√d (dは入力層及び中間層の数)の範囲で一様分布から決定される。
Step5:  nn.supervised_function(f, idata)は教師データを作成する。引数は関数とサンプルデータをとる。
Step6:  nn.simulate(N, eta)は引数に更新回数と学習率をとる。普通はN=1で行うべきかもしれないが、工夫として作成してみた。N回学習した後に出力層を返す。
Step7:  nn.calculation()は学習せずに入力層から出力層の計算を行う。nn.simulate()内にも用いられている。
次に実際に学習を行う。サンプルデータは、
Step8:  の組み合わせである。
Step9:  例えば(0, 0)を入力すると0.52328635を返している（つまりa[0]とb[0]を入力して、c[0]の値を返している）。
Step10:  確率的勾配降下法を100回繰り返したが見た感じから近づいている。回数を10000回に増やしてみる。
Step11:  見た感じ随分近づいているように見える。
Step12:  同様のことを課題の例で使われた関数でも試してみる。
Step13:  上手く近似できないので中間層の数を変えてみる。5層にしてみる。
Step14:  目標と比べると大きく異なる。
サンプル数を、
Step15:  で取り、学習の際にランダムに一個選ばれたサンプルを何十回も学習させてみた。
Step16:  本来ならば下のような形になるべきであるので上手くいっているとは言い難い。
Step17:  同じ方法でコブ・ダグラス型生産関数を学習させた様子をアニメーションにしてみた。この方法が何の意味を持つかは分からないが学習はまあまよくできていた。
mp4ファイルで添付した。
[考察]ここにはコードを書けなかったが、サンプル数が多くなった時は、ミニバッチ式の学習を試すべきだと思った。
最後に交差検定を行う。
初めに学習回数が極めて少ないNNである。
Step18:  次に十分大きく(1000回に)してみる。
Step19:  誤差の平均であるので小さい方よい。
学習回数を大幅に増やした結果、精度が上がった。
次に回数を100回にして、中間層の数を2と5で精度を比較する。
<ASSISTANT_TASK:>
Python Code:
def example1(x_1, x_2):
    z = x_1**0.5*x_2*0.5
    return z
fig = pl.figure()
ax = Axes3D(fig)
X = np.arange(0, 1, 0.1)
Y = np.arange(0, 1, 0.1)
X, Y = np.meshgrid(X, Y)
Z = example1(X, Y)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
pl.show()
Explanation: コブ・ダクラス型生産関数と課題文で例に出された関数を用いる。
いずれも定義域は0≤x≤1である。
<P>コブ・ダグラス型生産関数は以下の通りである。</P>
<P>z = x_1**0.5*x_2*0.5</P>
End of explanation
nn = NN()
Explanation: <P>課題の例で使われた関数は以下の通りである。</P>
<P>z = (1+np.sin(4*math.pi*x_1))*x_2*1/2</P>
NNのクラスはすでにNN.pyからimportしてある。
End of explanation
x_1 = Symbol('x_1')
x_2 = Symbol('x_2')
f = x_1**0.5*x_2*0.5
Explanation: 以下に使い方を説明する。
初めに、このコブ・ダグラス型生産関数を用いる。
End of explanation
nn.set_input_layer(2)
nn.set_hidden_layer(2)
nn.set_output_layer(2)
Explanation: 入力層、中間層、出力層を作る関数を実行する。引数には層の数を用いる。
End of explanation
nn.setup()
nn.initialize()
Explanation: <p>nn.set_hidden_layer()は同時にシグモイド関数で変換する前の中間層も作る。</p>
<p>set_output_layer()は同時にシグモイド関数で変換する前の出力層、さらに教師データを入れる配列も作る。</p>
nn.setup()で入力層ー中間層、中間層ー出力層間の重みを入れる配列を作成する。
nn.initialize()で重みを初期化する。重みは-1/√d ≤ w ≤ 1/√d (dは入力層及び中間層の数)の範囲で一様分布から決定される。
End of explanation
idata = [1, 2]
nn.supervised_function(f, idata)
Explanation: nn.supervised_function(f, idata)は教師データを作成する。引数は関数とサンプルデータをとる。
End of explanation
nn.simulate(1, 0.1)
Explanation: nn.simulate(N, eta)は引数に更新回数と学習率をとる。普通はN=1で行うべきかもしれないが、工夫として作成してみた。N回学習した後に出力層を返す。
End of explanation
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
print X, Y
Explanation: nn.calculation()は学習せずに入力層から出力層の計算を行う。nn.simulate()内にも用いられている。
次に実際に学習を行う。サンプルデータは、
End of explanation
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
a = np.array([])
b = np.array([])
c = np.array([])
nn = NN()
nn.set_network()
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
        
for i in range(100):
        l = np.random.choice([i for i in range(len(a))])
        m = nn.main(1, f, [a[l], b[l]], 0.5)
for x in X:
    for y in Y:
        idata = [x, y]
        c = np.append(c, nn.realize(f, idata))
a
b
c
Explanation: の組み合わせである。
End of explanation
fig = pl.figure()
ax = Axes3D(fig)
ax.scatter(a, b, c)
pl.show()
Explanation: 例えば(0, 0)を入力すると0.52328635を返している（つまりa[0]とb[0]を入力して、c[0]の値を返している）。
End of explanation
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
a = np.array([])
b = np.array([])
c = np.array([])
nn = NN()
nn.set_network()
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
        
for i in range(10000):
        l = np.random.choice([i for i in range(len(a))])
        m = nn.main(1, f, [a[l], b[l]], 0.5)
for x in X:
    for y in Y:
        idata = [x, y]
        c = np.append(c, nn.realize(f, idata))
fig = pl.figure()
ax = Axes3D(fig)
ax.scatter(a, b, c)
pl.show()
Explanation: 確率的勾配降下法を100回繰り返したが見た感じから近づいている。回数を10000回に増やしてみる。
End of explanation
ここで、
nn.hidden_layer
Explanation: 見た感じ随分近づいているように見える。
End of explanation
x_1 = Symbol('x_1')
x_2 = Symbol('x_2')
f = (1+sin(4*math.pi*x_1))*x_2*1/2
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
a = np.array([])
b = np.array([])
c = np.array([])
nn = NN()
nn.set_network()
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
        
for i in range(1000):
        l = np.random.choice([i for i in range(len(a))])
        m = nn.main(1, f, [a[l], b[l]], 0.5)
for x in X:
    for y in Y:
        idata = [x, y]
        c = np.append(c, nn.realize(f, idata))
fig = pl.figure()
ax = Axes3D(fig)
ax.scatter(a, b, c)
pl.show()
Explanation: 同様のことを課題の例で使われた関数でも試してみる。
End of explanation
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
a = np.array([])
b = np.array([])
c = np.array([])
nn = NN()
nn.set_network(h=5)
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
        
for i in range(1000):
        l = np.random.choice([i for i in range(len(a))])
        m = nn.main(1, f, [a[l], b[l]], 0.5)
for x in X:
    for y in Y:
        idata = [x, y]
        c = np.append(c, nn.realize(f, idata))
fig = pl.figure()
ax = Axes3D(fig)
ax.scatter(a, b, c)
pl.show()
Explanation: 上手く近似できないので中間層の数を変えてみる。5層にしてみる。
End of explanation
X = np.arange(-1, 1, 0.1)
Y = np.arange(-1, 1, 0.1)
print X, Y
Explanation: 目標と比べると大きく異なる。
サンプル数を、
End of explanation
fig = pl.figure()
ax = Axes3D(fig)
f = (1+sin(4*math.pi*x_1))*x_2*1/2
X = np.arange(-1, 1, 0.1)
Y = np.arange(-1, 1, 0.1)
a = np.array([])
b = np.array([])
c = np.array([])
fig = plt.figure()
nn = NN()
nn.set_network()
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
        c = np.append(c, nn.main2(50, f, [x, y], 0.8))
for i in range(50):
    l = np.random.choice([i for i in range(len(a))])
    m = nn.main2(20, f, [a[l], b[l]], 0.5)
    c[l] = m
a = np.array([])
b = np.array([])
c = np.array([])
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
        c = np.append(c, nn.realize(f, [x, y]))
        
ax.scatter(a, b, c)
ax.set_zlim(0, 1)
pl.show()
Explanation: で取り、学習の際にランダムに一個選ばれたサンプルを何十回も学習させてみた。
End of explanation
def example2(x_1, x_2):
    z = (1+np.sin(4*math.pi*x_1))*x_2*1/2
    return z
fig = pl.figure()
ax = Axes3D(fig)
X = np.arange(-1, 1, 0.1)
Y = np.arange(-1, 1, 0.1)
X, Y = np.meshgrid(X, Y)
Z = example2(X, Y)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
ax.set_zlim(-1, 1)
pl.show()
Explanation: 本来ならば下のような形になるべきであるので上手くいっているとは言い難い。
End of explanation
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
a = np.array([])
b = np.array([])
c = np.array([])
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
evl = np.array([])
for i in range(len(a)):
    nn = NN()
    nn.set_network()
    for j in range(1):
        l = np.random.choice([i for i in range(len(a))])
        if l != i:
            m = nn.main(1, f, [a[l], b[l]], 0.5)
    idata = [a[i], b[i]]
    est = nn.realize(f, idata)
    evl = np.append(evl, math.fabs(est - nn.supervised_data))
np.average(evl)
Explanation: 同じ方法でコブ・ダグラス型生産関数を学習させた様子をアニメーションにしてみた。この方法が何の意味を持つかは分からないが学習はまあまよくできていた。
mp4ファイルで添付した。
[考察]ここにはコードを書けなかったが、サンプル数が多くなった時は、ミニバッチ式の学習を試すべきだと思った。
最後に交差検定を行う。
初めに学習回数が極めて少ないNNである。
End of explanation
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
a = np.array([])
b = np.array([])
c = np.array([])
nn = NN()
nn.set_network(h=7)
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
evl = np.array([])
for i in range(len(a)):
    for j in range(10000):
        nn = NN()
        nn.set_network()
        l = np.random.choice([i for i in range(len(a))])
        if l != i:
            m = nn.main(1, f, [a[l], b[l]], 0.5)
    idata = [a[i], b[i]]
    evl = np.append(evl, math.fabs(nn.realize(f, idata) - nn.supervised_data))
evl
np.average(evl)
Explanation: 次に十分大きく(1000回に)してみる。
End of explanation
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
a = np.array([])
b = np.array([])
c = np.array([])
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
evl = np.array([])
for i in range(len(a)):
    for j in range(100):
        nn = NN()
        nn.set_network()
        l = np.random.choice([i for i in range(len(a))])
        if l != i:
            m = nn.main(1, f, [a[l], b[l]], 0.5)
    idata = [a[i], b[i]]
    est = nn.realize(f, idata)
    evl = np.append(evl, math.fabs(est - nn.supervised_data))
np.average(evl)
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
a = np.array([])
b = np.array([])
c = np.array([])
for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
evl = np.array([])
for i in range(len(a)):
    for j in range(100):
        nn = NN()
        nn.set_network(h=5)
        l = np.random.choice([i for i in range(len(a))])
        if l != i:
            m = nn.main(1, f, [a[l], b[l]], 0.5)
    idata = [a[i], b[i]]
    est = nn.realize(f, idata)
    evl = np.append(evl, math.fabs(est - nn.supervised_data))
np.average(evl)
Explanation: 誤差の平均であるので小さい方よい。
学習回数を大幅に増やした結果、精度が上がった。
次に回数を100回にして、中間層の数を2と5で精度を比較する。
End of explanation
<END_TASK>