AI_ML_DL’s diary

人工知能、機械学習、ディープラーニングの日記

Kaggle散歩(February 2021)

Kaggle散歩(February 2021)

HuBMAPコンペは3月26日が最終日。(日本時間:3月27日午前9時00分)

2月3日追記:最終日は新規データが追加されてから2か月後とのこと、現時点で新規データは追加されていないため、4月2日以降になることは確実。

2月24日追記:データの更新はまだのようだ。最終日はデータ更新から2か月後との方針に変わりなければ、最終日は4月末。

 

2月1日(月)

HuBMAP

昨日、efficientnet-UnetのB5, B6, B7, B8について、同一条件で計算した結果、LBスコアは、B5: 0.831, B6: 0.831, B7: 0.829, B8: 0.809となった。efficientnet-Unetを用いている公開コードでは、B4またはB5がベスト、となっているようである。スコアの大小関係は、画像サイズやaugmentationの複雑さなどによって変わる可能性があるので、いまは、どれがよいとはいえない。最終的には、public_LBではなく、private_LBだということも頭に入れておかないといけない。

DiceLoss, LovaszLoss, JaccardLoss, FocalLossなどを使って計算し、BCEWithLogitsLossとの比較を行ったところ、LBスコアは次のようになった。

BCE: 0.829, DiceLoss: 0.794, LovaszLoss: 0.830, JaccardLoss: 0.832, FocalLoss: 0.833

DiceLossのみ、他と少し違っている。なぜだろう。

明日は、segmentation modelの比較をやってみよう。

GPUの残り時間が7時間程度になったので、encoderを中くらいのefficientnetB4にして、Unet、Unet++, MAnet, Linknet, FPNなどのモデルの計算をしてみよう。

 

2月2日(火)

HuBMAP

efficientnetB4をEncoderにして、Unet, Unet++, MAnet, FPNのモデルについて計算したところ、LBスコアは、次のようになった。

Unet: 0.832, Unet++: 0.823, FPN: 0.830, MAnet: 0.825

もっと違った結果を予想(期待)していたのだが、どんぐりの背比べといったところか。

各モデルのパラメータは、ほぼ、デフォルトのままで、最適化していないので、今は動作確認しているだけ、ということにしておこう。

そんなことを言っている場合ではないかもしれない。

今日はBCELossを使ったのだが、この課題のmetricsはmean Dice coefficientなのだから、DiceLossを使ったほうが良かったのかもしれない。

しかし、それで違いが現れるかどうか、期待しているような結果が得られるかどうかはわからない。

さて、GPUの割当時間の残りが3時間くらいになったので、明日から3日間は、機能アップのためのコードを探して組み込もう。

Loss関数の組み合わせ(BCEとDice)は今日組み込んだ。

DiceLossとLovaszLoss, JaccardLoss, FocalLossなどとの組み合わせもテストできるように組み込んでおこう。

あとは、TTA、pseudo labelの作成と訓練、モデルのアンサンブルなどが課題となる。

最新のDiscussionから2つのことがわかった。1つは、データの更新が遅れていること(1月中旬の予定だった)で、2つめは、データ更新の2か月後が締め切りとなる予定とのことだから、締め切りは4月になりそうだということ。

Kaggleスタッフからの1か月前の情報だが、20個のデータが全て公開され、新たに10個のprivate_dataが追加されるとのことなので、訓練に使えるデータが増えることになる。これは、正確さ向上に役立つのだが、増えたデータを有効に使いこなす能力が問われることになり、使える計算資源が限られる者にはハンディーとなる可能性がある。しかしながら、計算資源は同じはずなのに、次元の違う結果を出す人もいる。どのコンペだったか忘れたがデータ量が多くて扱えないと悲鳴があがっていたとき、高速処理ができるパッケージやモジュールやツールが紹介されていた。コンペではあらゆる能力が試されている。不可能を可能にする能力が求められている。

 

2月3日(水)

HuBMAP

今日はLossの組み合わせと、TTAを実現しよう。

Effb4-Unetについて、BCEとDiceとLovaszとJaccardとFocalを等分に混合したLossを適用してみた。その結果、BCE単独のLBが0.832であったのに対し、0.827となった。結果はともかく、動作しているようだ。

中身がわからないままではだめなので、Lossについて学ぼう。

FocalLoss:Focal Loss for Dense Object Detection
Tsung-Yi Lin, Priya Goyal, Ross Girshick, Kaiming He, and Piotr Doll´ar

f:id:AI_ML_DL:20210203105733p:plain

f:id:AI_ML_DL:20210203115123p:plain

これが、FocalLossのパラメータ、alphaとgammaだろうと思う。

違うかもしれないな。

 

昨日「この課題のmetricsはmean Dice coefficientなのだから、DiceLossを使ったほうが良かったのかもしれない。」と書いたが、そうだろうか。

Google Scholarで検索した結果では、多くの場合、Dice lossのシンプルな定義を示した後、様々なオプションを付加したり、BCEなど他のLossと組み合わせている。segmentation modelsに含まれているDicelossは最もシンプルなタイプなので、Eff-Unetに対してLoss functionを比較したときにDice lossだけが少し低いLB値(0.794他の4種類は0.830~0.833)になったのは、種々の論文が示唆していることと整合している。

*文献で良い結果を出しているLoss functionのパラメータとモデルの組み合わせを試してみたが、ダメだった。LB=0.833を超えると予想していたら、0.810だった。UnetとUnet++の比較にしてもそうだ、Unet++の方が良いという結果は、まだ得られていない。

Lossとモデルの組み合わせにしても、試してみないとわからない事ばかりなので、効率よく試す、実験する、ということを念頭において、最小の計算時間で適切な組み合わせを見つける方法を考えなければいけない。

encoderはefficientnetだけしか使っていないが、それでも、b0からb8まであるし、weightも3種類(imagenet, advprop, noisy-student)ある。検討する内容、最適化する内容に応じて、どれを使うかを適切に決める必要がある。

チューニングが主たる作業だった頃は、0.0001でも上がりそうだと、すぐに飛びついて計算し、順位を1つでも上にあげようとしていた。その癖が残っていて、0.001くらい上がりそうだと、すぐにやってみたくなる。それが、GPU消費(浪費)時間の増大につながっている。0.001の積み上げは重要だが、そこで止まってしまうようなチューニングではなく、さらに上を目指せる課題を探すことにもっと注力すべきなのだろうと思う。

今ある5種類のLossについては単純な線形結合で、自由に組み合わせることができるようにした。(注:単純な線形結合ではうまく計算されていない可能性がある)Lossのパラメータ設定については十分調べることはできなかったが、パラメータの意味を理解しながら実験していくしかなさそうである。

明日は、TTAを組み込む。

GitHubで、test time augmentation pytorchで検索し、上位に出てきた次のサイトがよさそうだったので、使わせていただこう。

https://github.com/qubvel/ttach

すぐにコードを組み込むことができなくても、TTAに関する情報収集の基地として便利なサイトだと思う。

Datasetに入れて、notebookのinput dataに追加し、次の命令で、インターネットなしで、インストールすることができるようにした。

!pip install ../input/ttach-pytorch -f ./ --no-index

 

2月4日(木)

HuBMAP

TTAによって追加する画像の種類と枚数を決める基準は何だろう。 Chris Deotteさんが、枚数に対して効果をプロットとしていたような記憶がある。12~15枚がピークだったような気がする。モデルやハイパーパラメータ、augmentationの内容によって、効果は違うと思うので、自分で実験することが重要。

github.com/qubvel/ttachから引用:

Similar to what Data Augmentation is doing to the training set, the purpose of Test Time Augmentation is to perform random modifications to the test images. Thus, instead of showing the regular, “clean” images, only once to the trained model, we will show it the augmented images several times. We will then average the predictions of each corresponding image and take that as our final guess [1].

データ拡張がトレーニングセットに対して行っていることと同様に、テスト時間拡張(Test Time Augmentation)の目的は、テストイメージにランダムな変更を実行することです。 したがって、通常の「クリーンな」画像をトレーニング済みモデルに1回だけ表示する代わりに、拡張画像を数回表示します。 次に、対応する各画像の予測を平均し、それを最終的な推測として使用します[1]。by Google翻訳

HuBMAPコンペサイトに、TTAを非常にわかりやすく、具体的に説明したcodeが公開されている。Let's Understand TTA in Segmentation by @ joshi98kishan

この図面はすばらしい!

f:id:AI_ML_DL:20210204120424p:plain

github.com/qubvel/ttachに説明されている手順:reverse transformations for each batch of masks/labels、の意味が一目でわかって納得した。図中では、文字が小さくて読み取りにくいが、TTA in Segmentationのすぐ下に、Deaugmentationと書かれている。

要するに、変換して変形した形状を、再度変換することによって、元の形状に戻すということだ。

ところで、torchvision.transformとalbumentationの区別がつかなくて困っている。

それぞれTとAを前に付けていればわかるのだが、

