論文: Objects as Points
先日下記の2イベントでこの論文について発表させていただきました。
上記のいずれも発表された方々ががっつり読み込まれていて、 非常に有意義な議論を交わすことができました!
資料も一応2通り作りましたが、前半は 手抜き LT用でしたので後半の資料を見ていただければ幸いです。
この論文で提案されている CenterNet(同名の他のネットもあるので注意) は CornerNet の派生形になります。 ですが CornerNet がボックスの対角の 2点を予測するのに対し、CenterNet では中心のみを予測します。(検出の場合) 発想としてはむしろ自然であり、Backbone(DLA・Hourglass) から後は非常にシンプルなネットワークです。 これで YOLOv3 よりも速くて精度が高いらしいので、Object Detection 周りの進歩も非常に速いことが伺えます。
論文: Sequence to Sequence Learning with Neural Networks
reading-innovation.connpass.com
先日上記のイベントで発表させていただいた際の資料です! NLP系の論文は久しぶりだったのでハードでしたが読んで良かったです。
論文: M2Det: A Single-Shot Object Detector based on Multi-Level Feature Pyramid Network
注意
- 元論文:https://qijiezhao.github.io/imgs/m2det.pdf
- 本記事中の図はここを参照しています
- この解説は元論文の Google 日本語訳に対し毛が生えたようなものです
- ですので可能な限り元論文を読むことを推奨します
- 綺麗にまとめた訳ではないので似たような文が何度か繰り返される箇所があります
- 真剣に読んでまとめましたが間違えてる可能性はあります。マサカリください
- Experiments, Discussion, Conclusion については本記事では扱ってません
- M2Det って何?構造上これまでのモデルと何が違うのか?をしっかりまとめたかったので
- Experiments は後日追記するかもしれません
導入
2018年の物体検出では、速度精度の両方を見た場合 YOLOv3 が最もインパクトが大きかったと思います。 特に機械学習触ったことがない人にとって比較的導入しやすい(導入しやすいとは言っていない)のもポイントだったと思います。
そんな YOLOv3 に対し M2Det は もっと速くてもっと精度良い らしいです。 元論文は AAAI2019 にも採択されたらしいです。 今回はそんな M2Det の論文を頭からしっかり読んでいきます。
- 詳細な論文の訳が知りたい人は下記の内訳を確認してください。
- scale と level について
- 論文内では scale と level の 2つの観点で feature を分けています
- scale: 画像内での大きさ、scale が大きい -> 画像内で対象の占める面積が大きい
- level: 特徴としての抽象度や複雑度
- level が低い feature -> より単純な特徴
- level が高い feature -> より複雑な特徴や、抽象度が高い特徴
- 論文内では scale と level の 2つの観点で feature を分けています
- base feature について
- この論文内での base feature は、backbone となるネットワーク (VGG16 とか) から得た feature を FFMv1 モジュールによって統合したものです
ぶっちゃけ何がすごいの?
- YOLOv3 より速くて精度良い
- multi-level な特徴を multi-scale に扱えるようにした
- 過去のメジャーなモデルほとんでについて実験してる
- すごすぎる
- ここまでやれば AAAI 通るのか…
論文内訳
1. 著者情報
- 著者一覧
- Qijie Zhao(1)
- Tao Sheng(1)
- Yongtao Wang(1)
- Zhi Tang(1)
- Ying Chen(2)
- Ling Cai2 and Haibin Ling(3)
- 著者所属
- 1: Institute of Computer Science and Technology, Peking University, Beijing, P.R. China
- 2: AI Labs, DAMO Academy, Alibaba Group
- 3: Computer and Information Sciences Department, Temple University
中国すご…
2. Abstract
- Feature pyramids めっちゃ流行ってるよな
- one-stage object detectors (e.g., DSSD, RetinaNet, RefineDet)
- two-stage object detectors (e.g., Mask R-CNN, DetNet)
- でも上記のモデルたちは backbone のタスク(classification) 用のマルチスケール feature 使ってるからある程度制限かかってるよな?
- 🤔
- 俺らは "Multi-Level Feature Pyramid Network (MLFPN)" を提案するぜ
- 上記より detection に特化した feature pyramids だぜ
- 以下 3 step で作るぜ
- base feature として extract した fuse multi-level features (i.e. multiple layers) を融合する
- 以下2つ
- base feature を次の2つを組み合わせたブロックに入れる
- Thinned U-shape Modules
- Feature Fusion Modules
- また U-shape module の decoder layers は Object detection 時に活用する
- base feature を次の2つを組み合わせたブロックに入れる
- 同じ scale(size) の decoder layer を集約して Detection 用の feature pyramid を作る
- どの feature map も multiple-level な layer(feature) を含む
- だから精度上がってる???
- 上記の MLFPN を SSD アーキテクチャに組み込んだものを M2Det と呼ぶことにするわ
- 性能は one-stage detector 間で SOTA だぜ
- MS-COCO benchmark
- AP of 41.0 at speed of 11.8 FPS with single-scale inference strategy
- AP of 44.2 with multi-scale inference strategy
- 上記2つの strategy の違いは???
- コードは GitHub - qijiezhao/M2Det: M2Det: A Single-Shot Object Detector based on Multi-Level Feature Pyramid Network にあるぜ
- 4月頃コードが載るらしい?
3. Introduction
- Object detection において scale variation はメジャーなテーマ
- scale variation は大きく 2つの戦略がある
- 1: image pyramid
- いろいろなサイズに resize してコピーしたイメージ群等
- test 時にしかできないぞ
- もちろんメモリ使用量や計算量は増えるぞ
- よって効率はめっちゃ悪くなるぞ
- 2: detect objects in a feature pyramid extracted from the input image
- train 時も test 時も使えるぞ
- 1 に比べてメモリ使用量や計算量が少ないぞ
- feature pyramid は SOTA detection model への統合が楽にできるぞ
- 1: image pyramid
- SSD, FPN, RetinaNet, Mask R-CNN 強いよな
- でもクラス分類用に設計された feature pyramid のせいで限界あるよな
- 一般に上記の feature pyramid 作成方法は 2つの限界がある
- 1: pyramid 内の feature map の表現力が十分でない
- Object detection 用として考えると
- Base net は object classification 用に設計したからね
- 2: pyramid 内の各 feature map は、主に single-level layer in backbone から構成されている
- 各 feature map は特定範囲サイズの object detection 用
- そのため各 feature map は主に single-level の情報のみ含んでいる
- 1: pyramid 内の feature map の表現力が十分でない
- 一般に high-level feature と low-level feature は以下の違いがある
- high-level
- 分類サブタスクに役立つ
- 複雑な見た目の物体を特徴づけるのに役立つ
- low-level
- 物体位置回帰サブタスク(Object Location Regression) に役立つ
- 単純な見た目の物体を特徴づけるのに役立つ
- high-level
- 実際にはサイズが同じでも見た目がかなり違う場合がある
- 例:「信号機」と「遠くにいる人間」-> サイズは同じくらいでも人間の方がかなり複雑な見た目をしている
- pyramid 内の各 feature map は全てもしくはそのほとんどが single-level な特徴しか含んでいない
- -> Detection の performance が準最適(最適ではない)
- 上記の問題に対処するため以下 3step で M2Det 作った
- 1: 各 level の feature を混ぜて base feature とした
- 2: 以下の操作を行う
- 以下2つを交互に組み合わせたネットワークに入力する
- Thinned U-shape Modules(TUM)
- Feature Fusion Modules(FFM)
- より multi-level, multi-scale な feature を抽出するため
- 大事なこと:U-shape Module の各 decoder layers が同じ深さを共有している
- 以下2つを交互に組み合わせたネットワークに入力する
- 3: detection 用の feature pyramid を構築するために、同じ scale の feature map を集約する
- final feature pyramid 内の各 feature map は multi-level decoder layer を含んでいる
- Hence, we call our feature pyramid block Multi-Level Feature Pyramid Network (MLFPN).
4. Related Work
- 皆、one-stage や two-stage に限らず、様々な scale に対応するため頑張ってきた。それらは大きく2つの戦略がある
- 1: featurizing image pyramids
- 例: 画像をコピーして各スケールに resize したもの
- 各 scale の画像からそれぞれ予測を出力して、それらを合わせて最終的な出力を出す
- 単純に単一 scale で予測するより精度が高い
- Shrivastava et al.2016 や SNIP(Singh and Davis 2018) が該当する
- SNIP は SNIPER の元っぽい
- これらは時間やメモリ上のコストがかかるため、real-time task は厳しい
- 上記に対処するため、SNIP(Singh and Davis 2018) では test 時は特定の featurized image pyramid のみを採用できるようになっている
- 一方 Fast-RCNN や Faster-RCNN ではデフォルトではこの方法を選択しないようになっている
- 2: feature pyramid
- 単一 scale の画像のみを使い、ネットワーク層からそれぞれの feature を取ってきて pyramid を構成する方法
- 上記の方法(featurizing image pyramids)に比べ、メモリや計算コストを抑えることができるし、real-time 処理の train, test 時の両方でそのまま使える
- 加えて、この方法は SOTA のネットワークに容易に適用できる
- 以下のネットワークがそれぞれの方法で feature pyramid を適用している
- 俺らが調べたところ、
- MS-CNN(Cai et al.2016) が 2つの sub-network を提案して初めて multi-scale features を Object detection 用にネットワークに組み込んだ
- SSD(Liu et al.2016) は VGG16 の後半の層と追加した層からの feature map を multi scale な予測のために利用した
- FPN(Lin et al.2017a) は低い層から深い層への path を追加することでより強力な表現を得ることができた
- DSSD(Fu et al.2017) はコンテキスト(背景知識?)を集約して浅い層における high-level semantics を強化するための deconvolution layer を実装しました
- この文だけでは何言ってるか分からなくて、下記のリンクを参照しました
- リアルタイム物体検出向けニューラルネット、SSD(Single Shot Multi Detector)及びその派生モデルの解説 - verilog書く人
- SSD の feature exetractor (VGG + 追加層) に対しさらに deconv 層を足して浅い feature exetractor の層を深い層にも追加した
- RefineDet(Zhang et al.2018) は 2段階の cascade regression を適用することで、SSD の効率性を維持しながら精度がめっちゃ高くなった
- 1: featurizing image pyramids
5. Proposed Method
- M2Det は backbone と Multi-Level Feature Pyramid Network (MLFPN) を使って入力画像から特徴抽出を行っている
- SSD に似てる
- 密な bounding-box と category score を出力する
- その後 NMS をして最終的な結果を出力する
- Multi-Level Feature Pyramid Network (MLFPN) は以下の 3つのモジュールを含んでる
- Feature Fusion Module (FFM)
- Thinned U-shape Module (TUM)
- Scale-wise Feature Aggregation Module (SFAM)
- FFMv1 は backbone の特徴を統合することで意味的な情報を強化している
- 各 TUM は multi-scale features 群を出力し、TUM と FFMv2 を交互に適用することで multi-level で multi-scale な features を抽出している
- SFAM は scale 毎の feature concat と attention 機能を適用することで各 feature を集約して multi-level feature pyramid を作る
5.1 Multi-level Feature Pyramid Network
- ネットワーク全体図では MLFPN は 3つのモジュールから構成されれる
- 1: FFMv1 では base feature 生成用に shallow な feature と deep な feature を統合する
- 例: VGG16(Simonyan and Zisserman2015) の conv4_3 と conv5_3
- ココらへんは SSD とかでもよく出てくる
- これらは MLFPN 用の multi-level な意味的情報を得るのに役立つ
- 2: いくつかの TUM と FFMv2 を交互に重ねる
- 特に各 TUM は異なる scale の feature map をいくつか生成する
- FFMv2 では、base feature と前の TUM から得られた feature map 内で最も大きいものを統合する
- 統合された feature map は次の TUM の入力となる
- ただし最初の TUM は他の TUM からの事前知識がないので、 から学習する
- multi-level multi-scale features は下記のように計算される
-
- : base feature
- : 番目の TUM の 番目の scale の特徴
- : 番目の TUM の処理
- : FFMv1 の処理
- 3: SFAM で multi-level multi-scale features を統合
- scale をまたいだ concat
- channel-wise attention
- 1: FFMv1 では base feature 生成用に shallow な feature と deep な feature を統合する
5.1.1 FFMs
- FFM モジュールは M2Det 内の異なる level の feature を統合する
- 以下の操作を行う
- 1x1 Conv 層を使ってチャンネルを圧縮
- concat で各 feature map をまとめる
- 特に FFMv1 では backbone 内の scale の異なる 2つの feature map を扱うため、片方に対し upsample を適用して同じ scale にしてから concat する
- 一方 FFMv2 では base feature と一つ前の TUM で出力された最も大きな feature map を扱い、これらは同じ scale である
5.1.2 TUMs
- FPN(Lin et al.2017a) や RetinaNet(Lin et al.2017b) との違いとして TUMは 薄い U型構造となっている(下図)
- 薄い U型構造?🤔
- encoder は "3x3 convolution layers with stride 2" 連続でつなげてる
- decoder は これらを feature map として受け取る
- FPN(Lin et al.2017a) では last layer of each stage in ResNet backbone
- 私達はさらに upsample の後に 1x1 の Conv 層を足し、decoder での要素和をとることによって学習能力を高めかつ特徴の滑らかさを保った
- 各 TUM の decoder の出力は、ある level での multi-scale な feature となります
- 前から後ろの TUM にかけて low-level な特徴から deep-level な特徴を出力するようになる
5.1.3 SFAM
- 目的: 各 TUM から生成された multi-level multi-scale features を統合して multi-level feature pyramid に集約する
- SFAM は大きく分けて 2つのステップがある
- Step1: 同じ scale の feature をチャンネルも一緒に concat する
-
- 番目に大きい scale の特徴
- まとめられた各 feature pyramid は、各 level の feature を含んでいる
- ただし単に concat するだけでは不十分
-
- Step2: channel-wise attention module を使って有用なチャンネルを絞る
- SENet(Hu, Shen, and Sun2017) で使われた SE ブロックを使う
- squeeze step では GAP(Global Average Pooling) を使ってチャンネル別統計 を得る
- 次にチャンネルの依存関係を捉えるため 2つの FC(Fully Connected)層を使って attention を実現する
-
- : ReLU
- : シグモイド関数
-
- : 減衰率 (論文中では を使用
- で重み付けした最終的な出力は以下の通り
-
- 各 feature は rescale 操作によって強弱がついている
-
- Step1: 同じ scale の feature をチャンネルも一緒に concat する
5.2 Network Configurations (ネットワークの設定)
- M2Det では backbone を 2種類使った(同時ではない)
- backbone は ImageNet で pre-traine 済
- デフォルトの MLFPN は以下の構成
- 8 TUMs
- 各 TUM は 5 つの Conv 層と 5つの Upsample 層を持つ
- scale は 6つ
- 各 scale の TUM feature のチャンネルは 256 のみ(学習パラメータ数を減らすため)
- 画像サイズは 320, 512, 800 (SSD, RefineDet, RetinaNet を参考に)
- 6 つの pyramidal features に対し、それぞれ 2 つの Conv 層を加え、detection(location regression と classification ) をできるようにした
- 各 pyramidal feature の pixel に対し、6つの anchor と 3つの比率(ratios) で候補ボックスを定義した
- 上記候補ボックスに対する score のしきい値は 0.05 とした
- 後処理として線形カーネルを使った soft-NMS(Bodla et al.2017) を使ってより正確なボックスを残した
- しきい値を 0.01 とするとよりよい結果になったけど、推論時間がめっちゃ長くなったので実用上このしきい値は採用しなかった
6. Acknowledgements
「機械学習のエッセンス」を読んだ感想とかメモ
機械学習のエッセンス、読んだ同期からは「誤植ちょっと多すぎるけどそれもある意味学べる」とポジティブな意見もらったので買おうと思う
— ふぁむたろう (@fam_taro) 2019年1月10日
誤植多すぎてすいません
— 加藤公一(はむかず) (@hamukazu) 2019年1月10日
すみません。。。すみません。。。。ちゃんと買って学びきります
— ふぁむたろう (@fam_taro) 2019年1月10日
:;(∩´﹏`∩);:
先日同期から 機械学習のエッセンス -実装しながら学ぶPython, 数学, アルゴリズム- (Machine Learning) | 加藤 公一 | Amazon を推され、神(著者ご本人様)からの啓示圧力もいただきましたので、買って読みました。
以下に各所感や自分が読んだ際のメモを残します。 全実装は終わってないので注意
結論
- この記事読むくらい買うか悩んでるなら買いましょう
まあ 2,800 円(税抜き)なんて人生において許容誤差ですし
- 演習問題もちゃんとやりましょう
- 誤植はある(でも第一刷からに第二刷にかけてかなり減った)ので、数式まで追う人は気をつけましょう
- 地味にページめくる時にうるさいです
- 紙版ですとページめくるたびに表紙やカバーがギチギチ言うので、地味に気になります
- 図書館だと読めないなってくらいです
- どちらにしろ PC 叩くこと多いので図書館では読むことはなさそうですが
- プロフェッショナルシリーズとかはそんなことなかったので、気になってきます
個人的には各回帰(リッジ・ロッソ)や SVM の実装において必要となる式の導出から Python 実装までをカバーされていて非常に勉強になりました(Python 3 で動くということも大変ありがたいです)。
SVM 等は 2014〜2016 年頃(自身が修士の頃)ですと、僕の周辺では サポートベクターマシン入門 | ネロ クリスティアニーニ, ジョン ショー‐テイラー, Nello Cristianini, John Shawe‐Taylor, 大北 剛 | Amazon か パターン認識と機械学習 上 | C.M. ビショップ, 元田 浩, 栗田 多喜夫, 樋口 知之, 松本 裕治, 村田 昇 | Amazon を参考文献にしていたのですが、これらの文献は深いところまで記載されている一方、理論からコードに落とし込もうとすると「???」となって手が全く動かなくなることがあり、この本のように理論から実装につなげてくれる著書は無かった(見つけられなかった)です。当時欲しかったなあ
一方実装までカバーされている分、理論面では足りないところ(例えばカーネル SVM のカーネル部分とか)もあります。ですのでこの本読んでもっと知りたい気持ちを膨らませて上記の本とかにチャレンジするのが良いと思います。
あと演習問題もあってプログラミングに限らず手を動かす場面もあって良かったです。
この本を薦めたい人
- エンジニアやってきて、もう少しちゃんとキカイガクシュウシタイナーって人
- 理系学部1年生等の、線形代数や微積の授業やってて寝ちゃう人
- 使い途わかればもう少しちゃんとやれる人って結構いる気がするので
- 人工知能って単語にワクワクした大学生
- 行列系の数式読んでて「ウッ」となる人
- 数式から Python(numpy) コードに落とし込む際に「ウッ」となる人
この本を薦めない人
- 手を動かしたくない人
- この本に出てくる計算や演習問題・Python コードは自分で書いて動かしてなんぼなので
- 今買えば本文中のコードがそのまま動くのに動かさないのはもったいないです
- 紙版買ったらまず正誤表見て直した方が良いので、手を動かす前提でこの本は買いましょう
- この本に出てくる計算や演習問題・Python コードは自分で書いて動かしてなんぼなので
- サクッと概要だけ押さえたい人
- この本はほどよく深く(浅く)ほどよく広い(狭い)ので、広く浅く概要だけ掴みたい場合には不向きだなと思います
- モデル選択や細かいパラメータチューニングについて知りたい人
- 本書の目的にもある通りココらへんはあまり触れてません
- とりあえず Deep Learning を動かしたい人
- 著者も述べていますが、他に詳細な本がたくさんあります
- とはいえ著者が言う "この本が Deep Learning の理解に役に立つ"というのは同意します
各章の所感とか個人用メモ
前提
- Python の環境構築・基礎あたりはちゃんと読んでません
- 手元に環境あったので
- 自分の環境は Python 3.7 です
- 自分でコード書く時は以下の環境を都度都度(気分で)変えてやってました
- iPython
- jupyter notebook
- jupyter lab
- 自分でコード書く時は以下の環境を都度都度(気分で)変えてやってました
第1章「学習を始めるまえに」
- 本書の目的と本書が含まないものが載ってて良かったです
- 初めに必ず目を通すべき
第2章「Python の基本」
- 例外処理まで触れられてて良いなと思いました
- Python 3.6 からは
"a: {:2d}".format(a)
をf"a : {a:2d}"
で書けたりするので興味がある人はお試しください- "fstring" とか "フォーマット済文字リテラル" とかで調べると出てきます
- オブジェクト指向
- ここは深追いすると二度と帰ってこれなくなるので、これくらいの深度で十分だと思います
クラス=メソッド+データ
程度の理解だけ頭において先に進んだ方が良いです
第3章「機械学習に必要な数学」
- "ブロック化"とかたしかにそんな単語あった気がする…
- 機械学習に必要な線形代数と微積がピックアップされてるのすごくありがたい
- 対称行列(半正定値・正定値)やとかも、単語だけ覚えておいてまたどこかで出てきたらこの本とか他の詳しい本を見れるようにしておきたい
- 多変数関数の極値とヘッセ行列の関係は知らなかった…(一度聞いて忘れたのだと思われ)
- 二次形式の勾配の形はまれによく出るので知っておくと良い
第4章「Python による数値計算」
- 桁落ちとか有効桁数・誤差
- 忘れかけてたので良い戒めになった
- 機械学習続けてると "1e-8 の誤差とか知らんがな" と思う時が結構あったので
- 疎行列の扱い
- めっちゃ参考になりました
- 行とるか列をとるかで
crc_matrix
とcsr_matrix
を使い分ける - それぞれ
getrow()
とgetcol()
の効率が違う
- 逆行列・numpy の solver・LU分解を使った一次連立方程式の解法
- 個人的にすごく楽しかったです
- これまで必死に手計算で方程式を解いてきた人類にとっては、これってものすごく衝撃的だと思うんですよね
- 人によっては解放感とか爽快感があると思います
大学デビューとはかくあるべき
- データの可視化
- 僕自身細かい文法忘れることが多いので、たまにこの本とかに帰ってくる気がしてます
- 数理最適化
- 今後機械学習やるなら絶対押さえなきゃいけないところ
- 線形計画法や2次計画法等の解析的に解ける(≒式変形等で解ける≒手計算で解を出せる)問題から解析的に解けない 問題に対しどのように解を出そうとしているかが載っています
- 解析的 - Wikipedia
- そして現在の機械学習では多くが解析的に解けない問題を扱っています
- 最急降下法とニュートン法について以下の違いは押さえておきましょう
- 更新式
- 収束条件
- "数値微分に関する補足" も地味に大事なお話だなと思いました
- ラグランジュの未定乗数法
- チッ…はいはいラグランジュラグランジュ
- 議論の抽象度的にはここ結構難しかったです…
- きついと思ったら一旦軽く流して先に進んでも良いと思います
- 気になったら他の文献とかまたここに戻ってくれば良いですし
- 統計
- ここも高校までは手計算地獄だった分「数行で書けちゃう俺Tueeeee」できたりして楽しかったりします
- 後半は数式多めだけど大事なので体力ある人は追いましょう
第5章「機械学習アルゴリズム」
この本のメインテーマ(だと思ってます)
- 準備
- 回帰と分類の違いは押さえておきましょう
- インターフェースについては、ここで押さえておくと他のライブラリを使った時なども楽になれます
- 回帰
- なにを最適化(最小化 or 最大化)しようとしているのかは押さえましょう
- 3次元空間でのプロット法が載ってるのすごくありがたいです
- 外部データを自分で持ってきて読み込ませるのは大事な経験なので初めての人は必ずやりましょう
- 評価指標は必ず押さえてください
- リッジ回帰
- 汎化と過学習
- 交差検証(クロスバリデーション)はめっちゃ大事。めっちゃ大事
- ラッソ回帰
- 線形回帰 + 正則化項(L1)
- 線形回帰・リッジ回帰と何が違うのか
- 座標降下法(corordinate descent) を絶対値関数にどう適用するか
- 必要な式変形(うまく j=k の部分のみ抜き出せるか等)
- 上記の実装部分
- ロジスティック回帰
- 回帰と分類がつながる箇所
- ココらへんも式変形が続くので、気を抜いて一行飛ばしたりすると訳分からなくなるので注意
- 式変形が長いと変形ばかり気にして何をしようとしているのか頭から抜けちゃうのも注意
- サポートベクターマシン(要実装)
- k-Means 法
- SVM 超えた方にとってはボーナスステージ
- 主成分分析(PCA)
- どうして固有値が出てくるのか押さえる
- イメージ図がなくてイメージしきれない人も多いので自分で調べてみると良いです
- 僕が読んだ中では scikit-learnとTensorFlowによる実践機械学習 | Aurélien Géron, 下田 倫大, 長尾 高弘 | Amazon は比較的分かりやすかったです
- 適当にググっても良いと思います
- どうして SVD が出てくるのか押さえる
個人用メモ(コード周り)
第4章「Python による数値計算」
1次連立方程式の解法の比較(逆行列・numpy.linalg.solve・scipy.linalg.lu_factor)
この規模の小ささですと numpy.linalg.solve
が最も速かったですが、
行列が大きくなったり b
が複数列になってくると LU 分解(lu_factor) が速くなってくるのだと思います。
In [1]: import numpy as np In [2]: a = np.array([[3, 1, 1], [1, 2, 1], [0, -1, 1]]) ...: b = np.array([1, 2, 3]) In [3]: np.linalg.inv(a) @ b Out[3]: array([-0.57142857, -0.14285714, 2.85714286]) In [4]: np.linalg.solve(a, b) Out[4]: array([-0.57142857, -0.14285714, 2.85714286]) In [5]: from scipy import linalg as slinalg In [6]: lu, p = slinalg.lu_factor(a); slinalg.lu_solve((lu, p), b) Out[6]: array([-0.57142857, -0.14285714, 2.85714286]) In [7]: %timeit np.linalg.inv(a) @ b 13.2 µs ± 968 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) In [8]: %timeit np.linalg.solve(a, b) 8.03 µs ± 79.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) In [9]: %timeit lu, p = slinalg.lu_factor(a); slinalg.lu_solve((lu, p), b) 28.4 µs ± 569 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each) In [10]: %timeit slinalg.lu_solve((lu, p), b) 17.5 µs ± 96.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
第5章「機械学習アルゴリズム」
ラッソ回帰
import numpy as np import csv def soft_thresholding(x, y): return np.sign(x) * max(abs(x) - y, 0) class Lasso: def __init__(self, lambda_, convergence_thres=0.0001, max_iter=1000): self.lambda_ = lambda_ self.convergence_thres = convergence_thres self.max_iter = max_iter self.w_ = None def fit(self, X, t): n, d = X.shape self.w_ = np.zeros(d + 1) avg_L1 = 0. for _ in range(self.max_iter): avg_L1_prev = avg_L1 self._update(n, d, X, t) avg_L1 = np.abs(self.w_).sum() / self.w_.shape[0] if abs(avg_L1 - avg_L1_prev) <= self.convergence_thres: break def _update(self, n, d, X, t): self.w_[0] = (t - (X @ self.w_[1:])).sum() / n w0vec = np.ones(n) * self.w_[0] for k in range(d): ww = self.w_[1:] ww[k] = 0 q = (t - w0vec - (X @ ww)) @ X[:, k] r = X[:, k] @ X[:, k] self.w_[k + 1] = soft_thresholding(q / r, self.lambda_) def predict(self, X): if X.ndim == 1: X = X.reshape(X.shape[0], 1) Xtil = np.c_[np.ones(X.shape[0]), X] return Xtil @ self.w_ def main(): # Read data Xy = [] with open("winequality-red.csv") as fp: for row in csv.reader(fp, delimiter=";"): Xy.append(row) Xy = np.array(Xy[1:], dtype=np.float64) # Split train & test data np.random.seed(0) np.random.shuffle(Xy) n_test = 1000 train_X, train_y = Xy[:-n_test, :-1], Xy[:-n_test, -1] test_X, test_y = Xy[-n_test:, :-1], Xy[-n_test:, -1] # Show results reach hyper parameters for lambda_ in [1., 0.1, 0.01]: model = Lasso(lambda_) model.fit(train_X, train_y) y = model.predict(test_X) print(f"--- lambda: {lambda_} ---") print("coefficients:") print(model.w_) mse = ((y - test_y) ** 2).mean() print(f"MSE: {mse:.3f}") if __name__ == '__main__': main()
機械学習エンジニアに転職して4ヶ月が経ちました
注意事項
- 本記事は転職ポエムになります
- 1/3 の純情なエモさです
- このポエムを読んでもあなたの Python コードは 1行も進みません
- これは個人の意見であり、会社の見解を代表するものではありません
- 見返したら SES dis 色が強かったです
- そんなつもりは無かったんです :;(∩´﹏`∩);:
結論
- 転職活動はしたほうが良いけどとても疲れます
- 転職するかは別
- 機械学習周りの市場は活気づいてます
- アウトプットゎ大事です
導入
この会社に機械学習系エンジニアとして転職し気づけば 4ヶ月となりました。
転職活動時の気持ちや転職してみた感想を、忘れる前にここに残そうと思います。
このポエムが転職を考えている人や機械学習エンジニアに興味がある人にとって有用な1サンプルになれば幸いです。
著者情報
- 2016年度情報系院卒
- 学部・院卒時は NLP やってました
- 今回の転職活動時は 27歳でした
- 現在 3社目
なんで転職したのか
- 特定ドメインでの機械学習をしてみたくなったから
- HR かライフサイエンスの領域で
- 自身の裁量でいろいろ挑戦してみたかったから
- SES 常駐マンにそんな裁量はないです
- 常駐先の良し悪しの問題ではなく、契約上他社の人間に裁量与える訳ないだろってだけの話です
- 請負じゃないし責任の取りようもないので
- とはいえ常駐先の上司や社員の方には可能な限りいろんなことをやらせていただいたので本当に感謝しています
- マシンスペック良かったですし(RAM 32GB)
- SES 常駐マンにそんな裁量はないです
- 心の底から SES 会社は不要だなと思ったから
- 中抜きしてるだけにしか見えなかった
- 常駐先の数々のリスクの投げ先になってるだけにしか見えなかった
- 賃金・スキル的に伸び代を感じられなかったから
- 僕は 10, 20 年のスパンで見たときに OracleDB チューニングには未来を感じませんでした
- 加えて SES で働き続けると SES 以外に転職できる気がしなかったのもあります
- 働きづらかったから
- 以下は全 SES のお話ではなく前職の本社のお話です
- 勤怠管理サービス使ってなかった
- もちろん Excel 大活躍でした
- 会社(常駐先ではなく本社)の文化に対し馴染みきれなかった
- 社長と上司に年賀状送ったほうが良い
- 忘年会とか社員旅行行かないと「評価に値しない」とか定例で言われる
- 常駐先固有の休日なのに僕の有給が強制消費される
- 他の会社だと公休扱いだし、せめて休むか本社で作業するか選ばs(
- 若手が病気で休養すると議事録でお叱りを頂ける
転職活動について
いつからいつまで
- 2018年4月下旬〜7月上旬(3ヶ月)
- GW 中はほとんどしてませんでした
何社ぐらい受けたか
- 30 社ぐらい
- 面談以降(書類選考含め)に進んだもののみカウントしてます
- 書類で落ちた会社も含まれます
- サイトでイイね押しただけの会社含むなら倍ぐらいになります
これなんて出会い系サイト
- 週3ペースで面接してた気がします
- 非常にきつかったのでおすすめしません
- 面談以降(書類選考含め)に進んだもののみカウントしてます
正直この数は多すぎたと思います。 今回はいろんな会社を見たかったのでこれだけ多く受けてみましたが、 平日は面談とか面接で埋まりがちで肉体・精神的に辛かったです。
加えて下記の Green や Paiza を使うと、①日程調整は自分で行う必要がある・②企業によって選考結果や日程の通知に時間かかる場合があるため、Google カレンダー上のほとんどの平日が候補日で埋まりました。
ですので希望条件とか志望動機をしっかり固めた方は、応募する会社数を絞った方が良いと思います。
どの転職サービス使ったか
- Green・Paiza・エージェントによる紹介(Team AI)を使いました
- 今の会社は エージェントによる紹介 で入社しました
- Team AI は以前勉強会に出てお世話になった縁で使いました
- 1 社だけ直接応募しました
- 初めての転職ではワークポート・リクナビ・doda を使いました
- 以下の理由から今回は使いませんでした
- 紹介する会社が微妙・広く浅い紹介が多い
- 最終面接付近(面接前や内定後)で辞退するとめっちゃ電話かけてきて説得してきた
- 30分ほど
説教説得されたのは思い出です
- 30分ほど
- 電話が多くて時間とられた
- よく知らない他人に任せる気になれなかった
- 業種をまたぐような転職ならありかもしれません
- エージェントガチャがある
- そもそもエージェントはその人の転職先での年収割合分の成功報酬をもらうことが多いので、年収高いところ行けバイアスが強いです
- 年収上げたいだけの方はエージェント使う選択肢もありだと思います
- ですがその時の採用にかかった費用は回り回って自分に来るものだと思います
- 年収上げたいだけの方はエージェント使う選択肢もありだと思います
- 以下の理由から今回は使いませんでした
以下に今回お世話になった各サービスの比較を記載します。
サービス | 良い点 | |
---|---|---|
Green | ●完全広告型なので、エージェントが一切絡んで来ない(内定時は絡むかも?) ●ベンチャー気質(ベンチャーとは言っていない)な会社が多く、他のサービスだと書類が通らないような魅力的な企業と面談できた ●代表とお話できる機会が多かった(代表は大抵熱量あるから刺激や学びになった) ●ほんとにいろんな企業を見れる 魅力的な人事も多数いました |
●面談の概念が企業によってバラバラ(ただの面接の場合あり) ●企業によってはこちらの状態(面談前・面接後とか)を選考中に変えないので、面談のフィードバックが書けない(しかもそういうところに限ってクソみたいな面接してくる) ●ミスマッチすぎる企業とも面談することが結構あった(なんで僕を通した?) |
Paiza | ●途中までエージェントが絡んでこない ●コーディングテスト楽しい(A しか取れない雑魚でしたが) ●日程調整がシステム上でできる ●エンジニアが気になる情報はしっかり載せてあった(開発環境とか) ●面接後企業からフィードバック(良い点悪い点)をシステム上でもらえる |
●面接を進めると、急にエージェントがしゃしゃり出てきて電話とかで時間を奪ってくる ●企業からのフィードバックがためにならない場合がある(良い点:なし、とか)のに、こちらのフィードバックが適当だとエージェントに追求される場合がある ●コーディングテストで時間取ったのに、結局技術面接とか事前課題で時間取られる(意味ない)、想定年収も全く現実に寄与しない ●中の人のブログがアレ(煽るのうまいっすね) |
Team AI (エージェント) | ●機械学習系の勉強コミュニティ発なのでそこらのエージェントより精通してる ●機械学習扱っているところを中心に紹介してもらえる ●代表の石井さんに対応してもらえる(今は分かりません) ●転職活動中はメールで細かくやりとりしてくれた |
●システムではなくメールでのやり取りしかない ●そのため日程調整周りでグダグダになることが比較的多かった ●こちらの内定後の対応が雑(最低限のやり取りしかしたくない人にとっては良いかもしれません) ●応募者のキャリアを考えるというよりも、企業紹介に重きをおいている(これも最低限n) |
直接応募 | ●(上手くいく or 優秀な人なら)内定まで一瞬で決まる ●企業からすると採用コストを抑えられる |
●(僕みたいな)微妙な人だと面接後めっちゃ待たされたり対応が雑、人事によるのかもですが |
Green は良くも悪くもガチャって感じがしましたし、 そのような感覚でやってるなと思う人事の方もいらっしゃいました。 とはいえここ受けて良かったと思えるくらい素敵な企業も一定数ありました。
Paiza は初めて利用する場合、コスパ悪い(かけた時間の割にという意味で)なと感じました。 しかし一度スキルチェックを終えれば当分使えそうなのと、エンジニアとして気になる部分(開発環境等)は詳しく載っていることが多かったので、エンジニアとして転職するなら使って良いと思いました。
機械学習しかしたくない & エージェントでも OK な場合は、Team AI(エージェント)を使ってみて良いと思います。
ベース高めの人はビズリーチ使っても良い気がします。 もしくは LinkedIn もありかもしれません。
転職活動において、やって良かったこと
- 在職しながら転職活動した
- 1社目はつらすぎて転職先決まる前に辞めてしまったのですが、転職先が無いため非常に焦りました
- 実家に住んでても焦ったので、一人暮らしとか家庭持ちだともっと焦ると思います
- 自分が納得できることより早く手に職つけることを優先してしまいました
- 在職中だと心に余裕を持って活動しやすかったです
- 1社目はつらすぎて転職先決まる前に辞めてしまったのですが、転職先が無いため非常に焦りました
- 面接のときに背筋を伸ばす
- 4,5 社ほど面接受けてから、自分が猫背であることに気づきました
- 気持ちハキハキ喋れます
- アウトプットを残した
- 機械学習系の論文を読んで実装した
- これは5月下旬辺り(転職活動始めて1ヶ月ほど経ってから)から始めました
- 上記の経歴に加え雑魚修論だったので、企業からするとよくいる機械学習エンジニアワナビー以外に評価のしようがなかったのだと思います
- これやってから結構機械学習面で一定の評価(高いとは言っていない)を得やすくなったと気がします
- 特にベンチャーとかですと人育てるほど整ってないので「環境与えれば勝手に学んでいきそうか」は必ず見られると思います
- 必ず選考通るとは言っていない
- 今なら arxiv に行けば実装未公開な NN が腐るほどあるし、 PyTorch という人間味溢れたパッケージ もあるので是非実装して記事とかで紹介お願いします
- kaggler ならメダルとって実装 github に載っけた方がはやいです
- それ通じない企業は辞退した方g(
- 年収についてほとんど考慮しなかった(要注意)
- 今回は優先順位が低かっただけです
- (それでも若干上がった不思議)
- 上げるほどのスキルがなかったとも言います
- このキャリアパスで年収あげようとするとろくなところ行けそうになかったです
- 一応 +100万ぐらいで提案してくださる企業もいました
変な企業とか SES だったけどネ!
- 選考中は「もし 5,000兆円手に入れてもこの会社で働き続けたいと思うか」を意識していました
- これを確認するためにも誰か 5,000 兆円ください
- 今回は優先順位が低かっただけです
今回の転職活動をして良かったこと
- いろんな企業を見れた
- 企業を見る目が養われた
- 今回応募した中で魅力的に感じた企業の多くが、その後追加で資金調達したりステージを上げたりしてました
- ですので世間並には企業を見れるようになったのかなと判断しました
- (今の会社もしてます)
- 結構嬉しかったです
- 今回応募した中で魅力的に感じた企業の多くが、その後追加で資金調達したりステージを上げたりしてました
- この市場の活気さを肌で感じられた
- 自身の市場価値(僕の場合はその無さ)を測れた
- 相手企業というフィルター越しではありますが、自身の価値ってどこにあっていくらぐらいあるのか知れたのは貴重な機会でした
- 漠然とではありますが、こうすれば(なれば)市場価値上がりそうという目安も分かったので良かったです
- 今の企業に転職できた
今回の転職活動を通した所感
- tensorflow 民が多かった
- 「tenslorflow できんの?」に近い質問は多かったです
- この時点ではまだ Define and Run が激強だったのかもしれません
- 2018年春夏段階だったからかも
- 修論提出させるところが以外とあった
- ゴミ修論でほんとごめんなさいって気持ちになりました
転職して 4ヶ月経ったけどどう?
日々転職して良かったなと思ってます(ポジトーク並感)。
機械学習エンジニアとして働いてみて、「機械学習界隈進歩速すぎ」「英語力雑魚すぎ」「ドメイン知識無さすぎ」「kaggle 雑魚すぎ」てキツイなと思うことは多々あります。 それでも自身の手でモデルを動かしたとき、様々な場面で社会実装されたりすごいモデルが出てくるのを見たとき、自身の工夫が活きたとき等のワクワク感は得難いものであり、これらのおかげで日々ワクワクしながら働くことができています。
現職の会社については、前職より非常に良くなりましたが、不満はまだあります。 しかしそれらを共有したり発言できる土台や、むしろ「僕が解決してあげないと(オタサーの騎士並感)」や「やってみよう・試してみよう」と思えるような社員の雰囲気や会社の文化があるため非常に好ましく、僕自身も引き続き維持できるように気をつけたいと思っています。 (あとフリードリンク・フードは大好きなので引き続き残して欲しいです)
まだまだスキル面・人間力面的に足りないことだらけなので引き続き頑張ります。
おまけ
今回の転職活動で出会えた個性的な企業 (or 人事) について
ここからはただの苦しい苦しいネガキャンです。
以下の企業様は今回応募した中の一部であり、ほとんどの企業様は応募して良かったと
思っていますのでその点ご留意ください。
- 適性テストという名目で1時間近く百マス計算的なことを課してくる企業様
- 正確には鉛筆片手に (a + b) % 10 を 1時間近くさせられました
- 僕は確かに機械学習エンジニアという名目で応募したのですが…
- このようなことをさせないためにエンジニアがいるのだと僕は思います
- ちなみにこの転職期間中において最も無駄な 1時間でした
- ここに入社すれば 刺身にタンポポ乗せる仕事 を経験できそうでした。ただし僕には適性が無かったようです
- 面接の雰囲気と選考結果が 180度違う企業
- 「あれ?違うな」くらいなら結構あったのですが 180度違う企業様は初めてでした。是非そのギャップは誇ってください
- そしてできれば御社の紹介欄に記載いただきたく。でないと僕みたいなのが応募して凹むので
- Paiza の応募者評価項目の記入欄が本当に自由記入欄なのg(ry
- 「あれ?違うな」くらいなら結構あったのですが 180度違う企業様は初めてでした。是非そのギャップは誇ってください
- 全力でマウント取ってくる自称 PM
PyTorch-Ignite で学習用コードをスマートにする
- 12月25日
- Early Stopping、モデルの保存ができるように train と main を変更しました
皆さんこんにちは。みなさんメリークリスマス☆茜ちゃんだよ☆
今回は PyTorch 用のライブラリである PyTorch-Ignite(https://github.com/pytorch/ignite) を使って Training 用のコードを簡潔に書けるようにします。
本記事のキーワード
- PyTorch
- Ignite
- MNIST
本記事の対象
- 何度か PyTorch のコードを書いてきてもう "for input in XXX_loader" は飽きてきた方
- 大体似たような Training 用のコードを書いている方
- Training 部分についてある程度のテンプレートを身につけたい方
- Ignite という響きに惹かれた方
本記事の対象でない方
- まだ PyTorch を始めたばかりの方
- 機械学習を始めたばかりの方
- Training 周りのラッパーを全てご自分で用意されている方
- 各バッチやデータ毎に細かい処理を行いたい方
Ignite とは
PyTorch の Training 周りをスッキリ書くためのライブラリです。 Training 周りに絞ってあるので、試しやすそうです。
例えば kaggle や業務等で、モデルや学習率をざっくばらんに試したいときに使いそうですね。
Ignite Documentation — ignite master documentation github.com
- 公式 Document の訳
- Ignite は PyTorch の Training 周りに絞ったライブラリ
- 各 metrics や earlystopping、model の保存などを含めた Training loop を扱えるよ
上記は公式画像の Document 内にありましたが、学習用コードがスッキリしてます。
使ってみる
https://github.com/pytorch/ignite/blob/master/examples/mnist/mnist.py と https://github.com/pytorch/ignite/blob/master/examples/mnist/mnist_with_tensorboardx.py を元に MNIST 用の Training コードを書いてみます。
Python のバージョンと必要なライブラリ
- Python 3.6.5
- 3.6 以降じゃないと f-Strings 使えません
今回は以下のライブラリを使いました。
特に pytorch-ignite はちゃんと "pip install pytorch-ignite" でいれましょう。 ("pip install ignite" だと違うものが入ります)
pytorch-ignite 0.1.2 tensorboardX 1.4 torch 0.4.1 torchvision 0.2.1
データセット
今回は MNIST を使います。 自分で行う場合は別途 Dataset を定義しましょう。 ここでついでに DataLoader も定義します。
from torch.utils.data import DataLoader from torchvision.datasets import MNIST from torchvision.transforms import Compose, ToTensor, Normalize def get_data_loaders(train_batch_size, val_batch_size): data_transform = Compose([ToTensor(), Normalize((0.1307,), (0.3081,))]) train_loader = DataLoader(MNIST(download=True, root=".", transform=data_transform, train=True), batch_size=train_batch_size, shuffle=True) val_loader = DataLoader(MNIST(download=False, root=".", transform=data_transform, train=False), batch_size=val_batch_size, shuffle=False) return train_loader, val_loader
モデル
今回は参考サイトのままシンプルなネットワークを用います。 使ってみたいモデルがある人は是非ここで定義しましょう。
import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self, num_class=10): super(Net, self).__init__() self.num_class = num_class self.conv1 = nn.Conv2d(1, 10, kernel_size=5) self.conv2 = nn.Conv2d(10, 20, kernel_size=5) self.conv2_drop = nn.Dropout2d() self.fc1 = nn.Linear(320, 50) self.fc2 = nn.Linear(50, self.num_class) def forward(self, x): x = F.relu(F.max_pool2d(self.conv1(x), 2)) x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2)) x = x.view(-1, 320) x = F.relu(self.fc1(x)) x = F.dropout(x, training=self.training) x = self.fc2(x) return F.log_softmax(x, dim=-1)
train に必要な関数の定義
早速 train 本体を記述したいのですが、その前に必要になる関数をここで定義します。
write_metrics()
は評価値をログに保存するついでに print もするための関数score_function()
は validation_loss をignite.handlers.EarlyStopping
オブジェクトに渡すために変換する関数ignite.handlers.EarlyStopping
は、与えたスコアが上がった場合に「スコアが改善した」と判断するため
def write_metrics(metrics, writer, mode: str, epoch: int): """print metrics & write metrics to log""" avg_accuracy = metrics['accuracy'] avg_nll = metrics['nll'] print(f"{mode} Results - Epoch: {epoch} " f"Avg accuracy: {avg_accuracy:.2f} Avg loss: {avg_nll:.2f}") writer.add_scalar(f"{mode}/avg_loss", avg_nll, epoch) writer.add_scalar(f"{mode}/avg_accuracy", avg_accuracy, epoch) def score_function(engine): """ ignite.handlers.EarlyStopping では指定スコアが上がると改善したと判定する。 そのため今回のロスに -1 をかけたものを ignite.handlers.EarlyStopping オブジェクトに渡す """ val_loss = engine.state.metrics['nll'] return -val_loss
train 本体の定義
ここで train する部分を記述します。 これまで頑張って以下のような for 文を書いていた部分です。
train(**args): for i, input in enumerate(train_loader): ...
これを pytorch-ignite を使うと以下のように書けます。
def train(epochs, model, train_loader, valid_loader, criterion, optimizer, writer, device, log_interval): # device: str であることに注意 # この時点では Dataloader を与えていないことに注意 trainer = create_supervised_trainer(model, optimizer, criterion, device=device) evaluator = create_supervised_evaluator(model, metrics={'accuracy': Accuracy(), 'nll': Loss(criterion)}, device=device) @trainer.on(Events.ITERATION_COMPLETED) def log_training_loss(engine): i = (engine.state.iteration - 1) % len(train_loader) + 1 if i % log_interval == 0: print(f"Epoch[{engine.state.epoch}] Iteration[{i}/{len(train_loader)}] " f"Loss: {engine.state.output:.2f}") # engine.state.output は criterion(model(input)) を表す? writer.add_scalar("training/loss", engine.state.output, engine.state.iteration) @trainer.on(Events.EPOCH_COMPLETED) def log_training_results(engine): evaluator.run(train_loader) metrics = evaluator.state.metrics write_metrics(metrics, writer, 'training', engine.state.epoch) @trainer.on(Events.EPOCH_COMPLETED) def log_validation_results(engine): evaluator.run(valid_loader) metrics = evaluator.state.metrics write_metrics(metrics, writer, 'validation', engine.state.epoch) # # Checkpoint setting # ./checkpoints/sample_mymodel_{step_number} # n_saved 個までパラメータを保持する handler = ModelCheckpoint(dirname='./checkpoints', filename_prefix='sample', save_interval=2, n_saved=3, create_dir=True) trainer.add_event_handler(Events.EPOCH_COMPLETED, handler, {'mymodel': model}) # # Early stopping handler = EarlyStopping(patience=5, score_function=score_function, trainer=trainer) # Note: the handler is attached to an *Evaluator* (runs one epoch on validation dataset) evaluator.add_event_handler(Events.COMPLETED, handler) # kick everything off trainer.run(train_loader, max_epochs=epochs)
ポイントとしては以下の通りです。
create_supervised_trainer()
で trainer を定義create_supervised_evaluator()
で evaluator を定義- これは train_loader にも valid_loader に対しても使えます
@trainer.on(<実行したいタイミング>)
で各処理を定義した関数をデコレートする- デフォルトでは以下のタイミングに処理を挟み込めるそうです(https://pytorch.org/ignite/engine.html#ignite.engine.Events)
COMPLETED
EPOCH_COMPLETED
EPOCH_STARTED
EXCEPTION_RAISED
ITERATION_COMPLETED
ITERATION_STARTED
STARTED
- 上記の通り大体実行したいタイミングは網羅してそうです
- デフォルトでは以下のタイミングに処理を挟み込めるそうです(https://pytorch.org/ignite/engine.html#ignite.engine.Events)
- 実行したいイベント(モデルの保存や EarlyStopping)は trainer や evaluator に
add_event_handler()
で追加する
また ModelCheckpoint()
によって学習途中のパラメータを保存できるようにしています。
これが 2行で書けるのは嬉しいです。
加えて n_saved
によって保存する直近のパラメータの個数を制限できるのも地味に嬉しいです!
さらに今回はコンペを意識して EarlyStopping
を導入しました。
注意事項としては evaluator
に対して追加していることと、実行するタイミングが Event.COMPLETED
になっていることです。
main 関数
main 関数では train() の実行に必要なものを定義します。 コマンドライン引数や config ファイルの読み込みもここで定義すると良いと思います。
ポイントでは、学習結果を見るために tensorboardX を使っていることぐらいです。 もし他に logger を使っている方はそちらでも可能です(ただし train を修正する必要あり)。
あとは Early Stopping を確認するために epochs=100
と大きめに設定していることに注意してください。
import torch import torch.nn.functional as F import torch.optim as optim from tensorboardX import SummaryWriter from model import Net from dataset import get_data_loaders from train import train def main(): # 定数 epochs = 100 train_batchsize = 128 valid_batchsize = 4 log_interval = 50 device = "cuda" if torch.cuda.is_available() else "cpu" # 各学習に必要なもの model = Net(num_class=10) train_loader, valid_loader = get_data_loaders(train_batchsize, valid_batchsize) criterion = F.nll_loss optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9) log_writer = SummaryWriter('./log') # 学習開始 train(epochs=epochs, model=model, train_loader=train_loader, valid_loader=valid_loader, criterion=criterion, optimizer=optimizer, writer=log_writer, device=device, log_interval=log_interval) # モデル保存 torch.save(model.state_dict(), './checkpoints/final_weights.pt') log_writer.close() if __name__ == '__main__': main()
学習実行
以下のように Epoch が回れば OK です。
僕が回したときは epochs = 100
に設定したにも関わらず epoch[23]
で学習が終わったので
ちゃんと early stopping されていることが確認できました。
$ python main.py <省略> Epoch[2] Iteration[1450/1875] Loss: 0.17 <省略> Epoch[23] Iteration[200/469] Loss: 0.07 Epoch[23] Iteration[250/469] Loss: 0.05 Epoch[23] Iteration[300/469] Loss: 0.24 Epoch[23] Iteration[350/469] Loss: 0.06 Epoch[23] Iteration[400/469] Loss: 0.12 Epoch[23] Iteration[450/469] Loss: 0.08 training Results - Epoch: 23 Avg accuracy: 0.99 Avg loss: 0.03 validation Results - Epoch: 23 Avg accuracy: 0.99 Avg loss: 0.03
学習が終わると以下のディレクトリが新しくできているかと思われます。
- checkpoints
- 学習中と学習後のモデルのパラメータが格納されています
- 私が確認したときは以下のファイルがあり、
final_weights.pt
を除くとちゃんとn_saved=3
が反映されていることが確認できましたfinal_weights.pt
sample_mymodel_18.pth
sample_mymodel_20.pth
sample_mymodel_22.pth
- log
- 学習結果が格納されています
- raw、processed
- これは MNIST のデータです(ですので他の Dataset を使った場合は発生しません)
学習結果の確認
$ tensorboard --logdir log
その後該当ページ(デフォルトですと localhost:6006) にアクセスして下記のようなグラフが見れれば OK です!
まとめ
- 思ったより自分で定義することが多くてびっくりしました😇。
- ただし Training 周りをスッキリさせることができ、導入する価値はあるなと思いました(特に for 文周り)。
- Early Stopping やモデルの保存はちゃんとカバーされてて地味に嬉しかったです
- 特に PyTorch をある程度書いてきて Training 周りのコードが整理しきれてない人は、テンプレートを知るという意味でも触る価値があるかと思います
- 今回は触れませんでしたが、example を確認すると pytorch-ignite は GAN や 強化学習にも対応しており 非常に自由度の高いライブラリであることが確認できています
これを使って fine-tuning のテンプレートを作ってみたいなと思いました。
ぜひ皆さんも触ってみてください!
ウチもやったんだからさ
今後確認しておきたいこと
- PyTorch 1.0 対応
- Multi GPU 対応
- より細かい操作
- 他のロスや出力に softmax 等がかかっていないときの対応