kaeken(嘉永島健司)のTech探究ブログ

主に情報科学/情報技術全般に関する知見をポストします。(最近は、特にData Science、機械学習、深層学習、統計学、Python、数学、ビッグデータ)

3章ニューラルネットワーク(ステップ関数・シグモイド関数・ReLU関数)『ゼロから作るディープラーニング』

3章になって結構重くなってきたので、ゆっくりやっていく。

・活性化関数activation function:入力信号の総和を出力信号に変換する関数
・ステップ関数(階段関数):閾値を境にして出力が切り替わる関数
・パーセプトロンでは、ステップ関数を使っている

def step_function(x):
  if x > 0:
    return 1
  else:
    return 0

#配列引数対応版
def step_function(x):
  y = x > 0 # 配列要素に対して不等号の演算をしてTrue/Falseのbool値を返す
  return y.astype(np.int) # boolからintに型変換

def step_function(x):
  return np.array(x > 0, dtype=np.int) # 圧縮記述

以下、生成されたステップ関数グラフ例

import numpy as np
import matplotlib.pyplot as plt
plt.switch_backend('agg')

def step_func(x):
  return np.array(x > 0, dtype=np.int)

x = np.arange(-5.0, 5.0, 0.1)
y = step_func(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)

plt.savefig('step_func.png')

f:id:kaeken:20161103223008p:plain

ニューラルネットワークについて。

・ニューラルネットワーク(多層パーセプトロン)では、活性化関数として、ステップ関数とは別の関数を使用する
・よく使われる関数はシグモイド関数sigmoid functionである。シグモイド関数は、
 ネイピア数の2.7182...の実装を表す e の-x乗に1を加えた式の逆数である(ネイピア数をあとで調べる?)

def sigmoid(x):
  return 1 / (1 + np.exp(-x))

import numpy as np
import matplotlib.pyplot as plt
plt.switch_backend('agg')

def sigmoid(x):
  return 1 / (1 + np.exp(-x))

x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)

plt.savefig('sigmoid.png')

f:id:kaeken:20161103223450p:plain

ステップ関数とシグモイド関数の比較

・下記合成した図を確認すると、「滑らかさ」が異なることが重要
・ステップは0/1の離散だが、シグモイドは連続的な実数値
・共通点は、入力が小さい時は0に近く、大きくなるに従い1に近づき、常に0から1の間にある非線形関数

f:id:kaeken:20161103225819p:plain

xの範囲を10倍した場合 f:id:kaeken:20161103225848p:plain

・最近はシグモイド関数の代わりにReLU関数(Rectified Linear Unit)が使われている
・ReLUは、入力が0を超えていればその入力をそのまま出力し、0以下なら0を出力する関数

def relu(x):
  return np.maximum(0, x)

x = np.arange(-5.0, 5.0, 0.1)
y = relu(x)
plt.plot(x, y)
plt.ylim(-1,)

plt.savefig('relu.png')

f:id:kaeken:20161103232333p:plain

いったんここまで。

ゼロから作るDeep Learningで気になる用語

1章 Python入門
ベクトルvector:1次元配列
行列matrix:2次元配列
テンソルtensor:ベクトルや行列を一般化したもの
ブロードキャストbroadcast:形状の異なる配列同士の演算時に要素が拡大されて演算される機能

2章パーセプトロン
パーセプトロンperceptron:複数の信号を入力とし、ひとつの信号を出力とするアルゴリズム
閾値threshold:重み付けされた入力値の総和が超えた場合に発火する限界値のこと。ニューロンが発火する値
バイアスbias:発火のしやすさを調整するパラメータ
重みweight:入力への重要度をコントロールするパラメータ

読み進めていきながら、順次更新していく。

Pythonでパーセプトロンperceptron関数

『ゼロから作るDeep Learning』(以下、『ゼロからDL』) 2章パーセプトロンのAND,OR,NANDは重みとバイアス値だけが異なる。

パーセプトロンとは、
複数の信号を入力として受け取り、一つの信号を出力する処理。
信号は、「流す:1」「流さない:0」の2値のみ。

今後、
ニューラルネットワークや
ディープラーニングへと進む上で必要な考え方。
# cat and.py

import numpy as np

# 重みとバイアスを用いたANDゲート
def AND(x1, x2):
  x = np.array([x1, x2]) #入力
  w = np.array([0.5, 0.5]) #重みは入力への重要度をコントロールするパラメータ
  b = -0.7 #バイアスは発火のしやすさを調整するパラメータ
  tmp = np.sum(w*x) + b #重み付き入力の和とバイアスの合計
  if tmp <= 0:
    return 0
  else:
    return 1

