機械学習のお勉強(chainerでkaggleに初挑戦)
Kaggleとは
公式:Kaggle: Your Home for Data Science
Kaggleは企業や研究者がデータを投稿し、世界中の統計家やデータ分析家がその最適モデルを競い合う、予測モデリング及び分析手法関連プラットフォーム及びその運営会社である。
Kaggleを始めるのに参考になるサイト
Kaggle に Python で入門しました(Digit Recognizer) | Futurismo
Kaggle の Titanic チュートリアルに挑戦した話
Kaggleのtitanic問題で上位10%に入るまでのデータ解析と所感 - mirandora.commirandora.com
全体の流れ
Kaggle: Your Home for Data Science
アカウントを作る
トライするCompetitionを決める
Dataをダウンロードする
Dataを解析して、提出用csvファイルを作る
提出する
Digit Recognizerをやってみる(chainerを使用)
trainとtestのcsvファイルのダウンロード
chainer用のデータセットの作り方
とてもわかりやすい 👇
chainerのデータセットの作り方 LinearやCNN - Qiita
chainerの独自datasetの作り方 - 午睡二時四十分
ChainerのCNNにおけるデータセットの作り方 – ハックマン.com
Chainer: ビギナー向けチュートリアル Vol.1 - Qiita
chainerはtupleで[data,label]となるようにdatasetsを作ってから、学習を行う
Import
# -*- coding: utf-8 -*- import chainer import pandas as pd import chainer.functions as F import chainer.links as L from chainer import training from chainer.training import extensions import pandas as pd import numpy as np from chainer import datasets from chainer.datasets import tuple_dataset from chainer import serializers
kaggle dataをchainerデータセットに変換
train = pd.read_csv('./train.csv') test = pd.read_csv('./test.csv') features = train.ix[:,1:].values labels = train.ix[:,0] features = features.reshape(features.shape[0],28,28) imageData = [] labelData = [] for i in range(len(labels)): img = features[i] imgData = np.asarray(np.float32(img)/255.0) imgData = np.asarray([imgData]) imageData.append(imgData) labelData.append(np.int32(labels[i])) threshold = np.int32(len(imageData)/8*7) train = tuple_dataset.TupleDataset(imageData[0:threshold], labelData[0:threshold]) val = tuple_dataset.TupleDataset(imageData[threshold:], labelData[threshold:])
Trainerで学習
モデル
class CNN(chainer.Chain): def __init__(self, train=True): super(CNN, self).__init__( conv1=L.Convolution2D(1, 32, 5), conv2=L.Convolution2D(32, 64, 5), l1=L.Linear(1024, 10), ) self.train = train def __call__(self, x): h = F.max_pooling_2d(F.relu(self.conv1(x)), 2) h = F.max_pooling_2d(F.relu(self.conv2(h)), 2) return self.l1(h)
学習
model = L.Classifier(CNN()) optimizer = chainer.optimizers.Adam() optimizer.setup(model) train_iter = chainer.iterators.SerialIterator(train, batch_size=100) test_iter = chainer.iterators.SerialIterator(val, batch_size=100, repeat=False, shuffle=False) updater = training.StandardUpdater(train_iter, optimizer) trainer = training.Trainer(updater, (5, 'epoch'), out='result') trainer.extend(extensions.Evaluator(test_iter, model)) trainer.extend(extensions.LogReport()) trainer.extend(extensions.PrintReport( ['epoch', 'main/loss', 'validation/main/loss', 'main/accuracy','validation/main/accuracy'])) trainer.extend(extensions.ProgressBar()) trainer.run() serializers.save_npz("digit-learn5.data", model)
テストデータの準備
test = test.ix[:,:].values.astype('float32') test_data = test.reshape(test.shape[0],28,28) testData = [] for i in range(len(test_data)): img = test_data[i] imgData = np.asarray(np.float32(img)/255.0) imgData = np.asarray([imgData]) testData.append(imgData)
作成モデルでの予測
def predict(model, test): # テストデータ全部に対して予測を行う preds = [] for img in test: img = img.reshape(-1, 1, 28, 28) pred = F.softmax(model.predictor(img)).data.argmax() preds.append(pred) return preds predictions = predict(model, testData)
kaggle提出用フォーマットに変換
submissions = pd.DataFrame({"ImageId": list(range(1, len(predictions)+1)), "Label": predictions}) submissions.to_csv("digit_cnn_output.csv", index=False, header=True)
提出
ここのsubmit predictionsに上記でできたdigit_cnn_output.csvをアップロード
結果
527位 (/ 1661)
これからコツコツ学んだことを活かして、100位以内を目指してみる〜
コードも適当なので、もっと綺麗にかけるよう練習する
2017/10/11
331位
全体参考
nocotan.github.io 👈 最高にわかりやすい
GitHub - nocotan/chainer-examples: This is implementation examples by Chainer.
Chainer: ビギナー向けチュートリアル Vol.1 - Qiita
top2%の私が教えるKaggleの極意, Bosch Production Line Performance | RCO Ad-Tech Lab Blog
機械学習のお勉強(scikit-learnを使ってみる:分類問題)
教科書
Perceptron
実装
# -*- coding: utf-8 -* from sklearn import datasets import numpy as np # Added version check for recent scikit-learn 0.18 checks from distutils.version import LooseVersion as Version from sklearn import __version__ as sklearn_version if Version(sklearn_version) < '0.18': from sklearn.cross_validation import train_test_split else: from sklearn.model_selection import train_test_split # 正規化 from sklearn.preprocessing import StandardScaler # パーセプトロン from sklearn.linear_model import Perceptron from sklearn.metrics import accuracy_score # load data iris = datasets.load_iris() X = iris.data[:, [2, 3]] y = iris.target print('Class labels:', np.unique(y)) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=0) # 正規化 sc = StandardScaler() sc.fit(X_train) X_train_std = sc.transform(X_train) X_test_std = sc.transform(X_test) # Perceptron Fit ppn = Perceptron(n_iter=40, eta0=0.1, random_state=0) ppn.fit(X_train_std, y_train) # show accuracy y_pred = ppn.predict(X_test_std) print('Misclassified samples: %d' % (y_test != y_pred).sum()) print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))
大事なのは
# Perceptron Fit ppn = Perceptron(n_iter=40, eta0=0.1, random_state=0) ppn.fit(X_train_std, y_train)
結果
Misclassified samples: 4 Accuracy: 0.91
結果を可視化(コードは教科書Git参照) 👇
3クラス分類において、線形の決定境界で完全に区切ることができない
ロジスティック回帰
分類のためのモデルで、線形分類問題と2値分類問題に使用される
ロジスティック関数
起こりやすさを表すオッズ比(P =p/(1-p))の対数の逆関数
入力として実数を受け取り、[0,1]の範囲の値に変換する。出力はそのクラスに所属している確率と解釈できる。
例として、降水確率や病気の確率を出す際などに利用されている
コスト関数
J = cost func p = probability if y==0: J = -log(1-p) elis y==1: J = -log(p)
実装
上記パーセプトロンのPerceptron Fit以降を下のように書き換える
from sklearn.linear_model import LogisticRegression lr = LogisticRegression(C=1000.0, random_state=0) lr.fit(X_train_std, y_train) y_pred = lr.predict(X_test_std) print('Misclassified samples: %d' % (y_test != y_pred).sum()) print('Accuracy: %.2f' % accuracy_score(y_test, y_pred)) # output probability print lr.predict_proba(X_test_std[0,:])
結果
Misclassified samples: 1 Accuracy: 0.98 [[ 2.05743774e-11 6.31620264e-02 9.36837974e-01]]
パーセプトロンより向上している
lr = LogisticRegression(C=1000.0, random_state=0)
のCについて以下で説明する
L2正規化
極端なパラメータの重みにペナルティをかす。コスト関数に正規化の項を追加すればよい
+ lambda / 2 * w2 **をコスト関数に足すことで、さらには、lambdaを大きくすることで、重みを小さく保ちながら学習させることができる。
J = cost func p = probability w = weight if y==0: J = -log(1-p) + lambda / 2 * w**2 elis y==1: J = -log(p) + lambda / 2 * w**2
C = 1 / lambdaを表している。Cの値を減らすと重みが小さくなる。
正規化をするメリットは?
直感的には、正規化することによりニューラルネットワークがより小さな重みを好むようになります。 大きな重みが許されるのは、そうすることがコスト関数の第1項を余程大きく改善する場合だけです。 言い換えると、正規化とは重みを小さくすることと元のコスト関数を小さくすることの間でバランスを取る方法であると 見ることもできます。このバランスを取る上で、2つの要素の相対的な重要性を決定するのが λλ の値です: λλ が小さい時は元のコスト関数を最小化することを好み、λλ が大きい時には より小さな重みを好むのです。
さて、実際のところ、そのようなバランスを取ることがなぜ過適合を軽減する助けになるのか、 その理由は誰の目にもすぐさま明らかなものではありません。しかし、正規化が実際に過適合を軽減することは分かっています。
もっと深堀りすると 👇
正規化されたニューラルネットワークで期待されるように、 ニューラルネットワークの大部分では小さな重みを持つと仮定しましょう。 重みが小さいということは、ここそこでランダムな入力を変化させても ニューラルネットワークの振る舞いが大きくは変わらないことを意味します。 そのため、正規化されたニューラルネットワークでは、 データに含まれる局所的なノイズの効果を学習しづらくなっています。 その代わり、正規化されたニューラルネットワークは訓練データの中で繰り返し見られる データの特徴に反応するのです。対照的に、大きな重みを持つニューラルネットワークは、 入力の小さな変化に敏感に反応してその振る舞いを大きく変えてしまいます。 そのため、正規化されていないニューラルネットワークは、大きな重みを使って、 訓練データのノイズに関する情報をたくさん含んだ複雑なモデルを学習してしまうのです。 要するに、正規化されたニューラルネットワークは訓練データに頻繁に現れるパターンに基づいた 比較的シンプルなモデルを構築します。そして、訓練データが持つノイズの特異性を学ぶことに対して 耐性を持つのです。このため、ニューラルネットワークがノイズではなく現象そのものに対する真の学習をして、 それをより良く汎化できるのではないかと、希望が持てます。
サポートベクターマシン
マージン最大化を行う
コスト関数
cost func = 1 / 2 * w**2
スラック変数を用いた際のコスト関数
epsilon = slack variable cost func = 1 / 2 * w**2 + C * (sum(epsilon))
このCを変化させることで、バイアスとバリアンスのトレードオフを調整できる
二次計画法
数学的に考えてみる(ハードマージンSVM) - Shogo Computing Laboratory
http://numaf.net/Z9/Z9a/html/THESIS/H15/abst_toda.pdf
http://www.r.dl.itc.u-tokyo.ac.jp/~nakagawa/SML1/kernel1.pdf
実装
上記パーセプトロンのPerceptron Fit以降を下のように書き換える
svm = SVC(kernel='linear', C=1.0, random_state=0) svm.fit(X_train_std, y_train) y_pred = svm.predict(X_test_std) print('Misclassified samples: %d' % (y_test != y_pred).sum()) print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))
結果
Misclassified samples: 1 Accuracy: 0.98
カーネルSVM
考え方:射影関数によってデータを高次元空間へ射影し、線形分離できるようにする
デメリット
射影変換(phi(x))を行うと本来、学習過程で生じるxxである計算がphi(x)phi(x)となるため、計算コストがかかる
しかし、カーネルトリックを用いることで軽減できる
k(x_i,x_j) = phi(x_i) * phi(x_j) # Radial Basis Function kernel k(x_i,x_j) = exp(-(x_i - x_j)**2 / (2 * sigma**2)) # Simple Radial Basis Function kernel k(x_i,x_j) = exp(- gamma *(x_i - x_j)**2 )
Radial Basis Function kernelは2つのサンプル間の類似度を表してる
実装
上記パーセプトロンのPerceptron Fit以降を下のように書き換える
先のkernelのパラメータがlinearからrbfに変わっただけ 👇
svm = SVC(kernel='rbf', random_state=0, gamma=0.10, C=10.0) svm.fit(X_train_std, y_train) y_pred = svm.predict(X_test_std) print('Misclassified samples: %d' % (y_test != y_pred).sum()) print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))
パラメータのgammaは
# Simple Radial Basis Function kernel k(x_i,x_j) = exp(- gamma *(x_i - x_j)**2 )
のgammaで小さくするとなめらかに、大きくすると複雑になる
gamma = 0.2にすると 👇
gamma = 100.0にすると 👇
未知のデータでは汎化誤差が生じることが予想される
決定木
意味解釈可能性に配慮する場合に良いモデル
上記のようなカテゴリだけでなく実数でも可能。閾値を1.0などと決めるだけで良い。
決定木の深さが深くなる場合、深さの制限や剪定が必要になる。
情報利得の最大化
目的関数(二分木)
親ノードの不純度と子ノードの不純度の合計の差。つまり、子ノードの不純度が低いほど情報利得は大きくなる
I = Impurity(不純度) Dp = Parent DataSet Dleft = Child DataSet Dright f = function I(Dp, f) = I(Dp) - Nleft/Np * I (Dleft) - Nright/Np * I (Dright)
不純度:エントロピー
t:ノード
相互情報量が最大化になるよう試みる。p(1|t)=1 or p(0|t)=0の時エントロピーは0。p(1|t)=1/2 or p(0|t)=1/2の時エントロピーは1。
Ih = - sum(p(i|t)log2 p(i|t))
不純度:ジニ不純度
誤分類の確率を最小化
Ig = sum(p(i|t) * (1 - p(i|t))) = 1 - sum(p(i|t)**2)
エントロピーと同様、p(1|t)=1 or p(0|t)=0の時エントロピーは0。p(1|t)=1/2 or p(0|t)=1/2の時エントロピーは1。
不純度:分類誤差
すべてのサンプルが最大条件付き確率を与えるクラスに所属すると予測した時に間違えるサンプルの割合を表現する
Ie = 1 - max(p(i|t))
不純度の比較
実装
上記パーセプトロンのPerceptron Fit以降を下のように書き換える
決定木の場合、特徴量のスケーリングは必要ない。
from sklearn.tree import DecisionTreeClassifier tree = DecisionTreeClassifier(criterion='entropy', max_depth=3, random_state=0) tree.fit(X_train, y_train) y_pred = tree.predict(X_test_std) print('Misclassified samples: %d' % (y_test != y_pred).sum()) print('Accuracy: %.2f' % accuracy_score(y_test, y_pred)) # 決定木の可視化 from sklearn.tree import export_graphviz export_graphviz(tree, out_file='tree.dot', feature_names=['petal length', 'petal width'])
ランダムフォレスト
決定木のアンサンブルと考えることができる
トレーニングデータからランダムにn個のサンプルを抽出
決定木を成長させる
上記を繰り返す
決定木ごとの予測をまとめて多数決に基づいてクラスラベルを割り当てる
「はじめてでもわかる RandomForest 入門-集団学習による分類・予測 -」 -第7回データマイニング+WEB勉強会@東京
メリット
パラメータの設定に悩む必要が少なく、上記ステップ1,2を何回繰り返すかを設定すれば良い。繰り返す回数を増やせば性能が上がるが計算コストが増える。
ポイント
上記ステップ1のnは多くの場合サンプルと同じ数に設定するのが良い
実装
上記パーセプトロンのPerceptron Fit以降を下のように書き換える
10個決定木からランダムフォレストをトレーニング
from sklearn.ensemble import RandomForestClassifier forest = RandomForestClassifier(criterion='entropy', n_estimators=10, random_state=1, n_jobs=2) forest.fit(X_train, y_train) y_pred = forest.predict(X_test_std) print('Misclassified samples: %d' % (y_test != y_pred).sum()) print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))
k近傍法
怠惰学習の代表例。識別関数を学習せずトレーニングデータセットを暗記する。ノンパラメトリックモデル。
kの値と距離指標を選択
分類したいサンプルからk個の最近傍のデータ点を見つける
多数決によりクラスラベルを割り当てる
実装
from sklearn.neighbors import KNeighborsClassifier knn = KNeighborsClassifier(n_neighbors=5, p=2, metric='minkowski') # Power parameter for the Minkowski metric knn.fit(X_train_std, y_train) y_pred = knn.predict(X_test_std) print('Misclassified samples: %d' % (y_test != y_pred).sum()) print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))
結果
Misclassified samples: 0 Accuracy: 1.00
機械学習のお勉強(Tiny Yoloを動かしてみる:予測のみ)
やりたいこと
低スペックパソコンで Tiny YOLOを使ってざっくりとした人の位置と大きさを出力する
教科書 👇
わかりやすい記事ありがとうございます。
今回扱うTinyYOLOの説明
上記でもあるように、
Pascal VOCという20クラス分類問題のデータセットに対して係数は最適化されています。
全画面を7x7のグリッドに区切り、グリッドごとのクラス確率と、そのグリッド内に中心をもつバウンディングボックスを1グリッドにつき最大2つずつ、そして、その2つのバウンディングボックス信頼度、というすべての情報を直接推論します。
バウンディングボックスの座標は中心位置のx,yをグリッドサイズで0から1.0に正規化した数値、サイズは幅と高さを画像サイズで0から1.0に正規化した数値の平方根になっています。平方根にする理由は、サイズが大きくなったときの誤差のペナルティを減らしたいからだそうです。
最終段の出力ベクトルは、
7x7x20 のグリッドごとの20クラスの確率 7x7x2 の各グリッドに2組のバウンディングボックスごとの信頼度 7x7x2x4 の各グリッドに2組のバウンディングボックス座標(0-1で正規化してある)
という順番で並んでいるので、reshapeしたあと、信頼度の高いバウンディングボックスを特定して、その座標とクラスを取り出します。
推論時はクラス確率とバウンディングボックスの信頼度を乗算してしきい値で切ればよいですが、学習時は重要なところだけロス関数に乗りやすいような工夫をするそうです。
という感じ。
モデル自体はシンプルで、使っているのは
畳み込み層
全結合層
leaky_relu(活性関数)
Max Pooling
くらい
実装(CPU)
[https://github.com/ashitani/YOLO_chainer:title] さんの実装を少しだけ変更する。ありがたや。
predict.py
import numpy as np def predict(model,im_org): im0=cv2.cvtColor(im_org, cv2.COLOR_BGR2RGB) im_size=np.shape(im0) im0=cv2.resize(im0,(448,448)) im=np.asarray(im0,dtype=np.float32)/255.0 im=im*2.0-1.0 ans=model.predict( im.transpose(2,0,1).reshape(1,3,448,448)).data[0] probs=ans[0:980].reshape((7,7,20)) # class probabilities confs=ans[980:1078].reshape((7,7,2)) # confidence score for Bounding Boxes boxes = ans[1078:].reshape((7,7,2,4)) # Bounding Boxes positions (x,y,w,h) p=np.zeros((7,7,2,20)) for i in range(20): for j in range(2): p[:,:,j,i]=np.multiply(probs[:,:,i],confs[:,:,j]) th=0.1 im_h=im_size[0] im_w=im_size[1] im_marked=im_org classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train","tvmonitor"] pos_size = None class_label = None for z in np.argwhere(p>th): by,bx,j,i = z box=boxes[by,bx,j,:] x= (bx+box[0])*(im_w/7) y = (by+box[1])*(im_h/7) w = box[2]**2.0*im_w h = box[3]**2.0*im_h im_marked=cv2.rectangle(im_marked, (int(x-w/2), int( y-h/2)),( int(x+w/2), int(y+h/2)),[0,0,255],thickness=2) im_marked=cv2.rectangle(im_marked, (int(x-w/2), int( y-h/2)),( int(x-w/2+100), int(y-h/2+20)),[0,0,255],thickness=-1) cv2.putText(im_marked, classes[i],(int(x-w/2+5),int(y-h/2+15)), cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,0),thickness=2) pos_size = [x, y, box[2]**2.0, box[3]**2.0] class_label = classes[i] return im_marked, class_label, pos_size
replay.py
#!/usr/bin/env python from YOLOtiny_chainer import * import cv2 import sys import os import numpy as np print "Loading model" model=YOLOtiny() serializers.load_npz('YOLOtiny_chainer/YOLOtiny.model',model) cap = cv2.VideoCapture(0) while(1): _, frame = cap.read() im_marked, class_label, pos_size = predict(model,frame) if class_label is "person": size = pos_size[2] * pos_size[3] # volume of bounding box print "position_x:{}".format(pos_size[0]) , "position_y:{}".format(pos_size[1]) print "person_size:{}".format(size) cv2.imshow('im_marked',im_marked) k = cv2.waitKey(5) & 0xFF if k == 27: break cap.release() cv2.destroyAllWindows()
出力結果はこんな感じ 👇
- bounding boxの中心位置(取得画像サイズでの横軸X,縦軸Yの値)
- bounding boxの面積 (ざっくりとしたサイズ)
実装(GPU)
import cv2 import numpy as np from chainer import cuda def predict(model, im_org, device = -1): im0=cv2.cvtColor(im_org, cv2.COLOR_BGR2RGB) im_size=np.shape(im0) im0=cv2.resize(im0,(448,448)) im=np.asarray(im0,dtype=np.float32)/255.0 im=im*2.0-1.0 img = im.transpose(2,0,1).reshape(1,3,448,448) if device == 0: cuda.get_device(device).use() model.to_gpu(device) img = cuda.to_gpu(img, device) xp = cuda.cupy else: xp = np ans=model.predict(img).data[0] probs=ans[0:980].reshape((7,7,20)) # class probabilities confs=ans[980:1078].reshape((7,7,2)) # confidence score for Bounding Boxes boxes = ans[1078:].reshape((7,7,2,4)) # Bounding Boxes positions (x,y,w,h) p=xp.zeros((7,7,2,20)) for i in range(20): for j in range(2): p[:,:,j,i]=xp.multiply(probs[:,:,i],confs[:,:,j]) th=0.1 im_h=im_size[0] im_w=im_size[1] im_marked=im_org classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train","tvmonitor"] pos_size = None class_label = None for z in np.argwhere(p>th): by,bx,j,i = z print i box=boxes[by,bx,j,:] x= (bx+box[0])*(im_w/7) y = (by+box[1])*(im_h/7) w = box[2]**2.0*im_w h = box[3]**2.0*im_h im_marked=cv2.rectangle(im_marked, (int(x-w/2), int( y-h/2)),( int(x+w/2), int(y+h/2)),[0,0,255],thickness=2) im_marked=cv2.rectangle(im_marked, (int(x-w/2), int( y-h/2)),( int(x-w/2+100), int(y-h/2+20)),[0,0,255],thickness=-1) cv2.putText(im_marked, classes[int(i)],(int(x-w/2+5),int(y-h/2+15)), cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,0),thickness=2) pos_size = [x, y, box[2]**2.0, box[3]**2.0] class_label = classes[int(i)] return im_marked, class_label, pos_size
インストール
chainerでサポートしているversionチェックするの大事
- CUDA 8.0
- cuDNN v6.0
参考サイト:
Installation Guide — Chainer 3.0.0rc1 documentation
Installation Guide — CuPy 2.0.0rc1 documentation
Ubuntu16.04にCUDA8.0とChainerをインストールする - Qiita
機械学習のお勉強(chainerのTrainerについて)
公式Docs
How to write a training loop in Chainer — Chainer 3.0.0rc1 documentation
わかりやすいまとめ
Chainer の Trainer 解説と NStepLSTM について
MNIST分類コードをChainer-v1.11.0のTrainerで書き換える - Monthly Hacker's Blog
Chainer: ビギナー向けチュートリアル Vol.1 - Qiita
使い方
Trainerオブジェクト(trainer)をつくる
trainer.run()で実行
Trainerオブジェクトの例
ChainerのTrainerを使ってみた - のんびりしているエンジニアの日記さんわかりやすい記事ありがとうございます👇
# coding:utf-8 from __future__ import absolute_import from __future__ import unicode_literals import chainer import chainer.datasets from chainer import training from chainer.training import extensions import chainer.links as L import chainer.functions as F class MLP(chainer.Chain): def __init__(self, n_units, n_out): super(MLP, self).__init__( l1=L.Linear(None, n_units), l2=L.Linear(None, n_units), l3=L.Linear(None, n_out), ) def __call__(self, x): h1 = F.relu(self.l1(x)) h2 = F.relu(self.l2(h1)) return self.l3(h2) train, test = chainer.datasets.get_mnist() train_iter = chainer.iterators.SerialIterator(train, 32) test_iter = chainer.iterators.SerialIterator(test, 32, repeat=False, shuffle=False) model = L.Classifier(MLP(784, 10)) optimizer = chainer.optimizers.SGD() optimizer.setup(model) updater = training.StandardUpdater(train_iter, optimizer, device=-1) trainer = training.Trainer(updater, (10, 'epoch'), out="result") # epoch数の指定 trainer.extend(extensions.Evaluator(test_iter, model, device=10)) # 評価 trainer.extend(extensions.dump_graph('main/loss')) trainer.extend(extensions.snapshot(), trigger=(10, 'epoch')) trainer.extend(extensions.LogReport()) trainer.extend(extensions.PrintReport( ['epoch', 'main/loss', 'validation/main/loss', 'main/accuracy', 'validation/main/accuracy'])) trainer.extend(extensions.ProgressBar()) trainer.run()
参考:
chainer/train_mnist.py at master · chainer/chainer · GitHub
chainer 1.11.0のMNISTサンプルを例にtrainerを読み解く - Monthly Hacker's Blog
Extension
Trainer extensions — Chainer 2.0.2 documentation
Trainerオブジェクトから学習済みモデルを取り出す方法
model = trainer.updater.get_optimizer('main').target.predictor
prediction = model(img)
chainer全体のわかりやすい記事
機械学習のお勉強(データセット)
Segmentation
ADK20K
いい感じ
SUN RGB-D
Introduced: CVPR 2015
Device: Kinect v1, Kinect v2, Intel RealSense and Asus Xtion Live Pro
Description: New images, plus images taken from NYUv2, B3DO and SUN3D. All of indoor scenes.
Labelling: 10,335 images with polygon annotation, and 3D bounding boxes around objects
The dataset contains RGB-D images from NYU depth v2 [1], Berkeley B3DO [2], and SUN3D [3]. Besides this paper, you are required to also cite the following papers if you use this dataset.
SUN RGB-D: A RGB-D Scene Understanding Benchmark Suite
NYU Dataset v2
- ~408,000 RGBD images from 464 indoor scenes, of a somewhat larger diversity than NYU v1. Per-frame accelerometer data.
NYU Depth V2 « Nathan Silberman
SceneNet RGB-D
Description: 5 million images rendered of 16,895 indoor scenes. Room configuration randomly generated with physics simulator.
Labelling: Camera pose, plus per-pixel instance, class labelling and optical flow.
SceneNet RGB-D: Photorealistic Rendering of 5M Images with Perfect Ground Truth
機械学習のお勉強(Classification,Detection,Segmentationの有名論文)
- All
- Classification
- Detection
- Segmentation
- 全体
- FCN
- Delated Convolution
- Instance sensitive FCN
- SegNet
- Refine Net
- Semantic Segmentation using Adversarial Networks
- DeepMask
- SharpMask
- U Net
- Pyramid Scene Parsing Network
- Pohlen_Full-Resolution_Residual_Networks
- End-to-End Instance Segmentation with Recurrent Attention
- Object Region Mining with Adversarial Erasing(弱教師あり学習)
- Bayesian SegNet
- Semi and Weakly Supervised Semantic Segmentation Using Generative Adversarial Network
- Global Average Pooling Layers for Object Localization
- 比較論文
- その他の機械学習手法
- CNN-SLAM
- OpenPose
- ScanNet
- PointNet
- Network Dessecion(中間層の理解)
- Multi-Scale Continuous CRFs as Sequential Deep Networks for Monocular Depth Estimation
- Global Hypothesis Generation for 6D Object Pose Estimation
- Cognitive Mapping and Planning for Visual Navigation
- Kehl_Real-Time_3D_Model Tracking
- Budget-Constrained 6D Object Pose Estimation via Reinforcement Learning
- Global hypothesis generation for 6D object-pose estimation
- Fine-Tuning by Increasing Model Capacity
- A Point Set Generation Network for 3D Object Reconstruction From a Single Image
- pix2pix
- Learning Local Geometric Descriptors from RGBD Reconstructions
- Image Caption Generator
- Neural Style Transfer
- Conditional Random Fields
- latent Dirichlet allocation
- スーパーピクセル
All
CVPR論文まとめ
http://hirokatsukataoka.net/temp/cvpaper.challenge/cvpr17_finalize.pdf
Classification,Detection,Segmentation
UberNet
https://arxiv.org/pdf/1609.02132.pdf
Classification
全体
chainer/examples/imagenet at master · chainer/chainer · GitHub
AlexNet
論文
https://www.cs.toronto.edu/~kriz/imagenet_classification_with_deep_convolutional.pdf
論文まとめ
【深層学習】畳み込みニューラルネットで画像分類 [DW 4日目] - Qiita
VGG16
論文
https://arxiv.org/pdf/1409.1556.pdf
論文まとめ
機械学習論文読み:VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION - Qiita
Fine-tuning
http://www.nlab.ci.i.u-tokyo.ac.jp/pdf/CNN_survey.pdf
ResNet
論文
https://arxiv.org/pdf/1512.03385.pdf
論文まとめ
ResNet論文を読んだメモ(arXiv:1512.03385) - 緑茶思考ブログ
機械学習論文読み:Deep Residual Learning for Image Recognition - Qiita
[Survey]Deep Residual Learning for Image Recognition - Qiita
Residual Network(ResNet)の理解とチューニングのベストプラクティス - DeepAge
SqueezeNet
Fireブロックを8つ重ねたモデル
論文
https://arxiv.org/pdf/1602.07360.pdf
論文まとめ
SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <1MB model sizeを読んだ
chainerbook/fcn_squeeze.py at master · ghmagazine/chainerbook · GitHub
https://www.semiconportal.com/archive/contribution/applications/170418-neurochip5-2.html
Squeezenet-residual by songhan
[Survey]SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <1MB model size - Qiita
DenseNet
論文
https://arxiv.org/pdf/1608.06993.pdf
Git
Local Binary Convolutional Neural Networks
https://arxiv.org/pdf/1608.06049.pdf
Detection
全体
Deep Learningによる一般物体検出アルゴリズムの紹介 - ABEJA Tech Blog
Object Detection & Instance Segmentationの論文紹介 | OHS勉強会#3
R-CNN
論文
https://arxiv.org/pdf/1311.2524.pdf
論文まとめ
Faster R-CNN
論文
https://arxiv.org/pdf/1506.01497.pdf
論文まとめ
yolo
YOLO: Real-Time Object Detection
論文
https://arxiv.org/pdf/1506.02640.pdf
https://arxiv.org/pdf/1612.08242.pdf
論文まとめ
Introduction to YOLO detection model
SSD
論文
https://arxiv.org/pdf/1512.02325.pdf
論文まとめ
SSD: Single Shot MultiBox Detector (ECCV2016)
SSD:Single Shot Multibox Detector - Qiita
Mask R-CNN
論文
https://arxiv.org/pdf/1703.06870.pdf
論文まとめ
最新の物体検出手法Mask R-CNNのRoI AlignとFast(er) R-CNNのRoI Poolingの違いを正しく理解する - Qiita
輪郭/物体抽出の新スタンダードになるか? – Mask R-CNN
A Brief History of CNNs in Image Segmentation: From R-CNN to Mask R-CNN
https://lmb.informatik.uni-freiburg.de/lectures/seminar_brox/seminar_ss17/maskrcnn_slides.pdf
http://classes.engr.oregonstate.edu/eecs/spring2017/cs637/Slides/CS_637_Fast_Faster_Mask_RCNN.pdf
Segmentation
全体
A Review on Deep Learning Techniques Applied to Semantic Segmentation : https://arxiv.org/pdf/1704.06857.pdf
【ディープラーニング】 セマンティックセグメンテーション手法のまとめ - 旅行好きなソフトエンジニアの備忘録
FCN
論文
https://arxiv.org/pdf/1411.4038.pdf
論文まとめ
memo: Fully Convolutional Networks 〜 Chainerによる実装 〜
Implementation of FCN via Keras - MATHGRAM
ディープラーニング セグメンテーション手法のまとめ - 前に逃げる 〜宇宙系大学院生のブログ〜
A brief introduction to recent segmentation methods
Net Surgery
caffe/net_surgery.ipynb at master · BVLC/caffe · GitHub
Shift and Stitch trick
https://www.cs.virginia.edu/yanjun/paperA14/2016-MustCnn.pdf
Delated Convolution
論文
https://arxiv.org/pdf/1511.07122.pdf
論文まとめ
Dilated Convolution - ジョイジョイジョイ
wave net
https://arxiv.org/pdf/1609.03499.pdf
Instance sensitive FCN
論文
https://arxiv.org/pdf/1603.08678.pdf
論文まとめ
論文輪読: Instance-sensitive Fully Convolutional Networks
SegNet
論文
https://arxiv.org/pdf/1511.00561.pdf
論文まとめ
Semantic Segmentationのサーベイ - takminの書きっぱなし備忘録
A Brief Introduction to Recent Segmentation Methods - YouTube
ディープラーニング セグメンテーション手法のまとめ - 前に逃げる 〜宇宙系大学院生のブログ〜
Refine Net
論文
https://arxiv.org/pdf/1611.06612.pdf
Semantic Segmentation using Adversarial Networks
論文
https://arxiv.org/pdf/1611.08408.pdf
DeepMask
論文
https://arxiv.org/pdf/1506.06204.pdf
SharpMask
論文
https://arxiv.org/pdf/1603.08695.pdf
U Net
論文
U-Net: Convolutional Networks for Biomedical Image Segmentation
Pyramid Scene Parsing Network
イケてるらしい
CNNにて階層化されたマップを統合して意味情報を復元
セマンティックセグメンテーションにて一位@ILSVRC2016
論文
https://arxiv.org/pdf/1612.01105.pdf
論文まとめ
[unofficial] Pyramid Scene Parsing Network (CVPR 2017)
Git
GitHub - Vladkryvoruchko/PSPNet-Keras-tensorflow: original code : https://github.com/hszhao/PSPNet
GitHub - hszhao/PSPNet: Pyramid Scene Parsing Network
Pohlen_Full-Resolution_Residual_Networks
論文
Git
GitHub - TobyPDE/FRRN: Full Resolution Residual Networks for Semantic Image Segmentation
End-to-End Instance Segmentation with Recurrent Attention
論文
Object Region Mining with Adversarial Erasing(弱教師あり学習)
論文
https://arxiv.org/pdf/1703.08448.pdf
Bayesian SegNet
論文
https://arxiv.org/pdf/1511.02680.pdf
Git
Semi and Weakly Supervised Semantic Segmentation Using Generative Adversarial Network
論文
https://arxiv.org/pdf/1703.09695.pdf
論文の参考
http://www.mi.t.u-tokyo.ac.jp/kanezaki/pdf/3D_and_weaklearning.pdf
Global Average Pooling Layers for Object Localization
分類ラベルからsegmentationする新しいもの
論文
http://cnnlocalization.csail.mit.edu/Zhou_Learning_Deep_Features_CVPR_2016_paper.pdf
論文まとめ
Global Average Pooling Layers for Object Localization
比較論文
論文
https://arxiv.org/pdf/1605.07678.pdf
Speed/accuracy trade-offs for modern convolutional object detectors : https://arxiv.org/pdf/1611.10012.pdf
論文まとめ
CNNモデル比較論文 "An Analysis of Deep Neural Network Models for Practical Applications"を読んだ - 人間だったら考えて
その他の機械学習手法
CNN-SLAM
http://campar.in.tum.de/pub/tateno2017cvpr/tateno2017cvpr.pdf
CNN-SLAM: Real-time dense monocular SLAM with learned depth prediction - YouTube
http://campar.in.tum.de/Chair/ProjectCNNSLAM
OpenPose
ScanNet
ScanNet: Richly-annotated 3D Reconstructions of Indoor Scenes (CVPR 2017 Spotlight) - YouTube
PointNet
Network Dessecion(中間層の理解)
https://arxiv.org/pdf/1704.05796.pdf
Multi-Scale Continuous CRFs as Sequential Deep Networks for Monocular Depth Estimation
RGBからDepthの推定
https://arxiv.org/pdf/1704.02157.pdf
Global Hypothesis Generation for 6D Object Pose Estimation
https://arxiv.org/pdf/1612.02287.pdf
Cognitive Mapping and Planning for Visual Navigation
ロボット視点からの画像から、マッピングとナビゲーションを同時に⾏い、ゴールまでの経路を推測する研究
https://arxiv.org/pdf/1702.03920.pdf
Cognitive Mapping and Planning
Kehl_Real-Time_3D_Model Tracking
RGB-D映像による3次元追跡を,シングルコアCPUで,2msの処理速度を実現
http://openaccess.thecvf.com/content_cvpr_2017/papers/Kehl_Real-Time_3D_Model_CVPR_2017_paper.pdf
Budget-Constrained 6D Object Pose Estimation via Reinforcement Learning
Global hypothesis generation for 6D object-pose estimation
Fine-Tuning by Increasing Model Capacity
http://ri.cmu.edu/wp-content/uploads/2017/06/yuxiongw_cvpr17_growingcnn.pdf
A Point Set Generation Network for 3D Object Reconstruction From a Single Image
http://openaccess.thecvf.com/content_cvpr_2017/papers/Fan_A_Point_Set_CVPR_2017_paper.pdf
pix2pix
Image-to-Image Demo - Affine Layer
Learning Local Geometric Descriptors from RGBD Reconstructions
https://arxiv.org/pdf/1603.08182.pdf
Git
Image Caption Generator
論文まとめ
Neural Style Transfer
論文
論文まとめ
Neural Style Transfer: Prismaの背景技術を解説する
Conditional Random Fields
CRFがよくわからなくてお腹が痛くなってしまう人のための30分でわかるCRFのはなし - EchizenBlog-Zwei
latent Dirichlet allocation
スーパーピクセル
kmeans を使った画像のセグメンテーション - Qiita
http://www.vision.cs.chubu.ac.jp/flabresearcharchive/master/m07/paper/kida_paper.pdf
http://www.vision.cs.chubu.ac.jp/FLABResearchArchive/Master/M07/Abstract/kida_abst.pdf
機械学習のお勉強(セグメンテーション)
画像認識のタスク
Classification : What?
Detection : What? Where?
Segmentation : What? Where? Shape?
セグメンテーション
こんな感じ👇
ポイント
ひとつのピクセルだけを見て、何かを推測することは難しい。なので、いかに周囲の情報を加味しながら、ピクセルの分類をするかが重要。
Sample
以下ではこれを例にsegmentationをお勉強する
chainerbook/ch6 at master · ghmagazine/chainerbook · GitHub
前処理
入力画像のサイズ調整
ストライドの累乗値の倍数に画像の大きさを変更
ex:ストライド2のMax Poolingが3つある場合、8の倍数に調整する必要がある
chainerbook/mini_batch_loader.py at master · ghmagazine/chainerbook · GitHub
画像の正規化
Local Contrast Normalization: theanoで局所コントラスト正規化(Local Contrast Normalization)を使う - 備忘録とか日常とか
Global Contrast Normalization: chainerbook/image_normalizer.py at master · ghmagazine/chainerbook · GitHub
オーギュメンテーション
左右上下反転: chainerbook/mini_batch_loader.py at master · ghmagazine/chainerbook · GitHub
Train
# データセットのロード train_mini_batch_loader, train_data_size = prepare_dataset() # モデルのロード model = FCN(chainer.global_config.user_train_args.n_class, chainer.global_config.user_train_args.in_ch) # オプティマイザーの定義 optimizer = chainer.optimizers.Adam() optimizer.setup(model) optimizer.add_hook( chainer.optimizer.WeightDecay( chainer.global_config.user_train_args.training_params.weight_decay))
Model
SqueezeNet 👈 Fire Moduleを8つ重ねたモデル
class Fire(chainer.Chain): def __init__(self, in_size, s1, e1, e3): super().__init__() with self.init_scope(): self.conv1=L.Convolution2D(in_size, s1, 1) self.conv2=L.Convolution2D(s1, e1, 1) self.conv3=L.Convolution2D(s1, e3, 3, pad=1) def __call__(self, x): h = F.elu(self.conv1(x)) h_1 = self.conv2(h) h_3 = self.conv3(h) h_out = F.concat([h_1, h_3], axis=1) return F.elu(h_out) class FireDilated(chainer.Chain): def __init__(self, in_size, s1, e1, e3): super().__init__() with self.init_scope(): self.conv1=L.DilatedConvolution2D(in_size, s1, 1) self.conv2=L.DilatedConvolution2D(s1, e1, 1) self.conv3=L.DilatedConvolution2D(s1, e3, 3, pad=2, dilate=2) def __call__(self, x): h = F.elu(self.conv1(x)) h_1 = self.conv2(h) h_3 = self.conv3(h) h_out = F.concat([h_1, h_3], axis=1) return F.elu(h_out) class FCN(chainer.Chain): def __init__(self, n_class, in_ch): super().__init__() with self.init_scope(): self.conv1=L.Convolution2D(in_ch, 96, 7, stride=2, pad=3) self.fire2=Fire(96, 16, 64, 64) self.fire3=Fire(128, 16, 64, 64) self.fire4=Fire(128, 16, 128, 128) self.fire5=Fire(256, 32, 128, 128) self.fire6=Fire(256, 48, 192, 192) self.fire7=Fire(384, 48, 192, 192) self.fire8=Fire(384, 64, 256, 256) self.fire9=FireDilated(512, 64, 256, 256) self.score_pool1=L.Convolution2D(96, n_class, 1, stride=1, pad=0) self.score_pool4=L.Convolution2D(256, n_class, 1, stride=1, pad=0) self.score_pool9=L.Convolution2D(512, n_class, 1, stride=1, pad=0) self.add_layer=L.Convolution2D(n_class*3, n_class, 1, stride=1, pad=0) # padding means reduce pixels in deconvolution. self.upsample_pool4=L.Deconvolution2D(n_class, n_class, ksize= 4, stride=2, pad=1) self.upsample_pool9=L.Deconvolution2D(n_class, n_class, ksize= 4, stride=2, pad=1) self.upsample_final=L.Deconvolution2D(n_class, n_class, ksize=16, stride=4, pad=6) self.n_class = n_class self.active_learn = False self.evaluator = Evaluator(False, n_class) def clear(self): self.loss = None self.accuracy = None def __call__(self, x, t): h = F.elu(self.conv1(x)) h = F.max_pooling_2d(h, 3, stride=2) p1 = self.score_pool1(h) h = self.fire2(h) h = self.fire3(h) h = self.fire4(h) h = F.max_pooling_2d(h, 3, stride=2) u4 = self.upsample_pool4(self.score_pool4(h)) h = self.fire5(h) h = self.fire6(h) h = self.fire7(h) h = self.fire8(h) # h = F.max_pooling_2d(h, 3, stride=2) h = self.fire9(h) u9 = self.upsample_pool9(self.score_pool9(h)) h = F.concat((p1, u4, u9), axis=1) h = self.add_layer(h) h = self.upsample_final(h) self.h = h self.loss = F.softmax_cross_entropy(h, t) self.evaluator.preparation(h, t) self.accuracy = self.evaluator.get_accuracy() self.iou = self.evaluator.get_iou() return self.loss
参考:
chainerbook/fcn_squeeze.py at master · ghmagazine/chainerbook · GitHub
https://www.semiconportal.com/archive/contribution/applications/170418-neurochip5-2.html
Squeezenet-residual by songhan
[Survey]SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <1MB model size - Qiita
Convolution層
paddingを使って計算後の出力サイズを維持しやすくするため,カーネルサイズを奇数に。(int(ksize/2)をpadに指定すると,stride=1の際に画像サイズが維持)
出力feature mapを小さくしたい場合は,1より大きいstrideに。(stride=nだと1/n)
出力サイズは、(input_size - ksize + pad×2) / stride+1に。 (strideを大きくすると出力特徴マップは小)
Deconvolution層
Transposed convolutionやBackward convolutionと呼ばれることも。入力特徴マップに対するアップサンプリング。
カーネルサイズをstrideで割り切れる数に。参考:Deconvolution and Checkerboard Artifacts
出力サイズは、stride×(input_size − 1) + ksize − 2×pad。
feature mapの周囲を「削る量」がpadになっている。Convolutionの逆。
参考:
ニューラルネットワークにおけるDeconvolution - Qiita
【保存版】chainerのconvolutionとdeconvolution周りを理解する - Monthly Hacker's Blog
chainerでx方向にconv、y方向にdeconvする - Qiita
モデルの結合
F.concat
In [2]: x1 = chainer.Variable(numpy.array([[1, 2], [3, 4]])) In [3]: x2 = chainer.Variable(numpy.array([[5, 6], [7, 8]])) In [4]: x1.data Out[4]: array([[1, 2], [3, 4]]) In [5]: x2.data Out[5]: array([[5, 6], [7, 8]]) In [6]: chainer.functions.concat([x1, x2], axis=1).data Out[6]: array([[1, 2, 5, 6], [3, 4, 7, 8]])
参考:
python - Chainerでネットワークの途中でのデータの合成方法は? - スタック・オーバーフロー
chainer.functions.concat — Chainer 3.0.0rc1 documentation
Segmentationのサンプル
Deep Learning Tutorial - Second Annual Data Science Bowl | Kaggle
Segmenatation論文まとめ
ディープラーニング セグメンテーション手法のまとめ - 前に逃げる 〜宇宙系大学院生のブログ〜
Tips
- MemoryErrorがでたら : Pythonで少なくメモリを使用する方法 - のんびりしているエンジニアの日記