trfm = A.Compose([
      A.Resize(NEW_SIZE,NEW_SIZE),
      A.HorizontalFlip(p=0.5),
      A.VerticalFlip(p=0.5),

これなら問題ないが、

transforms = Compose([
        HorizontalFlip( ),
        VerticalFlip( ),
        RandomRotate90( ),

これはどっちなんだろう。torchvisionには、RandomRotate90( )は無い。

このコードは、次のように両方のパッケージ/モジュールを呼び出していて、as Tとかas Aを使っていないので見づらくなっているように思う。

import torchvision
from torchvision import transforms

from albumentations import *

albumentationsのドキュメントでは、次のように例示している。

import albumentations as A

まずは、TTAの枠組みを作ろう。参考にするコードは2つあって、1つは、垂直と水平のフリップのみ、もう1つは、垂直と水平のフリップに加えて、回転と、ランダムに選んだ3種類の光学的条件(コントラスト、色相、明度など)のうちの1つ

どれが効果的なのかを調べるためにどうすればよいのか。

train time augmentation(TRAとしよう)の効果とtest time augmentation(TTA)の効果を個別に調べる、連動させて調べる、無関係に連動させて調べる。

TRAのみ。TTAのみ。TRAとTTAを一致させる。TRAとTTAを直交させる(同一種類の変更を用いない)

いずれにしても、まずは効果的なTRAの加工条件を探索する必要がある。

TTA加工条件は、TRA加工条件と連動できるようにする。(現状はtrainとinferenceがつながっているので容易にできる)

TTAのお手本のコードは、PyTorchでTPUを使っており、trainとinferenceを分けているので、TTAと一緒に、trainとinferenceの分離、および、TPUの使い方を学ぶことにする。

計算資源のことで不足があるなら、文句を言う前に、Kaggleが提供してくれている計算環境をすべて利用しなければならない。

https://www.kaggle.com/docs/tpu:ここに、How to Use Kaggle, Help and Documentationというのがあって、KerasとPytorchに分けて説明されている。

コードコンペでは、inferenceにTPUは使えないので、TPUを用いたtrainからGPUを用いたinferenceに引き継ぐ方法が説明されている。

TPUs in Code Competitions
Due to technical limitations for certain kinds of code-only competitions we aren’t able to support notebook submissions that run on TPUs, made clear in the competition's rules. But that doesn’t mean you can’t use TPUs to train your models!

A workaround to this restriction is to run your model training in a separate notebook that uses TPUs, and then to save the resulting model. You can then load that model into the notebook you use for your submission and use a GPU to run inference and generate your predictions.

コードコンペティションのTPU
特定の種類のコードのみのコンテストの技術的な制限により、コンテストのルールで明確にされているように、TPUで実行されるノートブックの提出をサポートすることはできません。 ただし、TPUを使用してモデルをトレーニングできないわけではありません。

この制限の回避策は、TPUを使用する別のノートブックでモデルトレーニングを実行し、結果のモデルを保存することです。 次に、そのモデルを送信に使用するノートブックにロードし、GPUを使用して推論を実行して予測を生成できます。by Google 翻訳

なんとかなりそうだな。これからは、TPUも使おう。 

 

早速、お手本予定のコードをTPUでRunさせたのだが、1回目は2エポックで停止、2回目は14エポックで停止した。

エラー箇所とエラーメッセージ:

---> 36 start_method = 'fork')

ProcessExitedException: process 3 terminated with signal SIGABRT

View Session Metricsを見ると、CPUが399%になっていたので、この負荷の大きさがエラーを引き起こしているかもしれないと思い、負荷を下げるためにbatch_sizeを32から16にしてみた。すると、止まらずに動くようになった。しかし、trainの進行が遅くなり、結果としてスコアも悪くなった。使っているversionのコードでは、trainの停止条件をエポック数だけで決めているので、スコアへの影響が大きいのだろう。

 

2月5日(金)

HuBMAP

今日もGPUは使えないので、TPUのコードで、augmentationの効果を調べる。trainだけのコードなので、val_diceで判断する。

当然、trainの場合にのみaugmentationを使うのだが、ここでふと思った。

validationのときに、TTAで使うaugmentationをためしてみてはどうかと。

trainのaugmentationとvalidationのaugmentationをそれぞれ、train_aug, val_augとしておけば、できるかもしれない。

簡単にはいかない。deaugmentationして平均をとる処理が必要であり、それをしないで、単に画像を増やしてもTTAのテストにはならない。

まずは、手元にある3組のaugmentationの効果を比べよう。

augmentation無しの場合のval_diceは0.85、2組はほぼ同等の0.86、幾何学的変形を強くした1組は0.79であった。現状はこの程度の効果であり、適切にやらないと、逆効果になってしまうということがわかった。augmentationによって、0.85が0.79になることがあるというのは、衝撃だ。augmentationすれば、予測性能は必ず上がるものと思っていた。EfficientnetB7-Unetで、AlbumentationのHPに紹介されている組み合わせの例をそのまま適用して、LBスコアが0.80に達しなかったとき、まさか、何もしない場合よりも悪いスコアになっているとは思わなかった。

data augmentationの本質を理解しよう。

data augmentationの本質を理解するためには、教師データの本質を理解している必要がある。機械学習モデルは、labelの正確さを超えることはない。画像とlabelは、pixelレベルで1対1に正しく対応していなければならない。機械学習モデルは、画像とlabelの対応関係を根拠として、新たな画像に対して、labelを推測する。labelが正確でない場合、機械学習モデルは、正確でないlabelを推測する。

無償で使わせていただいている立場では言いにくいことだが、このコンペのlabelは、ほぼ滑らかな曲線であるべき糸球体の境界を、不十分な辺の数の多角形で近似しているので、正しくない。スムージング処理によって改善されるかどうか調べてみようと思う。そのために、マスクの形状を加工する方法を探そう。

 

2月6日(土)

HuBMAP:964 teams, 2 months to go

良いaugmentationの方法はないものかと捜し歩いているがみつからない。

efficientnetb0-Unetは今日だけだが、LB=0.826がベストスコアだった。

このaugmentationの探索からは、TTAには、あまり期待できないが、3回の推測結果の平均値をとるという意味では、スコアアップの可能性はありそうだ。

 

2月7日(日)

HuBMAP

A.OneOf([
      A.RandomContrast( ),
      A.RandomGamma( ),
      A.RandomBrightness( ),
      A.ColorJitter(brightness=0.07, contrast=0.07, saturation=0.1, hue=0.1,      always_apply=False, p=0.3),
], p=0.3), 

最後のP=0.3としてあるところを、0.0から0.6まで変えた時の、efficientnetB0-Unetによる予測結果のLBスコアは、次のようになった。

0.0: 0.822, 0.1: 0.820, 0.2: 0.826, 0.3: 0.826, 0.4: 0.827, 0.5: 0.825, 0.6: 0.824

この結果から、この部分のaugmentationは効果があって、0.2から0.5くらいであれば大差ないように見える。

次は、p=0.4で固定して、efficientnetを複雑にしていくとどうなるかを調べてみよう。

b1からb5まで順に計算してみるつもりだ。気が変わらなければ。

 

2月8日(月)

HuBMAP:971 teams, 2 months to go

OneCycleLRを使っているのだが、性能が発揮できていないような気がしてきた。

論文を読んで理解しよう。

Super-Convergence: Very Fast Training of Neural Networks Using Large Learning Rates
Leslie N. Smith, Nicholay Topin, arXiv:1708.07120v3 [cs.LG] 17 May 2018

Abstract
In this paper, we describe a phenomenon, which we named “super-convergence”,
where neural networks can be trained an order of magnitude faster than with
standard training methods. The existence of super-convergence is relevant to
understanding why deep networks generalize well. One of the key elements of
super-convergence is training with one learning rate cycle and a large maximum
learning rate. A primary insight that allows super-convergence training is that large
learning rates regularize the training, hence requiring a reduction of all other forms
of regularization in order to preserve an optimal regularization balance. We also
derive a simplification of the Hessian Free optimization method to compute an
estimate of the optimal learning rate. Experiments demonstrate super-convergence
for Cifar-10/100, MNIST and Imagenet datasets, and resnet, wide-resnet, densenet,
and inception architectures. In addition, we show that super-convergence provides
a greater boost in performance relative to standard training when the amount of
labeled training data is limited. The architectures to replicate this work will be
made available upon publication.

概要
この論文では、ニューラルネットワークを標準的なトレーニング方法よりも1桁速くトレーニングできる、「超収束」と名付けた現象について説明します。超収束の存在は、なぜ深いネットワークがうまく一般化するのかを理解することに関連しています。超収束の重要な要素の1つは、1つの学習率サイクルと大きな最大学習率でのトレーニンです。スーパーコンバージェンストレーニングを可能にする主な洞察は、学習率が高いとトレーニングが正規化されるため、最適な正規化バランスを維持するために、他のすべての形式の正規化を減らす必要があるということです。また、最適な学習率の推定値を計算するために、ヘッセ行列のない最適化手法の簡略化を導き出します。実験は、Cifar-10 / 100、MNIST、Imagenetデータセット、およびresnet、wide-resnet、densenet、およびinceptionアーキテクチャの超収束を示しています。さらに、ラベル付けされたトレーニングデータの量が限られている場合、スーパーコンバージェンスが標準トレーニングと比較してパフォーマンスを大幅に向上させることを示します。この作業を複製するためのアーキテクチャは、公開時に利用可能になります。

by Google翻訳

OneCycleLRのexampleは、optimizerにSGDを使っているが、そのexampleをコピペして使っても、良い結果が得られない(まともな結果が得られない)ので、optimizerにAdamWを使っている。

論文では、optimizerはSGDだけであり、SGDの良さを強調している。

While deep neural networks have achieved amazing successes in a range of applications, understanding why stochastic gradient descent (SGD) works so well remains an open and active area of research. Specifically, we show that, for certain hyper-parameter values, using very large learning rates with the cyclical learning rate (CLR) method [Smith, 2015, 2017] can speed up training by as much as an order of magnitude. We named this phenomenon “super-convergence.” In addition to the practical value of super-convergence training, this paper provides empirical support and theoretical insights
to the active discussions in the literature on stochastic gradient descent (SGD) and understanding generalization.

ディープニューラルネットワークはさまざまなアプリケーションで驚くべき成功を収めていますが、確率的勾配降下法SGD)がうまく機能する理由を理解することは、オープンで活発な研究分野です。具体的には、特定のハイパーパラメータ値について、循環学習率(CLR)法[Smith、2015、2017]で非常に大きな学習率を使用すると、トレーニングを1桁も高速化できることを示します。 この現象を「超収束」と名付けました。 超収束トレーニングの実用的な価値に加えて、この論文は、確率的勾配降下法SGD)と一般化の理解に関する文献での活発な議論に対する経験的サポートと理論的洞察を提供します。 by Google翻訳

optimizerをSGDにして、lrとMax_lrを変更してみた。AdamWでのLBスコアが0.827となったモデルである。LBスコアは0.815と0.821で、他にもトライした2条件では、良い結果を期待できそうなval_lossの変化だったが、Submission Scoring Errorになってしまった。適切な値というのは、モデル、データ、課題などの組み合わせによって違ってくるので、計画的に実験しないと、なかなか、良い結果にたどり着けない。

max_lrの設定値が重要で、目安はoptimizerのデフォルトのlr値の10倍から30倍程度ということだろうと思う。SGDなら1から3、AdamWなら1e-2から3e-2程度という感触を得たので、明日、気が向いたら確かめてみようと思う。

 

2月9日(火)

HuBMAP

SGD:

Max_lr=0.3: LB=0.815

Max_lr=2: LB=0.824

Max_lr=3: LB=0.821

AdamW:

Max_lr=1e-3: LB=0.827(過去のデータ)

Max_lr=1e-2: LB=0.818

Max_lr=2e-2: LB=0.805

Max_lr=3e-2: LB=0.812

この3件、プログラムミスの影響を受けている可能性あり。

OneCycleLRの条件検討を行ってきたここまでの結果では、Max_Lrをデフォルトのlr(SGD: 0.1, AdamW: 1e-3)の10~30倍にすることによるLBスコアは、SGDにおいては少し上がったが、AdamWでは、逆に下がった。この手法は、SGD限定なのかもしれない。

 

気分転換に、Encoderを変えてみようと思う。

ResNet18, 34, 50, 101, 151, Senet154, Se_Resnet50, 101, 152, Se_Resnext50_32x4d, 101, Densnet121, 169, 201, 161, Inceptionresnetv2, Inceptionv4, Xception, Dpn68, 98, 131, VGG11, 13, 16, 19, などを使う準備をした。

 

2月10日(水)

HuBMAP

Efficientnet-UnetでLB~0.83を示すコードのEncoderを次のモデルで置き換え、他の条件は一切変えずに走らせた。

Resnet18: LB=0.813

Resnet34: LB=0.805

Resnet50: LB=0.810

Resnet101: LB=0.815

Rennet152: LB=0.812

この5件、プログラムミスの影響を受けている可能性あり。

次の論文は、最新のテクニックを駆使すれば、昔のモデル(ResNet)でも新しいモデル(EfficientNet)に匹敵するような性能を示す、ということを示している論文のようだが、そういうテクニックを持ち合わせていない場合は、新しい高性能なモデルを使う方が良い結果を得られますよ、というふうに読める。

Compounding the Performance Improvements of Assembled Techniques in a Convolutional Neural Network
Jungkyu Lee, Taeryun Won, Tae Kwan Lee, Hyemin Lee, Geonmo Gu, Kiho Hong

arXiv:2001.06268v2 [cs.CV] 13 Mar 2020

f:id:AI_ML_DL:20210210203558p:plain

f:id:AI_ML_DL:20210210203729p:plain

Autoaugという単語が気になる。

AutoAugment: Learning Augmentation Strategies from Data
Ekin D. Cubuk , Barret Zoph, Dandelion Man´e, Vijay Vasudevan, Quoc V. Le

arXiv:1805.09501v3 [cs.CV] 11 Apr 2019

 

明日の予定:気が変わらなければ、se_resnet50, 101, 152, se_resnext50_32x4d, 101をencoderに用いたUnetを使ってみる。

 

2月11日(木)

HuBMAP

①se_resnext50_32x4d: LB=0.822

②se_resnext101_32x4d: LB=0.809

➂senet154: LB=0.823

この3件、プログラムミスの影響を受けている可能性あり。

Resnetよりは、少し、良い結果になった。

ちなみに、trainの所要時間の比率は、①1.0 : ②1.5 : ➂2.6であった。

もっと良いモデルはないものか。 

ResNeSt: Split-Attention Networks
Hang Zhang et al., arXiv:2004.08955v2 [cs.CV] 30 Dec 2020

f:id:AI_ML_DL:20210211102800p:plain
7. Conclusion
This work proposes the ResNeSt architecture that leverages the channel-wise attention with multi-path representation into a single unified Split-Attention block. The model
universally improves the learned feature representations to boost performance across image classification, object detection, instance segmentation and semantic segmentation. Our Split-Attention block is easy to work with (i.e., dropin replacement of a standard residual block), computationally efficient (i.e., 32% less latency than EfficientNet-B7 but with better accuracy), and transfers well. We believe ResNeSt can have an impact across multiple vision tasks, as it has already been adopted by multiple winning entries in 2020 COCO-LVIS challenge and 2020 DAVIS-VOS chanllenge.

f:id:AI_ML_DL:20210211100031p:plain

こういうのを見ると、あらためて、EfficientNetは凄いんだな、と思う。

予定を変更して、EfficientNet-B7とResNeSt-269を比較してみよう。

EfficientNet-B7: 0.682

明らかにおかしな結果になったので、プログラムを見直したら、inferenceのところで実験的に変えていたパラメータを元に戻し忘れていた。2月9日から2月11日15時までの間に行った計算結果は、間違っている可能性がある。

以下は、元に戻したコードで計算した結果である。

ResNeSt-269: LB=0.829

EfficientNet-B7:0.652

???、何か変だ。

 

2月12日(金)

HuBMAP

EfficientNetB0-UnetのLBスコアのバッチサイズ(32, 16, 8, 4)による違いを調べてみた。(commitまで昨日行い、今朝9時すぎにsubmitした。)

Batch_size=4:   LB=0.819

Batch_size=8:   LB=0.647

Batch_size=16: LB=0.830

Batch_size=32: LB=0.826

ここでも、異常値が生じた。

これらの異常は、overfittingによって生じている可能性がある。

lrスケジューラーとして使っているOneCycleLRは、overfittingしにくく、再現性が高いので、信用しきって使っているが、パラメータは殆どデフォルト値で、エポック数は時間節約のために10に設定しているが、公開コードを見ていると、エポック数として25±5くらいが良く使われていることなどを勘案すると、問題発生の原因になっている可能性がある。OneCycleLRの適切なパラメータの探索が必要だ。

さらに、予測したマスクを画像に戻して、trained_modelが予測しているsegmentationがどうなっているのかを、画像として確認できるようにしよう。

メモ:予測結果を画像に変換して確認、K-fold, Auto-augmentation, TTA, DropBlock, Model-ensemble, pseud_label, ...

 

これはどうなんだろう。著者は、Google Research, Brain Teamとなっている。

EfficientNetの論文のときと似たような図がトップページに掲載されている。

EfficientDet: Scalable and Efficient Object Detection
Mingxing Tan, Ruoming Pang, and Quoc V. Le,  arXiv:1911.09070v7 [cs.CV] 27 Jul 2020

f:id:AI_ML_DL:20210212235542p:plain

While our EfficientDet models are mainly designed for object detection, we are also interested in their performance on other tasks such as semantic segmentation. Following
[19], we modify our EfficientDet model to keep feature level fP2; P3; :::; P7g in BiFPN, but only use P2 for the final per-pixel classification. For simplicity, here we only evaluate a EfficientDet-D4 based model, which uses a ImageNet pretrained EfficientNet-B4 backbone (similar size to ResNet-50). We set the channel size to 128 for BiFPN and
256 for classification head. Both BiFPN and classification head are repeated by 3 times. 

f:id:AI_ML_DL:20210212234921p:plain

f:id:AI_ML_DL:20210212235123p:plain

f:id:AI_ML_DL:20210212235207p:plain

この論文見てたら、「いつまでUnet使っているのか」「なぜ、FPNとかDeepLav3を使わないのか」さらに、「それらを飛ばして、EfficientDetを使ってみたらどうか」と言われているような気がする。

 

2月1日のデータだが、EfficientnetB7-Unetで、損失関数を評価した結果は、次のようになった。これで、DiceLossを使わなくなったのだが、

BCELoss:       LB=0.829(1月31日)

DiceLoss:      LB=0.794

LovaszLoss:  LB=0.830

JaccardLoss: LB=0.832

FocalLoss:    LB=0.833
いずれもOneCycleLRの10エポックで、Lossの収束具合から判断すると、FocalLossは収束が速く、10エポックでも十分という感じだが、他は、もっとエポック数を増やせば、よくなりそうな気配を感じる。

ということで、明日は、エポック数依存性を、DiceLossについて調べてみよう。

EncoderとDecoderの組み合わせをどうするか。

 

2月13日(土)

HuBMAP:990 teams, a month to go(データの更新から2か月:データ更新待ち)

今日から1週間のGPUの割当は、先週と同じで、43時間である。

まずは、DiceLossで、OneCycleLRのエポック数を10回から20回、30回に増やしてみよう。

B0とB7では、単位エポックあたりの計算時間が3倍くらい違うので、B0でテストしてみよう。現状、256x256で、8000枚程度の画像処理なので、B0で十分だろうと思う。

EfficientNetB0-Unet, DiceLoss:

epochs=10: LB=0.826

epochs=20: LB=0.830

epochs=30: LB=0.832

まあまあ、期待していたような結果になった。

それならば、BCELossは10エポックのデータがあるので、20エポックと30エポックの場合について計算してみよう。

BCEWithLogitsLoss:

epochs=10: LB=0.830(2月11日のデータ)

epochs=20: LB=0.822

epochs=30: LB=中止:計算が途中で停止し、かつ、Lossの変化も適正ではなかった!

BCELossは期待外れ、ということになった。

今日の最後は、JaccardLossの20エポックにしてみよう。

JaccardLoss:

epochs=10: LB=0.832(EfficientNetB7-Unet:2月1日計算)

epochs=20: LB=0.829(EfficientNetB0-Unet)

これらは比較できない!

B7の10エポックがB0の20エポックを少し上回っただけ。

複数の条件が異なる場合の比較は不可。

2月2日に、Decoderを比較したところ、以下のようになった。

LossFunction=BCE, lr_Scheduler=OneCycleLR(epochs=10)

Encoder:EfficientNetB4

Decoder:Unet: LB=0.832, Unet++: LB=0.823, FPN: LB=0.830, MAnet: LB=0.825

これらの結果に対しては、「動作確認しただけ」と書いたが、この後今日まで、Decoderは、Unetを使ってきた。

このときのメモをよく見ると、Unetのパラメータはデフォルトではなく、decoder_attention_type="scse"としていた。

 

明日は、DecoderとしてFPN、Loss functionとしてDiceLossを使ってみよう。

そろそろ、パーソナルベストのLB=0.833を超えたいな。

 

2月14日(日)

HuBMAP:994 teams

EfficientNetBn-FPN-DiceLoss-AdamW-OneCycleLR-soft_augmentation:

EfficientNetB3-FPN_10 epochs: LB=0.826

EfficientNetB4-FPN_10 epochs: LB=0.829

EfficientNetB5-FPN_10 epochs: LB=0.832:EfficientNetB5-FPN_20 epochs: LB=0.834

EfficientNetB6-FPN_10 epochs: LB=0.828

似たり寄ったりというところかな。

B3からB6の比較では、B5が良さそうという結果だが、Unetでは、B0でも十分という結果なのだが。Decoderによって、最適なEncoderのサイズが違うのかもしれない。

EncoderにEfficientNetB5、Loss functionにDiceLossを使って、9種類のDecorderとの組み合わせで、LBスコアの比較をしてみよう。DiceLossはBCEより収束が遅いので、ベースのエポック数を15にしよう。

 

2月15日(月)

HuBMAP: 998 teams

EfficientNetB5-Decoder-DiceLoss-AdamW-OneCycleLR_15epochs-soft_augmentation:

Unet_scse:      LB=0.827

Unet++_scse: LB=0.831

MAnet:           LB=0.831

Linknet:          LB=0.832

Linknetの論文を示しておこう。

LinkNet: Exploiting Encoder Representations for Efficient Semantic Segmentation

Abhishek Chaurasia and Eugenio Culurciello, postarXiv:1707.03718v1 [cs.CV] 14 Jun 2017

f:id:AI_ML_DL:20210215121009p:plain

f:id:AI_ML_DL:20210215121157p:plain

LinkNetは計算速度の速さが売りのようだが、1エポックあたりの計算時間はUnetより10%くらい短いだけだった。LBスコアは(今回の条件では)Unetより少しよさそうだ。


OneCycleLR

OneCycleLRは、モデルが小さい場合には、エポック数を多くする方が良いようだ。その理由は、モデルが小さいほど収束が遅いから、ということのようだ。

モデルが大きい場合には、エポック数を増やしていくと、overfittingして、スコアが低下することがあるようだ。

EfficientNetB0-Unetで、10, 20, 30のエポック数に対して、 LBスコアが、0.826, 0.830, 0.832となったのは、DiceLossが相対的に収束が遅く、かつ、小さなモデルであるB0と組み合わせたことによるのかもしれない。

BCELossを用いた場合には、DiceLossよりも収束が速いので、OneCycleLRのエポック数を増やすと、overfittingになりやすいようである。

ただし、これらの現象は、OneCycleLRと組み合わせるOptimizerの種類やMax_Lrの設定値によっても変わるようなので、適宜、チューニングすることが必要だろう。

組合せの数が多くて、収拾がつかなくなりそうだ。

これだけ多くのモデルを扱っているのだから、アンサンブルする方法を考えて、スコアアップにつなげていきたいものだ。

 

明日submitする予定の計算実施:

EfficientNetB5-Decoder-DiceLoss-AdamW-OneCycleLR_15epochs-soft_augmentation:

PSPNet: 

PAN: 1エポックの計算時間が長いため中止

DeepLabV3: GPUモリーオーバー

DeepLabV3+: 1エポックの計算時間が長いため中止

FPNは10エポックと20エポックの結果があるので、別の検討を行う。

EfficientNetB5-FPN-DiceLossを用いたMax_Lrの検討:

optimizer: SGD:max_lr=3(x30): エポック数を20、30、50とする。

optimizer: AdamW:max_lr=1e-2(x10): エポック数は30とする。

torch.optimのマニュアルでは、SGDのlrはlr=<required parameter>となっていて、デフォルト値は与えられていない。すぐ後のexampleに、lr=0.1とあるだけ。

AdamWのlrのデフォルト値はlr=0.001となっている。

 

明日から、今使っているコードのinferenceの部分を理解し、TTAを組み込む。 

 

2月16日(火)

HuBMAP

EfficientNetB5-Decoder-DiceLoss-AdamW-OneCycleLR_15epochs-soft_augmentation:

PSPNet: LB=0.821

この条件で計算した中では、PSPNetのLBスコアが最も低かった。

PSPNetの論文を見ておこう。

Pyramid scene parsing network
H Zhao, J Shi, X Qi, X Wang… - Proceedings of the IEEE …, 2017 - openaccess.thecvf.com

Abstract
Scene parsing is challenging for unrestricted open vocabulary and diverse scenes. In this paper, we exploit the capability of global context information by different-regionbased context aggregation through our pyramid pooling module together with the proposed pyramid scene parsing network (PSPNet). Our global prior representation is effective to produce good quality results on the scene parsing task, while PSPNet provides a superior framework for pixellevel prediction. The proposed approach achieves state-ofthe-art performance on various datasets. It came first in ImageNet scene parsing challenge 2016, PASCAL VOC 2012 benchmark and Cityscapes benchmark. A single PSPNet yields the new record of mIoU accuracy 85.4% on PASCAL VOC 2012 and accuracy 80.2% on Cityscapes.

f:id:AI_ML_DL:20210226091810p:plain

 

OneCycleLR(DiceLoss)のmax_lrの検討:

optimizer: SGD:max_lr=3(x30):

epochs=20: LB=0.826: (2/18 submit)

epochs=30: LB=0.829: (2/18 submit)

epochs=50: LB=0.828

optimizer: AdamW:max_lr=1e-2(x10):

epochs=30: LB=(submission scoring error): (2/18再度submit): LB=0.827

SGDでもAdamWに近い結果が得られるようになってきた。さらに、50エポックまで増やしても効果はなく、30エポックで十分だということを示すものとなった。

 

TTA

TTAを組み込んだコードのベースは、自分が使っているコードのベースと同一なので、単に移植するだけであれば、難しくないと思われる。

と、思って取り掛かってみたが、そう簡単ではない。

最初に、Lambda、が定義されていないとのエラー、次は、preprocess_inputでひっかかり、これらを使わない方法を考えていたのだが、get_preprocessing_fn、が気になって調べてみた結果、これらが重要な関数であることがわかった。

調べてみると、TTAを追加した人は、Segmentation Modelsのパッケージを使っており、そのパッケージのマニュアルには、次の例に従って入力データを前処理するように書かれているのだが、自分は同じSegmentation Modelsのパッケージを使っていながら、これらの関数を知らなかったために、エラーの意味するところが分からなかった、ということである。これは重要な情報である。今使っているコードを見直す必要があるかもしれない。(まずは、このコードの機能と使い方を理解しよう)

from segmentation_models_pytorch.encoders import get_preprocessing_fn

preprocess_input = get_preprocessing_fn('resnet18', pretrained='imagenet')

'resnet18' はexampleで、使用するEncoder名を入れる。

とりあえず、大きなエラーは解消できたので、TTAが機能するかどうか調べてみる。

といっても、inferenceの部分だから、commit, submitしないとわからないので、明日にしよう。

 

2月17日(水)

HuBMAP: 1,012 teams

TTAを搭載したコード、昨日はCPUで途中まで動くことを確認した。

GPUでinferenceまで完了。

EfficientNetB0-FPNで、inference所要時間は41分であった。

commitしてoutputを見て唖然!

何も出力されていなかった。

最終行に、submission.head( )、と書いておきましょう!

 

***バグ出し・コード修正作業中***

・バグ出しに必要なコードの知識が不足。

・必要と考えられる機能を全て追加してしまってからバグを見つける、ということができるような、コーディング技術は、まだ持っていない。

・動いているコードに、正確に作動する状態を保持しながら、TTAに必要な機能を、1行づつ(少しづつ)追加していく、というようなやりかたをとってみよう。

 

2月18日(木)

HuBMAP: 1,019 teams

TTAのセットで使われている次のコードの意味がわからない。

preprocess_input = Lambda(image = get_preprocessing_fn(encoder_name = ENCODER_NAME, pretrained = 'imagenet'))

TTAのコード(inference)の作者の(train)コードを見ると、そこでも使われている。

TTAの作者がtrainで用いているEncoderは'se_resnext50_32x4d'であり、自分が今使っているEncoder(EfficientNet)とは異なることに起因する何らかの不整合がエラーの原因となっている可能性がある。

ということで、TTAの作者と同じ、se_resnext50_32x4d-Unetを使って確かめてみよう。

これはピントはずれだった。

出力されなかった原因は、単純ミスだった。

TTA用の画像も、それに対する予測も正しく行われていることを確認した。

それでも、最終出力は空(empty)であった。このことから、次のコード「preds[x1:x2,y1:y2] = (pred > 0).astype(np.uint8)」が動作していないということが推測された。このコードは、次のforループ「for (x1,x2,y1,y2) in slices:」の中にあるべきものだが、それが、インデントの間違いによって、このforループの外に出てしまっていたのである。そのために、予測値が格納されず、空のままだったということである。

原因:TTAを含むコードの作者は、複数のFoldに対応するモデルによる予測値の平均を計算するためのforループを用いていたが、自分が使っているコードは、Foldを使っていないので、そのforループを除去したのだが、その作業中にそのforループの外側の行まで動かして(インデントの変更をして)しまったために、予測値の読み込みのコードが必要な時に呼び出されなくなってしまった、ということである。

 

ということで、ようやく解決した。

明日は、TTAの効果を調べたいところだが、GPUの残り時間が無くなった。

明日は、trainとinferenceの分離、モデルのアンサンブル、などについて検討する。

 

2月19日(金)

HuBMAP:1,028 teams, two months to go (To be determined)

 

trainとinferenceに分離:trainedパラメータの授受

train_code: パラメータの保存コードの例

torch.save(model.state_dict(), 'model.pth')

torch.save(model.state_dict(),"best.pth")

torch.save(model.state_dict(),f'FOLD-{fold}-model.pth')

inference_code: 保存したパラメータの読み込みコードの例

model.load_state_dict(state_dict)

model.load_state_dict(checkpoint['state_dict'])

model.load_state_dict(torch.load("../input/private_dataset/FOLD-{fold}-model.pth"))

 

モデルのアンサンブルについて:

現状のinferenceの所要時間は15分程度。TTAで3枚に増えると45分程度、モデルを4種類使うと180分程度となる。

TTAの参考にさせていただいたコードは4Foldの計算で、各Foldのパラメータを読み込んだモデルを用意しておいて、forループで順に予測し、予測値をループ毎に加算し、最後に4で除算している。この4Foldの代わりに、4種類のtrain済みのモデルを用意しておけばアンサンブルができそうな気がするのだが、どうだろう。

4Foldの場合は、inferenceコードでモデルを準備し、trainコードで作成し出力した各Foldのtrainedパラメータを読み込んだモデルをmodel_0, model_1, model_2, model_3のように準備し、これらのモデルを順に適用して予測し、最後に平均をとる。

モデルのアンサンブルの場合は、inferenceコードで複数のモデルを準備し、trainコードで作成した各モデルのtrainedパラメータを読み込んだモデルをmodel_A, model_B, model_C, model_Dのように準備し、これらのモデルを順に適用して予測し、最後に平均をとる。

モリーオーバーになりそうだし、そう簡単にはいかないかもしれないが、まずは、サイズの小さな、2種類のモデルを使って、やってみよう。(後日)

 

これなに?:

identity = rasterio.Affine(1, 0, 0, 0, 1, 0)

この括弧の中の6つ並んでいる1と0の数字は、下のマトリックスの(a, b, c, d, e, f)に対応していて、対角成分が1の対角行列を示しているようだ。

以下は、https://github.com/sgillies/affine、から引用したもので、適当に書き加えた。

The 3x3 augmented affine transformation matrix for transformations in two dimensions is illustrated below.

| x' |   | a  b  c | | x |
| y' | = | d  e  f | | y |
| 1  |   | 0  0  1 | | 1 |

>>> Affine.identity()
Affine(1.0, 0.0, 0.0,
           0.0, 1.0, 0.0) 

a=1, b=0, c=0, d=0, e=1, f=0, を代入すると上のマトリクスの式はつぎのようになる。

| x' |   | 1  0  0 | | x |
| y' | = | 0  1  0 | | y |
| 1  |   | 0  0  1 | | 1 |

 x'=1, y'=1

identity(同一)だから、こんな感じでいいのかな。

 

明日は、TTAの効果を試してみよう。

 

2月20日(土)

GPU: 43 h

HuBMAP:1,042 teams, two months to go

TTA

TTA-EfficientNetB0-FPN(decoder-dropout=0.5)-Batch_16-Epochs_10-Dice-AdW-trfm_1

TTA_0: no TTA: LB=0.825

TTA_1: identity + holrizontal_flip: LB=0.822

TTA_2: identity + horizontal_flip + vertival_flip: LB=0.827

TTA_3: identity + horizontal_flip + vertival_flip + rotate: LB=0.828

TTA_4: identity + horizontal_flip + vertival_flip + rotate + pixel_level_trfms: LB=0.830

プログラムは正しく動作しているようで、TTAの効果が認められた。

計算時間をできるだけ短くしようとしてB0を用いたが、それにはDiceLossは適切ではなく(10エポックでは不足)、LBスコアとしては、満足のいく結果にはならなかった。

大きなモデルを使うと予測時間が極端に長くかかり、この先、モデルのアンサンブルのことも考えると、計算速度は速く、モデルは小さく、する必要がある。

今回のモデルでは、TTA無しのときの予測時間が12.5分で、4枚追加すると予測には、45分くらいかかっている。仮に5つのモデルをアンサンブルすると、45x5=225分かかる。よくわかっていないのだが、submit中に、予測はprivate_dataに対しても行われ、private_dataがtest_dataの1.4倍ある場合には、225 x 2.4=540分=9時間となる。B0でギリギリなので、大きなモデルを使うには、アンサンブルするモデルの数を減らす、TTAの枚数を減らす、ということをする必要がある。B5などでは、予測時間が長くなって、とても使えそうにないと思う。

明日は、TTAなし、予測時間15分以内、LBスコア0.832以上をリストアップ/探索し、実際に0.832以上になった場合には、TTA_4を適用してみよう。

EfficientNetB0,B1,B2,B3,B4

Unet, Unet-scse, FPN, MAnet, Linknet,

FocalLoss, JaccardLoss, LoaszLoss, BCELoss, DiceLoss,

組み合わせとしては、おおよそ、この範囲内で、検討しよう。

 

過去の実験結果リマインド:OneCycleLRのエポック数とLoss_function:一例

EfficientNetB0-Unet, OneCycleLR (AdamW: lr=1e-4, Max_lr=1e-3)

BCEWithLogitsLoss:

epochs, public_LB = (10, 0.830) -> (20, 0.822) -> (30, no submittion)

at last epoch: (train_loss, val_loss) = (0.041, 0.053) -> (0.034, 0.047) -> (0.031, 0.054)

DiceLoss:

epochs, public_LB = (10, 0.826) -> (20, 0.830) -> (30, 0.832)

at last apoch: train_loss, val_loss = (0.106, 0.123) -> (0.101 0.113) -> (0.096, 0.111)

 

2月21日(日)

HuBMAP:1,054 teams, two months to go

GPU: 36h40m

EfficientNetB0-Decoder, FocalLoss, OneCycleLR(AdamW, 1e-4, max_lr=1e-3), TTA-4

Unet:          LB=0.830

Unet-scse:  LB=0.829

FPN:           LB=0.818

MAnet:      LB=0.828

Linknet:     LB= 0.820

TTA無しでのスコアが0.832以上になる組み合わせを探索したうえで、TTA-4を適用するつもりだったが、trainの段階でのFocalLossの値が良さそうだったので、条件出しせずにTTA-4の計算を行った結果は以上のようになった。

FocalLossを使ったのは、EfficientNetB7-Unetに(FocalLoss, JaccardLoss, LoaszLoss, BCELoss, DiceLoss)を適用したとき、最も収束が良く、LBスコアも高かったのがFocalLossだったためである。EfficientNetB0-FPN(とLinknet)のスコアがこんなに低くなるとは思わなかったが、train結果を見直してみると、EffB0-FPN(とLinknet)のval_lossの値は、他のDecoderの結果よりも明らかに大きい。ResNext152-FPNを扱った文献に、FocalLoss(α=0.25, β=2.0)が良好な結果を与える、と記述されていたのをメモっていたので、FocalLossとFPNとの相性は良いんだろうと思っていた。相性が良いのはResNext152やEfficientNetB7と組み合わせた場合に限る、ということかもしれない。

モデルが小さい場合、エポック数を増やす必要がある。

予測時間は、モデルサイズを大きくすると長くなるが、エポック数を増やしても、予測時間は変わらないと思い込んでいたが、実験してみると・・・。

小さなモデルで、エポック数を増やして、良い結果が得られるならば、その方が良い。

EfficientNetBn-FPNを用いて、Bnと予測時間の関係をTTA無しで比較してみよう。

EffB0-FPN: 11m19s(draft), 11m51s(commit)

EffB1-FPN: 13m11s(draft), 11m12s(commit)

EffB2-FPN: 12m29s(draft), 10m47s(commit)

EffB3-FPN: 13m15s(draft), 12m43s(commit)

この程度の時間差であれば、パラメータの増加等による性能アップの効果の方が大きいのではないだろうか。 

明日は、EncoderをEfficientNetB3に変更し、他は全く同じ条件のままで、計算してみようと思っていたが、上記のように予測時間のモデル依存性を調べた結果、B4, B5, B6, B7等についても調べ、そのうえで、これまで得られている結果も勘案して、これから使っていくEfficientNetのモデルを絞り込んでいこうと思う。 

 

2月22日(月)

HuBMAP:1,062 teams, two months to go

EfficientNetBn-FPNの予測時間

EffB4-FPN: 12m11s(draft), 14m49s(commit)

EffB5-FPN: 13m27s(draft), 15m25s(commit)

EffB6-FPN: 16m10s(draft), 15m42s(commit)

f:id:AI_ML_DL:20210222102631p:plain


f:id:AI_ML_DL:20210222085906p:plain

これにスコアを加えたいのだが、Decoder、エポック数、損失関数、augmentationの種類等によって変わるので、難しい。

ここからは、OneCycleLRのエポック数は30、EncoderはEfficientNetB5、損失関数はDiceLoss、をbaseとしよう。

EfficientNetB5-Decoder, DiceLoss, OneCycleLR(AdamW, 1e-4, max_lr=1e-3, 30 epochs), batch_size=16, with soft augmentation, without TTA

Unet:      LB=0.836 (15 epochs: 0.827)

Unet++: LB=0.836 (15 epochs: 0.831)

FPN:       LB=0.830 (20 epochs: 0.834)

MAnet:  LB=0.834 (15 epochs: 0.831)

Linknet: LB=0.836 (15 epochs: 0.832)

Unet, MAnet, Linknetについて、さらに、エポック数を増やしてみようかなと思うのだが、overfittingによってスコアは反転するだろうから、そこを見極める必要がある。overfittingしてから、適度なdata_augmentationができれば、スコアはさらに上げることができるかもしれない。 

FPNは、Decoderのdropoutを0.5にしたのがまずかったかもしれないので(20エポックもdropout=0.5)、0.2に戻してみよう。

GPUの残りが8.5時間になった。明日、Linknet, Unet, MAnetのエポック数を増やすだけで使い切ってしまいそうだ。

その後の3日間は、trainと、inferenceのコードを作り、K-Foldとアンサンブルができるように準備しよう。

 

2月23日(火)

HuBMAP:1,070 teams, two months to go(まだデータは更新されていないようだ)

エポック数を50にしてみた。1エポックあたり1分を少し超えるので、trainで60分くらいかかる。データ前処理の5分とinferenceの15分を足すと約80分を要す。

commitも同じ時間を要するので、パラメータ設定時間等も加えると、1つのスコアを得るのに、3時間くらいかかる。

ということで、今日は、Linknet, Unet, Manetの50エポックの計算で終了予定。

OneCycleLRにおけるエポック数:プログラムのTTAの動作確認のために3エポックでtrainを終え、commit,submitしてみたら、LBスコアが0.80くらいになってたいへん驚いたことがある。10エポックで0.82+のモデルである。エポック数を増やす実験を、30くらいまで、何度かやってみたところ、このブログにも部分的に記録を残しているが、EncoderがB0でDiceLossの場合、エポック数が10、20、30と増えるにつれてスコアは上がったが、EncoderがB5以上でBCELossの場合には20以上ではスコアは低下する傾向がみられた。といっても、OneCycleLRの性能は、用いるoptimizerとそのパラメータだけでなく、Max_lrによっても大きく変わるので、エポック数の最適値がどこにあるかは、実験してみるしかない、ということになる。

Linknet:15エポックでLB=0.832、30エポックでLB=0.836だったのに対し、50エポックまで増やすと、LB=0.831となった。エポック数を40にするか50にするか迷ったのだが、これによって、50以下にピークがあることがわかった、ということにしておこう。

この結果をみると、UnetやMAnetは50エポックではなく、40エポックくらいにしてみよう、となるかもしれないが、既に、Unetは50エポックで計算し、commit, submitしており、MAnetは50エポックで計算中である。

Unet: 30エポックでLB=0.836だったのに対し、50エポックまで増やすと、LB=0.834となった。

MAnet: 30エポックでLB=0.834だったのに対し、50エポックまで増やすと、LB=0.830となった。

以上、いずれのDecoderも、50エポックまで増やすことによって、publicLBスコアは下がった。LinknetとMAnetのLBスコアのピークは30エポック前後、UnetのLBスコアのピークは40エポック近傍であると推測される。

最後に、B5-UnetのLB=0.836のときと同じ条件でtrainingした後で、TTA_4を適用してみよう。

inferenceに要した時間は約54分で、B0-Unetの41分の約1.3倍となった。

TTA_4を追加することによって、0.84+となることを期待したが、LB=0.836となり、スコアは上がらなかった。

GPUの残り時間が30分以下となったので、ここで終了!

これまでの実験結果を簡単にまとめると次のようになる。

1.TTAが可能になった。

2.EfficientNetB0-FPNのモデルを用いて、TTAの効果を調べ、TTA無しでLB=0.825だったのが、TTA_4ではLB=0.830となり、TTAによってLBスコアが向上することを確認した。

3.OneCycleLRで常用してきた10エポックを30エポックまで増やすことによって、LBスコアが0.836まで向上したので、そのモデルにTTA_4を適用することでさらにスコアが上がることを期待したが、TTA無しと同じスコア0.836となった。

検討:

TTAの効果を最初に調べたモデルでのLBスコアは、TTA無し: 0.825、TTA_1: 0.822, TTA_2:0.827, TTA_3: 0.828, TTA_4: 0.830であった。数字は追加画像の枚数である。

これに対して今日のモデルは、TTA無しでもLBスコアが0.836と高いことが関係しているのか、それとも、TTA無しで0.836というのは別の計算なので、TTA_4を適用したときのモデルの性能が、TTA無しのときのモデルの性能よりも低かったということか。

TTA適用無し:30エポック目: train_loss=0.094, val_loss=0.107

TTA_4適用: 30エポック目: train_loss=0.096, val_loss=0.113となっていた。

両者は、trainまでは、全く同じコードの筈なのだが、この最終エポックでのlossの値からは、TTA適用無しのtrainedモデルの方が良いと判定される。すなわち、TTAを適用する前のモデルの予測性能が劣っていたために、あたかも、TTAの効果が皆無であったかのような結果になったということではないだろうか。

最初にTTAの効果を調べたときも、TTA無しと各TTA有は、全てその都度trainを行なっている。それゆえ、毎回、trainedモデルの性能は異なっていた可能性が高い。実際、TTA_1のスコア0.822は、TTA無しのスコア0.825よりも低かった。この時の実験をこれでやめていたら、TTAの効果は無い、TTAをすることで、かえってスコアは悪くなる、2枚の予測結果の処理の仕方を見直そう、などと考えたかもしれない。しかし、TTAの枚数を増やしていった結果、枚数が多くなればスコアが上がるという結果となり、それによって、TTAによりLBスコアは良くなる、と判断することになった。

今のコードは、trainとinferenceが連結されているので、このような現象が起きる。

trainとinferenceが分離されていれば、同一のtrainedモデルを使うことができるので、inferenceの条件の違いが明確に現れ、同一のモデルを使っているにもかかわらず、TTAの効果が現れたり、消えたり、マイナスになったりする、ということは生じないはずである。

ということで、明日から、train専用モデルと、inference専用モデルを作るとともに、アンサンブルの方法も検討していくことにする。

 

2月24日(水)

HuBMAP:1,082 teams, two months to go

trainコード

・inferenceを切り離す(不要なセルを消去するのではなく、markdownに変更する)。

・trained_modelをsaveする。公開コードには次のようなコードが使われている。

torch.save(model.state_dict(), 'model.pth')

torch.save(model.state_dict(),f'FOLD-{fold}-model.pth')

・Foldを使う。公開コードで使われているコード例。容易ではないのでもう少しコードに慣れてからチャレンジする。

from sklearn.model_selection import GroupKFold

group_kfold = GroupKFold(n_splits = 3)

inferenceコード:

・Trainコードで、次のように識別しやすいファイル名で出力したstate.dict( )ファイルを、データセットにして、Inferenceコードのinput_datasetに加える。

torch.save(model.state_dict(), 'EfficientNetB5-Unet_model.pth') 

・inferenceコードで同じモデルを次のようにして準備し、データセットから、state_dictを読み込む。

model = smp.Unet('efficientnet-b5', encoder_weights='imagenet', classes=1)

path = '../input/state_dict_dataset/EfficientNetB5-Unet_model.pth'

state_dict = torch.load(path)

model.load_state_dict(state_dict)

明日、trainのコードセルをmarkdownに変更し、これらのコードを追加して、inferenceできるかどうか試してみよう。

 

2/21に計算し、commitしておいたものをsubmitしてみた。

EfficientNetBn-FPN-FocalLoss-OneCycleLR(AdamW, epoch=10)

B0: LB=0.793,  B1: LB=0.570,  B2: LB=0.817,  B3: LB=0.812

B4: LB=0.813,  B5: LB=0.822,  B6: LB=0.823

B0(epoch=10, BCELoss): LB=0.82+, B4(epoch=10, BCELoss): LB=0.830

*EfficientNetB7-Unetに対して、Focal Lossは他のLoss_functionより良いスコアを与えたこと、および、Focal Lossの論文を斜め読みして、Focal LossはFPNとの相性が良い、と思い込んだ結果がこれである。

 

Twitterで @Deep Learning Weeklyがtweetしていた論文:興味深い:

Unsupervised Semantic Segmentation by Contrasting Object Mask Proposals
Wouter Van Gansbeke1* Simon Vandenhende1* Stamatios Georgoulis2 Luc Van Gool1,2
1KU Leuven/ESAT-PSI 2ETH Zurich/CVL, TRACE,  arXiv:2102.06191v1 [cs.CV] 11 Feb 2021

f:id:AI_ML_DL:20210225002045p:plain

f:id:AI_ML_DL:20210225001407p:plain

f:id:AI_ML_DL:20210225001704p:plain

f:id:AI_ML_DL:20210225002150p:plain

 

糸球体の領域を過不足なく囲うことができるヒトは、糸球体をどう定義しているのだろうか。そのヒトは、1枚の光学顕微鏡像から、3次元構造を正しく想像することができているのだろう。それが正しくできるためには、細胞レベルでの腎臓の正しい3次元構造を知っていることが必要である。さらに、加工(包埋/凍結・切断)による変形・変質、染色等の化学処理による変形・変色などについての正しい知識を適切に適用することで、より正確に糸球体の境界を判定することが可能になるのだろう。同じことをコンピュータが自動的に行えるようにするためには、最初に与えられた課題と画像から必要な知識領域を判定し、課題解決に必要な知識を収集し、課題解決に必要な知識を集約し、知識を解析手段に変換し、画像を解析し、課題を解決するまでのプロセスを自動的に実行する。

 

2月25日(木)

HuBMAP: 1,090 teams, two months to go(締切日は、データ更新から2か月後)

今日は、trainedモデルのstate_dict( )をデータセットに格納し、inferenceコードにそのデータセットを追加し(+ add data)、そのデータセットからstate_dict( )を読み込み、inferenceモデルにstate_dict( )を読み込んで、inferenceを行う。

今日のテスト用に作ったtrained_modelは、EfficientNetB0-UnetとEfficientNetB0-MAnetであり、それらの学習済みモデルのパラメータ、EffB0-Unet-SBCE-model.pthとEffB0-MAnet-SBCE-model.pthは、データセットに入れた。

model_U = smp.Unet('efficientnet-b0', encoder_weights='imagenet', classes=1)

model_M = smp.MAnet('efficientnet-b0', encoder_weights='imagenet', classes=1)

path_U = '../input/state_dict_dataset/EffB0-Unet-SBCE-model.pth'

path_M = '../input/state_dict_dataset/EffB0-MAnet-SBCE-model.pth'

state_dict_U = torch.load(path_U)

state_dict_M = torch.load(path_M)

model_U.load_state_dict(state_dict_U)

model_M.load_state_dict(state_dict_M)

こんな感じで、2つの学習済みモデルをinferenceに使うことができるのだろうか。

試してみようとしたが、CPUだけだとメモリーオーバーになりやすく、かつ、予測も進まないので、土曜日の午前9時にGPUが使えるようになるまで本件は休止。

 

2月26日(金)

HubMAP:1,104 teams, two months to go

Albumentations Documentationsの入り口あたりをちょっと眺めていた。

import albumentations as A
import cv2

transform = A.Compose([
A.RandomCrop(width=256, height=256),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
])

AutoAlbument is an AutoML tool that learns image augmentation policies from data using the Faster AutoAugment algorithm. It relieves the user from manually selecting augmentations and tuning their parameters. AutoAlbument provides a complete ready-to-use configuration for an augmentation pipeline.

AutoAlbument supports image classification and semantic segmentation tasks. The library requires Python 3.6 or higher.

The source code and issue tracker are available at https://github.com/albumentations-team/autoalbument

この論文を読んでみよう。

Faster AutoAugment: Learning Augmentation Strategies using Backpropagation
Ryuichiro Hataya, Jan Zdenek, Kazuki Yoshizoe, and Hideki Nakayama

arXiv:1911.06987v1 [cs.CV] 16 Nov 2019  

 

2月27日(土)

GPU: 38h:≒ 5.4h/day

HuBMAP:1,111 teams, two months to go

1st public LB=0.896: my public LB=0.836: Δ=-0.06: very large

この差を埋める方法を探す:

現状を知る:予測結果を画像化する:難しい:検討中

 

画像サイズ、縮小率など、基本的なところを、検討することが必要である。画素数を、256, 320, 384, 448, 512と変えてみて、スコアがどうなるかを調べてみよう。といっても、画素数の大きな画像を扱うには小さなモデルを使うとか、バッチサイズを小さくするとかしないとメモリーオーバーになるので、スコアアップにつながる組み合わせを見つけるのは容易ではない。

 

EfficientNetB5-Decoderを計算したときに結果が出なかったPAN, DeepLabV3,および  DeepLabV3Plusの性能が気になっている。PSPNetも含め、DiceLoss, 30エポックの結果を調べてみたいと思って、再度、検討してみた。PSPNetはDiceLossの30エポックでLB=0.822となり、他のモデルより0.01以上小さい。PAN, DeepLabV3, およびDeepLabV3Plusは、前回調べたときには、GPUの残り時間が少なくなっていなかったので、少し待つだけでデータが出ないとあきらめていたが、今回は、1エポック目の結果が出るまで待ってみた、その結果、1エポックあたりのtrain時間が、他のDecoderの場合の10倍以上になることがわかった。以上のようにPSPNetは明らかに他よりスコアが低いこと、PAN, DeepLabV3,およびDeepLabV3Plusは、理由はわからないが、計算時間が長すぎるので、これ以上追求しないことにする。

 

inference専用コード:作成中

 

2月28日(日)

HuBMAP:1,115 teams, two months to go

素数増大の効果:

元画像の切り出しと縮小は、ここまで、公開コードをフォークしたときの値を変更せずに使ってきた。切り出しが1024x1024、これを256x256に解像度を下げて使っている。

EfficientNetB5-FPNで、256x256で、LB=0.835であったものを、320x320, 384x384, 512x512と変えてみた。GPUのメモリー占有量は、画素数を反映しているので、コードは正しく動作していると思うのだが、LBスコアは、0.829から0.835の間であった。

モリーオーバーを避けるために、B4またはB5、バッチ数は16または32とした。

コンペのディスカッションでも、低解像度でバッチ数を増やしてtrainingした方がLBスコアが高いと報告している人もいる。

HuBMAPコンペサイトのDiscussionから引用:

LB 0.837 : batch size =16 / size=320x320
LB 0.845 : batch size =32 / size=256x256

これは、ぜひ、検討してみよう。256x256のbatch=32だと、EfficientNetB5-Unetではメモリーオーバーになるので、B4EfficientNetB4-Unetにする必要がある。他のDecoderについては、調べる必要がある。

EfficientNetの番号を決めるときの根拠の1つになる。画素数が多くなるとメモリーを消費するのでバッチ数を上げられなくなる。それでもバッチ数を上げようとすると、EfficientNetの番号の小さいモデルを選ぶ必要が出てくる。最適な組み合わせは実験によってしか得られない。

FoldもTTAもアンサンブルも適切なタイルの作成も後処理もNoisyStudentもpseudo labelsもSelf-trainingも検討中。augmentationもoptimizerもlr-schedulerも検討中。

2月の目標:LB=0.84+には届かなかった。

 

f:id:AI_ML_DL:20210131221532p:plain

style=163 iterations=500

f:id:AI_ML_DL:20210131221655p:plain

style=163 iterations=50

f:id:AI_ML_DL:20210131221742p:plain

style=163 iterations=5

 

Kaggle散歩(January 2021)

Kaggle散歩(January 2021)

1月7日に、Riiidコンペが終了する。:1月8日追記:Riiidコンペは393位だった。72時間くらいの間に100チームくらいに追い越された。これがKaggleだ!

その後は、

HuBMAP - Hacking the Kidney
Identify glomeruli in human kidney tissue images

を考えている。

このテーマから、Discussionとnotebookの全ての関連情報(引用文献、引用コードを含む)に目を通すことによって知識を増やし、研究者レベルのコード開発を目指していきたいと思っている。

1月は、前処理、モデル構築と訓練、予測とsubmissionデータの作成、の順にベースモデルを作成する予定である。

 

1月1日(金)

Riiid AIEd Challenge, 3,221 teams, 7 days to go

private LB scoreが見えてしまうというトラブルがあったようだ。

公平を期するために、各人の昨年のある時点までの投稿データのうち、private LBスコアが最も高いものについて、private LB scoreを見ることができるようになっている。

"To retrieve your team’s score as of 2020-12-29 16:00:48 UTC, please visit this link."

こういうことは、メールで参加者に伝えられるのではなく、Discussionをチェックして、自分で気づかないとわからない。

必要な情報は、コンペサイトの中(Discussion)で適切に表示されるので、参加者の責任で取得する、というのが、Kaggleのルールになっている。

 

1月2日(土)

Riiid AIEd Challenge, 3,238 teams, 6 days to go

featureの選択にしても、LGBMのチューニングにしても、もう限界のようだ。

それでもまだ終わっていないので、何か手段を講じてスコアを上げたいものだ。 

 

Discussion

Most Votesでsortして、順にみていこう。

最初はKaggleのstaffによるメッセージである。

SAINT+: A Transformer-based model for correctness prediction

SAINT+はRiiidの研究者によって開発されたtransformerベースのプログラムで、論文へのリンクが張られている。このコンペに参加した当初は自分で文献調査して同じ論文を見つけて、”しめしめ”と思ったのだが、その時すでにDiscussionでKaggleのスタッフから紹介されていたようである。

さらに、トピックには、コメント(Comments)がつく。Kagglerたちが、トピックオーサー(ここではKaggleスタッフの1人)に対して質問したり、関連情報を交換したり、Kagglerどうしで、当該トピックスに関連した議論をする。

GitHubにSAINTとSAKTのコード例が公開されているとか、コンペサイト内にそれらしいコードが公開されているとか、コードにデータを入力するためにfeatureをベクトル化する方法を聞くとか、transformerモデルのコーディングの基礎が紹介されているサイトを紹介する、などのやりとりがある。SAINTやSAKTなどのNNと、LGBMとの比較。データ量が多いので、データハンドリング方法の工夫が必要だとか。コーディングに長けた人が、テストデータに対するハンドリング方法のコード例を具体的に示すこともある。

次は、kaggle staffによる新規参加者に対するlectureや注意事項の説明である。内容は省略するが、Kaggle内における遵守事項は重要である。

次は、kaggle staffによる、private scoreの情報が漏れたことへの対応に関するものである。kaggle staffが熟慮して決められた方法を受け入れるべきだと思う。が、しかし、金メダルレベル、賞金レベルの人達にとっては、公開される情報の質と量は非常に重要であり、真に公平な解決方法はないのかもしれない。

あとは、kaggel staffによるwelcome message、 課題提供者の挨拶、kaggle staffによるチーム結成の案内などがある。

次から、参加者からのトピックスである。

最初は、投票数256(upvote)、コメントや返信が40件ほどある。2か月前の投稿で、課題解決の参考になる情報である。課題解決のヒントになる情報で、特に、上記のSAINTの情報を調べると、GBM系よりもNN系が良さそうに思うだろうが、LGBMモデルベースでpublic LB=0.789を得ている、と記されている。

こういう情報は、締切日が近くなると、公開することに問題があると考えられなくもないが(他にこの種の情報が公開されていない場合)、締め切りまでにまだ2か月あるので、多くの人に有用だと考えて公開することにした、と書かれている。これ以外にも非常に本質的で有用な情報が含まれていて、全体のレベルを上げるのに貢献している優れた内容の投稿だと思う。

いまごろ読んでも遅いのかもしれないが、理解が深まってきた今だからこそ理解できる内容もたくさんある。

これ以上は書いてもきりがないので、書かないが、チューニングの合間に読み進めていきたいと思う。

 

1月3日(日)

  • Riiid AIEd Challenge
  • , 3,258 teams
  • , 5 days to go

なかなかスコアが上がらず、順位が下がっていく。このままだと、あと2日くらいでメダル圏外に放り出されそうだ。

min_data_in_leaf、SAKTとLGBMの比率、などの最適値を探索中。

アンサンブルの比率について:公開コードで、0.771と0.772くらいのアンサンブルで0.782になるというのがあって驚いたが、1.4%程度の増大である。小さくはないが驚くほどでもない変化幅である。

 

HuBMAP:

締切が当初の2月初旬から3月下旬に変更された。

実質、今日から参加。

Your challenge is to detect functional tissue units (FTUs) across different tissue preparation pipelines. An FTU is defined as a “three-dimensional block of cells centered around a capillary, such that each cell in this block is within diffusion distance from any other cell in the same block” (de Bono, 2013). The goal of this competition is the implementation of a successful and robust glomeruli FTU detector.:Descriptionより

あなたの課題は、さまざまな組織準備パイプライン全体で機能組織ユニット(FTU)を検出することです。 FTUは、「毛細血管を中心とするセルの3次元ブロックであり、このブロック内の各セルが同じブロック内の他のセルから拡散距離内にある」と定義されています(de Bono、2013)。 この競争の目標は、成功した堅牢な糸球体FTU検出器の実装です。:グーグル翻訳

The focus of HuBMAP is understanding the intrinsic intra-, inter-, and extra- cellular biomolecular distribution in human tissue. HuBMAP will focus on fresh, fixed, or frozen healthy human tissue using in situ and dissociative techniques that have high-spatial resolution.

The HubMAP Data Portal aims to be an open map of the human body at the cellular level. These tools and maps are openly available, to accelerate understanding of the relationships between cell and tissue organization and function and human health.

HuBMAPの焦点は、ヒト組織における固有の細胞内、細胞間、および細胞外の生体分子分布を理解することです。 HuBMAPは、高い空間分解能を持つin situおよび解離技術を使用して、新鮮な、固定された、または凍結された健康なヒト組織に焦点を当てます。

HubMAPデータポータルは、細胞レベルでの人体のオープンマップを目指しています。 これらのツールとマップは公開されており、細胞と組織の組織と機能および人間の健康との関係の理解を促進します。:グーグル翻訳

 

1月4日(月)

Riiid AIEd Challenge, 3,285 teams, 4 days to go ,286th

順位の後退速度の速さには勝てないが、ほんの少し前進した(283th)。

しかし、22:30現在、290thまで下がった。

 

InnovationDigi(HuBMAP - Hacking the Kidney
Identify glomeruli in human kidney tissue images
), 766 teams, 3 months to go

課題提供者からのメッセージと情報:

We are very much looking forward to the innovative solutions teams will generate to identify glomeruli in images of human kidney tissue.

私たちは、人間の腎臓組織の画像から糸球体glomeruliを特定するためにチームが生成する革新的なソリューションを非常に楽しみにしています。

提供されるデータ:

The kidney images and their segmentation masks, both of anatomical structures and glomeruli, were generated by HuBMAP’s tissue mapping center at Vanderbilt University (TMC-VU) team at the BIOmolecular Multimodal Imaging Center (BIOMIC). The glomeruli masks were further improved to provide a "gold standard" by the Indiana University team through a combination of manual and machine learning efforts. Any annotations of glomeruli that were considered incorrect, ambiguous, or originating from damaged portions of the images were removed.

解剖学的構造と糸球体の両方の腎臓画像とそのセグメンテーションマスクは、BIOmolecule Multimodal Imaging Center(BIOMIC)のヴァンダービルト大学(TMC-VU)チームにあるHuBMAPの組織マッピングセンターによって生成されました。 糸球体マスクはさらに改良され、手動学習と機械学習の組み合わせを通じて、インディアナ大学チームによって「ゴールドスタンダード」を提供しました。 不正確、曖昧、または画像の損傷部分に由来すると見なされた糸球体の注釈はすべて削除されました。

先行研究:5件の論文が紹介されている。

f:id:AI_ML_DL:20210104111238p:plain

感想:目的物以外の検出、分野の固有評価方法の援用などが使えそう。解析ソフトは既製品で、GitHubにある。

"This Github page explains how to use the output of ilastik classification in segmentation .tiff files and obtain disease scores per glomeruli."「このGithubページでは、セグメンテーション.tiffファイルでilastik分類の出力を使用して、糸球体ごとの疾患スコアを取得する方法について説明します。グーグル翻訳」

この"ilastik classification"について調べてみた。

"Leverage machine learning algorithms to easily segment, classify, track and count your cells or other experimental data. Most operations are interactive, even on large datasets: you just draw the labels and immediately see the result. No machine learning expertise required."

機械学習アルゴリズムを活用して、細胞やその他の実験データを簡単にセグメント化、分類、追跡、カウントします。 大規模なデータセットであっても、ほとんどの操作はインタラクティブです。ラベルを描画するだけで、すぐに結果が表示されます。 機械学習の専門知識は必要ありません。グーグル翻訳」

既製品なので、コンペで使うものではない。

NotebooksとDiscussionにおいて"ilastik"で検索したが何も出てこない。

次は2つめの論文:

Glomerulus Classification and Detection Based on Convolutional Neural Networks
Jaime Gallego, Anibal Pedraza, Samuel Lopez, Georg Steiner, Lucia Gonzalez, Arvydas Laurinavicius and Gloria Bueno

In this paper we propose two methods devoted to: Glomerulus classification and Glomerulus detection. In the Glomerulus classification proposal (Method I), we study the viability of the CNN to achieve a correct Glomerulus classification into Glomerulus/non-Glomerulus classes. In the Glomerulus detection method (Method II), we use the CNN configuration that gave the best results and performance for Glomerulus classification (Method I) to achieve the Glomeruli detection in a WSI. In this proposal, we present a method suitable for PAS samples belonging to different laboratories, thanks to color normalization process used in the data augmentation step. Our method uses a sliding
window with overlapping to perform the detection, and utilizes a majority vote decision for each pixel to reduce false positive detections. With this proposal, we achieve a detection score of 93.7%, which improves upon the results obtained in reference methods.

「 この論文では、糸球体分類と糸球体検出の2つの方法を提案します。 糸球体分類提案(方法I)では、CNNの実行可能性を調査して、糸球体/非糸球体クラスへの正しい糸球体分類を実現します。 糸球体検出法(方法II)では、糸球体分類(方法I)で最高の結果とパフォーマンスを提供するCNN構成を使用して、WSI(Whole Slide Images)で糸球体検出を実現します。 この提案では、データ拡張ステップで使用される色の正規化プロセスのおかげで、さまざまな研究所に属するPAS(Periodic Acid Schiff)サンプルに適した方法を提示します。 私たちの方法は、オーバーラップのあるスライディングウィンドウを使用して検出を実行し、各ピクセルの多数決を利用して誤検出を減らします。 この提案により、93.7%の検出スコアを達成し、参照方法で得られた結果を改善します。グーグル翻訳」

論文はこのくらいにしておこう。自分が良い結果を得て論文にしようとするときには、先行研究を引用しながら自分の研究のどこが先行研究と異なっているかを説明するために用いる。今の自分のレベルと3月末の締め切り日を考えると、新しい評価方法を考案し良い結果を得て論文にまとめることになるとは考えにくい。

課題提供者からの情報のもっと重要な部分に移ろう。

(How to Convert Polygon Masks to Pixel Masks)と(How to Perform Run-Length Encoding)である。多角形で与えられたマスクをピクセルマスクに変換するコードと、検出領域を報告する書式の説明である。

データを眺めてみよう。

とりあえず、論文の画像。

f:id:AI_ML_DL:20210104235805p:plain

f:id:AI_ML_DL:20210104235936p:plain

f:id:AI_ML_DL:20210105000050p:plain

f:id:AI_ML_DL:20210105000152p:plain

f:id:AI_ML_DL:20210105000259p:plain

f:id:AI_ML_DL:20210105000353p:plain

f:id:AI_ML_DL:20210105000434p:plain

f:id:AI_ML_DL:20210105000525p:plain

f:id:AI_ML_DL:20210105000609p:plain

f:id:AI_ML_DL:20210105000709p:plain

f:id:AI_ML_DL:20210105000752p:plain

f:id:AI_ML_DL:20210105000959p:plain


f:id:AI_ML_DL:20210105000905p:plain

f:id:AI_ML_DL:20210105001129p:plain

f:id:AI_ML_DL:20210105001627p:plain

f:id:AI_ML_DL:20210105001736p:plain

以上は主催者がDiscussionで紹介されている5件の論文から転載したものである。

 

1月5日(火)

Riiid AIEd Challenge, 3,312 teams, 3 days to go:301th(9:12)

進展なし。

 

1月6日(水)

Riiid AIEd Challenge, 3,344 teams, 2 days to go:327th

チューニング中!

夜中に、メダル圏外に放出されました。

あと1日ある。さらに離されるか、それとも・・・。

 

HuBMAP, 783 teams, 3 months to go

ベースモデルを作成しようとしている。

edaとbaselineをキーワードに、公開コードから、自分でハンドリングできそうなコードを探しているのだが、なかなか見つけられない。

チューニングの立場から見ると、チューニングしやすいコードは、スコアに関係しているコードがどれであるか、がわかりやすく、理解しやすく、かつ、パラメータだけでなく、コードの変更も容易であるということになる。目の前のコードがどこまであてはまるかは、見る側のコード理解力、コード構成能力による。

いわゆるベースラインコードと呼ばれるものは、初級レベルの人にも理解しやすいということに加えて、前処理も、訓練/予測モデルも教科書的であり、必要最小限の機能をもつだけであることが多い。

ゼロから作るのは難しく、ベースラインとなるコードから始めるということであれば、これまでと同じように、チューニングしやすいコードを探すことから始めるのがよさそうであるということになる。

これまでと変えたいと思っているのは、フォークしたコードは、理解できる範囲でチューニングするのではなく、隅々まで理解して、あらゆる箇所に手を加えることができるようになることである。

1つのモデルを選定した。そのモデルの作成者は、機械学習ディープラーニングの中級であると自称している。Kaggleのcompetition, notebook, およびdiscussionのexpertである。

前処理が約110行、訓練が約30行、予測も約30行で、その他が約120行である。

順に理解していこう。

前処理は3種類あり、1つは、マスクの処理で、Run-Length Encodingに関する処理のための関数:rle_encode, rle_decodeなど、もう1つは、画像の分割、最後に、画像とマスクのデータセットの作成である。

 

1月7日(木)

 Riiid AIEd Challenge, 3,366 teams, a day to go:350th

メダル圏外に放出された。

完敗です。

チューニングメインの戦いはこれを最後にする。

最後にちょっと面白い現象を見ることができた。

フォークしたとき、feature_fractionの値は、0.52に設定されていた。意味が分からずそのまま使っていたが、12月29日に、先が見えなくなって、意味も分からず、0.75と0.25を試してみたら、0.25の場合にpublic LBが上がった。といっても数値は変わらず順位が少し上がっただけである。翌日、0.20を試してみたら、さらに、順位が少し上がった。それ以降0.2がベストだと思い込んでそのまま使っていた。今日、もうすることがなくなって、試しに、feature_fractionを外してみた(デフォルトは1.0)。そうすると、収束後のfeature_importanceの分布が0.2の場合とは全く違うものになった。0.2の場合は、40近くのfeatureを使っていても、ほぼ全てのfeatureがそれなりに寄与していたのだが、デフォルトの1.0では、20個を超えたくらいから寄与が非常に小さくなった。寄与率の減衰率が明らかに大きくなったのである。0.2に設定すると、ランダムに選ばれた2割のfeatureで最適化しようとするから、もともと重要でないfeatureでも無理に使われていたのかもしれない。さらに、0.2では、計算の都度、val_AUCがかなりばらついたし、feature_importanceもval_AUCと同様、計算するたびに、明らかに分布が異なっていたように思う。本質的ではないところで時間を無駄にしたような気がする。上位にいくためには、こんなチューニングよりは、アンサンブルの片割れのSAKTのチューニング、もしくは、SAKTのSAINTとの置き換えに時間を使ったほうが良かったのではないかと思う。

 

HuBMAP:796 teams, 3 months to go

Run-Length Encodingについては、コンペの課題提供グループから、説明図付きでコードが提供されている。

f:id:AI_ML_DL:20210105000905p:plain

これはglomerulusとマスクの画像の例である。このマスクは、glomerulusの領域を正しく表現しているのだろうか。

もっと詳細な評価をしている論文はないのか。

f:id:AI_ML_DL:20210107100256p:plain

この論文では、 glomerular lesions(糸球体の病変)まで検出している。

f:id:AI_ML_DL:20210107101640p:plain

The convolutional neural networks implemented in this paper consist of U-Net, DenseNet, LSTM-GCNet, and 2D V-Net. All of these architectures receive images
with labels, and output the corresponding predictions. UNet [33], consists of several contracting paths to capture context and symmetric expanding paths which enable
precise segmentation and location.

このホワイトペーパーで実装されている畳み込みニューラルネットワークは、U-Net、DenseNet、LSTM-GCNet、および2DV-Netで構成されています。 これらのアーキテクチャはすべて、ラベル付きの画像を受け取り、対応する予測を出力します。 UNet [33]は、コンテキストをキャプチャするためのいくつかの縮小パスと、正確なセグメンテーションとロケーションを可能にする対称的な拡張パスで構成されています。(グーグル翻訳)

画像解析には、U-Net、DenseNet、LSTM-GCNet、および2DV-Netを用いていると書かれており、最初の段階である糸球体の検出とセグメンテーションには、U-Netが用いられている。

もう1つの論文を見よう。

f:id:AI_ML_DL:20210107112013p:plain

この論文の解析対象は、糸球体の内部に存在するスパイク状の構造である。

f:id:AI_ML_DL:20210107112139p:plain

f:id:AI_ML_DL:20210107112535p:plain

U-Netでセグメンテーションを行い、その内部にあるスパイク構造をResNetで検出・分類している。コンペの課題は、この図では、前処理段階に相当する。

セグメンテーションの正確さが問われているが、正確さの評価は Dice coefficient、
f:id:AI_ML_DL:20210107114325p:plain

すなわち、正しいマスクと予測したマスクとの重なり度合いで評価される。

train_dataのマスクと、test_dataのマスクのグレードは同じであると仮定すると、train_dataのマスクを用いて訓練するのが最良だと思うが、どうなんだろう。

Run-Length Encodingについて考えているうちに、検出しようとしている糸球体の形状の詳細と対応するマスクの形状との関係が気になって、以上の論文を調べてみた。

コンペの画像とマスクの位置関係を見ていると、マスクは糸球体そのものだけでなく、糸球体を覆っている境界層、および境界層と糸球体の隙間も含んでいるように見える。

ウイキペディアの模式図はつぎのように描かれている。

f:id:AI_ML_DL:20210107090551p:plain

Bowman's capsuleは、自分が見た範囲(上記論文およびコンペの画像数枚)では、この模式図ほどは厚くないようであるが、コンペのマスクが、総じてこのカプセルを含んでいるように見える。マスクは提供されたまま使うべきかどうか。マスクのサイズや形状を変えたらどうなるのか気になるので、変えられるようにしよう。

*1月8日追記:2か月前にマスクの正確さについてユーザーから問題提起され、スタッフが対応したことがdiscussionに残されている。その後、private_test_dataにおいても不具合が見つかり、その対応のために、コンペ期間が3月下旬まで延長されることになったということのようである。

主催者が用意している情報をもう一度最初からチェックする。

discussionのタイトル:Welcome to the HuBMAP: Hacking the Kidney Competition!

最初のnotebookのタイトル:Dataset Details

Normal glomeruli typically range from 100-350 μm in diameter with a roughly spherical shape (Kannan, 2019)30155-X/abstract). 