print(AND(0,0), AND(0,1), AND(1,0), AND(1,1))


# cat nand.py
import numpy as np

# 重みとバイアスを用いたNANDゲート
def NAND(x1, x2):
  x = np.array([x1, x2]) #入力
  w = np.array([-0.5, -0.5]) #重みとバイアスだけ違う
  b = 0.7
  tmp = np.sum(w*x) + b #重み付き入力の和とバイアスの合計
  if tmp <= 0:
    return 0
  else:
    return 1

print(NAND(0,0), NAND(0,1), NAND(1,0), NAND(1,1))

# cat or.py
import numpy as np

# 重みとバイアスを用いたORゲート
def OR(x1, x2):
  x = np.array([x1, x2]) #入力
  w = np.array([0.5, 0.5]) #重みとバイアスだけ違う
  b = -0.2
  tmp = np.sum(w*x) + b #重み付き入力の和とバイアスの合計
  if tmp <= 0:
    return 0
  else:
    return 1

print(OR(0,0), OR(0,1), OR(1,0), OR(1,1))

実行結果 (.bashrcでalias py='python'にしてる)

py and.py
0 0 0 1
py nand.py
1 1 1 0
py or.py
0 1 1 1

ついでにNOR

# cat nor.py
import numpy as np

# 重みとバイアスを用いたNORゲート
def NOR(x1, x2):
  x = np.array([x1, x2]) #入力
  w = np.array([-0.5, -0.5]) #重みとバイアスだけ違う
  b = 0.2
  tmp = np.sum(w*x) + b #重み付き入力の和とバイアスの合計
  if tmp <= 0:
    return 0
  else:
    return 1

print(NOR(0,0), NOR(0,1), NOR(1,0), NOR(1,1))

→1 0 0 0 になった。

単体のパーセプトロンには限界があり、
排他的論理和XORゲートを実装するには、
複数のゲートを組み合わせて
多層パーセプトロンにする必要がある。

結論から言えば、
NANDとORを
ANDでつなぐ
# cat xor.py
import numpy as np

def AND(x1, x2):
  x = np.array([x1, x2])
  w = np.array([0.5, 0.5])
  b = -0.7
  tmp = np.sum(w*x) + b
  if tmp <= 0:
    return 0
  else:
    return 1

def NAND(x1, x2):
  x = np.array([x1, x2])
  w = np.array([-0.5, -0.5])
  b = 0.7
  tmp = np.sum(w*x) + b
  if tmp <= 0:
    return 0
  else:
    return 1

def OR(x1, x2):
  x = np.array([x1, x2])
  w = np.array([0.5, 0.5])
  b = -0.2
  tmp = np.sum(w*x) + b
  if tmp <= 0:
    return 0
  else:
    return 1

def XOR(x1, x2):
  s1 = NAND(x1, x2)
  s2 = OR(x1, x2)
  y = AND(s1, s2)
  return y

print(XOR(0,0), XOR(0,1), XOR(1,0), XOR(1,1))
#=> 0 1 1 0 排他的論理和になった

Python×数学×人工知能を平行して勉強していく

機械学習や深層学習など人工知能の技術は数学が必須だ。
ライブラリが細かい計算を隠蔽してくれるとはいえ、
「何のためにこの数式を使うか」を理解していないと、
使い方を間違えるし、変更することもできない。

数学は遠い昔にやったが忘れているので、
復習&新規分野を学習していく。

とはいえ、鉛筆を使って勉強するのもだるいので、
ここはプログラマらしくプログラミングしながら学ぶ。
以下、オライリーの既刊本からピックアップして、
人工知能プログラミングと平行してやっていこう。

また、
Pythonは書いていくうちに、
手に馴染んでくる。
Rubyほどの衝撃はないが、
確かに書きやすい言語みたいだ。

Python
数学
人工知能

三本柱で集中的に取り組んでいく。

http://www.oreilly.co.jp/catalog/

www.oreilly.co.jp www.oreilly.co.jp www.oreilly.co.jp www.oreilly.co.jp www.oreilly.co.jpwww.oreilly.co.jp

次にグラフ描画用にmatplotlib.pyplotモジュール

いきなりエラッタのでyum

>>> import matplotlib.pyplot as plt
...
ImportError: libXext.so.6: cannot open shared object file: No such file or directory
yum install libXext.x86_64
yum install libSM.x86_64
yum install libXrender.x86_64

気を取り直して、importしたら成功したがplotでXの指定がないのでコケた

>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> x = np.arange(0,6, 0.1)
>>> y = np.sin(x)
>>> plt.plot(x,y)
...
    raise RuntimeError('Invalid DISPLAY variable')
RuntimeError: Invalid DISPLAY variable


#以下をimport後に指定すればよいらしい
>>> plt.switch_backend('agg')
#すると
>>> plt.plot(x,y)
>>> plt.savefig('sin.png')
# これで画像が生成された

f:id:kaeken:20161103004351p:plain

さすがに対話モードは面倒なのでファイルに変更

import numpy as np
import matplotlib.pyplot as plt
plt.switch_backend('agg')

x = np.arange(0, 6, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, label='sin')
plt.plot(x, y2, linestyle = '--', label='cos')
plt.xlabel('x')
plt.ylabel('y')
plt.title('sin & cos')
plt.legend()


plt.savefig('sin_cos.png')

sinとcos f:id:kaeken:20161103005056p:plain

あと画像読込もできるとのこと(未確認)

import matplotlib.pyplot as plt
from matplotlib.image import imread

img = imread('lena.png')
plt.imshow(img)

plt.show()

まずはNumPy配列操作

『ゼロから作るDeep Learning』でディープラーニングに必要な行列処理をPythonでやるための準備。まずは、NumPyで配列操作を学ぶ。

>>> import numpy as np
>>> x = np.array([1.0, 2.0, 3.0])
>>> x
array([ 1.,  2.,  3.])
>>> type(x)
<class 'numpy.ndarray'>
>>> y = np.array([2.0, 4.0, 6.0])
>>> x+y
array([ 3.,  6.,  9.])
>>> x*y
array([  2.,   8.,  18.])
>>> x/y
array([ 0.5,  0.5,  0.5])


>>> x
array([ 1.,  2.,  3.])
>>> x/2 #ブロードキャスト機能
array([ 0.5,  1. ,  1.5])

# N次元配列
>>> A = np.array([[1,2], [3,4]])
>>> A
array([[1, 2],
       [3, 4]])
>>> A.shape
(2, 2)
>>> A.dtype
dtype('int64')

>>> A
array([[1, 2],
       [3, 4]])
>>> B = np.array([[3,0],[0,6]])
>>> B
array([[3, 0],
       [0, 6]])
>>> A+B
array([[ 4,  2],
       [ 3, 10]])
>>> A*B
array([[ 3,  0],
       [ 0, 24]])


>>> A
array([[1, 2],
       [3, 4]])
>>> A*10
array([[10, 20],
       [30, 40]])
>>> C = np.array([10,20])
>>> A*C
array([[10, 40],
       [30, 80]])

>>> X = np.array([[51,55],[14,19],[0,4]])
>>> X
array([[51, 55],
       [14, 19],
       [ 0,  4]])
>>> X[0]
array([51, 55])
>>> X[0][1]
55
>>> for row in X:
...   print(row*2)
...
[102 110]
[28 38]
[0 8]

>>> x = X.flatten()
>>> x
array([51, 55, 14, 19,  0,  4])
>>> x[np.array([0,2,4])]
array([51, 14,  0])
>>> x > 15
array([ True,  True, False,  True, False, False], dtype=bool)
>>> x[x>15]
array([51, 55, 19])
# この不等号が使える文法は特徴的


printとかarrayとか もっと短くしたいが あまり言語文法を弄っても仕方がないので、 甘受しよう。

さくらVPS CentOS7にPython3を入れる&ディープラーニング実装環境準備

さくらVPS CentOS7にPython3を入れる

# yum install gcc zlib-devel bzip2 bzip2-devel readline readline-devel sqlite sqlite-devel openssl openssl-devel git
# git clone https://github.com/yyuu/pyenv.git ~/.pyenv

# vim .bash_profile
下記を追記
# pyenv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

# source .bash_profile

# pyenv install --list

# pyenv install 3.5.1

# pyenv global 3.5.1
# pyenv rehash
# python --version
Python 3.5.1

追記:

pyenvで生pythonを入れたが、 分析環境はAnacondaが良いとのことなので、 以下を参考に入れ直し。

データサイエンティストを目指す人のpython環境構築 2016 - Qiita

pyenv install anaconda3-4.1.1

続いて『ゼロから作るDeep Learning』本を参考に、ライブラリ準備

