{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# 「深層学習」読書会 〜第6章〜" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

2016/05/21 機械学習 名古屋 第4回勉強会

" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## 第6章 畳込みニューラルネット" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.1 単純型細胞と複雑型細胞" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "後回し。 \n", "《TODO: やるとしても言葉の説明だけ?》 \n", "《TODO: 図を描くか?》" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.2 全体の構造" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "from graphviz import Digraph" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "fig_6_3 = Digraph(\"fig_6_3\", format=\"svg\")\n", "\n", "fig_6_3.body.extend(['rankdir=LR'])\n", "\n", "c1 = Digraph('cluster_1')\n", "c1.body.append('style=filled')\n", "c1.body.append('color=white')\n", "c1.node_attr.update(shape='box', style='rounded,filled', color='white', penwidth='2')\n", "c1.attr('edge', color=\"#737373\")\n", "c1.edges([('input', 'conv0'), ('conv0', 'conv1'), ('conv1', 'pooling1'), ('pooling1', 'lcm1')])\n", "c1.node('input', 'input (image)', fillcolor=\"#b3ffff\", color=\"#009999\")\n", "c1.node('conv0', 'convolution', fillcolor=\"#fb8072\", color=\"#941305\")\n", "c1.node('conv1', 'convolution', fillcolor=\"#fb8072\", color=\"#941305\")\n", "c1.node('pooling1', 'pooling', fillcolor=\"#80b1d3\", color=\"#275372\")\n", "c1.node('lcm1', 'LCM', fillcolor=\"#eeeeee\", color=\"#808080\")\n", "\n", "c2 = Digraph('cluster_2')\n", "c2.body.append('style=filled')\n", "c2.body.append('color=white')\n", "c2.node_attr.update(shape='box', style='rounded,filled', color='white', penwidth='2')\n", "c2.attr('edge', color=\"#737373\")\n", "c2.edges([('conv2', 'pooling2'), ('pooling2', 'fc1'), ('fc1', 'fc2'), ('fc2', 'softmax'), ('softmax', 'output')])\n", "c2.node('conv2', 'convolution', fillcolor=\"#fb8072\", color=\"#941305\")\n", "c2.node('pooling2', 'pooling', fillcolor=\"#80b1d3\", color=\"#275372\")\n", "c2.node('fc1', 'fully-\\nconnected', fillcolor=\"#ffffb3\", color=\"#999900\")\n", "c2.node('fc2', 'fully-\\nconnected', fillcolor=\"#ffffb3\", color=\"#999900\")\n", "c2.node('softmax', 'softmax', fillcolor=\"#b3de69\", color=\"#597d1c\")\n", "c2.node('output', 'output (label)', fillcolor=\"#b3ffff\", color=\"#009999\")\n", "\n", "fig_6_3.subgraph(c1)\n", "fig_6_3.subgraph(c2)\n", "\n", "fig_6_3.attr('edge', color=\"#737373\")\n", "\n", "fig_6_3.edge('conv2', 'lcm1', dir=\"back\", minlen=\"4\")\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "fig_6_3\n", "\n", "cluster_1\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "input\n", "\n", "input (image)\n", "\n", "\n", "conv0\n", "\n", "convolution\n", "\n", "\n", "input->conv0\n", "\n", "\n", "\n", "\n", "conv1\n", "\n", "convolution\n", "\n", "\n", "conv0->conv1\n", "\n", "\n", "\n", "\n", "pooling1\n", "\n", "pooling\n", "\n", "\n", "conv1->pooling1\n", "\n", "\n", "\n", "\n", "lcm1\n", "\n", "LCM\n", "\n", "\n", "pooling1->lcm1\n", "\n", "\n", "\n", "\n", "conv2\n", "\n", "convolution\n", "\n", "\n", "conv2->lcm1\n", "\n", "\n", "\n", "\n", "pooling2\n", "\n", "pooling\n", "\n", "\n", "conv2->pooling2\n", "\n", "\n", "\n", "\n", "fc1\n", "\n", "fully-\n", "connected\n", "\n", "\n", "pooling2->fc1\n", "\n", "\n", "\n", "\n", "fc2\n", "\n", "fully-\n", "connected\n", "\n", "\n", "fc1->fc2\n", "\n", "\n", "\n", "\n", "softmax\n", "\n", "softmax\n", "\n", "\n", "fc2->softmax\n", "\n", "\n", "\n", "\n", "output\n", "\n", "output (label)\n", "\n", "\n", "softmax->output\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig_6_3" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "fig_6_3_ja = Digraph(\"fig_6_3_ja\", format=\"svg\")\n", "\n", "fig_6_3_ja.body.extend(['rankdir=LR'])\n", "\n", "c1j = Digraph('cluster_1')\n", "c1j.body.append('style=filled')\n", "c1j.body.append('color=white')\n", "c1j.node_attr.update(shape='box', style='rounded,filled', color='white', penwidth='2')\n", "c1j.attr('edge', color=\"#737373\")\n", "c1j.edges([('input', 'conv0'), ('conv0', 'conv1'), ('conv1', 'pooling1'), ('pooling1', 'lcm1')])\n", "c1j.node('input', '入力(画像)', fillcolor=\"#b3ffff\", color=\"#009999\")\n", "c1j.node('conv0', '畳み込み', fillcolor=\"#fb8072\", color=\"#941305\")\n", "c1j.node('conv1', '畳み込み', fillcolor=\"#fb8072\", color=\"#941305\")\n", "c1j.node('pooling1', 'プーリング', fillcolor=\"#80b1d3\", color=\"#275372\")\n", "c1j.node('lcm1', '正規化', fillcolor=\"#eeeeee\", color=\"#808080\")\n", "\n", "c2j = Digraph('cluster_2')\n", "c2j.body.append('style=filled')\n", "c2j.body.append('color=white')\n", "c2j.node_attr.update(shape='box', style='rounded,filled', color='white', penwidth='2')\n", "c2j.attr('edge', color=\"#737373\")\n", "c2j.edges([('conv2', 'pooling2'), ('pooling2', 'fc1'), ('fc1', 'fc2'), ('fc2', 'softmax'), ('softmax', 'output')])\n", "c2j.node('conv2', '畳み込み', fillcolor=\"#fb8072\", color=\"#941305\")\n", "c2j.node('pooling2', 'プーリング', fillcolor=\"#80b1d3\", color=\"#275372\")\n", "c2j.node('fc1', '全結合', fillcolor=\"#ffffb3\", color=\"#999900\")\n", "c2j.node('fc2', '全結合', fillcolor=\"#ffffb3\", color=\"#999900\")\n", "c2j.node('softmax', 'softmax', fillcolor=\"#b3de69\", color=\"#597d1c\")\n", "c2j.node('output', '出力 (ラベル)', fillcolor=\"#b3ffff\", color=\"#009999\")\n", "\n", "fig_6_3_ja.subgraph(c1j)\n", "fig_6_3_ja.subgraph(c2j)\n", "\n", "fig_6_3_ja.attr('edge', color=\"#737373\")\n", "\n", "fig_6_3_ja.edge('conv2', 'lcm1', dir=\"back\", minlen=\"4\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "fig_6_3_ja\n", "\n", "cluster_1\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "input\n", "\n", "入力(画像)\n", "\n", "\n", "conv0\n", "\n", "畳み込み\n", "\n", "\n", "input->conv0\n", "\n", "\n", "\n", "\n", "conv1\n", "\n", "畳み込み\n", "\n", "\n", "conv0->conv1\n", "\n", "\n", "\n", "\n", "pooling1\n", "\n", "プーリング\n", "\n", "\n", "conv1->pooling1\n", "\n", "\n", "\n", "\n", "lcm1\n", "\n", "正規化\n", "\n", "\n", "pooling1->lcm1\n", "\n", "\n", "\n", "\n", "conv2\n", "\n", "畳み込み\n", "\n", "\n", "conv2->lcm1\n", "\n", "\n", "\n", "\n", "pooling2\n", "\n", "プーリング\n", "\n", "\n", "conv2->pooling2\n", "\n", "\n", "\n", "\n", "fc1\n", "\n", "全結合\n", "\n", "\n", "pooling2->fc1\n", "\n", "\n", "\n", "\n", "fc2\n", "\n", "全結合\n", "\n", "\n", "fc1->fc2\n", "\n", "\n", "\n", "\n", "softmax\n", "\n", "softmax\n", "\n", "\n", "fc2->softmax\n", "\n", "\n", "\n", "\n", "output\n", "\n", "出力 (ラベル)\n", "\n", "\n", "softmax->output\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig_6_3_ja" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.3 畳込み" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "import tensorflow as tf" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### 6.3.1 定義" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "+ $x_{ij}$: (入力の)画像の $(i, j)$ の画素値($0 \\le i, j \\lt W$, $W$ は画像の縦及び横のサイズ(正方形と仮定))\n", "+ $h_{pq}$: **フィルタ**画像の $(p, q)$ の画素値($0 \\le p, q \\lt H$, $H$ はフィルタの縦及び横のサイズ(フィルタは正方形))\n", "\n", "↓" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$$\n", "u_{ij} = \\sum_{p=0}^{H-1}\\sum_{q=0}^{H-1} x_{i+p,j+q}h_{pq}\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### 6.3.2 畳込みの働き" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "《略》" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "※ 教科書 p.84 の 図6.4 参照。" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### 6.3.3 パディング" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**パディング**: \n", "+ 出力画像が元の画像サイズと同じになるように、上下左右に追加する「ふち」。\n", "+ 例:画像のサイズを $8 \\times 8$、フィルタのサイズを $3 \\times 3$ とする。 \n", " ⇒ 上下左右に 1px 分の「ふち」をつければ、出力サイズが $8 \\times 8$ となる。\n", "+ 追加した「ふち」の画素値は $0$ にする(**ゼロパディング**)のが一般的。\n", " + 出力画像のふちの付近が「暗く」なる傾向が出てしまう問題あり。" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "参考:**パディングなし**の場合 \n", "+ 出力画像の縦および横のサイズが少しだけ小さくなる。\n", " + 例:画像を $8 \\times 8$、フィルタを $3 \\times 3$ とすると、出力は $6 \\times 6$ になる。\n", "+ ただし、元のデータのみを利用するので、画像の劣化が少なくなる。" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### 6.3.4 ストライド" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**ストライド**:\n", "\n", "+ ずらすサイズ $s$。\n", "+ 出力サイズは(入力サイズの)約 $1/s$ となる。\n", " + 畳み込み層では通常、ストライドは $(1, 1)$ (大きくすると特徴を取りこぼす)\n", " + プーリング層では $(2, 2)$ 以上を指定することが一般的" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.4 畳込み層" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "+ 入力サイズ: $W \\times W \\times K$\n", " + $W$:画像(または前層の出力マップの各チャネル)の縦(および横)のサイズ\n", " + $K$:前層の出力チャネル数(前が入力画像の場合、$K=1$(グレースケール)または $K=3$(RGB画像)など)\n", "+ フィルタサイズ: $H \\times H \\times K \\times M$\n", " + $H$:1つのフィルタの縦(および横)のサイズ\n", " + $K$:入力サイズの $K$ に一致(=チャネル数)\n", " + $M$:フィルタの数\n", "+ ストライド:通常 $(1, 1)$\n", "+ パディング:あり(=出力の(縦および横の)サイズが入力サイズに一致)とすることが多い\n", "+ 出力サイズ: $W \\times W \\times M$ (ストライド・パディングが↑の通りである場合)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "+ $z^{(l-1)}_{ijk}$: 前層(または入力画像)の $k$ チャネルの $(i, j)$ 画素値($0 \\le i, j \\lt W$、$0 \\le k \\lt K$)\n", "+ $h_{pqkm}$: $m$番目 のフィルタの $k$ チャネルの $(p, q)$ 画素値($0 \\le p, q \\lt H$, $0 \\le m \\lt M$)\n", "+ $b_{ijm}$: $m$番目 のフィルタのバイアス($b_{ijm} = b_m$ とすることが多い)\n", "+ $f$: 活性化関数\n", "\n", "↓" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$$\n", "\\begin{eqnarray*}\n", "u_{ijm} &=& \\sum_{k=0}^{K-1}\\sum_{p=0}^{H-1}\\sum_{q=0}^{H-1} z^{(l-1)}_{i+p,j+q,k}h_{pqkm} + b_{ijm}\\\\\n", "z^{(l)}_{ijm} &=& f(u_{ijm})\n", "\\end{eqnarray*}\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "※ この $h_{pqkm}$ が、通常の(全結合型の)ニューラルネットの「重み」に相当。 \n", "※ (この層においては)学習するということは、$h_{pqkm}$ および $b_{ijm} (= b_m)$ を最適化すること。" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "TensorFlow で書くと、こんな感じ(コードの一部):" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# z1: shape が [*, W, W, K] の4次元 tensor\n", "# weight_variable(): 指定したサイズの「重み」を定義する関数\n", "# bias_variable(): 指定したサイズの「バイアス」を定義する関数\n", "# f(): 活性化関数\n", "\n", "h1 = weight_variable([H, H, K, M])\n", "b1 = bias_variable([M])\n", "\n", "u2 = tf.nn.conv2d(z1, h1, strides=[1, 1, 1, 1], padding='SAME') + b1\n", "z2 = f(u2)\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "※ `strides=[X, w, h, X]` のうち、重要なのは真ん中の2つ(`w`, `h`)。この2つがストライドの「ずらすサイズ」。 \n", "※ `padding='SAME'` は、「パディングあり(出力サイズが入力と同じ)」の意味。パディングなしにするには `padding='VALID'` と指定する。" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.5 プーリング層" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "+ 畳み込み層:\n", " + フィルタによりパターン認識・抽出を行う\n", " + 位置のずれに鈍感(少しでもずれると別のパターンと認識してしまう)\n", "+ **プーリング層**:\n", " + 畳み込み層の位置感度を若干低下させ、ずれを吸収する(複雑型細胞のモデル)\n", " + 重み(パラメータ)は固定(=学習の対象外)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "+ 入力サイズ: $W \\times W \\times K$\n", " + $W$:縦(および横)のサイズ\n", " + $K$:チャネル数\n", "+ プーリングサイズ: $H \\times H$\n", " + $H$:正方形領域の一辺のサイズ\n", "+ ストライド:$(s, s)$ ただし $1 \\le s \\le H$($s \\ge 2$ とするのが普通)\n", "+ パディング:あり(=出力の(縦および横の)サイズが入力サイズの $1/H$)とすることが多い\n", "+ 出力サイズ:だいたい $(W/s) \\times (W/s) \\times K$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**最大プーリング**:\n", "$$\n", "u_{ijk} = \\max_{(p,q \\in P_{ij})} z_{pqk}\n", "$$\n", "\n", "**平均プーリング**:\n", "$$\n", "u_{ijk} = \\frac{1}{H^2} \\sum_{(p,q \\in P_{ij})} z_{pqk}\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "※ ただし \n", "\n", "+ $z_{pqk}$: 入力(前の層の出力)、$0 \\le p, q \\le W$、$0 \\le k \\lt K$\n", "+ $P_{ij}$: 入力(前の層の出力)のある $H \\times H$ サイズの部分領域(を表すインデックス)\n", "+ $u_{ijk}$: 出力\n", "\n", "※ プーリング層では通常、活性化関数を適用しない($z^{(l)}_{ijk} = u_{ijk}$)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "TensorFlow で書くと、こんな感じ(コードの一部):" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "# z1: shape が [*, W, W, K] の4次元 tensor\n", "\n", "# 最大プーリング\n", "z2 = tf.nn.max_pool(x, ksize=[1, H, H, 1], strides=[1, s, s, 1], padding='SAME')\n", "\n", "# 平均プーリング\n", "z2 = tf.nn.avg_pool(x, ksize=[1, H, H, 1], strides=[1, s, s, 1], padding='SAME')\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.6 正規化層" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "おさらい([3.6.1](http://antimon2.github.io/MLNGY_201604/slides/Chapter3_StochasticGradientDescent.slides.html#/7/1)):" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "> **正規化**(**normalization**)(もしくは**標準化**(**standardization**)): \n", "> データの平均を0に(および分散を1に)なるよう変換すること。\n", "> データに偏りがある場合に実行する(詳細略)。" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**正規化層**: \n", "正規化を入力データに対して行うのではなく、画像1枚1枚に対して行う。 \n", "プーリング層と同様、重み(パラメータ)は固定(=学習の対象外)。" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**局所反応正規化**: \n", "TensorFlow に用意されている、正規化層を形成する仕組み。 \n", "(この書籍で説明されている 局所コントラスト正規化 と少し違う。代わりに利用出来る) \n", "利用の仕方は次のような感じ(例):" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# z1: shape が [*, W, W, K] の4次元 tensor\n", "\n", "# 局所反応正規化\n", "z2 = tf.nn.local_response_normalization(z1, 4, bias=1.0, alpha=1.0, beta=0.5)\n", "# z2 = tf.nn.lrn(z1, 4, bias=1.0, alpha=1.0, beta=0.5) # ←でもOK\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "※ MNIST(手書き数字認識)では普通利用しない(元々 0.0〜1.0 のグレースケールでデータのばらつきがないため不要)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "※ **6.6.1 局所コントラスト正規化**、**6.6.2 単一チャネル画像の正規化**、**6.6.3 多チャネル画像の正規化** は略" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.7 勾配の計算" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "《略》" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 6.8 実例" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "《略》" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "TensorFlow v0.8 (Python 3)", "language": "python", "name": "tensorflow08" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }