2017年度Deep Learning基礎講座_2_まとめ

  • 10
    いいね
  • 0
    コメント

AAI-2017

2017年度Deep Learning基礎講座(公開講座)の第2回のまとめ
(第1回は授業ガイダンスのためまとめはない)

第2回はnumpy,scikit-learn,matplotlibの基本的な使い方を教えた講座

演習システムiLect

講座で利用した演習システム
基本はjupyterの環境なので自分で用意できれば使わなくてもよさそう

講師

Yusuke Sugomori

github
Home Page
blog

100 numpy experiment

講座はnumpyなどを使うため授業についてこれるように用意されている練習問題100問

numpy

numpyのまとめ
個人的に知らなかったり忘れていたものだけ載せる

numpyのバージョンを表示

np.__version__
# >>1.11.3等

numpyのコンフィグを表示

np.show_config()
# >> いっぱい情報が出てくる

関数の情報を表示

np.info(np.add)
# > パラメータや戻り値や説明や使用例などが出力される

配列の初期化

スライス

np.arange(1, 2, 0.1) # start = 1, end = 2, slice = 0.1
# > [ 1.   1.1  1.2  1.3  1.4  1.5  1.6  1.7  1.8  1.9]

N等分

np.linspace(0, 2, 5)
# > [ 0.   0.5  1.   1.5  2. ]

配列の操作

スライス

a[start : end : slice]sliceを負にすると逆順で取得する

# 2行2列の配列

W = np.array([[1, 2], [3, 4]])

#> [[1 2]
#> [3 4]]



#行を逆順で取得
#列に関しては記載しない(省略記法)ので先頭から取得

W[::-1]

#>[[3 4]
#> [1 2]]



#列を逆順で取得
#行に関しては記載しない(省略記法)ので先頭から取得

W[:, ::-1]

#>[[2 1]
#> [4 3]]



#行も列も逆順で取得

W[::-1, ::-1]

#> [[4 3]
#> [2 1]]

色々なインデックスによる要素のアクセス法

#二次元配列を用意
x = np.arange(1, 9).reshape(2, 4)
# > [[1 2 3 4]
# > [5 6 7 8]]

#xの(0,0), (1,1), (0,2), (1,3)の要素を取得して新しい配列にする

#パターン1
p1 = x[[0, 1, 0, 1], [0, 1, 2, 3]]

#パターン2
p2 = np.array([x[0, 0], x[1, 1], x[0, 2], x[1, 3]])

#パターン3
a = np.array([0,1,0,1])
b = np.array([0,1,2,3])
p3 = x[a,b]

#p1,p2,p3共に
# > [1 6 3 8]

条件がTrueの要素だけ選び出す

#配列を用意
x = np.arange(50, 60)
# > [50 51 52 53 54 55 56 57 58 59]

#index用の配列を用意 偶数indexだけTrue
indexes = np.arange(10)%2==0
# > [ True False  True False  True False  True False  True False]

x[indexes]
# > [50, 52, 54, 56, 58]

集約関数のaxis

sumなどの集約関数でaxisを指定すると行ごと、列ごとなどで集約できる

# 2行2列の配列

W = np.array([[1, 2], [3, 4]])

#> [[1 2]
#> [3 4]]



#普通に全てを合計
#2種類の書き方を記す

W.sum()
np.sum(W)

#> 10



#列方向に足す

W.sum(axis=0)
np.sum(W,axis=0)

#> [4 6]



#行方向に足す

W.sum(axis=1)
np.sum(W,axis=1)

#> [3 7]

ノルム

# 配列を用意
x = np.array([7, 8, 9])
# > [7,8,9]


# (|7|^1+|8|^1+|9|^1)^(1/1)
n = np.linalg.norm(x, ord=1)
# > 24


# (|7|^2+|8|^2+|9|^2)^(1/2)
n = np.linalg.norm(x, ord=2)
# > 13.9283882772



# (|7|^3+|8|^3+|9|^3)^(1/3)
n = np.linalg.norm(x, ord=3)
# > 11.6569533665

newaxis

次元を追加する

# 配列を用意
x = np.array([7, 8, 9])
# > [1 2 3]

x2 = x[np.newaxis,:]
# > [[1,2,3]]

x3 = x[:,np.newaxis]
# > [[1]
# > [2]
# > [3]]

行列積

# 行列を用意
W = np.array([[1, 2, 3], [4, 5, 6]])
x = np.array([7, 8, 9])

#行列積
y1 = np.matmul(W, x)
y2 = np.dot(W, x)

#y1, y2ともに
# > [ 50 122]

テンソル積

このあたりからついていけなくなった
テンソル積自体知らなかったのでこのあたりで勉強
numpyやchainerでのベクトル、行列、テンソルの積関連演算まとめ
もういちどだけ内積・外積

# 行列を用意
x = np.arange(8).reshape(2,2,2)
# >[[[0 1]
# > [2 3]]
# > [[4 5]
# > [6 7]]]

a1 = np.tensordot(x, x, axes=2)
# > [[28 34]
# > [76 98]]

a2 = np.tensordot(x, x, axes=1)
# > [[[[ 4  5]
# >    [ 6  7]]
# > 
# >   [[12 17]
# >    [22 27]]]
# > 
# >  [[[20 29]
# >    [38 47]]
# > 
# >   [[28 41]
# >    [54 67]]]]

アインシュタインの縮約規則

テンソル積一般を表現できる
3つ以上のテンソル間の演算も一度に実現可能

積和の式が与えられた時のeinsumの表現は一般に次のようにして得る

(例:$c_{ik} = \sum_{j} a_{ij}\times b_{jk}$)

  1. 変数名を消す(例:$ik = \sum_{j} ij \times jk$)
  2. 積($\times$)をカンマで置き換える(例:$ik = \sum_{j} ij, jk$)
  3. シグマを消す(例:$ik = ij, jk$)
  4. 左辺右辺を反転させ、等号を->にする(例:$ij, jk -> ik$)

(例)

np.einsum('ij,jk->ik', A, B):行列積$\sum_{j} a_{ij}b_{jk}$

np.einsum('i,i->', v, u):ベクトルの内積$\sum_{i} v_{i}u_{i}$

#行列を用意

A = np.arange(25).reshape(5,5)
# > [[ 0  1  2  3  4]
# > [ 5  6  7  8  9]
# >  [10 11 12 13 14]
# >  [15 16 17 18 19]
# >  [20 21 22 23 24]]

b = np.arange(5)
# > [0 1 2 3 4]

b2 = np.arange(5) + 1
# > [1 2 3 4 5]



# トレース(対角成分の和)

tr1 = np.einsum('ii', A))
tr2 = np.trace(A)
tr3 = A.trace()

#tr1,tr2,tr3共に
# > 60



# 転置

t1 = np.einsum('ji', A))
t2 = A.T

#t1,t2共に
# > [[ 0,  5, 10, 15, 20],
# >        [ 1,  6, 11, 16, 21],
# >        [ 2,  7, 12, 17, 22],
# >        [ 3,  8, 13, 18, 23],
# >        [ 4,  9, 14, 19, 24]]



# 内積

in1 = np.einsum('i,i', b, b2))
in2 = np.inner(b, b2)

#in1,in2共に
# > 40



# 対角成分

di1 = np.einsum('ii->i', A))
di2 = np.diag(A)

# di1,di2共に
# > [ 0  6 12 18 24]



# 軸指定和

s1 = np.einsum('ij->j', A))
s2 = np.sum(A, axis=0)

#s1,s2共に
# > [50 55 60 65 70]



# 行列ベクトル積
mat1 = np.einsum('ij,j->i', A, b))
mat2 = np.matmul(A, b)

#mat1,mat2共に
# > [ 30  80 130 180 230]


# outer product(直積。クロス積ではない)
outer1 = np.einsum('i,j->ij', b, b2))
outer2 = np.outer(b, b2)

#outer1,outer2共に
# > [[ 0  0  0  0  0]
# >  [ 1  2  3  4  5]
# >  [ 2  4  6  8 10]
# >  [ 3  6  9 12 15]
# >  [ 4  8 12 16 20]]



# 行列積(matmul)
#新しい行列を用意

a1 = np.arange(6).reshape((3,2))
# > [[0 1]
# >  [2 3]
# >  [4 5]]

a2 = np.arange(12).reshape((4,3))
# > [[ 0  1  2]
# > [ 3  4  5]
# > [ 6  7  8]
# > [ 9 10 11]]

matm1 = np.einsum('ij,ki->jk', a1, a2))
matm2 = np.matmul(a1.T, a2.T))

#matm1,matm2共に
# > [[10 28 46 64]
# > [13 40 67 94]]



# テンソル積(tensordot)
#新しい行列を用意

b1 = np.arange(18).reshape(2,3,3)
# > [[[ 0  1  2]
# >   [ 3  4  5]
# >   [ 6  7  8]]
# > 
# >  [[ 9 10 11]
# >   [12 13 14]
# >   [15 16 17]]]

b2 = np.arange(36).reshape(3,3,4)
# > [[[ 0  1  2  3]
# >   [ 4  5  6  7]
# >   [ 8  9 10 11]]
# > 
# >  [[12 13 14 15]
# >   [16 17 18 19]
# >   [20 21 22 23]]
# > 
# >  [[24 25 26 27]
# >   [28 29 30 31]
# >   [32 33 34 35]]]

ten1 = np.einsum('ijk,jkl->il', b1, b2))
ten2 = np.tensordot(b1, b2)

#ten1,ten2共に
# > [[ 816  852  888  924]
# >  [2112 2229 2346 2463]]

問題 1

講義中に出た問題。解答は後述

1-1.

x = np.array([7, 8, 9])
W = np.array([[1, 2, 3], [4, 5, 6]])

と同様の x, W を得るように np.arange を用いてコードを書いてください。

1-2.

以下のような表式を得るように W を変形してください。

[[ 1.  0. -1.]
[ 4.  3.  2.]]

ヒント: 縦の差は3,横の差は-1

1-3.

エディントンのイプシロン
「エディントンのイプシロン」を用いてベクトルの外積(クロス積)を実装してください。

matplotlib

あとで追記...

scikit-learn(sklearn)

pythonの機械学習ライブラリ
深層学習についてはサポートされていないので便利機能を中心に利用する

shuffle

numpy配列の要素の順番をランダムに入れ替える

import numpy as np
from sklearn.utils import shuffle

#seedを設定しないでシャッフル
np.random.seed()

sh1 = shuffle(range(10))
# 実行のたびに変わる
# > [5, 6, 2, 8, 4, 1, 0, 3, 7, 9]

sh2 = shuffle(range(10))
# 実行のたびに変わる
# > [1, 9, 0, 4, 7, 5, 6, 8, 3, 2]

#seedを設定してシャッフル
#1回目
np.random.seed(12345)
x1 = shuffle(range(10))
y1 = shuffle(range(10))
#2回目 
np.random.seed(12345)
x2 = shuffle(range(10))
y2 = shuffle(range(10))

#x1,x2共に
# > [0, 7, 3, 9, 6, 4, 1, 8, 5, 2]
#y1,y2共に
# > [4, 0, 9, 5, 7, 3, 8, 6, 1, 2]


#RandomStateによるseedのカプセル化

#rng0とrng1を設定して2回実行
rng0 = np.random.RandomState(12345)
rng1 = np.random.RandomState(34567)

rng0_0_0 = shuffle(range(10), random_state=rng0)
rng1_0_0 = shuffle(range(10), random_state=rng1)
rng0_1_0 = shuffle(range(10), random_state=rng0)
rng1_0_0 = shuffle(range(10), random_state=rng1)

#rng0とrng1を設定して実行順序を変えて2回実行
rng0 = np.random.RandomState(12345)
rng1 = np.random.RandomState(34567)

rng1_0_1 = shuffle(range(10), random_state=rng1)
rng1_1_1 = shuffle(range(10), random_state=rng1)
rng0_0_0 = shuffle(range(10), random_state=rng0)
rng0_0_1 = shuffle(range(10), random_state=rng0)

#rng0_0_0とrng0_0_1が共に
# > [0, 7, 3, 9, 6, 4, 1, 8, 5, 2]
#rng0_1_0とrng0_1_1が共に
# > [4, 0, 9, 5, 7, 3, 8, 6, 1, 2]
#rng1_0_0とrng1_0_1が共に
# > [3, 0, 5, 1, 7, 8, 4, 9, 6, 2]
#rng1_1_0とrng1_1_1が共に
# > [9, 7, 4, 1, 6, 5, 2, 0, 8, 3]

train_test_split

読み込んだデータから得られた配列等を、学習しやすいように学習データとテストデータに分けてくれる

from sklearn.model_selection import train_test_split
import string

#string.ascii_uppercaseで'ABCDEFGHIJKLMNOPQRSTUVWXYZ'の配列を得る
lettersAtoE = string.ascii_uppercase[:5]
# > 'ABCDE'

#入力をいい感じに分けてくれる その時のインデックスも配列として得られる
train0to4, test0to4, trainAtoE, testAtoE = train_test_split(range(5), lettersAtoE)

#train0to4 学習データのindex
# > [3, 1, 2]
#trainAtoE 学習データ
# > ['D', 'B', 'C']
#test0to4 テストデータのindex
# > [4, 0]
#test0to4 テストデータ
# > ['E', 'A']

fetch_mldata

mldata.orgから学習データを取得する

from sklearn.datasets import fetch_mldata

# MNIST originalデータを読み込む、存在しなければネットからダウンロードする
mnist = fetch_mldata('MNIST original')

# mnist.dataにはたくさんの画像データ(手書き数字)がある
#画像サイズを表示
print(mnist.data.shape)
# > (70000, 784) 28*28=784の画像が70000枚
#画像のラベルを表示
print(set(mnist.target))
# > {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0} 0~9の手書き数字

#画像を表示
plt.imshow(mnist.data[0].reshape(28, 28), cmap='gray', interpolation='none')
plt.show()
# > 28*28の画像にしてgrayscaleで表示

機械学習のサンプル

# Select one of Classifeir (LinearSVC, KNeighbor, SDG) using validation set
# and test best set

from sklearn.svm import LinearSVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import SGDClassifier

from sklearn.metrics import accuracy_score

mnist = fetch_mldata('MNIST original')
M = len(mnist.data)
N = 2000  # Use part of MNIST data to save computation time
# randomly select N numbers from 0 to M
selected = shuffle(range(M))[:N]

# Split data into Train, Valid, Test
train_valid_X, test_X, train_valid_y, test_y =\
    train_test_split(mnist.data[selected], mnist.target[selected])
train_X, valid_X, train_y, valid_y =\
    train_test_split(train_valid_X, train_valid_y)

classifiers = [LinearSVC(), KNeighborsClassifier(), SGDClassifier()]

# Train each classifier with Train set
accs = []
for clf_type, classifier in enumerate(classifiers):
    classifier.fit(train_X, train_y)
    pred_train = classifier.predict(train_X)
    acc_train = accuracy_score(train_y, pred_train)
    pred_valid = classifier.predict(valid_X)
    acc_valid = accuracy_score(valid_y, pred_valid)
    print("classifier type: %d, Train Accuracy: %f, Validation Accuracy %f" \
        % (clf_type, acc_train, acc_valid))
    accs.append(acc_valid)

# Chose best classifier with the highest validation accuracy
i_clf_best = np.argmax(accs)
print("Best Classifier: %d" % i_clf_best)
clf_best = classifiers[i_clf_best]

# Test selected classifier
pred = clf_best.predict(test_X)
acc = accuracy_score(test_y, pred)
print("Test(Best Classifier): %f" % acc)

collections

あとで追記

問題 2

講義中に出た問題。解答は後述

2-1. mnist.data には画像は何枚あるか

2-2. 画像データはどのようなグレースケールで表されているか

2-3. 4枚の数字を 縦2 $\times$ 横2 で表示する

2-4. mnist にはどの数字がどれだけ入っているか

問題の解答

1-1

x = np.arange(7,10)
W = np.arange(1,7).reshape(2,3)

1-2

np.arange(-1,5).reshape(2,3)[::,::-1]

1-3

def my_cross(u, v):
    eps = np.zeros((3, 3, 3))
    eps[0, 1, 2] = eps[1, 2, 0] = eps[2, 0, 1] = 1
    eps[0, 2, 1] = eps[2, 1, 0] = eps[1, 0, 2] = -1
    return np.einsum('ijk,j,k->i', eps, u, v)

#確認
u = np.array([2,3,4])
v = np.array([1,2,5])
print(my_cross(u, v))
# > [ 7. -6.  1.]
print(np.cross(u, v))
# > [ 7 -6  1]

2-1

import sklearn
mnist = sklearn.datasets.fetch_mldata('MNIST original')

print(len(mnist.data))
# > 7000

2-2

あとで追記...

2-3

あとで追記...

2-4

あとで追記...