準備

Googleドライブのマウント

In [5]:
from google.colab import drive
drive.mount('/content/drive')
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).

sys.pathの設定

以下では,Googleドライブのマイドライブ直下にDNN_codeフォルダを置くことを仮定しています.必要に応じて,パスを変更してください.

In [6]:
import sys
sys.path.append('/content/drive/My Drive/DNN_code_colab_lesson_1_2')

importと関数定義

In [7]:
import numpy as np
from common import functions

def print_vec(text, vec):
    print("*** " + text + " ***")
    print(vec)
    print("shape: " + str(vec.shape))
    print("")
#【コメント】ベクトル、行列のprint汎用関数

順伝播(単層・単ユニット)

In [9]:
# 順伝播(単層・単ユニット)

# 重み
W = np.array([[0.1], [0.2]])

## 試してみよう_配列の初期化
#W = np.zeros(2)
#W = np.ones(2)
#W = np.random.rand(2)
#W = np.random.randint(5, size=(2))

print_vec("重み", W)


# バイアス
b = np.array(0.5)

## 試してみよう_数値の初期化
#b = np.random.rand() # 0~1のランダム数値
#b = np.random.rand() * 10 -5  # -5~5のランダム数値

print_vec("バイアス", b)

# 入力値
x = np.array([2, 3])
print_vec("入力", x)


# 総入力
u = np.dot(x, W) + b
print_vec("総入力", u)

# 中間層出力
z = functions.relu(u)
print_vec("中間層出力", z)

#【コメント】入力2個、1ノードの場合のコード
#【コメント】1ノードなのでバイアスがスカラー
*** 重み ***
[[0.1]
 [0.2]]
shape: (2, 1)

*** バイアス ***
0.5
shape: ()

*** 入力 ***
[2 3]
shape: (2,)

*** 総入力 ***
[1.3]
shape: (1,)

*** 中間層出力 ***
[1.3]
shape: (1,)

順伝播(単層・複数ユニット)

In [11]:
# 順伝播(単層・複数ユニット)

# 重み
W = np.array([
    [0.1, 0.2, 0.3,0], 
    [0.2, 0.3, 0.4, 0.5], 
    [0.3, 0.4, 0.5, 1],
])

## 試してみよう_配列の初期化
#W = np.zeros((4,3))
#W = np.ones((4,3))
#W = np.random.rand(4,3)
#W = np.random.randint(5, size=(4,3))

print_vec("重み", W)

# バイアス
b = np.array([0.1, 0.2, 0.3])
print_vec("バイアス", b)

# 入力値
x = np.array([1.0, 5.0, 2.0, -1.0])
print_vec("入力", x)

#  総入力
u = np.dot(W, x) + b
print_vec("総入力", u)

# 中間層出力
z = functions.sigmoid(u)
print_vec("中間層出力", z)

#【コメント】入力4個、3ノードの場合のコード
#【コメント】複数ノードなのでバイアスがベクトル
*** 重み ***
[[0.1 0.2 0.3 0. ]
 [0.2 0.3 0.4 0.5]
 [0.3 0.4 0.5 1. ]]
shape: (3, 4)

*** バイアス ***
[0.1 0.2 0.3]
shape: (3,)

*** 入力 ***
[ 1.  5.  2. -1.]
shape: (4,)

*** 総入力 ***
[1.8 2.2 2.6]
shape: (3,)

*** 中間層出力 ***
[0.85814894 0.90024951 0.93086158]
shape: (3,)

順伝播(3層・複数ユニット)

In [12]:
# 順伝播(3層・複数ユニット)

# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
    print("##### ネットワークの初期化 #####")
    network = {}
    
    input_layer_size = 3
    hidden_layer_size_1=10
    hidden_layer_size_2=5
    output_layer_size = 4
    
    #試してみよう
    #_各パラメータのshapeを表示
    #_ネットワークの初期値ランダム生成
    network['W1'] = np.random.rand(input_layer_size, hidden_layer_size_1)
    network['W2'] = np.random.rand(hidden_layer_size_1,hidden_layer_size_2)
    network['W3'] = np.random.rand(hidden_layer_size_2,output_layer_size)

    network['b1'] =  np.random.rand(hidden_layer_size_1)
    network['b2'] =  np.random.rand(hidden_layer_size_2)
    network['b3'] =  np.random.rand(output_layer_size)

    print_vec("重み1", network['W1'] )
    print_vec("重み2", network['W2'] )
    print_vec("重み3", network['W3'] )
    print_vec("バイアス1", network['b1'] )
    print_vec("バイアス2", network['b2'] )
    print_vec("バイアス3", network['b3'] )

    return network