f:id:AI_ML_DL:20210107135300p:plain

図3は、PASで染色されたヒト腎臓組織のサブセクションからの糸球体を含む光学顕微鏡画像です。 細胞の遺伝物質(核酸で構成される染色体)を含む、細胞ごとに1つの核(球形)は、PAS染色画像で濃い青紫色に染色されます。 PAS染色組織のマゼンタ染色領域は、染色された多糖類です。グーグル翻訳

f:id:AI_ML_DL:20210107150934p:plain

Figure 3: Glomerulus within PAS Stain Kidney Image

次は、Polygon to Pixel Mask Conversionのnotebookから学ぼう。

学ぶだけでは前進できない。

さあ、新しく、自分のnotebookを立ち上げよう。
 

1月8日(金)

  • Riiid AIEd Challenge
  • 3,399 teams, 
  • 2 hours to go:393th 

結果:目標としていた銀メダル以上に届かなかった。

成果:LightGBMに対する理解が増した。

反省:

1.feature engineeringの技術習得が進まなかった。

2.AI Educationへの興味が続かず、当該分野の本質を理解できなかった。(プログラミングやチューニングは手段であり、メダル取得、賞金取得などは目標ではあっても目的ではない。目的はAIの技術開発に寄与することであり、それを実現するためには、コンペの課題をもっと深く理解し、AIをどう使えばこれまでと違うレベルのことができるようになるのかを考え続ける状態を維持しなければならなかったと思う。目標に集中するあまり、目的を見失っていたということになる。当該コンペの開催期間中は当該コンペの課題に集中しなければ何も得られずにおわってしまうということ。期間が短いので、より集中力を高めて取り組まないと身に付かないのだろうと思う。)

3.Riiidコンペが終了する前に次のコンペに取り掛かったのはまずかった。1月3日、Riiidのドラフト計算とcommitの待ち時間に、次のコンペをどれにしようかと考え、on goingのコンペを調べているうちに、HuBMAPに入り込み、お手本になりそうなコードをフォークしてsubmitまでしてしまった。Riiidモデルの見直しやfeature選択の見直しなどやるべきことがあったはずなのに、メダル圏内残留を諦めたようになってしまった。コンペの最後の3日間に集中できなかったことは、反省、反省、反省。

感想:

ちょっと調べたら、すでに商品化されていること、商品化のベースとなっていると推測されるレベルの高い予測モデルが論文発表されていることなどがわかった。それにもかかわらず賞金までつけてKaggleに課題を出したということは、トップレベルのKagglerへの挑戦(状)であって、自分の出る幕ではないと感じた。だからこそ自分の取り組み方を変えなければと思いながら取り組み始めたが、公開コードのチューニングから抜け出せず、途中であきらめようとしたが、それでも何かを学ばねばという思いで取り組んでいた。しかしながら、結局は、チューニングのどつぼにはまってしまったということだ。また、終盤に集中を切らした理由の1つは、銀のレベルまで上がる可能性がなくなったことである。次のレベルに上がるには銀以上が必要だから。

 

HuBMAP:805 teams, 3 months to go:624th(仮)

notebookの立ち上げ:今日は枠組みを作ろう。

1.notebookのタイトル

・公開コードからキーワードを拾ってみると、(PyTorch or Fastai or Keras or TF)、(EffUNet or ResUNet or PraNet or RetinaNet or FPN or Double UNet or ...)、(GPU or TPU)、・・・

2.構成:概要説明、import、configuration、前処理(preprocess)、augmentation(PyTorch :albumentations) 、モデル(model)、訓練(train)、予測(inference)、TTA、後処理(postprocess)、submitファイルの作成など。

・公開コードから、どのようにパーツを配置しているのかを学ぼう。

・1つ1つのセルに、どれだけのコードを入れるのか。1セル、1機能とか。

・注釈は、どの位置に、どのように入れるのか。マークダウンセルを使う。コードセルの先頭に書く。クラスや関数の直前に書く。

・わかりやすいコードの書き方、改造しやすいコードの書き方。

 

1月11日(月)

HuBMAP

さあ、自分のnotebookを作ろう。

HuBMAPのコンペサイトで、New Notebookをクリックし、Notebookを選択し、Createをクリックすると、notebookが立ち上がる。

notebookのタイトルは、"notebook84f8ff2dab"のように、自動的に割り当てられる。そのタイトルのまま使うのは不便なので、コードの内容を表すタイトルに変更する。

*notebookのタイトル変更:仮に、"HuBMAP TF/Keras UNet"としておこう。

notebookには、コンペのDatasetがデフォルトで付属する。

Notebookを説明しているセルが1つデフォルトで付属する。

そのセルは、実行すると、pandasとnumpyとosをimportし、Datasetのディレクト名やファイル名を表示する。ファイル名の拡張子は、csvの他に、tiffjsonがある。

 

1月12日(火)

HuBMAP:839 teams, 2 months to go

自分のnotebookを作ろうとしている。

そのnotebookのタイトルを仮に"HuBMAP TF/Keras UNet"としたのは、HuBMAPのコンペで、プログラムをTF/Kerasで記述し、UNetを使って、glomeruli FTU(functional tissue units )を検出しようと考えている、ということである。

notebookを立ち上げた時にデフォルトで付いていたセルはそのまま使う。これを1番目のセルとする。1番目のセルは手を加えずにそのまま使うことにする。

2番目のセルをどうしようか迷っている。よくあるパターンは、モジュールとかパッケージをimportすることである。

プログラムを作る順番を、迷う必要はない。セルの追加・削除、順番の入れ替えなどは、いつでも、容易にできるので、1セル1機能の考え方で、とにかく必要なセルを作っていこう。

ようやく、train.csvを読み込んでtableを表示した。8つの画像のidとマスクの位置情報(RLE encoded segmentation masks)が含まれている。

まずは、画像とマスクを表示してみよう。

画像を読み込んで表示してみた。ファイルサイズが大きいので、適切なタイミングで消去しなければ、メモリーオーバーになって、プログラムは途中で停止してしまう。

 

1月13日(水)

HuBMAP:849 teams, 2 months to go (Mar 26)

今日は、マスクデータの操作方法を学ぶ。

Paulo Pinto氏により公開された、Severstal: Steel Defect Detectionのコンペにおける"mask2rle"と"rle2mask"のコードが、このコンペの公開コードで引用されている。

"mask2rle"のコードは、実質6行、"rle2mask"のコードは、実質9行である。

rle2maskには、shape=(1600, 256)というように画像サイズが指定されていて、違和感を感じたが、これは、Severstal: Steel Defect Detectionコンペのsteel試験片の画像サイズに対応しているので、目的とする画像サイズに合わせればよいということがわかる。

理解しておくべき主なキーワードは、"T", "flatten", "concatenate", "where", "join", "split"である。 

Notebooks Grandmasterのiafoss氏も同様なコードを使っており、扱いにくい大きな画像を短冊状に切り出して使いやすくした画像のデータセットを公開されているので、iafoss氏のコードも見ておく。iafoss氏の関数のネーミングは、"mask2enc" と "enc2mask" となっている。

この2つの関数 "mask2enc"  と "enc2mask" を使うことにして、先へ進む。

 

1月14日(木)

HuBMAP

いろいろなコードを見ていると、目移りして、現在位置がわからなくなった。

自分のnotebookは、1週間経っても、まだ、"train/0486052bb.tiff"を表示しただけである。

1月6日に、trainとinferenceを含む公開コードの1つを選んで、それに倣って、自前のコードを構築するつもりだったが、2,3日の中断の間にそのことから離れてしまっていた。その公開コードにもどろう。

そのコードは、train+inferenceであり、submitしてpubliv LBも得られているので、学ぶには適切だと思ったが、入力データが3つあって(input(3))、PreTrain coco weightsと、PyTorch pretrained modelsが含まれている。こういうデータセットは有用だが、最初からこれを使ってしまうと、それに縛られて次の展開が難しくなるかもしれないので、入力データが、コンペのデータセットのみ(input(1))のコードを探した。そうすると、version1がそれに該当し、かつ、そのコードは公開コードのコピーではないことがわかったので、version1をお手本にして次に進もう。

version1はtrainまでだが、そのtrainの結果を見ると、1エポックに約40分かかっており、かつ、train BCEは順調に下がっているが、valid BCEは1度下がっただけで反転、すなわち3エポック目でoverfittingになっている。

モデルは、torchvision.models.segmentation.fcn_resnet50(True)を使っている。

PyTorchのドキュメンテーションを見ると、Semantic Segmentationとして、FCN ResNetとDeepLabV3 ResNetの2種類がある。

notebookのタイトルからは、EffUNet, ResUNet, PraNet, RetinaNet, FPN, Double UNet, Unet++などのモデルが使われていることがわかった。

それぞれの特徴を調べてみようと思って文献を検索してみた。特徴を調べると書いたが、本音は、糸球体の領域を正しく検出できるモデルはどれかを知りたいということである。しかし、糸球体をDNNで調べる最終的な目的は、糸球体の病態を調べることにあるからだろうと思うのだが、今回のコンペのように糸球体の領域をいかに正確に切り出すことができるか、ということについて、種々のモデルを比較した論文は見つけられなかった。自分でやってみて論文にまとめると面白いかもしれない。しかしながら、本当に重要なのはこれまでのどのモデルよりも正確に評価するモデルを構築することだ。

input(1)にこだわっていたが、このコードの作者は、version4(input(3))において、学習済みモデルを使用するなどの対策を講じることによって、train時間を短縮し、val_lossを低減することに成功し、かつsubmissionファイルも完成させているので、このversion4の理解を次の目標にする。

version4のセルの総数は20。セル1からセル5までは準備。

セル6は、rle_encode, rle_decode, make_grid(画像の分割)。

セル7は、全く理解できない。セル8は、・・・。セル9は画像とマスクのペアを描画して確認。

セル10とセル11は、train_dataとval_dataへの分割か?

セル12からセル17までは、get_modelからtrainまで。セル18で不要なデータを消去。

セル19は、test_dataの処理と予測とsubmissionデータの作成。

セル20は、submissionファイルの作成。

 

1月15日(金)

HuBMAP:

セル単位で理解しながら、1語づつ、1行づつ、丁寧に転記していこうと思ったが、理解が追い付かず、思うように進まないので、夕方になって、version 4の20のセルの全てをコピペした。

これをRunしたら、これまでのチューニングと、ほぼ同じことになる。

学びやすいコードを選んだ結果、PyTorchを使うことになった。notebookの名前は、TF/Keras UNetとしていたが、中身は、現時点では、PyTorch FCN ResNet50である。

FCN ResNet101、DeepLabV3 ResNet50、DeepLabV3 ResNet101などを使ってみることについては、比較的容易にできそうである。

この中では、DeepLabV3 ResNet101が最も性能が高そうだが、Kaggle kernelで動かせるかどうかわからないが、やってみればわかること。

それよりも、EfficientNetとUNetの組み合わせが良さそうなので、UNet with EfficientNet Encoderモデルを調査しよう。

 

 1月16日(土)

HuBMAP

UNet with EfficientNet Encoderを論文を見ながら組み上げる力はないので、コードを探してみる。

最初に探すべき場所は、GitHubであろう。

efficientnet unetで検索すると14件のrepositoryが出てきた。

segmentation modelを包括的に扱っているrepositoryでは、Unet, Linknet, FPN(Feature Pyramid Network), PSPNet(Pyramid Scene Parsing Network)の4種類のモデルと、VGGからEfficientNetまで10種類(サイズまでカウントすれば32種類)のbackboneの組み合わせが紹介されている。

当該コンペ内で、Unetがどのように使われているかを調べてみると、ほぼ、上記のGitHubサイトからの引用であることがわかった。

ということで、明日は、すでに誰かが作成しているデータセットがあればそれを使うこととし、もし、便利に使えるデータセットがなければ、自分でデータセットを作ってみようと思う。

最初は、網羅的なことは考えず、EfficientNetをbackboneとするUnetを、intenet offで使えるようにする。 

 

1月17日(日)

HuBMAP

インターネットに接続しておけば、次のコードで簡単にインストールできるのだが、

!pip install git+https://github.com/qubvel/segmentation_models.pytorch

これをデータセットにして、インプットデータに加えて、次のコードでインストールしようとしたが、うまくいかなかった。

!pip install ../input/qubvelsegmentationmodelspytorch -f ./ --no-index

"qubvelsegmentationmodelspytorch"は、作成したデータセットのファイル名である。

次のようなメッセージが現れて停止する。

Looking in links: ./
Processing /kaggle/input/qubvelsegmentationmodelspytorch
Requirement already satisfied: torchvision>=0.3.0 in /opt/conda/lib/python3.7/site-packages (from segmentation-models-pytorch==0.1.3) (0.8.1)
ERROR: Could not find a version that satisfies the requirement pretrainedmodels==0.7.4 (from segmentation-models-pytorch)
ERROR: No matching distribution found for pretrainedmodels==0.7.

requirements.txt は、以下の内容である。

torchvision>=0.3.0
pretrainedmodels==0.7.4
efficientnet-pytorch==0.6.3
timm==0.3.2

これらのモジュール/パッケージがインストール済みであることが前提になっているのだろう。ということだとすると、Kaggle kernelの中を把握し、それを適切にコントロールできることが必要なのだろう。 

 

1月18日(月)

HuBMAP

GitHubにあるsegmentation modelをHuBMAP用のnotebookで使えるようにするために、今日は、Kaggle の notebook について学ぼう。

 

***急用が入ったので中断 ***

 

1月20日(水)

HuBMAP: 

1月18日に調べていたnotebookのDockerについて、作業を進めよう。

KaggleのNotebookのサイトのトップページに移動する。

Notebooks
Explore and run data science and machine learning notebooks. Learn More.

トップページにある、このLearn More.をクリックすると、次のサイトに移動する。

How to Use Kaggle
Help and Documentation

ここから、Notebooks/The notebook Environment/modifying a Notebook-specific Environmentと辿れば、notebookのDockerの使い方がわかる。

自分が今使っているnotebookのセルにおいて、!pip install my-new-package(!pip install pretrainedmodels==0.7.4)を実行すれば、notebookのDocker containerに、モジュールやパッケージを、インストールすることができる。

既に存在するパッケージのバージョンを変更したい場合は、!pip install my-existing-package==X.Y.Zとすればよい。

ということで、次の3つをインストールした。

!pip install pretrainedmodels==0.7.4
!pip install efficientnet-pytorch==0.6.3
!pip install timm==0.3.2

この3つを、今使っているnotebookにインストールしておけば、インターネットを閉じて、notebookにinput dataとしてアップロードしたdatasetに格納したPyTorchのsegmentation modelsをインストールすることができることを確認した。

これで、課題を1つクリヤすることができた。

インストールしたモジュールやパッケージがnotebookのDockerに格納されているかどうかは、notebookのセルで、!pip listを実行すれば、確認することができる。

このDockerの状態が、notebookに対して別の作業をしたときにも保持されているかどうかは、まだわからない。

明日から、segmentation modelsに入っていて、notebookのDockerに格納されたであろうパッケージ内にあるモデルを読み込んで、現状のモデル "Pytorch FCN-Resnet50"と置き換えることに挑戦する。

最初に、EfficientNet-Unetを使えるようにする。

 

1月21日(木)

notebookのDockerへのパッケージの追加はうまくいったと思ったが、Run allを実行すると、追加したパッケージは削除されていた。

特定のnotebookに特定のDockerを付属させることができるようだが、再スタートするとインストールされたはずのパッケージが消えている。

Kaggleの説明文:

Modifying a Notebook-specific Environment
It is also possible to modify the Docker container associated with the current Notebook image.

Using a standard package installer
In the Notebook Editor, make sure "Internet" is enabled in the Settings pane (it will be by default if it's a new notebook).

For Python, you can run arbitrary shell commands by prepending ! to a code cell. For instance, to install a new package using pip, run !pip install my-new-package. You can also upgrade or downgrade an existing package by running !pip install my-existing-package==X.Y.Z.

!pip installを実行すれば、確かに、新たにDocker containerに、インストールしたことを!pip listによって、確認することができる。

Restart sessionで、元の木阿弥になる、インストールしたパッケージが消えてしまうのだ。

変更したDocker imageを使うのだから、Environment Preferenceの、Pin to original environmentではなく、Always use latest environmentを選んでいる。

インターネットOnで、パッケージをインストールした後、インターネットOffにして、ドラフトを走らせれば良いのではないかと思うのだが、うまくいってない。timmとかefficientnet-pytorchなども、datasetに入れて、inputdataとして読み込んでインストールできれば良いのだが、できないだろうか。

 

HuBMAP:892 teams, 2 months to go : 698th(0.827)

FCN-Resnet50のかわりに、とりあえず、DeepLabV3 Resnet50を使おうとしたら、エラーが出てしまった。うまくいかないものだ。まだ、コードの理解が足らないのだろう。torchvisionに入っているのだから、簡単だろうと思ったのだが、うまくいかない。

 

1月22日(金)

HuBMAP

Dockerにパッケージを追加してからinternet offにしてRun allにすれば計算は可能で、submitも可能(エラーは出ない)であることを確認した。

しかし、commitの結果を見ると、プログラムの最初に実行した!pip listによって、ドラフト計算中に存在していたはずのパッケージが消失していることが分かった。

internet offの条件付きのコードコンペでは、追加したいモジュール/パッケージは、全て、Datasetからインストールするしかなさそうだ。

 

よくわからなかったが、いろいろやってみて、なんとかできるようになった。

*必要なもの(pretrainedmodels==0.7.4、efficientnet-pytorch==0.6.3、timm==0.3.2)は、Datasetにして、Datasetからインストールすることができるようになった)

Datasetの作り方:

・pretrainedmodels==0.7.4をインストールするためのDataset:

Googleで検索し、ダウンロードサイトhttps://pypi.org/project/pretrainedmodels/ に行って、ファイルをダウンロードし、Kaggle のDatasetサイトの、+ New Datasetをクリックし、ダウンロードしたファイルを、フォルダーごと、Drag and drop files to uploadのスペースに移動する。データセットに名前を付けて、Createボタンをクリックすれば出来上がり。Createボタンの横にあるボタンで、PrivateかPublicかを選んでおく。

・efficientnet-pytorch==0.6.3をインストールするためのDataset:

同様にして、https://pypi.org/project/efficientnet-pytorch/ このサイトからダウンロードした。ただし、バージョンがefficientnet-pytorch 0.7.0となっていたので、Project descriptionボタンの下の、Release historyをクリックして、0.6.3を選んでダウンロードした。以下同じ。

・timm==0.3.2をインストールするためのDataset:

同様にして、https://pypi.org/project/timm/0.3.2/ このサイトからダウンロードして、同様の操作をしたが、圧縮ファイルであったためか、作成したDatasetでは、installできなかった。エラーメッセージに、setup.pyが見つからないと表示されていた。確かに、フォルダーの中を見ても、そのようなファイルが見当たらない。結局、7-zipで解凍し、setup.pyを確認してから、Datasetを作成した。

*これで、Segmentation-models-pytorch 0.1.3 を使う準備ができた。

明日は、FCN-Resnet50が使っているpretrain-coco-weights-pytorchとpytorch-pretrained-modelsの2つのDatasetがどのように使われているのかを確かめるとともに、新たなDataset:segmentation-models-pytorch013の使い方を検討する。

 

1月23日(土)

HuBMAP:896 teams, 2 months to go:

FCN-Resnet50をdeeplabv3-Resnet50に変更した。

オリジナルコードのinput Datasetに必要なデータが入っていたのでモデル名を書き換えただけで動くと思ったが、エラーが出た。データサイズが違うからダメとのこと。

model.classifier[4]とmodel.aux_classifier[4]の意味が分からずググると、GitHubでabeja-incが公開しているコードplatform-feature-image-segmentationのtrain.pyの中で使われていて、FCN-とdeeplabv3ではコードが少し異なっていて、if文で分けている。それに倣ってコードを変更することによりdeeplabv3-が使えるようになった。しかし、計算時間は3割増し、Lossの初期値は4割増しとなり、途中までは期待外れ。エポック数を増やしてみてどうなるか、調べてみる。

3エポックでは、deeplabv3の方がval_lossがかなり大きいにもかかわらずLBは同レベルだった。deeplabv3を7エポックまで増やしてcommit, submitした結果、overfittingのためLBは14/1000悪化した。FCNとの比較ではdeeplabv3が少しよさそうな感触だが、これ以上は追及しない。 

 

segmentation_models_pytorch 0.1.3:

各モデルのweightは、外部から読み込むようになっているので、internet offでは、

URLError: <urlopen error [Errno -3] Temporary failure in name resolution>

このようにエラーとなる。

ということで、Datasetを作った。といっても新たに作ったのはなく、Datasetのコピーである。元のdatasetのネーミングがわかりにくかったので、わかりやすいものにした。

internet経由でのweightの読み込みは、こんなふうになっている。

Downloading: "https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b5-b6417697.pth" to /root/.cache/torch/hub/checkpoints/efficientnet-b5-b6417697.pth

Dataset(名前は、pytorch_efficientnet_pretrained_models)から読み込んだweightのデータは、同じ場所に置くことになる。そのためのコードは、勉強中のコードを参考にすると、次のようになる。(最初にこのコードを見たときは全く理解できなかった)

!mkdir -p /root/.cache/torch/hub/checkpoints/

!cp ../input/pytorch_efficientnet_pretrained_models

/efficientnet-b5-b6417697.pth /root/.cache/torch/hub/checkpoints/ 

ようやく、internet offで、efficientnetB5-Unetのモデルができた。

モデルのコードのほんの1部分を表示する。(注) インデントは表示できない。

最初の6行:effitientnetB5ベースのエンコーダ:

Unet(
(encoder): EfficientNetEncoder(
(_conv_stem): Conv2dStaticSamePadding(
3, 48, kernel_size=(3, 3), stride=(2, 2), bias=False
(static_padding): ZeroPad2d(padding=(0, 1, 0, 1), value=0.0)
)

おそらく、デコーダーの開始:

(decoder): UnetDecoder(
(center): Identity()
(blocks): ModuleList(
(0): DecoderBlock(
(conv1): Conv2dReLU(
(0): Conv2d(688, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
デコーダのブロックが0から4まで続き、最後はセグメンテーションブロック:
(segmentation_head): SegmentationHead(
(0): Conv2d(16, 1, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): Identity()
(2): Activation(
(activation): Identity() ) ) )

次は、このefficientnetB5-Unetで解析する方法を検討しよう。

コードを作るにも、バグ出しするにも、時間がかかるだろうから、まずは、B5よりも倍以上計算速度が速い、efficientnetB0-Unetで検討することにしよう。

関係ありそうなコード

model = smp.Unet('efficientnet-b0', classes=1, aux_params=aux_params)

試しに走らせてみたらエラーになった箇所

output = model(image)['out']:TypeError: new(): invalid data type 'str'

 

1月24日(日)

HuBMAP

PyTorchでEfficientnet-Unetを用いたコードを調べた。

output = model(image)['out']ではなく、output = model(image)となっていたので、['out']を削除した。

その結果、trainまでエラーなく動き、lossも減少している。

efficientnetB0からB3にすると、B0では、train_lossとval_lossの反転が3エポック目で生じたが、B3では、5エポックでも反転しなかった。B5では、GPUのメモリーオーバーとなって計算できなかった。

順調かと思いきや、trainまでは動いたが、inferenceの次の行でエラーが発生した。

score = model(image.to(DEVICE)[None])['out'][0][0]

上記と同様に対処すればよいのだろうが、どこまで削除したらよいのだろう。

score = model(image.to(DEVICE)):これで動けばよいのだが。

動作確認中に、failed to fetchと表示されて計算停止。再度Run。

RuntimeError: Expected 4-dimensional input for 4-dimensional weight [40, 3, 3, 3], but got 3-dimensional input of size [3, 257, 257] instead

trainのときの対応と同じく、['out']のみ除去する、ということでエラーは回避できた。

 

1月25日(月)

HuBMAP

efficientnetB3-Unetの5エポックで、LB=0.740:849th相当/905 teams

3エポックでは、LB=0.280となり、心配だったが、うまく計算できているようだ。

6エポックでは、LB=0.777となった。

他の条件は全く同じで、FCN-Resnet50の場合には、3エポックでLB=0.798であった。ちょっと計算してみた、というだけでは、各モデルを正しく評価できていないかもしれない。

 

U-Netの調査

Review: U-Net (Biomedical Image Segmentation)
Sik-Ho Tsang, Nov 5, 2018·5 min read

 

f:id:AI_ML_DL:20210125112851p:plain

 

f:id:AI_ML_DL:20210125112937p:plain

 Since unpadded convolution is used, output size is smaller than input size. Instead of downsizing before network and upsampling after network, overlap tile strategy is used. Thereby, the whole image is predicted part by part as in the figure above. The yellow area in the image is predicted using the blue area. At the image boundary, image is extrapolated by mirroring.

 

f:id:AI_ML_DL:20210125113558p:plain

 Since the training set can only be annotated by experts, the training set is small. To increase the size of training set, data augmentation is done by randomly deformed the input image and output segmentation map.

GitHub:qubvel/segmentation_models.pytorch:に含まれているモデルは、9種類ある。HuBMAPの課題に対して、どれが最適かは、実際に適用しなければわからない。

Unet,  Unet++, MAnet, Linknet, FPN, PSPNet, PAN, DeepLabV3, DeepLabV3+

これらのモデルの文献を調べると、Unetが2015年、PSPNetが2016年、LinknetとDeepLabV3が2017年、Unet++とPANとDeepLabV3+が2018年、FPNは2017年の論文ではdetectionに、2018年以降にsegmentationにも用いられたようである。MAnetは2020年となっている。このように、MAnetが最も新しく、肝臓と腫瘍のsegmentationや、空撮画像のsegmentationに威力を発揮しているようである。その模式図は以下の通り。

f:id:AI_ML_DL:20210125202949p:plain

それではと意気込んでMA-Netで計算してみたが、デフォルトでは、良い結果は得られなかった。HuBMAPの課題に合わないのか、それとも、正しく使えていないのか。

 

1月26日(火)

HuBMAP

MA-Net:上に示した模式図の外観からはU-Netのバリエーションの1つと考えられる。

名称はMulti-scale Attention Netで、2つの構成要素からなる。Position-wise Attention Block (PAB) and Multi-scale Fusion Attention Block (MFAB)

それぞれ次のように説明されている。The PAB is used to model the feature interdependencies in spatial dimensions, which capture the spatial dependencies between pixels in a global view. In addition, the MFAB is to capture the channel dependencies between any feature map by multi-scale semantic feature fusion.

引用文献を示していなかった。

f:id:AI_ML_DL:20210126105630p:plain

f:id:AI_ML_DL:20210126105813p:plain

f:id:AI_ML_DL:20210126110012p:plain

f:id:AI_ML_DL:20210126110103p:plain

f:id:AI_ML_DL:20210126110150p:plain

f:id:AI_ML_DL:20210126115244p:plain

表2と表3の両方に、U-Netがある。表2のU-Netはオリジナルで、表3のU-Netは``Liver segmentation in CT images using three dimensional to two dimensional fully convolutional network"というタイトルの論文中で次のような模式図で表されている。

f:id:AI_ML_DL:20210126123337p:plain

というように、MA-Netは優れもののようだが、試しに動かしただけでは、期待した結果は得られていない。

今日は、LinknetとPSPNet(Pyramid Scene Parsing Network)を3エポック計算してcommit, submitしたが、いずれもSubmission Scoring Errorとなった。

PAN(Pyramid Attention Network)も計算してみた。計算時間は他のモデルの2倍くらいかかった。LBスコアは2エポックからoverfittingになっていたので予想通り低く、0.243であった。

encoderをefficientnetB3にし、batch_size=32で、9つのモデルの全てで計算可能か否かを調べた。その結果DeepLabV3のみ、batch_size=16にしてメモリーオーバーを回避した以外は、計算できた。1エポックあたりの計算時間は6つが12分程度だったが、PANとDeepLabV3+は約20分、DeepLabV3はbatch_size=16で24分を要した。

まだ、性能を比較できる段階には到っていない。

公開コードの様子から、efficientnetB3-UnetでLB=0.85が視界に入るぐらいになってからにしようかなと思っている。

  • Aux classification outputが次のように例示されているが、まだ使っていない。
  • 今回の課題は糸球体だけを検出するから、不要!
  • aux_params=dict(
        pooling='avg',             # one of 'avg', 'max'
        dropout=0.5,               # dropout ratio, default is None
        activation='sigmoid',      # activation function, default is None
        classes=4,                 # define number of output labels
    )
    model = smp.Unet('resnet34', classes=4, aux_params=aux_params)
    mask, label = model(x)
    mask.shape, label.shape
    # (N, 4, H, W), (N, 4)

次のようなlossが用意されているが、これもまだ使っていない。

JaccardLoss
DiceLoss
FocalLoss
LovaszLoss
SoftBCEWithLogitsLoss
SoftCrossEntropyLoss
SoftCrossEntropyLossは、Drop-in replacement for torch.nn.CrossEntropyLoss with label_smoothingとのことである。

あとは、k fold cross validationと、data augmentationをやらないといけない。

GPUは残り20分程度になってしまったので、本格的な計算はできない。

(出力層)、loss、K fold cv、augmentationなどを、GPUが使えるようになる土曜日の朝までに追加して、次のステージに進めるようにしよう。

 

1月27日(水)

HuBMAP

出力層(Aux classification output)を、良く考えずに追加しようとしたが、maskは1種類で、分類はしないから、不要!

augmentationをやってみよう。

Albumentations Documentationを見ると、目的毎に良く使われる方法や、ベースセットのようなものが、加工後の画像例とともに示されているので、適当に選んで、コピペして使うことができる。

augmentasionのセットをコピペして、計算できることをCPUで確認した。GPUが使えない(使い切った)ので3エポックぐらい計算しただけで、commit, submitまではできなかった。効果の確認やチューニングは土曜日以降になる。

loss関数、optimizer、lrについては、明日、検討してみる。


1月28日(木)

HuBMAP

lossは、順に試してみるつもりだが、2つか3つを組み合わせることで、より良い結果が得られるという報告もあり、最適解を見つけるのは容易ではなさそうだ。

Kaggleで過去のコンペのトップクラスの解法を見れば、参考になることは多いが、状況が異なっているので、そのまま適用してもうまくいかないかもしれない。

プログラム中に、全てのloss関数を書き込んでおいて、単独でも混合でも使えるようにしておこう。

optimizer, lr scheduler:

最近提案されたoptimizerに、NovoGradというのがあって、AdamやAdamWよりも高性能ということらしい。

Training Deep Networks with Stochastic Gradient Normalized by Layerwise Adaptive Second Moments, Boris Ginsburg  et al., arXiv:1905.11286v3 [cs.LG] 6 Feb 2020

In all experiments, NovoGrad performed equally or better than SGD and Adam/AdamW. NovoGrad is more robust to the initial learning rate and weight initialization than other methods. For example, NovoGrad works well without LR warm-up, while other methods require it. NovoGrad performs exceptionally well for large batch training, e.g. it outperforms other methods for ResNet-50 for all batches up to 32K. In addition, NovoGrad requires half the memory compared to Adam.

NovoGrad and all models in this paper are open sourced. 

https://github.com/jettify/pytorch-optimizer

Datasetを作って、このpytorch-optimizerを使う準備をした。

明日は、NovoGradとOneCycleLR Schedulerを使ってみよう。 

 

1月29日(金)

HuBMAP

optimizerとlr_scheduler:素人につき、検討中!

順序:

optimizer = torch.optim.AdamW( ...

scheduler = optim.lr_scheduler.OneCycleLR(optimizer, ...

for image, mask in loader:

      ................................

      output = model(image) 

      loss = loss_fn(output, mask)

      loss.backward( )

      optimizer.step( )

      scheduler.step( )

こんな感じでよいのかな。

この順に並べてみたが、計算結果は異常であった。train_lossはlr_scheduler無しの場合よりも少し大きかったが問題ないレベルだと思う。しかしval_lossが桁違いに大きかった。

pytorchのマニュアルをみるとexampleがあり、引用文献をみるとoptimizerにSGDを使い、lrは考えられないくらい大きな値(最大値)を使っている。まずは、次のexampleをそのまま使ってみよう。

Example

>>> data_loader = torch.utils.data.DataLoader(...)
>>> optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
>>> scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=0.01, steps_per_epoch=len(data_loader), epochs=10)
>>> for epoch in range(10):
>>>     for batch in data_loader:
>>>         train_batch(...)
>>>         scheduler.step()

これでは、trainingは進まなかった。原因調査中。

Example

>>> optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
>>> scheduler = ReduceLROnPlateau(optimizer, 'min')
>>> for epoch in range(10):
>>>     train(...)
>>>     val_loss = validate(...)
>>>     # Note that step should be called after validate()
>>>     scheduler.step(val_loss)

Example

>>> scheduler = CosineAnnealingWarmRestarts(optimizer, T_0, T_mult)
>>> iters = len(dataloader)
>>> for epoch in range(20):
>>>     for i, sample in enumerate(dataloader):
>>>         inputs, labels = sample['inputs'], sample['labels']
>>>         optimizer.zero_grad()
>>>         outputs = net(inputs)
>>>         loss = criterion(outputs, labels)
>>>         loss.backward()
>>>         optimizer.step()
>>>         scheduler.step(epoch + i / iters)

WARNING

Prior to PyTorch 1.1.0, the learning rate scheduler was expected to be called before the optimizer’s update; 1.1.0 changed this behavior in a BC-breaking way. If you use the learning rate scheduler (calling scheduler.step()) before the optimizer’s update (calling optimizer.step()), this will skip the first value of the learning rate schedule. If you are unable to reproduce results after upgrading to PyTorch 1.1.0, please check if you are calling scheduler.step() at the wrong time.

 

1月30日(土)

HuBMAP

OneCycleLR:これを使えるようにする。

optimizer:SGD:torch.optimのマニュアルのexampleそのままで実行してみた結果、train_lossは見事に収束したが、val_lossはtrain_lossより小さい。すなわち、underfitting、のような結果である。パラメータの設定が不十分なのだと思う。

今は、submitしてスコアが計算されることの確認が重要なのでcommitした。

ところが、commit中にWarningが現れ、心配た。約4時間後、スコアは計算されていた。それはよかったのだが、なんと、LB=0.486であった。なさけない。

optimizer:AdamW:AdamWはlr_schedulerを使わない場合のデータがあるので、lr_schedulerを入れたことによるlossの変化を比較することができる。

schedulerはそのままで、lrとweight_decayはデフォルト値から始めてみた。

train_lossは減少したが、val_lossが、ありえないくらい大きな値になった。

不慣れでよくわからなかったが、lrの初期値や最大値を変更することで、設定した10エポックで収束し、かつ、lr_schedulerを使わない場合よりも30%くらい小さいval_lossが得られた。

その結果、ようやくLB=0.796(859th相当)となった。

公開コードのチューニングをしていて最も驚いたことの1つが、この、lr_scheduler.OneCycleLRである。

指定したエポック数で収束する仕組みは凄いなと思う。

efficientnetのpretrained modelには、imagenetの他に、advpropやnoisy-studentいうのがある。これらを使えるようにしたいと思う。

これは、モデルのweightに"advprop"もしくは"noisy-student"を指定してRunすれば、学習済みモデルのweightの場所を指定するメッセージが現れてプログラムが停止するので、そのメッセージに示されているURLからweightをダウンロードして、Datasetを作ればよい。

明日は、計算速度向上の方法を、"Pytorch FCN-Resnet50 in 20 minute"に学ぼう。

 

1月31日(日)

HuBMAP

昨日だけでGPUを16時間以上使い、LBスコアは0.777から0.796まで上がった。

元は同じコードで、前処理の計算時間を短縮したバージョンを別のKagglerが公開しているので、それに乗り換えてみる。train時間だけを見ると、8倍くらい速く、トータルでも3~4倍速い。

コードを解析して高速化した部分だけ移植する方法もあるが、コードの変更履歴がわからないことと、コードの理解力不足のため、乗り換える(主に、segmentation modelsパッケージの追加)という方法をとることにする。

とりあえず、trainまで動くようにした。メモリーの使用状況を見ると、前処理したデータを全部RAMに格納してから、trainを開始していることがわかった。元のコードではCPUとGPUが交互に動作していたが、高速コードでは、CPUとGPUが並列動作しているように見える。それで、全体として、処理速度が向上しているのだろう。commit, submitしてみると、LBスコアも計算された。

昨日は、LB=0.80を超えられなかったが、時間短縮できるコードに乗り換えると、時間短縮の効果に加えて、LBスコアも0.83+にアップした。

スコアアップの原因は、augmentationであることがわかった。

コード乗り換えの際に、使われているaugmentationのコードが同じものに見えたので、取り換えなかったのだが、よく見ると、新たなaugmentationコードでは、distortion(ElasticTransform, GridDistortion, OpticalDistortion)の確率がゼロになっていたのである。昨日までのコードは、変形量を大きくしすぎていたために、trainがうまく進まなかったものと思われる。

 

1月7日に終了したRiiid!コンペは残念な結果に終わった。チューニングだけでは、まぐれあるいは幸運にも恵まれないとメダルは難しい。

次のステップに進むために、GitHubを活用し、モデルの選択肢を増やし、最新の情報に接し、日々勉強を怠らず、技術と知識を積み重ねていこう。

1月は今日で終わり。来月もKaggleに集中しよう。

 

f:id:AI_ML_DL:20210101145217p:plain

style=162 iteration=500

f:id:AI_ML_DL:20210101145334p:plain

style=162 iteration=50

f:id:AI_ML_DL:20210101145458p:plain

style=162 iteration=5

 

Kggle散歩(December 2020)

Kggle散歩(December 2020)

MoAが終了した。

現在参加しているものはいくつかあるが、今月は、Riiid!に注力しようと思う。

MoAで2つめのメダルがとれそうである(暫定181位で銀):12月11日確定!!Kaggle Competition Expertになった。

次のランクアップのためには、金メダルが必要になる(銀も必要)。これまでの参加経験からして、相転移しなければ、金メダル獲得は無理である。金の難しさは桁違いだ。

 

12月1日(火)

Riiid!:2,177 teams, a month to go

the starter notebookを学習中

 

MoA: 終了

終了後に上位陣のスコアを生み出したコードのアーキテクチャが明らかになるので、しっかり学びたい。コンペ終了時にはいつもそう思うのだが、上っ面を眺めただけで終わってしまうことが多い。コンペが途切れた時に時間ができて過去のコンペに戻って復習しようとしても、反省すべきことも、コンペの課題もぼやけてしまっていて、結局のところ、真剣に振り返って学んだことはほとんどない。

まだ記憶に残っているうちに、次のレベルに向かうために必要なことを検討しよう。

学習を効果的に行うために必要なことは何か。Riiid!コンペの本質もそこにあると思うのだが、いつ何をどのように学習すると成績が向上するのか。なぜ、同じだけ得点をアップするのに3か月で済む人と半年以上かかる人がいるのかを考えてみる必要がある。

Riiid!が、学習の効率を測るために、学校での学習や塾での学習ではなく、TOEICを取り上げたのは、本当の理由は知らないが、次のように推測される。

TOEICには、固定した学習プログラムがなく、同じテキストと教材を使っても、スケジュールが個人任せになっているので、参加者の取り組み方に、非常に大きなばらつきが存在する可能性が高い。効果的に学習出来て成績が短期間で向上する人から、そうでない人まで、非常に広範囲にわたるデータが集まる可能性がある。学校のプログラムで同じことをやると、記憶力とか理解力が大きく反映されて、学習効率を測ることが難しくなるのではないだろうか。

本題に戻ろう。

1.現状分析

これまでに20件近くのコンペに参加した。そのうちの13件は成績が残っており、そのうちの2件は、ほんの少しだけの参加で、残りの11件は、メダル獲得を目指したものであり、入賞はLandmarkとMoA (暫定)の2件である。

まず、見えていない部分(約20件と13件の差、約7件)について検討してみよう。

記憶に新しいものはARCコンペである。これに取り組んでいた頃は、ARCの論文を勉強していて、知能テストについてもいろいろと調べていた。コンペが始まってすぐに感じたことは、コンペの主催者(F. Chollet氏)が求めていることと、現に存在している機械学習ディープラーニング等を含む)でできることとのギャップの大きさである。このコンペは、目指しているものが非常に高いところにあるということでは歴史に残るものかもしれない。勝者はいわゆる力づくで解いたヒトのようである。train dataからできるだけ多くのパターンを把握し、test dataの例題から解答パターン(モザイクの構造パターン)を推測し、用意しておいたパターン変換を行うというもので、従来型のプログラミング手法によるものである。機械学習を用いて、興味深い結果を得ているものもいくつかあった。自分は、コンピュータに解き方を教えるための方法を考えるために、課題を解きながら解き方を分類してプログラムコードに置き換えようとしていたが、途中で投げ出してしまった。5月27日にコンペが終了した後、ARCコンペから何かを学ぼうとしたが、人工知能に関する論文(教育心理学?哲学?)をいくつか読んで終わった。

他に、かなり力を入れて参加したのは、眼底写真から病状を分類するAPTOS2019と鋼板表面の異常部を検出するSeverstalがある。

APTOS2019は、submit後にエラーになって記録が残らなかった。前処理とsubmissionファイルを作成する部分がよくわからずその部分のコードを公開コードから借用した。

Severstalは、前処理からできるようにしたいと思って、ゼロからプログラムしていたが、結局、前処理を完成することなく終わった。

このころの目標は、自前のプログラムコードを作成して、予測して、結果をsubmitして,リーダーボードに載ることだった。

ここからは、あまり見られたくないことも、少し書いておく。

Kaggleでは、まず、参加することによって得るものがあると思ったコンペに参加する。

次に、コンペの概要、データの概要をある程度把握したら、notebookのEDAをざっと見てデータの概要を図や表から、もう少し詳しく把握する。

その次に、高いスコアを得ているコードの中から、読みやすく、再チューニングやモデルの変更がしやすそうなコードをフォークして、Kaggle kernel内で実行、commit、submitする。

その次に、予測モデルのハイパーパラメータや構造をチェックして、経験上、変更した方が良さそうなパラメータ(モデルの簡単な構造変更を含む)を変更し、Kaggle kernel内で実行し、commit、submitする。

選んだモデルで得られるスコアに限界を感じたら、ディスカッションを読み、高得点を得ている公開コードをチェックする。このとき、高得点を得ていなくても、良いモデルを使っていて、読みやすい、変更しやすい、改善すべきポイントがなんとなく見える、というような公開コードを探す。

勝負は、generalizationにあり、ということで、最終段階はどのようにしてアンサンブルを行うか、ということになる。ここでは、モデルを組み合わせる技術、コンペ毎に定められている計算時間内に計算を終わらせる技術などが求められるが、これについては、まだまだ、不十分である。

2.課題と対策

グランドマスターの方々の講演を聞いていると、あるいは聞くまでもないことだが(すでに常識となっている)、データサイエンス、機械学習で最も重要なことは、データの前処理である。前処理と言っても、予測モデルに読み込ませるだけの定型的なプログラミング技術ではない。データが持っている有用な情報をいかにして取り出すかということである。雑音を除去し、重要な特徴量を抽出するだけではなく、データの中に潜んでいる、原理や法則、関係性を把握して、それをモデルに反映させることができるようにすることが重要であろう。

自分の今の課題は、1)前処理の部分を読み飛ばしていること、2)モデルの性能を左右するツールに関する勉強不足、3)後処理(submission.txtの作成を含む)の部分を読み飛ばしていること、4)チューニングに膨大な時間を費やしていること、および、5)上に書いたような前処理技術、と思っている。

これらに対する対策は、一言でいえば、当該コンペサイトのKagglerに学ぶ、ということである。できることから書いていくと、1)技術的ディスカッションの理解に努める(Discussionもしくは公開コードの後ろのComments)、2)公開コードをスコアの高いものだけ見るのではなく、自分の現状に見合ったコードやEDA中心のコードの理解に努めること、3)予測モデルの制御部分のコードを意識して理解すること、4)前処理技術を理解すること、5)後処理技術を理解すること、6)チューニングよりもコードの理解を優先すること、などである。

以上、実行あるのみ。 

 

12月2日(水)

Riiid! Answer Correctness Prediction

NotebooksのMost Votesの最初から見ていくことにしよう。

最初は、大きなデータの扱い方で、大きなデータをpandasで普通に読み込むと、メモリーオーバーや読み込むのに10分くらいかかるところを、メモリーオーバーを生じさせることなく1分もかからず読み込む方法が紹介されている。フォーマット変換方法も紹介されていて非常に応用範囲の広いものである。

2番目は、EDA+Baselineである。図表を駆使しながら非常に丁寧に説明されている。

これまで、EDAは、ただ眺めるだけであったが、今回は、Kaggle kernel内で実行しながら学ぶことにした。そうすると、よくできたEDAは、詳細な説明とプログラムコードが交互に現れ、説明を読みながらコードセルを1つ1つ実行させていくことになるので、データの内容を調べながら、プログラムの書き方も学ぶことができる。

この調子で、チューニングのエキスパートではなく、データサイエンスと機械学習のエキスパートを目指して頑張ってみることにしよう。

 

12月3日(木)

Riiid! Answer Correctness Prediction

EDA + Baselineを最後まで見た。ようやく全体像が見えてきたように思う。

Baselineは、LightGBMである。

Riiid! AI Researchが、関連論文を公開している。

Towards an Appropriate Query, Key, and Value Computation for Knowledge Tracing

SAINT+: Integrating Temporal Features for EdNet Correctness Prediction

コンペと同じ条件かどうかはわからないが、AUCの最大値が0.7914となっている。

コンペでは、すでに、8チームが0.800を超えている。さすが、Kagglerってとこかな。

この、Riiid! AI Researchの論文とKagglerのスコアを見ると、このコンペでの金は無理だなと思うが、どのコンペであっても、似たようなものだろうな。APTOS2019でもコンペ開催時期に非常に優れた論文が発表されたが、Kagglerの上位者のスコアはそれを遥かに上回っていた。

金メダルは、狙ってもとれるものではないかもしれないが、狙わないととれないのも確かだろうな。

2021年1月7日に、単独で金メダル圏内に入っているための必要条件を考えてみよう。

1.課題と提供されるデータを完全に理解すること。

2.Time-series API(Competition API Detailed Introduction)を完全に理解すること。

3.コンペのdiscussionと公開コードを完全に理解すること。

4.上記2件の論文と完全に理解すること。

これをやり遂げれば、少しは、金メダルに近づけるだろうか?

公開コードに、SAKTと、SAINTを意識したものがあるので、それをフォークさせていただいて、あとは、自力で進めるというのが当面の仕事になりそうだな。

 

12月4日(金)

Riiid!: 2,307 teams, a month to go

フォークしたTransformer Encode Modelを3日以内を目標に解読してみよう。

F. Cholletさんのテキストでは索引に載っていない。A. Geronさんのテキストでは、Transformer architecture, 554となっている。

Chapter 16: Natural Language Processing with RNNs and Attention

Attention Is All You Need: The Transformer Architecture

画期的な技術で、次のように書かれている。

... the Transformer, which significantly improved the state of the art in NMT without using any recurrent or convolutional layers, just attention mechanisms (plus embedding layers, dense layers, normalization layers, and a few other bits and pieces).

554ページには、Transformer architecture の模式図がある。元の論文を示す。

f:id:AI_ML_DL:20201204112516p:plain

f:id:AI_ML_DL:20201204112852p:plain


f:id:AI_ML_DL:20201204112727p:plain

 

f:id:AI_ML_DL:20201204112952p:plain

GitHubで’”Tranformer””で検索すると10,835 repository resultsと表示される。トップに出てくるrepositoryをクリックすると、そこには膨大な量の情報がある。どこに何があるか知っていればいつか役に立つだろう。

A. Geronさんのテキストでは10ページあまりにわたって説明されているが、それを読み込んでもコードが書けるわけではない。

フォークしたコードは、TensorFlowのチュートリアルhttps://www.tensorflow.org/tutorials/text/transformerのコードを用いているので、そちらで学ぶことにしよう。

TensorFlowのチュートリアルのタイトルが"Transformer model for language understanding"となっていて、text generationとattentionの知識があることを前提にしていると書かれている。

チューニングの合間に、チュートリアルと、フォークしたコードを比較している。

よくできているチュートリアルだと思う。

チュートリアルの事例はスペイン語から英語への翻訳で、言語間の相関を解析しているのだが、Riiid!の課題は行動(学習)パターンを解析することで、全く異質だと思うので、途惑うことばかりだ。そういうことからすると、フォークしたコードは、よく考えているなと思う。といっても、翻訳用のコードを、学習行動解析用に、どういうふうに変換しているのかは、まだ、まったく把握できていない。

 

12月5日(土)

Riiid!:2,344 teams, a month to go

 

<雑談>

F. Chollet氏のテキストに、AttentionやTransformerは無い。と思う。やはり、古いのだ。これに比して、A. Geron氏のテキスト(第2版:TF2)は、TF2というだけあって、2019年の前半くらいまでの情報が含まれていて、GPTやBERTも紹介されている。AnacondaにTF2がインストールできず、かつ、英語力も不足していたので、A. Geron氏のテキストを十分学べず、知らないことが多すぎるだけでなく、自分の勝手な解釈も多いことがわかってきた。目の前の話だと、encoder-decoderの理解の問題。variational auto encoderの印象が強くて、encoder-decoderに対して本来の意味とは全く異なるイメージを抱いていたようだ。情けないことだが、これが現実なのだ。

 

A. Geron氏のテキストでは、Figure 15-4にEncoder-Decoder networks、Figure 16-6にEncoder-Decoder network with an attention model、Figure 16-8にTransformer architecture、Figure 16-10にMulti-Head Attention layer architectureがそれぞれ図示されている。これで、encode-decoderとattentionとtransformerがつながった。

 

こんなんじゃ、だめだな。

本丸に切り込んでみよう。

解答者の解答履歴と行動履歴の中から、正答率との相関(正でも負でも)が高いものを選ぶこと、作り出すこと、見つけること、などが重要になるのだろうから、データをよく見て理解していく必要があるな。

どの情報が重要かは、最終的には、モデルに組み入れて確認することになるだろう。

TOEICについて、知らないよりは知っている方が良さそうだな。

TOEICをウイキペディアで調べてみよう。

試験問題の構成[編集]

2016年5月以降に実施されている試験問題の構成は次の通りである。

聞き取り(リスニングセクション)[編集]

聞き取り(リスニングセクション[28])は合計100問、所要時間は45分間である(但し、音声の長さに応じて所要時間が多少変わる場合があり、その場合は予め告知される)。

  • Part 1 - 写真描写問題 (Photographs) - 1枚の写真を見て、その写真について放送される適切な英文を選ぶ。4択式で合計6問。
  • Part 2 - 応答問題 (Question-Response) - 質問文が放送された後、それに対する応答文が3つ放送され、適切なものを選ぶ。合計25問。
  • Part 3 - 会話問題 (Short Conversations) - 2人の会話を聞いて、その会話についての質問に対し最も適当な選択肢を選ぶ。質問文と選択肢は問題用紙に記載されている。4択式で合計39問。
  • Part 4 - 説明文問題 (Short Talks) - ナレーションを聞いて、それについての質問に対し適切な選択肢を選ぶ。1つのナレーションにつき複数問出題される。質問と選択肢は問題用紙に記載されており、4択式で合計30問。

旧構成の Part 3、Part 4の問題文は印刷のみであったが、新構成では印刷されている問題文が音声でも読み上げられる。またPart 3、Part 4の1つの会話・説明文に対する問題数が2〜3問と不定であったものが、新構成ではそれぞれ3問に固定されている。

読解(リーディングセクション)[編集]

読解(リーディングセクション[28])は合計100問、制限時間は75分間である。聞き取り(リスニング[28])の終了と同時に読解(リーディング[28])の試験が開始され、読解(リーディング)の開始の指示は特になされない。

  • Part 5 - 短文穴埋め問題 (Incomplete Sentences) - 短文の一部が空欄になっていて、4つの選択肢の中から最も適切な語句を選ぶ。合計30問。
  • Part 6 - 長文穴埋め問題 (Text Completion) - 手紙などの長文のうち複数の箇所が空欄になっていて、それぞれ4つの選択肢から最も適切な語句を選ぶ。合計16問。
  • Part 7 - 読解問題 (Reading Comprehension) - 広告、手紙、新聞記事などの英文を読み、それについての質問に答える。読解すべき文書が一つのもの (Single passage) が29問。「手紙+タイムテーブル」など読解すべき文書が2つもしくは3つのもの (Multiple passage) が25問。それぞれ4択式。

question.csvのpartは、Kaggleのデータの説明に、the relevant section of the TOEIC test.と書いてあるので、上記の1~7を指すのだろうが、lectures.csvのpartは、top level category code for the lectureと説明されていて、よくわからない。

今のモデルの現状は、LB=0.736である。

来週末までに、流すデータを見直して、0.74+にしたいと思う。

 

12月6日(日)

Riiid!2,383 teams, a month to go : gold 0.797+, silver 0.776+

 

<雑談>

LightGBM系とDNN系についてちょっと考えてみよう。機械学習ディープラーニングの比較のつもりだが、ディープラーニングは定義上、機械学習に含まれるようなので、このような表現にした。ただし、LightGBMはDNN以外のモデルというつもりで示しており、このモデルに限るということではない。Riiid!コンペもそうだが、表データのコンペでは、LightGBMを使ったコードがたくさん公開される。同じツールを使っていても、データの前処理、後処理、アンサンブル、ハイパーパラメータなど、の最適化の程度によってスコアはばらつく。DNNを使った場合も同様なのだが、ばらつきは概してLight GBMのグループの方が小さい。ハイスコア側は公開コードには現れないので実際のところはわからないが、見える範囲ではそう感じる。そこで知りたいのはばらつきの大きさやその原因ではなく、ハイスコアの限界はどこにあるか、LightGBMとDNNのどちらのスコアが高いのか、ということが、誰もが知りたいことである。DNNと書いただけだと、LightGBMに勝ち目はなくDNNの勝利となるだろう。最終的にどちらが高いスコアに達するかというときに、もしかすると、最高位は、両方のグループを合わせたアンサンブル、LightGBM系+DNN系かもしれない。多分そうなんだろうと思う。特性の異なるモデルを適切にアンサンブルすることによって最高のスコアが得られるということなのだろうと思う。Kaggleコンペに限らず、コンペの順位は主催者が選んだテストデータに対するスコアの順位で決められるので、話は複雑である。submitしたモデルの中から選んだ数件のモデルで最終スコアを争うのではなく、submitした全てのモデルに対して最高スコアを争うことにすると、勝者の範囲は狭くなるだろう。ある意味、面白さは減るかもしれない。自分が勝者になるかもしれない!、という期待感も小さくなるかもしれない。番狂わせがあるというのは、多くの場合は、public_test_dataに対してoverfittingになっているかどうかということであって、よくないモデルでも勝てるということではない。この雑談を書こうと思ったのは、1つには、単独のモデルで勝つのは難しいということ、ベストモデルにこだわるなということである。MoAでいえば、TabNetが話題になり、TabNetで競うようなところもあったようだが、つまるところ、同じモデルを使っても、前処理、featureの選び方・作り方により、もちろんハイパーパラメータによってもスコアは変わるので、結局は総合力ということになる。だから、今回も、特定のモデルにこだわることなく、種々のモデルを試すこと、データベースをより深く理解すること、time-series APIを正しく理解することなど、様々な要素に対する取り組みが必要だということであると思うが、どこまでできるだろうか。

 

MoAコンペの優勝チームの手の内紹介記事を見た。難しくて理解できない。やっていることは、文章と模式図から、なんとなくわかるが、どうやってそういう発想になったのか、発想できたとしてどうやってコード化したのか、トレーニングはどうやって行ったのか、皆目わからん。こういう人と勝負して勝つにはどうすれば良いのだろうか。

GitHubに用いた7つのモデルを公開しているというので見に行ったら、この優勝チームのリーダーは、既に、162のrepositoriesを作っている。大半はフォークしたものだが、オリジナルもいくつかある。Kaggleコンペの優勝者のモデルもいくつかフォークしている。そうなんだ、オープンソースライセンスが、今のプログラムの流通のベースになっているし、Kaggleのサイトの中も同様なんだ。といっても、コンペサイトだから、なんでもオープンにするわけにはいかない。

チューニングしないとパラメータの最適値が分からないし、プログラムの各部分が正しく機能しているのかどうかを確かめるためにもチューニングは適切に行っていく必要がある。

やっと、0.74+になったが、原作者は0.767まで向上している。

Riiid! Researchの論文をチェックして、エンコーダ、デコーダに入力しているデータを特定しようとしているのだが、まだ、まったく、つかめない。

 

12月7日(月)

Riiid!2,415 teams, a month to go:gold 0.797 over, silver 0.777 over

今のモデルのパラメータのおおよその適正範囲がわかってきたので、今日は、流すデータ量を単純に増やしてみる。具体的には、10Mでパラメータ調整し、そのまま、データ量だけ増やすということ。20M, 50M, 100Mと増やしてみたいが、100Mをやってみてからその次を考える。

その後で、再度、パラメータの適正範囲を探索してみよう。

10Mを100Mにすると、val_AUCは、0.8-0.9%程度大きくなった。

この増分は、モデルとハイパーパラメータと流すデータの質にも依存すると思うし、そもそもどのレベルにあるのかにもよるだろう。この結果は、val_AUC=0.75+で得られたものである。現状でも、かなり良くできたモデルなのかもしれない。

ここから、ハイパーパラメータを変更するのは、ベースラインを上げてからにしようと思う。入力データの検討とモデルのアーキテクチャの検討をして結果を出さなければ、0.76+以上は望めないように思う。

最終目標の0.82+は、はるか彼方である。 

 

100Mのデータを通した結果のcommit中に、トラブル発生。3時間以上かかった計算のやり直し。計算とcommit合わせて、約7時間のロスだ。ただで使わせいただいているのだから文句は言えないというところか。残念だな。

もう1度100Mをやるには、さらに6時間以上GPUを使うことになる。

一足飛びに100Mをやるのではなく、着実に進めなさいということを暗示しているのだと思って、10Mから始めて20M, 30Mという順で、結果(public LB)を出してみることにしよう。今の条件では、10Mのデータでも、2エポック目でval_AUCは最大値になっていて、1エポック目との差も0.5-1.0%程度なので、時間節約のために1エポックで結果を出してみる。

 

12月8日(火)

Riiid!: 2,453 teams, a month to go

投入したデータ量(目安)とスコアの関係(1エポックでtraining終了)

          val_AUC    public LB

10M     0.748      0.744

20M     0.751      0.749

30M     0.755      0.748

40M     0.755      0.750

60M     0.757      0.755

100M   0.758         ?

このような相関が常に成り立つかどうかわからないが、通常の条件検討は効率優先で、20~30M程度でテストして、最終段階では、データ量を増やすことによって少しでもスコアを上げるのに役に立つかもしれない。といっても、メモリーオーバーで停止するとか、改善につながらない可能性も否定できない。データのばらつきにも注意が必要。

ちなみに、Kaggle kernel内ですべての計算を行っているのだが、transformerモデルのユニット数や層数は最小限に近いレベルに設定しないとメモリーエラーが生じ、それでも、100Mのデータを流すと、1エポックでも、計算を完了するには、3時間くらいかかっている

 

<メモ>

MoAコンペの、submitしたモデルを眺めていて気付いたこと。NNモデルのdropoutの数値を下げてweight_decayを上げると、単独モデルのpublic LBスコアは良くなったが、他のモデルとアンサンブルしたときには、そのdropoutの数値を下げてweight_decayも下げたモデルの方が、public LBスコアも最終的なprivate LBスコアも良かった。といっても、それはもちろん、結果がそうだったというだけのこと。それを見越して最終モデルを選んだわけではない。単独のスコアは良いのに、アンサンブルしたら悪化するモデルのことは、discussionでも話題になっていた。dropoutは、アンサンブルの一種とみなされる。ユニット数を変えながら訓練しているので、様々なユニット数のモデルを組み合わせているのと似ているということだ。だから、CVが同じでも、dropoutの割合が高いモデルの方が、汎用性は高いと考えられる。これまでの経験では、dropoutの割合が高いモデルの方が、private teat dataに対しては良い結果となっている。今使っているTransformerモデルでは、dropoutを変えても有意差がわからない。モデルの安定性の問題かもしれない。今使っているモデルのval_AUCは、計算後とcommit後とで、±0.3%くらいは変動しているようである。

同じことの繰り返しはやめよう、じじくさい。

 

transformerの論文でも読もう

f:id:AI_ML_DL:20201208193313p:plain

なんちゃわからん。

RNNがわかっとらんからな。

以下は、A. Geronさんのテキスト第2版からの転載です。

p.501 Input and Output Sequences

An RNN can simultaneously take a sequence of inputs and produce a sequence of outputs. this type of sequence-to-sequence network is useful for predicting time series such as stock prices: you feed the prices over tha last N days, and it must output the prices shifted by one day into the future.

Alternatively, you could feed the network a sequence of inputs and ignore all outputs except for the last one. In other words, this is a sequence-to-vector network. For example, you could feed the network a sequence of words corresponding to a movie review, and the network would output a sentiment score (e.g., from -1 [hate] to +1 [love]).

Conversely, you could feed the network the same input vector over and over again at each time step and let it output a sequence. This is a vector-to-sequence network. For example, the input could be an image (or the output of a CNN), and the output could be a caption for that image.

sequence-to-sequenceと、sequence-to-vectorと、vector-to-sequenceについて、なんとなくわかった。

ここからが本命のEncoder-Decoderだ。

Lastly, you could have a sequence-to-vector network, called an encoder, followed by a vector-to-sequence network called a decoder. For example, this could be used for translating a sentence from one language to another. You would feed the network a sentence in one language, the encoder would convert this sentence into a single vector representation, and then the decoder would decode this vector into a sentence in another language. This two-step model, called an Encoder-Decoder, works much better than trying to translate on the fly with a single sequence-sequence RNN: the last words of a sentence can affect the first words of the translation, so you need to wait untill you have seen the whole sentence before translating it. We will see how to implement an Encoder-Decoder in Chapter 16.

ふむふむ。なんとなく、Encoder-Decoderのことがわかってきたような気がする。

A. Geronさんのテキストの第16章 Natural Language Processing with RNNs and Atentionを理解しよう。

全40ページだ。

読書百遍義自ずから見る、といきますか。ちなみに「見る」は「あらわる」と読む。

で、読んでいるのだが、tokenizer, GRU, embedding, LSTM, ...勉強不足でわからん。Chapter 15: Processing Sequencies Using RNNs and CNNsにもどらないと、・・・。

40+25=60ページになる。必要なことだが、まず、40ページを、最後まで読もう。

 

12月9日(水)

Riiid!: 2,487 teams, a month to go

今日は朝からA. Geronさんのテキストの第16章を勉強している。

現状のモデルでもチューニングしたいことはたくさんあるのだが、KaggleのGPUの残り時間がわずかになっているので、今日はチューニングの計算をしていない。

するとどうだろう、時間が余る。テキストを読んでいても時間が長くなると頭が飽和して先に進めなくなる。などと、うだうだいってサボっていては金メダルに近づけないので、テキストを読む。

545ページにEncoder-Decoderのコードが20行あり、その説明の最初にこう書かれている。The code is mostly self-explanatory, but there are a few point to note.

それはそうだろうな。難しい数式も、難しい理論も、なさそうだ。あるのは、等式: =, tuple: ( ... ), list: [ ... ]の他に、英単語が並んでいるだけ。
encoder_inputs, keras.layers.Input, shape, dtype, np.int32, decoder_inputs, sequence_length, embeddings, keras.layers.Embedding, vocab_size, embed_size, encoder_embeddings, decoder_embeddings, encoder, keras.layers.LSTM, return_state, True, state_h, state_c, sampler, tfa.seq2seq.sampler.TrainingSampler, encode_cell, keras.layers.LSTMCell, output_layer, keras.layers.Dense, tfa.seq2seq.basic_decoder.BasicDecoder, sampler, final_outputs, final_state, final_sequence_length, initial_state, Y_proba, tf.nn.softmax, 

単語を書き並べてみた。

547ページのBeam Searchとは何か。

約2ページにわたる解説のまとめが以下のようになっている。

With all this, you can get good translations for fairly short sentences (esoecially if you use pretrained word embeddings). Unfortunately, this model will be really bad at translationg long sentences. Once again, the problem comes from the limited short term memory of RNNs. Attention mechanisms are the game-changing innovation that addressed this problem.

だとさ。技術的な中身が理解できないまま、表面的な理解で読み進んでいるだけのような気がする。

次は、549ページからのAttention Mechanism

自然言語処理としてのTransformerの説明のようだし、Riiid!コンペの課題に対してイメージが湧かない。もちろん、イメージが湧くまで読み込んでいないということかもしれないが、TOEICの問題に対して正答する確率を求めることと、翻訳とか、文章生成とか、要約とかが全く結びつかないので、このへんで、テキストの学習は中断する。百篇どころか一遍読んだかどうかというところで中断とは情けないが読んでいても明らかに脳のニューロンを素通りしている。

Riiid! AI Researchの論文を読んでみよう。

SAINTの0.78、SAINT+の0.79を、当面の目標にしよう。今は0.755だから目標高すぎ!

 

12月10日(水)

Riiid!:2,516 teams, a month to go

昨夜、Riiid!コンペに対応している(らしい)プログラムコードをGitHubで見つけ、ダウンロードした。Kaggle kernelにアップロードして実行し、trainingまで動作することを確認した。途中経過をsaveし、継続してtrainingできるように組まれており、制限時間を気にせず、十分なtrainingが可能ということで期待して実行してみた。途中でエラーが発生しないように変更した以外、パラメータは変更しなかった。GPUを使用し、10Mのデータ量で、1エポックの80%くらい走らせてみた。約50分くらいかかり、val_AUCは、0.65+で収束しそうな感じであった。スコアはともかく、プログラムコードは、課題に合うように考えて、しっかり書かれているようで、参考になりそうだ。

今日、GitHubからのモデルのハイパーパラメータを見直してtrainingした結果、val_AUCは0.74+レベルになった。計算時間が長かったのは、ユニット数が多かっただけである。ただし、1エポックでの比較なので、ユニット数を減らすのが良いかどうかはわからない。土曜日にGPUが使えるようになれば、ユニット数が多い場合のtrainingをやり直し、(ユニット数、エポック数、val_AUC)等について相関を調べる予定である。

GitHubからのコードとKaggleの公開コードの比較だが、使っているデータもモデルの構造も少し異なっているので比較できないが、いずれのコードも自分のレベルを超えており、しっかり学びたい。

 

今日は、SAINTの要点を把握し、実際のデータとの関係を把握しよう。

重要な要素は2つある。

1つは、Exercise embedding sequenceをEncoderに、Responce embedding sequenceをDecoderに分けて流す(入力する)こと。

Exercise embedding sequence    -->  enter the Encoder

Response embedding sequence  -->  enter the Decoder

2つめは、ExercisesとResponcesの複雑な関係を、deep self-attentive computationsを使って、効果的に捕える(capture)こと。

 

Ii : interactions Ii = ( Ei, Ri )

Ei : denotes the exercise information, the i-th exercise given to the student with related matadatasuch as the type of the exercise

Ri : denotes the responce information, the student responce ri to Ei with related metadata such as the duration of tome the student took to respond

ri : denotes the student responce, is equal to 1 if their i-th responce is correct and 0 if it is not

Thus, SAINT id designed to predict the probability

P( rk = 1 | Ii, ..., Ik-1, Ek

 

12月11日(金)

Riiid!2,543 teams, 28 days to go

SAINTに関連するDiscussionで、全データ(100M)を用い、d_modelもwindow_sizeもかなり大きく(ユニット数を多く)しないと、0.78-0.79には、届かないようなことが書かれている。SAINTの論文に書いてある条件では、メモリーアウトで計算できない。まあでも、解は1つではないはずだ。 

 

MoA:varification終了により順位確定

コンペの結果が確定し、Silver medalとKaggle Competition Expertの通知メールがきた。

1年前の12月12日、手帳に、「ビリでもいいからリーダーボードにのりたい」と書いてある。そのページには、YOLO、3D、6D、バウンディングボックス、KITTI、などの単語が書きつけられている。1月には鋼材表面の欠陥検出、2月には高額の賞金がかかったfake画像検出、3月にはARC、4月は大学受験数学に集中、5月はARC再開、6月中旬からTReNDS、7月にはPANDA、7月末からSIIIM、COVID-19、LandMark、Bird、OSIC、RSNA、LyFT、MoA、Riiid!、・・・。

 

12月12日(土)

Riiid!2,601 teams, 27 days to go

これからも何度も起きると思うが、ハイスコア(自分のレベルと比較して)の公開コード(0.765)が投稿され、60番くらい下がった。

今のコードのポテンシャルを生かせず、0.755を超えられず、苦戦中。

ユニット数を文献やDiscussionでの値に近づけて設定して計算してみた。1エポックに4時間くらいかかる条件だったが、可能性を調べるために計算を初めて見た。そうすると、途中からlossの下がり方、AUCの上がり方が悪くなり、2時間くらい経過すると、lossとAUCが反転し始めた。一時的なものかと思い、しばらく様子を見たが、だめなようで、中止した。GPUがリセットされ34時間まで使用可能になったので、意気込んで計算し始めたのだが、残念な結果となった。

ギャー、0.772が投稿された。目標が0.78以上だから関係ない!と、強がってみる。

気になったのは、その公開コードの前書きに、12Mのデータで0.770-0.772を得たとなっていることだ。

10M使って0.744、60M使って0.755では、話にならんな。

今日は、60Mのデータにこだわって計算して、思うような結果が得られず(実のところ、非常に良い結果が得られそうな気がしていた。SAINTの論文とKaggle Discussionでの話とで一致する条件を選んでいるから、間違いないと思った)、結局10時間近くもGPUを消費してしまった。大きなデータ量で良い結果が出れば言うことなしなのだが、結果が出なかったときの損失は非常に大きく感じる。

12Mのような、少ないデータ量で、もっと基本的なところを押さえていこう。

60Mでの失敗は、特定のパラメータ群を一気に変更して、うまくいかなかったということだが、それは、関連する他の条件があって、それらも同時に変更する必要があった、ということなのだろうと思う。そのパラメータが何であるか、それを探索して調整する必要がある、ということなのだろうと思っている。

 

優先順位を決めておこう。

1.Transformerのスレの内容を確認する。まだ手を付けることができていなことがいくつかあるが、このスレには、具体的な解決につながるヒントがありそうだ。

2.1.を終えるまでは、次の段階に移らないことにする。そのスレの何か所かを拾い読みし、その情報で対応してきたのだが、全部きちんと読まないとダメな気がしてきた。SAINTの論文を読むと、わかったような気になるが、プログラムとの対応は、いまいちわからず、具体的な問題解決につながらないで困っている。

 

12月13日(日)

Riiid!

今日は、transformerに関する情報収集の前に、やりかけのチューニングを片付けようとしてドツボにはまった。GPUの使用時間を今日だけで14時間以上消費し、残りは8時間になった。

ユニット数を多くしすぎて失敗した件は、原因がはっきりわかったわけではないが、learning rateのスケジューリングプログラムを使うことで、とりあえず、解消した。

それならばと、意気込んで、60Mのデータを流してハイスコアの可能性を調べたものだから、時間ばかりかかって、成果は殆どなかった。現状のプログラムでは、0.76+が限界であることがわかった。0.77+が次々と公開されている状況では話にならないので、transformer関する情報収集と検討を明日からやる。

今週の目標は0.76だったが、実現したのは0.757までだった。

来週の目標は0.77に設定しているので、金曜日までにプログラムに手を入れて、土日に結果を出したいと考えている。 

 

12月14日(月)

Riiid!:2,678 teams, 25 days to go

SAINT benchmarkというというトピックに関する意見交換を読んでいるのだが、topic autherは0.795、transformerのbaseline code(0.715)を公開した人は0.784、に達していて、毎日のようにスコアは向上しているようだ。

give and takeが進んでいて、性能に直結するような情報の交換が行われている。公開コードを共有するのと同様に、ハイパーパラメータの具体的な値、モデルの構造、プログラムの一部などの情報を交換している。

読み込むべきは、discussionでも論文でもなく、コード自体である。英語力を鍛えてきたように、プログラミング力を最優先に鍛えていこう。

プログラミング力の無いところに金メダルは無い。

 

12月15日(火)

Riiid!2,722 teams, 24 days to go

昨夜、0.78のコードが公開されていた。SAKTとLGBMのアンサンブルである。SAKTはtrain済みのパラメータを読み込むだけで、LGBMはtrainを含む。SAINTを完成させないとその先は無いと思って、フォークは少し控えていたのだが、手を出してしまった。すでに、150チームくらいが並んでいる。別の方法でそこに到達したチームもおられるが、ちょいと乗っかったチームと見分けはつかない。その大部分はメダル圏内だが、まだ先は長いので、コンペが終わるまでには、みんなメダル圏外だろうな。何度も見てきた風景だが、そこに自分も入っている。

積読してあった「ゼロからはじめるデータサイエンス:Joel Grus著、菊池彰訳」に目を通し始めている。原著は2015年、訳本は2017年の発刊のようである。機械学習のテキストとしては新しくはないが、Python、データの可視化、線形代数、統計、確率、仮説と推定、勾配降下法、データの取得、データの操作、機械学習、・・・と続いていて、基礎を学ぶには最新でなくても良いと思う。2年以上前に何冊か購入したうちの1冊だが、数ページ目を通しただけで放置したようだ。最低でも購入日や購入書店名、読み始めればその日付などを書くのだが、そのどれもが記入されていないほど、気に入らなかったのだろうと思う。今見ると、機械学習初心者には向かない(基礎の部分が延々と続き、機械学習の話が始まるのは160ページを過ぎてからである)が、実務者には必携の書物だなと思う。

F. CholletさんのテキストもA. Geronさんのテキストも英文のまま読んでいる。コードが英文で書かれているので、とにかく、英単語が日本語に変換することなくすっと頭に入るようになりたいと思ってそうしているのだが、それにはデメリットもある。とにかく、進むのが遅い。それと、今、訳本を読み始めて感じたのだが、英語のテキストだと本文を読むのに疲れて、コードへの集中力が高まらない。対して訳本は、コードに集中できる。原著だと、コードを理解するために本文を読むのは英英辞典を使うようなものだが、訳本だと、コードを理解するときに、コードの英単語にはかなり慣れてきて辞書は要らないので、コードの機能を理解することに集中できるというメリットがある。結局は、学習の積み重ねが重要ということになるのかな。

ちょっと戻るが、FORTRANやBASICを使ってプログラミングしてきたから、Pythonなんてチョロいと思っていたのが良くなかったな。なんでもかんでもFORTRANではどうだったかな、BASICではどうだったかなと考えて、無理に置き換えて理解しようとしてつまづいたような気がする。CとかC++でもやっておけばよかったのかもしれないが、そこはまったく手を付けることがなかった。

雑談はこのくらいにしてプログラミングに集中しよう。

つい、悪い癖が・・・。0.780のコードをフォークして、チューニングしている自分がいる。  チューニングで負けないことも重要なのだ、ということにしておこう。 

 

12月16日(水)

  • Riiid AIEd Challenge
  • , 2,760 teams
  • , 23 days to go

今、0.780に約220チーム(166~384)が並んでいる。

ここから脱出しようともがいている。その結果、今、0.780の先頭にいる。

今日は、0.780で先頭のまま、終わってしまいそうだ。 

 

「ゼロからはじめるデータサイエンス」

1章のイントロダクションの中をウロウロしている。辞書形式のユーザーリストから始まる。idとnameが並んでいるだけ。交友関係を調べてグラフ化する。

users = [

      { "id": 0, "name": "Hero"},

      { "id": 1, "name": "Dunn"},

こんな感じで並んでいるのだが、いかにもめんどくさそう。

この辞書形式は、パラメータの設定で使われる。

Riiid!のコンペで使っているtrain_dataの情報をdictionary形式で表現すると、

data_types_dict = {
    'timestamp': 'int64',
    'user_id': 'int32', 
    'content_id': 'int16', 
    'content_type_id':'int8', 
    'task_container_id': 'int16',
    'user_answer': 'int8',
    'answered_correctly': 'int8', 
    'prior_question_elapsed_time': 'float32', 
    'prior_question_had_explanation': 'bool'
}

目の前の課題に直結した事例で説明されていれば、だれでも食らいつくだろうが、内容に興味が持てない場合には、勉強が捗らない。これが、自習の難しさの重要な要因の1つだろうな。

次は、交友関係をタプルで表したものが現れる。

friendships = [(0, 1), (0,2), (1, 2), (1, 3), (2, 3), ..., ...]

さらに各ユーザーが持っている興味を表にしたもの。

interests = [

      (0, "Hadoop"), (0, "Big Data), ..., (1, "NoSQL"), ..., (2, "Python"), ...,

]

書くのが面倒だからめちゃくちゃ省いた。

書いてることもめちゃくちゃになってきた。

次に移ろう。

第2章のPython速習コースだ。

19ページ:空白によるフォーマット

知らなかった:

丸カッコ、角カッコの内部では空白が無視されるので、長い行を折り返して書けます。

コードの右側が見えないとき、適当に切断して折り返したら、誤動作したことがあった。これは、簡単なことだが、重要だ。

20ページ:モジュール

importの便利な機能、import *には要注意。

不用意にモジュール全体をインポートすると、自分で定義した変数を意図せずに上書きしてしまう点に注意が必要。

21ページ:関数

def double(x):

      return x * 2

名前を持たない短い関数(ラムダ:lambda)がよくわからない。

y = apply_to_one(lambda x: x + 4)

デフォルト引数という使い方:こういうのは知らないと困る。

def subtract(a=0, b=0):

      return a - b

subtract(10, 5) # =5

subtract(b=5) # =-5:b=5だけが関数subtractに送られると、a=0とb=5が代入されて、0-5=-5 が返される。

22ページ:文字列

バックスラッシュに注意

複数文字列については理解できない。

29ページ:例外

try:

    print 0 / 0

except ZeroDivisionError:

    print "cannot divide by zero"

29ページ:リスト

Pythonの最も基本的なデータ構造は、おそらくリストでしょう。:と書かれている。

これは、イロハのイですかね。:自分は、これを理解できていないがゆえに、コードの理解/解読/書き換え等に手間取っている、苦しんでいる。

integer_list = [1, 2, 3]

heterogeneous_list = ["string", 0.1, True]

list_of_lists = [integer_list, heterogeneous_list, [ ] ]

list_length = len(integer_list) # 3

list_sum = sum(integer_list) # 6

24ページ:リストの続き

x = range(10) # list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

zero = x[0] # 0番目 インデックス0の要素、すなわち0

one = x[1]

nine = x[-1]

eight = x[-2]

x[0] = 1 # list [-1, 1, 2, 3, 4, 5, 6, 7, 8, 9]:ここで、xが変更されたことに注意!

first_three = x[ :3] # 0番目から3番目までの要素:[-1, 1, 2]

three_to_end = x[3: ] # 3番目から最後までの要素:[3, 4, 5, 6, 7, 8, 9]

one_to_four =  x[1:5]

last_three = [-3: ] # 最後から3つ前までの要素:[7, 8, 9]

without_first_and_last = x[1:-1]

copy_of_x = x[ : ]

...

x = [1, 2, 3]

x.extend([4, 5, 6]) # xは[1, 2, 3, 4, 5, 6]になる。

[ ]が( )に囲まれている、[ ] が( )の中にある、( [     ] )、こういうのを見ただけで気分が悪くなる。違和感を感じてしまう。それぞれの役割が理解できていないからだろう。

x.extend( )が定義で、extendしたいリスト[ ]を、( )の中に記述する、というだけのことか。y = [4, 5, 6]としておけば、x.extend(y) = x.extend([4, 5, 6])。

x = [1, 2, 3]

z = len(x):z = len([1, 2, 3])

x, y = [1, 2]:x=1, y=2

_, y = [1, 2]:y=2:こういう表記 "_," は違和感を感じるのだが、こういうのを多用したコードから、つい、目をそらしてしまう。慣れてしまおう。

25ページ:タプル

読めばわかるかな。

26ページ:辞書

2,3写しておく。

grades = { "Joel" : 80, "Tim" : 95 }

joel_grade = grades["Joel"]

少しぼやけてきた。辞書は、キー”Joel"と値80を関連付けて格納したもの。

27ページ:defaultdictクラス

文章document中の単語wordの数を数えるcount。

word_counts = { }

for word in document:      # documentの端から順にwordを取り出す

      if word in word_counts:            # 取り出したwordが辞書にあれば1を追加する。  

            word_counts[word] += 1

      else:                # 取り出したwordが辞書になければwordを登録し1とする。

         word_counts[word] = 1

コメントは自分が適当につけたもので、これでよいかどうかわからない。

キーが登録されていることが前提のようなコードなので、最初の行でword_countsを初期化しているのが腑に落ちない。

defaultdictというのを使えばよいらしい。

29ページ:Counterクラス

単語の出現数を数える問題は次の1行で完成するとのこと。

word_counts = Counter(document)

出現数の多い順に要素を返すmost_commonメソッドが用意されているとのこと。

for word, count in word_counts.most_common(10):

      print word, count

29ページ下:集合

大量のデータの中から要素が含まれるかチェックする必要があるなら、集合は最も適したデータ構造とのこと。

最後に、集合より辞書やリストの方が頻繁に使われます、と書かれている。

30ページ:実行順制御

ifによる条件判定

whileループ

forとinの組み合わせ

for x in range(10):

      print x, "は、10より小さい”

より複雑な制御が必要ならcontinueやbreakも利用できる、とのこと。

31ページ:真偽

True, False

次は上級Pythonと書いてある。

 

12月17日(木)

Riiid AIEd Challenge, 2,787 teams, 22 days to go

急に順位が下がったと思ったら、0.781のコードが公開されている。

0.780のコードとの違いは、主に、流すデータ量の違いで、0.780のコードは、(12M、fraction=0.15)、0.781のコードは、(20M、fraction=0.09)、となっている。

これを実現するために、featureを減らしている。featureを減らさないでこれだけのデータ量を流そうとするとエラーが出る(確認済み)。

今(13時)調べると約80チームが0.781に、約200チームが0.780に並んでいる。

Discussionによれば、現在1位の人は、SAINTベースで、7位の人はLGBMベースのようである。重要なのは、feature engineeringのようだ。

0.780が0.781になったのは、データ量が12Mから20Mに増えたのが原因ではなく、featureを減らしたことが原因であるかもしれない。その効果を打ち消すようなfeatureの組があって、片方を削除したことで、他方の効果が現れたのかもしれない。

といっても、効果は+0.001です。小さくはないが、大きくもない。今の段階では、データ量を増やすことよりも、featureを工夫することが重要だろうな。

 

LightGBM

優れものらしいが、パラメータが多くて、性能を発揮するには、データ、前処理、プログラム構成などの要素に加えて、LGBMそのものの特性・特徴をよく理解しておかなければならない。ということだけど、具体的にどうすればよいのか。

ドキュメント量は非常に多く、パラメータの定義を見ても、パラメータの設定範囲がわかりにくいものもある。optunaの開発メンバー、小嵜氏のブログを見ると、次のようなコードが示されている。これで、チューニングにおいてこれらのパラメータが重要だろうと推測される。

param = {
        'objective': 'binary',
        'metric': 'binary_logloss',
        'lambda_l1': trial.suggest_loguniform('lambda_l1', 1e-8, 10.0),
        'lambda_l2': trial.suggest_loguniform('lambda_l2', 1e-8, 10.0),
        'num_leaves': trial.suggest_int('num_leaves', 2, 256),
        'feature_fraction': trial.suggest_uniform('feature_fraction', 0.4, 1.0),
        'bagging_fraction': trial.suggest_uniform('bagging_fraction', 0.4, 1.0),
        'bagging_freq': trial.suggest_int('bagging_freq', 1, 7),
        'min_child_samples': trial.suggest_int('min_child_samples', 5, 100),
    }

このコードであれっと思った箇所が2つある。1つは、num_leavesの最大値が256となっていること、もう1つは、lambdaの設定値の最大値が10となっていることである。

前者については、300以上に設定している例をよくみかける。性能アップにはnum_leavesを大きくすべし、と書かれている記事が多いからだろうと思う。

後者については、設定範囲は0-1と、勝手に思いこんでいた。

これを見ると、optunaというものを使ってみたくなるな。

投入できるデータ量を増やすために、featureを見直した結果、良いか悪いかはわからないが、これまでの条件では極端なオーバーフィッティングになることがわかった。L1,L2も効かないので、num_leavesから見直しを始めた。フォークしたときの350を、そのまま使い続けていたがこの際だから、再出発のつもりで、デフォルトの32から検討している。

num_leaves=32:train_auc=0.782, val_auc=0.767でピーク:目標の0.772+は遠い。

num_leaves=64:train_auc=0.787, val_auc=0.769:まだまだだが、num_leaves=350の結果をわずかではあるが上回った。葉っぱの枚数が多ければ良いというものではないことを実感した。NN系のoverfittingには慣れているが、機械学習系はこれまでoverfittingを実感することはなかった。

num_leaves=96:train_auc=0.788, val_auc=0.768:これ以上良くならない。

 

「ゼロからはじめるデータサイエンス」J. Grus著、菊池彰訳

第5章 統計

代表値:

通常、データはどこが中心となっているのかに興味がある。多くの場合、値の総和をデータ数で割った平均値を用いる。

def mean(x):

      return sum(x) / len(x)

場合により、中央値medianが必要になる場合もある。

def median(v):

      n = len(v)

      soeted_v = sorted(v)

      midpoint = n // 2

      if n % 2 == 1:

            return sorted_v[midpoint]

      else

            lo = midpoint - 1

            hi = midpoint

            return (sorted_v[lo] + sorted_v[hi]) / 2

平均値meanはデータ内の外れ値に対して中央値medianよりも敏感である。

繰り返し語られる話題:1980年代中ごろ、ノースカロライナ大学の卒業生で最も高い初任給を得られた専攻は地理学であった。それは、NBAのスター選手(良い意味の外れ値を提供)、マイケル・ジョーダンが原因である。

モード(最頻値)も重要である。

 

12月18日(金)

Riiid AIEd Challenge, 2,823 teams, 21 days to go

当面は、公開コードによって増殖中の0.781を超えないとメダルは無い。

0.781を超えようと思って昨夜セットした計算は1000ラウンドで収束したが、commitは3500ラウンドを超えても収束しない。どうなることやら。

結局、4700ラウンドの手前で終了したが、8時間くらいかかった。やれやれ。

なんとか、0.781の列の前の方に着地した。

val_AUCからは、0.782になってもよさそうなのだが・・・。

commit中にラウンド数が増えるとともに、val_aucも上がったので喜んでいたのだが、期待通りにならなかった。

どうも、commit中にオーバーフィッティングが増幅されているようだ。

 

12月19日(土)

この1週間のGPUの割当は30時間となっている。少ないな!

 

Riiid AIEd Challenge, 2,854 teams, 20 days to go

オーバーフィッティングを避ける方法の1つとして、少なめのラウンド数で止めてsubmitしてみた。val_aucがほぼ同じで、train_aucは低く抑えられた。

しかし、LBの改善には結びつかなかった。

再現性が良くない。

commit中にoverfitting気味になるかと思えば、明らかに小さな値になることもある。

現在の条件で再現性を調べてみる。

誰かの記事にならって6Mくらいのrawデータ量でチューニングしてから、データ量を増すことにして、チューニングをしてみたが、ラウンド数が少ないと、ばらつきのために違いが見えにくく、6Mのデータでも時間がかかる。パラメータによっては、ラウンド数が増えてから効果が現れてくるものもあるので、早い段階での数値を比較していると判断を誤ることがある。これは結構深刻な問題である。

フォークしたコードのLBスコアを0.001上げられずに苦しんでいる自分がいる。

昨日はcommit中のスコアが高くなり、今日はcommit中のスコアが低くなった。

結果として、どちらの場合でもLBスコアの向上に結び付いていない。

feature engineeringをやれと言われているような気がしてくる。 

 

12月20日(日)Riiid AIEd Challenge, 2,890 teams, 19 days to go

チューニングによるスコアが頭打ちになってきたので、featureの選択や処理/追加作製方法を学ぼうと、notebookを検索してみた。

以前にも参考にさせていただいたコードが、バージョンアップされていた。EDAとBaseline modelという内容はそのままだと思うが、以前に見たときは、計算するところで終わっていたように思うが、submitできるようになっている。

コンペで競うことを目的に参加している人が大半だと思うが、コンペ参加者のために、EDA、解法例、submittするためのコード、などを公開することを目的とされている人がおられるのではないかと思う。非常にありがたいことである。

featureの選択をやっているが、難しい。

 

12月21日(月)

Riiid AIEd Challenge, 2,923 teams, 18 days to go 

今日もfeatureの選択をやっている。

いろいろやっていて、面白い現象がおきた。

投入するfeatureの組み合わせによって、Feature Importanceの分布が大きく変化したのである。分布の見た目の違いほどには、Val_AUCは変わらなかったが、少し大きくなる組み合わせも出てきた。LBも改善されることを期待しているが結果はまだ出ていない。

残念、少し良い結果をcommitしている最中にエラーが発生した。

計算からやり直しだ。

 

12月22日(火)

Riiid AIEd Challenge, 2,960 teams, 17 days to go 

feature選定検討中

 

12月23日(水)

Riiid AIEd Challenge, 2,994 teams, 16 days to go

12月18日に0.781に着地して以来、更新できていない。

それも、100%借り物のコードである。

LGBMについては、少しは理解が進んだと思うが、思考錯誤の時間さえあればだれでもできそうなことしかできていない。

feature engineeringをやっている、と感じられるコードをみていると、val_AUCの値も、feature importanceの分布も、用いるfeatureによって大きく変化しているのがわかる。

それらの変化の大きさと比べると、LGBMのチューニングによる効果は小さい。

といっても、'gbdt'の中でのことであって、'goss'や'dart'までは試していない。

LGBMのサイトの、Parameters Tuningには、次のような項目がある。

For Better Accuracy

  • Use large max_bin (may be slower)

  • Use small learning_rate with large num_iterations

  • Use large num_leaves (may cause over-fitting)

  • Use bigger training data

  • Try dart

これだけでは、さっぱりわからない。

LGBMのサイトのExperimentsに、xgboostとxgboost_histとLightGBMの性能を比較した結果があるが、その際に用いられているLGBMのパラメータは次のようになっている。

(・・・)は自分の付記である。

LightGBM:

learning_rate = 0.1(デフォルト)
num_leaves = 255(デフォルト:31)
num_trees = 500(num_iterationsと同じ?)
num_threads = 16(CPUのコア数)
min_data_in_leaf = 0(デフォルト:20)
min_sum_hessian_in_leaf = 100(デフォルト:1e-3)

 

12月24日(木)

  • Riiid AIEd Challenge
  • , 3,029 teams
  • , 15 days to go

現在、0.782の最後尾:まだ2週間もあるので、このままでは、メダル圏外は確実だ:銀は0.785:金は0.805

LGBMのコードのfeatureの選択を行っている。

現状でほぼ最大値を示す状態から、各featureをOn, Offしたときのスコアの変化量を見ようとしている。各featureは独立しているとは限らないので、その扱いは単純ではないが、数値化することによって、先が見えてくるかもしれない。

各featureをOn, Offしたときのスコア変化を1つ1つ調べ、変化による差異を記録し、全てを調べた後で、プラス方向に変化するようにfeatureをon,offすれば、最適化が進むと考え、試してみた。

問題は、データ量と、収束条件をどうするかだ。

データ量はある程度の大きさで固定すれば良さそうである。

収束条件は、early_stoppingを使ったのだが、onとoffの差が小さく、有用なはずのfeatureがマイナスの評価になることがあった。こういう評価は、探索の前に、必ず、ばらつきを抑えておかないとだめだな。スコアがなかなか上がらないとあせってしまって、手抜きになって、十分な成果が得られない。不要なfeatureを選び、必要なfeatureを落としているかもしれない。

他にも問題がある。これもばらつきが原因なのだが、どうも、ドラフト計算結果よりcommit後の方が良くない結果になることが多い。これも、同一条件で3回繰り返せばはっきりするのだが、ドラフトとcommitで5~6時間以上かかっているので、同一条件の繰り返しは、できていない。何度かやろうとしたが、ついつい、パラメータをいじってしまう。同じ時間を費やすなら、異なるパラメータの結果を知りたいと思ってしまうのだが、結局、それも、ばらつきがわからないから、大小関係の判定が正しく行えないので意味不明の結果になってしまう。

今から、同一条件で、ドラフトーcommitを3回繰り返してみよう。ばらつきは、計算プロセスの中に存在し、ドラフトかcommitかは無関係なので、それぞれがばらついて、3回とも、commit後の値が小さくなる確率は非常に小さいはずだ。

1回目:ドラフト:0.7745、commit:0.7734

2回目:ドラフト:0.7742、commit:0.7743

3回目:ドラフト:0.7745、commit:0.7743

結果は、こうなった。いずれも、LGBM:500ラウンドの結果である。1回目のcommitが若干はずれている、というところか。

なぜ、commit後の値の方が小さくなると感じているのかを分析してみよう。

その答えは簡単である。

すなわち、計算は、何らかの指標によって改善が見込まれるときに行うので、途中経過が良くないと、中止してしまっているのである。反対に、途中経過が良いときには、気をよくしてcommit, submitに進むのである。つまり、途中経過が良くない場合に中止しないでcommitしていれば、ドラフトよりもcommit後の結果の方が良くなっていただろう、ということである。つまり、commit後の計算がいつも小さくなっているように感じるのは、途中経過が良い場合にのみ、commitしているからである。

予測モデルの汎用性を高めるには、計算を繰り返して、良い結果も悪い結果も全部含めて平均を取ることが効果的であって、良い結果だけの平均をとることは、汎用性を下げてしまうことになっている可能性が高い。いわゆるoverfittingである。

ヒトが介入することで、良くなることもあれば、悪くなることもある。

ということからすると、AとBのアンサンブルをする場合に、スコアの良い方の比重を上げようとすることが多いが、それは、overfittingにつながるかもしれない。public LBも常に向上するとは限らない。凝り固まらずに、いろいろ試してみることが重要。

どのコンペだったか、アンサンブルにアンサンブルを重ねて失敗したことがあった。private LBが最も良かったのは、全てのモデルの単純平均だったような気がする。このときは、ヒトが介入しすぎて、public_dataにoverfitしてしまったということだろうな。

そうだ、機械的にやればいい。・・学習ですから。

 

計算の合間に「ゼロからはじめるデータサイエンス」Joel Grus著、菊池彰訳

ソート

x = [ 4, 1, 2, 3 ]

y = sorted(x) # y = [ 1, 2, 3, 4 ]

x.sort( ) # x = [ 1, 2, 3, 4 ]

# 絶対値で降順にソート

x = sorted([ -4, 1, -2, 3], key=abs, reverse=True) # is [ -4, 3, -2, 1 ]

リストの連結

x = [1, 2, 3]

x.extend([4, 5, 6]) # リストxは、[1, 2, 3, 4, 5, 6]になる。

要素の追加

x = [1, 2, 3]

x.append(0) # リストxは、[1, 2, 3, 0]となった。

z = len(x) # z = 4

 

12月25日(金)

Riiid AIEd Challenge, 3,061 teams, 14 days to go 

昨日はmax_round=500で実施したが、earlystopの条件を満たさず、3回ともmax_roundの500で停止した。

次は、max_round=1000、にして、3回繰り返してみる。

ちょっと(5時間程度)やってみたが、昨日の3回の結果でLBスコアの改善が見られなかったことと、繰り返し再現性(ばらつき)についてある程度の知見は得られたので、スコアアップのための他の方法を検討する。

featureを順位の高い方から10件だけ使うとか、30件くらい使うとか、いろいろやっているが、val_AUCが上がらない。下がることの方が多い。

正直、途方に暮れている。

こういうときに、最も簡単で効果的な方法がある。

これまで最高のスコアを出したコードに戻って、そこから、確実な改善を積み重ねることである。ここから、まだ、ハイスコアのコードが公開される可能性は高いが、だからといって、まだ、そういうものと戦う力は無いので、一足飛びに上を目指すのは少し横においておこう。

まずは、0.782の中を這い上がろう。

 

計算の合間に「ゼロからはじめるデータサイエンス」Joel Grus著、菊池彰訳

リスト内包

even_numbers = [x for x in range(5) if x % 2 == 0] # [0, 2, 4]

squares = [x * x for x in range(5)] # [0, 1, 4, 9, 16]

even_squares = [x * x for x in even_numbers] # [0, 4, 16]

square_dict = { x : x * x for x in range(5)} # { 0:0, 1:1, 2:4, 3:9, 4:16 }

square_set = { x * x for x in [1, -1]} # { 1 }

簡単な表現で十分に慣れておけば、実際の場面でも理解できるようになるだろう。

アンダースコア "_" も慣れておけば、出くわしたときに、あわてなくてすむ。

zeros = [ 0 for _ in even_numbers ] # even_numbersと同じ長さの0が続くリスト

 

Training data-efficient image transformers & distillation through attention
Hugo Touvron, Matthieu Cord, Matthijs Douze, Francisco Massa, Alexandre Sablayrolles, and Herve J ´ egou ´, Facebook AI, Sorbonne University

Abstract

Recently, neural networks purely based on attention were shown to address image understanding tasks such as image classification.

However, these visual transformers are pre-trained with hundreds of millions of images using an expensive infrastructure, thereby limiting their adoption by the larger community.

In this work, with an adequate training scheme, we produce a competitive convolution-free transformer by training on Imagenet only.

We train it on a single computer in less than 3 days. Our reference vision transformer
(86M parameters) achieves top-1 accuracy of 83.1% (single-crop evaluation) on ImageNet with no external data. We share our code and models to accelerate community advances on this line of research.

Additionally, we introduce a teacher-student strategy specific to transformers.

It relies on a distillation token ensuring that the student learns from the teacher through attention.

We show the interest of this tokenbased distillation, especially when using a convnet as a teacher.

This leads us to report results competitive with convnets for both Imagenet (where
we obtain up to 84.4% accuracy) and when transferring to other tasks. 

 

12月26日(土)

Riiid AIEd Challenge, 3,098 teams, 13 days to go 

残り2週間を切った。0.8+に至る道は、まだ見えない。

0.79+レベルのコメントでは、公開コードにあるfeatureの組み合わせでは不十分で、さらに工夫が必要になるとのこと。

 

***雑談***

Python系のプログラミング技術の習得が不十分であるために自分でプログラムを組むことができないからフォークするのか、それとも、課題を解決する方法がわからないためにプログラミングするところまでいかないからフォークするのか。

優れたプログラミング技術と優れた課題解決方法を学ぶためにフォークしているのです、と答えたいところだが、実際のところは、リーダーボードに掲載されてみたいし、あわよくばメダルを獲得したいからである、ということになろうか。

フォークすること自体は何の問題もない。問題があるとすれば、フォークしたコードをそのまま実行し、その結果をsubmitしてしまうことである。いや、これも問題はない。フォークしたコードをチューニングすることも加工することも、問題はない。

公開コードは、ある程度の時間が経てば、初級レベルからメダル圏内に入りそうなレベルのものまで公開されている。したがって、十分な時間があれば、手作りから始めて、わからないところは、公開コードを参考にしながら、プログラムを組み上げていけばよいのである。この作業を丁寧にやっていれば、プログラミング技術は向上し、課題解決能力も向上していく。

 

12月27日(日)

Riiid AIEd Challenge, 3,122 teams,12 days to go 

0.783の爆弾が落とされて、メダル圏外に放り出されてしまった。

このコードは、0.780、0.781と似ているが、LGBMモデルに学習させるfeatureの数と種類が異なっていて、データ量も違っている。

データ量とfeature数は逆相関になっていて、データ量を増やすには、featureを減らす必要があった。公開コードの0.780と0.781が示していた(暗示していた)ことは、feature数を減らしてデータ量を増やせば、0.001だけLBが上がるということであった。

200チーム以上がフォークしてチューニングを試みたと思うが、この方向が効果的であれば、0.782になだれ込むはずだが、そうはならなかった。自分も、featureを減らしてデータ量を増やすことでLBアップを狙ったが、労力の割には効果は小さかったと思う。

0.781の中を通って、0.782の仲間入りを果たしたまでは良かったが、0.782の最後尾に張り付いたまま動けなくなった。

現在、0.783のコードが 2つ公開されているが、まさにこのfeature数とデータ量の違いである。feature量を効果的に減らしてデータ量を増やすか、データ量は押さえてfeatureの種類を増やすかの2者択一になっている。

では、もっと上位の方々は、どういう方法を用いてるのだろうか。

アンサンブルかな。

SAKT、SAINT、TabNet、1次元CNNやLSTM、GRUなどの従来型のRNNなど様々な手法のモデルのアンサンブルが有効なのかもしれない。
公開コードの中に存在しているものを適切に組み合わせる技術があればいいのだが。

今後のためにも、その方法を少しでも多く学んでおこう。

 

12月28日(月)

Riiid AIEd Challenge, 3,161 teams, 11 days to go

銀以上を狙っているのだが、現状では、銅も難しい。

競争が本格化するのはここからだ。1週間前、3日前と、さらに厳しくなる。

0.783をフォークしてチューニングしているが、前進できない。featureの選び方に不自然さを感じたので、これまで自分なりに順位付けしていたfeatureを優先的に選んでみたが、val_aucは上がっても、LBスコアは上がらない。

不思議なのは、40個以上あるfeatureのうちで、feature importanceが小さい5つを除いてみると、val_aucは0.0013上がるが、LBは上がらない。それだけでなく、feature importanceの順番と分布が一目でわかるくらい大きく変わったことである。

ということから、val_aucの値とfeature importanceの分布が、それぞれ適切な値/分布になるときに、LBスコアは上がるということのようなので、探索範囲を拡げて1つ1つ調べていく必要がありそうだ。

 

計算の合間に文法を学ぼう。

.replace:文字列を置換する

pandas.get_dummies()

note.nkmk.meから引用:

pandasでカテゴリ変数(カテゴリカルデータ、質的データ)をダミー変数に変換するには、pandas.get_dummies()関数を使う。

文字列でカテゴリー分けされた性別などのデータを、男を0, 女を1のように変換したり、多クラスの特徴量をone-hot表現に変換したりすることができる。機械学習の前処理として行うことが多い。

例として以下のデータを使用する。説明のために列を追加している。

import pandas as pd
import numpy as np

df = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0)

df['sex'] = ['female', np.nan, 'male', 'male', 'female', 'male']
df['rank'] = [2, 1, 1, 0, 2, 0]

print(df)
#          age state  point     sex  rank
# name                                   
# Alice     24    NY     64  female     2
# Bob       42    CA     92     NaN     1
# Charlie   18    CA     70    male     1
# Dave      68    TX     70    male     0
# Ellen     24    CA     88  female     2
# Frank     30    NY     57    male     0

引数にpandas.DataFrameを指定する場合
pandas.DataFrameの場合は、デフォルトではデータ型dtypeがobject(おもに文字列)またはcategoryである列がすべてダミー変数化される。

数値(int, float)やブールboolの列は変換されず元のまま。数値やブールの列もダミー化したい場合の設定については後述。

pandas.DataFrameの場合の列名は元の列名_カテゴリー名となる。変更する設定は後述。

print(pd.get_dummies(df))
#          age  point  rank  state_CA  state_NY  state_TX  sex_female  sex_male
# name                                                                         
# Alice     24     64     2         0         1         0           1         0
# Bob       42     92     1         1         0         0           0         0
# Charlie   18     70     1         1         0         0           0         1
# Dave      68     70     0         0         0         1           0         1
# Ellen     24     88     2         1         0         0           1         0
# Frank     30     57     0         0         1         0           0         1

 

これ以上の転載はやめておく。

pd.get_dummies( )を使いこなせるようになろう。

.groupby:note.nkmk.meから引用

pandas.DataFrameをGroupByでグルーピングし統計量を算出

pandas.DataFrame, pandas.Seriesのgroupby()メソッドでデータをグルーピング(グループ分け)できる。グループごとにデータを集約して、それぞれの平均、最小値、最大値、合計などの統計量を算出したり、任意の関数で処理したりすることが可能。

なお、マルチインデックスを設定することでも同様の処理ができる。以下の記事を参照。

関連記事: pandasのMultiindexで階層ごとの統計量・サンプル数を算出
また、pandas.pivot_table(), pandas.crosstab()という関数を用いてカテゴリごとの統計量やサンプル数を算出することもできる。この方法が一番シンプルかも知れない。

関連記事: pandasのピボットテーブルでカテゴリ毎の統計量などを算出
関連記事: pandasのcrosstabでクロス集計(カテゴリ毎の出現回数・頻度を算出)

groupby()でグルーピング
pandas.DataFrameのgroupby()メソッドでグルーピング(グループ分け)する。なお、pandas.Seriesにも同様にgroupby()メソッドがある。

pandas.DataFrame.groupby — pandas 1.0.4 documentation
pandas.Series.groupby — pandas 1.0.4 documentation
引数に列名を指定するとその列の値ごとにグルーピングされる。

GroupByオブジェクトからメソッドを実行することでグループごとに処理ができる。メソッド一覧は以下の公式ドキュメント参照。

GroupBy — pandas 1.0.4 documentation
例えばsize()メソッドでそれぞれのグループごとのサンプル数が確認できる。

平均、最小値、最大値、合計などを算出
上記のメソッド一覧にあるように、GroupByオブジェクトに対しmean(), min(), max(), sum()などのメソッドを適用すると、グループごとの平均、最小値、最大値、合計などの統計量を算出できる。

そのほか標準偏差std()、分散var()などもある。

いずれのメソッドも新たなpandas.DataFrameを返す。

任意の処理を適用して集約: agg()
GroupByオブジェクトのagg()メソッドで任意の処理を適用することもできる。

pandas.core.groupby.GroupBy.agg — pandas 1.0.4 documentation
引数に適用したい処理を指定する。

GroupByオブジェクトのメソッド名を文字列で指定できるほか、組み込み関数やNumPyの関数などの呼び出し可能オブジェクト(callable)を指定可能。

関連記事: pandasのagg(), aggregate()の使い方

.reset_index

pandas.DataFrame, Seriesのインデックスを振り直すreset_index

reset_index()メソッドを使うと、pandas.DataFrame, pandas.Seriesのインデックスindex(行名、行ラベル)を0始まりの連番(行番号)に振り直すことができる。

pandas.DataFrame.reset_index — pandas 0.22.0 documentation
行番号をインデックスとして使っている場合、ソートして行の順番が変わったときや行を削除して欠番が出たときなどはインデックスを振り直したほうが使いやすい。

また、行名(行ラベル)をインデックスとして使っている場合に、現在のインデックスを削除したりデータ列に戻すためにも使う。set_index()とreset_index()を使うことで、インデックスを別の列に変更(再設定)することができる。

 

feature enginering

An Empirical Analysis of Feature Engineering for Predictive Modeling
Jeff Heaton, SoutheastCon 2016, 2016 - ieeexplore.ieee.org

I. INTRODUCTION
Feature engineering is an essential but labor-intensive component of machine learning applications [1]. Most machinelearning performance is heavily dependent on the representation of the feature vector. As a result, data scientists spend much of their effort designing preprocessing pipelines and data transformations [1]. To utilize feature engineering, the model must preprocess its input data by adding new features based on the other features [2]. These new features might be ratios, differences, or other mathematical transformations of existing features. This process is similar to the equations that human analysts design. They construct new features such as body mass index
(BMI), wind chill, or Triglyceride/HDL cholesterol ratio to help understand existing features’ interactions. Kaggle and ACM’s KDD Cup have seen feature engineering play an essential part in several winning submissions. Individuals applied feature engineering to the winning KDD Cup 2010 competition entry [3]. Additionally, researchers won
the Kaggle Algorithmic Trading Challenge with an ensemble of models and feature engineering. These individuals created these engineered features by hand.  

... the following sixteen selected engineered features:
• Counts
• Differences
• Distance Between Quadratic Roots
• Distance Formula
• Logarithms
• Max of Inputs
• Polynomials
• Power Ratio (such as BMI)
• Powers
• Ratio of a Product
• Rational Differences
• Rational Polynomials
• Ratios
• Root Distance
• Root of a Ratio (such as Standard Deviation)
• Square Roots

こういう演算によってfeatureを作り出すということのようだ。

LGBMを使った公開コードを見ていると、これらの演算を使ってfeatureを作っていることがわかる。演算の種類も、featureの組み合わせ方も重要で、いかにして良いfeatureを作り出すか、ということなんだろうな。

 

12月29日(火)

Riiid AIEd Challenge, 3,184 teams, 10 days to go

昨夜、LGBMのパラメータ:feature_fractionが気になって、値を少し大きく変えて計算してみた。そうすると、feature_importanceの分布がその値によって大きく変わることがわかった。val_aucの値も変化している。submitしてLBスコアを確かめよう。LBスコアは少し改善した。といっても、0.001以下でのこと。

 

計算の合間にLGBMとfeature_engineering:

Francois Chollet “Developing good models requires iterating many times on your initial ideas, up until the deadline; you can always improve your models further. Your final models will typically share little in common with the solutions you envisioned when first approaching the problem, because a-priori plans basically never survive confrontation with experimental reality.”

Francois Chollet「優れたモデルを開発するには、締め切りまで、最初のアイデアを何度も繰り返す必要があります。 モデルはいつでもさらに改善できます。 事前の計画は基本的に実験的な現実との対立に耐えることができないため、最終的なモデルは通常、最初に問題に取り組むときに想定したソリューションとほとんど共通点がありません。」

                                                                                                           by google translation

 

12月30日(水)

Riiid AIEd Challenge, 3,211 teams, 9 days to go 

意味を理解できていないパラメータを意味の分からない値に設定しながら、ようやく0.785に到達した。

今朝、自信をもってsubmitしたが、前進できなかった。改善は、ばらつきの範囲で、偶然生じただけかもしれない。

確認のためには、同一条件での計算を、3回繰り返すことになる。

ばらつきによって上がったのを、パラメータが適切であったと思ってしまったら、誤った方向に行くことになる。

さらに、忘れてはならないのは、private_dataへのover-fittingである。

「意味を理解できていないパラメータを意味の分からない値に設定しながら」:こういうことだと、public_LBだけを頼りにfeatureの選択やパラメータの設定をすることになるので、public_dataへのoverfittingになりやすい。

チューニングが行き詰ってきたこともあり、LightGBMのマニュアルの ”Parameters Tuning"を参考に、num_leavesとmin_data_in_leafとmax_depthを用いて、条件検討をやりなおすことにした。num_leavesしか使っていなかったので、他の2つは適当に値を設定してやってみたら、10時間くらいで、なんとなくそれらしい結果が出始めた。そこで、submitではなく、記録のためにcommitしたら、commitの途中で、"[Worning] No further splits with positive gain, best gain: -inf"というメッセージが現れた。これはダメだろうと思い、中断して、調べたら、min_data_in_leafの設定値、1024が大きすぎることによるものであるらしい、ということがわかった。

マニュアルには、大きなデータの場合には数百もしくは数千で十分"In practice, setting it to hundreds or thousands is enough for a large dataset".とあったので、間をとって1024にしたのだが、この1024が不適切だったようだ。

そこで、min_data_in_leafを512, 256, 128とかえてみたが、同じ症状だった。ドラフト計算可能、良好な結果が得られている。しかし、commitすると、警告が出る。

min_data_in_leafは、over-fittingしないための非常に重要なパラメータである(This is a very important parameter to prevent over-fitting in a leaf-wise tree.、と書かれている。 

なんとかして、使いこなしたいものだ。 

 

計算の合間にLGBMとfeature_engineering:

bagging_fractionの使い方:指定した割合のデータをランダムにサンプリングする。

pos_とneg_があって、used for imbalanced binary classification problem、となっている。今回のRiiidコンペの場合だと、正答率が約65%でアンバランスだから、正答をpositiveとすれば、pos_bagging_gractionを0.35、neg_bagging_fractionを0.65とすれば、サンプリングしたデータ中には、正答と誤答が同等の割合で含まれることになる。ただし、他の方法で補正しているかもしれないので、公開コードを使うときには、全部調べてからにしないと、これを使ったがために、かえって、アンバランスを生じる可能性がある。しかしながら、理屈通りに動作するとは限らないので、比率を系統的に変えてみて、結果がどうなるかを実験してみるのも、よいかもしれない。

feature_fractionもbagging_fractionも、”can be used to speed up training、can be used to deal with over-fitting””という記述がある。直観的には、dropoutに似た効果かなと思う。

LGBMのParameterの説明について"over-fitting"を検索すると、次のパラメータが、over-fittingに関連していることがわかる。

"extra_trees", "max_bin", "min_data_in_bin", "max_depth", "min_data_in_leaf", "min_sum_hessian_leaf",

"max_bin"は、"small number of bins may reduce training accuracy but may increase general power (deal with over-fitting)"、と記述されている。

max_binは、accuracyが上がることを期待して大きな値にセッティングしがちだが、generalizationとのバランスが必要のようだ。

LightGBMのマニュアルの”Parameters Tuning"をじっくり眺めてみよう。

Tune Parameters for the Leaf-wise (Best-first) Tree

LightGBM uses the leaf-wise tree growth algorithm, while many other popular tools use depth-wise tree growth. Compared with depth-wise growth, the leaf-wise algorithm can converge much faster. However, the leaf-wise growth may be over-fitting if not used with the appropriate parameters.

To get good results using a leaf-wise tree, these are some important parameters:

  1. num_leaves. This is the main parameter to control the complexity of the tree model. Theoretically, we can set num_leaves = 2^(max_depth) to obtain the same number of leaves as depth-wise tree. However, this simple conversion is not good in practice. The reason is that a leaf-wise tree is typically much deeper than a depth-wise tree for a fixed number of leaves. Unconstrained depth can induce over-fitting. Thus, when trying to tune the num_leaves, we should let it be smaller than 2^(max_depth). For example, when the max_depth=7 the depth-wise tree can get good accuracy, but setting num_leaves to 127 may cause over-fitting, and setting it to 70 or 80 may get better accuracy than depth-wise.

  2. min_data_in_leaf. This is a very important parameter to prevent over-fitting in a leaf-wise tree. Its optimal value depends on the number of training samples and num_leaves. Setting it to a large value can avoid growing too deep a tree, but may cause under-fitting. In practice, setting it to hundreds or thousands is enough for a large dataset.

  3. max_depth. You also can use max_depth to limit the tree depth explicitly. 

リーフワイズ(ベストファースト)ツリーのパラメーターを調整する
LightGBMは葉ごとのツリー成長アルゴリズムを使用しますが、他の多くの一般的なツールは深さ方向のツリー成長を使用します。深さ方向の成長と比較して、葉方向のアルゴリズムははるかに速く収束できます。ただし、適切なパラメーターを使用しないと、葉ごとの成長が過剰適合する可能性があります。

リーフワイズツリーを使用して良好な結果を得るには、次のいくつかの重要なパラメーターがあります。

num_leaves:これは、ツリーモデルの複雑さを制御するための主要なパラメーターです。理論的には、num_leaves = 2 ^(max_depth)を設定して、深さ方向のツリーと同じ数の葉を取得できます。ただし、この単純な変換は実際には適切ではありません。その理由は、葉の数が決まっている場合、通常、葉の数のツリーは深さのツリーよりもはるかに深いためです。制約のない深さは、過剰適合を引き起こす可能性があります。したがって、num_leavesを調整しようとするときは、2 ^(max_depth)より小さくする必要があります。たとえば、max_depth = 7の場合、深さ方向のツリーは良好な精度を得ることができますが、num_leavesを127に設定すると過剰適合が発生する可能性があり、70または80に設定すると深さ方向よりも精度が高くなる可能性があります。

min_data_in_leafこれは、葉ごとのツリーでの過剰適合を防ぐための非常に重要なパラメーターです。その最適値は、トレーニングサンプルとnum_leavesの数によって異なります。大きな値に設定すると、ツリーが深くなりすぎるのを防ぐことができますが、フィットが不十分になる可能性があります。実際には、大規模なデータセットの場合は、数百または数千に設定するだけで十分です。

max_depth: max_depthを使用して、ツリーの深さを明示的に制限することもできます。                                                                 by google translation

この文章は、LGBMはパラメータを適切に設定しないで使うとover-fittingします、という忠告文としてとらえるのがよさそうである。

 

12月31日(木)

Riiid AIEd Challenge, 3,234 teams, 8 days to go 

min_data_in_leafとmax_depthは、over-fittingの抑制に効果的だということは実感できたが、commit中にエラーになるのでは使えない。

この2つが競合していると仮定して、片方だけ使うことにしてみる。min_data_in_leafの方が重要だとの記述から、最初に、max_depthを省いてみる。それでだめなら、逆にする、それでもだめなら、今回は両方とも使わないことにする。

max_depthを省くことで、commit中のエラーは表示されなくなった。

ただし、max_depthが、over-fittingの抑制にかなり寄与していたことがわかったので、min_data_in_leafをさらに調整する必要がある。 

 

 

f:id:AI_ML_DL:20201201122057p:plain

style=160 iteration=500

f:id:AI_ML_DL:20201201122209p:plain

style=160 iteration=50

f:id:AI_ML_DL:20201201122259p:plain

style=160 iteration=5

 

GitHub散歩(November 2020)

GitHub散歩(November 2020)

これまでは、コードを見るだけのGitHubだった。

もう少し活用したいと思っている。

 

11月21日(土)

GitHub Guidesのページの下端に次のように書かれている。

GitHub is the best way to build and ship software.
Powerful collaboration, code review, and code management for open source and private projects.

GitHubを初めて使ったのは、機械学習のテキストを学習する際、実際にプログラムコードを動かすため、GitHubに置かれているプログラムコードをダウンロードしたときである。機械学習のテキストを購入するたびにGitHubからプログラムをダウンロードした。

テキストの著者がGitHubでBuildしたソフトウエアを利用していたということだ。

GitHubをプログラムをダウンロードする場所としてしかみていなかったが、プログラムを作って公開して共同で編集する場所のようですね。

GitHub Guidesに入ると、そこには、GitHubを理解し、活用するために必要なさまざまな仕掛け、教育ツール、ドキュメントが存在している。さまざまなプログラム言語も学べるようになっている。

 

11月22日(日)

What is GitHub?

I'm glad you asked! Many people come to GitHub because they want to contribute to open source 📖 projects, or they're invited by teammates or classmates who use it for their projects. Why do people use GitHub for these projects?

open source

Open source software is software that can be freely used, modified, and shared (in both modified and unmodified form) by anyone. Today the concept of "open source" is often extended beyond software, to represent a philosophy of collaboration in which working materials are made available online for anyone to fork, modify, discuss, and contribute to.

forkは次のように定義されている。

fork

A fork is a personal copy of another user's repository that lives on your account. Forks allow you to freely make changes to a project without affecting the original upstream repository. You can also open a pull request in the upstream repository and keep your fork synced with the latest changes since both repositories are still connected.

forkは、forkしたコードの改善、改良のために行うものであり、成果があれば、元の所有者に、改善結果等を反映するかどうか打診する。ということかな。

 

GitHubの中に、Learnibg labというのがあり、いろいろ学べるようになっているのだが、Introduction to GitHubを最初にやりましょうと促されたので、やってみることにした。

Introduction to GitHubは、1から8までのコースステップからなっていて、このコースを完了すれば次のステップに進めるようになっているようだ。逆にいえば、このコースを完了しないと、GitHubを利用することはできないのではないかと推測される。

1から8までのステップの項目は、1. Assign yourself, 2. Turn on GitHub Pages, 3. Close an issue, 4. Create a branch, 5. Commit a file, 6. Open a pull request, 7. Respond to a review, 8. Merge your pull request, となっていて、GitHubでの操作手順の説明がなされているようである。

わからないことがあれば、こまごまとしたことまで、丁寧にリンクが張られていて、用語もきちんと説明されている。

今日の書き始めの箇所に、一部、コピペしているが、いくらやってもきりがないので、教育内容まで踏み込むのはやめておく。

 

上記の8つの項目についても、前に進むには、少なくとも、紫で示した単語についての、GitHub内での定義とその内容を理解しておかなければならないので、初心者がこの8つのステップをクリヤするのは、容易ではないと思う。

ということで、自分も、ちょっと見ただけでも、理解しなければならないことがたくさんあり、かつ、英語で直接コミュニケーションできるようにするために、苦手の英語を、できるだけそのまま理解しながら前に進もうとしているので、いつ、8つのステップをクリヤできるかわからない。

この8つのステップをクリヤ出来たら、そのことを書きたいと思う。

 

11月23日(月):

Introduction to GitHub

Step 1を学習中:Step 4まで通過したが、

Step 5: Commit a fileで止まっている。

 

 

 

f:id:AI_ML_DL:20201121115658p:plain

style=159 iteration=500

f:id:AI_ML_DL:20201121115805p:plain

style=159 iteration=50

f:id:AI_ML_DL:20201121115914p:plain

style=159 iteration=5

 

DNNで量子化学計算(November 2020)

DNNで量子化学計算(November 2020)

最近の進展についてまとめる機会があったので、より深く理解することと、実際の解析コードを使えるようになることを目標に、その経過をブログに記す。

 

11月10日(火)

FermiNet:

FermiNet is a neural network for learning the ground state wavefunctions of atoms and molecules using a variational Monte Carlo approach.

基底状態波動関数を学習するためのNNであるという記述が気になる。

troyerらの成果

Despite the simplicity of the restricted Boltzman machines, very accurate results for both ground-state and dynamical properties of prototypical spin models can be readily obtained.

図のタイトルを並べてみると、

Figure 1.  Artificial Neural Network encoding a many-body quantum state of N spins.

Figure 2.  Neural Network representation of the many-body ground states of prototypical spin models in one and two dimensions.

Figure 3.  Finding the many-body ground-state energy with neural-network quantum states.

Figure 4.  Describing the many-body unitary time evolution with neural-network quantum states.  Shown are results for the time evolution induced by a quantum quench in the microscopical parameters of the models we study (the transverse field h, for the TFI model and the coupling constant Jz in the AFH model). 

TFI : transverse-field Ising (model)

AFH : anti-ferromagnetic Heisenberg (model)

 

11月11日(水)

HermannらのPauliNetの成果

PauliNet outperforms comparable state-of-the-art VMC anzats for atoms, diatomic molecules and a strong-correlated hydrogen chain by a margin and is yet computational efficient.

成果は、正確さと効率化(行列の数)だけなのか。効率化によって、より大きな原子、分子について正確な計算結果を得ることができたということなのか。

Figure 1に、PauliNetによる効率化の程度がわかりやすく図示されている。

PfauらのFermiNetの成果

Using no data other than atomic positions and charges, we predict the dissociation curves of the nitrogen molecule and hydrogen chain, two challenging strongly correlated systems, to significantly higher accuracy than the coupled cluster method, widely considered the most accurate scalable method for quantum chemistry at equilibrium geometry.

coupled cluster method:結合クラスター法

 結合クラスター法(けつごうクラスターほう、クラスター展開法CC法:Coupled Cluster)は多体系を記述するために使われる数値手法である。最もよく使われるのは、量子化学計算化学)におけるポスト-ハートリー-フォック第一原理計算がある。CC法は、ハートリーフォック分子軌道法を基本にして、電子相関を考慮する指数関数クラスタ演算子を使って多電子波動関数を構成する。CC法を用いて、小さい分子や中程度の大きさの分子について最も正確な計算を行うことができる[1][2][3]。from ウイキペディア

Table 1.  Ground state energy, ionization potential, and electron affinity for first-row atoms.

Table 2.  Ground-state energy at equilibrium geometry for diatomic and small molecules.

いずれの表も、FermiNetがCCSD(T)に優っていることを示している。イオン化ポテンシャルと電子親和力は、FermiNetの結果しかないのは、CCSD(T)では基底状態のエネルギーしか計算できないということだろうか。

C.  The H4 rectangleの最初に次のように記述されている。

While CCSD(T) is exceptionally accurate for equilibrium geometries, it often fails for molecules with low-lying exited states or stretched, twisted or otherwise out-of-equiliblrium geometries.

昨日学会に送ったA4半ページの紹介記事で、FermiNetやPauliNetは励起状態のエネルギーも正確に計算できると書いたのだが、励起状態あるいは非平衡状態のエネルギーの計算に関しては、論文の斜め読みでそう書いただけだったので、気になっていたのだが、少なくとも、FermiNetに関しては問題ないようだ。図4から図6には、非平衡状態の計算においてもFermiNetはFCIなどの厳密な計算手法や正確な実験データに匹敵する正確さをもつことが示されている。

PauliNetについても、原子間距離に対するエネルギーの変化をHaetree-Fockなどの量子化学計算結果と比較していて、PauliNetのほうが、exactなデータに近いことが示されているので問題なさそうである。

 

11月12日(木)

PauliNetのGitHubを見てみよう。

deepqmc:Deep learning quantum Monte Carlo for electrons in real space

deepqmc.github.io:DeepQMC documentation

プログラムコードとは別にドキュメンテーション(ユーザーガイドを含む)も用意されていて、勉強しやすそうだ。

 

11月14日(土)

FermiNetのGitHubを見てみよう。

REDME.mdの最後に、This is not an official Google product.と書かれていて不安になるが、アルファ碁を開発し、その後はバイオやフィジックスなどの自然科学の領域でも影響力を増しているDeepMindが運営している89のrepositoriesのうちの1つである。

 

PauliNetの開発者Jan Hermann氏は、量子物理の専門家であり、計算物理の専門家でもある。Hermann氏のGitHubには45のrepositoriesがあり、量子物理計算関連の内容がメインで、pySCFSchNet(K.T. Schütt. P.-J. Kindermans, H. E. Sauceda, S. Chmiela, A. Tkatchenko, K.-R. Müller. SchNet: A continuous-filter convolutional neural network for modeling quantum interactions. Advances in Neural Information Processing Systems 30, pp. 992-1002 (2017))なども含まれている。

 

FermiNetとPauliNetのどちらから始めようか考えているのだが、Hermann氏のサイトは、SCF計算やSchuNetなど量子物理の匂いが強く、DeepMind社のサイトはディープラーニングの匂いが強い。個人と団体の違いもある。入り口で立ち往生しても始まらないし、チェックしたいGitHubサイトは無限にあるので、GitHub散歩、みたいな感じで進めていこうと思う。

 

11月15日(日)

Hermann氏のサイトをながめてみよう。

Software projects

Most of my programming is related to my research in computational materials science. I believe that strong computational science benefits from strong software engineering, and that all scientific academic software should be open source.

I am involved in the following software projects.

Creator

Beta projects

These are experimental packages that, although fully functional, I don’t yet consider finished.

  • KnitJalternative front-end to Jupyter kernels aiming at editor freedom and easy versioning
  • Mona—framework for reproducible and distributed, potentially long-running calculations

Contributor

  • FHI-aims—massively parallel electronic structure code package with DFT at its core

 

<雑談>

ずっと会社に勤めていて、結局、独立することなく終わったのだが、50歳くらいで研究に没頭できる環境が欲しいと思って、理論計算の受託で稼ぎながら、研究できないかと検討したことがある。 理論屋でも物理屋でもないのだが、量子化学化学結合論などに興味があって、様々な分子軌道計算の論文をながめていたことがあったので、Gaussianのようなソフトを購入して、自分で使いながら、使いたい人に使い方や理論を教えたり、計算代行したりということを考えていた。このとき、ネックになったのが、ソフトの購入代金(使用料)と計算環境であった。会社の中で提案できるヒトではなかったので、夢想に終わった。ネットにアクセスできるパソコンがあれば、幸いにも、無料で、Gaussian(詳細は知らない)のような計算ができるようになっているので、夢の大半は実現することができる。ということを、pySCFについて調べながら、ぼんやり振り返っている。

 

DNN+量子化学計算+紹介記事 ⇒ FermiNet & PauliNet

ということになったのだが、現実問題として、FermiNetやPauliNetにアクセスしてすぐに計算を始められるヒトは理論も計算もすでにプロの領域にいる研究者に限られるだろう。φ、ψ、HF、CBS、FN-DMC、QMC、VMC、Jastrow、FCI、fixed-node correlation energy、・・・、専門用語や略語の意味も分からず、DNNが最先端の量子化学計算の分野に応用されているというだけで食いついても、この技術を適用する課題をもっていないことには始まらない、いや、終わらない。

 

PySCFについて調べてみた。

Recent developments in the PySCF program package
Qiming Sun et al., arXiv:2002.12531v2 [physics.chem-ph] 11 Jul 2020

abstract

PYSCF is a Python-based general-purpose electronic structure platform that both supports first-principles simulations of molecules and solids, as well as accelerates the development of new methodology and complex computational workflows.

The present paper explains the design and philosophy behind PYSCF that enables it to meet these twin objectives.

With several case studies, we show how users can easily implement their own methods using PYSCF as a development environment.

We then summarize the capabilities of PYSCF for molecular and solid-state simulations.

Finally, we describe the growing ecosystem of projects that use PYSCF across the domains of quantum chemistry, materials science, machine learning and quantum information science.

machine learningに関係する記述を次に示す。

A. PySCF in the materials genome initiative and machine learning

As discussed in section I, one of our objectives when developing PYSCF was to create a tool which could be used by non-specialist researchers in other fields.

With the integration of machine learning techniques into molecular and materials
simulations, we find that PYSCF is being used in many applications in conjunction with machine learning.

For example, the flexibility of the PYSCF DFT module has allowed it to be used to test exchange-correlation functionals generated by machine-learning protocols in several projects, and has been integrated into other machine learning workflows.

PYSCF can be used as a large-scale computational engine for quantum chemistry data generation.

Also, in the context of machine learning of wavefunctions, PYSCF has been used as
the starting point to develop neural network based approaches for SCF initial guesses, for the learning of HF orbitals by the DeepMind team, and for Hamiltonian integrals used by fermionic neural nets in NETKET.

最後のNETKETってなんだろう。

著者19名の論文が出ている。

トップオーサーのCarleo氏は最初に多体問題にNNを適用した2017年の論文の著者。

NetKetを共通基盤にして、さらなる発展を目指すということかな。

NetKet: A machine learning toolkit for many-body quantum systems
Giuseppe Carleo, Kenny Choo et al., SoftwareX 10 (2019) 100311

abstract

We introduce NetKet, a comprehensive open source framework for the study of many-body quantum systems using machine learning techniques.

The framework is built around a general and flexible implementation of neural-network quantum states, which are used as a variational ansatz for quantum wavefunctions.

NetKet provides algorithms for several key tasks in quantum many-body physics and
quantum technology, namely quantum state tomography, supervised learning from wavefunction data, and ground state searches for a wide range of customizable lattice models.

Our aim is to provide a common platform for open research and to stimulate the collaborative development of computational methods at the interface of machine learning and many-body physics.

NetKetのホームページがある。

What is NetKet?

NetKet is an open-source project delivering cutting-edge methods for the study of many-body quantum systems with artificial neural networks and machine learning techniques.

GitHubに公開されているが、NetKetで検索しても出てこないので、使いにくそうだ。ElsevierのSoftwareXというシステムの中に埋もれてしまっているようである。

NetKetのホームページはチュートリアルもあって、コードの説明も詳しく、自習に適しているように思う。

Carleo氏オリジナルのNQS(Neural-network Quantum States)がGitHubに掲載されているが、更新している形跡がない理由がこれでわかったような気がする。

 

<雑談>

頭が使える間に、何かできないかなと思うのだが、何もできていない。小柴先生が亡くなられたが、ニュートリノの検出に成功されてノーベル賞を受賞され、お弟子さんの梶田先生もニュートリノに質量があることを明らかにしてノーベル賞を受賞された。こんな実験は誰にでもできるものではないが、湯川先生の中間子理論なら誰にでも発見のチャンスはあった。最先端の分野の論文を読んでディスカッションを重ね仮説を積み上げ理論を組み立て・・・。

 

11月16日(月)

G. Carleo氏らの総説(著者8名)、Machine learning and the physical science、arXiv:1903.10563v2 [physics.comp-ph] 6 Dec 2019を読んでみた。 

機械学習がこれだけ浸透していたのかと驚かされる内容だ。

と、書いてみたが、斜め読み(英文の斜め読みだから内容までは頭に入っていない)しただけで、これからじっくり解読していこうと思う。

著者と所属(専門領域が想像できる機関名)をいくつか示す。

Giuseppe Carleo
Center for Computational Quantum Physics,

Ignacio Cirac
Max-Planck-Institut fur Quantenoptik,

Kyle Cranmer
Center for Cosmology and Particle Physics,
Center of Data Science,

Maria Schuld
National Institute for Theoretical Physics,

Leslie Vogt-Maranto
Department of Chemistry

Lenka Zdeborová
Institut de physique théorique

 

11月17日(火)

FermiNetとPauliNetのどちらに食らいつこうか考えていて、チュートリアルも含め、コードの解説がしっかり書かれているように感じたHermann先生のPauliNetでほぼ決まりのつもりだった。

ところが、Neural-network quantum states (NQS) の創始者のCarleo先生は、FermiNetとPauliNetの論文を引用したうえで、NQSをさらに発展させた論文を書いておられる。

さらに、共著で機械学習の物理学への展開と相互作用に関する総説を書かれている。

加えて、NetKetと称する多体量子系に適用する機械学習toolkitを開発されている。

以上のことを勘案して、NetKetで本格的な学習を始めることにしたいと思う。

 

ということで、早速、NetKetのホームページへ、行く。

まずは、Get Started、をクリック。

下の方に、青地に白抜きで、こんな表示がある。

Remarks

We are not yet supporting Conda installs
Windows Os is not supported

想定されているのは、MacUbuntuである。

Windowsユーザーは、これにて終了!

ということにならないために、

Windowsパソコンで、Ubuntuを使えるようにする、ということになる。

今使っているパソコンに何かあると困るので、他のWindowsパソコンで確認してみようと思う。

昨年、使わなくなったWindows Vistaパソコンに、Ubuntuをインストールしており、すぐにでも使える状態にある。GPUはなく、RAMは4GB、HDは100GBで、とりあえず動くのであるが、勝手がわからないというか、まったく手も足も出ず、放置している。

Windowsの方々は、私のように、ここで止まってしまう可能性が高いので、Ubuntuを使えるようになることを、当面の目標としよう。

 

Ubuntuの立ち上げ:

WindowsUbuntuをパソコンの起動時に切り替えられるようにしている。

Ubuntuを使いたいと思ったのは、Anacondaに後から追加できるpythonパッケージやモジュールに制限があることで、AnacondaはTF2.0に対しても対応が非常に遅かった。無理に入れようとして、Anaconda3を壊してしまったこともある。

Ubuntuのインストールは、簡単なマニュアルを見ればできる。問題は、UbuntuでAnaconda3を使おうとしたときにおきた。WindowsにAnaconda3をインストールするのは容易で、Windows10だと、すぐに使えるようになったので、その感覚でUbuntuにもAnaconda3を簡単にインストールできると思ったのが間違いだった。

Anacondaのドキュメントには、Installing on Linuxという項目があって、インストール手順を説明しているのだが、Ubuntuという単語が見当たらない。

 

ウイキペディアによると、

Ubuntu(ウブントゥ[6][ʊˈbʊnt] ( 音声ファイル); oo-BOON-too[7])はDebian GNU/Linuxを母体としたオペレーティングシステム(OS)である。Linuxディストリビューションの1つであり、フリーソフトウェアとして提供されている。概念はディストリビューションも参照。カノニカルから支援を受けて開発されている。開発目標は「誰にでも使いやすい最新かつ安定したOS」を提供することである。

Linuxリナックス、他の読みは後述)とは、狭義にはUnix系オペレーティングシステムカーネルであるLinuxカーネルを指し、広義にはそれをカーネルとして周辺を整備したシステム全体のことをいう(GNU/Linuxシステムも参照)。

Linuxは、狭義にはLinuxカーネル、広義にはそれをカーネルとして用いたオペレーティングシステムを指す。LinuxUnix系Unix likeUnixライク)オペレーティングシステム (OS) の1つとされる。カタカナでは「リナックス」と表記されることが多い(「Linux」の読み方を参照)。Linuxは、スーパーコンピュータメインフレームサーバパーソナルコンピュータ組み込みシステム(携帯電話やテレビなど)など、幅広い種類のハードウェアで使用されている。

