Pythonで理解するディープラーニング入門

1a818bcb46ae361694782268afd5fb21?s=47 makaishi2
October 09, 2019

 Pythonで理解するディープラーニング入門

ディープラーニングの仕組みを理解するための一番のポイントは「損失関数」と「勾配降下法」の考え方です。本講演では、線形回帰モデルを題材に、この2つの考え方についてPythonのコーディングも含めた形で説明します。講演者の著作「最短コースでわかるディープラーニングの数学」からエッセンスをお届けします。

1a818bcb46ae361694782268afd5fb21?s=128

makaishi2

October 09, 2019
Tweet

Transcript

  1. 2.

    【主な経歴】 1987年⽇本アイ・ビー・エムに⼊社。東京基礎研究所で数式処理システムの研究開発に従事する。 1993年にSE部⾨に異動し、主にオープン系システムのインフラ設計・構築を担当。 2013年よりスマーターシティ事業、2016年8⽉にワトソン事業部に異動し、今に⾄る。 現在は、Watson Studio / Watson OpenScaleなどデータサイエンス系製品の提案活動が主体。 いろいろな領域を幅広くやっているので、IT基盤系・アプリ開発・プログラム⾔語・SQLチューニン

    グはもとよりWatsonや機械学習、ディープラーニングまで⼀通り語れるのが⾃慢。 【社外講師】 ⾦沢⼯業⼤学⼤学院 ⻁ノ⾨キャンパス客員教授 「AI技術特論」講師 【著作】 「Watson Studioで始める機械学習・深層学習」 リックテレコム 「最短コースでわかるディープラーニングの数学」 ⽇経BP この他雑誌や qiita (https://qiita.com/makaishi2) 執筆多数 ⾚⽯ 雅典 ⽇本IBM Data & AI 事業部 Watsonテクニカルセールス Executive IT Specialist 講演者紹介
  2. 3.
  3. 6.

    機械学習モデルとは 次の2つの原則を満たすモデル(システム)のことです 原則1 ⼊⼒データから出⼒データを返す 原則2 モデルは学習により作られる モデル ⼊⼒ ⾎液検査 データ

    出⼒ 慢性腎疾患 判定 横画素数 縦画素数 分類結果 200 300 縦⻑ 250 150 横⻑ 150 200 縦⻑ 右の学習データを観察して、⼈間が次のようなルールを作るのはNG if (横画素数) < (縦画素数) then (縦⻑)
  4. 8.

    教師あり学習 - 回帰モデル - 教師あり学習には、予測結果から次の2つの種類に⼤別されます。 回帰モデル: 数値を予測 分類モデル: クラス(グループ)を予測 回帰モデルの例

    (売上げ予測システム) モデル 天気︓雪 気温: 3°C ⽉曜⽇ 天気︓晴れ 気温: 20°C ⽇曜⽇ 1万円 20万円 (数値を予測) 売上げ⾦額
  5. 12.

    機械学習の実装⽅式 下図で右になるほどモデルの構造は複雑になりますが、学習の⽅式はすべて共通です。 そこで、本講演では、この中で最も単純でわかりやすい「線形回帰モデル」を例に、機械学習 のアルゴリズムを理解していきます。 1 1 × 0 × 1

    = ∙ 1 !" = %& + %( )( 1 1 × 2 () (1) (2) (3) = 0 + 1 1 + 2 2 = () 1 活性化関数 重み × × × 0 1 1 1 2 1 = () 0 2 0 2 = () × (隠れ層) u (出力層) 1 1 2 (入力層) × a 1 a 2 a f(u 1 ) f(u 2 ) = ( ) = = 線形回帰 ロジスティック回帰 ニューラルネットワーク
  6. 13.

    機械学習の実装⽅式 この図が線形回帰モデルからディープラーニングまで共通の学習⽅式です。 この中で、「損失関数」と「勾配降下法」の2つが重要な概念となります。 学習データ yt (正解データ) モデル (学習中) yp (予測値)

    損失関数 学習(勾配降下法) x (入力データ) 重要概念1: 正解データと予測値の 近さを数値で表現する 関数 重要概念2: 「微分」を使って損失関数 が最⼩になるパラーメータ 値を決定する モデルの構造は決まっている。 パラメータの値が学習対象。
  7. 19.

    座標系の平⾏移動 Numpyのブロードキャスト機能で、次元の違う変数同⼠で引き算ができます。 166 58.7 176 75.7 171 62.1 173 70.4

    169 60.1 171 65.4 - 166 58.7 176 75.7 171 62.1 173 70.4 169 60.1 - 171 65.4 171 65.4 171 65.4 171 65.4 171 65.4 ブロードキャスト機能で変数 のサイズが⾃動調整される (data) (mean)
  8. 21.

    前処理 ⼊⼒データの抽出 学習データは、⼊⼒データ(⾝⻑)の列と、 正解データ(体重)の列が含まれています。 ここから⼊⼒データの列を抽出します。 data1[:,0:1] すべての⾏を取得 0番⽬の列をベクトルのままで取得 学習データ yt

    (正解データ) モデル (学習中) yp (予測値) 損失関数 学習(勾配降下法) x (入力データ) ┽ = ┻ ɾ ø + ┻ ┼ ͱॻ͖׵͑ͯΈ·͢ɻ͢Δͱɺ͜ͷࣜͷӈล͸ ┻ ┻ ͱ͍͏ϕΫ τ ϧͱɺ ┼  ┼ ͱ͍͏ϕΫ τ ϧ ಺ੵ┻ ɾ ┼ͱද͢͜ ͱ͕Ͱ͖ ·͢ɻ ɹ1ZUIPOͰ͸͔Βಋೖ͞Εͨ৽ػೳͱ ͯ͠ɺ ਤ˔ਖ਼ղσʔλZUͷઃఆ ਤ˔ֶशσʔλ͔Βೖྗσʔλྻநग़ ਤ˔ೖྗσʔλྻʹμϛ ʔม਺௥Ճ ਤ˔ֶशσʔ ਤ˔ֶशσʔλͷฏߦҠಈͱɺ /VN1Zͷϒϩʔ υΩϟε τػೳ ਤ˔ֶशσʔλ͔Βೖྗσʔλྻநग़ ਤ˔ೖྗσʔλྻʹμϛ ʔม਺௥Ճ ਤ˔ֶशσʔλͷฏߦҠಈͱɺ /VN1Zͷϒϩʔ υΩϟε τػೳ ɹ ɹ ɹ ɹ ɹ ɹ ɹ ɹ ɹ ɹ ベクトルでなく「5⾏1列」の ⾏列にする。 (後で⾏う列追加に備えて)
  9. 22.

    前処理 正解データの抽出 学習データは、⼊⼒データ(⾝⻑)の列と、 正解データ(体重)の列が含まれています。 ここから正解データの列を抽出します。 data1[:,1] すべての⾏を取得 1番⽬の列をスカラーとして取得 学習データ yt

    (正解データ) モデル (学習中) yp (予測値) 損失関数 学習(勾配降下法) x (入力データ) ┽ = ┻ ɾ ø + ┻ ┼ ͱॻ͖׵͑ͯΈ·͢ɻ͢Δͱɺ͜ͷࣜͷӈล͸┻ ਤ˔༧ଌؔ਺ͷఆٛ ਤ˔ਖ਼ղσʔλZUͷઃఆ ਤ˔༧ଌؔ਺ͷςε τ ਤ˔ֶशσʔ ਤ˔ֶशσʔλͷฏߦҠಈͱɺ /VN1Zͷϒϩʔ υΩϟε τػೳ ┽ = ┻ ɾ ø + ┻ ┼ ͱॻ͖׵͑ͯΈ·͢ɻ͢Δͱɺ͜ͷࣜͷӈล͸┻  ┻ ┻ ͱ͍͏ϕΫ τ ϧͱɺ ┼  ┼ ͱ͍͏ϕΫ τ ϧͷɺ ಺ੵ┻ ɾ ┼ͱද͢͜ ͱ͕Ͱ͖ ·͢ɻ ɹ1ZUIPOͰ͸͔Βಋೖ͞Εͨ৽ػೳͱ ͯ͠ɺ!ԋ ਤ˔༧ଌ ༧ଌ ਤ˔ਖ਼ղσʔλZUͷઃఆ ग़ Ճ ਤ˔༧ଌ 正解データは単なる5次元ベクトル
  10. 23.

    予測関数 (凡例) y については、予測値と実測値の両⽅があるので、以下の表記で区別します。 予測値: (predict) 実測値: (true) ⼀次関数を利⽤した予測関数の式は次のとおりです。 =

    & + ( ポイント ・モデルの構造は事前に決まっている。 ・パラメータの値のみ⾃由度がある ・学習とは最適なパラメータ値を決めるプロセス この原理はディープラーニングでも同じです 学習データ yt (正解データ) モデル (学習中) yp (予測値) 損失関数 学習(勾配降下法) x (入力データ)
  11. 24.

    予測関数と内積計算 線形回帰モデルは⼀次関数なので、 予測値を記号ypで表すと、予測値の式は yp = & + ( と書けます。この式を =

    (&, () 、 = &, ( = (1, )とすると、(& は常に1の値を持つダミー変数とする) yp = & 2 1 + ( = 2 と2つのベクトルの内積の形で表現できます。 学習データ yt (正解データ) モデル (学習中) yp (予測値) 損失関数 学習(勾配降下法) x (入力データ)
  12. 25.

    ダミー変数列の追加 予測値を単純な内積の形式で計算するため、 ⼊⼒変数に常に1の値を持つダミー変数列を追加します。 np.insert(x1, 0, 1.0, axis=1) 0番⽬に挿⼊ 値 1.0

    を挿⼊ 列⽅向に挿⼊ 挿⼊されたダミー変数列 学習データ yt (正解データ) モデル (学習中) yp (予測値) 損失関数 学習(勾配降下法) x (入力データ)
  13. 26.

    予測関数と内積計算 Python3 では、内積は記号@で表記できます。 この記号を使って、予測関数を内積で表現します。 学習データ yt (正解データ) モデル (学習中) yp

    (予測値) 損失関数 学習(勾配降下法) x (入力データ) wに勝⼿な初期値を設定して、モデルの最初の予測値を計算してみます。 結果は全然間違っていますが、5つの点に対する予測値が同時に得られることがわかります。
  14. 27.

    損失関数 予測関数のグラフ(直線)を⻘で⽰しました。 このとき、実測値に対応した予測値の値は 実測値から直線に引いた垂線の⾜に相当します。 線形回帰の場合、損失関数は、 差が正負どちらでもいいように 「実測値-予測値」の⼆乗で計算されます。 絶対値を使わないのは、絶対値を使うとこの後の 微分計算がややこしくなってしまうためです。 学習データ

    yt (正解データ) モデル (学習中) yp (予測値) 損失関数 学習(勾配降下法) x (入力データ) ਤͰ͸ɺݩͷֶशσʔλ͔ΒɺೖྗσʔλYʹ͋ ΔྻͷΈΛநग़͍ͯ͠·͢ɻී௨ʹEBUB< >ͱ͍ ίʔσΟ ϯάʹ͢Δͱɺ݁Ռ͸ϕΫ τϧʹͳΔͷͰ͢ ɺ͜͜Ͱ͸ߦྻͷੑ࣭Λอͬͨ··ʹ͍ͨͨ͠Ίɺ ͑ͯEBUB< >ͱ͍͏ॻ͖ํʹ͍ͯ͠·͢ɻ/VN1Z ਺͸͢΂ͯTIBQFͱ͍͏ϓϩύςΟ Λ͍࣋ͬͯͯɺ ౰͢Δม਺͕Կ࣍ݩσʔλͰཁૉ਺͕͍ͭ͘ͳͷ ͕֬ೝͰ͖ ΔͷͰɺͦͷ͜ ͱ Λར༻ͯ͠Y഑ྻͷཁ ਺Λද͍ࣔͯ͠·͢ɻ ༧ଌؔ਺΁ͷ಺ੵͷར༻ͱ μϛʔม਺ͷ௥Ճ ઢܗ୯ճؼͷ৔߹ɺ༧ଌ஋Λܭࢉ͢Δࣜ͸ ┽ ━   ┻ ┼Ͱ͋Γɺ͜Ε͕͜ͷ··༧ଌؔ਺ͷࣜͱͳ ·͢ɻ͔͠͠ɺ1ZUIPOͰͷ࣮૷Λ؆୯ʹ͢ΔͨΊɺ ͷࣜΛ ͍ͯ·͢ɻ લॲཧ ʢਖ਼ղσʔλͷ෼཭ʣ ɹਤͰ͸ɺֶशσʔλ͔Βਖ਼ղσʔλZUͷઃఆΛ ͍ͯ͠·͢ɻ͜ͷ࣍ݩϕΫ τϧͷͦΕͧΕͷ஋͸ɺ ͜Ε͔Βߦ͏ػցֶशʹ͓͍ͯ࠷ऴతͳ໨ඪ஋ͱͳ Γ ·͢ɻ ਤ˔ଛࣦؔ਺ͷߟ͑ํ         9 :   Z U rZ Q  Z U ࣮ଌ஋ Z Q ༧ଌ஋ ͔͠͠ɺ ʹ͜ͷΑ ࢉͯ݁͠ ࣜΛX ͨɻ͜ͷ རͳͱ ͜ ɹ಺ੵ
  15. 29.

    損失関数 学習データ yt (正解データ) モデル (学習中) yp (予測値) 損失関数 学習(勾配降下法)

    x (入力データ) 損失関数の数式は次のように書き換えることができます。 ⾚枠で囲んだ部分は(())の平均値なので、np.mean関数を利⽤できます。 結局、損失関数はPythonの場合、次のコーディングで実装できます。 現段階で予測値ypはパラメータ値は適当に決めて計算しているので、 損失関数の値は約50.4とかなり⼤きな値になっています。
  16. 31.

    勾配降下法 2変数関数 (, )があるとき、Lを最⼩にする(u, v)の値を求めたい -> (1) Lの微分※の値が0になる(u, v)を求めればいい ->

    (2) Lの微分にマイナスを付けた結果は、斜⾯においたボールが斜⾯を降りる向きと同じ -> (3) 少しずつ斜⾯を降りると最後は底にたどり着く ※ 厳密にいうと「偏微分」です
  17. 32.

    勾配降下法 ✓ uk+1 vk+1 ◆ = ✓ uk vk ◆

    ↵ ✓ Lu(uk, vk) Lv(uk, vk) ◆ (, ) ( , ) θ が最小値を取るとき の(, )の向き = 90°のとき、の値 は変化しない (の等高線の向き) 結論(重要) 前ページ(2)の詳細な説明 (イメージだけ持てればいいです) 斜⾯を⼀歩降りるための式。 この操作を繰り返すと斜⾯の底に達する! Lの微分結果 学習率 (2ページ前の微分計算結果)
  18. 33.

    勾配降下法 勾配降下法のPython実装は以下のとおりです。 下の式の中で alphaは学習率と呼ばれる 機械学習で最も重要なパラメータで通常は0.01や0.001といった値を利⽤します。 損失関数の微分計算がなぜこのコードになるかは、 右の図に概要を⽰しました。 学習データ yt (正解データ)

    モデル (学習中) yp (予測値) 損失関数 学習(勾配降下法) x (入力データ) 学習率 損失関数の微分結果 1 2 3 4 5 6 X = yd = 1 2 3 × × やりたいこと (Xに対して列方向の内積) X . T = 1 3 5 2 4 6 yd = 1 2 3 @ Xの転置行列をつくれば内積計算ができる × × ✓ uk+1 vk+1 ◆ = ✓ uk vk ◆ ↵ ✓ Lu(uk, vk) Lv(uk, vk) ◆
  19. 34.

    実装コード(初期化処理) 最後に実装コード全体を⽰します。まず、初期化処理部分です。 # 初期化処理 # データ系列総数 (=5) M = x.shape[0]

    # ⼊⼒データ次元数(ダミー変数を含む) (=2) D = x.shape[1] # 繰り返し回数 iters = 200 # 学習率 alpha = 0.01 # 重みベクトルの初期値 (勝⼿な値を設定) w = np.array([2, -1]) # 評価結果記録⽤ (損失関数値, w0, w1を記録) history = np.zeros((0,4)) データ系列数 M、⼊⼒データ次元数 Dを⼊⼒変数のshape から取得することで、汎⽤的な実装コードになっている。 繰り返し回数(iter)と学習率(alpha)は、案件毎に最適な値 に調整する必要がある。
  20. 35.

    実装コード(繰り返し処理) 次に繰り返し処理部分です。 # 繰り返しループ for k in range(iters): # 予測値の計算

    yp = pred(x, w) # 誤差の計算 yd = yp - yt # 勾配降下法の実装 w = w - alpha * (x.T @ yd) / M # 学習曲線描画⽤データの計算、保存 # 重みベクトル値の取得 w0 = float(w[0]) w1 = float(w[1]) # 損失関数値の計算 L = np.mean(yd ** 2) / 2 # 計算結果の記録 line = np.array([k, L, w0, w1]) history = np.vstack((history, line)) # 画⾯表⽰ print( "iter = %d L = %f w0 = %f w1 = %f" % (k, L, w0, w1)) 勾配降下法の本質的な部分はこの3⾏だけ グラフ表⽰、途中経過表⽰のためのコード
  21. 36.

    実装コード(計算結果) 計算結果は次のようになりました。 左の画⾯から、損失関数値Lが最後は2.3程度の⼩さな値になっていることがわかります。 右の画⾯から、正解値と近い値を予測値が取っていることがわかります。 iter = 0 L = 50.416000

    w0 = 1.980000 w1 = -0.672800 iter = 1 L = 40.291163 w0 = 1.960200 w1 = -0.383555 iter = 2 L = 32.371142 w0 = 1.940598 w1 = -0.127863 iter = 3 L = 26.174246 w0 = 1.921192 w1 = 0.098169 iter = 4 L = 21.324050 w0 = 1.901980 w1 = 0.297982 iter = 5 L = 17.526391 w0 = 1.882960 w1 = 0.474616 (途中略) iter = 195 L = 2.309214 w0 = 0.278951 w1 = 1.820690 iter = 196 L = 2.308424 w0 = 0.276162 w1 = 1.820690 iter = 197 L = 2.307650 w0 = 0.273400 w1 = 1.820690 iter = 198 L = 2.306891 w0 = 0.270666 w1 = 1.820690 iter = 199 L = 2.306147 w0 = 0.267959 w1 = 1.820690 ループ処理出⼒ 予測値と正解値