#【コメント】入力3個、1層目10ノード,2層目5ノード,出力層4ノードの
#【コメント】重み行列、バイアスベクトルを乱数で生成する


# プロセスを作成
# x:入力値
def forward(network, x):
    
    print("##### 順伝播開始 #####")

    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']
    
    # 1層の総入力
    u1 = np.dot(x, W1) + b1
    
    # 1層の総出力
    z1 = functions.relu(u1)
    
    # 2層の総入力
    u2 = np.dot(z1, W2) + b2
    
    # 2層の総出力
    z2 = functions.relu(u2)

    # 出力層の総入力
    u3 = np.dot(z2, W3) + b3
    
    # 出力層の総出力
    y = u3
    
    print_vec("総入力1", u1)
    print_vec("中間層出力1", z1)
    print_vec("中間層出力2", z2)
    print_vec("総入力2", u2)
    print_vec("出力", y)
    print("出力合計: " + str(np.sum(y)))

    return y, z1, z2

# 入力値
x = np.array([1., 2., 4.])
print_vec("入力", x)

# ネットワークの初期化
network =  init_network()

y, z1, z2 = forward(network, x)
#【コメント】出力層は活性化関数なし?
*** 入力 ***
[1. 2. 4.]
shape: (3,)

##### ネットワークの初期化 #####
*** 重み1 ***
[[0.80462819 0.75590361 0.75247828 0.34344484 0.62307129 0.56385273
  0.4944344  0.69515368 0.41885838 0.98506208]
 [0.03101983 0.78025342 0.94501772 0.50407553 0.54278541 0.39998045
  0.49397586 0.68275688 0.99700838 0.85508265]
 [0.69530818 0.87025039 0.15045663 0.77860886 0.57749014 0.56491656
  0.44529549 0.78842557 0.45769525 0.5001091 ]]
shape: (3, 10)

*** 重み2 ***
[[0.44309375 0.12064227 0.0270668  0.05216269 0.05014122]
 [0.90110697 0.44734748 0.12977899 0.81210899 0.00563751]
 [0.90605304 0.79171647 0.87067677 0.67344183 0.89084141]
 [0.70063285 0.70625241 0.04830472 0.58994716 0.4738396 ]
 [0.80694314 0.77063217 0.67256225 0.27797171 0.34647861]
 [0.0767706  0.61423937 0.53731102 0.12895384 0.02936232]
 [0.18220853 0.99529319 0.58304453 0.04262901 0.62534071]
 [0.29480519 0.05552075 0.7285459  0.97063584 0.37592046]
 [0.39682665 0.30129704 0.76165752 0.94887399 0.17267126]
 [0.26383628 0.67394551 0.68555802 0.04131149 0.84505855]]
shape: (10, 5)

*** 重み3 ***
[[0.45317899 0.05071563 0.60768666 0.03751517]
 [0.90839287 0.78199019 0.56462528 0.57035412]
 [0.99923463 0.56749438 0.53028838 0.01029807]
 [0.82016943 0.32213467 0.83697231 0.14210795]
 [0.27600264 0.16118455 0.99562136 0.33507701]]
shape: (5, 4)

*** バイアス1 ***
[0.82580496 0.55910066 0.41018746 0.22137272 0.52366476 0.33907132
 0.59304322 0.04938901 0.31508317 0.14995501]
shape: (10,)

*** バイアス2 ***
[0.11875237 0.15070145 0.28790415 0.79802853 0.56326225]
shape: (5,)

*** バイアス3 ***
[0.06049414 0.33212788 0.14005534 0.78359935]
shape: (4,)

##### 順伝播開始 #####
*** 総入力1 ***
[4.47370553 6.35651265 3.65452767 4.68740406 4.54226741 3.96255119
 3.85661129 5.26375872 4.5587393  4.84561879]
shape: (10,)

*** 中間層出力1 ***
[4.47370553 6.35651265 3.65452767 4.68740406 4.54226741 3.96255119
 3.85661129 5.26375872 4.5587393  4.84561879]
