空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

機械学習のお勉強(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

使い方

  1. Trainerオブジェクト(trainer)をつくる

  2. 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全体のわかりやすい記事

【機械学習】ディープラーニング フレームワークChainerを試しながら解説してみる。 - Qiita

機械学習のお勉強(データセット)

Segmentation

ADK20K

いい感じ

ADE20K dataset

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

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

論文まとめ

AlexNet論文 | 有意に無意味な話

【深層学習】畳み込みニューラルネットで画像分類 [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) - 緑茶思考ブログ

Res netと派生研究の紹介

機械学習論文読み: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

20160901 jwein

Squeezenet-residual by songhan

[Survey]SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <1MB model size - Qiita

2016年の深層学習を用いた画像認識モデル - Qiita

DenseNet

論文

https://arxiv.org/pdf/1608.06993.pdf

Git

GitHub - liuzhuang13/DenseNet: Densely Connected Convolutional Networks, In CVPR 2017 (Best Paper Award).

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

論文まとめ

R-CNNの原理とここ数年の流れ

20140131 R-CNN

Faster R-CNN

論文

https://arxiv.org/pdf/1506.01497.pdf

論文まとめ

論文紹介: Fast R-CNN&Faster R-CNN

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

YOLO CVPR 2016 - Google スライド

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

論文

http://openaccess.thecvf.com/content_cvpr_2017/papers/Pohlen_Full-Resolution_Residual_Networks_CVPR_2017_paper.pdf

Git

GitHub - TobyPDE/FRRN: Full Resolution Residual Networks for Semantic Image Segmentation

End-to-End Instance Segmentation with Recurrent Attention

論文

http://openaccess.thecvf.com/content_cvpr_2017/papers/Ren_End-To-End_Instance_Segmentation_CVPR_2017_paper.pdf

Object Region Mining with Adversarial Erasing(弱教師あり学習)

論文

https://arxiv.org/pdf/1703.08448.pdf

Bayesian SegNet

論文

https://arxiv.org/pdf/1511.02680.pdf

Git

GitHub - alexgkendall/SegNet-Tutorial: Files for a tutorial to train SegNet for road scenes using the CamVid dataset

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

GitHub - CMU-Perceptual-Computing-Lab/openpose: OpenPose: Real-Time Multi-Person Keypoint Detection Library for Body, Face, and Hands

ScanNet

ScanNet: Richly-annotated 3D Reconstructions of Indoor Scenes (CVPR 2017 Spotlight) - YouTube

PointNet

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

http://openaccess.thecvf.com/content_cvpr_2017/papers/Krull_PoseAgent_Budget-Constrained_6D_CVPR_2017_paper.pdf

Global hypothesis generation for 6D object-pose estimation

http://openaccess.thecvf.com/content_cvpr_2017/papers/Michel_Global_Hypothesis_Generation_CVPR_2017_paper.pdf

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

GitHub - andyzeng/3dmatch-toolbox: 3DMatch - a 3D ConvNet-based local geometric descriptor for aligning 3D meshes and point clouds.

Image Caption Generator

論文まとめ

Show and tell takmin

Neural Style Transfer

論文

https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Gatys_Image_Style_Transfer_CVPR_2016_paper.pdf

論文まとめ

Neural Style Transfer: Prismaの背景技術を解説する

Conditional Random Fields

CRFがよくわからなくてお腹が痛くなってしまう人のための30分でわかるCRFのはなし - EchizenBlog-Zwei

latent Dirichlet allocation

LDA入門

スーパーピクセル

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

http://www.nlab.ci.i.u-tokyo.ac.jp/pdf/ssii2015tamanaha.pdf

機械学習のお勉強(セグメンテーション)

画像認識のタスク

  1. Classification : What?

  2. Detection : What? Where?

  3. Segmentation : What? Where? Shape?

セグメンテーション

  • ピクセルごとにクラス分類を行う。推定はピクセル✕分類クラス数。

  • 入力と同じサイズに出力を合わせる必要がある。逆畳み込みを行う。つまり、画像を入力として画像を出力する。

こんな感じ👇

f:id:robonchu:20171003215824p:plain

ポイント

ひとつのピクセルだけを見て、何かを推測することは難しい。なので、いかに周囲の情報を加味しながら、ピクセルの分類をするかが重要。

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

20160901 jwein

Squeezenet-residual by songhan

[Survey]SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <1MB model size - Qiita

2016年の深層学習を用いた画像認識モデル - 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と呼ばれることも。入力特徴マップに対するアップサンプリング。

可視化:GitHub - vdumoulin/conv_arithmetic: A technical report on convolution arithmetic in the context of deep learning

  • カーネルサイズをstrideで割り切れる数に。参考:Deconvolution and Checkerboard Artifacts

  • 出力サイズは、stride×(input_size − 1) + ksize − 2×pad。

  • feature mapの周囲を「削る量」がpadになっている。Convolutionの逆。

参考:

ニューラルネットワークにおけるDeconvolution - Qiita

GitHub - vdumoulin/conv_arithmetic: A technical report on convolution arithmetic in the context of deep learning

【保存版】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論文まとめ

robonchu.hatenablog.com

ディープラーニング セグメンテーション手法のまとめ - 前に逃げる 〜宇宙系大学院生のブログ〜

Tips

機械学習のお勉強(CNN)

全結合層の欠点

  • 畳み込み層と比較してパラメータ数が膨大になる

  • コンテキストの活用が難しい

  • 位置ずれに弱い

畳み込みニューラルネットワーク(CNN)

全結合層の問題点はデータの形状が無視されてしまうこと。例えば、画像28×28ピクセルの形状を784個のデータとして入力する。

これは、画像の空間的な相関関係を無視しているため、形状に関する情報を生かすことができない。

一方、畳み込み層は形状を維持する。CNNでは入出力データを特徴マップという。

層が深くなるにつれて、抽出される情報はより抽象化(犬や車など高度な情報へと変化)されていくといわれている。

畳み込み演算、フィルター(カーネル)演算

フィルターのウインドをスライドさせながら、それぞれで積和演算を行う。

このフィルターパラメータがこれまでの重みに対応する。バイアスも同様に存在する。

パディング

入力データの周囲に固定データ(0など)を埋めること。これによって出力サイズを調整することができる。

これによって空間の圧縮により、畳み込みができなくなってしますことを防ぐ。

入力データの大きさに対して考慮すべきことがへる

ストライド

フィルターのウインドをスライドさせる間隔。

出力サイズ

大事!

畳み込み層の出力から全結合層への入力を計算するときに必要

全結合層への入力 = 畳み込み層のフィルター数 * h_o * w_o

# h_o, w_o : outout
# h_i, w_i : input
# h_p, w_p : padding
# h_k, w_k : filter size
# s_y, s_x : stride

h_o = (h_i + 2 * h_p - h_k) / s_y + 1
w_o = (w_i + 2 * w_p - w_k) / s_x + 1

大事!

Convolutional Neural Networkを実装する - Qiita

Deep Learning覚え書き(convolutionとpoolingの出力サイズ) - 覚え書きブログ

【保存版】chainerのconvolutionとdeconvolution周りを理解する - Monthly Hacker's Blog

GitHub - vdumoulin/conv_arithmetic: A technical report on convolution arithmetic in the context of deep learning

プーリング層

縦、横方向の空間(サイズ)を小さくする演算。

  • 情報量を落とさずに特徴マップの空間を小さくする

  • 微小な位置ずれに対して頑強にする

  • Maxプーリング:対象領域から最大値をとる演算

  • Averageプーリング:対象領域の平均をとる演算

画像認識の分野では主にMaxプーリングが用いられる。

  1. 入力データを展開する
  2. 行ごとに最大値を求める
  3. 適切な出力サイズに整形する

What is max pooling in convolutional neural...(2017) - Quora

ROIプーリング

バックワードの計算でそれぞれのBOXに対して、勾配を加算する

切り取った部分のみに勾配を加算することで、切り取った部分に関係するパラメータのみに対してロスを反映できる

chainer/roi_pooling_2d.py at master · chainer/chainer · GitHub

[1504.08083] Fast R-CNN

三次元データの畳み込み演算

入力データのチェンネル数とフィルター数は同じにすること。

フィルター自体を複数用意すると多チャンネルの特徴マップを出力することができる。

よってフィルターの重みデータは4次元のデータ(チャンネル数4、サイズ5×5、フィルター数20)としてあらわすことができる。

バッチ処理

各層を流れるデータは四次元データとなる。

チャンネル数、サイズに加え、バッチ数が付け加えられる。

層の深さに関して

簡単な文字認識などでは層は深くないほうが高精度

大規模画像認識のコンペなどでは層が深いものは上位

そして、層を深くするとパラメータを減らすことができる

しかし、層を深くしすぎると性能が劣ることもあった

ResNet

層を深くすることができる手法で、スキップ構造を導入している。

これによって層を深くすることに比例して性能を向上させることができる。

転移学習

学習済みの重みをベースに学習を行う。

課題

如何に畳み込み層の計算を速く行うか。

つまり、いかに速く効率的に積和演算を行うか。

機械学習のお勉強(chainerの概要)

chainerの特徴

ネットワーク構築と学習を同時に行う「Define-by-Run」方式。イメージはインタプリタデバッグしやすい。

tensorflowは「Define-and-Run」方式。イメージはコンパイラ

計算グラフ

class MulAdd(Function):
    def forward_cpu(self, inputs):
        x, y, z = inputs
        w = x * y + z
        return w,

    def backward_cpu(self, inputs, grad_outputs):
        x, y, z = inputs
        gw, = grad_outputs

        gx = y * gw
        gy = x * gw
        gz = gw
        return gx, gy, gz

Define your own function — Chainer 3.0.0rc1 documentation

全結合層におけるバックワード計算

class LinearFunction(Function):
    def forward(self, inputs):
        x, W, b = inputs
        return x.dot(W.T) + b,

    def backward(self, inputs, grad_outputs):
        x, W, b = inputs
        gy, = grad_outputs

        gx = gy.dot(W)
        gW = gy.T.dot(x)
        gb = gy.sum(axis=0)
        return gx, gW, gb

def linear(x, W, b):
    return LinearFunction()(x, W, b)

Config オブジェクト

train/test flagを立てれたり、debug modeの指定などができる

Configuring Chainer — Chainer 3.0.0rc1 documentation

Variableクラス

最高にわかりやすい 👉 Chainerのソースを解析。順伝播と逆伝播の仕組み | コード7区

参考:

chainer-cifar10/Cifar10.py at master · mitmul/chainer-cifar10 · GitHub

ノート/Chainerでネットを可視化する(備忘) 2017-04-27 - 東邦大学理学部情報科学科 山内のサイト

Functionクラス

最高にわかりやすい 👉 Chainerのソースを解析。順伝播と逆伝播の仕組み | コード7区

Standard Function implementations — Chainer 3.0.0rc1 documentation

Linkクラス

イメージ: Function Class + Parameter Class

import chainer
import chainer.functions as F
from chainer import initializers
import numpy as np

class LinearLayer(chainer.Link):

    def __init__(self, n_in, n_out):
        super(LinearLayer, self).__init__()
        with self.init_scope():
            self.W = chainer.Parameter(
                initializers.Normal(), (n_out, n_in))
            self.b = chainer.Parameter(
                initializers.Zero(), (n_out,))

    def __call__(self, x):
        return F.linear(x, self.W, self.b)

chainer.Link — Chainer 3.0.0rc1 documentation

Chainクラス

  • 上記のクラスを統合、管理するクラス

  • これを継承して作成したネットワーク構造のインスタンスをモデルオブジェクトとして使用する

  • Link機能のように機能させることも可能(ChainクラスはLinkクラスの子クラス)

以下の例ではchainクラスを通常のLinkと同様に用いている

import chainer
import chainer.functions as F
import chainer.links as L


class Fire(chainer.Chain):
    def __init__(self, in_size, s1, e1, e3):
        super(Fire, self).__init__(
            conv1=L.Convolution2D(in_size, s1, 1),
            conv2=L.Convolution2D(s1, e1, 1),
            conv3=L.Convolution2D(s1, e3, 3, pad=1),
            bn4=L.BatchNormalization(e1 + e3)
        )

    def __call__(self, x):
        h = F.relu(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.relu(self.bn4(h_out))


class SqueezeNet(chainer.Chain):
    def __init__(self, ):
        super(SqueezeNet, self).__init__(
            conv1=L.Convolution2D(3, 96, 7, stride=2),
            fire2=Fire(96, 16, 64, 64),
            fire3=Fire(128, 16, 64, 64),
            fire4=Fire(128, 16, 128, 128),
            fire5=Fire(256, 32, 128, 128),
            fire6=Fire(256, 48, 192, 192),
            fire7=Fire(384, 48, 192, 192),
            fire8=Fire(384, 64, 256, 256),
            fire9=Fire(512, 64, 256, 256),
            conv10=L.Convolution2D(512, 1000, 1,
                pad=1, initialW=normal(0, 0.01 (1000, 512, 1, 1)))
        )

    def __call__(self, x, train=False):
        h = F.relu(self.conv1(x))
        h = F.max_pooling_2d(h, 3, stride=2)

        h = self.fire2(h)
        h = self.fire3(h)
        h = self.fire4(h)

        h = F.max_pooling_2d(h, 3, stride=2)

        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)
        h = F.dropout(h, ratio=0.5, train=train)

        h = F.relu(self.conv10(h))
        h = F.average_pooling_2d(h, 13)

return F.reshape(h, (-1, 1000))

squeezenet-chainer/model.py at master · ejlb/squeezenet-chainer · GitHub

Optimizerクラス

登録

optimizer = optimizers.SGD(lr=0.01)
optimizer.setup(model)

更新

loss = model(x,t)
loss.backward()
optimizer.update()

正規化するメソッドもある

optimizer.add_hook(chainer.optimizer.WeightDecay())

optimizerオブジェクトを作成したあとにadd_hookメソッドを用いて、最適化計算に追加する

Optimizers — Chainer 3.0.0rc1 documentation

Optimizer — Chainer 3.0.0rc1 documentation

Trainerクラス

これを用いることで途中経過や学習経過の監視が一行でかける

ChainerのTrainerを使ってみた - のんびりしているエンジニアの日記

Chainer の Trainer 解説と NStepLSTM について

Reporterによる監視対象のフック

self.loss = F.softmax_cross_entropy(y, t)
self.accuracy = F.accuracy(y, t)

chainer.report({'loss': self.loss, 'accuracy':self.accuracy},self)

Updateクラス

chainer 1.11.0のMNISTサンプルを例にtrainerを読み解く - Monthly Hacker's Blog

複数のモデルをchainerのTrainerで扱うための3つのポイント - Qiita

機械学習のお勉強(オプティマイザーと学習率とエポック、イテレーション)

オプティマイザー

勾配

勾配(微分に負をかけたもの)が示す方向は関数の値を減らす方向になる。

↓数値微分。シンプルだが計算に時間がかかる。

def numerical_gradient(f,x):
    h = 1e-4 # 0.0001
    grad = np.zeros_like(x)

    for idx in range(x.size):
        tmp_val = x[idx]
        x[idx] = tmp_val + h
        fxh1 = f(x)

        x[idx] = tmp_val - h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2)/(2*h)
        x[idx] = tmp_val

    return grad

この勾配の計算を高速に求める手法として、誤差逆伝播法が存在する。

勾配降下法

勾配方向に一定距離だけ進み、そこで勾配を求め再度進む。これの繰り返しによって関数の値を減らす。

以下の式のlrは学習率(learning rate)はあらかじめ人が決める(試行錯誤的に決める)必要があり、ハイパーパラメータと呼ばれる。

このパラメータはバイアスや重みと異なり自動で決めることはできない、かつ、正しく学習するうえで重要。

def gradient_descent(f, init_x, lr = 0.01, step_num = 100):
    x = init_x
    
    for i in range(step_num):
        grad = numerical_gradient(f, x)
        x -= lr * grad
        
    return x

確率的勾配降下法

上記のxをランダムに選んだサンプル一つだけで計算したもの

ミニバッチ確率勾配降下法

上記の1つのサンプルだけではなく、k個のサンプルを1回の更新に利用

モーメンタムSGD

def gradient_descent(f, init_x, lr = 0.01, step_num = 100):
    x = init_x
    
    for i in range(step_num):
        grad = numerical_gradient(f, x)
        v = gamma * pre_v + (1 - gammma) * grad
        x -= lr * v
        pre_v = v
    return x
v = gamma * pre_v + (1 - gamma) * grad

とする、gamma=0.9などにすることが多い。