>>>import numpy as np
>>> np.random.rand(100)
array([ 0.86892336,  0.66170946,  0.05887993,  0.42099383,  0.80438276,
        0.19044123,  0.23335116,  0.31559316,  0.88670526,  0.82667895,
        0.79776356,  0.80881683,  0.99474501,  0.05019365,  0.19625688,
        0.86203096,  0.29162751,  0.72087276,  0.40451478,  0.36296256,
        0.89809188,  0.46221825,  0.5993458 ,  0.0626044 ,  0.68405878,
        0.01012476,  0.83778932,  0.56676707,  0.18140237,  0.97366154,
        0.49387919,  0.57424144,  0.44275469,  0.14197617,  0.04196403,
        0.9784503 ,  0.59244845,  0.09614099,  0.58814902,  0.18990487,
        0.62918135,  0.33347414,  0.86367738,  0.89845232,  0.13748251,
        0.03077333,  0.08952327,  0.95140962,  0.76248493,  0.37645204,
        0.59090669,  0.33756122,  0.94142886,  0.37007636,  0.35679969,
        0.50614196,  0.20450811,  0.94660012,  0.95909313,  0.84177225,
        0.79149603,  0.5654826 ,  0.38281388,  0.70233475,  0.34317186,
        0.40587616,  0.50553225,  0.60524493,  0.08440945,  0.74772122,
        0.9691486 ,  0.00477779,  0.8752755 ,  0.33538002,  0.73304029,
        0.12212355,  0.47077921,  0.92045206,  0.52865073,  0.2070013 ,
        0.72662729,  0.0087631 ,  0.26692977,  0.63211109,  0.56244538,
        0.51641049,  0.67545334,  0.79915446,  0.28771985,  0.34116686,
        0.24343494,  0.18029586,  0.98822042,  0.10098339,  0.75538892,
        0.60376798,  0.03763307,  0.09447491,  0.24395278,  0.81511218])

Python3系の最速文法メモは以下。

qiita.com

『ゼロから作るDeepLearning』入手

人工知能関連の記事を書いていく。

 

まず、まったく何から初めてよいのか分からないが、

ひとまずオライリーで入門書を探す。

『ゼロから作るDeepLearning』という書籍が良さそうなので買ってきた。

 

www.oreilly.co.jp

目次

1章 Python入門
1.1 Pythonとは
1.2 Pythonのインストール
1.3 Pythonインタプリタ
1.4 Pythonスクリプトファイル
1.5 NumPy
1.6 Matplotlib
1.7 まとめ

2章 パーセプトロン
2.1 パーセプトロンとは
2.2 単純な論理回路
2.3 パーセプトロンの実装
2.4 パーセプトロンの限界
2.5 多層パーセプトロン
2.6 NANDからコンピュータへ
2.7 まとめ

3章 ニューラルネットワーク
3.1 パーセプトロンからニューラルネットワーク
3.2 活性化関数
3.3 多次元配列の計算
3.4 3層ニューラルネットワークの実装
3.5 出力層の設計
3.6 手書き数字認識
3.7 まとめ

4章 ニューラルネットワークの学習
4.1 データから学習する
4.2 損失関数
4.3 数値微分
4.4 勾配
4.5 学習アルゴリズムの実装
4.6 まとめ

5章 誤差逆伝播
5.1 計算グラフ
5.2 連鎖率
5.3 逆伝播
5.4 単純なレイヤの実装
5.5 活性化関数レイヤの実装
5.6 A.ne/Softmaxレイヤの実装
5.7 誤差逆伝播法の実装
5.8 まとめ

6章 学習に関するテクニック
6.1 パラメータの更新
6.2 重みの初期値
6.3 Batch Normalization
6.4 正則化
6.5 ハイパーパラメータの検証
6.6 まとめ

7章 畳み込みニューラルネットワーク
7.1 全体の構造
7.2 畳み込み層
7.3 プーリング層
7.4 Convolution/Poolingレイヤの実装
7.5 CNNの実装
7.6 CNNの可視化
7.7 代表的なCNN
7.8 まとめ

8章 ディープラーニング
8.1 ネットワークをより深く
8.2 ディープラーニングの小歴史
8.3 ディープラーニングの高速化
8.4 ディープラーニングの実用例
8.5 ディープラーニングの未来
8.6 まとめ

 

 

サンプルコード

 

https://github.com/oreilly-japan/deep-learning-from-scratch

 

さっそく6章まで読んだが、

5章誤差逆伝播法から疑問点が増えてきた。

高校数学は理系できっちり学習したが、

忘れているようなので、復習が必要。

 

PHP,Rubyばかりで、

少し使っていたPython

本格的に取り組んでいきたい。