shape: (10,)

*** 中間層出力2 ***
[23.73579553 24.44212641 22.70396768 22.99305592 17.2626901 ]
shape: (5,)

*** 総入力2 ***
[23.73579553 24.44212641 22.70396768 22.99305592 17.2626901 ]
shape: (5,)

*** 出力 ***
[79.32945163 43.72312016 76.83592851 24.90035308]
shape: (4,)

出力合計: 224.78885338147555
In [13]:
np.random.rand(3, 3)
Out[13]:
array([[0.07405986, 0.15883957, 0.83113315],
       [0.45333262, 0.53658353, 0.14504478],
       [0.20044202, 0.35197703, 0.53805627]])

多クラス分類(2-3-4ネットワーク)

In [20]:
# 多クラス分類
# 2-3-4ネットワーク

# !試してみよう_ノードの構成を 3-5-6 に変更してみよう

# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
    print("##### ネットワークの初期化 #####")

    #試してみよう
    #_各パラメータのshapeを表示
    #_ネットワークの初期値ランダム生成

    network = {}
    
    input_layer_size = 3
    hidden_layer_size=5
    output_layer_size = 6
    
    #試してみよう
    #_各パラメータのshapeを表示
    #_ネットワークの初期値ランダム生成
    network['W1'] = np.random.rand(input_layer_size, hidden_layer_size)
    network['W2'] = np.random.rand(hidden_layer_size,output_layer_size)

    network['b1'] =  np.random.rand(hidden_layer_size)
    network['b2'] =  np.random.rand(output_layer_size)
    
    print_vec("重み1", network['W1'] )
    print_vec("重み2", network['W2'] )
    print_vec("バイアス1", network['b1'] )
    print_vec("バイアス2", network['b2'] )

    return network

# プロセスを作成
# x:入力値
def forward(network, x):
    
    print("##### 順伝播開始 #####")
    W1, W2 = network['W1'], network['W2']
    b1, b2 = network['b1'], network['b2']
    
    # 1層の総入力
    u1 = np.dot(x, W1) + b1

    # 1層の総出力
    z1 = functions.relu(u1)

    # 2層の総入力
    u2 = np.dot(z1, W2) + b2
    
    # 出力値
    y = functions.softmax(u2)
    
    print_vec("総入力1", u1)
    print_vec("中間層出力1", z1)
    print_vec("総入力2", u2)
    print_vec("出力1", y)
    print("出力合計: " + str(np.sum(y)))
        
    return y, z1

## 事前データ
# 入力値
x = np.array([1., 2.,  3.])

# 目標出力
d = np.array([0, 0, 0, 1, 0, 0])

# ネットワークの初期化
network =  init_network()

# 出力
y, z1 = forward(network, x)

# 誤差
loss = functions.cross_entropy_error(d, y)

## 表示
print("\n##### 結果表示 #####")
print_vec("出力", y)
print_vec("訓練データ", d)
print_vec("交差エントロピー誤差",  loss)

#【コメント】順伝搬で出力し目標との誤差を表示
#【コメント】重みバイアスを乱数できめているため実行ごとに誤差が異なる
##### ネットワークの初期化 #####
*** 重み1 ***
[[0.52501272 0.37385113 0.72092218 0.63294443 0.22725646]
 [0.57788169 0.59670048 0.02759574 0.99318705 0.90217288]
 [0.42424177 0.28478812 0.50794304 0.33814182 0.33418085]]
shape: (3, 5)

*** 重み2 ***
[[0.27848622 0.95627033 0.51353199 0.59933326 0.88947273 0.71380458]
 [0.6309585  0.38090757 0.28883381 0.59187245 0.80927582 0.83793551]
 [0.5086149  0.51036347 0.74412906 0.0855829  0.63266818 0.78326842]
 [0.59070701 0.00324265 0.55643702 0.75328504 0.54281514 0.36668387]
 [0.12415409 0.91165027 0.57368711 0.0978945  0.48419199 0.33345375]]
shape: (5, 6)

*** バイアス1 ***
[0.75416657 0.24689273 0.8891334  0.90225682 0.85016803]
shape: (5,)

*** バイアス2 ***
[0.76045809 0.17882642 0.43053913 0.28811364 0.14812331 0.26779854]
shape: (6,)