デスクトップやサーバ用のLinuxは、Linuxディストリビューションという形でパッケージ化されて配布されている。有名なLinuxディストリビューションとしては、Debian(とその派生であるUbuntuLinux Mint)、Red Hat Linux(とその派生であるFedoraRed Hat Enterprise LinuxCentOS)、Mandriva Linux/MageiaopenSUSEArch Linuxなどがある。各Linuxディストリビューションは、Linuxカーネルシステムソフトウェアライブラリ等、巨大なコンパイル済のアプリケーション群を含んでいる。

 

<雑談>

Ubuntuはメジャーではなさそうだが、Kerasを開発したF. Cholleさんが、著書Deep Learning with PythonのAppendixAに、Installing Keras and its dependences on Ubuntuという記事を書かれていたことと、12年ほど前にイオン散乱シミュレーションのソフトを使おうとしたときに、教授から渡されたソフトがUbuntu上で動いていて、Ubuntuの入門書を渡されたということがあって、自分の中ではメジャーであった。しかし、今から思えば残念なのだが、ほどなくして、Windows上で動作する高性能のシミュレーションソフトを使うことになって、Ubuntuという奇妙な単語だけが頭に残った。さらに、F. Cholle氏のテキストをバイブルとしてディープラーニングを学ぶときにはAppendixAの記事を読む前にGPUを搭載したWindowsマシンを購入してAnaconda3上でKeras/TensouFlowを使うようになっていたので、後に、Ubuntuを使ってみたいと思ったときには、時すでに遅し、大きな壁が立ちはだかっていたのである。

 

今、そのAppendixAを眺めているのだが、sudo apt-get update, sudo pip3 install tensorflow-gpu, sudo python setup.py installなどの単語が並んでいる。

こういうものだということがわかったのだから、コマンドプロンプトに慣れて、Ubuntuを自分のものにしていこう。ほんとうに必要性を感じた時に使ってみよう。難しいのではなく、不慣れなだけである、ということにして、Ubuntuは、とりあえずこのへんでおいておく。

 

11月18日(水)

NetKetのホームページを丁寧に辿っていけば目的とする量子化学計算に辿りつけそうであることはわかってきた。

NetKetの論文のabstractをもう1度見てみよう。

abstract

We introduce NetKet, a comprehensive open source framework for the study of many-body quantum systems using machine learning techniques.

The framework is built around a general and flexible implementation of neural-network quantum states, which are used as a variational ansatz for quantum wavefunctions.

NetKet provides algorithms for several key tasks in quantum many-body physics and
quantum technology, namely quantum state tomography, supervised learning from wavefunction data, and ground state searches for a wide range of customizable lattice models.

Our aim is to provide a common platform for open research and to stimulate the collaborative development of computational methods at the interface of machine learning and many-body physics.

 

NetKitの論文を最後まで読んでみた感想:

neural-network quantum states (NQS)とrestricted Boltzman machine (RBM)が根底にあり、C++でプログラムを強化しているようである。使いやすさを強調しており、例題をみると、プログラムコードは非常に単純化されていて、確かに、すぐに使えそうな感じである。機械学習量子化学計算の橋渡しをするプログラム開発の拠点を目指しているようである。

PauliNet:Hermann先生のこてこての量子物理、FermiNet:DeepMindチームのディープラーニング等と比べると、NetKitに対しては、量子物理の観点からも、機械学習の観点からも、前2者と比べると、もの足りなさを感じる。

ということで、NetKitは、このあたりで、ひとまずおいておく。

 

さて、つぎ、どうしようか。

 

多体電子系の量子化学計算ができるようになりたいと思って、このテーマでブログを書いているのだが、「DNNで量子化学計算」というタイトルから多くの方が思い浮かべるのは、おそらく、教師あり学習で、分子構造と基底状態のエネルギー(DFT、CCSD(T)等による計算結果)を教師データにして、DNNにその関係性を学ばせることによって、任意の分子構造に対して基底状態のエネルギー値を予測することができる、ということではないだろうか。

ここで紹介している3種類のNNは、波動関数をなんらかの方法でNNに記述し、その波動関数に物理的意味を与える(最適化する)ために、そのNNを、VMC(variational Monte Carlo)等を用いて学習させる。そうすると、学習したNNは、基底状態だけでなく、非平衡状態や励起状態の分子のエネルギーをも計算することができる、というものだと理解している。

この説明は正確ではないかもしれないので、正しい知識を得るために、D. PfauらのFermiNetの論文を熟読したいと思う。

Ⅰ.  Introduction

ここでは、DNNを量子化学計算に用いる、これまでの方法が紹介されている。そのうちの1つの論文(引用文献6)を眺めてみよう。

Physical machine learning outperforms “human learning” in Quantum Chemistry
A. V. Sinitskiy and V. S. Pande, Department of Bioengineering, Stanford University, Stanford CA 94305, arXiv:1908.00971 (2019).

abstract

Two types of approaches to modeling molecular systems have demonstrated high practical efficiency. Density functional theory (DFT), the most widely used quantum chemical method, is a physical approach predicting energies and electron densities of molecules.

Recently, numerous papers on machine learning (ML) of molecular properties have also been published. ML models greatly outperform DFT in terms of computational costs, and may even reach comparable accuracy, but they are missing physicality — a direct link to Quantum Physics — which limits their applicability.

Here, we propose an approach that combines the strong sides of DFT and ML, namely, physicality and low computational cost. By generalizing the famous Hohenberg-Kohn theorems, we derive general equations for exact electron densities and energies that can naturally guide applications of ML in Quantum Chemistry. Based on these equations, we build a deep neural network that can compute electron densities and energies of a wide range of organic molecules not only much faster, but also closer to exact physical values than current versions of DFT. In particular, we reached a mean absolute error in energies of molecules with up to eight non-hydrogen atoms as low as 0.9 kcal/mol relative to CCSD(T) values, noticeably lower than those of DFT (down to ~3 kcal/mol on the same set of molecules) and ML (down to ~1.5 kcal/mol) methods. A simultaneous improvement in the accuracy of predictions of electron densities and energies suggests that the proposed approach describes the physics of molecules better than DFT functionals developed by “human learning” earlier. Thus, physics-based ML offers exciting opportunities for modeling, with high-theory-level quantum chemical accuracy, of much larger molecular systems than currently possible.

赤色に変えた文章が、これまで最も多く用いられてきた手法である。同じことが本文中ではもう少し詳しく記述されている。

Recently, many authors used machine learning (ML) for much faster computations of E and some other molecular properties (polarizabilities, HOMO-LUMO gaps, etc.).

However, neither currently used descriptors of molecules, nor ML models have a transparent connection to the basic physical concepts derived from the Schrödinger equation.

For example, the vast majority of ML models cannot be extended to compounds with new elements without retraining, making them methodologically inferior even to least accurate DFT functionals, let alone the absolutely transferable Schrödinger equation.

As a result, such approaches might be devoid of physics, and the criticism of ML as “black boxes” and “curve-fitting” seems totally applicable to them.

物理の教授に機械学習ディープラーニングの話をすると、ああ、あれね、ブラックボックス化されていて、何やってるかわからないよね、物理じゃなくて、単なるカーブフィッティングでしょ、などどいわれる。

A. V. Sinitskiyらは、上記abstractの紫色で示したように、ネットワークの中に物理(DFT)を持ち込み、持ち込んだ関数をDNNで最適化することによってDFTよりも高性能なCCSD(T)を超える正確さでEやρを高速に計算することができるとのことである。FermiNetやPauliNetは基底状態だけでなく非平衡状態(例えば結合距離を変化させたとき)や励起状態のエネルギーを計算できる。これに対して、A. V. Sinitskiyらがこの論文で示しているのは基底状態のみであるが、本文の最後に次の記述がある。

We foresee wide-scale applications of the approach proposed here (after certain technical developments) to computer modeling of various large molecular systems, including biomolecular or artificial material systems of much practical interest, and highly accurate and fast modeling of excited states of molecules and chemical reactions involving bond breaking and formation.

Fig.1 に、用いたDNNモデルの模式図が示されている。

f:id:AI_ML_DL:20201118224659p:plain

Pfauらの論文は20ページもあって読むのも理解するのもたいへんなのだが、参考のためにと思って引用しているこのSinitskiyらの論文は、62ページ(本文7ページ)もある。

 

準備が整ってきたようなので、FermiNetにフォーカスしようかと思ったのだが、根底にある量子物理、シュレーディンガー波動方程式波動関数、密度汎関数、多体電子系、スピン、強相関、・・・、これらに対する強い興味と理解がないと、何をやっているのかわからない。

ここで偶然出会ったA. V. Sinitskiy and V. S. Pandeの論文は、分子を扱っていて、他の論文をみると、生体分子とタンパク質 との相互作用を計算機シミュレーションで調べているようだ。さらに、上記論文の1つ前の論文もある。Deep Neural Network Computes Electron Densities and Energies of a Large Set of Organic Molecules Faster than Density Functional Theory (DFT), Anton V. Sinitskiy, Vijay S. Pande

ということだが、A. V. Sinitskiyらの研究は、別にフォローすることにして、ここでは、FermiNetを、とことん理解することにしよう。

 

11月19日(木)

FermiNetの全体像

f:id:AI_ML_DL:20201119190813p:plain

文字が小さくて見えないので拡大してみよう。

f:id:AI_ML_DL:20201119185931p:plain

 

f:id:AI_ML_DL:20201119191234p:plain

f:id:AI_ML_DL:20201119191524p:plain

f:id:AI_ML_DL:20201119191732p:plain

f:id:AI_ML_DL:20201119191915p:plain

f:id:AI_ML_DL:20201119192002p:plain

f:id:AI_ML_DL:20201119192210p:plain

f:id:AI_ML_DL:20201119192304p:plain

f:id:AI_ML_DL:20201119192822p:plain

入力するのは原子核と電子の座標だけで、ネットワークの形状と四則演算、行列演算との組み合わせによって、波動関数が表現されます、ということのようなのだが、確かに、アルゴリズムの最上段と最下段を見るとそうなっている。

ついでに、変数間の関係式も張り付けておこう。

 

f:id:AI_ML_DL:20201119213948p:plain

f:id:AI_ML_DL:20201119214044p:plain

f:id:AI_ML_DL:20201119214118p:plain

f:id:AI_ML_DL:20201119214152p:plain

f:id:AI_ML_DL:20201119214243p:plain

PauliNetのHermann先生は、論文Deep neural network solution of the electronic Schrodinge equationの中で、次のように書いている。

The parallel work of Pfau et al. (2019) follows the same basic idea as ours, but differs in several significant aspects.

Their architecture does not encode any physical knowledge about wave functions besides the essential antisymmetry, which is compensated by a much larger number of optimized parameters.

Perhaps as a result of that, their ansatz achieves somewhat higher accuracy at the cost of being about two orders of magnitude more computationally expensive than ours.

この文章から、FermiNetは、反対称性以外に波動関数に関する物理学的知識を含んでいないと思い込み、自分の紹介記事にもそう書いたのだが、これは正しい認識だろうか。

次にPauliNetの模式図を示す。

Hartree Fock, Jastrow, Backflow, Electronic cusps, Equivariant Interaction Blockが、fixed functionもしくはtrainable functionとして組み込まれている。

Fermi netには、それらのphysical knowledgeを表現することができる変数は用意されているが、physical knowledgeが含まれているとは言えない、という理解でよいのだろうか。

 

f:id:AI_ML_DL:20201119224317p:plain

 

11月20日(金)

B. Wave-function optimization

これが、FermiNetにphysical knowledgeを教え、学ばせる作業、ということかな。

波動関数のエネルギー期待値を最小化する、ということのようだが、Kronecker-factored approximate curvature (KFAC)、Fisher Information Matrix (FIM)など、ついていけなくなる。

大沢 和樹 氏の記事を一部転載させていただく。

Kronecker-factored Approximate Curvature (K-FAC) は(当時)University of Toronto の Ph.D. 学生であった James Martens らによって、2015年のICMLで提案された深層ニューラルネットワークのための最適化手法である。大規模な深層学習において応用が限られていた二次最適化手法のボトルネックである曲率 (Curvature) 計算の効率的な実現手法である。

自然勾配学習法(Natural Gradient Learning)は1998年にShun-ichi Amariによって提案された情報幾何に基づくニューラルネットワークの最適化手法である。自然勾配学習ではFisher情報行列を曲率として用いることで目的関数の地形を正確に捉え、「反復数」において学習の高速な収束を実現する。このため、自然勾配学習法は二次最適化の効率的な実現法としても知られる。

Natural Gradient Works Efficiently in Learning
Shun-ichi Amari
RIKEN Frontier Research Program, Saitama 351-01, Japan

This article introduces the Riemannian structures to the parameter spaces of multilayer perceptrons, blind source separation, and blind source deconvolution by means of information geometry. The natural gradient learningmethod is then introduced and is shown to be statistically efficient. This implies that optimal online learning is as efficient as optimal batch learning when the Fisher information matrix exists. It is also suggested that natural gradient learning might be easier to get out of plateaus than conventional
stochastic gradient learning.

KFACの論文:

Optimizing Neural Networks with Kronecker-factored Approximate Curvature
James Martens∗ and oger Grosse†
Department of Computer Science, University of Toronto

Abstract
We propose an efficient method for approximating natural gradient descent in neural networks which we call Kronecker-factored Approximate Curvature (K-FAC). K-FAC is based on an efficiently invertible approximation of a neural network’s Fisher information matrix which is neither diagonal nor low-rank, and in some cases is completely non-sparse. It is derived by approximating various large blocks of the Fisher (corresponding to entire layers) as being the Kronecker product of two much smaller matrices. While only several times more expensive to compute than the plain stochastic gradient, the updates produced by K-FAC make much more progress optimizing the objective, which results in an algorithm that can be much faster than stochastic gradient descent with momentum in practice. And unlike some previously proposed approximate natural-gradient/Newton methods which use high-quality non-diagonal curvature matrices (such as Hessian-free optimization), K-FAC works very well in highly stochastic optimization regimes. This is because the cost of storing and inverting K-FAC’s approximation to the curvature matrix does not depend on the amount of data used to estimate it, which is a feature typically associated only with diagonal or low-rank approximations to the curvature matrix.

optimizationの奥の深さを少し感じることができたような気がする。Optimizationの方法を理解するだけならもうすこし簡単だと思うのだが、ハミルトニアン波動関数の式を目の前にしてoptimizationのアルゴリズムを理解することは、たいへん難しく感じる。

Ⅲ. RESULTS

ここから先は、他の手法と比較して、FermiNetの方がより正確に計算結果を出すことができるかということを示している。ちょっととばして先に進んでみよう。

 

 

APPENDIX A: EXPERIMENTAL SETUP

1. FermiNet architekuture and training

FermiNetは4層+最終層

各層は、one-electron streamに対して256のhidden units、two-electron streamに対して32のhidden units

最終層はlinear、Laplacianが良く定義されて、全領域で正になるように、4層全てにtanh nonlinialityを用いている。

特に指定がなければ、16の行列を用いている。

表1に示したSethらの通常のVMC (Variational Monte Carlo)の結果は、50のconfiguration state function (CSF)を用いている。

CSFの行列の数は系に依存し、その数は数百から数千である。

対応するFermiNetのパラメータ数は、約700,000であり、正確な数は原子数や分子構造によって異なってくる。

*以上がFermiNetの構造に関する本文より具体的な説明である。これでも、Fig.1の概略図との対応はわかりにくいが、なんとなくわかったような気にもなる。

 

optimizationとしてlocal energyを適用する前に、pySCFを用いて計算したHartree-Fock (HF)軌道に合致するように事前トレーニングを行っている。

この事前トレーニングは、optimizationに対して非常に効果的であるとのこと。

事前学習のlossの式が示されており、Hartree-Fock計算に用いるminimal basisはSTO-3Gであるとのこと。

少しとばす。

 

FermiNetはTensorFlowで書かれている。

20電子系に対しては、8台のV100 GPUを並列作動させている。より大きな系では16 GPUも用いられている。

etheneの計算には、8GPUで2日間を要するとのこと。

30電子のBicyclobutaneは、16GPUで1か月を要するとのこと。

デフォルトのパラメータが表4に示されている。ただし、Bicyclobutaneの場合には、batch sizaは半分にし、事前トレーニングの試行回数は桁で増やしているとのこと。

 

このブログの目的は、多電子系の電子状態の計算をANNを使ったプログラムで実行するところまでの道筋を記録することだった。しかし、ここまで見てきてわかったように、FermiNetは、計算コストが高すぎるように思う。