また、v[t] = (1 - gamma) * sum(gamma**k * grad[t-k] for k in range(t))

と過去の勾配の和として書くことができる。

学習率

上記の

x -= lr * grad

のlrにあたるもの。

学習の速さや最終的なロス値にトレードオフがあるため適切な学習率の設定が必要

AdaGrad

学習率を勾配が大きい時は小さく、小さい時は大きくする方法

eps = 1e-4 # 0.0001
G_2 = pre_G**2 + grad**2
x -= lr / sqrt(G_2 + eps) * grad
pre_G = G_2

G_2 は増加し続けるため、学習が進まなくなることがある

Adam

Momentum SGDの重み付き平均 と AdaGradの重み付き分散を踏まえ、

上記の問題を解決した手法

eps = 1e-4 # 0.0001
bias = sum(gamma**k * grad[t-k] for k in range(t))  # 重み付き平均
var = (bata * pre_var**2 + (1- beta) * grad**2) / (1 -beta) 
x -= lr * bias / sqrt(var + eps)
pre_var = var

参考:

Optimizer : 深層学習における勾配法について - Qiita

エポックとイテレーション

エポック

すべての学習サンプルを学習するのに要した機関

イテレーション

重みを1回更新すること

まとめ

学習率を表す際、イテレーションはバッチサイズに依存してしまうため不適切。

エポックの場合、勾配降下法なのかミニバッチ確率的勾配降下法なのかでかわらない、つまりバッチサイズに依存しない。