##### 順伝播開始 #####
*** 総入力1 ***
[3.70766798 2.66850916 3.18907617 4.53600082 3.8843128 ]
shape: (5,)

*** 中間層出力1 ***
[3.70766798 2.66850916 3.18907617 4.53600082 3.8843128 ]
shape: (5,)

*** 総入力2 ***
[ 8.26042354  9.92424614 10.23076414  8.15974424 11.96614287 10.60680717]
shape: (6,)

*** 出力1 ***
[0.01527095 0.08062227 0.10954034 0.01380834 0.62121152 0.15954658]
shape: (6,)

出力合計: 1.0

##### 結果表示 #####
*** 出力 ***
[0.01527095 0.08062227 0.10954034 0.01380834 0.62121152 0.15954658]
shape: (6,)

*** 訓練データ ***
[0 0 0 1 0 0]
shape: (6,)

*** 交差エントロピー誤差 ***
4.282475042356507
shape: ()

回帰(2-3-2ネットワーク)

In [22]:
# 回帰
# 2-3-2ネットワーク

# !試してみよう_ノードの構成を 3-5-4 に変更してみよう

# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
    print("##### ネットワークの初期化 #####")

    input_layer_size = 3
    hidden_layer_size=5
    output_layer_size = 2
    
    #試してみよう
    #_各パラメータのshapeを表示
    #_ネットワークの初期値ランダム生成
    network['W1'] = np.random.rand(input_layer_size, hidden_layer_size)
    network['W2'] = np.random.rand(hidden_layer_size,output_layer_size)

    network['b1'] =  np.random.rand(hidden_layer_size)
    network['b2'] =  np.random.rand(output_layer_size)
    
    print_vec("重み1", network['W1'] )
    print_vec("重み2", network['W2'] )
    print_vec("バイアス1", network['b1'] )
    print_vec("バイアス2", network['b2'] )

    return network

# プロセスを作成
def forward(network, x):
    print("##### 順伝播開始 #####")
    
    W1, W2 = network['W1'], network['W2']
    b1, b2 = network['b1'], network['b2']
    # 隠れ層の総入力
    u1 = np.dot(x, W1) + b1
    # 隠れ層の総出力
    z1 = functions.relu(u1)
    # 出力層の総入力
    u2 = np.dot(z1, W2) + b2
    # 出力層の総出力
    y = u2
    
    print_vec("総入力1", u1)
    print_vec("中間層出力1", z1)
    print_vec("総入力2", u2)
    print_vec("出力1", y)
    print("出力合計: " + str(np.sum(y)))
    
    return y, z1

# 入力値
x = np.array([1., 2., 3.])
network =  init_network()
y, z1 = forward(network, x)
# 目標出力
d = np.array([2., 4.])
# 誤差
loss = functions.mean_squared_error(d, y)

## 表示
print("\n##### 結果表示 #####")
print_vec("中間層出力", z1)
print_vec("出力", y)
print_vec("訓練データ", d)
print_vec("二乗誤差",  loss)

#【コメント】順伝搬で出力し目標との誤差を表示
#【コメント】重みバイアスを乱数できめているため実行ごとに誤差が異なる
##### ネットワークの初期化 #####
*** 重み1 ***
[[0.99357924 0.77457023 0.64998199 0.13347247 0.0322367 ]
 [0.03121338 0.95988125 0.98510098 0.55749656 0.92106169]
 [0.57992816 0.09000112 0.33679806 0.71723988 0.66009802]]
shape: (3, 5)

*** 重み2 ***
[[0.26159894 0.16731779]
 [0.74782821 0.45383759]
 [0.03868085 0.14681247]
 [0.67018687 0.20942432]
 [0.87173763 0.92554074]]
shape: (5, 2)

*** バイアス1 ***
[0.07524576 0.13528987 0.71201515 0.74279906 0.76397613]
shape: (5,)

*** バイアス2 ***
[0.89091437 0.16480165]
shape: (2,)

##### 順伝播開始 #####
*** 総入力1 ***
[2.87103623 3.09962596 4.34259329 4.14298429 4.61863027]
shape: (5,)

*** 中間層出力1 ***
[2.87103623 3.09962596 4.34259329 4.14298429 4.61863027]
shape: (5,)