FermiNetの論文解読はこのへんで中断して、プログラムの中身をのぞいてみようか。

 

早速、GitHubにあるdeepmind/ferminetに行ってみましょう。

github.com

ここへは何回か来ているが、プログラムをちょっと覗いてみただけで、何もしていない。したがって、どうなるかまったくわからない。

FermiNet: Fermionic Neural Networks

An implementation of the algorithm and experiments defined in "Ab-Initio Solution of the Many-Electron Schroedinger Equation with Deep Neural Networks", David Pfau, James S. Spencer, Alex G de G Matthews and W.M.C. Foulkes, Phys. Rev. Research 2, 033429 (2020). FermiNet is a neural network for learning the ground state wavefunctions of atoms and molecules using a variational Monte Carlo approach.

Installation

pip install -e . will install all required dependencies. This is best done inside a virtual environment.

virtualenv -m python3.7 ~/venv/ferminet
source ~/venv/ferminet/bin/activate
pip install -e .

11月21日(土)

ここで壁にぶち当たりました。

GitHubのコードの利用の仕方を学ぶ必要があります。 

 

11月22日(日)

Introduvtion to GitHubを学習中

 

 

f:id:AI_ML_DL:20201110151235p:plain

style=158 iteration=500

 

f:id:AI_ML_DL:20201118002548p:plain

style=158 iteration=50

f:id:AI_ML_DL:20201118002845p:plain

style=158 iteration=5

 

Kggle散歩(November 2020)

Kggle散歩(November 2020)

 

11月は、25日にLyftが、30日にMoAが終了する。

Lyftは、計算資源の確保が課題であり、MoAは、Public LBとCVを天秤にかけながら、性能を上げる方法を探ることが課題である。

 

11月1日(日)

Generative Deep Learning by David Foster : CHAPTER 1 : Generative Modeling

discriminativeとgenerative:discriminativeは、training datasetに含まれる特徴を把握して、test dataが何であるかを予測する。generativeは、training datasetに含まれない、新たなデータを作(創)り出す。

generative modelの定義:

A generative model describes how a dataset is generated, in terms of a probabilistic model. By sampling from this model, we able to able to generate new data.

ここに馬の画像データがある。新たに用意した画像が馬かどうかを判別することが、discriminative(識別)であり、馬の画像データに含まれていない馬の画像をつくるのが、generativeである。馬の画像をつくるためには、作られた画像が「馬」でなければならないので、馬であることを、馬の画像から学ぶのである。

元の画像に含まれず、かつ、元の画像に含まれていたがごとく、「リアル」であることが、generative modelの性能を測るものさしになる。

The Rise of Generative Modeling:

2018年に、NVIDIAからStyleGAN(非常にリアルな顔画像を生成)が発表され、

2019年に、OpenAIからGPT-2(導入文から完全なテキストを生成)が発表された。

6ページから7ページにかけて、著者のgenerative modelingに対する考え方が、簡潔に表現されていて、その内容が非常に興味深い。

As well as the practical uses of generative modeling (many of which are yet to be discovered) , there are three deeper reasons why generative modeling can be considered the key to unlocking a far more sophisticated form of artificial intelligence, that goes beyond what discriminative modeling alone can achieve.

このあと、約40行にわたってそのthree deeper reasonsが説明されている。

うまく要約できないし、全文掲載するのもはばかられるので、3つのパラグラフのはじめの方の文章を転記しておく。

First, purely from a theoretical point of view, we should not be content with only being able to excel at categorizing data but should also seek a more complete understanding of of how the data was generated in the first place.

Second, it is highly likely that generative modeling will be central to driving future developments in other fields of machine learning, such as reinforcement learning (the study of teaching agents to optimize a goal in an envilonment through trial and error).

Finally, if we are to truly say that we have built a machine that has acquired a form of intelligence that is comparable to a human's, generative modeling must surely be part of the solution. One of the finest example of a generative model in the natural world is the person reading this book. Take a moment to consider what an incredible generative model you are.

 

11月2日(月)

MoA:

先週、GPUを使わないで、CPUだけでパラメータ調整を行った。CPUだけだと、少ししか走らせることができないので、最も早く結果が分かる、最初のFoldのVal_lossを使うことにした。

モデルの性能を上げるために、チューニングを行った結果、最初のFoldのval_lossの値を、公開コードの初期条件で計算した場合よりも小さくすることができた。

良い結果が得られるだろうと思って、GPUが使えるようになった土曜日に、全体の計算をして、commit, submitしたところ、CVもpublic LBも公開コードより悪くなった。

期待外れの結果になったのは、最初のFOLDにoverfittしたのが、その原因だろうな。

Public_dataにoverfittして、private_dataのスコアが悪くなるのと同じようなことだな。

DNNではないので、計算時間が短く、チューニングの作業は比較的簡単に行えるのだが、見えないprivate_dataに適合するモデルに仕上げるチューニングは、難しい。

 

11月3日(火)

MoA: 

今日は、モデルの不具合に気づいたおかげで、CVが少し改善した。(epochsを50にしてearly stop=Trueにすると、なぜか収束が悪くなる。どうしてそうなるのかわからないので、とりあえず、early stoppingを使わないようにした。)

SEEDを変えたモデルのアンサンブルの効果を調べてみた。その効果は意外に大きかったので、それならばと、本命のモデルに適用してみたところ、効果は実験に使ったモデルの場合の1/3程度しかなく、少しがっかりした。原因は、おそらく、実験に使ったモデルの方が、FOLD間でのval_lossのばらつきが大きかったので、SEED間でのばらつきも実験に使ったモデルの方が大きかったため、アンサンブルの効果も大きかったのではないかと考えている。

3000人以上が参加していて、同一スコアにたくさん並んでいる。

上位のスコアの公開コードを見ると、public LBはCVとは連動しているようには見えず、public_dataにoverfittingしているのではないかと思う。CVもpublic LBも良好なコードも公開されているので、それらに勝るモデルにするには、CVだけでなく、public LBもある程度の値になっていないとダメだろうけど、それがどのあたりなのかは、わからない。

 

11月4日(水)

MoA:

NNの特徴は、深さだと思うのだが、どうなんだろう。

非線形活性化関数を通過する毎に非線形性が増して、より複雑な関係性を繋ぐことができるのではないだろうか。

浅いNNは従来の機械学習に劣り、深くすることによって、従来の機械学習を凌ぐことができるのではないだろうか。

DNNの世界から表データが取り残されているように思っていたら、TabNetというのが考案されたようだ。

TabNet: Attentive Interpretable Tabular Learning
Sercan O. Arık and Tomas Pfister, arXiv:1908.07442v4 [cs.LG] 14 Feb 2020

ABSTRACT
We propose a novel high-performance and interpretable canonical deep tabular data learning architecture, TabNet.

TabNet uses sequential attention to choose which features to reason from at each
decision step, enabling interpretability and more effcient learning as the learning capacity is used for the most salient features.

We demonstrate that TabNet outperforms other neural network and decision tree variants on a wide range of non-performance-saturated tabular datasets and yields interpretable feature attributions plus insights into the global model behavior.

Finally, for the first time to our knowledge, we demonstrate self-supervised learning for tabular data, significantly improving performance with unsupervised representation learning when unlabeled data is abundant.

 

11月5日(木)

Study:

量子多体問題を解く鍵である多体量子状態を完全に(近似ではなく)表現する波動関数ニューラルネットワークで表現する方法が注目されている。それを初めて具体化したのが次の研究のようである。

Solving the Quantum Many-Body Problem with Artificial Neural Networks

G. Carleo and Matthias Troyer, arXiv: 1606.02318v1 [cond-mat.dis-nn] 7 Jun 2016

この研究に至る前夜の状況が次の総説にまとめられているようである。

THE NONEQUILIBRIUM QUANTUM MANY-BODY PROBLEM AS A PARADIGM FOR EXTREME DATA SCIENCE
J. K. Freericks, B. K. Nikoli´c and O. Frieder,  arXiv:1410.6121v1 [cond-mat.str-el] 22 Oct 2014

Generating big data pervades much of physics.

But some problems, which we call extreme data problems, are too large to be treated within big data science.

The nonequilibrium quantum many-body problem on a lattice is just such a problem, where the Hilbert space grows exponentially with system size and rapidly becomes too large to fit on any computer (and can be effectively thought of as an infinite-sized data set).

Nevertheless, much progress has been made with computational methods on this problem, which serve as a paradigm for how one can approach and attack extreme data problems.

In addition, viewing these physics problems from a computer-science perspective leads to new approaches that can be tried to solve them more accurately and for longer times.

We review a number of these different ideas here.

Keywords: Nonequilibrium quantum many-body problem; extreme data science.

 

MoA:

CVかpublic LBか、ということだけでなく、val_log_lossの単純平均も重要だと思う。

CVとlog_lossは比例していない。 

log_lossのFoldごとのばらつきが大きいと、CVが小さくなる傾向にあるが、どういう計算をしているのか、よくわからない。

優先順位は、val_log_loss > CV > public LBというところかな。

 

11月6日(金)

Study:

以前に掲載したかもしれないが、今日は、波動関数をNNで表現するところにフォーカスしたいと思う。

Ab initio solution of the many-electron Schrödinger equation with deep neural networks
David Pfau, James S. Spencer, Alexander G. D. G. Matthews, and W. M. C. Foulkes

PHYSICAL REVIEW RESEARCH 2, 033429 (2020)

f:id:AI_ML_DL:20201107001409p:plain

Deep neural network solution of the electronic Schrödinger equation
Jan Hermann, Zeno Schätzle, and Frank Noé, 

arXiv:1909.08423v5 [physics.comp-ph] 23 Sep 2020

f:id:AI_ML_DL:20201107001743p:plain

明日は、FermiNetとPauliNetを理解したうえで、簡潔な日本語で説明できるようにしようと思っている。

 

MoA:

CPUを使って、NNのチューニングを行っていた。

2層、3層、4層、および5層のNNについて、log_lossが最小になる条件を探している。

 

11月7日(土)

MoA:

GPUを使うとサクサク進むが、細部にこだわりすぎることがあるので、要注意。

log_lossを小さくしていくのは、簡単ではないが、log_lossが小さくなっても、submitしてみたときにpublic LBが大きい値になると、これでいいのだろうかと、悩んでしまう。

 

FermiNetとPauliNet:

原理を正しく説明しようとしているのだが、正しく理解するのが難しくて、原稿の締め切りに間に合わない!

 

11月8日(日)

MoA:

今日は、最も基本的なhidden_layerが2層のNNモデルに集中してチューニングした。

val_log_lossは、これまでになく小さくなったが、public LBスコアは、改善せず、むしろ悪化した。何に注力すべきか迷う。

learning_rate, batch_size, hidden_size, dropout_probabilityなどの変更は常にやっているが、今回は、これまで以上に、変化率を小さくして検討している。そうすると、パラメータ間の相関がこれまでよりもよく見えるようになったと思う。それもそのはず、見ている数値の桁数が違うのだ。4桁目、5桁目、6桁までじっくり見ていると、見えなかったものが見えてくるのだ。活性化関数による違いもよく見える。

 

11月9日(月)

今日は、FermiNetとPauliNetの説明文を作成しよう。

第一原理量子化学計算、変分量子モンテカルロ波動関数仮説

量子多体問題を厳密に解く

数原子、数十電子(2-30電子)を超えると計算機の能力を超える

近似計算しかできない

多体電子系波動関数ニューラルネットワークで表現する(ニューラルネットワーク量子状態:neural-network quantum states:NQS)

多体スピン構造の波動関数を、制限ボルツマンマシンによって表現する

ニューラルネットワークのパラメータ(多体電子波動関数)の最適化は、変分モンテカルロ法もしくは時間依存変分モンテカルロ法を用いて行う

PauliNet:ハートリーフォックベースラインや標準ジャストロー因子やバックフロー変換などの物理モデルから構成されているネットワーク

FermiNet:PauliNetの考案者らは、FelmiNetについて、物理学を組み込むことなく印象的な精度に到達している、と評価している:比較的単純な数学関数とディープニューラルネットワーク構造によって多電子系波動関数を表現

PauliNetは物理屋さん主導で、FermiNetは機械学習屋さん主導、の印象

 

11月10日(火)

DNNを用いた量子化学計算手法について、半ページほどにまとめた原稿を完成させて学会の編集部に送った。できれば、もう少し長い原稿を書きたいと思うが、それが読者に役に立つ内容にするためには、GitHubの公開コードを実際に使ってみて、実際に使うにはどうすれば良いのかを紹介できることが必要だな。

Kaggleの計算環境を使うのは筋違いだろうな。

パソコン環境だと、自分のGPUがもう古臭いからだめだろうな。

そうなると、google colabを使うことになるのか。 

 量子化学のブログを書いてみよう。

 

MoA:

dropoutとCVとpublic LBの相関を調べてみる。

自前の条件で計算した結果だけを比較してみると、dropoutは0.4以上よりも0.3以下の方がCVもpublic LBも小さくなる傾向がみられた。

public LBのスコアは、公開コードの条件では0.01839だが、自前の条件では0.0186+の後半の方だったのが、今日、やっと0.185+の前半の領域に入った。

CVが小さいところでpublic LBも小さくなってきたのは、良い傾向だと思っている。

今日は、CVを下げるために、hidden layerのユニット数の増減の幅をかなり小さくして、計算を繰り返した。パラメータの調整幅をこれまでにやったことがないくらいまで小さくしているので、まだまだ時間がかかりそうだ。

 

11月11日(水)

MoA:現在、3680チーム

今日もファインチューニングだ!

モデルの基本構造を変えずにCVを下げると、public LBのスコアの最後の桁が1だけ下がった。これを繰り返せばいいのだが、どんどん難しくなる。

 

11月12日(木)

MoA:現在、3730チーム 

今日もファインチューニングだ!

training中にあらわれるnanが気になりはじめた。

train_lossとval_lossがnanになる。discussionで問題提起して解釈や対策が書かれていて、その対策が役に立ったとの返信があるのだが、さっぱり理解できない。

コメントに気になる箇所があったので、weight_decayをデフォルトに戻したら、とんでもないことになった。

 

11月13日(金)

MoA:3762チーム

train_lossとval_lossがnanになる原因がわかった。

weight_decayの値を変えてみると、nanが生じやすくなったり、全く現れなくなることが、現象として把握できた。

weight_decayは、L2正則化のパラメータで、overfittingの抑制に効果があるということを、確認することもできた。

 

11月14日(土)

MoA:3798チーム

全結合層は2層、dropout=0.2、weight_decay=1e-6、こんな感じで、ようやく、0.184+になった。

気をよくして気合を入れて、CVを小さくすることができたので、期待してsubmitしたら、0.01858が現れてがっかりした。public_dataに適合しなくても、private_dataで良いスコアが出ればいいのだと思っていてもやはり気になるものだ。

何度も同じ言葉を並べてしまうが、頭を整理しながら進まないといけないな。

今日は、活性化関数や最適化関数をいくつか試してみて面白い結果も得られたので良しとしよう。

relu, leaky_relu, elu, seluなどを試してみたが、少しづつ違う結果になる。

reluでnanが発生しても、leaky_reluにすれば少し抑制され、さらに、eluにすればnanが現れなくなった。といっても、良いことばかりではない。reluでnanが頻繁に出現する条件では、eluで抑制できても、スコアは悪化するだけだった。

Adamの他に、AdamW, Adamax, SGD,などを試したが、Adamより良い条件は見つけられなかった。それぞれの特徴を生かすには、細かい調整も必要なので、良く調べてからでないと、どれが本当に合うのかは、わからない。

今日から1週間のGPUの割当は、37時間だが、今日だけで7時間使った。

 

11月15日(日)

MoA:

今日も、ちまちまと、チューニングしていた。

public LBのスコアは同じだったが、順位が少し変動した。 

 

11月16日(月)

MoA:

今日はじめて気がついた。

optim.lr_scheduler.OneCycleLR

これはすごい機能だと思う。

これに関わるパラメータの値によって、nanが現れたり消失したりする。

 

11月17日(火)

MoA:3,911 teams, 14 days to go

今日も、public LBを上げることに注力していた。

nanが発生しにくくなって計算できる領域は広がったが、public LBのスコアをよくする方向は、なかなか見えてこない。CVを下げるにはdropoutを大きくするのが効果的だが、public LBのスコアは良くならない。

それでもようやく0.01838に到達した。

 

11月18日(水)

MoA:3,958 teams, 13 days to go

今日もチューニング、チューニング、チューニング。

改善の見込みがありそうな条件だと思ったが、

CVもpublic LBも改善できなかった。

 

11月19日(木)

MoA:4,004 teams, 12 days to go

低スコアの公開コードが投稿されている。

なかなかやるもんだな。

今日もチューニング、チューニング、チューニング。

 

こんなことばっかりしとったら、あかん。

プログラミング技術が上がらん。

 

11月20日(金)

MoA:11 days to go

TabNetを勉強する予定だったが、進捗なし。

dropoutの比率に対するCVとpublic LBスコアの依存性を調べている。

 

11月21日(土)

MoA:4,072 teams, 10 days to go 

dropoutとの相関調査継続中。

 

TabNet:

TabNet: Attentive Interpretable Tabular Learning
Sercan O. Arık and Tomas Phister, Google Cloud AI
arXiv:1908.07442v4 [cs.LG] 14 Feb 2020

ABSTRACT
We propose a novel high-performance and interpretable canonical deep tabular data learning architecture, TabNet. TabNet uses sequential attention to choose which features to reason from at each decision step, enabling interpretability and more efficient learning
as the learning capacity is used for the most salient features. We demonstrate that TabNet outperforms other neural network and decision tree variants on a wide range of non-performance-saturated tabular datasets and yields interpretable feature attributions plus insights into the global model behavior. Finally, for the first time to our knowledge, we demonstrate self-supervised learning for tabular data, significantly improving performance with unsupervised representation learning when unlabeled data is abundant.

Overall, we make the following contributions in the design of our method:
(1) Unlike tree-based methods, TabNet inputs raw tabular data without any feature preprocessing and is trained using gradient descent-based optimization to learn flexible representations and enable flexible integration into end-to-end learning.
(2) TabNet uses sequential attention to choose which features to reason from at each decision step, enabling interpretability and better learning as the learning capacity is used for the most salient features (see Fig. 1). This feature selection is instancewise, e.g. it can be different for each input, and unlike other instance-wise feature selection methods like [6] or [61], TabNet employs a single deep learning architecture with end-to-end
learning.
(3) We show that the above design choices lead to two valuable properties: (1) TabNet outperforms or is on par with other tabular learning models on various datasets for classification and regression problems from different domains; and (2) TabNet enables two kinds of interpretability: local interpretability that visualizes the importance of input features and how they are combined, and global interpretability which quantifies the contribution of each input feature to the trained model.
(4) Finally, we show that our canonical DNN design achieves significant performance improvements by using unsupervised pre-training to predict masked features (see Fig. 2). Our work is the first demonstration of self-supervised learning for tabular data. 

とても良さそうな手法だけど、論文をいくら読んでもだめだな。

実際に使ってみないと。

GitHubに、TabNetが、いくつも出ています。

こういうのを使えないのがなさけない。

なんとかしなければ。

 

11月22日(日)

MoA:4,094 teams, 9 days to go

これまでよりスコアの良いコードを用いて、NNの部分だけ、チューニングしてみた。

自信を持って自分のチューニング結果をsubmitしたところ、最後の桁の数値が+2と+4になった。

公開するだけのことはある、と、感心するばかりである。

 

11月23日(月)

MoA:4,124 teams, 8 days to go

CVはほとんど変わらず、むしろ、わずかではあるが少し大きかったにもかかわらず、LBが、-4も下がった。 

こんなことがあると、CVが少し大きかったためにsubmitしていない計算条件がたくさん残っているのが気になる。その中に、宝物が隠れているかもしれない。

そうではなく、これが、もしかして、public dataへのoverfittingなのか?

 

11月24日(火)

MoA:4,122 teams, 7 days to go

昨日うまくいったベストLBモデルをさらに改良できないかとパラメータを変更してみたが、そう簡単にはいかない。

パラメータの、小さな変更によって改善されることを期待したが、いずれも、最後の桁が+2もしくは+3となった。

難しい。

 

11月25日(水)

MoA:

チューニングを繰り返すのみ。

月曜日にメダル圏内に入ったのに、もう、追い出されて、どんどん離れていく。

 

11月26日(木)

MoA:4,201 teams, 5 days to go

public LBスコアを上げることだけ考えてチューニングしている。

 

Lyft 

本日午前9時00分終了。

課題に適合するモデルの選択と、train時間の確保が、後半の課題だった。

データが膨大で、前処理が複雑にみえて、不十分な取り組みとなってしまった。

複雑なデータに取り組む練習をしないと、こういう課題はクリヤできそうにない。

 

<雑談>

自分は、この分野には、ディープラーニングから入った。データを呼び出し、それを、train_data, validation_data, test_dataに分け、DNNモデルに投入する。最初に使ったテキストでは、いわゆるデータの前処理は、簡素化されていた。ある程度、モデルが組めるようになったので、Kaggleに挑戦した。そこには大きな壁があった。データの前処理と後処理である。データサイエンスのテキストは、ディープラーニングのテキストとペアで購入していて、並行して勉強しようとしたのだが、面白くなかった。それに対して、ディープラーニングは、AIの歴史とともに語られ、インターネット、ビッグデータ、その集大成としてのディープラーニングというふうに続いていて、非常に興味が湧いた。

手元にあるデータサイエンスの本は、和訳で360ページくらいのものだが、機械学習の内容が始まるのは、165ページからである。単純にいえば、自分には、この前半部分の勉強が足りてない、ということになる。今日から、まず、前半部を勉強するとしよう。

 

Riid!:2,062 teams, a month to go

このコンペ、MoAが終われば集中して取り組むつもりだが、MoAはチューニングのみなので、計算の合間に、こちらも進める。

Riiid! Answer Correctness Prediction

Track knowledge states of 1M+ students in the wild

課題は、生徒の学習履歴から、正答率を予測することのようだ。

用いるデータは、EdNetと称するもののようだ。

EdNetというネーミングは、ImageNetを意識したものだろうか。

主催者がすでにそれらしい論文を出している。

SAINT+: Integrating Temporal Features for EdNet Correctness Prediction

DONGMIN SHIN, YUGEUN SHIM, HANGYEOL YU, SEEWOO LEE, BYUNGSOO KIM, and
YOUNGDUCK CHOI, Riiid! AI Research, Republic of Korea

arXiv:2010.12042v1 [cs.CY] 19 Oct 2020

 

11月27日(金)

MoA:4,232 teams, 4 days to go

最終日が近いので、とりあえず、LBスコアの良いモデルに対して、試行回数を増やすなどして、少しでも汎用性を高くしておこう。

試行回数を増やすと、順位が少し上がった。

 

  • Riiid AIEd Challenge
  • :2,076 teams
  • , a month to go

データベース、EdNetに関する論文を見ていたら、EdNetは、韓国の学生の約2年間にわたるTOEICの学習履歴データを収集したものであることがわかり、さらに、santaというワードが気になってgoogleで検索したら、次のような宣伝が出てきた。

SANTA TOEIC

世界的な学会から認定されたAI技術を搭載したTOEIC®︎学習ソリューションです。
“AIチューター”が解答傾向から苦手問題を推測し、あなただけのカリキュラムを構築。
解くべき問題だけに集中することで、短期間で大幅なスコアアップを実現します。

すでに、スコア予測システムは出来上がっていて(上記論文ではAUCが0.80前後)、商品に組み込まれているようだな。さらに性能を向上させることを狙って、Kagglerの知恵を拝借ってことなのか。

Time-series API Details

  • Refer to the starter notebook for an example of how to complete a submission. The time-series API has changed somewhat from previous competitions!

とりあえず、starter notebookを見る。

 

11月29日(日)

MoA:4,287 teams, 2 days to go

締め切りまで、あと2日、となった。

メダル圏内に0.01825が160件あまり、並んでいる。

公開コードがあるので、こういうことになるのだが、9日前に公開されたときには無視していた人たちも、間際になると、保険のつもりで使ってみるのだろうな。

かくいう自分も、最終投稿の2件のうちの1件はこれにしようかなと思って準備している。

 

11月30日(月)

MoA:4,332 teams

今日が実質、最終日だ。

とりあえず、メダル圏内に入った。

圏外で待つよりは、圏内で待つ方が、メダル獲得の可能性は高い、だろう、と思いたい。

 

12月1日(火)

MoA:4384チーム:終了

暫定結果だが、182位となり、銀メダル相当である。

このまま確定すれば、2個目のメダル獲得となり、エキスパートになる。

最終日の投稿結果を選んだことによって、銀メダル相当となった。

最終的に2件の投稿を選ぶのだが、このとき違うものを選んでいれば、違った結果になる。

過去に、メダル圏内の投稿結果を最終投稿として選ぶことができなかったことでメダルを逃したことが2回ある。1回は、public LBが良くなかったので仕方ないともいえるものであるが、もう1回は、Public LBスコアにこだわりすぎて、アンサンブルのし過ぎによるpublic_dataへのオーバーフィッティングを意識できなかったことによるものである。

さて、うまくいった原因を書きたいのだが、自分の今後の指針になるようなものは、残念ながら、いまのところ思いつかない。

 

 

f:id:AI_ML_DL:20201101113720p:plain

style=157, iteration=1

f:id:AI_ML_DL:20201101113848p:plain

style=157, iteration=20

f:id:AI_ML_DL:20201101113944p:plain

style=157, iteration=500

 

Kggle散歩(October 2020)

Kggle散歩(October 2020)

 

10月は、OpenVaccine(10/5:訂正10/6)とOSIC(10/6)とRSNA(10/26)が締め切りを迎える。

これらのコンペの中からメダルを1個獲得できれば、2個目となり、Expertにランクアップされる。

しかし、どのコンペも難しい。

OpenVaccine:メダル圏の外ではあるが近くにいる。(10/2追記:すごい勢いで遠ざかっていく、public LBでは勝負にならない)

OSIC:適正なパラメータセッティングの方向性が見えない。

RSNA:いまだに、戦う手段を持っていない。(OpenVaccineとOSICが終わってから検討する)

 

10月1日(木)

OpenVaccine:

アンサンブルの重みの検討:

最大値と最小値の差が2/1000程度ある6件のデータを用いたアンサンブルでは、単純平均の場合と比べると、重みづけにより、public LBは、2/10000程度改善した。

今の自分の順位だと、周辺のチームは数時間で2/10000くらい上がってしまうので、もっと効果的なスコアアップ手段がないとメダル圏内は難しい。

少しスコアが悪くても、スコアが近いものを複数合わせると良くなるので、今日検討した6件以外のデータについて、アンサンブルに使えるかどうか、明日、調べる。

10時間くらいで、メダル圏内との距離が、5/10000以上、大きくなった気がする。

13時間くらい前に、新たなコードが公開された。活発な議論が展開されている。

伝説のKagglerまで現れてコメントしている。(ただし、ネガティブなコメント?)

それにしても、参加していないようでも、ちゃんと、見ているんだね。

しかし、非常に難しい状況になってきた。

 

10月2日(金)

OpenVaccine:

メダル圏との差が2/1000以上になった。

チャレンジしないと、とても追いつかないし、追いつけない戦いはしたくないし、ここであきらめることもしたくない。(public_test_dataが9%と少ないので、どんでん返しにも少しは期待しながら・・・。)

まずは、アンサンブルの効果確認から始めよう。

メダル圏内が、0.239+となっているときに、3件の0.247+と4件の0.246+を利用できるかどうかを調べるのは無意味のように思うが、やってみよう。

それぞれの効果はそれなりに認められたが、最終結果への効果は、4/100000であった。

順位変動なし、というより、この作業中にも順位は下がった。

自分のアンサンブルのやり方では、public LB値は、最もよいモデルのそれよりも、2/1000くらい小さくなることがわかった。

自分の単一モデルの結果0.243+は、現在トップの0.228とは、6-7%くらい違う。

efficientnetの'b0'と'b7'くらい違うということか。

mrkmakr氏の公開コードの概要説明を転記させてもらおう。

training scheme

(1) train denoising auto encoder model using all data including train and test data

(2) from the weights of denoising auto encoder model, finetune to predict targets such as reactivity

rough network architecture

inputs -> conv1ds -> aggregation of neighborhoods -> multi head attention -> aggregation of neighborhoods -> multi head attention -> conv1d -> predict

this architecture was inspired by https://www.kaggle.com/cpmpml/graph-transfomer

最後にinspireされたプログラムとしてあげられているのは、CPMP氏の公開コードで、NFL Big Data Bowlコンペのものである。

 

(さきほど、スカパーのチャンネルを適当に変えていたら戦争映画にでくわした。途中からだったが、引き込まれて、最後まで見た。Darkest Hourというタイトルだった。)

 

10月3日(土)GPU:0/38, TPU:0/30

OpenVaccine:245/1543, 0.24148, 0.23846

現時点で、3/1000の改善が必要。

単独のスコア0.24353を0.24053まで下げる方法を探す。

最初に試した結果も、2番目に試した結果も、散々(0.245+)だった。

深夜までトライしていたが、0.24353すら超えられない!

 

OSIC:309/2063, -6.8072, -6.8070

検討中

 

10月4日(日)

OpenVaccine:

新たに得た3件の予測データをアンサンブルに追加したが、スコアは改善されなかった。

ともかく、最良と思われる結果を、締め切りまで、計算し、submitしつづけるだけだ。(やけくそ!)

ようやく単独で0.242+となったが、ちょっと遅かったかな。

メダル圏内はすでに0.237+にまで下がっているので、このスコアでは、届かない。

計算資源を節約しながら(時間制限を受け入れながら)ハイスコアを出すには、まだまだ、技術が足りないということだ。

 

10月5日(月)

OpenVaccine:

昨夜計算した結果はcommit中のトラブルにより失ったため、計算は終了した。あとは、新たに得た2件の結果をアンサンブルに追加してsubmitするだけである。

今、public LBで320番くらいで、新しい結果をどう組み合わせても、メダル圏内に入ることはないが、最後の5回のsubmissionで最善をつくそう。

コンペ挑戦終了。

0.24105, 311st(10/5/10:57)

 

OSIC:

締切日の前日にして、GPU割当時間を使い切った。

といっても、結局、方向が定まらず、気になる計算条件を煮詰めようとして計算を繰り返していたが、見えない相手に対して、どう攻めたらよいのか、わからないままである。

88回のsubmit履歴が残っているが、どのモデルがprivate test dataに対して最も確からしい予測結果を出せるのか、判断基準がわからないままである。

コンテストのために用意されたデータではなく、現実世界で使われているデータで、よく整理されたデータというよりは、医療現場で蓄積されたデータを取捨選択することなくかき集めてきたもののように思う。

それだけに、このデータから何が言えるのかを根拠をもって説明できるだけのモデルでなければならないのだろうが、残念ながら、そこには辿りつけていない。

 

10月6日(火)

OpenVaccine:

最終提出期日を間違っていた。

昨日ではなく、今日だった。

 

OSIC:

今日が投稿最終日だ。

 

RSNA:

20日間は、このコンペに集中しよう。

現在、330チームがリーダーボードに掲載されている。

A pulmonary embolism (PE) is caused by an artery blockage in the lung.

Currently, CT pulmonary angiography (CTPA), is the most common type of medical imaging to evaluate patients with suspected PE. 

In this competition, you’ll detect and classify PE cases. 

 

10月7日(水)

OSIC:

暫定結果は、1504番目

気合十分で始めたコンペだったので、この結果は、非常に残念である。

結局、最後の2回のsubmissionを選んだ。

public LBの最も良い値を選んでいたら、1120番くらい。

submitした中で最も良かったのは、最終順位で106番で、銀メダル相当だった。これは、NNのフィッティング結果が良かったのでsubmitしたのだが、public LBは良くなかったし、これを選ぶ特段の理由がなかったので、選ばなかった。

これは、順位が大きく変動するだろうという予想どおりとなったが、どうすれば良いか、どれを選べばよいかは、わからなかった。

 

OpenVaccine:

暫定結果は、379番だった。

メダル圏外ということでは、残念な結果だが、これは、ほぼ、予想通りである。

普通に計算して、その結果をアンサンブルしただけなので、大きく上がることも下がることもないだろうと思っていた。

 

RSNA:

データが非常に大きく、inferenceに長時間を要することから、コードコンペでありながら、inferenceに限るということだが、こういうのは、自分にとっては初めてのことである。

画像の扱いも、少し、特殊であり、train画像の枚数も多い。

データは、大きすぎて(900 GB以上)ノートパソコンにダウンロードできない。

 

10月8日(木)

RSNA:379チーム

今日は。trainコードとinferenceコードを準備しよう。

参加者が少ないためか、公開コードが少ない。

trainコードの準備

・学習させたモデルはsaveする。

・saveしたモデルは、kaggle datasetとして保存する。

inferenceコードの準備

・ 学習済みモデルのload:作成したkaggle datasetから学習済みモデルを読み込む。

これだけのことなんだが、モデルの保存・読み込みは、これまで、それほど意識して使ったこなかったが、これを機に、使えるようにしよう。

モデルの保存等に関するコード:A. Geronさんのテキスト314ページ

Saving and Restoring a Model

When using the Sequential API or the Functional API, saving a trained Keras model is as simple as it gets:

    model = keras.models.Sequential([...]) # or keras.Model([...])

    model.compile([...])

    model.fit([...])

    model.save('my_keras_model.h5')

Keras will use the HDF5 format to save both the model's architecture (including every layer's hyperparameters) and the values of all the model parameters for every layer (e.g. connection weights and biases).

It also saves the optimizer (including its hyperparameters and any state it may have).

 

<雑談>

AIを極めることに取り組んできたが、そこから遠ざかっている自分の姿が見える。自分に見えているAIは、自分が見てきた過去のプログラミングでは成し得なかったことを成し遂げているが、それらが、ものすごく大きなものに見えることもあれば、想像していたものとは全く違って見えることもある。 (twitterに書こうとしてやめた)

今のプランは、メダル獲得競争と、メダル獲得を強いモチベーションにして、様々な課題解決のためのプログラミング技術を習得しながら技術レベルを高め、様々な課題に対してより高いレベルの解決方法を模索していくことであり、その先に、次の世代のAIを考え、構築していこうというものである。

今の自分の最大の弱みは、英語力である。このハンディーは非常に大きい。マニュアルをいちいち和訳していては進まないし、プログラムは英語そのものだから、プログラムもマニュアルも論文も書籍も斜め読みできる英語力がなければだめだ。

そう思って、昨年の6月頃にdeep learningを勉強するためのテキストとして、F. Chollet氏の著書を購入し、その後も、何冊か英語のテキストを購入してきた。しかし、読まなければ、書かなければ、使わなければ、英語力は身に付かない。

気がつくと、Google翻訳やオンライン翻訳に頼っている自分がいた。英語のテキストが理解できずに和訳を買って見比べながら読むこともやってみたが、新しい概念は和訳したってわからないのだ。定義や応用事例を見てその意味を理解していくのだから、1つの概念を理解するために日本語と英語の両方でやるなんてことは非効率の極みである。

 

10月9日(金)

Riiid!:

Answer Correctness Prediction

Track knowledge states of 1M+ students in the wild

The goal is to accurately predict how students will perform on future interactions.

If successful, it’s possible that any student with an Internet connection can enjoy the benefits of a personalized learning experience, regardless of where they live.

面白そうだな。オンライン学習が進めば、学習プロセスに関するデータが蓄積され、各人に合った学習プロセスを提供できるようになるということか。

学習の経過がフィードバックされるようにプログラムしておけば、自律的に成長していくということか。個々人の成長に合った学習プログラムが提供できればいいな。

各人が、自分で、自分の脳にプログラミングしているために、その能力の違いが学力の違いを生じさせているのだろう。そうすると、自分で自分の脳にプログラミングできない人にとっては、このような学習システムは重要なものになるのだろう。

学力に応じたプログラムが自動的に生成されるようにすればいいのだろう。

Tailoring education to a student's ability level is one of the many valuable things an AI tutor can do.

Your challenge in this competition is a version of that overall task; you will predict whether students are able to answer their next questions correctly.

You'll be provided with the same sorts of information a complete education app would have: that student's historic performance, the performance of other students on the same question, metadata about the question itself, and more.

公開コードのパラメータを少し変えて投稿してみた。

NNよりもLGBMの方が良さそうだ。

 

10月10日(土)

RSNA:

10月8日に検討した結果を元に進めるが、全体の流れをチェックしやすいように、再スタートする。

1.kerasで書かれた公開コードを使ってみる。(trainを含んでいるので切り離すが、trainを含んだままでcommit->submit->scoreまで進むかどうか調べてみる)

2.コードコンペなので、internet offにしなければならないが、このコードは、'imagenet' pretrained modelのweightsを、インターネット経由でダウンロードするようになっている。

3.kaggle kernelで使うdatasetを準備する。

 tensorflow/kerasのサイトの情報から、'imagenet' pretrained modelのweightsをダウンロードし、kaggle datasetに格納する。

4.このデータセットを、kaggle kernelの入力データに追加する。

5.train+inferenceプログラムを実行してcommitする。trainもinferenceも実行時間を設定しているので、各1時間で試してみる。実験なので、GPUは使わないでやってみる。

6.submitまでは無事に済んだ。

 ここで、スコアが表示されるかどうかによって、次の対応が決まる。

7.スコアが出た。0.975(0に近い方が良いスコア)であった。

 ということは、trainとinferenceが共存しても大丈夫ということだ。

8.GPUをonにすると、trainは5倍以上速くなるが、inferenceは2倍程度しか早くならないことがわかった。

9.試しに、512x512のデータをefficientnetB5でinferenceすると、GPUを使っても1時間に50kくらいしか処理できなかった。したがって、trainとinferenceの両方を含むコードでは、9時間の制限時間でも不足する。それだけでなく、大きなモデルで大きな画像を処理すると、inferenceだけのコードでも、制限時間内にinferenceが終わらない可能性が出てくる。ということで、trainとinferenceは分離しよう。

10.と言いつつ、0.975(これはとんでもなく悪いスコアで、トップは0.149、0.325とか0.434がたくさん並んでいる)を上回るスコアになるかどうか確かめるための計算を行う。CPUのみで、trainとinferenceのそれぞれに、4時間の時間制限をつける。0.975のときは、1時間の時間制限であった。どうなるか楽しみだが、計算とcommitを合わせて16時間、それにスコア計算の時間が加わるので、20時間以上かかりそうだ。

・こういう長い時間を要する場合は、いろんな不具合が生じて、何日もかかることがあるので、気長に、楽しみながらやるのがよい。

 

10月11日(日)

RSNA:

悪い予想が当たった。朝起きると、次のメッセージを残して、計算が止まっていた。

Your notebook tried to allocate more memory than is available. It has restarted.

停止していたのは、inferenceの途中だったので、train中の情報がメモリーに蓄積されていたのが、まずかったのか。ともかく、途中経過がわからないと対策のしようがない。

'view session metrics'を'on'にしておけば、メモリーの使用状態が、リアルタイムでわかる。(眠っていたらわからないけど)

途中経過を見ているところだが、Diskではない。RAMの使用量(max 16GB)が、14GBから徐々に増え、50分くらいで16GBに到達し、それ以降は、なんらかの調整機能が働いているようで、15.4-15.9GBあたりで推移している。

GPUをonにしたらどうなるのだろうか。:RAMは16GBから13GBに割り当てが減少するので直接比較できない。GPUのRAMとの関係もわからない。GPU併用との大きな違いは、CPUの稼働率が300%を超えていたのが、120%以下に下がったこと。ともかく、途中で停止せず、予定の計算を最後までやってくれたらそれでいい。

順調に進んでいるように見えていたが、one batch timeが、inferenceの進行とともに長くなっている。バッチあたり13秒くらいで始まったのが、1時間を過ぎるころには2倍くらいかかっている。

予定の3時間まであと25分のところで、同じメッセージYour notebook tried to allocate more memory than is available. It has restarted.があらわれて停止した。

嫌なパターンだ。

どうしたものか。

モリー使用量が問題なら、batch_sizeを下げれば良かろうと思って500から250に下げると、処理時間が倍ほどかかりそうで、途中でやめた。batch_sizeが原因かどうかもわからず下げるより、上限を探ろうと1000に設定してみた。理由はわからないが、とりあえず最後まで計算が進んだので、ひとまずOK。

さらに条件検討してみよう。メモリーコントロールを学ばないといけないようだ。プログラムコード中に、del modelとか、del x,とか、見かけたような気がする。

とりあえず、inferenceもできるようになった。しかし、スコアがおかしい。最初のスコアは、一部の結果しか得られていないから仕方ないのだが、inferenceは完了したにもかかわらず、スコアがそれほど良くならない。

 

10月12日(月)

RSNA:

predictionの割合とLBスコア:53k/147k:0.975、88k/147k:0.934、147k/147k:0.862

 train:efficientnetB0、256x256、25k-125k/1790k 

いまは、predictionが進めば、スコアが少しづつだが、良くなっている(値が小さくなっている)、というレベル。

次は、predictionの後処理を調べてみよう。

evaluationを見ているのだが、よくわからん。

 

10月13日(火)

RSNA:

うまく動き出したと思ったのだが、submitした後のスコアリング中にNotebook Timeoutが発生した。

なぜエラーになるのかわからない。

 

Kaggle cources:

Kaggleから、Intro to Deep Learningの案内が来た。

昨年、deep learningを本格的に勉強し始めたころは、Kaggle minicource ?、には、たいへんお世話になっていたのだが、もの足りなくなって、data campを利用したり、テキストを追加購入したりして勉強していたのだが、ある程度習得したつもりで、あとは、応用だとばかりに、Kaggleコンペにのめりこんでいるところである。

しかしながら、課題に取り組んでみると、自作のモデルでは、良い性能が出せなくて、いつしか、公開コードをフォークするのがあたりまえのようになってきた。

こういう状況をみすかされたわけではないと思うが、良い機会ととらえ、勉強してみようと思っている。

昨晩は、YouTubeDeep Learning State of the Art (2020) | MIT Deep Learning Seriesを聴講したが、お話は、いくら聞いても身に付かないと感じていたところである。

入門レベルだが、英語の勉強を兼ねて、取り組もう。

 

10月14日(水)

mail from Kaggle:

You’re not too far from receiving a completion certificate!

f:id:AI_ML_DL:20201014093748p:plain

For every course you complete on Kaggle, we’ll issue an official certificate that celebrates the progress that you’ve made in your data science and machine learning journey.

手を付けたはいいが、ほったらかしにしていたら、こんなメールが届いた。

今月中に、全コースの終了証をもらえるように、がんばってみよう。

 

<雑文>

ここ2,3日、頭が重い。なぜかと考えてみた。脳になんらかの負担がかかっているということなんだろうな。脳には、体のあらゆる情報が集まっているのだから、頭が重いのは、体のどこかに不具合が生じているということだろう。ここ2,3日の変化と言えば、1週間くらい前から、ダンベルを持ち出して、腕力のトレーニングを始め、数日前からは、push ups(腕立て伏せ)の回数を増やそうとして、計算の合間に、強めのトレーニングをしてきた。今日は、肩から上腕部にかけて痛みがあり、同時に、頭の重さを強く感じるようになった。こうなると、トレーニングをやめてしまい、三日坊主に終わってしまうことになるんだろうな。負荷を調整しながら、トレーニングを続けよう。

 

RSNA:

まだ、trainとinferenceの両方を含むプログラムを使っている。

性能アップのためには、十分なtrainingが必要であり、trainとinferenceを分離する必要がある。これが、まだうまくいっていない。

train modelは、detasetに入れて、inference notebookの入力データに追加して、読み込もうとしているのだが、・・・。

今日は、trainとinference共存で、trainをかなり多くしてみたところ、inferenceに移ってからの処理速度が遅くなった。負荷がかかってるなという気がしてから30分くらいの間にプログラムが停止した。

GPU使用、'B0', 256x256で3エポックでも18時間くらいかかりそうなので、もうこれは、単にtrainとinferenceを切り離せばよいというものではないことを確信した。

ここからメダル圏内に入るために、trainにTPUを使おうと思う。当初からそうしないとだめだろうなというところにきてしまった。

ぼちぼち勉強しながら前進しよう。

 

Winner's Interview:Tweet Sentiment Extraction

Kaggleからのメールを見て、インタビューの一部を聴講してみた。2位は日本人3名のチームだった。説明内容もトークも良かった。あたりまえだが、レベルが高い。雲の上の人たちだなと感じてしまう。

 

intro to machine learning:

ぼちぼち勉強中。

 

10月15日(木)

RSNA:

スコアの良いコードが公開されていたので、利用させていただいた。それでもメダル圏外である。公開したチームは、(当然)それより良いスコアで上位にいる。

関連するdiscussionから、trainには、相応の計算資源と計算時間(+コーディング+デバッグ)が必要であることがわかる。

trainに用いたコード(例)も公開されている。

この公開コードによって、Project MONAIの存在を知った。

https://docs.monai.io/en/latest/:以下、ここから引用

Project MONAI

Medical Open Network for AI

MONAI is a PyTorch-based, open-source framework for deep learning in healthcare imaging, part of PyTorch Ecosystem.

Its ambitions are:

  • developing a community of academic, industrial and clinical researchers collaborating on a common foundation;

  • creating state-of-the-art, end-to-end training workflows for healthcare imaging;

  • providing researchers with the optimized and standardized way to create and evaluate deep learning models.

Features

The codebase is currently under active development

  • flexible pre-processing for multi-dimensional medical imaging data;

  • compositional & portable APIs for ease of integration in existing workflows;

  • domain-specific implementations for networks, losses, evaluation metrics and more;

  • customizable design for varying user expertise;

  • multi-GPU data parallelism support.

Modules in v0.3.0

MONAI aims at supporting deep learning in medical image analysis at multiple granularities. This figure shows a typical example of the end-to-end workflow in medical deep learning areaimage

MONAI architecture

The design principle of MONAI is to provide flexible and light APIs for users with varying expertise.

  1. All the core components are independent modules, which can be easily integrated into any existing PyTorch programs.

  2. Users can leverage the workflows in MONAI to quickly set up a robust training or evaluation program for research experiments.

  3. Rich examples and demos are provided to demonstrate the key features.

  4. Researchers contribute implementations based on the state-of-the-art for the latest research challenges, including COVID-19 image analysis, Model Parallel, etc.

The overall architecture and modules are shown in the following figure: image

これまでに、MONAIを見たり聞いたりしたことがない。情報収集力に問題ありだな。

0.1.0-2020-04-17となっているので、半年前に公開されたということか。

PANDAとTReNDSのdiscussionでは話題になっていたようである。

特に、TReNDSでは、discussionで7件、notebookで1件、検索でひっかかった。

discussionで多くでてきたのは、上位者が入賞記事でMONAIに言及していたため、すなわち、上位入賞者はMONAIのことを4か月以上くらい前から知っていて使っていたのである。さすがだな。

Kaggleは、100 ppmレベルの違いを競っていて馬鹿らしく見えるときもあるが、さらに上を目指すために、新しい優れた技術を探し当てて利用し、あるいは、それらを創り出すきっかけになっているのだろう。

 

Intro to Machine Learning:

初歩の初歩だけど、あらためて、やり直してみると、最近はプログラムを一から書いていないからだろうな、解説やコード例を何度も見返さないと正しいコードが書けなくなっている。

 

10月16日(金)

Intro to Machine Learning:

本日22時46分、やっと終了した。過去にsubmitまでやった履歴が残っていたが、記憶に残っていたのは少なかった。

 

Bonus Lessons:Intro to autoML:

google cloud autoMLの宣伝?ひとまず中断!

 

Intermediate Machine Learning:

2019年9月14日に終了していた。

記録が残っているのだが、記憶に残っていない。

気がつけば、ボケ老人になっていたということか。

1年前は、3時間で片付けようとか、3日でやってしまおうとか、1週間もあればできるとか、3か月後にエキスパート、6か月後にマスター、1年後にグランドマスターとか、言っていた。

そのようなノリで、このコース:Intermediate Machine Learning:も、斜め読み(英語の斜め読みはいい加減だったと思う)とコピペで終了したのかもしれない。正確には思い出せないが、じっくりと腰を据えて取り組んだものではなさそうだ。

PythonがYour Completedの中に入っていたので、中を見たが、とても理解できているとは思えない。とにかく、Coursesを、全部、やりなおそう。

 

10月17日(土)

RSNA:

パラメータを変えてRun, commit, submit, スコアに変化なし。

 

Cources:Pandas

英文の単語の配置を変更して少し記号を追加すればコードになるのに、日本語が間に入ってしまうから、難しくなる。それだけのこと。

Lessonは、TutorialとExerciseに分かれていて、Tutorialのテキストを読み、Exerciseの各問題を解く(コードを入力する)、ということだと思っていて、Tutorialは読むだけだったが、Editorを動かせば、例題のコードを好きなように変更して、コードの動作確認をしながらコーディングを学ぶことができる。いまごろ気付いた。

 

10月18日(日)

RSNA:

進捗なし。

 

Cources:Pandas

Create variable centered_price containing a version of the price column with the mean price subtracted.

(Note: this 'centering' transformation is a common preprocessing step before applying various machine learning algorithms.)

centered_price = reviews.price - reviews.price.mean()

Exercise中にYour notebook tried to allocate more memory than is available. It has restarted. このメッセージが現れた。全く、理由がわからない。

リスタートしたら、こんどは、このメッセージがすぐに現れて、停止した。

 

Lyft

フォークして実行するだけ。だめだな。進歩無し。

 

10月19日(月)

今日は、朝から、Cheatingに関する議論を眺めている。

Cheatingは不正行為全般を指しているので案件ごとに内容が異なり、対応も異なるが、詳細を記することは、それを真似た不正が生じる恐れもあり、対応策にしても明確に示すのは難しく、検討のさなかにあるということである。

Plagiarismの話題では、盗作といえば、公開コードに関するものだが、公開コードを使って計算して投稿すること自体が問題だという人もいる。これを許容していることがKaggleの特徴であり、これ自体は問題ではない。

問題は、Kaggleのランク付けと関係しており、公開コードのupvote数およびその件数によってランクが上がり、コンペのランクと同じ呼称、エキスパート、マスター、グランドマスターが与えられる。この公開コードでランクアップを狙う過程で盗作があるということである。コードを販売して利益を得ているのではないが、公開コードへの投票が自分への投票になるということにおいて、栄誉という利益を得ていることになり、それが、著作権を盗んでいることになるのである。

論文を書いたことのある人はわかると思うのだが、著作物は、そこで使われている文章、図面、手段、理論などの出典を明らかにすることと、著作者の許諾を得ることは必須であるが、それを理解しない人が多いということである。

こういう決まり事は、体得していないとわからないものである。SNSで発信する場合も同じ縛りがあるのだが、個人使用と公開との境界があいまいになり、放置されていることが多い。

Plagiarismに関する議論で、誰かが、盗作者に対しては、きちんと取り締まるべきであり、盗作か否かの境界を明確にし、担当者を増やすなりしてきちんと対処してほしいということをKaggleに対して要望していた。これに対して、Kaggleの担当者の1人が、そのとおりであるが、全体のバランスも勘案しながら良い方法を検討していくと述べた。実社会でもそうだが、訴えがなければ、裁判は始まらず、訴えができるのは、原則として、損害を被った当事者であることから、利害関係のない人から盗作の指摘があっても、主催者が事実関係を調べるべきである、ということにはならない。

コンペは賞金が絡むので不正を見逃すことはできないが、それ以外は、当事者がKaggle参加者であれば、ゆるくしておいてもよさそうな気はする。

最近、GitHubから引用した人が引用元を明示していなかったことを、制作者に指摘されているのを見た。これは非常識すぎると思った。GitHubには、ライセンスの種類が明記されており、表示が必要な場合には、表示の仕方が明記されている。

 

RSNA:

STARTER DATASET: Train JPEGs (256x256)

This competition is challenging due to the huge dataset size. In addition, people may not be familiar with medical imaging and CT scans.

To lower the barrier to entry to this competition and to encourage more people to participate, I have converted all of the DICOM images into JPEGs (about 52GB), 256x256 pixels (standard is 512x512).

GMIan Pan氏が、1か月も前に、コンペに参加してもデータが大きすぎて、手も足も出ない者に対して、このようなデータセットを作っておられたことに気付かなかった。

 

Cources:Pandas

学習中のエラーの原因は、コードの書き間違いだった。'.'とすべきところに'/'が入っていたのが原因だったようだ。しかし、メッセージの意味とのつながりがわからない。

とりあえず、エラーは解消し、次に進めるようになった。

 

今日のスロージョギング:4.2 km, 46 min

 

10月20日(火)

Cources:Pandas

ようやく、一通り終えた。TutorialとExerciseがペアになっているので、Tutorialで学び、Exerciseで学んだことを確認するものと思ったが、そうではない。両方を合わせて1つであり、両方合わせても、Pandasのごく一部にすぎない。ということは、このレベルのことは、スイスイできるようになっていなければならないということだろう。

 

Cources:Data Visualization

Progressが53%になっているので半分くらいやったのかなと思ったら、Tutorialをすべて眺めただけだった。ということで、Exerciseにとりかかろう!ではなくて、Tutorialの最初から、英文で内容を理解しよう!

genre:ゲンレと発音していて、ジャンルの意味だとは知らなかった。こんなレベル!

categorical scatter plot:

sns.swarmplot(x=candy_data['chocolate'], y=candy_data['winpercent'])

f:id:AI_ML_DL:20201020201216p:plain

作図は形式的にやっていても得るものは少ない。表から直観的に概要を捉えたうえで、仮説を立てながら、図示し、図から関係性を定量的につかんでいく、というような感じで進めていくことができなければ、コードも頭に入らない。1年くらい前に取り組んだ時には、表の意味を理解することに、ものすごく手間がかかって、結局、放り出していたのだろうと思う。

 

RSNA:

何かやれることはないかと考えていただけである。

 

10月21日(水)

自主学習:ニューラルネットワークと第一原理計算

最近の状況をA4半ページ以内のスペースで紹介することが直接の目的。

引用論文は次の3件にするつもり。

1)  D. Pfau, J. S. Spencer and A. G. D. G. Matthews, Phys. Rev. Res. 2, 033429 (2020)

Ab initio solution of the many-electron Schrödinger equation with deep neural networks.

2)  J. Hermann, Z. Schätzle and F. Noé, arXiv:1909.08423v5 [physics.comp-ph] 23 Sep 2020

Deep neural network solution of the electronic Schrödinger equation.

3)  K. Choo, A. Mezzacapo and G. Carleo, Nat. Commun. 11, 2368 (2020)

Fermionic neural-network states for ab-initio electronic structure.

1番目の論文では、FermiNet、2番目の論文ではPauliNet、という略語が用いられているが、3番目の論文では、どちらの略語も使われていない。

 

RSNA:

2~3日、見ていない間に、ハイスコアのコードが公開されたようだ。

とりあえず、フォークさせていただいて、実行してみる。

commit, submitでスコアが出ると、そのスコアを上げる方法はないものかと思い、コードをながめまわすことになるのだが、このときに、経験値が生きてくる。

ハイレベルな人たちは、自分のコードと比較して良いところを取り込むだろうし、組み合わせの上手な人は、いろいろな公開コードから使えそうなパーツを借りてきて、組み上げていくんだろうな。このときに忘れてはならないのは、それぞれのパーツのオリジナルの引用元を明示しておくことだな。オリジナルが分からない場合でも、最低限、直前の引用元を明示しておくことが必要だな。

Kaggleのmicro courceを少し勉強しただけでも、コードは理解しやすくなるものだし、フォークしたコードのチューニングを繰り返している間も、少しづつはコードの理解が進んでいくものだ。

時にはレベルは低くても自前のモデルにこだわるのもいいし、時には、ベースモデルに、パーツを組み合わせていくのもいいし、ハイレベルのモデルからコーディングを学ぶのもいいし、いろんな使い方をして、前進していけばいいんだ。

とにかく、立ち止まらないことが大切だろうな。

 

10月22日(木)

RSNA:

昨日計算した結果は、timeout errorであった。パラメータの値の変更が裏目に出たようだ。公開コードの理解を進め、改善の可能性を探る。

 

自主学習:ニューラルネットワークと第一原理計算

4)  Z. Schätzle, J. Hermann and F. Noé, arXiv:2010.05316v1 [physics.comp-ph] 11 Oct 2020

Convergence to the fixed-node limit in deep variational Monte Carlo

・PauliNetとFermiNetの違い(同一内容の異称かどうか調べる)

・variational quantum Monte Carloからの改善点と発展性

45年くらい前に最も興味のあった分野なんだけど、言葉に慣れても、量子化学計算の式の理解力が不足しているために、途中で思考が途切れる、あるいは、停止する。それでも、当該分野の最近の展開を、インパクトのある文章に仕上げなければならないのだ。 

 

10月23日(金)

RSNA:

メダル圏内が見えてこない。

 

micro-cource:Data Visualization

f:id:AI_ML_DL:20201023090554p:plain

 

micro-cource:Data Cleaning

1. Handling Missing Values

Exerciseのデータベースが、building permits(建築許可)である。こんなデータに興味はない。そうすると内容を考えずに形式的に解答してしまう。やる気が失せることもある。NaNとなっている理由が理解できなければ、その次の処理の方法とその理由を理解することが難しくなる。データの意味が分からないと、そのカラムを無視して良いのか、仮のデータを代入すべきかなどを正しく判断できない。

Tutorialのデータはnfl_dataで、これも、面白いものではない。そのために、つい、読み飛ばしたり、内容を理解しないままに形だけ真似てしまって、必要なコードが頭に入っていなかった。Kaggleのコンペではよく出てくるようだ。アメフトのルールをある程度知らないと理解できないことが多い。

好き嫌いや興味の有無は、技術習得の段階では、邪魔者でしかない。

興味が無くても、その内容を理解して、必要な技術を1つづつ習得していかなければならない。

2. Scaling and Normalization

3. Parsing Dates

4. Character Encodings

5. Inconsistent Data Entry

 

10月24日(土)

RSNA:

final submission deadlineまであと3日となった。5日前に公開されたコードのLBスコアは、100番から320番まで並んでいる。3日前は、およそ、60番くらいから260番くらいまで並んでいた。ということは、3日間の間に、40名くらいが、0.233を超えていったということになる。

trainからやりなおせるなら、画素数を増やして、EfficientNetB0をB5以上にするとか いうことになるのだろう。

ハイスコアの公開コード、5回ほど、パラメータを変えて計算してみたが、予測データに変化がなかった。ようやく6回目にその値が変わったので、結果を楽しみに、commitしていたら、並行してmicro-courceのexaciseをやっているときに、パソコンがフリーズした。1時間くらいして復帰したが、動作不安定となった。commitは終了していて、submitまでできたが、スコアが出るかどうか不安。

ほぼ同じ条件で、再計算中。---> エラー発生(上記エラーの影響だろうな:windows10の性能が悪いということだろうな:4時間半のロス)

同一条件で再計算。結果は、0.696と、ひどいものだった。悪化させただけだ。

先ほど、別の条件で計算している途中で、あと1時間でメンテナンスのためコンピュータを停止するからcommitするようにとのメッセージがあった。

計算途中でcommitするとはどういうことなのだろうか。

途中の状態が維持されて、その状態から再開されるというのだろうか、やったことないからわからないけど、うまくいきそうに思えない。

何か仕掛けがあるのかどうか、どこかで時間をとって、調べてみよう。 

 

micro-cource:Data Cleaning:scaling and normalization

# for Box-Cox Transformation
from scipy import stats

# for min_max scaling
from mlxtend.preprocessing import minmax_scaling

in scaling, you're changing the range of your data

f:id:AI_ML_DL:20201024111020p:plain
in
 
normalization
, you're changing the shape of the distribution of your data.

f:id:AI_ML_DL:20201024111057p:plain

これは、非常にわかりやすい説明だ。

重要なのは、スケーリングや規格化をいつ、どこで(どのような場面で)、どのように使うかということだろうな。

micro-cource:Data Cleaning:parsing dates

earthquakes['date_parsed'] = pd.to_datetime(earthquakes['Date'], format="%m/%d/%Y") 

よくわからんが、10/24/2020 とか、2020-10-24とかの期日の表示方式に関すること。

micro-cource:Data Cleaning:character encodings

# helpful character encoding module
import chardet

UTF-8 is the standard text encoding. All Python code is in UTF-8 and, ideally, all your data should be as well. It's when things aren't in UTF-8 that you run into trouble.

Try using .decode() to get the string,

then .encode() to get the bytes representation, encoded in UTF-8.

micro-cource:Data Cleaning:inconsistent data entry

import fuzzywuzzy
from fuzzywuzzy import process

これは、かなりたくさんのデータを、手作業で眺めてみて、問題点を拾い出すことを丹念にやって、見つかった課題を、自動で正確に処理するために、便利な関数を使うことができるようにするということのようだ。

 

10月25日(日)

RSNA:

Data setの理解:数%

Metricの理解:数%

モデルの構築:ゼロ

目標達成度:ゼロ

たとえば、データの説明のために、わざわざ次の図が掲載されていたのだが、それぞれの項目の意味とともに理解しておかないとプログラムが作れないことが分かっていながら、理解しようとしなかった。もちろん、容易なことではない。でも、それをやらないと、この先はない。

 

<行事メモ>

応用物理学会・東海支部 基礎セミナー

「AIを用いた画像処理・認識技術の進展」

Zoomウエビナー

4件の講演があった。最も新鮮だったのは、AIチップの話である。そのほかの話は、わかりやすかったが、驚きはなかったので、省略する。

開発中のAIチップは、コンタクトレンズに組み込み、涙で発電してAIチップを駆動し、涙の中の糖分の量の情報を得て、それを電波発信してスマホ等で受信するというもので、類似のシステムは、Googleで開発が進められていた(採用している技術は本質的に異なるところがある)が、中止されたとのこと。

AIチップは、最先端の半導体バイス工場でしか生産できない。すでに衰退している日本の状況が心配である。AIチップの話をされた名古屋大学の先生は、設計したチップの製造を台湾のTSMC社に委託しているとのことである。悲しい話ではないか。

クラウドはもはや時代遅れで、あるべき姿はエッジということかもしれない。それも、AIマシン専用の電源が必要な設備ではなく、パソコンレベルでもなく、スマホレベルでもなく、ゆくゆくは、チップレベルということになるのか。

AIチップの開発は、世界中で競争が激化しているようだ。先を走っていたNVIDIAGoogleも安閑とはしていられないくらい多くの企業が参入しているようだ。

我に返ると、TPUを使うプログラムを書いたことがないというのは、もはや、時代遅れということになる。なんとかしないといけない。

 

<雑談>

コンペへの取り組み方:

これまでの取り組み方の全てを用い、どれかを捨てるということはしない。捨ててきたものとして、「ゼロからモデルを組み立てる」というのがある。これを捨ててきた理由は、コンペによって得るものが殆どない、すなわち、自前のプログラム作成に固執すると、プロや研究者の高度なプログラミング技術を学ぶ機会が殆どないまま、完成度もレベルも低いコードをつくることに終始していたことから脱却したいとの思いを強くしたからである。

しかし、公開コードをベースにしてコンペに参加すると、自らコードを作り上げていく際に必要となるデータの扱い方、metricsの理解とそのコードへの反映、特徴量の理解、判断、抽出方法など、課題毎に異なる様々な状況や要因を把握し理解する能力を養い向上させる機会が得られないなど、マイナス要素が大きく、プログラミング能力向上の機会が大きく損なわれている。

Kaggleコンペから、エキスパート、マスター、グランドマスターに認証されるだけの事をなす能力を獲得することは容易ではなく、重要であり、その過程で学ぶものは多いと予想されるが、その過程で獲得していくさまざまな技能や技術は、基本的には、他者が開拓、開発したものであることが大半であろうと推測される。

そのレベルに達してから考えるべきことかもしれないが、そのレベルに達するための道は複数あって、どの道をたどるかによって、同じランクであっても、質的に異なることは想像に難くない、というか、コンペに参加してきた経験から、容易に想像できる。

自分がそうありたいと思うあるべき姿は、明確に、かつ、継続的に意識し続けなければならない。それは、資格、技能、技術、理論、哲学、倫理、思想、のどれにも偏ることなく追求し続けていきたいと思う。息絶えるまで。

 

micro-cource:Computer Vision

In this course, you'll:

  • Use modern deep-learning networks to build an image classifier with Keras
  • Design your own custom convnet with reusable blocks
  • Learn the fundamental ideas behind visual feature extraction
  • Master the art of transfer learning to boost your models
  • Utilize data augmentation to extend your dataset

If you've taken the Introduction to Deep Learning course, you'll know everything you need to be successful.

1. The Convolutional Classifier

2. Convolution and ReLU

ReLUは指示されたとおりに使っていただけだったが、ここでの説明と、処理例をみて、納得した。フィルター処理したときには、特徴は浮かび上がるものの、境界がぼやけて見えるのだが、ReLUを通すと、境界が明瞭になる。それは、フィルター処理の後にReLU処理すると行列の負の値がゼロになるためだということで、それが境界を明瞭にしているということがよくわかった。

3. Maximum Pooling

2x2のmaximum poolingを学んだときに、average poolingも紹介されていた。maximum poolingだと、位置がずれる。直観的に、average poolingの方が良いのではないかと思ったが、画像を処理してみると、average poolingは、コントラストが下がり、max poolingはコントラストが上がったので、納得した。

4. The Sliding Window

5. custom Convnets

6. Data Augmentation

 Keras lets you augment your data in two ways.

The first way is to include it in the data pipeline with a function like ImageDataGenerator. The second way is to include it in the model definition by using Keras's preprocessing layers. This is the approach that we'll take. The primary advantage for us is that the image transformations will be computed on the GPU instead of the CPU, potentially speeding up training.

これは知らなかった。training timeを短縮できることは重要だ。

model = keras.Sequential([
    # Preprocessing
                              preprocessing.RandomFlip('horizontal'), # flip left-to-right
                              preprocessing.RandomContrast(0.5), # contrast change by up to 50%
    # Base
                              pretrained_base,
    # Head
                              layers.Flatten(),
                              layers.Dense(6, activation='relu'),
                              layers.Dense(1, activation='sigmoid'),
])

モデルを定義する ところ’model = keras.Sequential’で、最初にimage_transformationの処理、preprocessing.RandomFlip('horizontal')、を行なえばよいということだ。

 

10月26日(月)

RSNA:

明日の午前9時がsubmissionの締め切りだ。

残念だが、作業は終了としたし、メダル圏内に入る可能性もない。

 

 Courses:

今後は、公開コードのフォークと並行して、自分で作成したコードをもってコンペに参加できるように、Kaggleのコースを最大限、活用していく。

要注意

deep learningのCourseで、notebookを実行するとデフォルトでGPUが立ち上がる場合があり、放置しておくと、使ったことになって、気付かないうちに、10時間くらい消費していた。

GPUを使ってdeep learningのtrainをパラメータを変えながら体験できるようになっているためであり、すぐに使えるコードだということの証明でもある。

 

Intro to Deep Learning

知っているつもりで放置していた。あらためて勉強してみよう。

1. A Single Neuron

We could define a linear model accepting three input features ('sugars''fiber', and 'protein') and producing a single output ('calories') like so:

model = keras.Sequential([
                          layers.Dense(units=1, input_shape=[3])

このコースは、tabular dataのみを扱う。

  • apply neural nets to two classic ML problems: regression and classification

2. Deep Neural Networks

Be sure to pass all the layers together in a list, like [layer, layer, layer, ...], instead of as separate arguments.

model = keras.Sequential([
    # the hidden ReLU layers
                        layers.Dense(units=4, activation='relu', input_shape=[2]),
                        layers.Dense(units=3, activation='relu'),
    # the linear output layer 
                        layers.Dense(units=1),
])

F. Cholletさんのテキストから、ずいぶん変わったなと思う。第2版はまだかいな。

A. Geronさんのテキストは第2版でTF2対応になったし、複数の形式で説明している。

3. Stochastic Gradient Descent

4. Overfitting and Underfitting 

full connection modelでも、deepとwideがあるのか。単純に1層あたりのノード数を増やせばwideってあたりまえか。これから意識してみよう。たとえば、線形性が高い場合は幅を拡げる、非線形性が高い場合は深くする。これらは、意識していなかった。

earlystoppingはoverfittingを防ぐものだと思っていたが、underfittingをも防ぐとの記述に目からうろこ。言われてみれば、そうだよな。損失曲線の底付近得を見つけて、その付近で最適モデルになったとみなして、trainingを停止するわけだから。

Early Stopping Callbackは、使い方等がわかったが、GroupShuffleSplitについての説明が見当たらず、全く理解できていない。なぜこの場合に必要なのか、どういう効果があり、どういう作用があるのかなどまったく不明。

5. Dropout and Batch Normalization

 

10月27日(火)

RSNA:

午前9時00分、Final submission deadline 

暫定順位:274位

獲得技術:無

技術向上:無

今後に向けて:おんぼろでもいいから、自前のコードをつくる。

 

Cources:

Intro to Deep Learning

5. Dropout and Batch Normalization

batch normalizationの意味がよくわかった。

CNNでよく使っていたのだが、それほど大きな効果は認められなかった。

入力データの規格化もできるということは、知らなかった。

6. Binary Classification

layers.Dense(1, activation='sigmoid')
model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['binary_accuracy'],
)

 

 

Cources:

 

Feature Engineering

1. Baseline Model

Using this data, how can we use features such as project category, currency, funding goal, and country to predict if a Kickstarter project will succeed?

これらのfeatureからprojectが成功する確率を計算するわけだが、これらのfeatureに、成功の要因がどれだけ含まれているか疑問である。

ラベルは、正解ではなく、結果であり、必然といえる要因が含まれているとは思えない。それでも、ここでは、技術を習得することを優先しないといけない。

Prepare the target column

First we'll convert the state column into a target we can use in a model. Data cleaning isn't the current focus, so we'll simplify this example by:

  • Dropping projects that are "live"
  • Counting "successful" states as outcome = 1
  • Combining every other state as outcome = 0

この作業に異論はない。ターゲットは、プロジェクトが成功するかどうかである。

Prep categorical variables

Now for the categorical variables -- categorycurrency, and country -- we'll need to convert them into integers so our model can use the data. For this we'll use scikit-learn's LabelEncoder. This assigns an integer to each value of the categorical feature.

文字情報を整数に置き換えるのだが、識別子としての意味しかないので、ここに、違和感を感じる。

2. Categorical Encodings

In this tutorial, you'll learn about count encodingtarget encoding, and CatBoost encoding.・・・識別子+αの意味を持たせる方法の説明のようだ。

Count encoding replaces each categorical value with the number of times it appears in the dataset. For example, if the value "GB" occured 10 times in the country feature, then each "GB" would be replaced with the number 10.

categorycurrency, and countryこれらを出現頻度数に置き換えると、AUCが0.7467から0.7486に上がった。

Target encoding replaces a categorical value with the average value of the target for that value of the feature. For example, given the country value "CA", you'd calculate the average outcome for all the rows with country == 'CA', around 0.28. 

これは、おかしいな。ターゲットの値を使っている。train_dataだけで、validation_dataとtest_dataに使わなければtarget leakではないと書かれているが、納得できない。

これを使うとAUCは0.7491になるとのこと。

Finally, we'll look at CatBoost encoding. This is similar to target encoding in that it's based on the target probablity for a given value. However with CatBoost, for each row, the target probability is calculated only from the rows before it.

これを使うとAUCは0.7492になるとのことだが、よくわからん。

3. Feature Generation

4. Feature Selection

 

Lyft

計算終了後のsaveでHDDが容量オーバーで停止した。なんてこった。

条件を変えて計算中に気がついたら停止していた。今日はついてない。

追加学習と思ってちょっと学習させてみたが、ゼロからの学習だったようで、話にならないことが分かった。なにかやろうとすれば、それだけコードを読みにいくので、まったく無駄な作業ということではない。

約3時間かかって、あと10分から20分くらいで終わるはずのところで、また、妨害された気がする。どうも、サーバー側でなにかやらかしている気がする。

Your notebook tried to allocate more memory than is available. It has restarted. 

全く問題ない状態で動いているはずなのに、突然停止した。

腹立つけど、無料だから、文句が言えないな。

午前3時くらいまでかけてcommitする予定だったのだが。

 

10月28日(水)

Lyft

Final submission deadline: November 25

今後の予定

1.train済みモデルを3種類作成し、これらのtrain済みモデルのパラメータをkaggle  datasetsとして保存した後、このパラメータを読み込んでinferenceする。

 

とりあえず、不十分だが、trainしたモデルのパラメータをkaggleのdatasetsにして、inferenceしてみる。

trainingにはかなり時間がかかりそうだ。

2.base_modelを変える。

3.画素数を変える。

 

Cource:

Deep LearningのExerciseは、立ち上げと同時にGPUがOnになるものがある。このとき、別画面でKaggle notebookをGPUで走らせていると、警告なしに、Kaggle notebookは停止する。計算はゼロからやり直しになるので、要注意。

Deep Learning以外のExerciseでも、立ち上げと同時にGPUがOnになるものは、同様の症状が生じるので要注意。

(コンペ間でも、GPU間で衝突すると、計算は即時停止となるので、要注意。)

Feature Engineering

Exercise 1 : 

q_1が要求している解答/正解とSolutionが異なっている。

Solutionを使うと、次に進めなくなる。出来上がるDataFrameの名称が異なる。

 

<雑談>

 画像を解釈するとき、ヒトは、全体から細部へ、細部から全体へ、視野を変えながら眺めまわす。こういうことを実現すれば、高精細な画像と大きなモデルの単純な組み合わせに優るものになるかもしれない。自然言語処理においても、ヒトが翻訳したり作文したり抄録を作成したりする過程をモデルに組み込むことができれば・・・。

 まだまだ単細胞的な働きしかできていないのかもしれないと思って、モデルの高度化を目指した取り組みをしていかないと、と思うのだが、それを実現するには、プログラミング技術が必要である。プログラミングは、Pythonに限る必要はない。適当なものがなければゼロから言語を創ればいいだけのこと。

 画像処理だと、複数の解像度の画像を、複数のモデルで学習/予測するだけでなく、複数の箇所に分割して学習/予測し、複数の標的を探し出し、標的毎に特徴量を抽出し、課題との関連を学習し、・・・。

 

10月29日(木)

MoA:

 

さあ、挑もう、と思っても、意味の分からない文字と数字の羅列。

結局、パラメーター最適化にはまってしまう。

 

10月30日(金)

MoA:

CVの改善を進めるだけなのだが、Lyftのtrainで3日前にGPUを使い果たしたので、tab_dataといえども、feature数が多く、hidden_sizeが比較的大きいNNを使うと、当然であるが、CPUだけでは、時間がかかるが、特定の指標の変化だけなら調べることができて、パラメータの最適化に、ある程度は使える。

NNの1層あたりのユニット層を増やすと、あるところまでは改善され、それ以上では飽和もしくは悪化する。また、NNの層数を増やすと、あるところまでは改善され、それ以上では飽和もしくは劣化する。underfittingとoverfittingの間を動いているだけ。

 

10月31日(土)

MoA:

GPUが使えるようになったので、お気に入りの条件で計算してsubmitしたら、1400-1500位相当であった。public_dataに無理に合わせるのはダメだと言われても、離れすぎているのもダメだし、Train_data(val_data)に合わせすぎるのもダメだしな。

コンペでは、最終的に、2件の投稿しかできないということの意味が、少しづつわかってきたような気がする。コンペが終わってから、あの結果を選んでおけばよかった、などというのは、だめなんだ。

ついこのあいだも、めんどくさいと思って最新の2件を選んだら、弾き飛ばされて、後でよく見たら、ゆうゆうメダル圏内のものがあった。それをsubmitしたときのメモを探して見返してみたら、NNの条件が偏っていたので、もっと汎用的なモデルにするためにパラメータを変えてみる、というメモ書きがあった。しかしながら88件もsubmitしていたのと、データ整理が悪いのと、そのような計算をしていたことを思い出せなかったことなどによって、適切なモデルを選ぶことができなかった。しかし、こういうのは、後出しじゃんけんでしかないだろう。仮に、そのことを思い出し、メモを見ても、そのときのスコア(public LB)では、60%くらいの順位だから、やはり、選ばなかっただろうと思う。

 

Lyft

データ量がハンパないコンペで、私でも使えるコードが公開されると、計算環境の勝負になる。もちろん、トップレベルの人たちの間の競争は、別次元だろうとは思うが。

とりあえず、350kのデータを学習させようとすると、KaggleのGPUで200時間くらいかかりそうだ。貧乏人には手が出せないコンペだな。kaggle kernelを、6時間毎に継いで使おうと思っても、途中データを出力するにはcommitしなければならず、時間が足りない。こういう不満を言うのは、初級レベルだということだ。小さくて速いモデルを探して使うとか、TPUやコラボを使うとか、探せば手段はありそうに思う。さぼっているだけなんだろうな。

 

GPU:初日に12時間25分も使ってしまった。

 

明日から11月だ。

6月中旬のPANDAコンペ、TReNDSコンペから、本格的に、Kaggleに参加した。

2019年のAPTOSが最初のKaggleだったと思うが、F. Cholle氏のテキスト片手にモデルを作成し、commit, submissionしたが、エラーばかりでリーダーボードに載らなかった。

その後もいくつか挑戦していたが、モデルを作ることもできず、submissionもできないことが続いた。

コンペに参加してもsubmissionしない、できない状況は、ARCでも同じだった。アルゴリズムを考えることに熱中し、文献も読み、公開コードにも学んでいたが、結局、submissionできずに終わった。

2020年5月8日に、Kaggleのリーダーボードに載ること、を目標に定めた。

最初から公開コードを使って参加することに躊躇もあった。

その躊躇の気持ちは今も変わらないが、公開コードは、非常に高度な内容を含んでおり、これほどのお手本に直に触れることができるというのは、非常に良い経験になると思っている。

はやく自前のコードで勝負できるようになりたいという思いがあるのだが、公開コードでもまだまだずいぶん先にあるように感じるけれども、コンペの後に出てくるトップクラスのコードは、さらに先をいっているので、コンペ後にGitHubやKaggleのコンペサイトに公開されるトップクラスのコードを時間をかけて理解することもやっていかないとだめである。

AIの学習も、多面的にやっていこう。Kaggle以外も含めて、いろんな方法をensembleしながら進もう。

 

11月につづく

 

f:id:AI_ML_DL:20200930212926p:plain

style=156 iteration=1

f:id:AI_ML_DL:20200930213016p:plain

style=156 iteration=20

f:id:AI_ML_DL:20200930213123p:plain

style=156 iteration=500