*** 総入力2 ***
[10.93074482  7.83182283]
shape: (2,)

*** 出力1 ***
[10.93074482  7.83182283]
shape: (2,)

出力合計: 18.762567643187865

##### 結果表示 #####
*** 中間層出力 ***
[2.87103623 3.09962596 4.34259329 4.14298429 4.61863027]
shape: (5,)

*** 出力 ***
[10.93074482  7.83182283]
shape: (2,)

*** 訓練データ ***
[2. 4.]
shape: (2,)

*** 二乗誤差 ***
23.610267287621365
shape: ()

2値分類(2-3-1ネットワーク)

In [60]:
# 2値分類
# 2-3-1ネットワーク

# !試してみよう_ノードの構成を 5-10-20-1 に変更してみよう

# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
    print("##### ネットワークの初期化 #####")

    network = {}
    network['W1'] = np.array([
        [0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1],
        [0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1],
        [0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1],
        [0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1],
        [0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1]
    ])
    network['W2'] = np.random.rand(10, 20)
    network['W3'] = np.random.rand(20, 1)

    network['b1'] = np.random.rand(10)
    network['b2'] =np.random.rand(20)
    network['b3'] =np.random.rand(1)

    return network


# プロセスを作成
def forward(network, x):
    print("##### 順伝播開始 #####")
    
    W1, W2, W3 = network['W1'], network['W2'],network['W3']
    b1, b2, b3 = network['b1'], network['b2'],network['b3']

    # 隠れ層の総入力
    u1 = np.dot(x, W1) + b1
    # 隠れ層1の総出力
    z1 = functions.relu(u1)
    # 隠れ層2層への総入力
    u2 = np.dot(z1, W2) + b2
    # 隠れ層2の出力
    z2 = functions.relu(u2)
    
    u3 = np.dot(z2, W3) + b3
    z3 = functions.sigmoid(u3)
    y = z3    
    print_vec("総入力1", u1)
    print_vec("中間層出力1", z1)
    print_vec("総入力2", u2)
    print_vec("総入力3", u3)
    print_vec("出力1", y)
    print("出力合計: " + str(np.sum(y)))

    return y, z1

# 入力値
x = np.array([1., 2.,2.,4.,5.])

# 目標出力
d = np.array([1])
network =  init_network()
y, z1 = forward(network, x)
# 誤差
loss = functions.cross_entropy_error(d, y)

## 表示
print("\n##### 結果表示 #####")
print_vec("中間層出力", z1)
print_vec("出力", y)
print_vec("訓練データ", d)
print_vec("交差エントロピー誤差",  loss)

#【コメント】順伝搬で出力し目標との誤差を表示
#【コメント】W1以外は乱数できめているのに実行ごとにy変わらない
#【コメント】u3が200くらいになっているのでシグモイド関数で1になる
#【コメント】重み、バイアスが大きすぎる?
##### ネットワークの初期化 #####
##### 順伝播開始 #####
*** 総入力1 ***
[2.01778396 4.22737494 7.23996492 1.6719499  5.0989575  7.65190808
 1.94946513 5.01710757 7.54302522 2.17287395]
shape: (10,)

*** 中間層出力1 ***
[2.01778396 4.22737494 7.23996492 1.6719499  5.0989575  7.65190808
 1.94946513 5.01710757 7.54302522 2.17287395]
shape: (10,)

*** 総入力2 ***
[26.69375131 24.38139238 29.17373197 24.16840841 30.49687175 24.45730836
 24.25987802 16.60045357 23.50378179 23.81909939 29.67480141 27.89760291
 21.16031914 26.94562271 20.32536802 18.35238748 20.5378596  21.95068852
 27.42809407 21.61670844]
shape: (20,)

*** 総入力3 ***
[246.63031999]
shape: (1,)

*** 出力1 ***
[1.]
shape: (1,)

出力合計: 1.0

##### 結果表示 #####
*** 中間層出力 ***
[2.01778396 4.22737494 7.23996492 1.6719499  5.0989575  7.65190808
 1.94946513 5.01710757 7.54302522 2.17287395]
shape: (10,)

*** 出力 ***
[1.]
shape: (1,)

*** 訓練データ ***
[1]
shape: (1,)

*** 交差エントロピー誤差 ***
-9.999999505838704e-08
shape: ()