AI_ML_DL’s diary

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

Kaggle散歩(2021年6月)

Kaggle散歩(2021年6月)

不特定コンペ

 

6月9日(水)

CommonLit:1,913 teams, 2 months to go

Rate the complexity of literary passages for grades 3-12 classroom use

3-12 classroomの子供たちにとって読みやすいかどうか、読みやすさの程度を推測するモデルを競うもの。機械学習において難問のように思うが、その前に、学校の教師、教育関係者、研究者にとっても評価のわかれる課題のように思う。まだ少し見ただけだが、Kagglerたちのdiscussionも白熱しているようだ。

予測モデルの一例:

https://huggingface.co/transformers/model_doc/roberta.html

以下はこのサイトから引用

Transformers
State-of-the-art Natural Language Processing for Jax, Pytorch and TensorFlow

RoBERTa
Overview
The RoBERTa model was proposed in

RoBERTa: A Robustly Optimized BERT Pretraining Approach

by Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar Joshi, Danqi Chen, Omer Levy, Mike Lewis, Luke Zettlemoyer, Veselin Stoyanov. It is based on Google’s BERT model released in 2018.

It builds on BERT and modifies key hyperparameters, removing the next-sentence pretraining objective and training with much larger mini-batches and learning rates.

The abstract from the paper is the following:

Language model pretraining has led to significant performance gains but careful comparison between different approaches is challenging. Training is computationally expensive, often done on private datasets of different sizes, and, as we will show, hyperparameter choices have significant impact on the final results. We present a replication study of BERT pretraining (Devlin et al., 2019) that carefully measures the impact of many key hyperparameters and training data size. We find that BERT was significantly undertrained, and can match or exceed the performance of every model published after it. Our best model achieves state-of-the-art results on GLUE, RACE and SQuAD. These results highlight the importance of previously overlooked design choices, and raise questions about the source of recently reported improvements. We release our models and code.

自然言語処理はあまりやっていないので少しずつ習得しよう。

 

Coleridge Initiative:1,447 teams, 14 days to go

Coleridge Initiative - Show US the Data, Discover how data is used for the public good

In this competition, you'll use natural language processing (NLP) to automate the discovery of how scientific data are referenced in publications. Utilizing the full text of scientific publications from numerous research areas gathered from CHORUS publisher members and other sources, you'll identify data sets that the publications' authors used in their work.

論文から、情報を抽出する技術?

抽出した情報の正確さや、実験結果の解釈の正確さや、式の導出の正確さなども含めて評価できれば、論文の査読システムとして、論文作成者の手助けとして、役に立つかもしれないが・・・。

これも自然言語処理なので少しずつ習得しようと思っている。

 

Berkeley SETI Research Center:854 teams, 2 months to go

SETI Breakthrough Listen - E.T. Signal Search
Find extraterrestrial signals in data from deep space

Search for ExtraTerrestrial Intelligence:地球外知的生命体の探索

面白そうだな。

 

6月10日(木)

Berkeley SETI Research Center:873 teams, 2 months to go

信号を受信する方向を交互に切り替えれば、特定の方向からなにがしかの信号が放出されていると推定され、その信号を発している主体を、地球外知的生命体とみなすということのようである。

上側の画像は実際にボイジャーからの信号を受け取った物で、ボイジャーの方向と外した方向からの信号を受信している。

下側の画像は、地球外知的生命体が発する信号を模擬したときに検出されるであろう信号を模擬したものである。

そんなに難しい課題ではないように思う。

 

Coleridge Initiative:1,478 teams, 12 days to go

公開コードをコピーして、submitした。これから、コードの内容を学んで、スコアアップにもっていきたい。 

関係ないかもしれないが、Coleridge Initiativeで検索したら、こんな論文があ,った。

Harvard Data Science Review • Issue 3.2, Spring 2021
Enhancing and Accelerating Social Science Via Automation: Challenges and Opportunities

Tal Yarkoni, Dean Eckles, James A. J. Heathers, Margaret C. Levenstein, Paul E. Smaldino, Julia Lane Published on: Apr 30, 2021 DOI: 10.1162/99608f92.df2262f5

 

6月11日(金)

  • Coleridge Initiative
  • 1,483 teams
  • 12 days to go

The objective of the competition is to identify the mention of datasets within scientific publications. Your predictions will be short excerpts from the publications that appear to note a dataset.

引用していると推測される、出版物に掲載されているデータセットを特定して、短い抜粋として記述する。複数のデータセットがあれば、区切り記号を使って示す。

 

Transformersライブラリーに学ぶ

次のようなタスクに分けられている。文献中で使われているデータセットを抽出するにはどうすればよいのだろうか。

・Sentiment analysis: is a text positive or negative?

・Text generation (in English): provide a prompt and the model will generate what follows.

・Name entity recognition (NER): in an input sentence, label each word with the entity it represents (person, place, etc.)

・Question answering: provide the model with some context and a question, extract the answer from the context.

・Filling masked text: given a text with masked words (e.g., replaced by [MASK]), fill the blanks.

・Summarization: generate a summary of a long text.

・Translation: translate a text in another language.

・Feature extraction: return a tensor representation of the text.

要約を作ってみてそこにデータセットの情報が含まれるかどうか調べる。

データセットは何を使っていますか?と聞いて答えさせる。

質問の仕方によって答えは違ってくるかもしれないが、試してみる価値はありそう。

この文献は*****を参考にして書かれています。という文章の*****の部分の穴埋めをさせてみる。

固有表現抽出の方法(まだ理解できていないが)を使って、単語以上、文章以下の単語のクラスター(句)が表すエンティティ―のラベルを付けて、データセットに相当するものを引き出す。

dataset_titleと類似した句を抽出する。 

明日は、Transformersライブラリーの学習を進めるとともに、Transformersライブラリーを使っている公開コードを探し、あれば、それに学びながら、スコアアップの方法を探っていこう。

 

6月12日(土)

Coleridge Initiative:1,495 teams, 11 days to go

BERTの論文:

BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
Jacob Devlin, Ming-Wei Chang, Kenton Lee and Kristina Toutanova, Google AI Language arXiv:1810.04805v2 [cs.CL] 24 May 2019

 Abstract
We introduce a new language representation model called BERT, which stands for
Bidirectional Encoder Representations from Transformers. Unlike recent language representation models (Peters et al., 2018a; Radford et al., 2018), BERT is designed to pretrain deep bidirectional representations from unlabeled text by jointly conditioning on both left and right context in all layers. As a result, the pre-trained BERT model can be finetuned with just one additional output layer to create state-of-the-art models for a wide range of tasks, such as question answering and language inference, without substantial taskspecific architecture modifications.

トランスフォーマーからの双方向エンコーダー表現を表すBERTと呼ばれる新しい言語表現モデルを紹介します。 最近の言語表現モデル(Peters et al。、2018a; Radford et al。、2018)とは異なり、BERTは、すべてのレイヤーで左右両方のコンテキストを共同で調整することにより、ラベルのないテキストから深い双方向表現を事前トレーニングするように設計されています。 その結果、事前にトレーニングされたBERTモデルを1つの追加出力レイヤーで微調整して、質問応答や言語推論などの幅広いタスク用の最先端のモデルを作成できます。タスク固有のアーキテクチャを大幅に変更する必要はありません。by Googlr翻訳

A.3 Fine-tuning Procedure
For fine-tuning, most model hyperparameters are the same as in pre-training, with the exception of the batch size, learning rate, and number of training epochs. The dropout probability was always kept at 0.1. The optimal hyperparameter values are task-specific, but we found the following range of possible values to work well across all tasks:
• Batch size: 16, 32                                 • Learning rate (Adam): 5e-5, 3e-5, 2e-5
• Number of epochs: 2, 3, 4

このファインチューニング条件が目にとまり、かつ、ここに転載する理由は、開催中のCommonLitコンペにおいて、でtransformerモデル(model = AutoModelForSequenceClassification.from_pretrained)を用いたtrainingのハイパーパラメータが、ほぼ、この条件に合っていて、これを外すとトレーニングがうまくいかなったことがあったからである。

transformers v.4.6.0:

Sequence Classification:

>>> tokenizer = AutoTokenizer.from_pretrained("bert-base-cased-finetuned-mrpc")
>>> model = AutoModelForSequenceClassification.from_pretrained("bert-base-cased-finetuned-mrpc")

Extractive Question Answering:

>>> tokenizer = AutoTokenizer.from_pretrained("bert-large-uncased-whole-word-masking-finetuned-squad")
>>> model = AutoModelForQuestionAnswering.from_pretrained("bert-large-uncased-whole-word-masking-finetuned-squad")

Language Modeling:

Language modeling is the task of fitting a model to a corpus, which can be domain specific. All popular transformer-based models are trained using a variant of language modeling, e.g. BERT with masked language modeling, GPT-2 with causal language modeling.

Language modeling can be useful outside of pretraining as well, for example to shift the model distribution to be domain-specific: using a language model trained over a very large corpus, and then fine-tuning it to a news dataset or on scientific papers e.g. LysandreJik/arxiv-nlp.

Masked Language Modeling:

>>> tokenizer = AutoTokenizer.from_pretrained("distilbert-base-cased")
>>> model = AutoModelWithLMHead.from_pretrained("distilbert-base-cased")

Causal Language Modeling:

>>> tokenizer = AutoTokenizer.from_pretrained("gpt2")
>>> model = AutoModelWithLMHead.from_pretrained("gpt2")

Text Generation:

>>> model = AutoModelWithLMHead.from_pretrained("xlnet-base-cased")
>>> tokenizer = AutoTokenizer.from_pretrained("xlnet-base-cased")

Named Entity Recognition:

>>> model = AutoModelForTokenClassification.from_pretrained("dbmdz/bert-large-cased-finetuned-conll03-english")
>>> tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

Summarization:

Summarization is the task of summarizing a document or an article into a shorter text. If you would like to fine-tune a model on a summarization task, you may leverage the run_summarization.py script.

>>> model = AutoModelWithLMHead.from_pretrained("t5-base")
>>> tokenizer = AutoTokenizer.from_pretrained("t5-base")

Translation:

Translation is the task of translating a text from one language to another. If you would like to fine-tune a model on a translation task, you may leverage the run_translation.py script.

>>> model = AutoModelWithLMHead.from_pretrained("t5-base")
>>> tokenizer = AutoTokenizer.from_pretrained("t5-base")

>>> inputs = tokenizer.encode("translate English to German: Hugging Face is a technology company based in New York and Paris", return_tensors="pt")
>>> outputs = model.generate(inputs, max_length=40, num_beams=4, early_stopping=True)

>>> print(tokenizer.decode(outputs[0]))
Hugging Face ist ein Technologieunternehmen mit Sitz in New York und Paris.

ゼロからコードを書くことができればよいのだが、そうはいかないので、公開コードを探そう。なかなか良さそうなのがみつからない。

BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension
Mike Lewis, Yinhan Liu, Naman Goyal, Marjan Ghazvininejad, Abdelrahman Mohamed, Omer Levy, Ves Stoyanov, and Luke Zettlemoyer, Facebook AI                arXiv:1910.13461v1 [cs.CL] 29 Oct 2019

BERTと間違ったのかと思ったら、BARTというのも別にあって驚いた、というくらいこの分野には疎い。

In this paper, we present BART, which pre-trains a model combining Bidirectional and Auto-Regressive Transformers. BART is a denoising autoencoder built with a sequence-to-sequence model that is applicable to a very wide range of end tasks. Pretraining has
two stages (1) text is corrupted with an arbitrary noising function, and (2) a sequence-to-sequence model is learned to reconstruct the original text. BART uses a standard Tranformer-based neural machine translation architecture which, despite its simplicity, can be seen as generalizing BERT (due to the bidirectional encoder), GPT (with the left-to-right decoder), and many other more recent pretraining schemes (see Figure 1).

この論文では、双方向トランスフォーマーと自己回帰トランスフォーマーを組み合わせたモデルを事前トレーニングするBARTを紹介します。 BARTは、シーケンス間モデルで構築されたノイズ除去オートエンコーダです。
非常に幅広いエンドタスクに適用できます。 事前トレーニングには2つの段階があります(1)テキストは任意のノイズ処理機能で破損し、(2)シーケンス間モデルは元のテキストを再構築するために学習されます。 BARTは、標準のTranformerベースのニューラル機械翻訳アーキテクチャを使用します。これは、その単純さにもかかわらず、BERT(双方向エンコーダーによる)、GPT(左から右へのデコーダーを使用)、およびその他の多くの最近の事前トレーニングスキームを一般化したものと見なすことができます。 (図1を参照)by Google翻訳

f:id:AI_ML_DL:20210612202405p:plain

とりあえず、こんな感じ。 GPT --> BERT --> BART

 

6月13日(日)

CommonLit:2,031 teams, 2 months to go

CommonLiコンペはテキストの一節からテキストの読みやすさを数値化する(3学年から12学年の範囲内に該当するか否かをRMSE値で評価する)。

モデルはbert, roberta-base, roberta-largeなど。overfittしやすく、最適エポック数は少ない。エポック数では調節しずらく、ステップ数で評価している人もいるようだ。

現時点では公開コードを借用すれば銀~銅メダル圏内だが、現状の公開コードをそのまま使っただけでは、8月2日の最終日までには、追い出されているだろうな。それまでに、公開コードに学んでスコアアップの手段を探さないとだめだろうな。

 

Coleridge Initiative:1,514 teams, 10 days to go

今見ている公開コードにliteral matchingという項目がある。単純に、文字合わせ、ということだろうか。 

 

6月14日(月)

Google:443 teams, 2 months to go

Google Smartphone Decimeter Challenge
Improve high precision GNSS positioning and navigation accuracy on smartphones 

Global Navigation Satellite System (GNSS) provides raw signals, which the GPS chipset uses to compute a position. Current mobile phones only offer 3-5 meters of positioning accuracy. While useful in many cases, it can create a “jumpy” experience. For many use cases the results are not fine nor stable enough to be reliable.

グローバルナビゲーション衛星システム(GNSS)は、GPSチップセットが位置を計算するために使用する生の信号を提供します。 現在の携帯電話は、3〜5メートルの測位精度しか提供していません。 多くの場合便利ですが、「ジャンピー」な体験を生み出すことができます。 多くのユースケースでは、結果は良好ではなく、信頼できるほど安定していません。by Google翻訳

In this competition, you'll use data collected from the host team’s own Android phones to compute location down to decimeter or even centimeter resolution, if possible. You'll have access to precise ground truth, raw GPS measurements, and assistance data from nearby GPS stations, in order to train and test your submissions.

このコンテストでは、ホストチームのAndroidスマートフォンから収集したデータを使用して、可能であればデシメートルまたはセンチメートルの解像度まで位置を計算します。 提出物をトレーニングおよびテストするために、正確なグラウンドトゥルース、生のGPS測定値、および近くのGPSステーションからの支援データにアクセスできます。by Google翻訳

Fast Kalman filters in Python leveraging single-instruction multiple-data vectorization. That is, running n similar Kalman filters on n independent series of observations. Not to be confused with SIMD processor instructions.

カルマンフィルターは、 離散的な誤差のある観測から、時々刻々と時間変化する量(例えばある物体の位置と速度)を推定するために用いられる。レーダーやコンピュータビジョンなど、工学分野で広く用いられる。例えば、カーナビゲーションでは、機器内蔵の加速度計や人工衛星からの誤差のある情報を統合して、時々刻々変化する自動車の位置を推定するのに応用されている。カルマンフィルターは、目標物の時間変化を支配する法則を活用して、目標物の位置を現在(フィルター)、未来(予測)、過去(内挿あるいは平滑化)に推定することができる。by Wikipedia

内容を理解するために、何日もかかりそう。

TPU仕様の公開コードを借りて、計算してみた。公開コードのスコアはLB=6.752なので、そのまま走らせて、同程度のスコアになることを確認した。

次に、GPUで走らせてみた。TensorFlow/Kerasで書かれているので、TPUを指定するコードは少なく、容易に変更できる。しかし、スピードが違う。TPU前提なので5 Foldで、エポック数が最大100に設定されている。とてもでないがGPUでは無理。と思ってテストのつもりで3エポックに設定してみたら、LB=0.676になった。それではと、6エポックに増やしたら、NNの学習は進んだはずなのだが、LB=0.701となってしまった。コードを理解しながら前進しよう。

 

6月15日(火)

Berkeley SETI Research Center:942 teams, a month to go

Image Size vs Scoreというタイトルで情報のやりとりが行われている。画像解像度が高いほどスコアは高い傾向にある。コードコンペではないので、使える計算資源による差が現れやすい。What's your best single model?ここでも画像サイズが話題になり、大きな画像で良いスコアだが、Kaggle kernelでは動かないという話。最後には、アンサンブルの話。

 

Coleridge Initiative:1,521 teams, 7 days to go

このコンテストでは、自然言語処理NLP)を使用して、出版物で科学データがどのように参照されているかを自動的に検出します。CHORUS出版社のメンバーやその他の情報源から収集された多数の研究分野からの科学出版物の全文を利用して、出版物の著者が彼らの仕事で使用したデータセットを特定します。by Google翻訳

1対の、train_dataの全文に目を通して、train_labelがどこに、どのように書かれているかを調べてみた。

test_dataを読んで、公開コードの推測結果が、求めているデータセットに該当するかどうか調べてみた。ANDIはデータセットではないように思う。BERT-MLMによる推測結果は、Lothian Birth Cohort Studyで、研究成果ではあるがデータセットと呼べるようなものでもなさそうだ。難しい。

 

6月16日(水)

Major League Baseball:148 teams, 2 months to go

MLB Player Digital Engagement Forecasting
Predict fan engagement with baseball player digital content

engagementが何を意味しているのかが、わからない。

In this competition, you’ll predict how fans engage with MLB players’ digital content on a daily basis for a future date range. You’ll have access to player performance data, social media data, and team factors like market size. Successful models will provide new insights into what signals most strongly correlate with and influence engagement.

このコンテストでは、ファンがMLBプレーヤーのデジタルコンテンツを将来の日付範囲で毎日どのように利用するかを予測します。 プレーヤーのパフォーマンスデータ、ソーシャルメディアデータ、市場規模などのチーム要因にアクセスできます。 成功したモデルは、どのシグナルがエンゲージメントと最も強く相関し、影響を与えるかについての新しい洞察を提供します。by Google翻訳

engage, engagementの意味がよくわからない。

 

6月17日(木)

Google Smartphone Decimeter Challenge:474 teams, 2 months to go

Our team is currently using only post processing to improve the accuracy.                      We have found that the order of post processing changes the accuracy significantly, so we share the results.

ポストプロセスに関する手順と効果に関するDiscussionが行われている。

 

6月18日(金)

Berkeley SETI Research Center:1,001 teams, a month to go

There are just a few of us data scientists at Kaggle launching about 50 competitions a year with many different data types over a very wide range of domains. Worrying about leakage and other failure points keeps us up at night. We absolutely value our community's time and effort and know how important it is to have fun and challenging competitions.

残念なことに、リークがあったようだ。 Kaggle staffは、このようなトラブルが生じないように少ないメンバーで日夜頑張っておられるのだ!

もうすぐ消されると思うが、LBには、1.000が45件、0.999が75件ほど並んでいる。タイミングが合えば、自分もそこに並ぼうとしただろうな。残念なことだが。

いち早くリークに気付いて公開し、Kaggleスタッフと協力して原因究明にあたろうとするKagglerたちがいる。こういう人たちがKaggleを支えているのだろう。

  

6月19日(土)

Major League Baseball:194 teams, a month to go

このコンペは通常のコンペとはかなり異なるように思う。それが顕著に分かるのは、Timelineである。Training TimelineとEvaluation Timelineに分かれている。

Training Timelineにおいては、Final Submission Deadlineの約1.5週間前に、Training Setが更新されるということが書かれている。

Evaluation Timelineにおいては、以下の説明がされている。

最終提出期限後から、このコンテストの評価期間の将来の日付範囲を反映するためにリーダーボードが定期的に更新されます。その時点で、各チームが選択したノートブックがその将来のデータで再実行されます(9月15日にコンテストが終了)。これらの再実行には、2021年7月31日までに更新されたトレーニングデータが含まれます。by Google翻訳

以上のように、7月20前後にTraining Setが更新され、提出締切後には更新データによるスコアの逐次変化が9月15日まで続くので、現時点におけるスコアには、ほとんど意味が無さそうだということになる。

 

6月20日(日)

Major League Baseball:228 teams, a month to go

As this competition is brought to you in collaboration with the launch of Vertex AI, we're providing GCP coupons for users to try out some of the great, powerful new resources made available through Vertex AI. This includes JupyterLab Notebooks, Explainable AI, hyperparameter tuning through Vizier, and countless other AI training and deployment tools.

このコンテストはVertexAIのリリースと共同で開催されるため、ユーザーがVertexAIを通じて利用できる優れた強力な新しいリソースのいくつかを試すためのGCPクーポンを提供しています。 これには、JupyterLab NotebooksExplainable AIVizierによるハイパーパラメータ調整、およびその他の無数のAIトレーニングおよび展開ツールが含まれます。by Google翻訳

Vertex AI

Vertex AI brings AutoML and AI Platform together into a unified API, client library, and user interface. AutoML allows you to train models on image, tabular, text, and video datasets without writing code, while training in AI Platform lets you run custom training code. With Vertex AI, both AutoML training and custom training are available options. Whichever option you choose for training, you can save models, deploy models and request predictions with Vertex AI.

Vertex AIは、AutoMLとAIプラットフォームを統合されたAPI、クライアントライブラリ、およびユーザーインターフェイスに統合します。 AutoMLを使用すると、コードを記述せずに画像、表、テキスト、およびビデオのデータセットでモデルをトレーニングできます。AIプラットフォームでのトレーニングでは、カスタムトレーニングコードを実行できます。 Vertex AIでは、AutoMLトレーニングとカスタムトレーニングの両方が利用可能なオプションです。 トレーニングにどのオプションを選択しても、Vertex AIを使用してモデルを保存し、モデルをデプロイし、予測をリクエストできます。by Google翻訳

JupyterLab is a next-generation web-based user interface for Project Jupyter.

Notebooks enables you to create and manage virtual machine (VM) instances that are pre-packaged with JupyterLab.

Notebooks instances have a pre-installed suite of deep learning packages, including support for the TensorFlow and PyTorch frameworks. You can configure either CPU-only or GPU-enabled instances, to best suit your needs.

Your Notebooks instances are protected by Google Cloud authentication and authorization, and are available using a Notebooks instance URL. Notebooks instances also integrate with GitHub so that you can easily sync your notebook with a GitHub repository.

Notebooks saves you the difficulty of creating and configuring a Deep Learning virtual machine by providing verified, optimized, and tested images for your chosen framework.

Introduction to Vertex Explainable AI for Vertex AI 

 

6月23日(水)

Coleridge Initiative:1,610 teams, 5 hours ago

今朝終了した。暫定420位であった。投稿したモデルの中には、170-177位相当のものもあったが、そのモデルは、public_LBが良くなかったことと、そのモデルの計算方法が他のモデルよりも良いと判断することができず、最終投稿の2件に選ぶことができなかった。161位以内がメダル圏内だったので惜しかったと思うが、そのモデルの詳細が理解できず、private_LBが少し良かったのは偶然にすぎない。夜中(早朝)に、新たにデータセットを追加して計算したものは、データセットに過剰適合して、全滅だった。憶測にすぎないが、特定のデータセットを用いた場合に、public_LBスコアが非常に高くなることを誰かが見つけたことによって、自分を含め、多くのチームが、自然言語処理本来の機能よりも、データセットへの適合に注意が向きすぎたのではなかろうか。

 

6月24日(木)

CommonLit:2,402 teams, a month to go

チューニングのみ。

Google:519 teams, a month to go 

チューニングのみ。

*チューニングのみでは、進歩しない。Discussionで、次のようなアドバイスをしている人がいた。公開コードのコピーは大いにやればよい。ただし、単にコピーして実行し、投稿するのではなく、自分の力量に合ったモデルを探し、そこからモデルのレベルアップを図りながらスコアアップしていくのが望ましい。

 

6月25日(金)

CommonLit:2,451 teams, a month to go (チューニングで50位)

Discussion:Readability(読みやすさ)とは何かを問うている。

まずは、Discussionを読まずに、自分の頭にあることを引き出してみよう。読みやすい文章は、わかりやすい文章である。わかりやすい文章は、易しい単語を使っている。わかりやすい文章は短い。わかりやすい文章は構文が簡単である。わかりやすい文章は単純である。わかりやすい文章は主語と述語を含んでいる。わかりやすい文章は論理が単純である。わかりやすい文章は具体的である。わかりやすい文章は理解しやすい。わかりやすい文章は直接的である。読みやすい。わかりやすい。理解しやすい。単純である。論理的である。論理が単純である。読みやすい文章は、知っている言葉、事柄、だけを含んでいる。学習した事、知っている事、覚えている事について書かれている。

Discussionを読んでみよう。困ったことに、英語は自分にとってreadabilityが悪い。英語であることが問題なのではなく、readabilityの評価法や評価方法の課題や問題点に関する知識が少ないために理解できないか理解するのに時間がかかるのだ。文章が表現している事柄に関する知識が無いと読めない。domain knowledgeというのかな、領域知識が必要なのだが、今は、WikipediaGoogle Scholarがあるので便利になった。読みやすい文章は、domain knowledgeを含まず、general knowledgeだけを含む文章ということで良いのか。general knowledgeにも、レベルがある。ここで問われているのは、これ、すなわち、general knowledgeのレベルを判定することになるのかもしれない。Wikipediaを見ると、common knowledgeと混同しないようにとの注意書きがある。domain knowledgeとgeneral knowledgeとcommon knowledgeは互いに重なっている部分があるように思う。Discussionとは違うところに来てしまった。

Discussionに戻る。readabilityは、これまで蓄積されたdomain knowledgeによって定義され、評価尺度も決められている。今は、train_dataをモデルに学ばせて、忠実に再現することが求められているだけ。期待は、分散を小さくし、readabilityの評価精度を上げることだろうと思うが、そんなことしてもスコアは上がらないだろうと思う。train_dataセットが全て!だろうと思う。本当に求めているのはそこではないが、今は、幻想でしかない。

100年先の世界から振り返れば、2021年も、toy problemに四苦八苦していた時代ということになるのだろう。それとも、ヒトが優れた知能を有していると思っていること自体が幻想であって、ヒトがやっていること(知的活動であると思っていること)は、ANNによって、すでに、忠実に再現されているだけでなく、ANNは、ヒトのレベルを超えようとしているのかもしれない。100年先、1000年先の人類は何を達成し、何を求めているだろうか。

 

6月29日(火)

Optiver:31 teams, 3 months to go

Optiver Realized Volatility Prediction
Apply your data science skills to make financial markets better

概要(自動翻訳)

この競争の最初の3か月で、さまざまなセクターにわたる数百の株式の短期的なボラティリティを予測するモデルを構築します。数億行の非常に詳細な財務データをすぐに利用できるようになり、10分間のボラティリティを予測するモデルを設計できます。モデルは、トレーニング後3か月の評価期間に収集された実際の市場データに対して評価されます。

Volatility(自動翻訳)

ボラティリティは、あらゆるトレーディングフロアで耳にする最も顕著な用語の1つであり、それには正当な理由があります。金融市場では、ボラティリティが価格の変動量を捉えます。ボラティリティが高いと、市場が混乱し、価格が大きく変動します。ボラティリティが低いと、市場はより穏やかで静かになります。オプティバーのようなトレーディング会社にとって、ボラティリティを正確に予測することは、オプションの取引に不可欠です。オプションの価格は、原商品のボラティリティ直接関係しています。

金融関係のコンペは敬遠していたが、参加しなければ何も得られず、参加すれば、domain knlowledge、train_data、予測モデルなどの概略に関する知識を得る機会が増えるので、散歩コースに加えることにした。

XGBRegressorを使った公開コードを使ってみた。

lightgbm.LGBMRegressorを使ってみようかな。

 

6月30日(水)

Optiver:147 teams, 3 months to go

まだ始まったばかり。参加チーム数は147と少ないので、50位以内に入った!

XGBをLGBMに変えてスコアは良くなったが、偶然にすぎないと思っている。これから、課題に合わせてチューニングしようと思う。

generalizeが重要な課題、specializeが重要な課題、accuracyが重要な課題、・・・

これらが混ざり合っていて、その寄与率は、課題によって異なる。 

画像診断の多くは、異常を見逃さないことが重要であることから、真剣に取り組む気になるが、課題によっては、真剣に取り組むのが馬鹿らしく思えてくるようなものもある。スコアを争っていると、本来の目的を忘れてしまうことがある。やりがいを感じて取り組んでいても、スコアが上がらないと興味を失うことがある。どうでもいいテーマでも、スコアが上がると、必死に取り組んで、時間を忘れることがある。ゲームに夢中になっている子供みたいに。Kaggle病にかかってしまったかな。

 

f:id:AI_ML_DL:20210609104123p:plain

style=167 iteration=500

 

 

 

Kaggle散歩(2021年6月1日~8月10日:SIIM-FISABIO-RSNA COVID-19 Detection)

2021年6月1日~8月10日:

SIIM-FISABIO-RSNA COVID-19 Detection

Identify and localize COVID-19 abnormalities on chest radiographs

今日から2か月と10日間、このコンペに取り組む。

このコンペは、コンペ内の全てのcodeとdiscussionを見て学ぶことに集中する。

In this competition, you’ll identify and localize COVID-19 abnormalities on chest radiographs.

In particular, you'll categorize the radiographs as negative for pneumonia or typical, indeterminate, or atypical for COVID-19.

You and your model will work with imaging data and annotations from a group of radiologists.

 

6月1日(火)

Society for Imaging Informatics in Medicine (SIIM):281 teams, 2 months to go 

概要:胸部レントゲン写真からCOVID-19感染者の症状を推測する。

discussion:

過去の類似コンペのトップレベルの解法の紹介がある。 

データサイズは約120 GB。画像サイズが大きくてそのままでは扱えないので、1000 x 1000以下のサイズに縮小し、データセットにして公開している人がいる。非常にありがたい。データセット作成に用いたコードが公開されているので、それを参考にして、自分で準備することも良い練習となる。

ケロッピアバターGMさんが、starter kitを作成しますと宣言。BMSコンペでも行っていて、トップ100位以内のレベルのコードを公開しており、当人のチームは20位以内のハイレベル。

ベストスコアのコードを検索。trainも公開されているコードを探す。この時点では、学ぶだけ。

ベストスコアで検索し、スコアは低いが正確なコードを選び、コピー、実行、commit, submitにより、リーダーボードの下位に顔を出す。LB=0.005

 

6月2日(水)

Society for Imaging Informatics in Medicine (SIIM):291 teams, 2 months to go

Evaluation

standard PASCAL VOC 2010 mean Average Precision (mAP) at IoU > 0.5を用いる。

In this competition, we are making predictions at both a study (multi-image) and image level.:スタディ(マルチ画像)画像レベルの両方で予測、となってる。

Study-level labelsとImage-level labelsがある。

train_study_level.csvとtrain_image_level.csvの2つのファイルがある。

Study-level labels

Studies in the test set may contain more than one label. They are as follows:

"negative", "typical", "indeterminate", "atypical"

For each study in the test set, you should predict at least one of the above labels.

The format for a given label's prediction would be a class ID from the above list, a confidence score, and 0 0 1 1 is a one-pixel bounding box.

Study-level labelsのSubmission Fileへの出力例

Id,            PredictionString

2b95d54e4be65_study,  negative 1 0 0 1 1
2b95d54e4be66_study,  typical 1 0 0 1 1
2b95d54e4be67_study,  indeterminate 1 0 0 1 1 atypical 1 0 0 1 1

Image-level labels

Images in the test set may contain more than one object.

For each object in a given test image, you must predict a class ID of "opacity", a confidence score, and bounding box in format xmin ymin xmax ymax.

If you predict that there are NO objects in a given image, you should predict none 1.0 0 0 1 1, where none is the class ID for "No finding", 1.0 is the confidence, and 0 0 1 1 is a one-pixel bounding box.

Image-level labelsのSubmission Fileへの出力例

Id,             PredictionString

2b95d54e4be68_image,  none 1 0 0 1 1
2b95d54e4be69_image,  opacity 0.5 100 100 200 200 opacity 0.7 10 10 20 20

以上のように、スタディレベル("negative", "typical", "indeterminate", "atypical")と、イメージレベル("non", "opacity")の2つに分けられている。

 

公開コード(train)(EfficientNetB7使用、TPUで動作)のチューニングをやってみた。

Dropoutの導入、全結合層の導入、EfficientNetのサイズの変更、バッチサイズ、学習率の初期値などの変更を検討した。

今日は、オリジナルを超える結果は得られなかった。

TPUの代わりにGPUを使ってみた。EfficientNetB7は使えず、B4に変更した。画像も600 pixelではオーバーフローする。とりあえず、動かそうと思い、224 pixelにすれば、余裕で動くのだが、これが、非常に遅い。

あまりに遅いので、B0に変更して、5Foldまで計算してみた。B7に600 pixelの画像を流すのとは比較にならないだろうと思ったが、予測モデルをデータセットにしてinferenceコードに追加して予測した結果をsubmitしてみたところ、スコアの数値としては比較的近い値となった。

オリジナル:B7 & 600 pixel & TPU --> LB=0.383

変 更  :B0 & 224 pixel & GPU --> LB=0.373

良いモデルは、どう扱っても、そこそこのスコアになるものだが、B7 --> B0と、600 pixel --> 224 pixelとグレードダウンしても、LBスコアが大きくは下がらなかったことに驚いている。

 

コンペの問題点

このコンペは、スタディレベル("negative", "typical", "indeterminate", "atypical")と、イメージレベル("non", "opacity")の2つの組み合わせ(病状の分類と病状箇所の検出)になっているのだが、イメージレベルの予測結果に対して、評価ミスが生じているようだ。イメージレベルの予測結果を追加・削除してcommitすることによって、イメージレベルの予測データの寄与は、LB=0.001あるいはLB=0.051となったとのこと)両方の寄与が五分五分だと仮定すると、LBスコアは、現在の0.4+レベルではなく倍の0.8+レベルになっていなければならない、ということのようである。

ということで、現状のリーダーボードは、ほぼ、スタディーレベルだけの評価になっている。Kaggle StaffのJulia Elliottさんによれば、来週には改善される予定。

このため、いまだ、参加チームが少ない、ということなのかもしれない。

 

6月3日(木)

Society for Imaging Informatics in Medicine (SIIM):312 teams, 2 months to go

公開コード使用:B0 & 224 pixel & GPU--> LB=0.373

このコードはスタディーレベル(分類)専用なので、これ以上やっても意味ないかなとは思うのだが、イメージレベル(検出)は使うモデルが違うので(EfficientDetは両方できる?)今は、スタディーレベルの課題に集中しよう。

 

224 pixel & GPUで、Lrを変えたり、factor(学習率の減衰率)を変えたり、さらにはB0からB1やB2もやってみたが、途中経過がよくなかったので、最後まで計算せずに終えたこともあって、今日は、LB=0.373を超えることはなかった。

 

HuBMAPでは、Super-Convergenceを期待して、CyclicLRとOneCycleLRを使っていたので、ここでも使ってみようと思ったのだが、今使っているコードはTensorFlow/Kerasなので、このようなモジュールは無い。

Kerasで検索しても似たようなものは無かったが、TensorFlowに、Useful extra functionality for TensorFlow maintained by SIG-addons.というのがあり、そこに同等のモジュールがあった。

 

Module: tfa.optimizers

class AdamW: Optimizer that implements the Adam algorithm with weight decay.

class AveragedOptimizerWrapper: Base class for Keras optimizers.

class COCOB: Optimizer that implements COCOB Backprop Algorithm

class ConditionalGradient: Optimizer that implements the Conditional Gradient optimization.

class CyclicalLearningRate: A LearningRateSchedule that uses cyclical schedule.

class DecoupledWeightDecayExtension: This class allows to extend optimizers with decoupled weight decay.

class ExponentialCyclicalLearningRate: A LearningRateSchedule that uses cyclical schedule.

class LAMB: Optimizer that implements the Layer-wise Adaptive Moments (LAMB).

class LazyAdam: Variant of the Adam optimizer that handles sparse updates more

class Lookahead: This class allows to extend optimizers with the lookahead mechanism.

class MovingAverage: Optimizer that computes a moving average of the variables.

class MultiOptimizer: Multi Optimizer Wrapper for Discriminative Layer Training.

class NovoGrad: Optimizer that implements NovoGrad.

class ProximalAdagrad: Optimizer that implements the Proximal Adagrad algorithm.

class RectifiedAdam: Variant of the Adam optimizer whose adaptive learning rate is rectified

class SGDW: Optimizer that implements the Momentum algorithm with weight_decay.

class SWA: This class extends optimizers with Stochastic Weight Averaging (SWA).

class Triangular2CyclicalLearningRate: A LearningRateSchedule that uses cyclical schedule.

class TriangularCyclicalLearningRate: A LearningRateSchedule that uses cyclical schedule.

class Yogi: Optimizer that implements the Yogi algorithm in Keras.

 

明日は、CyclicalLearningRateを使ってみようと思う。

tfa.optimizers.CyclicalLearningRate(
     initial_learning_rate: Union[FloatTensorLike, Callable],
     maximal_learning_rate: Union[FloatTensorLike, Callable],
     step_size: tfa.types.FloatTensorLike,
     scale_fn: Callable,
     scale_mode: str = 'cycle',
     name: str = 'CyclicalLearningRate'
)

SGD(0.1-2.0)を想定して具体的な数値を入力した例:

clr = tfa.optimizers.CyclicalLearningRate(0.1, 2.0,
step_size=10, 
scale_fn=lambda x: 1,
scale_mode= 'cycle',
name= 'CyclicalLearningRate'
)

 

<雑談>AI, Machin Learning, Deep Learning, Data Science, Engineer or Scientist or  Programmer, Kaggler:これらの単語からイメージされる領域で、自分が目指す方向を表現するのに適しているのは何か。AIは、漠然としていてつかみどころがない。Data Scienceは、自分の中では前処理のイメージが強い。Wikipediaで調べてみよう。

Data science is an interdisciplinary field that uses scientific methods, processes, algorithms and systems to extract knowledge and insights from structured and unstructured data,[1][2] and apply knowledge and actionable insights from data across a broad range of application domains. Data science is related to data mining, machine learning and big data.

Data Scienceは、Machin Learning、Deep Learningだけでなく、あらゆる科学技術分野に対して、横断的に関連しているものと捉えることができるもののようである。

自分にはなじみの薄い用語、data miningについてもWikipediaで調べてみよう。

Data mining is a process of extracting and discovering patterns in large data sets involving methods at the intersection of machine learning, statistics, and database systems.[1] Data mining is an interdisciplinary subfield of computer science and statistics with an overall goal to extract information (with intelligent methods) from a data set and transform the information into a comprehensible structure for further use.

勝手な解釈かもしれないが、data mining + big data = data scienceということにして、自分の現在および近未来の専門領域は、仮に、Data Scientistとしておこう。

最近の話題を調べるために、data scienceをキーワードに、Google Scholarで検索した。

雑談としては長すぎるような気もするが、面白そうなのでここに紹介しておく。

AutoDS: Towards Human-Centered Automation of Data Science

Dakuo Wang et al., arXiv:2101.05273v1 [cs.HC] 13 Jan 2021

Abstract

Data science (DS) projects often follow a lifecycle that consists of laborious tasks for data scientists and domain experts (e.g., data exploration, model training, etc.). Only till recently, machine learning(ML) researchers have developed promising automation techniques to aid data workers in these tasks. This paper introduces AutoDS, an automated machine learning (AutoML) system that aims to leverage the latest ML automation techniques to support data science projects. Data workers only need to upload their dataset, then the system can automatically suggest ML configurations, preprocess data, select algorithm, and train the model. These suggestions are presented to the user via a web-based graphical user interface and a notebook-based programming user interface. We studied AutoDS with 30 professional data scientists, where one group used AutoDS, and the other did not, to complete a data science project. As expected, AutoDS improves productivity; Yet surprisingly, we find that the models produced by the AutoDS group have higher quality and less errors, but lower human confidence scores. We reflect on the findings by presenting design implications for incorporating automation techniques into human work in the data science lifecycle.

データ サイエンス (DS) プロジェクトは、多くの場合、データ サイエンティストと分野の専門家 (データ探索、モデル トレーニングなど) の骨の折れるタスクで構成されるライフサイクルに従います。最近まで、機械学習 (ML) の研究者は、これらのタスクでデータ ワーカーを支援する有望な自動化手法を開発してきました。このホワイト ペーパーでは、最新の ML 自動化手法を活用してデータ サイエンス プロジェクトをサポートすることを目的とした自動機械学習 (AutoML) システムである AutoDS を紹介します。データ ワーカーはデータセットをアップロードするだけで、システムは ML 構成を自動的に提案し、データを前処理し、アルゴリズムを選択し、モデルをトレーニングできます。これらの提案は、Web ベースのグラフィカル ユーザー インターフェイスとノートブック ベースのプログラミング ユーザー インターフェイスを介してユーザーに表示されます。私たちは 30 人のプロのデータ サイエンティストと共に AutoDS を研究しました。一方のグループは AutoDS を使用し、もう一方のグループは使用しませんでした。データ サイエンス プロジェクトを完了しました。予想どおり、AutoDS は生産性を向上させます。しかし驚くべきことに、AutoDS グループによって作成されたモデルの方が品質が高く、エラーが少なくなっていますが、人間の信頼スコアは低いことがわかりました。データ サイエンス ライフサイクルにおける人間の作業に自動化手法を組み込むための設計の意味を示すことにより、調査結果を反映します。by Google翻訳

 

6月4日(金)

Society for Imaging Informatics in Medicine (SIIM):335 teams, 2 months to go

 

オリジナル:B7 & 600 pixel & TPU --> LB=0.383

B0 & 224 pixel & GPU--> LB=0.373

B1 & 240 pixel & GPU--> LB=0.377

B2 & 260 pixel & GPU--> LB=0.382

 

6月5日(土)

Society for Imaging Informatics in Medicine (SIIM):348 teams, 2 months to go

B2 & 260 pixel & GPU--> LB=0.382

TPUが使えるようになったので、GPUと同一条件で計算したが、途中経過がよくなかった。0.77+となるべきところが、0.75+となった。

TPUでは、bfloat16を宣言して使う必要があるらしい。

image = tf.cast(image, tf.bfloat16)

これによって、GPUのfloat32と同等の精度になるらしい。

さらに、KaggleのTPUは8ユニットの並列動作なので、バッチ数をチェックしないと、GPUの場合の8倍になって、実効的な学習率が下がるなどのために、GPUの場合より精度が下がることがある。

少し条件を検討してみたが、次の結果となり、GPUでのLB=0.383には届かなかった。

B2 & 260 pixel & GPU:LB=0.382

B2 & 260 pixel & TPU:LB=0.375

さらに検討する必要がある。なお、この場合、TPUの計算速度はGPUの約4倍であった。

 

GPUでは、TPUよりも小さなモデルと画素数の組み合わせで、同等の予測精度が得られた。しかしながら、GPUでは、さらに大きなモデルと画素数の組み合わせにすると、メモリーオーバーになる。これについては、バッチ数を下げることで対応できるかどうか調べる予定である。

TPUでは並列計算により、GPUより高速に計算できるのでより大きなモデルと画素数の組み合わせで計算できるようであるが、同レベルのモデルと画素数の組み合わせではGPUより精度が落ちるようである。原因の1つは、bfloat16を使っていなかったことにあることがわかった。条件を同じにすれば、精度は同じになる筈なので、見落としが無いか調べる必要がある。

 

data_augmentationの検討:

def build_augmenter(with_labels=True):
      def augment(img):
            img = tf.image.random_flip_left_right(img)
            img = tf.image.random_flip_up_down(img)
            return img
      def augment_with_labels(img, label):
            return augment(img), label
      return augment_with_labels if with_labels else augment

TensorFlowのData augmentationの説明ページに掲載されているrandom系の例

tf.image.stateless_random_brightness
tf.image.stateless_random_contrast
tf.image.stateless_random_crop
tf.image.stateless_random_flip_left_right
tf.image.stateless_random_flip_up_down
tf.image.stateless_random_hue
tf.image.stateless_random_jpeg_quality
tf.image.stateless_random_saturation

brightnessを追加してみたが、エラーが出て、うまくいかなかった。

tf.image.stateless_random_brightness(image, max_delta=0.5, seed=new_seed)

 

6月6日(日)

 Society for Imaging Informatics in Medicine (SIIM):366 teams, 2 months to go

公開コードを用い、次の組み合わせで、スタディーレベル(分類)の訓練を予測をやってみる。それぞれに最適条件はあるだろうと思うが、モデルと解像度以外は同一条件としてみた。batch_size=32, Adam(1e-3), 

B0 & 224 pixel & TPU:LB=0.367 : 1.000

B1 & 240 pixel & TPU:LB=0.374 : 1.019

B2 & 260 pixel & TPU:LB=0.375 : 1.022

B3 & 300 pixel & TPU:LB=0.378 : 1.030

B4 & 380 pixel & TPU:LB=0.381 : 1.038

B5 & 456 pixel & TPU:LB=0.375 : 1.022

B6 & 528 pixel & TPU:LB=0.379 : 1.033

B7 & 600 pixel & TPU:LB=0.369 : 1.005

B0 &224からB4 & 380までは、予想通り、期待通りだと思う。

ところが、その先B5 & 456からB7 & 600 の結果には、大半の人は首を傾げると思う。

EfficientNetの論文のFigure 1には、B0からB7までImagenet Top-1 Accuracyが高くなる様子が図示されている。この図を見ると、誰でも番号の大きいモデルを使いたいと思うはず。この論文が示していることと、上記の実験結果との不一致の原因を調べよう。

EfficientNetの論文のFigure 1は、次のように計算されたと書かれている。

5.2. ImageNet Results for EfficientNet
We train our EfficientNet models on ImageNet using similar settings as (Tan et al., 2019): RMSProp optimizer with decay 0.9 and momentum 0.9; batch norm momentum 0.99;
weight decay 1e-5; initial learning rate 0.256 that decays by 0.97 every 2.4 epochs. We also use swish activation (Ramachandran et al., 2018; Elfwing et al., 2018), fixed AutoAugment policy (Cubuk et al., 2019), and stochastic depth (Huang et al., 2016) with drop connect ratio 0.3. As commonly known that bigger models need more regularization, we linearly increase dropout (Srivastava et al., 2014) ratio from 0.2 for EfficientNet-B0 to 0.5 for EfficientNet-B7.

最後の3行が特に重要で、モデルが大きいほど、regularizationの重要性が高くなり、dropout ratioはB0の0.2をB7では0.5にしたと書かれている。

Figure 1だけ見て大きなモデルを使おうとしてもだめだということがわかる。

具体的にどうすれば良いのか。

1.RMSProp optimizer with decay 0.9 and momentum 0.9; batch norm momentum 0.99; weight decay 1e-5; initial learning rate 0.256 that decays by 0.97 every 2.4 epochs. 

2.swish activation

tf.keras.activations.swish

3.fixed AutoAugment policy

https://github.com/google/automl/blob/master/efficientnetv2/autoaugment.py

AutoAugment: Learning Augmentation Strategies from Data

RandAugment: Practical automated data augmentation with a reduced search space

4.stochastic depth (Huang et al., 2016) with drop connect ratio 0.3

Stochastic depth aims to shrink the depth of a network during training, while keeping it unchanged during testing. We can achieve this goal by randomly dropping entire ResBlocks during training and bypassing their transformations through skip connections.

5.linearly increase dropout (Srivastava et al., 2014) ratio from 0.2 for EfficientNet-B0 to 0.5 for EfficientNet-B7

大きなモデルに見合った結果を得るには、相当の準備が必要だということが分かった。

 

GitHubgoogle/automl/efficientnetv2

EfficientNetV2

May13/2021: Initial code release for EfficientNetV2 models: accepted to ICML'21.

1. About EfficientNetV2 Models

EfficientNetV2 are a family of image classification models, which achieve better parameter efficiency and faster training speed than prior arts.

Built upon EfficientNetV1, our EfficientNetV2 models use neural architecture search (NAS) to jointly optimize model size and training speed, and are scaled up in a way for faster training and inference speed.

f:id:AI_ML_DL:20210606141805p:plain

6月7日(月)

Society for Imaging Informatics in Medicine (SIIM):386 teams, 2 months to go

B5 & 456 pixel & TPU:LB=0.375(Batch_size=32)

これは、Batch_size=32でtrainingしたもの。Batch_sizeによる違いを調べてみよう。TPUの残り時間が少ないので、まずは、Batch_size=128にしてみよう。

結果は、LB=0.375、となった。32でも128でもLBスコアは変わらなかった。

 

B7 & 600 pixel & TPUは、batch_size=32ではLB=0.369となり、128ではLB=0.383であった。よくわからない。何か間違ったのだろうか。

 

B4 & 380 pixel & TPU $ batch_size=32:LB=0.381

このモデルのAdamをAdamW(weight_decay=1e-4)にしてみた。

その結果、LB=0.384となった。

LookaheadをAdamWとの組み合わせで試した。このとき、パラメータは、デフォルトもしくはexample of usageなどに例示されている値を使った。計算の途中経過が明らかに良くなかったので、Lookahead(AdamW)によるtrainingは途中で中止した。

 

CyclicLRとdata_augmentationのことをすっかり忘れている。

 

6月8日(火)

Society for Imaging Informatics in Medicine (SIIM):402 teams, 2 months to go 

TPUを使い切ったので、GPUによる検討に戻ろう。

B2 & 260 pixel & GPU:LB=0.382(batch_size=16), Adam, 1e-3, 

random_brightnessはこれで効果を確認する。

img = tf.image.rabdom_brightness(img, 0.2)

AdamはAdamW(lr=1e-3, weight_decay=1e-4)で試してみる。

training終了間際で、計算が停止していた。Go to Viewerも使えない。どうしたのだろうか。いずれにしても、約3時間が無駄になった。

 

イメージレベルが手つかずのままだ。検出は、本格的に取り組んだことがないので、お手本コードを探して勉強しよう。イメージレベルの予測結果のスコアリングの不具合もまだ修正されていないようだ。

 

6月9日(水)

  • Society for Imaging Informatics in Medicine (SIIM)
  • :415 teams
  • , 2 months to go

TPUの使用時間リセット待ち!

 

6月10日(木)

Society for Imaging Informatics in Medicine (SIIM):439 teams, 2 months to go 

 

*****中断***** 

 

6月15日(火)

SIIM:496 teams, 2 months to go (8/9)

ようやく、問題点の修復が進み始めたようだ。

みなさん、こんにちは。今しばらくお待ちいただきますようお願いいたします。 ホストチームはいくつかのテストラベルを更新しました。 また、画像レベルのラベルのスコアリングに影響を与える問題も修正しました。フィードバックをお寄せいただきありがとうございます。 リーダーボードを更新するプロセスを開始します。 すべての提出物を再実行するため、これには時間がかかることに注意してください。 by Google翻訳

0.45+で頭打ちになっていたのが、徐々にスコアアップし、今のトップは、0.62となっている。自分が提出している提出データは、テストレベルの予測データのみで、画像レベルの予測データはデフォルトのままである。

ということで、今日から、画像レベルの予測にとりかかる。といっても、公開コードに頼りっぱなしだが。

 

6月16日(水)

進捗なし 

 

6月17日(木)

進捗なし

 

6月18日(金)

SIIM:571 teams, 2 months to go

Image-levelの予測結果に対するスコアの再計算が進み、160件くらいが0.500を超えている。

スコアの再計算によって、Study-levelのスコアが0.055アップしていた。(0.384が0.439になっていた。)

最初はそう思ったのだが、そうではなくて、Image-levelの予測結果を、空欄ではなく、デフォルト値にしていたので(公開コードがそうなっていた)、Image-levelのスコアを正しく計算できるようになったことから、Image-levelのデフォルトデータのスコア:0.055が加算された、というのが、スコアアップの原因だとわかった。

 

***散歩中***

 

6月26日(土)

SIIM:706 teams, a month to go

このコンペに対しては、チューニングではなく、モデルの構築段階に踏み込んで、良い結果を出したいと考えている。考えてはいるのだが、難しい。ラベルは専門家が付けているが正確ではない。モデルは、ラベル以上に正確では、スコアは上がらず、かえって下がる。正解のラベルも正確ではないからである。かといって、このモデルが予測した結果こそが真実だ、というためには、そのことを証明しなければならない。専門家の判断を超える判断能力を備えるためには、専門家が見逃している、あるいは、専門家にも見えない情報をを増幅して見えるようにする、あるいはより正しく診断するために考慮しなければならない画像間の相関を見つけ出すことが必要になるのだろう。さらに、それらの証拠を見える化しなければならない。画像診断では、そういうことも起こりうるような気はするが、現状のレベルでは、100%、overfittingである。

 

7月1日(木)

あと40日

 

8月1日(日)

寄り道しているうちに、戻ってこれなくなった。

残念だが、ここで終了する。 

 

f:id:AI_ML_DL:20210531004031p:plain

style=166, iteration=500

f:id:AI_ML_DL:20210531004202p:plain

style=166, iteration=50

f:id:AI_ML_DL:20210531004252p:plain

style=166, iteration=5

 

Kaggle散歩(5月11日~6月3日)

5月11日~6月3日

Bristol-Myers Squibb – Molecular Translation
Can you translate chemical images to text?

参加する期間は約20日:コンペの課題は、化学構造式の画像から、InChI(International Chemical Identifier)形式のテキストデータを推測すること。

*3月8日にこのコンペに参加し、そのまま放置していた。

 

5月11日(火)

Bristol-Myers Squibb:647 teams, 23 days to go 

参加チーム数が比較的少ない。課題が専門的過ぎるのだろう。これほど専門的な課題でも、これだけのチームが参加しているというのは、すごいことかな、とも思う。

さて、このコンペ、どのように取り組もうか。

目的:省略

目標:トップ5%以内に入ること。 ⇒ 取り組み方を間違ったため、目標は、この論文”End-to-End Attention-based Image Captioning”の内容を理解すること、及び、コンペ終了後にトップレベルの解法をできるだけ深く学ぶこと、とする。 ⇒ 途中でコンペから離れてReinforcement Rearningに取り組むなど、まとまりのないものになってしまった。最後に時間があれば、公開コードのtrainとinferenceを走らせて、実際のコードから少しでも学ばせていただこう。

方法:省略

スコアの計算: Levenshtein distance:レーベンシュタイン距離は、二つの文字列がどの程度異なっているかを示す距離の一種である。編集距離(へんしゅうきょり、英: edit distance)とも呼ばれる。具体的には、1文字の挿入・削除・置換によって、一方の文字列をもう一方の文字列に変形するのに必要な手順の最小回数として定義される[1]。by ウィキペディア

正解がabcde、解答がbbccdだとすると、正解に一致させるためには、2文字を置換する必要があるので、スコアは、2となる。正解の場合のスコアは0となり、5文字全部間違えるとスコアは5となる。文字数が異なると、挿入回数、削除回数が加算される。

リーダーボードのスコアは、sample_submission.csvをそのままsubmitすると、109.63となる。現状、100位が3.70、50位が2.09、Goldが1.13以内、トップが0.65となっている。

これらのスコアを大雑把に評価すると、トップのチームは、100点満点で99点以上、50位でも98点くらいということなので、非常にレベルが高い。

ここまで正確に変換することができるのか。すごいことだな。ここに割って入るのは無理だなと思ってしまう。中途半端なやりかたでは、トップ5%以内には、入れないような気がする。

先のHuBMAPコンペのような”大波乱”がおきるようなことは考えられない。

 

化学構造式と対応するInChI表現の例。by ウィキペディア

f:id:AI_ML_DL:20210511153524p:plain

InChI=1S/C6H8O6/c7-1-2(8)5-3(9)4(10)6(11)12-5/h2,5,7-8,10-11H,1H2/t2-,5+/m0/s1

ウィキペディアから借用した構造式は非常に綺麗だが、コンペで提供される構造式は、古い書籍から転載を繰り返したような画像が多く、N, O, S, Pなどの元素記号の識別が容易でない図も含まれている。

 

このコンペと全く同じ内容の論文が発行されている。

End-to-End Attention-based Image Captioning

Carola Sundaramoorthy, Lin Ziwen Kelvin, Mahak Sarin, and Shubham Gupta

arXiv:2104.14721v1 [cs.CV] 30 Apr 2021

Abstract
In this paper, we address the problem of image captioning specifically for molecular
translation where the result would be a predicted chemical notation in InChI format
for a given molecular structure. Current approaches mainly follow rule-based or
CNN+RNN based methodology. However, they seem to underperform on noisy
images and images with small number of distinguishable features. To overcome this,
we propose an end-to-end transformer model. When compared to attention-based
techniques, our proposed model outperforms on molecular datasets.

概要
この論文では、特に分子翻訳のための画像キャプションの問題に取り組みます。この場合、結果は、特定の分子構造に対してInChI形式で予測される化学表記になります。 現在のアプローチは、主にルールベースまたはCNN + RNNベースの方法論に従います。 ただし、ノイズの多い画像や識別可能な特徴の数が少ない画像では、パフォーマンスが低下しているように見えます。 これを克服するために、エンドツーエンドのtransformer モデルを提案します。 Attentionベースの手法と比較すると、提案されたモデルは分子データセットよりも優れています。by Google翻訳

f:id:AI_ML_DL:20210511172043p:plain

f:id:AI_ML_DL:20210511172235p:plain

この論文での最高スコアは6.95で、現在のリーダーボードでは231位相当である。

コンペも終盤にさしかかっているので、コンペサイトには、非常にレベルの高い情報と公開コードが集まっている。

 

5月12日(水)

Bristol-Myers Squibb:654 teams, 22 days to go

 

Discussion

このコンペ、問題がおきていたようだ。

分子構造の画像SMILES変換AIコンテスト(Dacon molecular to smiles competition, 2020.09.01 ~ 2020.10.09)が韓国で行われ、トップ3のコードに関する情報がオープンになっていて、その情報がKaggleのコンペ内で、ある期間共有されていた。

SMILESとInChIとではフォーマットが異なっているが、高性能な予測モデルの作成にとって参考になる情報が含まれていて、それを利用してハイスコアを得ているチームがあったということのようである。

その状況を不公平と感じた方が、Discussionコーナーにサマリーを掲載し、さらに、他の方々も加わって、トップ3の情報に誰でもアクセスできるようにした、ということのようである。

トップ3のコードがデータセットに格納され、公開されていることを確認した。これを活用できるのは、レベルの高い人に限られるだろうな。自分には難しすぎるように思うが、チャレンジしてみよう。

 

5月13日(木)

Bristol-Myers Squibb:673 teams, 21 days to go

分子構造をInChIコードに変換するモデル:

分子構造は画像として与えられる。その画質は、新しい教科書に掲載されているような鮮明な画像ではなく、コピーを繰り返して不鮮明になった画像である。O, N, P, Sなどの元素記号は不鮮明であり、1重結合と2重結合が見分けにくいものがあり、立体構造を表す結合なども不鮮明なものがある。斑点状のノイズがのっている。

不鮮明な画像からInChIコードを推定する前に、鮮明な分子構造モデルを作成する。画像を鮮明にするだけでなく、全ての炭素原子を可視化する。各炭素原子の位置にInChIコードに対応する番号を表示する。原子を色分けして、識別しやすくする。

InChIコードを鮮明な分子構造モデルに変換する。元画像とInChIコードから変換した鮮明な分子構造モデルのペアを用いて、元画像を鮮明な分子構造モデルに変換するためのモデルを作る。

鮮明な分子構造をInChIコードに変換することができるモデルに、テスト画像から変換した鮮明な分子構造を入力することにより、正確なInChIコードに変換することができる。

元画像⇒モデルA⇒分子構造⇒モデルB⇒InChIコード。

このようなことは、実際に、できるのだろうか。

 

5月14日(金)

Bristol-Myers Squibb:688 teams, 20 days to go

けろけろけろっぴアバターをもつGMの方のDiscussionでの解説と引用文献等をフォローしようと思う。

 

5月15日(土)

Bristol-Myers Squibb:697 teams, 19 days to go

InChIコードから構造式を描くことはできるのだろうか。

RDKitを使ってInChIコードから分子構造を描くことができるコードが公開されている。

RDKitのDocumentationのトップページにInChIは存在せず、SMILESは11件存在する。

search pageから検索すると、Search finished, found 34 page(s) matching the search query.と表示され、InChIを含むページが34ページあることがわかる。

rdkit.Chem.inchi module

rdkit.Chem.inchi.MolFromInchi(inchi, sanitize=True, removeHs=True, logLevel=None, treatWarningAsError=False)¶
Construct a molecule from a InChI string

これは、InChIコード(文字列)から分子を構築する命令のようである。

構築した分子を描くためには、次のモジュールを使うようだ。

rdkit.Chem.Draw.rdMolDraw2D module

documentationを読めばすぐにコードが書けるわけではない。少なくとも、C++Pythonコードを自由に操ることができるようでないと使えそうもない。

お手本の公開コードがあるので、それを理解しながら、必要な作業を進めよう。

InChICコードからデータベースの画像よりも鮮明な分子構造画像が得られても、その分子構造画像からInChIコードに変換するモデルを作るのは容易ではない。

次の論文が参考になりそうだ。

Towards a Universal SMILES representation - A standard method to generate canonical SMILES based on the InChI,

Noel M O’Boyle, Journal of Cheminformatics 2012, 4:22

f:id:AI_ML_DL:20210515235510p:plain

Figure 1 An overview of the steps involved in generating Universal and Inchified SMILES. The normalisation step just applies to Inchified SMILES. To simplify the diagram a Standard InChI is shown, but in practice a non-standard InChI (options FixedH and RecMet) is used for Universal SMILES.

この図のように、原子位置の番号を表示した画像を発生することができれば、InChIコードへの変換を、より正確に行えるモデルを作ることができるように思う。

この論文は2012年に発行されているので、韓国で行われたSMILES形式のコードへの変換は、ここに示されているような手順を参考にして行われた可能性が高いように思われる。Kaggleのコンペにおいても、このスキームを利用できるのだろうと思う。

 

5月16日(日)

Bristol-Myers Squibb:703 teams, 18 days to go 

Towards a Universal SMILES representation - A standard method to generate canonical SMILES based on the InChI, Noel M O’Boyle, Journal of Cheminformatics 2012, 4:22

この論文に学ぶ:

主題は、InChIをベースにして、SMILES表現を標準化すること。

InChIとSMILESは、1行で分子構造を表現し、分子構造の情報を、格納し、表現し、コンピュータ入力するなどの目的に適していて、かつ、分子が一義的に決まるものであり、さらに、コンピュータにも人にも理解できること、簡潔であることなどが求められる。

InChIは、International Chemistry Identifierの名称が示しているように、国際標準化を目指して(NISTを推進母体として)IUPACが推進してきたもののようである。

SMILESは、Simplified Molecular Input Line Entry Systemの名称が示しているように、単純化された分子のライン入力システムで、InChIよりも簡潔で、直観的に把握しやすいものである。

SMILES : C(=O)([O-])C(=O)O

Standard InChI :  InChI=1/C2H2O4/c3-1(4)2(5)6/h(H,3,4)(H,5,6)/p-1

論文の1ページ目の最後の方には、SMILESとInChI以外の1行記述方法が列挙されている。SLN, ROSDAL, WLN, MCDLなど。InChIKeyというのもある。ウィキペディアによれば、「hashed InChIとも呼ばれるInChIKeyは、25文字の固定長であるが、デジタル表現なので人間には読むことができない。InChIKeyの仕様は、ウェブでの検索を可能にするために、2007年9月にリリースされた[5]。InChIそのものとは異なり、InChIKeyは一意ではなく、非常に稀ではあるが重複が発生する[6]。」

韓国のコンペで使われたSMILESは、2012年の時点では、最もポピュラーな1行表記方法”The SMILES format is the most popular line notation in use today."とのことであるが、課題は、立体構造の表現が困難であることの他に、標準化されていないことだということで、InChIをベースに標準化を提案しているのがこの論文の内容となっている。SMILESの標準化が進まなかった原因として、提案された方法が立体構造に対応していない、開発品の専売化、フリーソフトは互いに互換性が無く出版もされなかったことなどがあげられている。

1999年にNIST(National Institute of Standards and Technology)において、分子の新しい1行表記方法の開発がすすめられ、InChIが国際標準として提案されたようである。

この論文では、このInChIからの標準的なラベルを用いて、標準的なSMILESを生成するという方法をとっている。オープンソースの様々なケモインフォマティクスライブラリー(Open Babel, Chemistry Development Kit, RDKit, Chemkit, Indigoなど)に含まれるコードを用いることができるようである。

3ページ目には、Inchified SMILESとUniversal SMILESの2種類が定義されている。

論文ではOpen Babel chemoinformatics toolkitを用いた説明となっている。Kaggleの公開コードではRDKitを使っている。

Methods:次の4つのステップにおいて、図の表示、原子位置の番号表示、原子位置の番号の変更などを行うのか?そうではなさそうだ。

structure normalization

canonical labeling

graph traversal

SMILES generation 

Fig.1の図は、InChIからSMILESへの変換プロ節の説明のために分子構造を図示し、原子位置番号も理解を助けるために表示しているだけで、実際の変換作業は、Open Babelのobabelコマンドラインプログラムで瞬時に変換されるだけのようにみえる。

The following commands show how to use the obabel command-line program to generate Universal and Inchified SMILES strings for a structure stored in a Mol file:
C:\>obabel figure1.mol -osmi –xU
c1cc(/C=C/F)cc(c1)[N+](=O)[O-]
C:\>obabel figure1.mol -osmi –xI
c1cc(/C=C/F)cc(c1)N(=O)=O

 

明日は、InChIから分子構造を表示する方法を(公開コードから)学び、得られた分子構造画像のデータセットを作ろう。

 

5月17日(月)

Bristol-Myers Squibb:715 teams, 17 days to go

もう少し論文を読み進めよう。

論文読んでいてもよくわからないので、OpenBabelを使ってみよう。

OpenBabel 2.4.0をインストールした。

OpenBabelGUIが表示される。左側から、INPUT FORMAT, CONVERT, OUTPUT FORMATとなっている。次の命令をOpenBabelGUI上で実行してみよう。

C:\>obabel figure1.mol -osmi –xU
c1cc(/C=C/F)cc(c1)[N+](=O)[O-]

まずは、左側の入力画面のフォーマットをInChIに、右側の出力画面のフォーマットをSMILESにする。

次に、左側の画面に、論文のFig.1に示されているInChIコードを入力する。

InChI=1S/C8H6FNO2/c9-5-4-7-2-1-3-8(6-7)10(11)12/h1-6H/b5-4+

中央のCONVERTボタンをクリックすると、SMILESコードが出力された。

c1cc(/C=C/F)cc(c1)N(=O)=O

次に、左側は、InChIコードのままで、出力をpng -- PND 2D depictionとし、出力ファイル名を指定しておく。

この状態で中央のCONVERTボタンをクリックすると、指定しておいたファイルの中に次の画像が保存された。

f:id:AI_ML_DL:20210517112650p:plain

それならばと、コンペのデータセットのInChIコードを左側の画面に張り付けて、出力ファイル名を設定しなおして、CONVERTをくりっくすると次のように分子が出力された。

InChI=1S/C13H15NO2/c1-10(14-11(2)16)13-7-5-12(6-8-13)4-3-9-15/h5-8,10,15H,9H2,1-2H3,(H,14,16)

f:id:AI_ML_DL:20210517113405p:plain

分子構造の生成パラメータが詳細に決定できるようになっている。

炭素原子を明示することもできる。

InChI=1S/C38H40N4O6S2/c43-35-25-47-31-17-5-1-13-27(31)37(45)39-21-9-10-22-40-38(46)28-14-2-6-18-32(28)48-26-36(44)42-30-16-4-8-20-34(30)50-24-12-11-23-49-33-19-7-3-15-29(33)41-35/h1-8,13-20H,9-12,21-26H2,(H,39,45)(H,40,46)(H,41,43)(H,42,44)

f:id:AI_ML_DL:20210517121736p:plain

RDKitを用いてInChIコードから分子構造を得るのと同じことを、OpenBabelGUIでできることがわかった。ただし、現状では、InChIコードを1件づつしか処理できない。

InChIコードから綺麗な分子構造に変換できて炭素原子の表示も可能であるが、原子位置の表示はできていない。

とりあえず、train_dataの分子構造図を、InChIコードラベルを使ってクリヤ―な画像に変換できたとして、当初考えていたことが可能かどうか検証してみよう。

test_dataの画像をクリヤーにする方法:

コンペから遠くはなれてしまいそうだが、画質を向上させるということでは、GANやNeural Style Transferなどが使えそうに思うが、これらのコードを使ったことはあるが、その本質は理解できていないように思うので、Generative Deep Learningのテキストを読んでみる。

Generative Deep Learning

by David Foster

この本を読み終えるまでにこのコンペが終了しているかもしれない!何か使える手法はないか探してみよう。何か役に立つ情報が隠れているかもしれない。すぐには使えなくてもいい、次のステップが見えてくるだけいい・・・。

ほんの少しだけ頭を使ったらわかったことは、100%正解できることを、わざわざディープラーニングを使ってやってみようとしているだけのようにみえるということである。このコンペの課題は、本質的には、確率の世界ではなく、決定論の世界である。たとえば、四則演算の規則を教えないで、式の画像と数値の正解のセットを用いてCNN+RNN/LSTMでtrainingして式の画像から正しいラベルを推定させるのと同じ。同様のことは、人工知能東京大学の入試問題を解かせようとして成功とまではいかなかったことにも通じるところがある。問題が画像として与えられるために、決定論の問題であっても、確率論の問題におきかわってしまうか、ある確率でしか問題の意図を把握することができないということが、点数があるレベルを超えられなくなる原因になっていたのかもしれない。受験者が持っている知識レベルに到達するために必要な知識をどうやって保持させるかを考えた時、問題ごとにあるいは問題の要素ごとに、問題を解くことができるだけの能力を備えるために必要なデータセットを用意することが必要で、そのための膨大なデータセットを準備する手間が足りなかったのではないだろうか。

東大入学試験問題に限らず、あるいは入試問題に限らず、ニューラルネットワークによって様々な問題が解けるようにすることは、非常に重要なことかもしれない。それは、もしかしたら、自己学習につながるかもしれない。問題が解けるようになるということは、画像情報(試験問題)から疑似知識を習得することになり、算数のレベルから数学のレベルになり、物理、化学、生物などの自然科学から、論理学、経済学、経営学、法学、さらには哲学的的思考にまで発展していく可能性がある。ヒトはどうやって知識を獲得していくのか。ヒトはどうやって思考能力を獲得していくのか。思考の中身はなんだろう。会話の中身は単なる記憶情報の発出ではないのか。

マシンラーニングのラーニング手法についてもっとよく考えようと思うのだが、考える土台になるものを十分には理解できていないような気がしている。ラーニングマシンからシンキングマシンへ、さらにはクリエイティブマシン、リサーチマシンへと進化させていくためにどういう機能が必要なのか。さらに、これらが自己増殖するためにはどういう機能が必要になるのか。

空想(妄想)はこのへんにして、テキストに戻ろう。

今日はここまで・・・。 

 

5月18日(火)

Bristol-Myers Squibb:727 teams, 16 days to go

Genetative Deep Learning by David Fosterの続き:

GenerativeとDiscriminative:自分の印象では、Generativeは似たものを作ることで、Discriminativeは見分けること。似ていることは、見分けにくいことで、見かたが異なるだけのようだが、Generative modeling processとDiscriminative modeling processとの最も大きな違いは、出力である。Generative modelが出力するのは、画像であり、音であり、テキストである。Discriminative modelが出力するのは、ラベルもしくは評価値である。当該コンペの出力はラベルである。

Generative modeling:データがどのように作られているのかを明らかにすることが重要。reinforcement learningの指導原理のように目的を達成するための手段や経路の探索において重要。generative modelingの究極の姿は今この本を読んでいる人間の脳の中がおきていることを理解し再現すること。

reinfoecement learning:Atariのゲームで人を負かすプログラムということで有名になり、その後チェス、将棋、碁においても人を負かすことになったモデル。その後、自動運転、創薬支援、タンパク質の構造解析などにも適用されているようである。重要な技術だということで学ぼうとしているのだが、その本質がよくわからない。

最初にテキストのChapter 8 Playを眺めてみる。

Reinforcement Learningの説明のあと、実例を用いた説明となるのだが、実例がゲームで、CarRacingである。これで、一気に、やる気が失せるんだな。どうしようか。 

昨年の9月に、たくさんのコンペに参加した中に、Halite by Two Sigma, Collect the most halite during your match in spaceというのがあった。Reinforcement Learningを試すコンペのようなので、ここでReinforcement Learningを学ぼうと思った。しかし、同時期にいくつかのコンペにも参加していたので、各コンペに避ける時間があまりにも少なく、結局、RLの学習もスコアも中途半端で終わった。このコンペのことを思い出してそのサイトに行って、トップチーム(個人)の解説をざっと読んで驚いた。その方は、なんと、Reinforcement Learningを開発したDeep Mindにおられて熟知されていたようである。当然のことながらプログラミングレベルもはかり知れないものだろうと思う。RLがトップを狙うには不十分ということで、従来型のプログラミングで勝負したとのことである。なんと11,000行、とのこと。Reinforcement Learning自体がだめということではなく、学習時間が足りないということのようである。とてもまねできないなと思ったのは、対戦状況を観察して相手の戦術を読み取ってそれを凌駕する戦術を考えてプログラミングしたことである。

DEEP REINFORCEMENT LEARNING
Yuxi Li (yuxili@gmail.com), arXiv:1810.06339v1 [cs.LG] 15 Oct 2018

ABSTRACT
We discuss deep reinforcement learning in an overview style. We draw a big picture, filled with details. We discuss six core elements, six important mechanisms, and twelve applications, focusing on contemporary work, and in historical contexts. We start with background of artificial intelligence, machine learning, deep learning, and reinforcement learning (RL), with resources. Next we discuss RL core elements, including value function, policy, reward, model, exploration vs. exploitation, and representation. Then we discuss important mechanisms for RL, including attention and memory, unsupervised learning, hierarchical RL, multiagent RL, relational RL, and learning to learn. After that, we discuss RL applications, including games, robotics, natural language processing (NLP), computer
vision, finance, business management, healthcare, education, energy, transportation, computer systems, and, science, engineering, and art. Finally we summarize briefly, discuss challenges and opportunities, and close with an epilogue.

概要スタイルで深層強化学習について説明します。細部にまでこだわった全体像を描きます。現代の仕事に焦点を当て、歴史的な文脈で、6つのコア要素、6つの重要なメカニズム、および12のアプリケーションについて説明します。まず、人工知能機械学習、深層学習、強化学習(RL)の背景とリソースを使用します。次に、価値関数、ポリシー、報酬、モデル、探索と活用、表現など、RLのコア要素について説明します。次に、注意と記憶、教師なし学習、階層型RL、マルチエージェントRL、リレーショナルRL、学習学習など、RLの重要なメカニズムについて説明します。その後、ゲーム、ロボット工学、自然言語処理NLP)、コンピュータービジョン、財務、経営管理、ヘルスケア、教育、エネルギー、輸送、コンピューターシステム、科学、工学、芸術などのRLアプリケーションについて説明します。最後に、簡単に要約し、課題と機会について話し合い、エピローグで締めくくります。by Google翻訳

全150ページ、数式が多くて、さっぱりわからん。

Offline Reinforcement Learning: Tutorial, Review, and Perspectives on Open Problems
Sergey Levine, Aviral Kumar, George Tucker, Justin Fu                                        arXiv:2005.01643v3 [cs.LG] 1 Nov 2020

Abstract
In this tutorial article, we aim to provide the reader with the conceptual tools needed to get started on research on offline reinforcement learning algorithms: reinforcement learning algorithms that utilize previously collected data, without additional online data collection. Offline reinforcement learning algorithms hold tremendous promise for making it possible to turn large datasets into powerful decision making engines. Effective offline reinforcement learning methods would be able to extract policies with the maximum possible utility out of the available data, thereby allowing automation of a wide range of decision-making domains, from healthcare and education to robotics. However, the limitations of current algorithms make this difficult. We will aim to provide the reader with an understanding of these challenges, particularly in the context of modern deep reinforcement learning methods, and describe some potential solutions that have been explored in recent work to mitigate these challenges, along with recent applications, and a discussion of perspectives on open problems in the field.

このチュートリアル記事では、オフライン強化学習アルゴリズムの研究を開始するために必要な概念ツールを読者に提供することを目的としています。これは、追加のオンラインデータ収集なしで、以前に収集されたデータを利用する強化学習アルゴリズムです。オフライン強化学習アルゴリズムは、大規模なデータセットを強力な意思決定エンジンに変えることを可能にするという大きな可能性を秘めています。効果的なオフライン強化学習手法は、利用可能なデータから最大限の有用性を備えたポリシーを抽出できるため、医療や教育からロボット工学まで、幅広い意思決定ドメインの自動化が可能になります。ただし、現在のアルゴリズムの制限により、これは困難です。特に現代の深層強化学習方法の文脈で、読者にこれらの課題の理解を提供することを目指し、これらの課題を軽減するために最近の研究で探求されたいくつかの潜在的な解決策、最近のアプリケーション、および議論について説明しますフィールドの未解決の問題に関する視点の。by Google翻訳

全34ページ、数式が多くて、さっぱりわからん。

次の論文は、最初に紹介したテキストGenerative Deep Learning by David Fosterの第8章のReinforcement Learningのメインストーリーの土台となっているもので、非常に丁寧に書かれた必読文献だと思う。

World Models
David Ha and Jurgen Schmidhuber, arXiv:1803.10122v4 [cs.LG] 9 May 2018

Abstract
We explore building generative neural network models of popular reinforcement learning
environments. Our world model can be trained quickly in an unsupervised manner to learn a compressed spatial and temporal representation of the environment. By using features extracted from the world model as inputs to an agent, we can train a very compact and simple policy that can solve the required task. We can even train our agent entirely inside of its own hallucinated dream generated by its world model, and transfer
this policy back into the actual environment.

人気のある強化学習環境の生成ニューラルネットワークモデルの構築を検討します。 私たちの世界モデルは、教師なしの方法ですばやくトレーニングして、環境の圧縮された空間的および時間的表現を学習できます。 ワールドモデルから抽出された特徴をエージェントへの入力として使用することで、必要なタスクを解決できる非常にコンパクトでシンプルなポリシーをトレーニングできます。 エージェントを、その世界モデルによって生成された独自の幻覚の夢の中で完全にトレーニングし、このポリシーを実際の環境に戻すこともできます。by Google翻訳

Humans develop a mental model of the world based on what they are able to perceive with their limited senses. The decisions and actions we make are based on this internal
model. Jay Wright Forrester, the father of system dynamics, described a mental model as:
The image of the world around us, which we carry in our head, is just a model. Nobody in his head imagines all the world, government or country. He has only selected concepts, and relationships between them, and uses those to represent the real system. (Forrester, 1971)

人間は、限られた感覚で知覚できるものに基づいて、世界のメンタルモデルを開発します。 私たちが行う決定と行動は、この内部モデルに基づいています。 システムダイナミクスの父であるジェイライトフォレスターは、メンタルモデルを次のように説明しました。私たちが頭に抱えている私たちの周りの世界のイメージは、単なるモデルです。 彼の頭の中の誰も、すべての世界、政府、または国を想像していません。 彼は概念とそれらの間の関係のみを選択し、それらを使用して実際のシステムを表現しています。 (フォレスター、1971年)by Google翻訳

To handle the vast amount of information that flows through our daily lives, our brain learns an abstract representation of both spatial and temporal aspects of this information. We are able to observe a scene and remember an abstract description thereof. Evidence also suggests that what we perceive at any given moment is governed by our brain’s prediction of the future based on our internal model.

私たちの日常生活を流れる膨大な量の情報を処理するために、私たちの脳はこの情報の空間的側面と時間的側面の両方の抽象的な表現を学習します。 シーンを観察し、その抽象的な説明を思い出すことができます。 証拠はまた、私たちがいつでも知覚するものは、私たちの内部モデルに基づく私たちの脳の将来の予測によって支配されていることを示唆しています。by Google翻訳

 

 

5月19日(水)

Bristol-Myers Squibb:746 teams, 15 days to go 

このコンペに対して、日々、どういうふうに取り組んでいるのかを書きとめているつもりだが、脇道に入り込んでいる状態で、今日も、脇道を進んでいく。

Reinforcement Learning

学ぼうと思って何度かトライしたが、うまくいかない。昨日も、いくつかの論文に目を通し、Kaggleのコースを見たり、F. CholletさんやA. Geronさん、D. Fosterさんのテキストをながめていても頭に入ってこない。なんとなくわかってきたことは、Reinforcement Learningは、その起源が古く、ある意味、基本的な事項はわかっているものとして基礎的な説明が省略されているのではないかということである。

ということで、Google ScholarReinforcement Learningを検索して、次の文献を読むことにした。25年前の論文である。

Reinforcement Learning: A Survey

Leslie Pack Kaelbling, Michael L. Littman, and Andrew W. Moore, 

Journal of Artificial Intelligence Research 4 (1996) 237-285

Abstract
This paper surveys the field of reinforcement learning from a computer-science per-
spective. It is written to be accessible to researchers familiar with machine learning. Both
the historical basis of the field and a broad selection of current work are summarized.
Reinforcement learning is the problem faced by an agent that learns behavior through
trial-and-error interactions with a dynamic environment. The work described here has a
resemblance to work in psychology, but differs considerably in the details and in the use
of the word \reinforcement." The paper discusses central issues of reinforcement learning, including trading off exploration and exploitation, establishing the foundations of the field via Markov decision theory, learning from delayed reinforcement, constructing empirical models to accelerate learning, making use of generalization and hierarchy, and coping with hidden state. It concludes with a survey of some implemented systems and an assessment of the practical utility of current methods for reinforcement learning.

この論文は、コンピュータサイエンスの観点から強化学習の分野を調査します。機械学習に精通した研究者がアクセスできるように書かれています。この分野の歴史的根拠と現在の研究の幅広い選択の両方が要約されています。強化学習は、動的環境との試行錯誤の相互作用を通じて行動を学習するエージェントが直面する問題です。ここで説明する作業は心理学での作業に似ていますが、詳細と使用法がかなり異なります。この論文では、探索と活用のトレードオフ、マルコフ決定理論によるフィールドの基盤の確立、遅延強化からの学習、学習を加速するための経験的モデルの構築、一般化と階層の利用、そして隠された状態への対処など、強化学習の中心的な問題について説明しています。それはいくつかの実装されたシステムの調査と強化学習のための現在の方法の実用性の評価で終わります。by Google翻訳+一部修正

本文30ページの1/3くらい目を通してみた感想は、キラーアプリが見つかっていないためなのか、議論が理論的、概念的で、具体性がなく、同じところをぐるぐる回っているように感じることである。過去に学ぶのも良いが入り込みにくい世界でもある。

自動運転でReinforcement Learningがどう使われているかを調べてみよう。Reinforcement Learningとゲームの組み合わせよりも、断然、やる気が出る。

Deep Reinforcement Learning for Autonomous Driving: A Survey
B Ravi Kiran, Ibrahim Sobh, Victor Talpaert, Patrick Mannion, Ahmad A. Al Sallab,     Senthil Yogamani, and Patrick PérezarXiv:2002.00444v2 [cs.LG] 23 Jan 2021

Abstract—With the development of deep representation learning, the domain of reinforcement learning (RL) has become a powerful learning framework now capable of learning complex policies in high dimensional environments. This review summarises deep reinforcement learning (DRL) algorithms and provides a taxonomy of automated driving tasks where (D)RL methods have been employed, while addressing key computational challenges in real world deployment of autonomous driving agents. It also delineates adjacent domains such as behavior cloning, imitation learning, inverse reinforcement learning that are related but are not classical RL algorithms. The role of
simulators in training agents, methods to validate, test and robustify existing solutions in RL are discussed.
Index Terms—Deep reinforcement learning, Autonomous driving, Imitation learning, Inverse reinforcement learning, Controller learning, Trajectory optimisation, Motion planning, Safe reinforcement learning.

要約—深層表現学習の開発により、強化学習(RL)のドメインは、高次元環境で複雑なポリシーを学習できる強力な学習フレームワークになりました。 このレビューでは、深層強化学習(DRL)アルゴリズムを要約し、自動運転エージェントの実際の展開における主要な計算上の課題に対処しながら、(D)RLメソッドが採用されている自動運転タスクの分類法を提供します。 また、関連しているが古典的なRLアルゴリズムではない、動作の複製、模倣学習、逆強化学習などの隣接するドメインについても説明します。 トレーニングエージェントにおけるシミュレータの役割、RLの既存のソリューションを検証、テスト、および堅牢化する方法について説明します。
インデックス用語-深層強化学習、自律運転、模倣学習、逆強化学習、コントローラー学習、軌道最適化、動作計画、安全強化学習。by Google翻訳

The main contributions of this work can be summarized as follows:
・Self-contained overview of RL background for the automotive community as it is not well known.
・Detailed literature review of using RL for different autonomous driving tasks.
・Discussion of the key challenges and opportunities for RL applied to real world autonomous driving.
The rest of the paper is organized as follows.

Section II provides an overview of components of a typical autonomous driving system.

Section III provides an introduction to reinforcement learning and briefly discusses key concepts.

Section IV discusses more sophisticated extensions on top of the basic RL framework.

Section V provides an overview of RL applications for autonomous driving problems.

Section VI discusses challenges in deploying RL for real-world autonomous driving systems.

Section VII concludes this paper with some final remarks.

f:id:AI_ML_DL:20210519144158p:plain

f:id:AI_ML_DL:20210519220609p:plain

この表のキャプションは、OPEN-SOURCE FRAMEWORKS AND PACKAGES FOR STATE OF THE ART RL/DRL ALGORITHMS AND EVALUATION.(最先端のRL / DRLアルゴリズムと評価のためのオープンソースフレームワークとパッケージ。by Google翻訳

この表の最後にあるDeepMindの"bsuit"の論文を見よう。

Behaviour Suite for Reinforcement Learning
Ian Osband, Yotam Doron, Matteo Hessel, John Aslanides, Eren Sezener, Andre Saraiva, Katrina McKinney, Tor Lattimore, Csaba Szepesvari, Satinder Singh, Benjamin Van Roy, Richard Sutton, David Silver, and Hado Van Hasselt,                                        arXiv:1908.03568v3 [cs.LG] 14 Feb 2020
Abstract
This paper introduces the Behaviour Suite for Reinforcement Learning, or bsuite for short. bsuite is a collection of carefully-designed experiments that investigate core capabilities of reinforcement learning (RL) agents with two objectives. First, to collect clear, informative and scalable problems that capture key issues in the design of general and efficient learning algorithms. Second, to study agent behaviour through their performance on these shared benchmarks. To complement this effort, we open source
github.com/deepmind/bsuite, which automates evaluation and analysis of any agent on bsuite. This library facilitates reproducible and accessible research on the core issues in RL, and ultimately the design of superior learning algorithms. Our code is Python, and easy to use within existing projects. We include examples with OpenAI Baselines, Dopamine as well as new reference implementations. Going forward, we hope to incorporate more excellent experiments from the research community, and commit to a
periodic review of bsuite from a committee of prominent researchers.
このホワイトペーパーでは、強化学習のためのBehavior Suite、または略してbsuiteを紹介します。 bsuiteは、2つの目的を持つ強化学習(RL)エージェントのコア機能を調査する慎重に設計された実験のコレクションです。まず、一般的で効率的な学習アルゴリズムの設計における重要な問題を捉えた、明確で有益でスケーラブルな問題を収集します次に、これらの共有ベンチマークでのパフォーマンスを通じてエージェントの動作を調査します。この取り組みを補完するために、私たちはオープンソース
github.com/deepmind/bsuite。bsuite上のエージェントの評価と分析を自動化します。このライブラリは、RLの主要な問題に関する再現性のあるアクセス可能な研究を促進し、最終的には優れた学習アルゴリズムの設計を促進します。私たちのコードはPythonであり、既存のプロジェクト内で簡単に使用できます。 OpenAIベースライン、ドーパミン、および新しいリファレンス実装の例が含まれています。今後は、研究コミュニティからのより優れた実験を取り入れ、著名な研究者の委員会による定期的なbsuiteのレビューに取り組んでいきたいと考えています。by Google翻訳

Interest in artificial intelligence has undergone a resurgence in recent years. Part of this
interest is driven by the constant stream of innovation and success on high profile challenges previously deemed impossible for computer systems. Improvements in image recognition are a clear example of these accomplishments, progressing from individual digit recognition (LeCun et al., 1998), to mastering ImageNet in only a few years (Deng et al., 2009; Krizhevsky et al., 2012). The advances in RL systems have been similarly impressive: from checkers (Samuel, 1959), to Backgammon (Tesauro, 1995), to Atari games (Mnih et al., 2015a), to competing with professional players at DOTA (Pachocki et al., 2019) or StarCraft (Vinyals et al., 2019) and beating world champions at Go (Silver et al., 2016). Outside of playing games, decision systems are increasingly guided by AI systems (Evans & Gao, 2016).

近年、人工知能への関心が復活しています。 この関心の一部は、以前はコンピュータシステムでは不可能と考えられていた注目を集める課題に対する革新と成功の絶え間ない流れによって推進されています。 画像認識の改善は、これらの成果の明確な例であり、個々の数字の認識(LeCun et al, 1998)からわずか数年でImageNetを習得する(Deng et al, 2009; Krizhevsky et al, 2012)まで進んでいます。 RLシステムの進歩も同様に印象的でした。チェッカー(Samuel, 1959)、バックギャモン(Tesauro, 1995)、アタリゲーム(Mnih et al, 2015a)、DOTAでのプロプレーヤーとの競争(Pachocki et al, 2019)またはStarCraft(Vinyals et al, 2019)およびGo(Silver et al, 2016)で世界チャンピオンを破っています。 ゲームをプレイする以外に、意思決定システムはますますAIシステムによって導かれています(Evans&Gao, 2016年)。by Google翻訳

As we look towards the next great challenges for RL and AI, we need to understand our systems better (Henderson et al., 2017). This includes the scalability of our RL algorithms, the environments where we expect them to perform well, and the key issues outstanding in the design of a general intelligence system. We have the existence proof that a single self-learning RL agent can master the game of Go purely from self-play (Silver et al., 2018). We do not have a clear picture of whether such a learning algorithm will perform well at driving a car, or managing a power plant. If we want to take the next leaps forward, we need to continue to enhance our understanding.

RLとAIの次の大きな課題に目を向けるとき、システムをよりよく理解する必要があります(Henderson et al, 2017)。 これには、RLアルゴリズムのスケーラビリティ、それらが適切に機能すると予想される環境、および未解決の主要な問題が含まれます。
一般的なインテリジェンスシステムの設計において。 単一の自己学習RLエージェントが純粋に自己プレイから囲碁のゲームを習得できるという存在証明があります(Silver et al, 2018)。 そのような学習アルゴリズムが車の運転や発電所の管理でうまく機能するかどうかについては、明確な見通しがありません。 次の飛躍を遂げたいのであれば、理解を深めていく必要があります。 by Google翻訳

これは、Reinforcement Learningを復活させたDeepMindの研究者らの論文である。DeepMindの創業者はゲームの達人だったようで、Reinforcement Learningを再発見し、コンピュータゲームとボードゲームを征服し、Reinforcement Learningをさらに発展させ、応用範囲を拡げているようである。

囲碁、将棋、チェスでヒトを超えた。車の運転や発電所の管理でも既にヒトを超えている。後者は前者にはないセンサーや計測器からのリアルタイム情報が必要だというだけで、基本は同じなんだろうか。

 

5月20日(木)

  • Bristol-Myers Squibb
  • , 749 teams
  • 14 days to go

99%以上の正確さで分子構造のぼやけた画像からInChIコードに変換できるというのは、コード変換規則を正しく適用しているだけにしか見えないくらい凄いことだと思う。

自分の入る余地は無い。解法を楽しみに待つ。

 

Reinforcement Learning

ひきつづき、"Behaviour Suite for Reinforcement Learning" by DeepMindに学ぼう。

1.1 Practical theory often lags practical algorithms:

The current theory of deep RL is still in its infancy. In the absence of a comprehensive theory, the community needs principled benchmarks that help to develop an understanding of the strengths and weakenesses of our algorithms.

ディープRLの現在の理論はまだ揺籃期にあります。 包括的な理論がない場合、コミュニティは、アルゴリズムの長所と短所の理解を深めるのに役立つ原則的なベンチマークを必要としています。by Google翻訳

1.2 An ‘MNIST’ for reinforcement learning

Just as the MNIST dataset offers a clean, sanitised, test of image recognition as a stepping stone to advanced computer vision; so too bsuite aims to instantiate targeted experiments for the development of key RL capabilities.

1.3 Open source code, reproducible research

As part of this project we open source github.com/deepmind/bsuite, which instantiates all experiments in code and automates the evaluation and analysis of any RL agent on bsuite. This library serves to facilitate reproducible and accessible research on the core issues in reinforcement learning.

1.4 Related work

2 Experiments

2.1 Example experiment: memory length

f:id:AI_ML_DL:20210520162152p:plain

f:id:AI_ML_DL:20210520162248p:plain

読んで理解しようとしたが、課題が何なのか、次の語句が何なのか(DQNは見たことがあるという程度)、さっぱりわからない。
actor-critic with a recurrent neural network

feed-forward DQN

Bootstrapped DQN

A2C

A. Geronさんの第2版のテキストの18章 Reinforcement Learningに、これらの語句の説明があるので、次は、この章を見ていくことにする。全57ページ。

ゲームの話から始まるので、挑戦するたびに挫折したが、もう引くに引けない状況になった。これをクリヤ―しない事には、人工知能の世界では生き残れないので。

始まりは1950年ごろとある。私が生まれた頃だな。アッ、年がばれた。

注目されたのが2013年。DeepMindAtariに対する取り組み。ゲームのルールの情報を与えることなく、画面情報だけから、ヒトに優るスコアを出したとのこと。

DeepMindGoogleに$500 millionで買収された。

Deep Reinforcement Learningと称される手法の重要な技術要素は、policy gradientsとdeep Q networksと、Markov decision processである。

これらを、動くカート上のポールバランスに適用する。
TensorFlow-Agentsライブラリーを導入する。

このライブラリーを使って、Atariの有名なゲームBreakoutをプレーするエージェントを訓練する。

結局は、ゲームか、と思ってしまうが、これをクリヤしないと先はないということだと観念して取り組もう。Bristol-Myers Squibbコンペが終了するまでに。

Hands-One Machine Learning with Scikit-Learn, Keras & TensorFlow by A. Geron, Second Edition September 2019

Chapter 18 Reinforcement Learning

Reinforcement Learning (RL) is one of the most exciting fields of Machine Learning today, and also one of the oldest.

DeepMind applied the power of Deep Learning to the field of Reinforcement Learning, and it worked beyond their wildest dreams.

In this chapter we will first explain what Reinforcement Learning is and what it's good at, then present two of the most important techniques in Deep Reinforcement Learningpolycy gradients and deep Q-networks (DQNs), including a discussion of Markov decision processes (MDPs). 

 

5月21日(金)

Bristol-Myers Squibb:756 teams, 13 days to go

休眠中:スコア1.0でも14位とは、すごいな。

分子構造の画像を修正するコードを見た。ドット状のノイズを消去する、直線の欠けたドットを補充する、周辺の不要部分をカットする、などだが、これに加えて、炭素原子を追加するとか、炭素の位置情報を追加するなどの作業をreinforcement learningでやるためにはどうすればよいのだろうか。

 

Learning to Optimize Rewords

agentは、設定された環境においてwithin an environment、状況を観察/把握しmake observation、行動するtakes actionsことによって、報酬rewardsを得る。

task例

ロボット:agentはロボットを制御するプログラム、environmentはロボットの行動範囲、環境の把握(make obsevations)はカメラによる画像やタッチセンサーからの信号によって行う、actionはロボットを移動させる信号の送付や動作させるための信号の送付、rewardsは目的地への到達や所定の動作や所要時間などの達成度となる。

Pac-Man:agentはPac-Manをコントロールするプログラム、environmentはAtari gameのシミュレーション(意味がわからない:わかった。ゲームに勝つagentをtrainingするために、実際のゲームと同じ動作をさせるということだ。:どのタスクにおいても、trainingするためには実際のenvironmentを仮想的に作り出すことが必要なのだ。これは、supervised learningにおけるdata-labelセットと同様の役割を担うということか。:自動運転のagentをtrainingするためには、実際に道路を走らせて画像やレーダー信号などを収集するする必要があるということ。)、actionはジョイスティックの位置設定、observationsはスクリーンショット、rewardsは得点となる。

囲碁Pac-Manと同様、rewardsは、占有領域となる。

サーモスタット:わざわざreinforcement learningを導入して何をしようとするのかわかない。目的物の温度が設定温度に近いほどrewardsを高くする。目的物の温度はセンサーで検知する。加熱装置と冷却装置を交互に動作させるのか、過熱または冷却のみを動作させて設定温度に近づけるのか。キーワードは、smart thermosutatであった。

smart thermostat:ウィキペディアから関係ありそうな箇所を引用:

プログラム可能なスケジュールと自動スケジュール
スマートサーモスタットのプログラム可能なスケジュール機能は、標準のプログラム可能なサーモスタットの機能と似ています。ユーザーは、家から離れているときにエネルギー使用量を減らすためにカスタムスケジュールをプログラムするオプションが与えられます。ただし、調査によると、スケジュールを手動で作成すると、サーモスタットを設定温度に維持するよりも多くのエネルギー使用量につながる可能性があります。[8]この問題を回避するために、スマートサーモスタットは自動スケジュール機能も提供します。この機能では、アルゴリズムパターン認識を使用して、乗員の快適さとエネルギー節約につながるスケジュールを作成する必要があります。スケジュールを作成すると、サーモスタットは乗員の行動を監視し続け、自動スケジュールを変更します。スケジューリングから人為的エラーを取り除くことにより、スマートサーモスタットは実際にエネルギーを節約するスマートスケジュールを作成できます。[13]

agentはサーモスタットの動作条件を制御するプログラムということか。

他には、株式取引、recommender system, placing ads on a web page, controlling where an image classification system should focus its attentionなどがある。

Reinforcement Learningを適用するのに適したタスクにはどのようなものがあるのか。どのような応用分野があるのかを調査する必要がありそうだ。

Reinforcement Learning, suited tasks, applied areas, ..., 適当なキーワードを用いてGoogle Scholarで検索してみよう。

Reinforcement learning for personalization: A systematic literature review

Floris den Hengst et al., Data Science 3 (2020) 107–147

Abstract.

The major application areas of reinforcement learning (RL) have traditionally been game playing and continuous control. In recent years, however, RL has been increasingly applied in systems that interact with humans. RL can personalize digital systems to make them more relevant to individual users. Challenges in personalization settings may be different from challenges found in traditional application areas of RL. An overview of work that uses RL for personalization, however, is lacking. In this work, we introduce a framework of personalization settings and use it in a systematic literature review. Besides
setting, we review solutions and evaluation strategies. Results show that RL has been increasingly applied to personalization problems and realistic evaluations have become more prevalent. RL has become sufficiently robust to apply in contexts that involve humans and the field as a whole is growing. However, it seems not to be maturing: the ratios of studies that include a comparison or a realistic evaluation are not showing upward trends and the vast majority of algorithms are used only once. This review can be used to find related work across domains, provides insights into the state of the field and identifies opportunities for future work.
強化学習(RL)の主な応用分野は、伝統的にゲームプレイと継続的な制御でした。しかし、近年、RLは人間と相互作用するシステムにますます適用されています。 RLは、デジタルシステムをパーソナライズして、個々のユーザーとの関連性を高めることができます。パーソナライズ設定の課題は、RLの従来のアプリケーション分野で見られる課題とは異なる場合があります。ただし、パーソナライズにRLを使用する作業の概要は不足しています。この作業では、パーソナライズ設定のフレームワークを紹介し、系統的文献レビューで使用します。設定に加えて、ソリューションと評価戦略を確認します。結果は、RLがパーソナライズの問題にますます適用され、現実的な評価がより一般的になっていることを示しています。 RLは、人間が関与するコンテキストに適用するのに十分な堅牢性を備えており、フィールド全体が成長しています。ただし、成熟していないようです。比較または現実的な評価を含む研究の比率は上昇傾向を示しておらず、アルゴリズムの大部分は1回しか使用されていません。このレビューは、ドメイン間で関連する作業を見つけるために使用でき、フィールドの状態への洞察を提供し、将来の作業の機会を特定します。by Google翻訳

The Societal Implications of Deep Reinforcement Learning

Jess Whittlestone et al., Journal of Artificial Intelligence Research 70 (2021) 1003–1030 

Abstract
Deep Reinforcement Learning (DRL) is an avenue of research in Artificial Intelligence
(AI) that has received increasing attention within the research community in recent years,
and is beginning to show potential for real-world application. DRL is one of the most
promising routes towards developing more autonomous AI systems that interact with and take actions in complex real-world environments, and can more flexibly solve a range of problems for which we may not be able to precisely specify a correct ‘answer’. This could have substantial implications for people’s lives: for example by speeding up automation in various sectors, changing the nature and potential harms of online influence, or introducing new safety risks in physical infrastructure. In this paper, we review recent progress in DRL, discuss how this may introduce novel and pressing issues for society, ethics, and governance, and highlight important avenues for future research to better understand DRL’s societal implications.  

Deep Reinforcement Learning(DRL)は、近年研究コミュニティ内でますます注目を集めている人工知能(AI)の研究手段であり、実際のアプリケーションの可能性を示し始めています。 DRLは、複雑な実世界の環境と相互作用してアクションを実行する、より自律的なAIシステムを開発するための最も有望なルートのひとつであり、正しい答えを正確に特定できない可能性のあるさまざまな問題をより柔軟に解決できます。これは、人々の生活に大きな影響を与える可能性があります。たとえば、さまざまなセクターでの自動化の高速化、オンラインの影響の性質と潜在的な害の変化、物理インフラストラクチャへの新しい安全上のリスクの導入などです。このホワイトペーパーでは、DRLの最近の進歩を確認し、これが社会、倫理、ガバナンスに斬新で差し迫った問題をどのようにもたらすかについて説明し、DRLの社会的影響をよりよく理解するための将来の研究のための重要な手段を強調します。by Google翻訳

 

5月22日(土)

Bristol-Myers Squibb764 teams 12 days to go

トップ50のスコアは日々更新されている。凄いことだ。仲間に入りたいものだ。

 

Deep Reinforcement Learning

Reinforcement learning for personalization: A systematic literature review

この論文が何を扱っているのかまだ理解できていない。

WikipediaPersonalization (broadly known as customization) consists of tailoring a service or a product to accommodate specific individuals, sometimes tied to groups or segments of individuals. A wide variety of organizations use personalization to improve customer satisfaction, digital sales conversion, marketing results, branding, and improved website metrics as well as for advertising. Personalization is a key element in social media and recommender systems.

systematic literature review (SLR):この論文が、Reinforcement learning for personalizationの内容の論文をレビューしているのだと思ったが、SLRにRLを適用し、personalizationにLRを適用した文献の調査を行ったということなのだろうか。

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

The Societal Implications of Deep Reinforcement Learning

1. Introduction

Our discussion aims to provide important context and a clear starting point for the AI ethics and governance community to begin considering the societal implications of DRL in more depth.

私たちの議論は、AI倫理およびガバナンスコミュニティがDRLの社会的影響をより深く検討し始めるための重要なコンテキストと明確な出発点を提供することを目的としています。by Google翻訳

この論文も芯を外しているようだ。

2. Deep Reinforcement Learning: a Brief Overview

確かに、 簡単な概要だ。共感できるものが無かった。受け取り側が悪いということにしておこう。

Acknowledgementsの手前の、最後のパラグラフの和訳を張り付けて終わろうと思う。

DRLは、AIの将来において重要な役割を果たす可能性が高く、ますます自律的で柔軟なシステムを約束し、ますますハイステークスドメインでのアプリケーションの可能性を秘めています。 その結果、DRLは、AIの安全で責任ある使用に関する議論を形作る多くの懸念をもたらし、悪化させ、AIの影響のより一般的な処理では見落とされる可能性があります。 社会にとって最も差し迫った課題はAI研究の進歩の正確な性質に依存するため、将来のAIシステムの課題に備えるために、AIの進歩とAIガバナンスに取り組むグループ間の強力なコラボレーションを構築および維持することが重要です。

by Google翻訳

今日も内容の薄いものになってしまった。

A. Geronさんのテキストに戻ろう。

Plycy Search

The algorithm a software agent uses to determine its actions is called its policy.                The policy could be a neural network taking observations as inputs and outputting the action to take (see Figure 18-2).

Figure 18-2. Reinforcement Learning using a neural network polycy:この図は何度も見ていたのだが、今日、ようやくこの模式図の意味するところがわかったように思う。

左側にAgentの枠が描かれ、右側にEnvironmentの枠が描かれている。Agentの枠からenvironmentの枠に向かう→はActionsで、EnvironmentからAgentに向かう→はRewarsとObservationsである。よく見かける模式図だが、違うのは、Agentの枠内にヒト形ロボットの模式図とその頭部から雲形の吹き出しが描かれ、吹き出しの中にニューラルネットワークの模式図が描かれていて、入力側のノードはRewardsとObservationsが接続され、出力側のノードはActionsが接続されていることである。

この後にPolycyの説明が図を含めて1ページくらい続く。Agentは掃除ロボットで、stochastic policy, policy space, genetic algorithmsなどの用語の簡単な説明がある。そのあとで、rewardsのpolicy parameterに対する勾配を用いた最適化に言及し、このpolicy gradient (PG)の良く知られたアルゴリズムをTensorFlowで実装すると述べ、agentの居場所であるenvironmentを作るために必要なOpenAI Gymの導入となる。

 

5月23日(日)

Bristol-Myers Squibb:772 teams, 11 days to go

トップのスコアが0.60になり、チームも入れ替わった。1.00以下が15チーム。

 

Deep Reinforcement Learningと物理化学

物理や化学への応用事例がないか探していて、最初に目に付いたのが、次の論文。

Structure prediction of surface reconstructions by deep reinforcement learning
Søren A Meldgaard, Henrik L Mortensen, Mathias S Jørgensen and Bjørk Hammer

Published 8 July 2020 • © 2020 IOP Publishing Ltd
Journal of Physics: Condensed Matter, Volume 32, Number 40

Abstract
We demonstrate how image recognition and reinforcement learning combined may be used to determine the atomistic structure of reconstructed crystalline surfaces. A deep neural network represents a reinforcement learning agent that obtains training rewards by interacting with an environment. The environment contains a quantum mechanical potential energy evaluator in the form of a density functional theory program. The agent handles the 3D atomistic structure as a series of stacked 2D images and outputs the next atom type to place and the atomic site to occupy. Agents are seen to require 1000–10 000 single point density functional theory evaluations, to learn by themselves how to build the optimal surface reconstructions of anatase TiO2(001)-(1 × 4) and rutile SnO2(110)-(4 × 1).

 

Gaussian representation for image recognition and reinforcement learning of atomistic structure

Mads-Peter V Christiansen, Henrik Lund Mortensen, Søren Ager Meldgaard, and        Bjørk Hammer, J Chem Phys. 2020 Jul 28;153(4):044107

Abstract
The success of applying machine learning to speed up structure search and improve property prediction in computational chemical physics depends critically on the representation chosen for the atomistic structure. In this work, we investigate how different image representations of two planar atomistic structures (ideal graphene and graphene with a grain boundary region) influence the ability of a reinforcement learning algorithm [the Atomistic Structure Learning Algorithm (ASLA)] to identify the structures from no prior knowledge while interacting with an electronic structure program. Compared to a one-hot encoding, we find a radial Gaussian broadening of the atomic position to be beneficial for the reinforcement learning process, which may even identify the Gaussians with the most favorable broadening hyperparameters during the structural search. Providing further image representations with angular information inspired by the smooth overlap of atomic positions method, however, is not found to cause further speedup of ASLA.

 

Predictive Synthesis of Quantum Materials by Probabilistic Reinforcement Learning
Pankaj Rajak, Aravind Krishnamoorthy, Ankit Mishra, Rajiv Kalia, Aiichiro Nakano and Priya Vashishta, arXiv.org > cond-mat > arXiv:2009.06739v1, [Submitted on 14 Sep 2020]

Abstract
Predictive materials synthesis is the primary bottleneck in realizing new functional and quantum materials. Strategies for synthesis of promising materials are currently identified by time consuming trial and error approaches and there are no known predictive schemes to design synthesis parameters for new materials. We use reinforcement learning to predict optimal synthesis schedules, i.e. a time-sequence of reaction conditions like temperatures and reactant concentrations, for the synthesis of a prototypical quantum material, semiconducting monolayer MoS2, using chemical vapor deposition. The predictive reinforcement leaning agent is coupled to a deep generative model to capture the crystallinity and phase-composition of synthesized MoS2 during CVD synthesis as a function of time-dependent synthesis conditions. This model, trained on 10000 computational synthesis simulations, successfully learned threshold temperatures and chemical potentials for the onset of chemical reactions and predicted new synthesis schedules for producing well-sulfidized crystalline and phase-pure MoS2, which were validated by computational synthesis simulations. The model can be extended to predict profiles for synthesis of complex structures including multi-phase heterostructures and can also predict long-time behavior of reacting systems, far beyond the domain of the MD simulations used to train the model, making these predictions directly relevant to experimental synthesis. 

 

Learning to grow: control of material self-assembly using evolutionary reinforcement learning
Stephen Whitelam and Isaac Tamblyn, arXiv:1912.08333v3 [cond-mat.stat-mech] 28 May 2020

We show that neural networks trained by evolutionary reinforcement learning can enact efficient molecular self-assembly protocols. Presented with molecular simulation trajectories, networks learn to change temperature and chemical potential in order to promote the assembly of desired structures or choose between competing polymorphs. In the first case, networks reproduce in a qualitative sense the results of previously-known protocols, but faster and with higher fidelity; in the second case they identify strategies previously unknown, from which we can extract physical insight. Networks that
take as input the elapsed time of the simulation or microscopic information from the system are both effective, the latter more so. The evolutionary scheme we have used is simple to implement and can be applied to a broad range of examples of experimental self-assembly, whether or not one can monitor the experiment as it proceeds. Our results have been achieved with no human input beyond the specification of which order parameter to promote, pointing the way to the design of synthesis protocols by artificial intelligence.

 

Generative Adversarial Networks for Crystal Structure Prediction
Sungwon Kim, Juhwan Noh, Geun Ho Gu, Alan Aspuru-Guzik, and Yousung Jung         ACS Cent. Sci. 2020, 6, 1412−1420 

ABSTRACT: The constant demand for novel functional materials calls for efficient strategies to accelerate the materials discovery, and crystal structure prediction is one of
the most fundamental tasks along that direction. In addressing this challenge, generative models can offer new opportunities since they allow for the continuous navigation of chemical space via latent spaces. In this work, we employ a crystal representation that is inversion-free based on unit cell and fractional atomic coordinates and build a generative adversarial network for crystal structures. The proposed model is applied to generate the Mg−Mn−O ternary materials with the theoretical evaluation of their photoanode properties for high-throughput virtual screening (HTVS). The proposed generative HTVS framework predicts 23 new crystal structures with reasonable calculated stability and band gap. These findings suggest that the generative model can be an effective way to explore hidden portions of the chemical space, an area that is usually unreachable when conventional substitutionbased discovery is employed.

 

いくつかの論文を眺めてみて、Deep Reinforcement Learning (DRL) が自然科学においても非常に重要な択割を果たしており、急激に拡がりつつあることがわかった。

A. Geronさんのテキストに戻って、DRLを学ぼう。

 

5月24日(月)

Bristol-Myers Squibb:781 teams, 10 days to go

ケロッピアバターGMのスレッドを眺めてみた。

関連情報収集力、集約力、再構成力、等々に感心するばかり。

 

Reinforcement Learning:A. Geronさんのテキストを用いた学習

Introduction to OpenAI Gym:食わず嫌いだったOpenAI Gym

agentのトレーニングには、working environmentが必要。そのためのsimulated environmentを提供するのがOpenAI Gym (Atari games, board games, 2D and 3D physical simulations, and so on)。

さて、テキストでは、OpenAI Gymをインストールする方法が説明されている。

次に、CartPoleを動かしながらの説明が続いている。

import gym

env = gym.make("CartPole-v1")

obs = env.reset( )

obs

array([-0.01258566, -0.00156614, 0.04207708, -0.00180545])

CartPileは、2D physical simulationということのようだ。

obsは1D NumPy arrayで、4つの数字が、obs[0]: cart's horizontal position (0.0 = center), obs[1]: its velocity (positive means right), obs[2]: the angle of the pole (0.0 = vertical), and obs[3]: its angular velocity (positive means clockwise)の順に並んでいる。

CartPoleなんて面白くもなんともないから気が入らない。と思いながらしぶしぶテキストを眺めている。

>>> env.action_space

Discrete(2)

actionは2通り、integerで0と1、0はleftに加速、1はrightに加速。

>>> action = 1   # accelerate right

>>> obs, reward, done, info = env.step(action)

>>> obs

array([-0.01261699, 0.19292789, 0.04204097, -0.028092127])

>>> reward

1.0

>>> done

False

>>> info

{ }

The step( ) method exacutes the given action and returns four values:

obs:

This is the new observation. The cart is now moving toward the right (obs[1] > 0). The pole is still tilted toward the right (obs[2] >0), but its angular velosity is now negative (obs[3] <0), so it will likely be tilted toward the left after the next step.

reward:

In this environment, you get a reward of 1.0 at every step, no matter what you do, so that the goal is to keep the episode running as long as possible.

done:

This value will be True when the episode is over. This will happen when the pole tilts too much, or goes off the screen, or after 200 steps (in this last case, you have won). After that, the environment must be reset before it can be used again.

info:

This environment-specific dictionary can provide some extra information that you may find useful for debugging or for training. For example, in some games it may indicate how many lives the agent has.

まずは、単純なポリシーの場合:ポールが右側に倒れていたらcartを右側に加速し、ポールが左側に倒れていたらcartを左側に加速するというもの。

def basic_policy(obs):

      angle = obs[2]  # angle of the pole

      return 0 if angle < 0 else 1

 

totals = [ ]

for episode in range(500):

      episode_rewarda = 0

      obs = env.reset( )

      for step in range(200):

           action = basic_policy(obs)

           obs, reward, done, info = env.step(action)

           episode_rewards += reward

           if done:

                break

      totals.append(episode_rewards)

これを実行してみると、次のような結果となった。

>>> import numpy as np

>>> np.mean(totals), np.std(totals), np.min(totals), np.max(totals)

(41.718, 8.858356280936096, 24.0, 68.0)

poleが倒れなければ(ポールの傾きがある設定角度以下、かつ、カートが画面の中にある場合)、1 stepあたりrewardは1.0である。結果を見るとポールの保持に成功した平均step回数は41.7、標準偏差は8.9、最小ステップ数は24、最大ステップ数は68となったということである。

68 step以上の間、ポールを保持できなかったということである。neural networkを使えばpolicyを改善することができるということが次に示される。

Neural Network Policies

いよいよニューラルネットワークが登場する。 ニューラルネットワークにobservationを入力し、実行するactionを出力する。このとき出力されるのはactionの確率である。この確率に従ってactionをランダムに決める。

 

5月25日(火)

  • Bristol-Myers Squibb:782 teams, 9 days to go
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

今日も、ケロッピアバターGMのスレッドを眺めてみた。使われている単語の意味がわからないものばかり。いくつかを調べてみた。

Fairseq is a sequence modeling toolkit written in PyTorch that allows researchers and developers to train custom models for translation, summarization, language modeling and other text generation tasks.

Numba is an open source JIT compiler that translates a subset of Python and NumPy code into fast machine code.

pre-norm activation transformer:

Transformers without Tears: Improving the Normalization of Self-Attention

Toan Q. Nguyen and Julian Salazar, arXiv:1910.05895v2 [cs.CL] 30 Dec 2019

Abstract
We evaluate three simple, normalizationcentric changes to improve Transformer
training. First, we show that pre-norm residual connections (PRENORM) and smaller initializations enable warmup-free, validation-based training with large learning rates. Second, we propose `2 normalization with a single scale parameter (SCALENORM) for faster training and better performance. Finally, we reaffirm the effectiveness of normalizing word embeddings to a fixed length (FIXNORM). On five low-resource translation pairs from TED Talks-based corpora, these changes always converge, giving an average +1.1 BLEU over state-of-the-art bilingual baselines and a new 32.8 BLEU on IWSLT '15 EnglishVietnamese. We observe sharper performance curves, more consistent gradient norms, and a linear relationship between activation scaling and decoder depth. Surprisingly, in the highresource setting (WMT '14 English-German), SCALENORM and FIXNORM remain competitive but PRENORM degrades performance.

Transformerトレーニングを改善するために、3つの単純な正規化中心の変更を評価します。 まず、ノルム前の残余接続(PRENORM)と小さな初期化により、ウォームアップのない検証ベースのトレーニングが大きな学習率で可能になることを示します。 次に、トレーニングを高速化し、パフォーマンスを向上させるために、単一のスケールパラメータ(SCALENORM)を使用した `2正規化を提案します。 最後に、単語の埋め込みを固定長(FIXNORM)に正規化することの有効性を再確認します。 TED Talksベースのコーパスからの5つの低リソース翻訳ペアでは、これらの変更は常に収束し、最先端のバイリンガルベースラインを平均+1.1 BLEU、IWSLT '15EnglishVietnameseで新しい32.8BLEUを提供します。 よりシャープなパフォーマンス曲線、より一貫性のある勾配基準、およびアクティベーションスケーリングとデコーダー深度の間の線形関係を観察します。 驚いたことに、高リソース設定(WMT '14英語-ドイツ語)では、SCALENORMとFIXNORMは引き続き競争力がありますが、PRENORMはパフォーマンスを低下させます。by Google翻訳

次の2つの論文は、基礎知識。

Show and Tell: A Neural Image Caption Generator
Oriol Vinyals, Alexander Toshev, Samy Bengio, and Dumitru Erhan
arXiv:1411.4555v2 [cs.CV] 20 Apr 2015

Abstract
Automatically describing the content of an image is a fundamental problem in artificial intelligence that connects computer vision and natural language processing. In this
paper, we present a generative model based on a deep recurrent architecture that combines recent advances in computer vision and machine translation and that can be used to generate natural sentences describing an image. The model is trained to maximize the likelihood of the target description sentence given the training image. Experiments on several datasets show the accuracy of the model and the fluency of the language it learns solely from image descriptions. Our model is often quite accurate, which we verify both qualitatively and quantitatively. For instance, while the current state-of-the-art BLEU-1 score (the higher the better) on the Pascal dataset is 25, our approach yields 59, to be compared to human performance around 69. We also show BLEU-1 score improvements on Flickr30k, from 56 to 66, and on SBU, from 19 to 28. Lastly, on the newly released COCO dataset, we achieve a BLEU-4 of 27.7, which is the
current state-of-the-art.

画像の内容を自動的に記述することは、コンピュータービジョンと自然言語処理を結び付ける人工知能の基本的な問題です。この論文では、コンピュータビジョンと機械翻訳の最近の進歩を組み合わせ、画像を説明する自然な文を生成するために使用できる、ディープリカレントアーキテクチャに基づく生成モデルを提示します。モデルは、トレーニング画像が与えられた場合にターゲットの説明文の可能性を最大化するようにトレーニングされます。いくつかのデータセットでの実験は、モデルの正確さと、画像の説明からのみ学習する言語の流暢さを示しています。私たちのモデルはしばしば非常に正確であり、定性的および定量的に検証します。たとえば、Pascalデータセットの現在の最先端のBLEU-1スコア(高いほど良い)は25ですが、私たちのアプローチでは59が得られ、69前後の人間のパフォーマンスと比較されます。BLEU-1も示しています。 Flickr30kのスコアが56から66に、SBUのスコアが19から28に向上しました。最後に、新しくリリースされたCOCOデータセットで、現在の最先端のBLEU-4である27.7を達成しました。by Google翻訳

f:id:AI_ML_DL:20210525120808p:plain

f:id:AI_ML_DL:20210525120945p:plain

f:id:AI_ML_DL:20210525121037p:plain

Show, Attend and Tell: Neural Image Caption Generation with Visual Attention

Kelvin Xu et al., arXiv:1502.03044v3 [cs.LG] 19 Apr 2016

Abstract
Inspired by recent work in machine translation and object detection, we introduce an attention based model that automatically learns to describe the content of images. We describe how we can train this model in a deterministic manner using standard backpropagation techniques and stochastically by maximizing a variational lower
bound. We also show through visualization how the model is able to automatically learn to fix its gaze on salient objects while generating the corresponding words in the output sequence. We validate the use of attention with state-of-theart performance on three benchmark datasets: Flickr8k, Flickr30k and MS COCO.

機械翻訳とオブジェクト検出の最近の研究に触発されて、画像の内容を説明することを自動的に学習する注意ベースのモデルを紹介します。 標準的なバックプロパゲーション手法を使用して、変分下限を最大化することにより確率的にこのモデルを決定論的にトレーニングする方法について説明します。 また、視覚化を通じて、出力シーケンスで対応する単語を生成しながら、モデルが顕著なオブジェクトを注視することを自動的に学習する方法を示します。 Flickr8k、Flickr30k、MS COCOの3つのベンチマークデータセットで、最新のパフォーマンスを使用してattentionの使用を検証します。      by Google翻訳

f:id:AI_ML_DL:20210525122337p:plain

f:id:AI_ML_DL:20210525122541p:plain

Reinforcement Learning
Neural Network Policies

tf.kerasを用いたneural network policyの構築例

inport tensorflow as tf

from tensorflow inport keras

n_inputs = 4  # == env.observation_space.shape[0]

model = keras.models.Sequential([

      keras.layers.Dense(5, activation="elu", input_shape=[n_inputs]),

      keras.layers.Dense(1, activation="sigmoid"),

])

入力層のユニット数は4で、入力するのは、observationsで、position, velocity, angle, angular velocityの4種類である。

hidden layerのユニット数は、簡単な課題なので5としている。活性化関数は"elu"。

出力は、action 0 (left)の確率だけなのでユニット数は1。活性化関数は、出力が確率なので"sigmoid"。

これでneural network policyが構築できた。

入力ユニット数が4、隠れ層のユニット数が5、出力層が1のニューラルネットワークの出来上がり。

先のhardcodeとの違いを認識することが重要:hardcodeは、angle(poleの傾斜角)の極性からactionを決めた。これに対してneural network policyは、台車の位置(0.0が画面の中央)、台車の速度(右方向を正)、ポールの傾斜角(垂直が0.0で時計方向=右に膾炙している場合が正)、角速度(≒ポールが倒れる速さ、時計回りが正)の4つの値の非線形関数から推定した確率からactionを決める。

どうやってtrainingするのだろうか。

Evaluating Actions: The Credit Assighnment Problem(貢献度分配問題)

通常のsupervised learningはできない。先に示したhardcodeのプログラムで、平均以上のステップ数までポールを保持できたエピソードと平均以下のステップ数しか保持できなかった場合について、何をどう学ばせることができるのか。ポールが傾いている方向に台車を加速しているだけなのでより良い条件をどのようにして見つけるのだろうか。

discount factorなるものを導入して思考実験している。積算するrewardの回数と減衰の大きさをコントロールする因子のようである。discount factorが0.95では、13ステップでrewardが半分に、discount factorが0.99では69ステップでrewardが半分になる。

次にgood actionとbad actionが含まれる割合を比較することによってaction advantageを定義すれば、各actionをpositive advantageとnrgative advantageに分類することができる。これで、actionの評価(evaluation)ができたということになるようだ。

理解不十分につき、文章がつながっていないし、意味不明。要検討。

Figure 18-6. Computing an action's return: the sum of discounted future rewardsが、理解できないので、ここで、停止している。

この節の最後は次のように締めくくられている。

Perfect-now that we have a way to evaluate each action, we are ready to train our first agent using policy gradients. Let's see how. 

 

5月26日(水)

Bristol-Myers Squibb:791 teams, 8 days to go

今日は、Deep Reinfoecement Learningの学習を優先しよう。

 

Deep Reinfoecement Learning 

Evaluating Actions: The Credit Assighnment Problem:

本節の1行目から読み直そう。

日本語に訳してもよくわからないので、テキストから抜き書きする。抜き書きでなく、全文になりそうな気配。なぜなら、1行でもとばしたら意味がわからなくなりそうだ。

If we knew what the best action was at each step, we could train the neural network as usual, by minimizing the cross entropy between the estimated probability distribution and the target probability distribution.

It would just be regular supervised learning.

However, in Reinforcement Learning the only guidance the agent gets is through rewards, and rewards are typically sparce and delayed.

For example, if the agent manages to balance the pole for 100 steps, how can it know which of the 100 actions it took were good, and which of them were bad?

All it knows is that the pole fell after the last action, but surely this last action is not entirely responsible.

This is called the credit assignment problem: when the agent gets a reward, it is hard for it to know which actions should get credited (or blamed) for it.

Think of a dog that gets rewarded hours after it behaved well: will it understand what it is being rewarded for?

cart上のpoleが倒れないようにcartを左右に動かす。2次元の大道芸だな。

To tackle  this problem, a common strategy is to evaluate an action based on the sum of all the rewards that come after it, usually applying a discount factor ɤ (gamma) at each step. discount gactorの意味、役割がわからんな。

This sum of discounted rewards is called the action's return.  ここでのactionは、1 stepではなく、一連のstepの集合体を指しているようだ。

consider the example in Figure 18-6.

If an agent decides to go right three times in a row and gets +10 reward after the first step, 0 after the second step, and finally -50 after the third step, then assume we use a discount factor ɤ=0.8, the first action will have a return of 10 + ɤ x 0 + ɤ^2 x (-50) = -22.

ここで頭が混乱する。p.616のrewardの説明では、全てのステップで1.0のrewardを得ると書いてある。ところが、ここでは、rightへのstepを3回繰り返し、最初のstepから10のrewars、2番目のstepから0のreward、3番目のstepから-50のrewardを得ると書いてある。よく考えよう。

 

5月27日(木)

Bristol-Myers Squibb:799 teams, 7 days to go

あと1週間になった。終わってから猛勉強だな。

画像からテキストへの変換だが、分子構造画像からテキスト、図形からテキスト、数式からテキスト、関数からテキスト、方程式からテキスト、物理の理論式からテキスト、化学反応式からテキスト、タンパクの構造式からテキスト、・・・

人の五感に相当するセンサーを備え、自律的に学習し、行動する人工人間を、デザインしてみよう。目標はナンバーファイブだ。

WIKIPEDIAShort Circuit (1986 film)

 

Reinforcement Learning:A. Geronさんのテキスト第18章: Reinforcement Learning

If the discount factor is close to 0, then future rewards won't count for much compared to immediate rewards. 

Conversely, if the discount factor is close to 1, then rewards far into the future will count almost as much as immediate rewards. 

Typical discount factors vary from 0.9 to 0.99.

With a discount factor of 0.95, rewards 13 steps into the future count roughly for half as much as immediate rewards (since 0.95^13≒0.5), while with a discount factor of 0.99, rewards 69 steps into the future count for half as much as immediate rewards. 

In the CartPole environment, actions have fairly short-term effects, so choosing a discount factor of 0.95 seems reasonable. 

Figure 18-6.  Computing an action's return: the sum of discounted future rewards

Of cource, a good action may be followed by several bad actions that cause the pole to fall quickly, resulting in the good action getting a low return (similarly, a good actor may sometimes star in a terrible movie).

However, if we play the game enough times, on average good actions will get a higher return than bad ones.

We want to estimate how much better or worse an action is, compared to the other possible actions, on average.

This is called the action average.

For this, we must run many episodes and normalize all the action returns (by subtracting the mean and dividing by the standard deviation).

After that, we can reasonably assume that actions with a negative advantage were bad while actions with a positive advantage were good.

Perfect - now that we have a way to evaluate each action, we are ready to train our first agent using polycy gradients.

Let's see how.

 

Policy Gradients

As discusses earlier, PG algorithms optimize the parameters of a polycy by following the gradients toward higher rewards.

One popular class of GP algorithms, called REINFORCE algorithms, was introduced back in 1992 (https://homl.info/132) by Ronald Williams. 

Here is one common variant:

 

5月28日(金)

Bristol-Myers Squibb:806 teams, 6 days to go 

進捗なし。

 

5月29日(土)

Bristol-Myers Squibb:816 teams, 6 days to go

進捗なし。

 

5月31日(月)

Bristol-Myers Squibb:831 teams, 4 days to go

Bristol-Myers Squibbをメインに進めていたが、うまくいかず、途中でReinforcement Learningの勉強に切り替える等、何をやってるのかわからなくなった。

 

trainの公開コードを走らせ、チューニングすることで、少しでもコードを理解しよう。

公開コードを走らせる前にAttentionとTransformをきちんと理解しようと思って記事を書いていたのだが、途中で、ブラウザがリセットされ、書きかけの文章が全て消えてしまった。

斎藤康毅著 ゼロから作るDeep Learning 2 自然言語処理編 8章 Attentionから少し引用させていただこう。

8.5.2  Transformer

 私たちはこれまで、RNN(LSTM)をいたるところで使用してきました。言語モデルに始まり、文章生成、seq2seq、そしてAttection付きseq2seqと、その構成要素には必ずRNNが登場しました。そして、このRNNによって、可変長の時系列データはうまく処理され、(多くの場合)良い結果を得ることができます。しかし、RNNにも欠点があります。その欠点のひとつに、並列化処理が挙げられます。

 RNNは、前時刻に計算した結果を用いて逐次的に計算を行います。そのため、RNNの計算を、時間方向で並列的に計算することは(基本的には)できません。この点は、ディープラーニングの計算がGPUを使った並列計算の環境で行われることを想定すると、大きなボトルネックになります。そこで、RNNを避けたいというモチベーションが生まれます。

 そのような背景から、現在ではRNNを取り除く研究(もしくは並列計算可能なRNNの研究)が活発に行われています。これは『Attention is all you need』というタイトルの論文で提案された手法です。そのタイトルが示すとおり、RNNではなくAttentionを使って処理します。ここでは、このTransformerについて簡単に見ていきます。

 TransformerはAttentionによって構成されますが、その中でもSelf-Attentionというテクニックが利用される点が重要なポイントです。このSelf- Attentionは直訳すれば「自分自身に対してのAttention」ということになります。つまりこれは、ひとつの時系列データを対象としたAttentionであり、ひとつの時系列データ内において各要素が他の要素に対してどのような関連性があるのかを見ていこうというものです。私たちのTime Attentionレイヤを使って説明すると、Self-Attentionは図8-37のように書けます。

 これまで私たちは「翻訳」のような2つの時系列データ間の対応関係をAttentionで求めてきました。このときTime Attentionレイヤへの2本の入力には、図8-37の左図で示すように、異なる2つの時系列データ(hs_enc, hs_dec)が入力されます。これに対してSelf-Attentionは、図8-37の右図に示すように、2本の入力線にひとつの時系列データ(hs)が入力されます。そうすることで、ひとつの時系列データ内において各要素間の対応関係が求められます。

 Self-Attentionの説明が済んだので、続いてTransformerのレイヤ構成を見ていただきましょう。Transformerの構成は図8-38のようになります。

 Transformerでは、RNNの代わりにAttentionが使われます。実際に図8-38を見ると、EncoderとDecoderの両者でSelf-Attentionが使われていることがわかります。なお、図8-38のFeed Forwardレイヤは、フィードフォワードのネットワーク(時間方向に独立して処理するネットワーク)を表します。具体的には、隠れ層が1層で活性化関数にReLUを用いた全結合のニューラルネットワークが用いられています。また、図中に「Nx」とありますが、これは背景がグレーで囲まれた要素をN回積み重ねることを意味します。

 このTransformerを用いることで、計算量を抑え、GPUによる並列計算の恩恵をより多く受けることができます。その成果として、TransformerはGNMTに比べて学習時間を大幅に減らすことに成功しました。さらに翻訳精度の点でも、図8-39が示すように、精度向上を実現しました。

 図8-39では、3つの手法が比較されています。その結果は、GNMTよりも「畳み込み層を用いたseq2seq」(図中ではConvS2Sで表記)が精度が高く、さらにTransformerはそれをも上回っています。このように、Attentionは、計算量だけでなく、精度の観点からも有望な技術であることがわかります。

 わたしたちは、これまでAttentionをRNNと組み合わせて利用してきました。しかし、ここでの研究が示唆するように、AttentionはRNNを置き換えるモジュールとしても利用できるのです。これによって、さらにAttentionの利用機会が増えていくかもしれません。 

 以上が、斎藤康毅著 ゼロから作るDeep Learning 2 自然言語処理編 8章 AttentionからのTransformerに関する引用。

 

Bristol-Myers Squibbのtrainの公開コードは、明日走らせてみる予定。

 

6月1日(火)

Bristol-Myers Squibb:841 teams, 3 days to go

50位のスコアが1.42とは、凄い人達が集まっているんだ。

 

公開コード(train)を走らせてみる:

2週間くらいKaggleでcodeを走らせていなかったので、少し、とまどった。

いま走らせているコード”Tensorflow TPU Training Baseline LB 16.92”の動作状況とコードを見ていて思うのは、この2週間を無駄に過ごしたということ。2週間前には、このコードや、このコードの作者が参考にしたコードを学ぼうと計画していたのに、コンペの大通りを離れて脇道に入り、reinforcement learning広場で2週間も遊んでしまったことが悔やまれる。

TPUを使うには、データセットをTFRecordに書き換えるところから始める必要がある。

”Advanced Image Cleaning and TFRecord Generation”

画像を綺麗にする(点状のノイズ消去、線の欠けの修正)こと、画像の不要な外側の空白領域を削除すること、および、TFRecordへの変換を行っている。

画像のサイズを決めるのも容易ではない。作成者はつぎのように記述している。

Choosing an appropriate image size is difficult, as complex molecules will need a high resolution to preserve details, but training on 2.4 million in high resolution is unfeasable. The chosen resolution of 256*448 should preserve enough detail and allow for training on a TPU within the 3 hours limit. 

240万件の画像データを3時間以内に処理しなければならないという条件を満たしたうえで、画像解像度を決めなければならない。trainコードを見ると、1エポックで2.4Mではなく512kのデータをtrainingしている。このとき、何も考えずにやると、1部のデータしか使わないことになる。公開コードに対する質疑から、全データをtrainingできるように途中で改善したとのこと。これを見て、HuBMAPコンペでは、全部のtrainデータを使えず、スコアが上がらなかったのを思い出した。このときは、train_dataを読み込んでからtrainingをスタートする必要があり、メモリーオーバーで1/3程度のtrain_dataが読み込めなかった。しかし、自分でも、train_dataに偏りがあり、全てのtrain_dataを使わないと予測精度が上がらないことは常識なので、対応策を絞り出すべきだったと思う。たとえば、train_dataの2/3の読み込み時間は3分間くらいだから、10エポックのtrainingであれば、エポック毎に異なる組み合わせのtrain_dataを3分かけて読み込んでも30分くらい長くなるだけで全ての訓練データを使うことができて、スコアアップを図れた可能性がある。

画像を綺麗にする(点状のノイズ消去、線の欠けの修正)には、たとえば次のようなコードを用いている。

# single pixel width horizontal line with 1 pixel missing
kernel_h_single_mono = pad_kernel( a, a, a, -1, a, a, a , max_pad=1)

# single pixel width horizontal line with 3 pixels missing
kernel_h_single_triple = pad_kernel( a, a, a, -1, -1, -1, a, a, a , max_pad=1)

kernel_h_multi = pad_kernel([
      [ a, a, a, a, a, a, a ],
      [ a, a, a,-1, a, a, a ],
      [ a, a, a, a, a, a, a ],
], max_pad=1)

こういうのをANNでやりたいと思ったのだが、こういう技術も使えるようになっておくことは重要だと思う。

InChIコードに対して、inchi_intを定義しているようだが、コードを読むことができない。

遊び半分でエポック数を10、20、30と変えて訓練し、訓練済みのパラメータをデータセットに入れて、inferenceプログラムを走らせると、LBスコアは、それぞれ、11.36、8.23、7.85となった。 

これ以上どうなるものでもなさそうだが、とりあえず、あと2日間、discussionや他の公開コードを眺めながら、スコアアップの方法を試してみる。

 

6月2日(水)

Bristol-Myers Squibb:855 teams, 2 days to go

バッチサイズを512から1024にしてみよう。

学習率lrを2e-3~1e-4から1e-3~1e-5にしてみよう。

LBスコアは、9.19と悪化した。

 

明日は、最終日だが、これで終わる。

このコンペは、失敗であった。

 

6月4日(金)

先ほど、Bristol-Myers Squibbコンペの最終結果が出た。コードコンペではないので、結果が即日確定!順位変動も殆どなし。

 

反省の弁

1.コンペに参加する意義は、スコアアップ以外にはない。途中でreinforcement learningに向かったのは、generativeなモデルがスコアアップに必要だと感じたためであるが、reinforcement learningに向かったのは失敗であった。しかも、reinforcement learningの学習中は、集中力を欠いていた。

2.課題が自分の頭では解けなかった(分子構造式とInChIコードの対応関係を最後まで把握できなかった)ために、モデル構築の方向性を見出せず、スコアアップの方向に舵を切ることができなかった。コンペのdiscussionや公開コードをよく見て対策を考えるべきだった。

3.金や銀を意識することは、モチベーションを上げるために重要であるが、今回は、メダル圏内に入ることすら早々にあきらめてしまったために、あらぬ方向に行ってしまい、公開コードのチューニングすら殆ど行わなかった。けろっぴアバターの方が公開していたコードを試すことは、やるべきだったと思う。

 

f:id:AI_ML_DL:20210510234705p:plain

style=165, iteration=500

f:id:AI_ML_DL:20210510235029p:plain

style=165, iteration=50

f:id:AI_ML_DL:20210510235136p:plain

style=165, iteration=5




 

 

Kaggle散歩(1st March to 10th May 2021)

3月1日(月)

HuBMAP1,130 teams, two months to go

今日はBatch_sizeの16と32に違いがあるかどうかを調べる。

EfficientNetB5-UnetのLB=0.836のコードがBatch_size=16だったので、これを32に変更したがGPUのメモリーオーバーとなったため、B4で実行した:結果はLB=0.836となった。

これで改善が認められれば他のDecoderでもやってみるつもりだったが、・・・。

次は、Encoderのpre-training weights('imagenet'を常用している)によって違いがあるかどうかを調べる。

'noisy-student':LB=0.831:0.005下がった。

'advprop':LB=0.823:0.013下がった。

こういうのは、実際に使ってみないとわからないものだ。ただし、エポック数など、最適化できていないパラメータに起因して、スコアが低い、という可能性もある。

次は、pre-trained weightsではなく、random initializationでやってみよう。

A. Geron氏のテキストには、Glorot and He initialization, LeCun initialization, Xavier initializationなどが紹介されている。今使っているSegmentation Modelsでは、これらの initializationには対応していないようである。

random initialization(epochs=30):LB=0.819 :意外に健闘しているようにみえる。

今日のデータはすべて30エポックだが、random initializationについては、明日、エポック数を増やしてみよう。

 

3月2日(火)

HuBMAP:1,142 teams, two months to go

random initialization(epochs=50):LB=0.778:期待外れ。これ以上追求しない。

(lr_schedulerは、OneCycleLRを使い続けているので、エポック数は、OneCycleLRの設定エポック数である。このスケジューラーは、early_stopで監視する必要が無く、極端なoverfittingにもならないようで、便利だが、Max_lrとエポック数の最適化は必須。合間に最適化を試みているが、まだ使いこなせていないように感じている。)

 

ここまで、"An activation function to apply after the final convolution layer. "をNoneにして、 score > 0、で評価してきたが、activation functionを"sigmoid"にして、score > thresholdとして、thresholdの最適化をやってみる。

ちょっとやってみたが、うまくいかない。何かおかしい。間違ったことをしているかもしれない・・・。

 

best single modelというタイトルのdiscussionにおいて、LB=0.84+から0.86+くらいのスコアのモデル(encoder+decoder)、optimizer、loss function、epochsなど概要が紹介されている。自分の結果、0.83+とは最大で0.03くらい違う。前処理、後処理などの情報が少ないので何を参考にすればよいのかわからないが、気になるのは、スコアが高い0.85+の4件が、EncoderにEfficientNetを使っていないことと、開発年代の古いEncoderを用いて、エポック数を多くしていることである。さらに、resnet34-UnetでLB=0.857というスコアを得ているのは驚きだ。FPNは1件で、そのほかはUnetを使っている。

Googleが昨年発表した論文"EfficientDet: Scalable and Efficient Object Detection"で提案している新しいモデルEfficientDetは、FPNから派生したもののようである"we propose a weighted bi-directional feature pyramid network (BiFPN)"。

 

3月3日(水)

HuBMAPに集中している間に、いろいろなコンペが通り過ぎていった。今日、新しいテーマのコンペ案内メールが来ていた。化学系には興味があるので調べてみる。

Bristol-Myers Squibb – Molecular Translation
Can you translate chemical images to text?

chemical imagesというのは構造式、textというのは、InChIのこと。構造式は画像として与えられる。InCHIについて、wikipediaの説明は以下の通り。

InChI(International Chemical Identifier)は、標準的かつ人間が読める方法で分子情報を提供し、またウェブ上でのデータベースからの情報の検索機能を提供する。元々、2000年から2005年にIUPACとNISTによって開発され、フォーマットとアルゴリズムは非営利であり、開発の継続は、IUPACも参画する非営利団体のInChI Trustにより、2010年までサポートされていた。現在の1.04版は、2011年9月にリリースされた。

1.04版の前までは、ソフトウェアはオープンソースGNU Lesser General Public Licenseで無償で入手できたが[3]、現在は、IUPAC-InChI Trust Licenseと呼ばれる固有のライセンスとなっている[4]。ウイキペディアより引用。

構造式を含む文献を電子化する場合に必要となる技術の1つかもしれないが、InChIでは3次元構造は原理的に表現しきれないようであり、InChI表記は無味乾燥であり、機械学習で推測したInChIに学術的価値がどれだけあるのかも理解できないので、やってみようという気にならない。構造式の画像から近似的に3次元分子構造モデルを再現するということであれば楽しく取り組めそうだが、・・・。

 

HuBMAP:1,155 teams, two months to go(データ修正のため順延中)

昨日の取り組み「activation functionを"sigmoid"にして、score > thresholdとして、thresholdの最適化をやってみる。」のつづき。

threshold=0.5で、BCELossとFocalLossで10エポックの場合について調べた。

B5-Unet, BCELoss, AdamW, 10 epochs:LB=0.822 (output_file_ size=5.1 MB)

B5-Unet, FocalLoss, AdamW, 10 epochs:LB=0.799 (output_file_ size=4.94 MB) 

いずれも、出力データのサイズは4.9-5.1 MBとなり、sigmoidを使う前よりも小さい。sigmoidを使わずにLB=0.836となったときの出力データのサイズは、5.5-5.7 MBであった。データサイズとLBスコアとの間には必ずしも比例関係は無いが、今回の場合は、thresholdを下げればLBスコアが上がる可能性がありそうである。

GPUの割当は使い果たしたので、この確認は土曜日以降になる。

activation functionとしては、 “sigmoid”の他に, “softmax”, “logsoftmax”, “tanh”,などが使える。"tanh"は -1 < tanh < 1で、中央値付近の微分係数がsigmoidの4倍になるため、sigmoidよりも収束が速くなりそうだし、感度も高くなるかもしれないので、試してみよう。

 

3月4日(木)

HuBMAP: 1,167 teams, two months to go(データ更新待ち)

GPUが使えないのでCPUで計算する。:B5はメモリーオーバーになるので、計算時間も考えて、B0を使うことにする。B0-UnetでのLBスコアは0.827前後である。

最初にtanhを試す。

B0-Unet(tanh: threshold=0.0)-E10-B16 : LB=0.827

tanhも使えることがわかった。出力データは5.64 MBで、sigmoidの場合よりも大きい。

LBスコアは、sigmoidを使った場合よりも高くなっている。

次に、sigmoidで、thresholdの効果を試す。1サイクルに6時間くらいかかる(GPUなら60分くらい)ので、以下の3つの計算の結果が出そろうのは明日になる。

B0-Unet(sigmoid: threshold=0.50)-E10-B16: LB=0.819(このスコアで閾値を調整しても、とは思うのだが、何事も経験しておくことは大切だ、ということで、・・・。)

B0-Unet(sigmoid: threshold=0.45)-E10-B16: LB=0.820

B0-Unet(sigmoid: threshold=0.40)-E10-B16: LB=0.821

threshold依存性はありそうだ。しかし、このスコアでは、使う気にならない。

 

semantic segmentationについてもっと勉強しよう。 

Deep Semantic Segmentation of Natural and Medical Images: A Review
Saeid Asgari Taghanaki, Kumar Abhishek, Joseph Paul Cohen, Julien Cohen-Adad and Ghassan Hamarneh, arXiv:1910.07655v3 [cs.CV] 3 Jun 2020, 

f:id:AI_ML_DL:20210305000412p:plain

f:id:AI_ML_DL:20210305000510p:plain

Cross Entropy -->  Weighted Cross Entropy --> Focal Loss (Lin et al. (2017b) added the term (1 − pˆ)γ to the cross entropy loss)

Overlap Measure based Loss Functions:Dice Loss / F1 Score -->  Tversky Loss(Tversky loss (TL) (Salehi et al., 2017) is a generalization of the DL(Dice Loss) --> Exponential Logarithmic Loss --> Lovasz-Softmax loss(a smooth extension of the discrete Jaccard loss(IoU loss))

上記のような種々の損失関数の解説の最後に次のように書かれている。

The loss functions which use cross-entropy as the base and the overlap measure functions as a weighted regularizer show more stability during training. 

cross-entropy系をベースに、overlap系を加えることが推奨されている。Fig.12左側のcross-entropyとfocalの曲線は、相補的な特性を示しているように見える。これも組み合わせると良い、ということになるのだろうか。

 

3月5日(金)

HuBMAP:1,176 teams, two months to go(データ更新待ち)

シングルモデルでLB=0.85+となることを目標に、DeepLabV3+に集中してみよう。

DeepLabV3+の性能を発揮させるためには、パラメータを適正に設定しなければならない筈なので、論文を丁寧に読んで、モデルの中身を理解しなければならない。

ここまで、Unet以外の8種類のモデルのどれもが、Unetのスコアを超えられないのは、各モデルのパラメータを適切に設定することができていないからなのだろうと思う。

Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation
Liang-Chieh Chen, Yukun Zhu, George Papandreou, Florian Schroff, and Hartwig Adam
Google Inc. ECCV 2018

Abstract.

Spatial pyramid pooling module or encode-decoder structure are used in deep neural networks for semantic segmentation task. The former networks are able to encode multi-scale contextual information by probing the incoming features with filters or pooling operations at multiple rates and multiple effective fields-of-view, while the latter networks can capture sharper object boundaries by gradually recovering the spatial
information.

In this work, we propose to combine the advantages from both methods. Specifically, our proposed model, DeepLabv3+, extends DeepLabv3 by adding a simple yet effective decoder module to refine the segmentation results especially along object boundaries. We further explore the Xception model and apply the depthwise separable convolution
to both Atrous Spatial Pyramid Pooling and decoder modules, resulting in a faster and stronger encoder-decoder network.

空間ピラミッドプーリングモジュールまたはエンコードデコーダー構造は、セマンティックセグメンテーションタスクのディープニューラルネットワークで使用されます。 前者のネットワークは、フィルターまたは複数のレートと複数の有効視野でのプール操作を使用して着信機能をプローブすることにより、マルチスケールのコンテキスト情報をエンコードできます。後者のネットワークは、空間情報を徐々に回復することにより、より鋭いオブジェクト境界をキャプチャできます。

この作業では、両方の方法の利点を組み合わせることを提案します。 具体的には、提案されたモデルであるDeepLabv3 +は、シンプルでありながら効果的なデコーダーモジュールを追加することで、DeepLabv3を拡張し、特にオブジェクトの境界に沿ってセグメンテーション結果を改善します。 Xceptionモデルをさらに調査し、深さ方向に分離可能な畳み込みをAtrous Spatial Pyramid Poolingとデコーダーモジュールの両方に適用して、より高速で強力なエンコーダー-デコーダーネットワークを実現します。

以上、google翻訳

 

3月6日(土)

GPU: 43h

HuBMAP:1,182 teams, two months to go(データ更新待ち)

HuBMAPコンペは、糸球体を細胞群から抽出するという単純な作業なんだが、糸球体の周辺/背景は、似たような細胞で満たされている。内部と外部は類似しているので、境界層の識別能力を高めることが重要なのだろうと思うのだが、どうやったら実現できるのか。上記のabstractに、DeepLabV3+は境界層の識別能力を改善したと書かれているので期待して使ってみよう。

問題は、計算時間で、EncoderにEfficientNetB3を使っても、1エポックに8分以上かかる。他のDecoderでは2分以内である。CPUでの計算時間は1エポックが20分くらいで、他のモデルと変わらないので、他のモデルよりもCPUへの負荷が大きいということのようだが、よくわからない。

DeepLabV3+の論文では、EncoderにXceptionが使われているので、EfficientNetからXceptionに変えてみた。しかし、意外なことに、Xceptionに対応していないというメッセージが現れ、停止した。あらためて論文を見ると、Xceptionはモディファイして用いていると書いてある。

論文には、Xceptionよりスコアは低いが、ResNet-101を用いて計算した例も示されているので、EncoderをResNet-101に変更して計算してみた。CPUでは1エポックに30分くらいかかり、さすがにこれでは使えないのでGPUに切り替えてみた。そうすると、これも意外なことに、1エポックあたりの計算時間が、約60秒であった。これなら問題なく条件検討ができる。

計算結果:LB=0.811:BCE+0.5*Focal

256x256を同じ視野で解像度を384x384にすると、LB=0.816になった。

Atrous convolution:設定パラメータは"decoder_atrous_rates"となっていて、デフォルトは (12, 24, 36)である。開発者の論文では (6, 12, 18) となっている。

encoder_output_stride:デフォルトの16以外の設定32や8を試しているが、詳細不明

decoder_channels:256をデフォルトにして、128ではスコアが下がるという記述はあるが、系統的に調べたというふうでもない。

計算の合間に論文を見ていたのだが、納得できる説明が見当たらない。上記のReviewで目立っていたので、このモデルを中心に据えて、じっくりと、取り組もうと思って始めてみたが、原著者らによるモデルの説明があいまいで、あまり可能性を感じないし、デフォルトで計算したLBスコアは良くないし、何よりも、DecoderにEfficientNetが使えない(GPUを使ったときの計算時間が長すぎる)など、メリットが感じられないので、DeepLabV3+は、このへんでやめておこうかと思う。

 

"COCO"が気になって調べてみた。

Microsoft COCO: Common Objects in Context
Tsung-Yi Lin Michael Maire Serge Belongie Lubomir Bourdev Ross Girshick
James Hays Pietro Perona Deva Ramanan C. Lawrence Zitnick Piotr Dollar´

arXiv:1405.0312v3 [cs.CV] 21 Feb 2015
Abstract—We present a new dataset with the goal of advancing the state-of-the-art in object recognition by placing the question of object recognition in the context of the broader question of scene understanding. This is achieved by gathering images of complexeveryday scenes containing common objects in their natural context. Objects are labeled using per-instance segmentations to aid in precise object localization. Our dataset contains photos of 91 objects types that would be easily recognizable by a 4 year old. With a total of 2.5 million labeled instances in 328k images, the creation of our dataset drew upon extensive crowd worker involvement via novel user interfaces for category detection, instance spotting and instance segmentation. We present a detailed statistical analysis of the dataset in comparison to PASCAL, ImageNet, and SUN. Finally, we provide baseline performance analysis for bounding box and segmentation detection results using a Deformable Parts Model. 

f:id:AI_ML_DL:20210306094212p:plain

COCOデータセットを使ったコンペが継続的に開催されている。

Tasks: Detection | DensePose | Keypoints | Stuff | Panoptic | Captions

Leaderboard: Detection | Keypoints | Stuff | Panoptic | Captions

Panoptic segmentation aims to unify the typically distinct tasks of semantic segmentation (assign a class label to each pixel) and instance segmentation (detect and segment each object instance). Existing metrics are specialized for either semantic or instance segmentation and cannot be used to evaluate the joint task involving both stuff and thing classes. Rather than using a heuristic combination of disjoint metrics for the two tasks, the panoptic task introduces a new Panoptic Quality (PQ) metric. PQ evaluates performance for all categories, including both stuff and thing categories, in a unified manner.

Panoptic Leaderboardのトップのチームのpaper

Joint COCO and Mapillary Workshop at ICCV 2019: Panoptic Segmentation Challenge Track Technical Report: Explore Context Relation for Panoptic Segmentation
Shen Wang1,2∗ Tao Liu1,3∗ Huanyu Liu1∗ Yuchen Ma1 Zeming Li1 Zhicheng Wang1
Xinyu Zhou1 Gang Yu1 Erjin Zhou1 Xiangyu Zhang1 Jian Sun

 

f:id:AI_ML_DL:20210306112638p:plain

これくらいの論文を書いてみたいものだ。

さて、LB=0.836のモデル、EfficientNetB5-Unet、に戻って、シングルモデルのチューニングしてみよう。損失関数と画像分解能などで、LB=84+を目指そう。

 

3月7日(日)

HuBMAP:1,189 teams, two months to go(データ更新待ち)

LB=0.836を超えるために:

モデル:Unetは、"decoder_attention_type"に"scse"を設定することによって、Attention moduleを組み込んだUnetになる。scseの効果を系統的に比較できていないので、scseの効果を見極めたい。

損失関数:Diceをベースに、BCEやJaccardとの組み合わの効果を調べる。

スライス(1024x1024)とダウンサイズ(256x256):ダウンサイズの際の解像度を最大で512x512まで上げることを検討する。モデルサイズやバッチサイズの変更の効果と相殺されるので、可能な範囲で調べる。

モデル:種類もサイズも、まったく、最適化できていない。いろいろ調べたつもりだが、encode-decoderの組み合わせごとにある程度パラメータフィッティングしないと、判断を誤る可能性が高い。

バッチサイズ:モデルサイズと相反するので選択範囲は狭くなる。

Run1:scseの効果:LB=0.832:0.004下がった。:train中のloss(train_loss及びval_loss)は、scseを使う前よりも下がっているのでスコアは上がると期待していたのだが、どういうことだろうか。

Run2:scseは使わないで、解像度を256x256から320x320に変更:LB=0.834:0.002下がった。こちらも、train中のloss(train_loss及びval_loss)は、解像度を上げる前よりも下がっているのだが、どうなっているのだろうか。

Run1もRun2もoverfittingしている可能性が高い。Encoderを小さくするか、エポック数を少なくする必要があると思う。

次は、損失関数だが、上記のReviewには、「The loss functions which use cross-entropy as the base and the overlap measure functions as a weighted regularizer show more stability during training.」と書かれていた。今使っているものでいえば、overlap系はDice, Jaccard, Lovaszとなる。試してみるしかないのだろう。MAnetの論文では、BCEとDiceの比率は1対4であったように思う。Diceをベースに、BCEを加えている。LB=0.836を得ているのは全て、DiceLossのみなので、手始めに、MAnetの論文をまねてみるのもよいかもしれない。

と言いつつ、さきほど、Run2のDiceLossを、5つの損失関数を全て足したものに置き換えて、trainingした。その結果、val_lossがtrain_lossの1.75倍にもなってしまった。overfitting間違いなしだ。Diceが最も収束が遅いことはわかっていたのだから、エポック数は、少なくとも、30から20くらいまでは下げておくべきだったかもしれない。train_lossは、個々の損失関数のtrain_lossの和に近い値となっているので、正しく動作していることは確認できた。

Run3:Run2のDiceを、Dice + BCE + Lovasz + Jaccard + Focalとした:LB=0.828:train_lossとval_lossとの乖離が大きかった(1対1.75)ので、overfittingになり、もっと低いスコアになると予想していたので、このスコアには多少驚いた。

明日は、Run1, Run2, Run3のエポック数をいずれも30から25に減らしてみよう。さらに、20に減らしてみよう。Run1もRun2もスコアは上がるはずだと思っている。Run3は、エポック数を減らすとともに、学習速度が他よりも速いBCEとFocalの割合(寄与率)を下げてみよう(たとえば:Dice  + Lovasz + Jaccard + BCE/2 + Focal/2)。

 

3月8日(月)

HuBMAP:1,200 teams, 18 days to go (two months to go)

Run4:Unet ---> Unet_scseの効果を調べる:エポック数を30から25に減らしてみる。:LB=0.828:さらに0.004下がった。(0.836 -> 0.832 -> 0.828)

25エポックでの最終エポックのlossは、30エポックでの最終エポックのlossよりも大きいだけでなく、scseを使う前よりも大きな値になった。30エポックで、scseを使った場合、lossが下がったので、LBスコアは上がると予測したが、スコアは下がった。30エポックでは、overfittingになったと思ったのだが、そうではなかったのか。

振り返ると、モデルだけ変更した場合(例えばB5からB6に変更)、train_lossもval_lossも下がって、LBスコアが上がると期待するのだが、スコアが下がることもときどきあった。そういうときは、この課題にはB5が適切なのだろうと判断して先に進んできた。ここに問題/課題がありそうだが、・・・。

Run5:25エポックに下げてだめだったのだから、35エポックについても調べる必要がある。増やすという選択肢の他に、30エポックに戻して、収束の速いBCEやFocalと組み合わせる、という方法も考えられる。配合比をどうするか。まずは、30エポックに戻して、(Dice + BCE)を試してみよう。:LB=0.822:また下がった。

Run6:すなおにDiceのみ, 35エポックを試す。:LB=0.836:scse無しのスコアと同じだが、ほんの少し、前進できたような気がする。

Run7:では、40エポックにしてみよう。:LB=0.833:だめか。scseのメリットを見出せず。

次は、画像解像度の効果について調べる。320x320で検討するつもりだったが、現状のモデルとバッチ数ではこれ以上解像度を上げることができないので、512x512まで使える条件(モデルを小さく、バッチ数を少なく)で検討してみようと思う。

 

Bristol-Myers Squibb – Molecular Translation:138 teams, 3 months to go
Can you translate chemical images to text?

方針転換:参加しないと何も学べない --> 参加すれば、新たなデータと課題に触れる機会が得られ、新たな前処理手法、予測手法を学ぶことができる可能性がある。 --> 参加させていただくことにしよう。

以下、ウイキペディアより、

エタノール:CH3CH2OH:InChI=1S/C2H6O/c1-2-3/h3H,2H2,1H3 (standard InChI)

 全てのInChIは、”InChI=”という文字列から始まり、現在は1であるバージョンの数が続く。standard InChIでは、これにSの文字が続く。残りの情報は、レイヤーとサブレイヤーの配列として構造化され、各々のレイヤーは、1つの種類の情報を収める。レイヤーとサブレイヤーは、区切り文字 ”/” で隔てられ、(メインレイヤーの化学式サブレイヤーを除き)固有の接頭文字で始まる。6つのレイヤーと各々の重要なサブレイヤーは、以下の通りである。

1. メインレイヤー

化学式(接頭文字なし) - 全てのInChIに現れる唯一のサブレイヤー
原子の繋がり(接頭文字:”c”) - 化学式中の水素原子以外の原子には番号が付与される。このサブレイヤーでは、原子が他のどの原子と結合されているかを記述する。
水素原子(接頭文字:”h”) - 各々の原子にいくつの水素原子が結合しているかを記述する。

f:id:AI_ML_DL:20210308223005p:plain

L-アスコルビン酸

InChI=1S/C6H8O6/c7-1-2(8)5-3(9)4(10)6(11)12-5/h2,5,7-8,10-11H,1H2/t2-,5+/m0/s1 (standard InChI)

3. 立体化学レイヤー

二重結合とクムレン(接頭文字:”b”)
原子の四面体配置とアレーン(接頭文字:”t”, ”m”)
立体化学の種類の情報(接頭文字:”s”)

構造式からInChI式を推測させようとするこの課題は、非常にレベルが高いと感じる。

さらに、コンペで提供される構造式の画像は、上記アスコルビン酸の構造式のように明瞭なものではない。

課題は、構造式の画像とInChI式(ラベル)を用いてモデルを訓練することにより、構造式からInChI式を予測すること。

数字の並びは、IUPACの規則に従う。 

 

3月9日(火)

HuBMAP:1,205 teams, two months to go(データ更新作業開始)

Run8:EfficientNetB5-Unet, batch=8, 512x512

現在午前11時4分、submitできない。Discussionをみると、新しいデータが届き、更新作業に入ったとのこと。

We've got a new private test set incoming. Some of the old test samples will be moved to train. The process is currently underway and may take some time. Submissions are disabled while this is taking place. We will notify you when the update is complete. Thank you for your patience!

 

BMS149 teams, 3 months to go

画像からテキストへの変換だから、image-captioningのモデルを使うことができるようである。イメージを文字で表現する。分子構造式から、元素の種類と、数と、分子の形状と、官能基の結合位置と水素の結合位置を、InChIの表現形式に則って配置する。

captioningといっても、言葉ではなく、元素記号、結合位置を表す数字やハイフン、丸カッコ、意味内容の区切るスラッシュ、などが1列に並んだものである。アスコルビン酸だと、C, O, Hの3種類だが、N, P, S, Cl, F, Brなどの元素もあり、結合も1重、2重、3重があり、4員環、5員環、6員環、7員環、鎖状、なども区別して表示される。

 

3月10日(水)

HuBMAP:1,205 teams, 2 months to go(データのアップデート完了

さて、再始動だ!と思ってプログラムを動かしたら、早速、エラーが発生した。そう、train/に、マスク無しのデータが存在する(旧test data)ために生じたエラーだ。

借り物のコードを、部分的にしか理解できていない状態で使っているので、エラー解消は容易ではないが、コードを理解する良い機会だ。

 

***別件作業中***

 

3月11日(木)

 

***別件作業中***

 

HuBMAP:1,210 teams, 2 months to go : May 10, 2021 - Final submission deadline.

データセットが更新されることによって、マスクの不具合が修正され、train_dataが増えたことから、LBスコアが跳ね上がったようだ。今の1位はLB=0.921。休眠状態だったつわものたちが本格的に動き始めるとさらに上がっていくのだろう。

さて、データ修正前の値だが、自分の0.836では勝負にならない。望みがあるとすれば、現在LB=0.90+の方が使用しているモデルがEfficientNetB4-Unetで解像度が512x512だということで、特殊なモデルを使っているわけではなく、自分も同様の条件で試したことがあるというところだ。しかし、それは、参加者みんながわかっていることなので、そこまでは到達して当たり前みたいな感じだとすると、やはり、現状では勝ち目はない。

 

別件を済ませて、これに集中したいのだが、・・・。

 

3月12日(金)

HuBMAP:1,211 teams, 2 months to go (gold: 0.916+)

train_dataに更新前のtest_dataが追加されたという情報から、勝手に、マスク無しのtrain_dataとして追加されたと思い込んでいたが、マスクデータは全てのtrain_dataにセットされている。したがって、エラーの原因はマスクではない。

image = dataset.read([1,2,3], <---ここでエラーが生じているようだが、・・・。

IndexError: band index 2 out of range (not in (1,))

よくわからんが、次の3種類のフォーマットが混在しているために、エラーになっているのだろうと思う。

[height, width, channel]

[channel, height, width]

[1, 1, channel, height, width]

ここからは、さらに踏み込んで、コードを、書き換えなければだめだろう。

 

とりあえず、エラーが生じる直前までの8個のtrain_dataだけを用いることができるようにして、計算させてみた。

プログラムが最後まで走るのか、さらに、commit, submitを経て、LBスコアが得られるのかは全く分からないが、train_lossは、データ更新前には見られなかったくらい小さくなっている。そのぶん、極端なoverfittingになっているようにみえる。

trainからinferenceに移ったら、trainのときと同様のエラーが発生した。データの読み込みを、データフォーマットに合わせるように、プログラムしなおす必要がありそうだ。

trainの場合は、フォーマットの違うtrain_dataを読み込まないようにしたのだが、inferenceの場合は、フォーマットの違うtest_dataを避けたらスコアが正しく計算されなくなってしまう。

データ更新前に投稿したものは、更新されたデータを使って再計算されることになっているようだが、自分のプログラムは、更新されたデータには対応していないので、再計算されないように思う。

train_modelを読み込んで、inferenceだけKaggle kernelを使っているチームの場合、Kaggleスタッフでは、trainのやりなおしができないので、あまり、意味がないような気がする。

更新前のデータに対して動いていたのだから、更新されたデータに対しても動いてくれなければ困る、と言いたいところだが、だれも言わないだろうな。それくらいはできないとだめですよ、と言われそうだ。優しいスタッフが、更新されたデータに対応できないチームのために、変換コードを用意してくれるかもしれない。

いやいや、スタッフが乗り出す前に、Kaggler仲間が、解決策を提案してくれている。

参加者どうしで助けあっている!

これが、Kaggleだ!

 

3月13日(土)

HuBMAP:1,213 teams, 2 months to go(現在のLBスコア1位:0.926)

train_dataとしては、15個のうちの8個を使っているだけだが、データ更新前と比べて、train_lossが70%くらいになっているようである。val_lossも相応に下がればうれしいのだが、逆に大きくなっているので、明らかに、overfittingの状態になっている。

マスクの精度が向上していると思うので、train_lossが下がるのは想定どおりであるが、教師データに学んだ結果が、validation_dataに正しく反映されないというのはどういうことなのか。ふつうに、overfittingということで片付けておく。

transformの程度を強くしてみたら、val_lossが明らかに小さくなった。これは良い兆候である。

前処理で、データの切り出しで、MIN_OVERLAPという値があり、これによってスコアが大きく変わったというコメントがあったので、試してみることにする。

切り出しの際の重なりを大きくするということは、データ数を増やしていることになるのだろうと思う。

初期値の32から、64, 128, 192と変えてみた。MIN_OVERLAP=192では、RAMの使用量が約2.5GB増えた。

結果は、若干、overfitting側に変化しているようにみえる。

いずれにしても、現状では、train_dataの全体を読み込むことができず、さらに、もっと困ったことには、肝心のtest_dataが読み込めない。これでは、先に進めない。

明日は、Discussionと公開コードを参考にして、フォーマットが変わってしまったtrain_dataとtest_dataの読み込みができるようにする予定。

 

overfitting、underfitting、スコアアップ: A. Geron氏のテキスト参照(chapter 7: Ensemble Learning and Random Forests):実験第一!

・エポック数(early stopping, OneCycleLRのエポック数)

・モデルの大きさ:B0, B1, B2, B3, B4, B5, B6, B7, B8, 18, 34, 50, 101, 152, 121, 169, 201:パラメータの数を増やせば、より詳細なところまで見えるが、overfittingしやすくなり、汎用性は低下することがある。

・データ量(augmentationによる増量)

・augmentationの種類、変形強度(ElasticTransform, GlidDistortion, OpticalDistortion)

・dropout(ユニット、層、画像内部)

・ensemble(K-fold、stacking, voting, randomsampling, 

・ モデルの初期値(random, Glorot and He, LeCun, Xavier)

・pretrained_model(データの種類、量、質)

・out of bag evaluation

・random patches, random subspaces

 

from today's Twitter:

Deep Learning Weekly@dl_weekly
From this week's issue: Algorithms are meaningless without good data. The public can exploit that to demand change.

 

3月14日(日)

HuBMAP:1,219 teams, 2 months to go(Goldは0.92+)

今日は、Discussionと公開コードを参考にして、フォーマットの違うものが含まれているtrain_dataとtest_dataを読み込むことができるようにする。それができれば、データ更新後の初LBスコアを取得する。

公開コードを参考にして、作業を始めた。自分がベースにしているコードの作者をフォローしようと思って、そのコードを見に行ったら、2日前に更新されており、新たに加わったフォーマットに対応できるように変更されていた。有難い。しかも、そのコードは非常にスマートで、たった1行追加されているだけである。

ということで、更新データに、対応できるようになった。ただし、新たな課題が生じた。train_dataが増えたのはありがたいが、RAMに読み込んで動かしているため、13GBの制限に引っかかって、半分強くらいしか使えない。

さらに、train_lossとval_lossの差が大きい。更新データに対応したコードの製作者も、同様な結果になっていて、更新前のデータに対して使っていたパラメータのままでは、LBスコアは、かえって、悪くなる。

EfficientNetB5-Unetを試してみたが、今日は、LB=0.512が最大であった。いくらなんでもこれは無いだろう、と思った。リーダーボードのスコアがどんどん上がっているので、更新前のデータに対して用いていたのと同じ条件で計算しても、自分のスコアも、当然、上がるものだと思い込んでいた。

今日は、submitできるようになって、良かった。

しかし、明日から、overfittingとの戦いだ!

 

3月15日(月)

HuBMAP:1,223 teams

今頃は、LB=0.85+だと思ったのだが、更新データでの最良値は、なんと、LB=0.531である。原因は、train_dataの半分弱のデータを使っていないことにあるのかもしれない。

更新前と同じ8件のtrain_dataを使っているのだが、更新前と同じデータは5件あるが、3件は異なっている。

15件全部のtrain_dataを使いたいところだが、今の使い方ではメモリーオーバーになるので、まずは、更新前と同じデータ名のtrain_data:8件を使ってみよう。

更新前のrain_dataのみを読み込むようにコードを書き替えた。次のようなコードを追加して、新しいtrain_dataのファイルを読み飛ばすようにした。

if filename == '26dc41664':
    continue

その結果、データ更新前のモデルをそのまま使っても、train中の極端なoverfittingの傾向はなくなった。こんなにも違う結果になるとは、思わなかった。

さらに、train_lossもval_lossもデータ更新前よりも、かなり小さくなったので、データ更新前よりも、良いスコアが得られるのではないかと期待したが、LB=0.831となり、残念ながら、データ更新前のLB=0.836には届かなかった。

これで、ようやく、スタートラインに立てたように思う。

test_dataに類似したtrain_dataを使えば、スコアが良くなるのと同様に、test_dataと似ていないtrain_dataを使った場合にはスコアは上がらない、ということがおきていたということだろうと思う。試験範囲と外れたところを勉強しても良い点は取れない。

こういうことを経験すると、漫然と訓練していても良いモデルは作れない、という気がしてきた。test_dataを適切に処理できるためにどのように訓練しておけば良いのか。テストデータがわかっていれば、訓練データとの類似性や特徴などを調べておくことが重要になりそうだ。Kaggleのコンペがスタートすると、データ解析をしてみせて、訓練データとテストデータの特徴に違いがある場合には、Discussionで注意喚起し、その理由や対処方法まで丁寧に説明してくださるKagglerもおられる。

多値分類だと、分類するクラス毎の訓練データ数を同じになるようにするのだが、バックグラウンドとの識別の場合には、バックグラウンドの面積が何倍にもなる場合がある。そういうとき、segmentationの精度にはどんな影響があるのだろうか。精度に影響する因子にどのようなものがあって、どのように対処すればよい結果が得られるのだろうか。

 

明日は、

1.コードの学習:画像の前処理

2.LB=0.831を超えよう! 

 

3月16日(火)

HuBMAP1,232 teams (May 10, 2021 - Final submission deadline.)

1.コードの学習:3時間程度の予定:Resnet-Unetのようなモデルだが、DecoderにはFPNが使われているようだった。FPNのチャンネル数やUnetのチャンネル数の設定値を見ていて、自分もUnetとFPNを使っているが、デフォルトのままで、自分で設定したことがない。Unetのデフォルトはdecoder_channels=(256, 128, 64, 32, 16)となっているが、公開コードでは、もっと多くのチャンネル数が用いられているように見える。FPNにしても、デフォルトは、decoder_pyramid_channels=256, decoder_segmentation_channels=128となっているが、公開コードでは512チャンネルも使われているように見える。このあたりのパラメータを変えてみて、性能がどう変化するかを調べてみようと思う。

2.更新前のtrain_dataの8件に、新たに追加されたtrain_dataの7件から、メモリー一杯まで読み込んでtrainingすることによって、LBスコアが上がるかどうか調べる。

2件までしか追加できなかったが、とりあえず、train and inferenceを試してみることにする。

train_data=10件:LB=0.839になった。(EfficientNetB4-Unet-DiceLoss)

15件のtrain_dataを全て使うにはどうすれば良いのだろうか。

今使っているプログラムの良いところは、パラメータを変えてタイルを自由に作り変えることができるところだ。全てのtrain_dataを使えるようにすることを最優先に、タイルサイズを小さくし、オーバーラップをゼロにすることによって、15件のtrain_dataの全てを使うことができるようになった。

タイルサイズを小さくすると、1枚のタイルに含まれる糸球体が少なくなり、糸球体の多くが分割されてしまうのではないかと思う。このことが、糸球体のセグメンテーションにおいてどう作用するのだろう。

タイルサイズを小さくして計算した結果、出力ファイルのサイズが標準の5MBを大きく超えて、7.5MBとか21MBになってしまい、前者はエラー、後者はLB=0.675となった。commit中にもタイルサイズに関する警告が出ていたので、これは1024に戻すことを優先しようと思う。 

画像の分割は、非常に重要な作業のように思う。全ての糸球体の外周を分断することなく、完全な形のままで、画像を切り出す方法を調べてみよう。

 

明日は、これ(train_data=10件:LB=0.839になった。(EfficientNetB4-Unet-DiceLoss))を超える方法を検討しよう。その1つの手段として、Unetのdecoder_channelsの変更を行ってみる。

(それにしても、上位との差は歴然!:最終日、トップは0.95+になっていて、自分は0.85+に到達して喜んでいるかもしれない!:あと50日間でこの差を埋めて逆転するためにはどうすればよいのかを考えよう)

 

3月17日(水)

HuBMAP: 1,236 teams (May 10 final submission deadline)

1.コードの学習

@iafoss氏の公開コード:class UneXt50(nn.Module)というものを構築している。パーツとしてFPN, UnetBlock, ASPPが使われている。encoderはResNet50で、decoderはUnetだが、ASPPとFPNが仕込まれている。

高度な機能を組み合わせることで、高度なモデルができるということを示している。


2.Unetのdecoder_channelsの効果

デフォルトのdecoder_channels=(256, 128, 64, 32, 16)を、2倍、decoder_channels=(512, 256, 128, 64, 32)にしてみた。出力データサイズは4.9 MBから5.34 MBに増えた。ノイズが増えたように見える。結果はLB=0.815であった。チャンネル数を増やせば保持できる情報量が増えてデメリットは無いように思うが、overfittingという落とし穴がある。

次は、チャンネル数を半分、decoder_channels=(128, 64, 32, 16, 8)にしてみた。出力データサイズは10.66 MBに増えた。ノイズはさらに増えているように見える。結果は、LB=0.231であった。チャンネル数は各深さにおける特徴量を保持するためのメモリーのようなものだと思うので、メモリーが少なくて情報を保持できないということだろうと思う。train_lossとval_lossの値からは、ここまでスコアが悪くなるとは思わなかった。非常に驚いている。

もう少し遊んでみよう。チャンネル数を減少ではなく増大させるとどうなるのだろう。decoder_channels=(16, 32, 64, 128, 256)としてみると、出力データサイズは6 MBで、ノイズが多そうなデータにみえたが、LB=0.798と、思ったほどはひどくはなかった。

ならば、平均値あたりに揃えたらどうなるのか。decoder_channels=(128, 128, 128, 128, 128)としてみた。LB=0.821

オリジナルの論文を見ると、チャンネル数はこんなもんじゃない。最低が64だから、5段であれば、decoder_channels=(1024, 512, 256, 128, 64)となる。

バカなことして遊んでいる場合じゃなかった。

このセットdecoder_channels=(1024, 512, 256, 128, 64)で計算してみたら、悪くはなかった。明日、submitしてみよう。:LB=0.813:

実は、このセット(512, 256, 128, 64, 32)の次に1024のセットを準備していたが、512のセットのスコアが期待外れだったので、遊びに転じてしまった。

以下に結果をまとめて示す: 

decoder_channels=(128, 64, 32, 16, 8):LB=0.231

decoder_channels=(256, 128, 64, 32, 16):LB=0.831

decoder_channels=(512, 256, 128, 64, 32):LB=0.815

decoder_channels=(1024, 512, 256, 128, 64):LB=0.813

decoder_channels=(16, 32, 64, 128, 256):LB=0.798

decoder_channels=(128, 128, 128, 128, 128):LB=0.821

decoder_channels=(256, 256, 256, 256, 256):LB=0.790

この結果から何か言うとすれば、「いろいろ試してみれば、良い組み合わせが見つかるかもしれない」。

U-Net: Convolutional Networks for Biomedical Image Segmentation
Olaf Ronneberger, Philipp Fischer, and Thomas Brox

f:id:AI_ML_DL:20210317165706p:plain

このUnetのオリジナル論文を検索しているときに、Unetの新しいバージョンに出くわした。

UNET 3+: A FULL-SCALE CONNECTED UNET FOR MEDICAL IMAGE SEGMENTATION
Huimin Huang 1, *Lanfen Lin1, Ruofeng Tong1, *Hongjie Hu2, Qiaowei Zhang2, Yutaro Iwamoto3, Xianhua Han3, *Yen-Wei Chen3,4,1, Jian Wu1

f:id:AI_ML_DL:20210317182919p:plain

このUnet 3+のコードは、GitHubにある:https://github.com/ZJUGiveLab/UNet-Version

新たにコードを開発した研究者や技術者は、開発したコードをGitHubで公開することが多く、論文のabstractの下端に公開サイトのURLを示すことが多い。

 

3月18日(木)

HuBMAT:1,245 teams

今日は、Unet 3+を使ってみよう。https://github.com/ZJUGiveLab/UNet-Versionの、UNet-Version/models/には、次のコードが入っている。

UNet.py
UNet_2Plus.py
UNet_3Plus.py
init_weights.py
layers.py

さらに、UNet-Version/loss/には、次のコードが入っている。

bceLoss.py
iouLoss.py
msssimLoss.py

論文では、hybrid segmentation lossとして、focal lossとMS-SSIM lossとIOU lossを組み合わせたhybrid segmentation lossが提案されている。

UNet_3Plus.pyには、UNet_3Plusの他に、Unet_3Plus_DeepSupとUnet_3Plus_DeepSup_CGMが含まれている。それぞれ、ベースコード、with deep supervision、with deep supervision and class-guided moduleであり、論文中で追加機能として説明されているものである。

道具は揃った。

さて、このUnet_3Plus_DeepSup_CGMを使うにはどうすればよいのか。

まず、簡単なところから始めよう。

1.ライセンスの確認:

https://github.com/ZJUGiveLab/UNet-Versionのreadmeには、次の記述があるだけなので、このURLと論文を引用すれば十分ではないかと思う。

README.md
UNet 3+
Code for ICASSP 2020 paper ‘UNet 3+: A full-scale connected unet for medical image segmentation’

Requirements
python 3.6.2
pytorch 1.3.1

2.UNet.pyを使うための準備(最終的にはUnet_3Plus_DeepSup_CGMを使ってみたいが、使用方法を検討しやすい小さいプログラムを使う)

Unet.pyの最初に、次のコードが書かれている。

import torch
import torch.nn as nn
import torch.nn.functional as F
from layers import unetConv2, unetUp, unetUp_origin
from init_weights import init_weights
from torchvision import models
import numpy as np

UNet.pyをnotebookにコピペして走らせてみると、次のメッセージが出て停止した。

ModuleNotFoundError: No module named 'layers'

from layers import unetConv2, unetUp, unetUp_origin:ここでひっかかっている。

'layers.py'と'init_weight.py'の2つのモジュールを、カレントディレクトリに置かなければならないようだ。

Pythonのドキュメントの、 6. モジュール 、に次の説明がある。

モジュールは Python の定義や文が入ったファイルです。ファイル名はモジュール名に接尾語 .py がついたものになります。モジュールの中では、(文字列の) モジュール名をグローバル変数 __name__ で取得できます。例えば、お気に入りのテキストエディタを使って、現在のディレクトリに以下の内容のファイル fibo.py を作成してみましょう:

次に Python インタプリタに入り、モジュールを以下のコマンドで import しましょう:

つまり、UNet.pyが参照している関数が含まれている"layers.py"と"init_weights.py"をKaggle kernelのカレントディレクトリ―"/kaggle/working/"に入れておけば、importによって呼び出すことができるということのようだ。

そのためには、"layers.py"と"init_weights.py"をKaggleのデータセットに入れて、コードのinput_dataにアップロードすればよい。そうして、次のコードでカレントディレクトリ―にコピーする。

!cp ../input/unet-3plus-pytorch/models/init_weights.py /kaggle/working/
!cp ../input/unet-3plus-pytorch/models/layers.py /kaggle/working/

形式的には、こんな感じだが、これで、

from layers import unetConv2, unetUp, unetUp_origin
from init_weights import init_weights

この2つはエラーなく実行されたようである。

3.UNetを使う

これで、https://github.com/ZJUGiveLab/UNet-Versionの中のUNetを使う準備は整ったと思う。

model = UNet( )

model.to(DEVICE)

 

loss_fnには、 nn.BCEWithLogitsLoss( )を使ったのだが、どうも、うまく動作していないようである。lossが下がらない、すなわち学習が進まない。

とりあえず、先に進もう。

UNet_3Plus.pyは、ベースとなるUNet_3Plusの他に、オプションを付加した、Unet_3Plus_DeepSupとUnet_3Plus_DeepSup_CGMがある。

UNet_3Plusを動かしてみた。batch_size=16ではメモリーオーバーになった、batch_size=8ではGPUのRAMは14.7 GBで動いた。1エポックに7分以上かかっており、lossがわずかづつしか下がらず。

Unet_3Plus_DeepSupとUnet_3Plus_DeepSup_CGMは、GPUのRAMはそれぞれ11.4 GBと12.5 GBでUNet_3Plusより少ないが、いずれも次のようなエラーメッセージが現れて停止した。

AttributeError: 'tuple' object has no attribute 'size'

loss = loss_fn(output, target):この計算の過程でエラーが生じているようである。

とりあえず、オプションなしのUNet_3Plusは動くようになったので、引き続き検討していこう。lossの変化が小さいのは、出口の活性化関数'sigmoid'によるものだろうと思う。他のモデルでも’sigmoid'を使うとlossが減少しにくくなり、LBスコアも0.01くらい下がるので、ここに何か問題がありそうだと思っている。

 

明日は、LB=0.916の公開コードに学ぼう。

何か本質的なところで、自分のtraining方法(もしくはtrainingコード)に本質的な間違いがあるような気がしている。

 

3月19日(金)

HuBMAP:1,251 teams, to May 10

LB=0.916の公開コードに学ぶ:

EfficientNetB2-Unet or FPN:パラメータは activation=sigmoid 以外デフォルト

optimizer=Adam,

loss=bce_dice or bce_jaccard, 

以上の条件は、自分が調べた範囲に、ほぼ、含まれている。これらの条件では、自分は、LB=0.83+止まりであった。

ReduceLROnPlateau, EarlyStopping, 

これらを適切に使えば、自分が使っているOneCycleLRよりも0.01~0.02くらいは高くなる可能性はあるかもしれない。(3月25日修正:OneCycleLRはすぐれもので、適切に使えば上回る可能性もある)

KFold, GroupKFold

これも適切に使えば、0.01~0.02くらい上がるかもしれない。

TTA

これも、0.01~0.02くらい高くなる可能性があるだろうか。TTAを+4でやってみたときには、+0.005程度、上がったことがある。

augmentation(albumentations)

メジャーなものは同じなので、差がつくとしても0.01以下であろうと思うが(3月25日追記/修正:HuBMAPコンペでは強すぎる幾何学的変形は性能を下げる。カラー調整やボケ具合やコントラストは適切に用いると0.02+の向上は可能である)、あまり使われていないものの中には、よいものがあるかもしれない。複数のブロックで画像を隠す方法(3月25日追記:aibumentationに"cutout"というのがある)を使ってみたいと思っているのだがまだ手が出せないでいる。

以上の4つの効果を足すと、0.04~0.07ほど高くなる可能性があり、0.83を足すと、0.87~0.90くらいになる可能性があるということになるが・・・。

もっと、具体的なコードの中身まで検討するつもりだったが、明日以降の宿題とする。

明日からの1週間は、EfficientNetB2-Unetから離れないで、チューニングしてみようと思う。

 

3月20日(土)~3月26日(金)GPU 41h

HuBMAPEfficientNetB2-Unetに固定してチューニングを行ってみよう。

Unetは、activation="sigmoid"にして、他はデフォルトを用いる。

上記のLB=0.916の公開コードでは、loss=bce_dice or bce_jaccard, となっているが、コードをよく見ると、bce_weight=1となっているので、BCE一択のようである。これは、自分の最近の経験と一致する。すなわち、DiceLossとJaccardLossは、activationを"sigmoid"にすると、自分が使っているコードでは、全く機能しない。

BCEと組み合わせるなら、FocalLossやLovaszLossであろう。まずは、BCE単独で進めてみよう。SoftBCEWithLogitsLoss( )

optimizerは、AdamWをOneCycleLRとの組み合わせで使っていて、上記LB=0.916のコードで使われているAdamとは、weight_decayがデフォルトかどうかの違いだけで、大差ないように思う。

OneCycleLRは、比較のために、他のlr_schedulerも使ってみようかと思う。PyTorchは、種類が豊富で迷ってしまう。

簡単に使えて、有用だと思うもの。

torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1, verbose=False)

>>> # Assuming optimizer uses lr = 0.05 for all groups
>>> # lr = 0.05 if epoch < 30
>>> # lr = 0.005 if 30 <= epoch < 60
>>> # lr = 0.0005 if 60 <= epoch < 90
>>> # ...
>>> scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
>>> for epoch in range(100):
>>> train(...)
>>> validate(...)
>>> scheduler.step()

これは、step_size 毎に、lrが、lr x gammaになる。

ReduceLROnPlateau

val_lossをモニターして、変動幅が設定値より小さくなると、lr x gammaを行う方法で、StepLRを自動化したようなもの。

val_acc、val_dice等をモニタしながらlrを変更することもできる。

EarlyStopping, 

 

元のプログラムを書き替えるときに、その場しのぎの書き換えをやったことで、エラーは出ないが、動作は、正しくないということがおきているかもしれない。桁落ちの問題はなかったかな。(TPUの桁落ち対策のことを思い出した)

 

3月20日(土)

LB=0.911の公開コードのtrain_codeに学ぶ。(max: LB=0.918)

EfficientNetB4-Unet(activationはデフォルトのNoneか?)

loss_fn=FocalLoss(alpha=0.25, gamma=2.0, reduction='mean')、この設定(alpha=0.25)はMAnetの論文で見たような気がする。

optimizer=ranger

Ranger - a synergistic optimizer combining RAdam (Rectified Adam) and LookAhead, and now GC (gradient centralization) in one optimizer.

 

EfficientNetB2-Unet:

Unetにactivation="sigmoid"とし、OneCycleLR(AdamW, max_lr=1e-3. epochs=20...), SoftBCEWithLogitsLoss, batch_size=16, train_dataは、データ更新前の8件を用いて計算した結果、LB=0.808となった。最終エポックにおいて、train_loss=0.668, val_loss=0.669となり、14エポック以降は殆ど変化していない。

さすがにこれ(LB=0.808)では、続ける気にならないので、activationを外すことにして、他は何も変えずに計算してsubmitしてみたら、LB=0.850となった。驚いた!!!

最終エポックでtrain_loss=0.0219, val_loss=0.0356となっており、これらは約1.6倍異なっているので、overfittingにしかみえず、これまでであれば、commit, submitしなかったと思う。しかし、今回は、これをスタートラインにしようと思っていたので、commit, submitした。これが、自己ベスト(LB=0.839)を0.011も上回ったことは非常に大きな驚きである。train中に Dice coefficientを計算して表示していれば、もっと早く、このレベルの結果が得られていたかもしれない。

ここで、train_dataを2件追加(CPUの許容範囲ギリギリ)し、他の条件は変えずに計算してcommit, submitしたところ、LB=0.865までスコアが上がった。なにも変わったことはしていないので、なぜ上がっているのかわからない。データが更新された後、更新データが使えるようになったときにtrain_dataを8件から10件に増やしたときには、LBスコアが0.83+から0.839に上がっていたので、今回も上がることは期待していたが、ここまで(0.015も)上がるとは思わなかった。

しかし、トップの、LB=0.928まで、あと、0.063もある。

明日は、OneCycleLRのmax_lrを1e-3の付近で変えてみよう。今日、max_lr=2.5e-4を試してみたら、LB=0.853となった。ちょっと下げすぎたかもしれない。max_lr=5e-4, 2.5e-3, 5e-3あたりを調べてみる。さらに、FocalLossとLovaszLossを試してみようと思う。

 

3月21日(日)

OneCycleLRのmax_lrを変えた時のLBスコアを調べてみた。

lrは、デフォルト設定でepochs=20の場合、max_lr/25からスタートし、6エポックの計算直後にmax_lrに達し、そこからlrは減衰し、最終的にmax_lr/25/1e4となるようである。

結果は次のようになった。数値だけではわかりにくいので、プロットしてみる。

max_lr=2.5e-4:LB=0.853

max_lr=5.0e-4:LB=0.866

max_lr=1.0e-3:LB=0.865

max_lr=2.5e-3:LB=0.855

max_lr=5.0e-3:LB=0.863

プロットすると下図のようになる。LBスコアはmax\lrが5e-4と1e-3の間で最大になりそうだが、5e-3より大きい値にするとどうなるのかも気になる。

f:id:AI_ML_DL:20210321105826p:plain

f:id:AI_ML_DL:20210321104528p:plain

この挙動は、エポック数によっても変わる可能性がある。

max_lrを小さくすると、全過程においてlrは小さいので、収束速度が遅くなると推測される。もしそうであれば、max_lr=2.5e-4の条件でエポック数を増やせばLBスコアはもっと高くなるはずである。

max_lrが大きい場合、6エポック前後でのlrが標準的な値を超えているときには、不安定な動きをしているようにみえる。減衰しはじめてから標準的なlr値になるまでに時間がかかるため、標準的なlr値に戻ってから最終エポックまでの計算量が少なくなるために、学習が不十分という状況が生じているかもしれない。

OneCycleLRのエポック数を増やしても、lrの変化は相似形になるので、max_lrが大きい場合にエポック数を増やすと、適正なlrになるエポック数は増えるが、適正値を超えるlrになっているエポック数も増える。といっても、適正値を超えるlrになっているエポック数が増えることが、最終的な学習結果にどう影響するかはわからない。

すべては、やってみないとわからない、としておこう。

細かすぎるような気もするが(目標は遥か彼方)、次の2つの条件を追加してみる。

max_lr=7.5e-4:LB=0.857

max_lr=1.0e-2:LB=0.858

f:id:AI_ML_DL:20210321153650p:plain

f:id:AI_ML_DL:20210321153724p:plain

期待しかなかったのだが、笑うしかない。

 

次は、1サイクルではなく、複数サイクルのスケジューラーを使ってみよう。

torch.optim.lr_scheduler.CyclicLR(optimizer, base_lr, max_lr, step_size_up=2000, step_size_down=None, mode='triangular', gamma=1.0, scale_fn=None, scale_mode='cycle', cycle_momentum=True, base_momentum=0.8, max_momentum=0.9, last_epoch=-1, verbose=False) 

f:id:AI_ML_DL:20210323215518p:plain
ちょっと動かしてみただけだが、optimizerとしてAdamを使おうとしたら、momentumが使えないoptimizerは使えない、というようなメッセージが現れて停止した。そのため、SGDを nesterov=Trueとして使ってみた。base_lr=0.1, max_lr=3, epochs=20に設定し、他はデフォルトで使ってみたら、20エポックでは1サイクルの途中までだった。そこで、20エポックで3サイクルになるようにstep_size_up=500(デフォルトは2000)として計算してみたら、lr=3付近で異常値を示した。想像の域を出ないが、急激なlrの増大が良くなかったのではないかと思う。max_lrを3から2に下げたら、正常に動き、最終の20エポック目のlossもそれなりの値を示した。

サイクルの繰り返しによって、val_lossが下がっているので、max_lrとstep_size_upとエポック数の最適な組み合わせを探してみよう。

 

3月22日(月)

lr_scheduler.CyclicLR、20エポックで、max_lr=2とし、1サイクル、2サイクル、3サイクルになるようにstep_size_upを調整し、計算した結果をsubmitした。結果は以下のようになった。カッコの中は、最終エポックのtrain_lossとval_lossである。

3サイクル:LB=0.869 : (0.267, 0.314)

2サイクル:LB=0.839 : (0.258, 0.301)

1サイクル:LB=0.856 : (0.243, 0.296)

自己ベストが出たのはよかったが、lossの値からは、サイクル数が少ないほどLBスコアは高くなると予想していたので、あてが外れてしまった。 

これならいけるだろうと思って意気込んで計算してsubmitしたのが次の結果である。

30エポック:3サイクル:max_lr=3:LB=0.835 : (0.253, 0.353):val_lossが高すぎ!

最初から、base_lr=0.1, max_lr=3 : 20エポック&3サイクルと決めていたが、20エポック&3サイクルでは、max_le=3に設定すると、lr=3付近でval_lossが発散した。そこで、max_lr=3でも発散しない条件を調べて、30エポックであれば良い結果が得られそうだと思ってトライした。val_lossが0.353となり、かなり大きい値だが、29エポック目では、(0.251, 0.303)だったので、いけるかもしれないと思い、commit, submitした。残念。

ステップ数を正しく計算していなかったために、30エポックの最後は最少のlrが適用されるべきところが、base_lrからの立ち上がりの30ステップぶんのlrが適用されたために学習した重みが若干かく乱された可能性がある。少なくともステップ数は正しく設定しておくべきであった。(745とすべきところを740と設定していた)

他の条件についても正確に計算すると、偶然だが、LB=0.869となったものだけが、最終エポックがlrの減少中に終わっていた。494と入力するつもりのところに、500と入力されていたのが幸いしたのかもしれない。LB=0.835となったものは、max_lr=3であったことも、悪い方に作用したようである。

OneCycleLRを使っているときに、max_lr=3が頭にこびりついていて、今回のCyclicLRでも、base_lr=0.1, max_lr=3がベストと思い込んでしまっていたようだ。Leslie N. Smith氏の論文では、0.1-0.5, 0.1-1, 0.1-1.5, 0.1-2, 0.1-2.5, 0.1-3, 0.1-3.5, 0.1-4, 0.09-0.9など、いろいろ試した例が表に載っている。

Leslie N. Smith氏の2編の論文より、

Furthermore, there is a certain elegance to the rhythm of these cycles and it simplifies the decision of when to drop learning rates and when to stop the current training
run. Experiments show that replacing each step of a constant learning rate with at least 3 cycles trains the network weights most of the way and running for 4 or more cycles
will achieve even better performance. Also, it is best to stop training at the end of a cycle, which is when the learning rate is at the minimum value and the accuracy peaks.

3サイクル以上とすること(追記:要検討)、および、lrが最小値になるエポックで止めること、と書かれている。自分が気付いた注意点としては、ステップ数を正しく計算し、最終エポックの計算中に、lrが立ち上がっていく領域が含まれないようにすることが重要である。

3/24追記:cyclicの後に1 sycleの発想が出てきている。ここまでの自分の実験からは、サイクル数、学習率の範囲と変化形状、などの最適値は、用いるデータの量や質に依存し、モデルや画像処理にも依存するので、実験を適切に繰り返しながら見つけよう。

CyclicLRのエポック数は12から100くらいまで、OneCycleLRのエポック数は100から800くらいまで表に記載されている。max_lrが大きいほど、エポック数は多い傾向にある。自分が計算した例では、max_lrを3にすると異常値が現れてモデルが壊れることがあった。そういうときは、エポック数を増やすか、max_lrを下げるかする必要がある。

 

ずっと気になっていたのだが、train_lossとval_lossしか計算していないので、明日は、train_dice, val_diceを計算して表示できるようにしよう。

 

3月23日(火)

GPU : 17h 38m available of 41h 

HuBMAP

20エポック、3サイクル、0.1-2、(傾斜:(max_lr-base_lr)/step_size_up:(2-0.1)/500):LB=0.869:(昨日の結果)

20エポック、3サイクル、0.1-1、(傾斜:(max_lr-base_lr)/step_size_up:(2-0.1)/500):LB=0.845:(昨日の結果)

20エポック、4サイクル、0.1-2、(傾斜:(max_lr-base_lr)/step_size_up:(2-0.1)/373):LB=0.851:傾斜が1.34倍(max_lr=2.65と同等)

傾斜もmax_lrも同じにして、4サイクルにする:

27エポック、4サイクル、0.1-2、step_size_up=503:LB=0.846:

train_loss=0.0249, val_loss=0.0296:lossから予想されるLBスコアとの乖離は非常に大きいと感じる。

 

LB=0.869の再現実験:

1.条件設定を完全に一致させる:

2.train_lossもval_lossも表示範囲で一致、出力も見える範囲で完全一致

3.LB=0.869は、再現された。

max_lrを2から1にしただけで、LBスコアは、0.869から0.845に下がり、傾斜もmax_lrも同じにして、サイクルを1つ増やしただけで、0.869から0.846に下がった。

max_lr=2.25とmax_lr=1.75を試してみよう。

20エポック、3サイクル、max_lr=2.25 : LB=0.863 : (train_loss=0.0269, val_loss=0.0324)

20エポック、3サイクル、max_lr=1.75 : LB=0.869 : (train_loss=0.0266, val_loss=0.0352)

3月27日追記:20エポック、3サイクルでは、max_lrは2より小さい方が良いのか、もう少し調べてみたい。

OneCycleLRはAdamWを使っていた。CyclicLRでは、AdamWが使えないので仕方なくSGD(nesterov=True)を使っているのだが、良い結果が得られているので、OneCycleLRでも、再度、SGDを使ってみようかなと思う。

 

エポック数:

Leslie N. Smith氏の論文の表を見ると、エポック数を25、50、75、100、150と増やせば、確実に、スコアは上がっている。データ量が多い場合はこういう傾向になるのだろう。他方で、データ量が少ないときには、20エポックくらいで、CyclicLRやOneCycleLRが良い結果を与えることを、実験して確かめているようだ。

 

diceの計算:次のサイトから借用させていただく

https://github.com/UCAS-Vincent/UNet-3Plus/blob/master/metrics.py

def dice_coef(output, target):
      smooth = 1e-5

      if torch.is_tensor(output):
      output = torch.sigmoid(output).data.cpu().numpy()
      if torch.is_tensor(target):
      target = target.data.cpu().numpy()
      #output = torch.sigmoid(output).view(-1).data.cpu().numpy()
      #target = target.view(-1).data.cpu().numpy()

      intersection = (output * target).sum()

      return (2. * intersection + smooth) / (output.sum() + target.sum() + smooth)

......

dices = []

for image, target in loader:

      ......

      dice =dice_coef(output, target)

      dices.append(dice.item())

np.array(dices).mean()

動作確認中!!!

 

明日は、30エポック、3サイクル、0.1-3、1サイクルの前後の割合を30:70と70:30にした結果を比較してみる(OneCycleLRのデフォルトは30:70である:pct_start=0.3)。さらに、base_lrを0.1より小さくした場合についても調べる予定。OneCycleLRでも、SGDを試してみよう。

 

3月24日(水)

HuBMAP:1,291 teams:48 days to go : 0.869 ---> ???

remaining time of GPU:7 h

30エポック3サイクル、0.1-3、30:70:LB=0.857 : (train_loss=0.0253, val_loss=0.0368)

30エポック3サイクル、0.1-3、50:50:LB=0.835 : (train_loss=0.0253, val_loss=0.0353)

30エポック3サイクル、0.1-3、70:30:LB=0.834 : (train_loss=0.0270, val_loss=0.0310)

50:50は既出。昨日までのCyclicLRの結果は、すべて、50:50である。

lossは、最終エポックの平均値であり、モデルの最終パラメータは最終ステップ(バッチ)の学習結果だと思うので、これだけでも、対応関係は慎重に判断しないといけないように思う(この見立てが正しければ)。dice_coefficintの計算も、エポック毎の計算だと、予測性能の評価指標として不十分になる可能性はlossとかわらないだろう。今使っているCyclicLRは、最終エポックと最終ステップ(バッチ)における評価値(lossやacc)の差が、大きくなりやすい。(ということなのだろう)

30:70が良さそうだということで、ここまででLBスコアが最も高かった条件で、50:50を30:70に変えただけで計算し、commit, submitした。

20エポック3サイクル、0.1-2、30:70 : LB=0.849 : (train_loss=0.0252, val_loss=0.0301)

lossがエポック毎の平均値だからあてにならないとはいえ、つい、この値で判断してしまう。

submitするときにこのlossを見て、自己記録更新を確信した。

LB=0.849を見て、落胆した。

まさか、0.02も下がるとは思わなかった。

public_test_dataとの相性が悪いのだ、と思いたいが、汎用性が低い、すなわちoverfitting状態だということだろうと思う。

lossの全体としての変化の傾向から判断することにしよう。

この場合はoverfittingになったと仮定して、それを解消する方法として、少し条件のきついtransformを適用してみよう。transformの条件を強くし、他の条件はそのままで計算してみよう。

計算の結果、最終エポックでのlossは、train_loss=0.0266, val_loss=0.0372となった。train_lossが少し大きくなっているのは期待通りだが、val_lossは、平均値としてみても、あるいは1つ手前のエポックでの値と比較しても、少し大きすぎるように思う。

結果は、LB=0.875となった。自己新記録だ!

これは、30:70:LB=0.849からの0.026ものジャンプアップだ。

それならば、50:50 : LB=0.869に対して、この条件を強めたtransformを適用するとどうなるだろうか。明日計算してみよう。

もし、50:50でoverfittingになっていないのであれば、それに対して強めのtransformを適用すると、underfittingになる可能性もある。実験してみよう!

GPUの残りは5時間、20エポックで35-40分、commitがあるから70-80分、残り4条件程度となる。

OneCycleLRからCyclicLRへと移ってみたが、CyclicLRの完成系の1つが、OneCycleLRのようである。自分の計算結果を見直すと、train_lossもval_lossもOneCycleLR(optimizer=AdamW)を用いた場合の方が小さくなっている。

OneCycleLRを用いたときのLBスコアが0.86+で頭打ちになっていたのは、overfittingへの対策が不十分だったということだろうと思う。

ということで、明日は、OneCycleLR(optimizer=AdamW)と強めのtransformを用いて計算してみる。

 

3月25日(木)

HuBMAP: 1,295 teams:47 days to go : 0.875 ---> ???

remaining time of GPU:3.5 h

CyclicLRとSGDを組み合わせてある程度うまくいったので、OneCycleLRもSGDと組み合わせて使ってみよう。

OneCycleLRとAdamWとの組み合わせでLB=0.865となったコードをそのまま使う。

OneCycleLR(AdamW, maxlr=0.001) : LB=0.865 (train_loss=0.0238, val_loss=0.0311)

OneCycleLR(SGD, nesterov=True, max_lr=3) : LB=0.861 (train_loss=0.0252, val_loss=0.0286)

train_lossが小さいAdamWの方に、強めのtransformを適用してみよう。

OneCycleLR(AdamW, max_lr=0.001) : LB=0.869 (train_loss=0.0251, val_loss=0.0322)

0.004のアップ。期待したほどではなかった。

SGDのOneCycleLRを使ったものに対しても強めのtransformを試してみよう。

OneCycleLR(SGD, nesterov=True, max_lr=3) : LB=0.862 (train_loss=0.0262, val_loss=0.0328)

0.001のアップ。LB=0.875を超えることを期待したが、そうはならなかった。

 

次の1週間(3月27日(土)~4月2日(金))は、次のような、細かいチューニングをやってみよう。

⇒ OneCycleLR(SGD):max_lr=3を2.5, 2.0, 1.5,1.0等に変える。

⇒ OneCycleLR(AdamW) :epochs=20を18, 22, 24等に変える。

⇒ OneCycleLR(SGD), (AdamW) : pct_start=0.3を0.4, 0.5等に変える。

⇒ CyclicLR(SGD):3cycle epochs=3n (18, 21, 24, ... )  

⇒ CyclicLR(SGD):epochs=20, 3 cycle (step_size_up=297, step_size_down=696), max_lr=2で、mode="triangular2"を試す。

⇒ CyclicLR(SGD):base_momentum=0.85, max_momentum=0.95,を試す。

⇒ augmentationのCutout, blurなどのパラメータを変えてみる。

 

⇒ batch_size=16 --> 12 --> 8 --> 4 --> 2 -->1 ???

⇒ 画像解像度:EfficientNetB2でバッチ数を下げて解像度を上げる。256x256 --> 320x320 --> 384x384 --> 448x448 --> 512x512:overlapも増やす、32 --> 48 --> 64 --> 96 --> 128

⇒ B2 --> B3 --> B4:これは、B2で、十分に検討した後で!

⇒ train_dataの使用量を増やす。

 

overfittingの程度によって、augmentationの効果は変わる。OneCycleLRはエポック数によってoverfitting側にもnderfitting側にもある程度制御しながら振ることができるので、今日実験した系に対して、追加で試してみようと思っている。

20エポック、3サイクル、0.1-2、50:50 : LB=0.869に対して強めのtransformを試す予定だったが、OneCyleLR(SGD)を試したことで、GPUを使い切ったため、土曜日以降になる。

CyclicLRは、OneCycleLRよりも自由度が高く、良い値も得られているので、続けてみようと思う。CyclicLRには3種類のモードがあって、"triangler"は三角形の頂点の学習率が変わらないが、"triangler2"は、三角形の頂点の学習率が、1, 1/2, 1/4と減衰する。さらに、“exp_range”では、三角形の頂点の学習率が指数関数的に減衰する。gammaとステップ数によって減衰率を変えることができるのだが、ピーク値がどういう値になるかは与式に従って計算しておく必要がある。

1サイクルが300+700チャンネルで3サイクルまでの場合:

gamma=0.999:各サイクルのピーク値は、0.74, 0.27, 0.10となる。

gamma=0.9993:0.81, 0.40, 0.20となり、"triangle2"と似たような変化率になる。

gamma=0.99965:0.90, 0.63, 0.45 (1.0 : 0.7 : 0.5):ちょっと試してみたくなる。

Cyclicと1 Cycleの比較:

Cyclicのデフォルト:base_momentum=0.8, max_momentum=0.9

1 Cycleのデフォルト:base_momentum=0.85, max_momentum=0.95

Cyclicのbase_lr:固定かつデフォルト無し:論文では0.1が多いように思う。

1 Cycleのbase_lr:可変:初期値はmax_lr/div_factor(デフォルトはmax_lr/25)、最終値はmax_lr/div_factor/final_div_factor(デフォルトはmax_lr/div_factor/1e4):1 Cycleでは、学習率の初期値も最終値も、Cyclicより小さく設定しているようである。この方が良いということであれば、Cyclicのbase_lrは0.1よりも小さい値にした方が良さそうである。実験結果では、一例に過ぎないが、20エポック、2サイクル、max_lr=2で、base_lr=0.1, 0.001, 0.00001にしたとき、LB=0.839, 0.853, 0.847となった。 

 

3月26日(金)

HuBMAP:1,296 teams, 46 days to go : top 0.934

augmentationを正しく理解したい。

基本的な考え方:augmentationを行う確率は100%より低い。ある割合は元画像をそのまま通過させるためだ。ただし、切り出しやサイズ変更では100%処理もありうる。データ量が多い場合は、augmentationの必要性は少なく、確率は10-30%で変化の強度も低くする。データ量が少ない場合は、それぞれ40-50%の確率で処理し、変化の強度も高くする。

画像を水増しするというが、1つの処理を50%の確率で行うと、倍になるのか。100枚の画像に対してノイズ添加を50%の確率で行うと、50%はノイズが加わり、50%がそのまま通過する。トータルは100枚のままである。水増しの文字通りの意味であれば、元画像はそのまま使い、そのうちの半分にノイズ添加をして元の画像に足せば、150枚の画像が出来上がることになる。あるいは、100枚にノイズを添加して元の画像に加えれば200枚になる。このあたりのことを具体的に何も知らないのがはがゆい。

自分が使っているコードの動きを見ている限りでは、指定した割合でデータ加工されているようで、加工の種類を増やすとそれだけ元画像の割合が少なくなるようであり、これでいいのかなと思ってしまう。

それだったら、オートフォーカスじゃないけど、全ての画像をCNN処理しやすいように前処理できればそれがベストということになるのか。前処理せずとも全ての画像を正しく処理できるモデルを構築するということになるのか。求められているのは後者だ。実画像にありそうな画像処理をしてモデルを訓練するということだ。

import albumentations as A

transform = A.Compose([
      A.RandomCrop(512, 512),
      A.RandomBrightnessContrast(p=0.3),
      A.HorizontalFlip(p=0.5),
])

3つの処理が上から順に並んでいる。処理は、この順番に行われる。

1.元画像から512x512の部分をランダムに切り取る。これは、100%行われる。

2.1.で処理された画像のうち、3割は、明るさやコントラストの変更がランダムに行われ、7割は、未処理で通過する。

3.2.を通過した画像のうち、5割は水平方向にフリップされ、5割はそのまま通過する。

これだと、入力画像数と出力画像数は同じで、cropされただけで通過する画像は35%、cropされてフリップされた画像が35%、cropされて明るさやコントラストを変更されただけの画像が15%、cropされ明るさやコントラストを変更されフリップされた画像が15%ということになる。

こうして、1式の画像を処理した画像がメモリーに保存されると、学習中、エポック単位の画像は変化しない。エポック毎にaugmentationを行うという方法が使えれば、エポックごとに違う画像で訓練することができて、良さそうに思うが、計算時間はそれなりに増えそうに思う。

このあたりの制御を的確に行うためには、ゼロからプログラムする技術、プログラムを正確に読む技術、プログラムを正確に組み込む技術、などが必要になるので、そこを意識してプログラムを読もう。

このコンペに必要な加工を考えて、augmentationのパラメータを決めよう。そのためには、モデルが予測した結果を画像化して、どのようなミスをしているのかを具体的に把握して対策していくことが必要かもしれない。LB_scoreトップの方が、セグメンテーションが難しい糸球体を特定し、それらの画像に特化した対策をすることによってLBスコアが上がったというようなことを言っておられたと思う。

 

3月27日(土)~ 4月2日(金)LB=0.875 ---> 0.88+

1.0.875となったモデルの周辺探索(epochs, augmentation, resolution, max_lr, ...) 

2.CyclicLRの、"triangular2 ", "exp_range"の検討(21エポック以下を重点的に)

 

3月27日(土)

HuBMAP:1,303 teams, 45 days to go :  top 0.934

GPU : 42 h

Run 1 : based on the model of LB=0.875 (0.0266, 0.0372) : E20 B16(149) 1024,32,256 trfm_4 b2-Unet CyclicLR SGD(nestelov) lr=0.1-2 triangular cycle=3 298,696 momentum=0.8-0.9 BCE train_data=8+26d...+4ef... : lr=0.1-2 --> lr=0.001-2 : LB=0.867 (-0.008) (0.0271, 0.0347)

Run 2 : triangular --> triangular2 : LB=0.861 : (0.0258, 0.0375)

Run 3 : batch_size=16 --> 8 : 4エポック目まで普通だったのだが、5エポック目からtrain_loss, val_lossともに異常値を示し、5エポックほど待ったが、全く改善されなかったので中止した。

バッチサイズが変わると1エポックあたりのステップ数(データ量÷バッチサイズ)が変わるので、パラメータを計算し直さないといけないのだが、それを怠ったことによるエラーであることが分かった。20エポック、6サイクルの設定になっていた。

Run 4 : batch_size=16 --> 24 : LB=0.867 (0.0255, 0.0333)

これも再計算を怠ったので、20エポック、2サイクルで動作したことになる。

Run 5 : momentum 0.80, 0.90 --> 0.85, 0.95 : LB=0.866 (0.0278, 0.0329)

Run 6 : image 256x256 --> 320x320 : LB=0.877 (0.0238, 0.0319)

0.002だけだが、自己新記録となった。

バッチサイズ効果については、パラメータを正しく設定してやり直す必要がある。

Run 1のbase_lrの値は、OneCycleLRの設定を真似て少し低くしてみたのだが、効果的ではなかったようだ。

Run 2のtriangular2は、サイクルごとに学習率lrのピーク値が半分になるので、ピーク値が同じ場合よりも収束しやすくなって良いかなと思ったが、こう思ってしまうのは、lrを段階的に下げるとか指数関数的に下げるという従来の方法が頭にこびりついているせいだろうなと思う。

バッチサイズは、ケースバイケースのようでよくわからず、試してみたいと思ったのだが、パラメータ設定をミスったので、明日にでも、やりなおしてみる。

momentumは、OneCycleLRとCyclicLRとでデフォルトが違っているので、試しに相手側のデフォルトにしてみたということ。今回は効果的ではなかったが、使える場面はあると思う。

画像解像度を上げることは、効果的だが、overfittingとの戦いになりそう。

 

3月28日(日)

HuBMAP:1,309 teams, 44 days to go : 0.057 to first place

今日は、昨日効果が認められた320x320より画素数を増やしてみよう。

B2-Unet, batch_size=16, 320x320, CyclicLR(SGD, epochs=20, up=298, down=696, 0.1-2.0, momentum=0.8, 0.9, triangular, ... : LB=877 (0.0238, 0.0319)

384x384 : LB=0.873 (0.0229, 0.0323)

448x448 : LB=0.860 (0.0212, 0.0303)

512x512 : LB=0.871 (0.0202, 0.0294)

train_lossもval_lossも小さくなっているので、スコアが上がってもよさそうなものだが、足ふみ状態だ。train_lossが高めであることから、いずれもoverfittingになっているのだろうと思う。

ここで、decoderを変えてみよう。

512x512に対する対応可否の確認も兼ねて512x512から始めよう。

Linknet:512x512 : LB=0.876 (0.0220, 0.0285)

PSPNet:収束せず。

FPN:収束が非常に悪いので中止。

MAnet:512x512 : LB=0.865 (0.0220. 0.0284)

PSPNetとFPNの応答が良くない。その原因を調べたいが、後日とする。

 

3月29日(月)

HuBMAP:1,313 teams, 43 days to go : 

512x512について、Unet, MAnetよりも良いLBスコアを示したLinknetについて、他の解像度についても実験してみる。

256x256 : (0.0301, 0.0356) : commitまで

320x320 : 見送り

384x384 : 見送り

448x448 : (0.0224, 0.0291) : LB=0.862

Linknetの256x256, 448x448のlossの値がUnetよりも高い。このことは、LinknetがUnetよりも性能が悪いことを示唆している。512x512でも、UnetよりLinknetのlossが大きく、それでもLBスコアが高いのは、Linknetの性能が少し悪いことによってoverfitが少し抑えられたためであると推測される。Linknetについては、ひとまず中断。

解像度の低い画像に対してはencoderを大きくし、解像度の高い画像に対してはencoderを小さくする、というのも1つの方法かもしれない。

 

encoderをb2からb3, b4に変更してみた。すると、大きな問題が生じた。

320x320にb3-Unetを用いると、次に示すように、3サイクル目の3エポック目からlossが1桁大きくなりそのまま収束しなくなった。

  1│ 0.1397│ 0.0703│ 1.70
  2│ 0.0531│ 0.1602│ 1.67
  3│ 0.0576│ 0.0428│ 1.67
  4│ 0.0378│ 0.0418│ 1.67
  5│ 0.0356│ 0.0394│ 1.66
  6│ 0.0316│ 0.0344│ 1.67
  7│ 0.0292│ 0.0327│ 1.66
  8│ 0.0288│ 0.0353│ 1.67
  9│ 0.0341│ 0.0370│ 1.67
10│ 0.0350│ 0.0405│ 1.67
11│ 0.0334│ 0.0339│ 1.67
12│ 0.0299│ 0.0304│ 1.67
13│ 0.0274│ 0.0355│ 1.67
14│ 0.0260│ 0.0322│ 1.67
15│ 0.0248│ 0.0337│ 1.66
16│ 0.0273│ 0.1100│ 1.68
17│ 0.3699│ 0.2800│ 1.68
18│ 0.2860│ 0.2863│ 1.67
19│ 0.2851│ 0.2800│ 1.67
20│ 0.2845│ 0.2840│ 1.67
21│ 0.2855│ 0.2821│ 1.69

数字は、左から、エポック数、train_loss, val_loss, 計算時間(分)を表している。

3サイクル目は15エポックから始まり、17エポック目の途中で学習率lrが最大になるように設定されている。2サイクル目まで問題ないように見えて、3サイクル目でこのような現象が生じるとは思わなかった。

20エポック、3サイクルで、max_lr=3以上に設定すると、学習率lrが最大になるエポックで異常値を示すということはわかっていたが、今回のように、2サイクルまで正常だったので、驚いた。

max_lrを2.0から1.5に下げて、他はそのままで計算してみた。

15│ 0.0243│ 0.0295│ 1.66
16│ 0.0266│ 0.0417│ 1.67
17│ 0.0300│ 0.0360│ 1.69
18│ 0.0269│ 0.0586│ 1.66
19│ 0.0262│ 0.0431│ 1.67
20│ 0.0241│ 0.0339│ 1.66
21│ 0.0228│ 0.0278│ 1.68

異常は生じずに、収束した。

encoderのサイズや画像の解像度によって、max_lrを最適化することが必要であることがわかった。

256x256の画像に対してencoderにEfficientNetB3を使ったときに、最終エポックのtrain_lossが少し大きくなっている(収束が良くない)ように感じたことがあった。このときも、症状は軽いながらも、異常が生じていたということだろうと思う。

ということであれば、4サイクルに増やした時に、4サイクル目で収束しなかったのも、同様の現象が生じていたのかもしれない。すなわち、サイクルを繰り返すと、訓練が進むが、訓練が進んでも同じmax_lrを適用していると、学習率lrを大きくした効果がなくなるだけでなく、かえって、モデルが悪化したり、収束しなくなるということだろう。学習が進んだモデルに大きすぎる学習率を適用すると、完成に近づいていたモデルが壊れてしまう、ということだろう。

そういうこともあって、サイクル毎にピーク値が半減する"triangular2"がオプションとして用意されているということなのだろう。

さらに、max_lrをサイクルごとに減衰させることができ、かつ、減衰の仕方を変えることができる"exp_range"というのも、オプションとして用意されている。

3サイクル、21エポック、学習率のベースと最大値:0.1-1.5

256x256 : b3 : (0.0266, 0.0315) : LB=0.858

320x320 : b3 : (0.0228, 0.0278) : LB=0.868

encoderを大きくすることで、val_lossが小さくなってoverfittingが抑制されることを期待したが、max_lrを下げざるを得なくなって、Super-Convergenceがうまく働くなってしまっているのだろうか。

 

overfitting対策のために、augmentationの調整をしてみよう。

早速augmentationのミスがあった。

Cutoutを使っているのだが、切り出しサイズのピクセル数が、256 x 0.1のように絶対値にしていた。そうすると、画像解像度が2倍になったとき、切り取りサイズが相対的に半分になる。面積で1/4。画像の画素数が多いほど、augmentationの効果は小さくなっていたということになる。

Cutoutのサイズを画素数に連動するよう変更するとともに、確率、サイズ、個数等の適切な値を探してみよう。

次の論文のFig. 1では、隠すのは1か所で、1/4面積の正方形で、はみだしOKで、100%適用している。はみだし無しで50%とか、サイズの異なるものも試みられているようである。Kaggleのコンペで見かけるのは、サイズを小さくして数を増やしたものが多い。

f:id:AI_ML_DL:20210329213646p:plain

f:id:AI_ML_DL:20210329213555p:plain

先入観にとらわれず、色々なパターンを実験してみるしかないように思う。借り物は,小さい正方形を10枚使っている。

面積1/4のサイズを1枚:1/2 x 1/2 :確率25%に設定。

1│ 0.1415│ 0.0802│ 2.08
2│ 0.0614│ 0.1015│ 2.05
3│ 0.0744│ 0.2674│ 2.05
4│ 0.0598│ 0.0492│ 2.06
5│ 0.0479│ 0.0665│ 2.04
6│ 0.0438│ 0.0423│ 2.03
7│ 0.0404│ 0.0439│ 2.04
8│ 0.0396│ 0.0905│ 2.05
9│ 0.0472│ 0.0615│ 2.05
10│ 0.0490│ 0.0418│ 2.06
11│ 0.0437│ 0.0417│ 2.07
12│ 0.0396│ 0.0459│ 2.04
13│ 0.0367│ 0.0365│ 2.05
14│ 0.0352│ 0.0389│ 2.04
15│ 0.0365│ 0.0804│ 2.06
16│ 0.0377│ 0.0459│ 2.07
17│ 0.0406│ 0.1307│ 2.09
18│ 0.0411│ 0.0389│ 2.07
19│ 0.0370│ 0.0420│ 2.06
20│ 0.0329│ 0.0397│ 2.07
21│ 0.0340│ 0.0365│ 2.08

0.03以下でないと使えない。

面積1/10 のサイズを1枚≒0.316x0.316:確率25%に設定。

1│ 0.1341│ 0.0948│ 1.91
2│ 0.0531│ 0.0647│ 1.88
3│ 0.0431│ 0.0494│ 1.89
4│ 0.0389│ 0.0364│ 1.86
5│ 0.0358│ 0.0354│ 1.87
6│ 0.0316│ 0.0367│ 1.88
7│ 0.0296│ 0.0295│ 1.88
8│ 0.0289│ 0.0412│ 1.87
9│ 0.0307│ 0.0409│ 1.86
10│ 0.0335│ 0.0333│ 1.87
11│ 0.0315│ 0.0369│ 1.88
12│ 0.0298│ 0.0325│ 1.86
13│ 0.0271│ 0.0337│ 1.89
14│ 0.0268│ 0.0330│ 1.87
15│ 0.0258│ 0.0397│ 1.88
16│ 0.0282│ 0.0364│ 1.87
17│ 0.0296│ 0.0818│ 1.88
18│ 0.0323│ 0.0323│ 1.87
19│ 0.0274│ 0.0340│ 1.87
20│ 0.0250│ 0.0366│ 1.88
21│ 0.0256│ 0.0295│ 1.88

LB=0.874:A.cutoutが効いたかどうかはまだ不明。P=0.のときの結果が必要。

3サイクル目のlossの推移が若干、不自然のようだ。前に書いたが、3つの山が同じ高さだと、学習がある程度進んだあとの3つ目の山で収束が悪くなることや、モデルが壊れてしまうことがある。うまくいってるように見えても、収束が悪くなっている可能性がある。

ただし、ピークの高さゆえの、Super-Convergenceを利用しているので、全体を低くしてしまうわけにはいかない。

21エポック、3サイクル、batch\size=16の場合に、"exp_range"でgamma=0.9999とすれば、3つの山のピークは、0.969, 0.873, 0.787となる。こういうのを試してみよう。

gamma=1.0 (=triangular)  1.0, 1.0, 1.0 : LB=0.874 (0.0256, 0.0295)

gamma=0.9999   : 0.969, 0.873, 0.787 : LB=0.863 (0.0256, 0.0294)

gamma=0.9998   : 0.939, 0.762, 0.619 : LB=0.852 (0.0248, 0.0312)

学習率のピーク高さを減衰させると、LBスコアが低下する、という傾向が認められた。

 

4月1日(木)

GPU : no time left

ようやく、val_dice_coefficientを表示することができるようになった。

 

4月2日(金)

GPU : no time left

CPUを使って途中まで計算した結果を眺めてみよう(16エポックで止めた)。

21エポックで3サイクルになるように設定した(1サイクルが7エポック)。

CyclicLR(SGD, lr : 0.1-2.0),loss_fn=BCE, EfficientNetB2-Unet

左から、エポック数、train_loss, val_loss, train_dice, val_dice, 計算時間(min)

  1│ 0.1181│ 0.0710│ 0.6080│ 0.7867│ 26.24
  2│ 0.0676│ 0.4731│ 0.7739│ 0.3525│ 26.23
  3│ 0.0789│ 0.0875│ 0.7445│ 0.8000│ 26.10
  4│ 0.0563│ 0.2749│ 0.8181│ 0.4594│ 25.97
  5│ 0.0479│ 0.0423│ 0.8418│ 0.8608│ 25.97
  6│ 0.0398│ 0.0418│ 0.8616│ 0.8545│ 25.82
  7│ 0.0356│ 0.0334│ 0.8742│ 0.8781│ 25.85
  8│ 0.0358│ 0.0420│ 0.8740│ 0.8638│ 26.04
  9│ 0.0434│ 0.0935│ 0.8593│ 0.7237│ 26.04
10│ 0.0495│ 0.0421│ 0.8410│ 0.8683│ 26.10
11│ 0.0426│ 0.0381│ 0.8549│ 0.8719│ 26.16
12│ 0.0361│ 0.0386│ 0.8747│ 0.8560│ 26.08
13│ 0.0339│ 0.0341│ 0.8789│ 0.8730│ 25.93
14│ 0.0317│ 0.0334│ 0.8867│ 0.8852│ 26.07
15│ 0.0313│ 0.0363│ 0.8873│ 0.8756│ 26.31
16│ 0.0362│ 0.0432│ 0.8784│ 0.8691│ 26.11

val_diceは、サイクルの最後のエポック数において、最大値を示している。

2サイクル目の最後のエポックでのスコアの方が高い。今は、3回繰り返した後で、commit, submitしている。

さて、3月28日のLB=0.877を超えるためにどうすれば良いか考えよう。

これまでにわかったこと(確実なことは1つもない、すべては相対的):

・train_dataは、当初の8件だけよりは、それに2件追加して10件にすることで良くなった。15件全部使ってみたいが、今のやり方では、メモリーの制限に引っかかり、1件も増やせない。解決策はある筈なので見つけたい。

・augmentationは、機械的変形を強くしすぎると逆効果になる。形状変化を伴わない適切な光学的処理がよさそうである。Cutoutも効いているようだが、要検討。

・LB=0.87+は、CyclicLR(SGD)のみであり、20または21エポックの3サイクルで、lrの範囲は0.1-2.0である。これがベストだとは思っていない。

・画像解像度は、1週間くらい前から検討しているが、overfitting状態である。

・EfficientNetB2-Unetを超えられないのがもどかしい。B3やB4、FPNやMAnet, Linknetなどを少し試したが、それぞれに、固有のチューニングが必要で、収拾がつかなくなりそうだと感じている。

・やっと計算できるようになったDaice coefficientとLBスコアとの関係が非常に気になる。discussionでは、CVとLBは近いとのこと。0.932:0.916, 0.94:0.932, 0.923:0.924などが報告されている。

・CyclicLRを使うことによって、LBスコアが0.87+になった。

・CyclicLRのサイクル数は、論文では3サイクル以上が良いと書かれていたが、3サイクル(v28 : LB=869 : 0.0267, 0.0314)から4サイクルに増やすとスコアが下がった(v36:LB=0.851 : 0.0255, 0.0306)ので、その時点(3月23日)でサイクル数を増やすのをやめた。最終エポックでのtrain_lossとval_lossは、4サイクルの方が小さいにも関わらずLBスコアが悪く、その原因が、4サイクル目の途中のlossの異常値(0.0282, 0.1107)にあると考えたためである。しかし、この判断は早計だったかもしれない。

 

4サイクルを止めた原因となった2つのデータを比較する。

LB=0.869のデータ:20エポックで3サイクルに設定しているので、1サイクルの最後、2サイクルの最後はサイクルの最終位置ではない。(バッチ単位(ステップ)でサイクルを決めているため)

  1│ 0.1264│ 0.0543│ 1.05
  2│ 0.0544│ 0.0593│ 1.03
  3│ 0.0446│ 0.0572│ 1.03
  4│ 0.0446│ 0.0766│ 1.03
  5│ 0.0481│ 0.0416│ 1.03
  6│ 0.0390│ 0.0375│ 1.03
  7│ 0.0329│ 0.0326│ 1.03
  8│ 0.0327│ 0.0378│ 1.03
  9│ 0.0337│ 0.0335│ 1.03
10│ 0.0343│ 0.0392│ 1.03
11│ 0.0339│ 0.0386│ 1.03
12│ 0.0306│ 0.0379│ 1.03
13│ 0.0289│ 0.0330│ 1.03
14│ 0.0270│ 0.0373│ 1.03
15│ 0.0274│ 0.0353│ 1.04
16│ 0.0278│ 0.0337│ 1.02
17│ 0.0324│ 0.0978│ 1.03
18│ 0.0348│ 0.0370│ 1.03
19│ 0.0282│ 0.0316│ 1.03
20│ 0.0267│ 0.0314│ 1.03

LB=0.851のデータ:これは、20エポックで4サイクルに設定しているので、最終サイクル位置は、5, 10, 15, 20エポックと一致する。

  1│ 0.1229│ 0.0606│ 1.10
  2│ 0.0552│ 0.0577│ 1.09
  3│ 0.0441│ 0.0484│ 1.07
  4│ 0.0399│ 0.0361│ 1.10
  5│ 0.0346│ 0.0315│ 1.12
  6│ 0.0319│ 0.0384│ 1.09
  7│ 0.0334│ 0.0421│ 1.07
  8│ 0.0351│ 0.0416│ 1.08
  9│ 0.0335│ 0.0314│ 1.11
10│ 0.0307│ 0.0314│ 1.09                           11│ 0.0281│ 0.0378│ 1.09
12│ 0.0294│ 0.0362│ 1.08
13│ 0.0315│ 0.0348│ 1.12
14│ 0.0297│ 0.0372│ 1.16
15│ 0.0268│ 0.0349│ 1.12
16│ 0.0258│ 0.0286│ 1.11
17│ 0.0282│ 0.1107│ 1.00
18│ 0.0323│ 0.0368│ 1.13
19│ 0.0277│ 0.0321│ 1.09
20│ 0.0255│ 0.0306│ 1.10

このときは、LBスコアが低かったことと、赤で示した0.1107から、4エポックはダメと判断したのだが、3サイクルの場合でも、赤で示したように 0.0978というのがある。
4サイクルにすることでlossは下がっているので、LBスコアが3サイクルより低くなった原因は他にあると考えて、サイクル数を増やしてみようと思う。
3サイクルと4サイクルを正しく比較するには、1サイクルあたりのエポック数を同じにしなければならない。1サイクルを何エポックにするかは最適化できていないのでこれも含めて実験する必要がある。1サイクルの中での学習率が最大になるピーク位置についても最適化が必要で、この2つの場合は1サイクルの中心だったが、ある時点(v43)から、OneCycleLRでのデフォルト0.3(3:7)になるようにステップ数(step_size_up, step_size_down)を設定している。

4月3日(土)

GPU : 36 h (5.14 h/day)

Run 1:LB=0.875の計算過程におけるDice coefficientの確認(20エポック3サイクル)と、3サイクル以降のtrainingの経過調査(40エポック6サイクルに設定し、40エポックでのDice_coeffが良ければcommit, submitする。

20エポックでのval_dice_coeff=0.888であった。これがLB=0.875だというのは納得できる値だと思う。40エポック目のval_dice_coeff=0.9011となったので、commit, submitしてみよう。その結果が良ければ、60エポック、あるいは80エポックを試してみよう。結果は、LB=0.799であった。こうなると、次の一手が分からなくなってしまう。 

勝手にCutoutを悪者扱いして、Cutoutの影響/効果を調べる。そのために、Cutoutの確率0.25と0.0を比較する。

Cutout=0.25:val_dice_coeff=0.895 : LB=0.862

Cutout=0.0   : val_dice_coeff=0.903 : LB=0.850

Cutoutは、overfittingを抑制する効果があったということかな。

それにしても、val_dice_coefficientがまったく役に立たないとは、困ったものだ。

明日は、手前のサイクル数で止めて、LBスコアを出してみよう。しかし、こんなことをしても、前の週からの進展は、殆ど期待できないような気がする。

 val_dice_coefficientを計算することで、条件検討が捗ると期待したが、これでは、なんにもならない。何の指標にもならないのか。それとも、プログラミングに問題があるのか。val_lossと同一の手順で、val_lossに併記しているので、validationの結果を計算できている筈なのだが。

今日は、最高に、期待外れの日だった。

最初に、20エポック3サイクルでLB=0.875となったモデルで、20エポックの先を見るために、40エポック6サイクルの計算を行い、40エポック後にcommit, submitしたら、LB=0.799となった。val_Diceは20エポックで0.888となり、40エポックでは0.9011まで上がったので、20エポックの0.888でLB=0.875だから、40エポックの0.901では、LB=0.885くらいになると予想していたのだが、LB=0.799という値となった。残念過ぎる結果だ。

20エポック3サイクルというのは、立ち上がりが2エポックで、立下りが6.666エポックである。これだと学習率の最小値や最大値がエポックの中間にあらわれるので、立ち上がりを2エポック、立下りを4エポックという組み合わせに変更した。これだと、6エポック単位でサイクルが繰り返されるので、たとえば、5,6サイクルくらいまで計算しておいて、良さそうなサイクル数を選んで再度計算するのに都合が良いと考えた。

ということで、30エポック5サイクルで計算し、augmentationを3段階に設定して計算した。LBスコアは、augmentationの弱い方から、0.850, 0.862, 0.847となった。これもまた平凡な値になった。これらのval_Diceは、0.903, 0.895, 0.896であった。

3サイクルで0.875のモデルを6サイクルまで訓練したら、性能がガタ落ちしたということである。overfittingだけでは片づけられない問題だと思う。

augmentationの条件を3段階変えた例では、0.852がoverfitting、0.862は、augmentationによる予測性能の向上もしくはoverfittingの抑制、0.847は過剰なaugmentationということか。何のことかわからないので、解決策がわからない。

不適切なaugmentationだが、結果としてoverfittingは抑制されてLBスコアが少し上がったが、augmentationを強めると不適切な操作であるため、予測性能は低下した、ということかもしれない。今回変更したのはCutoutで、1)使わない、2)10個の正方形で、各正方形の面積は画像の1%、確率は25%、3)同2%、確率25%。 1%や2%というのは、1次元だと小さく感じるが、2次元だと、ヒトの目には大きく感じるものである。

LB=0.875は、Cutout(25%)とAffine(12.5%)を含んでいる。3サイクルまでは、ある程度学習が進み、適度なaugmentationによって予測性能が向上した。そこからさらに3サイクルほど学習が進む間に、CutoutやAffineのような幾何学的な画像操作による変形を学習してしまい、スライスによる入力画像であるがゆえのアーティファクトに過剰に反応するようになった、ということは考えられないだろうか。

 

4月4日(日)

GPU : 28 h

今日は、5サイクル30エポック、(1)Cutout無し、(2)0.1、(3)0.1414、について検討する。30エポックまで訓練したモデルのLBスコアは、(1)0.850、(2)0.862、(3)0.847だった。これを過剰訓練により、汎用性が失われたと推測する。過剰訓練によるものかどうかを確認するには、5サイクルより前のサイクルで終了させたモデルの予測性能をLBスコアで評価すればよい。

最初に、(1)Cutout無しについて、1サイクル後(6エポック後)のモデルで予測した結果を調べることから始めてみよう。lossを見ると、計算してみようとか、調べてみようとか思わないのだが、val_Diceの値を見ると、本当にそうなのだろうかと気になる。

6エポックと12エポックの結果が出た。ひどいもんだ。train_lossとval_lossだけ見ているほうが、まだまし、と思ってしまう。

epochs | train_loss | val_loss | train_Dice | val_Dice |

  1│ 0.1260│ 0.0678│ 0.5811│ 0.8120│
  2│ 0.0554│ 0.0500│ 0.8127│ 0.8475│ 
  3│ 0.0444│ 0.0867│ 0.8497│ 0.7538│ 
  4│ 0.0438│ 0.0386│ 0.8480│ 0.8574│ 
  5│ 0.0387│ 0.0511│ 0.8690│ 0.7533│ 
  6│ 0.0376│ 0.0347│ 0.8624│ 0.8859│ LB=0.850

..........

12│ 0.0286│ 0.0332│ 0.8988│ 0.8953│ LB=0.855

..........

18│ 0.0272│ 0.0322│ 0.9032│ 0.8987│ LB=0.852

..........

24│ 0.0243│ 0.0322│ 0.9125│ 0.9031│ 

..........

30│ 0.0235│ 0.0398│ 0.9144│ 0.9026│ LB=0.850

(1)Cutout無し、はここまで。(2)Cutout : 0.1、の12エポックと18エポックを計算しておこう。その後で、Dice_coefficientの計算を見直す。

(2)Cutout : 0.1(LB=0.875のモデルとの違いは、1サイクルのエポック数で、LB=0.875のモデルは、3サイクルで20エポック、ここでは、3サイクルで18エポック。

12│ 0.0300│ 0.0363│ 0.8931│ 0.8842│ LB=0.859

..........

18│ 0.0286│ 0.0305│ 0.8987│ 0.8930│ LB=0.859

Cutout : 0.1を追加することによって、train_lossが少し大きくなっている。train_lossは、パラメータの変化に対して最も再現性の良い指標の1つである。これに対して、val_lossは、試料数が少ないことや偏りがあることなどのために、ばらつきが大きい。

LBスコアを上げることはできなかったが、サイクル数の最適化には必要な作業だろうと思う。

 

***Dice coefficientのコードを変更している間に、inferenceのコードもおかしくなってしまったので、LB=0.877(version52/87)のコードまでもどって再スタートする。Dice coefficientのことは、しばらく忘れよう。

 

この2日間で得たLBスコアは、0.799, 0.862, 0.850, 0.847, 0.832, 0.850, 0.855, 0.852, 0.859, 0.859の10件である。

4月3日から4月9日の計画は、lossとDice coefficientとLBスコアの相関を調べて整理することによって、次の進め方を考えることであった。

この2日間でわかったことは、Dice coefficientの計算に失敗しているらしいこと、Dice coefficientを指標にして決めたサイクル数の設定条件(特に、1サイクルあたりのエポック数:良い結果を得ていたのは3サイクル20エポックであり、これは、1サイクルあたりのエポック数が整数にならないので、今回は、3サイクル18エポック(5サイクル30エポック)の検討と、Dice coefficientの計算と、Dice coefficientを指標にして、サイクル数とLBスコアの関係を調べようとした。得られた結果は、

・Dice coefficientの計算ができるようにしたが、それらしい値は示しているものの、LBスコアとの対応は良くない。

・3サイクル20エポックと同等かそれ以上の性能を求めて、3サイクル18エポックすなわち1サイクル6エポックを検討したが、3サイクル20エポックに近い、3サイクル18エポックでのLBスコアは、0.859となり、3サイクル20エポックでのLBスコア0.875より0.016小さい値となった。5サイクル30エポックでのLBスコアが0.862であったことも加味すると、今の諸々の条件下では、1サイクル6エポックは、1サイクル6.67エポック(3サイクル20エポック)よりも小さいLBスコアになることが分かった。1サイクル6エポックはdownのサイクル数が少ないぶんだけ、学習量が少なく、lossの下がりが少なくなったのだろう。

 

明日以降の予定:

1.1サイクル7エポック(up: 2 epochs, down: 5 epochs)と8エポック(up: 2 epochs, down: 6 epochs)を試す。

2.Cutout条件と1サイクルのエポック数の見直し:320pixelの画像を使ったときに、LBスコアが、0.877と0.862になった。両者の違いは2か所ある。0.877は、3サイクル20エポック、かつ、cutoutが0.1x256を10か所。0.862は、3サイクル21エポック(1サイクル7エポック)、かつ、cutoutが0.1x320を10か所。0.1x256と0.1x320とでは、ホール面積は1.56倍異なる。

3.Cutout条件の見直し:多数ホールか単一ホールか、および、ホールのサイズ

これらをふまえつつ、512 pixelにフォーカスして検討してみようと思う。

 

4月5日(月)

HuBMAP: 1,374 teams, 36 days to go

今日は、CyclicLRの1サイクルから始めてみよう。

1サイクル7エポック (up: 2epochs, down: 5 epochs): LB=0.859 (0.0255, 0.0292)

このあたりのLBスコアはもう見たくない。1サイクルのエポック数を増やしてみよう。立ち上がりも2エポックから3エポックに増やしてみよう。立ち上がりを1サイクルの30%にするのがOneCycleLRのデフォルトであることからここでもその値を用いてみよう。そうすると、立ち上がりが3エポック、下りが7エポックとなる。

1サイクル10エポック (up: 3 epochs, down: 7 epochs): LB=0.880 (0.0235, 0.0287)

ようやく、0.877(320 pixel)を超えたが、256 pixelで0.875が得られているので、512 pixelで0.880というのは、まだ何も達成していないのと同じようなものだ。

2サイクル20エポックを試してみよう。

2サイクル20エポック (up: 3 epochs, down: 7 epochs) x 2 : LB=0.870 (0.0203, 0.277)

train_loss=0.0203となっているので、overfitting状態になっている。 

この状態から、Cutout条件を適正に設定することによって、LBスコアを0.89+にもっていくことができる筈だ。と思って取り組もう。カラーやノイズについても検討しよう。

 

4月6日(火)

***また、文字変換の途中でフリーズして、フォーマットがぐちゃぐちゃになった。復元ボタンを使っても、フォーマットがぐちゃぐちゃのままで、全く使えない。無意味な復元ボタン!これで、何回目かな。なにもなくても(何かあったのだろうが気付かなかったのだろう)次に文書を開くとフォーマットが崩れていることもあった。*** 

1時間半くらい、GPUの使用計画を立てていたのだが、消えてしまった。脳の中に少し残っているので書きとめておこう。

改善の対象とするデータ:2サイクル20エポック (up: 3 epochs, down: 7 epochs) x 2 : LB=0.870 (0.0203, 0.277)

検討課題1:Cutout:hole_numとホール面積の調整:ベース:hole_num=10, hole_size=1/10(hole_area=0.01):2サイクル20エポックに適用して、train_lossが0.022~0.023くらいで、LB=0.88+になること。

検討課題2:Cutoutのベース条件で、train_lossが0.018レベルになること。何サイクル何エポックが最適かわからない。512 pixelで条件探索するのは時間がかかる。256 pixelで基本を押さえておこう。

実験:512 pixel

1.3サイクル30エポックで、train_lossが0.02以下になるかどうかを確認する。

2.hole_num=1, hole_area=0.1(hole_size=0.316)で、2サイクル20エポック条件の計算を行う。

予備実験:256 pixel

512 pixel 3サイクル30エポックで所望の結果(train_lossが0.018以下になること)が得られるかどうかを、256 pixelで確認する。

256 pixelでは、1サイクル10エポックはなく、2サイクル20エポックはあるが、3:7ではなく5:5である。3サイクル30エポックは3:7であるが、0.1-2.0ではなく0.1-3.0である。lr=0.1-3.0では、train_lossが、10E:0.0281, 20E:0.0255, 29E:0.0243, 30E:0.0253となっていて、LB=0.857(trfm_1:弱)であった。256 pixeで参考になるデータが少ないので、1から始めることになる。計算時間は512 pixelの1/3くらいですむが、基本データをとって、条件検討をするにはそれなりの時間がかかる。

ということで、256 pixelによる予備実験はとりやめにする。

まずは、512 pixelで、3サイクル30エポックの結果を確認しようか。

2サイクルで30エポックはどうだろうか。upは3エポックのままで、downを7エポックから12エポックに増やし、15エポックで0.21くらいまで下がれば、2サイクル目で0.185くらいまで下がることを期待するか。

ということは、1サイクルで15エポックがどうなるか調べておく必要がある。

1サイクル15エポック(up:3, down:12) : (0.0208, 0.0291) : LB=0.867

train_lossが0.021より少し低い値になったので、2サイクルで0.0185くらいになることを期待してもよさそうだ。

384 pixelの画像に対して、hole_num=1, hole_area=0.1(hole_size=0.316)と、hole_num=10, hole_size=0.1 (hole_area=0.01)を用いた結果を既に出していて、どちらを適用してもLBスコアが変わらなかったので、hole_num=1の条件を強くして適用することにしよう。

論文ではhole_area=0.25で良好な結果が得られると書かれていたように思うので、これを真似てみることにして、1サイクル15エポックに適用してみた。

1サイクル15エポック& hole_num=1, hole_area=0.25(hole_size=0.5) : (0.0293, 0.0347) : LB=0.878

train_lossは、0.0208から0.0293まで大きくなった。これはダメかな、ホールの面積が大きすぎたので、もう少し小さくしようかなと考えていたのだが、LBスコアが出てみると、それほど悪くない。使えそうだ!これで学習量を増やしていけば、LB=0.89+になるかもしれない。

サイクルを繰り返してみた。(CyclicLRというのは同じ学習を繰り返すことだということを、今初めて実感している。)

2サイクル30エポック& hole_num=1, hole_area=0.25(hole_size=0.5) : (0.0271, 0.0406) : 

思っていたほど、15エポックより30エポックのtrain_lossのほうが小さくなっているので、学習を繰り返した効果があったということだが、30エポックのval_lossが大きいので、LBスコアは上がるのだろうかと、かなり心配しながら、commitしているところ。

結果は、LB=0.859でした。ホールサイズが大きすぎたようだ。次はホールサイズを少し小さくしようと思うが、GPUの残り時間が6時間半となったし、1サイクル10エポックシリーズも先に検討しておきたいことがあるので、この続きは今週の土曜日以降になる。

学習経過は、こんなふうになった。

  1│ 0.1490│ 0.1265│ 2.98
  2│ 0.0597│ 0.0598│ 2.93
  3│ 0.0500│ 0.0583│ 2.94
  4│ 0.0465│ 0.0400│ 2.95
  5│ 0.0451│ 0.0450│ 2.94
  6│ 0.0392│ 0.0489│ 2.95
  7│ 0.0383│ 0.0482│ 2.95
  8│ 0.0366│ 0.0410│ 2.94
  9│ 0.0358│ 0.0388│ 2.94
10│ 0.0329│ 0.0441│ 2.96
11│ 0.0336│ 0.0362│ 2.96
12│ 0.0314│ 0.0415│ 2.98
13│ 0.0311│ 0.0444│ 2.97
14│ 0.0308│ 0.0376│ 2.95
15│ 0.0293│ 0.0347│ 3.00 : LB=0.878
16│ 0.0289│ 0.0384│ 2.95
17│ 0.0320│ 0.0620│ 2.97
18│ 0.0354│ 0.0527│ 2.97
19│ 0.0360│ 0.0528│ 2.98
20│ 0.0339│ 0.0427│ 3.00
21│ 0.0319│ 0.0343│ 2.97                           22│ 0.0315│ 0.0400│ 2.96
23│ 0.0332│ 0.0341│ 2.97
24│ 0.0304│ 0.0471│ 2.98
25│ 0.0301│ 0.0453│ 2.97
26│ 0.0299│ 0.0352│ 2.98
27│ 0.0302│ 0.0404│ 2.96
28│ 0.0320│ 0.0360│ 2.98
29│ 0.0283│ 0.0365│ 2.96
30│ 0.0271│ 0.0406│ 2.95 : LB=0.859

この結果から、hole_area=0.25ではなく、0.20や0.15を使えば、15エポックでは、0.880を超えることができそうである。

1サイクル15エポックは、2サイクルに用いる繰り返しの単位としては、長すぎたようだ。最適な単位エポック数はいくらだろうか。6は短すぎたようだ。7は効果的だった。それ以上は検討できていない。間をとばして10と15を試みているというところだが、upとdownの比率は3:7が良好だが、upが2エポックの場合は1サイクルが7エポックくらい、upが3エポックの場合は1サイクルが10エポックとなる。upが4エポックの場合は、1サイクルが13エポックくらいとなる。上記の1サイクル15エポックはupが3サイクルなので、upとdownの比率は2:8となる。3:7は、OneCycleLRのデフォルトということであって、CyclicLRに対してのデフォルトではない。CyclicLRのデフォルトは5:5である。CuclicLRのupとdownの比率を5:5から3:7に変更したのは、CyclicLRのチューニング中にOneCycleLRのデフォルト設定値を思い出してちょっとやってみようと思っただけである。どのような比率がベストなのかはわからない。実験して探すしかない。元に戻ると、upが3エポックでdownが12エポックの1サイクル15エポックは、単独では悪いモデルではないのかもしれない。これをそのまま繰り返して2サイクル30エポックとして動作させた場合、今回は、良いモデルではなかったということ。

schedulerに限らず、気に入らなければ自分で書き換えれば良い。最初は既製品をデフォルトで使う。慣れてくると内部パラメータの適切な組み合わせを探すようになる。さらに進むと、既製品ではできないパラメータの組み合わせを試してみたくなる。このときに、元のコードに戻って、自分で書き換えて、既製品では不可能だった動作をさせることができるようになりたいものだ。

CyclicLRで使っていないパラメータがある。これら {triangular, triangular2, exp_range}の他に、自分で関数を入力することができる。

scale_fn (function) – Custom scaling policy defined by a single argument lambda function, where 0 <= scale_fn(x) <= 1 for all x >= 0. If specified, then ‘mode’ is ignored. Default: None

次のサイトに簡単な関数例が示されている。現状でも、まだできることがある。

https://github.com/keras-team/keras-contrib/blob/master/keras_contrib/callbacks/cyclical_learning_rate.py

clr_fn = lambda x: 0.5*(1+np.sin(x*np.pi/2.))

 

4月7日(水)

HuBMAP: 1,397 teams, 34 days to go : me:0.880 ---> top:0.939

GPU : 6.5 h

2サイクル20エポック(train_loss=0.0203 : LB=0.870)については、3サイクル30エポックに、hole_num=1, hole_area=0.25(hole_size=0.5)、を適用する。

この予定だったが、2サイクル30エポックのLBスコア向上に失敗したので、この1サイクル10エポック系は、2サイクル20エポックで0.880を超えることを目指す。

面積率とホールサイズ:0.1≒0.316x0.316 : 0.15≒0.387x0.387 : 0.2≒0.447x0.447

Base  : 1 cycle 10 epochs : num_hole=10, hole_size=0.1 x 0.1 : LB=0.880 (0.0235, 0.0287)

Run1 : 1 cycle 10 epochs : num_hole=1, hole_size=0.387 x 0.387 : LB=0.864 (0.0271, 0.0312)

この2つは直接比較できないが、Cutoutの全ホール面積が1.5倍になったことによってunderfittingの傾向になったと考える。次に、後者の条件でサイクルを繰り返すことによって、学習が進み、underfittingが解消されることによって、スコアが上がると予想した。train_loss, val_lossともに、小さくなっているので、予想通り、学習は進んだので、LBスコアは上がる筈だと思うのだが、上がるどころか、少し下がった。

Run2 : 2 cycle 20 epochs : num_hole=1, hole_size=0.387 x 0.387 : LB=0.860 (0.0243, 0.0305)

CutoutがLBスコアの向上に寄与しなかった理由として何が考えられるだろうか。使っているCutoutのパターンは、ホールが1個と10個の場合の2種類である。Cutoutのオリジナル論文は、ホールが1個、HuBMAPのコンペで自分が見た使用例は、ホールが10個、であり、そのことについてのコメントや注釈は見当たらなかった。ということから、これは、比較評価することが必要である。気になっていたのだが、1個のホールの方が良いと思い込んでいたかもしれない。ということで、予想通りのスコアが得られなかった原因として、Cutoutのパターンの選択が課題に対して適切でなかったということが考えられる。

 

1サイクル15エポック& hole_num=1, hole_area=0.25(hole_size=0.5) : (0.0293, 0.0347) : LB=0.878

この結果に対して、hole_area=0.20や0.15にすれば、LBスコアは0.880を超える筈だと書いた。これを確かめよう。

1サイクル15エポック& hole_num=1, hole_area=0.20(hole_size=0.447) : (0.0270, 0.0335) : LB=0.880

わずかに改善したが、超えられなかった。

上に書いたように(もっと前にも書いたような気がする)ホールが1個の場合と10個の場合の比較をする必要がある。もっといえば、適切なホールの個数と面積の組み合わせを探す必要がある。実験結果に基づかないことを根拠や指標にしていることがある(多い)ように思うので注意しよう。

 

予測性能を上げるために必要なことが何であるのか、正しく理解できていない。道具の使い方を間違っているのかもしれない。適用範囲を逸脱した領域で使っているのかもしれない。わからないことがたくさんある。何がわかっていないのかもわからない。

 

同一視野の画像の画素数による違い:EfficientNetB2-Unet, CyclicLR(SGD), lr=0.1-2.0, up 3 epochs, down 7 epochs, BCE, trfm_4

512 pixel

  1│ 0.1387│ 0.0823│ 3.16
  2│ 0.0468│ 0.0521│ 3.15
  3│ 0.0382│ 0.0438│ 3.14
  4│ 0.0372│ 0.0404│ 3.11
  5│ 0.0335│ 0.0374│ 3.11
  6│ 0.0297│ 0.0319│ 3.12
  7│ 0.0270│ 0.0352│ 3.12
  8│ 0.0259│ 0.0317│ 3.12
  9│ 0.0248│ 0.0291│ 3.14
10│ 0.0235│ 0.0287│ 3.12 : LB=0.880

256 pixel

  1│ 0.1422│ 0.0888│ 1.14
  2│ 0.0595│ 0.0557│ 1.13
  3│ 0.0519│ 0.1444│ 1.13
  4│ 0.0484│ 0.0510│ 1.12
  5│ 0.0414│ 0.0405│ 1.12
  6│ 0.0396│ 0.0499│ 1.12
  7│ 0.0372│ 0.0422│ 1.12
  8│ 0.0350│ 0.0343│ 1.12
  9│ 0.0315│ 0.0334│ 1.12
10│ 0.0308│ 0.0299│ 1.11 : LB=0.869

OneCycleLRを使っていた頃とはaugmentationの条件がかなり異なっている可能性が高いので、OneCycleLRについても再度計算(性能確認)する必要があるように思う。

 

4月8日(木)

HuBMAP:1,405 teams, 33 days to go

 256 pixel, batch_size=24, CyclicLR(SGD, 0.1-2.0, 3:7, 298:696), trfm_4, v50

  1│ 0.1572│ 0.0902│ 1.10
  2│ 0.0589│ 0.0579│ 1.08
  3│ 0.0475│ 0.0444│ 1.08
  4│ 0.0437│ 0.0397│ 1.08
  5│ 0.0393│ 0.0433│ 1.08
  6│ 0.0368│ 0.0418│ 1.08
  7│ 0.0344│ 0.0319│ 1.08
  8│ 0.0331│ 0.0322│ 1.08
  9│ 0.0302│ 0.0309│ 1.08
10│ 0.0295│ 0.0311│ 1.08                           11│ 0.0290│ 0.0339│ 1.08
12│ 0.0295│ 0.0361│ 1.08
13│ 0.0309│ 0.0383│ 1.07
14│ 0.0327│ 0.0366│ 1.07
15│ 0.0318│ 0.0392│ 1.07
16│ 0.0303│ 0.0320│ 1.08
17│ 0.0298│ 0.0370│ 1.08
18│ 0.0285│ 0.0318│ 1.08
19│ 0.0269│ 0.0344│ 1.08
20│ 0.0255│ 0.0333│ 1.08 : LB=0.867

3サイクル20エポックで、batch_size=16-->24を検討するつもりだったが、ステップサイズを変更するのを忘れたために、当初の実験目的を外れたもの。

上に示した256 pixelの条件とbatch_size以外は全く同じで、1サイクル10エポック、を繰り返したものになっている。

1サイクル10エポックでは、バッチサイズを16から24に増やすことで、学習は少し効率よく進んだようにみえる。LBスコアへの影響を後日調べてみる。

 

EarlyStopping

迷路に迷い込んでいるような気がしている。学習率は低減させていくのが常識だったし、train_lossとval_lossの動きを見ていて、両者が大きく乖離しないことと、val_lossが反転しない事の両方を満たすところで学習を停止するのが常識だったと思うのだが、OneCycleLRやCyclicLRはこれまで見たことが無いような変化をするので、惑わされてしまったように思う。OneCycleLRもCyclicLRも、設定しておいた最終エポックで良好な結果が得られるものだと思い込んでしまっていたように思う。

その流れで、512 pixel、20エポック3サイクル、学習率0.1-2.0で20エポックでのtrain_lossが0.0202になったのを見て、ここから、augmentationの条件を適切に調整することができさえすれば、スコアは上がっていくものと思い込んでしまった。

このことに気がついたからと言って、スコアが上がるわけではない。地道に、トライアンドエラー、系統的な実験、先人に学ぶ、ということを繰り返していく・・・。

EarlyStoppingの考え方に近い/関連性があるのは、サイクル数の繰り返しを減らす、最終エポック数を設定エポック数の少し手前に設定する、トータルエポック数を減らす、小さなモデル(今使っているモデルだと小さなEncoder)を用いる、画像の解像度を下げる、などであるから、結局はそれらの間のバランスをとりながら、LBスコアが最大になる組み合わせを探索し、アンサンブルやTTAを適切に組み合わせるということになるのだろう。言うは易し、行うは難し・・・。

 

LB=0.925のモデル(inferenceはコンペサイトのnotebook(code)、trainはGitHub)が公開されているので、そのあたりのスコアを望むだけなら真似すれば良いだけだが(とはいえ、口で言うほど簡単ではないが)、自分としては、今のやり方でスコアアップを目指すことが自分には必要だと思っている。すでに、その公開コードからエッセンスの一部を拝借しながら進めているので大きなことは言えないが、それでも、直接真似るのと、実験しながら進めるのとでは大きな違いがあると思っている。

 

4月10日(土)から4月15日(木)までの6日間の実験計画を立てよう!

目を閉じると、シナプスが活動しているのが見えるような気がする。そろそろ、良いアイデアが浮かんでもよさそうなものだが、浮かんでこないということは、努力が足りていないということなのだろう。集中力が足りないのか。深く考えるために必要な演算能力と記憶能力が不足しているのだろうか。記憶したものが片っ端から消去されているような気がする。

明日は、4月15日までに、LB=0.880 ---> 0.900、となることを目指して、実験計画を立てよう。0.900 - 0.880 = 0.001 x 20 : 0.001の改善を20回繰り返せば0.900に到達!

*overfitting条件にしてから、augmentationを強めてjust-fittingにもっていこうとしていて条件探しの途中だが、min_lrとmax_lrの組み合わせ、1サイクルのエポック数、サイクル数、up_epochとdown_epochの組み合わせ、encoder、バッチサイズ、画素数なども並行して検討する必要がある。

限られた時間と資源の中で、効果的に実験する方法を考えよう。

教師データの量と質:バッチサイズ:モデル:損失関数:最適化関数:学習率スケジューラー

OneCycleLRから始めて、CyclicLRに移り、サイクル数や最大学習率、upとdownの比率などパラメータが多くて最適化はうまくいかず、最近の512 pixelの画像を使った実験では、CyclicLRを使いながら、11回の計算のうち、3回が2サイクルで8回は1サイクルであった。こうなった理由は、256 pixelの画像を使った場合よりも収束が速く、サイクルを繰り返すことによってlossを小さくする必要がなかったことにある。2回目に試みた1サイクル10エポックでLB=0.880になったが、それ以降はこれを超えることができていない。GPUを使った最後のテストは、512 pixelで0.88を得た1サイクル10エポックを256 pixelに適用することで、LB=0.869となった。1サイクルで十分ならば、OnsCycleLRがある。明日からのGPUマシンタイムは、OneCycleLRに集中するか1サイクルとの併用で進めようと思う。

バッチサイズの影響は、条件設定ミスで調べることができなかったので、優先度を上げて実施する。

Cutoutは、10ホールと1ホールの比較が不十分で、その中間状態(3ホールとか5ホール)については、全く調べることができていない。

256 pixelと512 pixelの間(320, 384, 448 pixelなど)はCutoutの条件設定ミスを含んだ結果があるだけで、0.877となった320 pixelすら、フォローできていない。これら中間的な解像度で良い結果が得られる可能性は高いと思うので、順に結果を出していく。

Encoderは、EfficientNetB2に固定して進めているが、underfittingになればB3やB4を試し、overfittingになればB1やB0を試すなど、最適な組み合わせを探っていく。

Decoderは、2月頃はFPNが良さそうであったが、3月末に調べたときには、FPNは収束が悪く、LinknetとMAnetは使えそうであったが、Unetに優るような感じはしなかった。

損失関数は、BCEから始めてDiceに落ち着きそうだったが、ある条件でDiceLossでは収束が遅くなったときにBCEで良好な結果が得られてからBCE単独で進めている。他の損失関数との組み合わせもどこかのタイミングで試してみたいと思っている。今回のマシンタイムに組み込もう。

 

4月10日(土)の予定

最初に、OneCycleLRの10エポックと20エポックの性能を評価し、CyclicLRで得られている結果と比較する。

Run1&2 : 256 pixelのスコアLB=0.875を、OneCycleLR(Adam)とOneCycleLR(SGD)で再現できるかどうかを調べる。CyclicLR(SGD)は3サイクル20エポックなので、20エポックで試す。

Run3&4 : 256 pixelのスコアLB=0.869を、OneCycleLR(Adam)とOneCycleLR(SGD)で再現できるかどうかを調べる。CyclicLR(SGD)は1サイクル10エポックなので、10エポックで試す。

 

4月11日(日)の予定:

256 pixelの画像を用いて、3サイクル20エポックで、LB=0.875を得ていたモデルとパラメータを用いて、1サイクルnエポックで同等のLBスコアが得られる条件を見出す。

CyclicLRによる1サイクル10エポックでは、LB=0.869が得られているので、エポック数を増やすだけで0.875に近い値が得られるのではないかと思っている。このときに、4月10日に検討したOneCycleLRの方が優れていれば、OneCycleLRを用いて、エポック数の最適な値を探すことになる。

 

4月12日(月)の予定:

Cutoutの1ホールと3ホールと10ホールのトータル面積を等しくしてその効果の比較を行う。面積率は0.10とする。

 

4月13日(火)の予定:

バッチ数の効果を調べる。これまでの16をベースとして、24と32について調べる。

 

4月14日(水)の予定:

素数の効果を調べる。256, 320, 384, 448, 512とし、256 pixelでの最大スコアが得られている条件をベースとして、画素数が増えるごとに、1エポックづつエポック数を減らして計算する。

たとえば、512 pixelでは、10エポックで0.880が得られているので、これをスタートラインとするならば、448 pixelでは11エポック、384 pixelでは12エポック、320 pixelでは13エポック、256 pixelでは14エポック、のように画像解像度が低いほどエポック数を増やす。

ただし、512 pixelありきで考えるよりは、256 pixelの方から積み上げていく方が、最終スコアは上がるのではないかと思っている。 

 

4月15日(木)の予定:

損失関数の検討。upとdownの割合、max_lr、

 

<CPUを用いた予備検討>

CPUを用い、同一条件で、ResNet34と EfficientNetB0の学習結果を比較してみる。

model = smp.Unet('resnet34', encoder_weights='imagenet', classes=1), batch_size=16, CyclicLR(SGD), lr=0.1-2.0, up=3 epochs, down=7 epochs

 

  1│ 0.1392│ 0.1253│ 25.53
  2│ 0.0850│ 0.5311│ 25.57
  3│ 0.1121│ 0.0932│ 25.49
  4│ 0.0781│ 0.0548│ 25.21
  5│ 0.0607│ 0.0632│ 25.28
  6│ 0.0568│ 0.0721│ 25.40
  7│ 0.0501│ 0.0496│ 25.34
  8│ 0.0479│ 0.0408│ 25.31
  9│ 0.0426│ 0.0397│ 25.25
10│ 0.0405│ 0.0372│ 25.37

model = smp.Unet('efficientnet-b0', encoder_weights='imagenet', classes=1), CyclicLR(SGD), lr=0.1-2.0, batch_size=16, up=3 epochs, down=7 epochs
  1│ 0.1533│ 0.1128│ 20.32                                                                                                      2│ 0.0657│ 0.3048│ 20.44
  3│ 0.0649│ 0.0624│ 20.31
  4│ 0.0587│ 0.0810│ 20.21
  5│ 0.0490│ 0.0474│ 20.67
  6│ 0.0444│ 0.0669│ 20.60
  7│ 0.0430│ 0.0385│ 20.67
  8│ 0.0381│ 0.0359│ 20.63
  9│ 0.0358│ 0.0337│ 20.44
10│ 0.0333│ 0.0360│ 20.44

以上の2つの結果は、resnet34とEfficientNetB0との違いを示すものである。これらのモデルで予測した結果がどうなるかまでは調べていないので安易な評価をしてはいけないかもしれないが、train_loss, val\lossともにEfficientNetB0の方が小さくなっているので、後者の方が速く収束しているとみてもよいのだろうと思う。

次に、model = smp.Unet('efficientnet-b0', encoder_weights='imagenet', classes=1)に対して、OneCycleLR(SGD, max_lr=2, epochs=10)を適用してみる。

  1│ 0.1547│ 0.0819│ 21.97
  2│ 0.0648│ 0.6287│ 21.18
  3│ 0.0905│ 0.1146│ 21.12
  4│ 0.0600│ 0.0506│ 21.11
  5│ 0.0493│ 0.0416│ 21.15
  6│ 0.0458│ 0.0681│ 21.23
  7│ 0.0418│ 0.0395│ 21.25
  8│ 0.0388│ 0.0364│ 21.19
  9│ 0.0355│ 0.0330│ 21.24
10│ 0.0334│ 0.0337│ 21.48

CyclicLRの1サイクルとOneCycleLRとで見た目には大差ない結果となっているように見える。同じ最適化関数とmax_lrを用いているが、異なるところは、学習率lrの変化が、CyclicLRが三角波であるのに対して、OneCycleLRはコサイン関数(三角波を選ぶこともできる)となっていることである。さらに、OneCycleLRでは、学習率lrの初期値と最終値を別々に指定することができる。デフォルトではlrの最終値はlrの初期値(デフォルトではmax_lrの1/25)より4桁小さい。

GPUが使えるようになれば、予測結果をsubmitしてLBスコアを比較する予定である。

最後に、model = smp.Unet('efficientnet-b0', encoder_weights='imagenet', classes=1)に対して、AdamWを最適化関数に用いた、OneCycleLR(AdamW, max_lr=1e-3, epochs=10)を試してみよう。これは、CyclicLRを使う前に、1か月以上使っていたものである。

  1│ 0.4280│ 0.1768│ 24.61
  2│ 0.1092│ 0.0692│ 24.71
  3│ 0.0607│ 0.0490│ 25.10
  4│ 0.0479│ 0.0434│ 25.04
  5│ 0.0439│ 0.0369│ 24.94
  6│ 0.0403│ 0.0374│ 24.98
  7│ 0.0371│ 0.0331│ 25.30
  8│ 0.0348│ 0.0341│ 25.21
  9│ 0.0327│ 0.0351│ 25.25
10│ 0.0320│ 0.0341│ 25.23

id predicted
0 aa05346ff 15325 185 46045 185 76764 187 107482 189 13820...
1 2ec3f1bb9 60690327 20 60714307 41 60738287 56 60762271 6...
2 3589adb90 68511797 12 68541223 56 68570651 65 68600081 7...
3 d488c759a 62493304 1 62539963 4 62586623 5 62633282 6 62...
4 57512b7f1 217865569 2 217898801 14 217898952 3 217932039...

 

4月10日(土)~4月16日(金)

GPU : 40 h

目標:LB=0.880 ---> LB=0.900

手段:256 pixelのLB=0.875から、augmentation, batch_size, loss_fn, optimizer, learning_scheduler, pixel_size, encoder-decoder,などの最適化

 

4月10日(土)

GPU : 40 h

HuBMAP:1,421 teams, 31 days to go : top LB score 0.943

今日は、OneCycleLRを用いて、256 pixelの自己記録LB=0.875を超えることを目指す。

CyclicLR(SGD, 0.1-2.0)の、1サイクル10エポックでLB=0.869、3サイクル20エポックでLB=0.875が得られている。

さて、このような状況で、本日最初の一手をどう指せばよいだろうか。これまでの248回のsubmissionデータを完璧な機械学習モデルに入力し学習させたら、どのような出力が出てくるだろうか。「入力データの質が悪すぎて予測不可能」と出力されそう。

5月10日のLBスコアの予測なら、簡単に答えが出てきそうだ。そんなのは、方眼紙にプロットすればすぐ出てくる。

2月22日(月):0.836(EfficientNetB5-Unet,scse, DiceLoss, OneCycleLR(Adam, max_lr=1e-3, 30 epochs)

3月20日(土):0.850(EfficientNetB2-Unet, BCELoss, OneCycleLR(Adam, max_lr=1e-3, 20 epochs, : train_loss= 0.0219, val_loss=0.0356):更新データ8件使用

同日:0.865 更新データ10件使用(データ更新によりtrain_dataは8件から15件に増えたがメモリーの制約により今と同じ10件のみ使用): (train_loss=0.0238, val_loss=0.0311)

3月24日(水):0.875, Cutout

3月28日(日):0.877, 320 pixel

4月5日(月):0.880, 512 pixel

5月10日(月):0.95???:妄想による予測結果

 

OneCycleLR

Adam or SGD

max_lr:Adamなら1e-3, SGDなら2.0

up/(up+down):デフォルトは0.3

エポック数 10CyclicLRの1サイクル10エポック(v12)との比較、及び、baselineとして

その他:encoder-decoder, pixel_size, batch_size, loss_fn, augmentation,

b2-Unet, 256 pixel, batch_size=16, BCELoss, Cutout 10, 10%

 

1サイクル10エポックLB=0.869のlossは、(0.0308, 0.0299)であったのに対し、OneCycleLR(SGD, max_lr=2.0, epochs=10)では、(0.0310, 0.0315)であった。

結果:LB=0.866(-0.003となった):0.869より少し低いが、CyclicLR(SGD)との比較ということでは、これで十分である。

次のターゲットは、3サイクル20エポックで得られたLB=0.875である。これには、エポック数を増やすことが必要だが、どこから始めようか。

それとも、エポック数10で、バッチ数の効果を先に調べておくか。

batch_size=16 : train_loss=0.0310, val_loss=0.0315 : LB=0.866

batch_size=24 : train_loss=0.0283, val_loss=0.0302 : LB=0.868

batch_size=32 : train_loss=0.0311, val_loss=0.0328 : commit, submitせず

batch_sizeを24に増やすと収束が良くなり、LBスコアも少し上がったが、32に増やすと収束が悪くなった。batch_sizeを大きくすると、GPUモリー占有量が増えて、大きな画素数の画像が扱えなくなることも加味して、batch_sizeは、16を継続する。

さて、エポック数をどうしようか。

15エポックと20エポックは、計算しておく必要がありそうだ。

OneCycleLR(SGD)のエポック数を増やすだけではなく、max_lrやupとdownの比率などの調整が必要になるかもしれない。

次の2つの場合について実験する:まずは、LB=0.869を越えないと。

OneCycleLR(SGD, max_lr=2.0, epochs=15) : loss (0.0273, 0.0308) : LB=0.858

予測結果が、これまでと違っていて心配だ。LB=0.858となり、悪い予想が的中した。

10エポックの結果はこうなっていた。

OneCycleLR(SGD, max_lr=2.0, epochs=10, pct_start=0.3) : loss (0.0310, 0.0315) : LB=0.866

train_lossとval_lossの値は、常識的には、15エポックの方が、かなり優れている。にもかかわらず、10エポックよりもLBスコアが悪い。

こうなると、次に20エポックを試してもだめだろう。

15エポックの方が悪くなる原因として考えられるのは、15エポックの中身で、upが3割だから、内部では、upが4.5エポック、downが10.5エポックとなっている。10エポックのときは、upが3エポックで、downが7エポックである。10エポックと15エポックの本質的な違いは、学習率の変化率である、10エポックの場合は、3エポックで最大学習率2.0に達するが、15エポックでは、4.5エポックで最大学習率に達する。この違いが、Super-Convergenceの効果に大きな違いを生じている可能性がある。

とりあえず、15エポックの場合に、3エポックで学習率が最大になるように、pct_startを0.3から0.2に変更してみる。そうするとupが3エポックで、downが12エポックとなる。

OneCycleLRも、CyclicLRも性能を発揮するための条件は、Super-Convergenceなので、それを満たす条件から外れると、通常の学習率の制御方法を用いた場合よりも、非常に悪い結果しか得られないということになるのではないかと思う。

ということは、train_lossとval_lossの組み合わせに対して、従来の常識に従って判断すると、良い結果を見逃し、悪い結果に固執してしまうことにもなりかねない。

自分が落ち込んでいた罠の正体の何割かは、これによるものではないだろうか。

非常に気になったので、"super convergence deep learning" で検索したら、Super-Convergenceを理論的に解明した(らしい)論文があった。

Super-Convergence with an Unstable Learning Rate
Samet Oymak∗, arXiv:2102.10734v1 [cs.LG] 22 Feb 2021
Abstract
Conventional wisdom dictates that learning rate should be in the stable regime so that gradient-based algorithms don’t blow up. This note introduces a simple scenario where an unstable learning rate scheme leads to a super fast convergence, with the convergence rate depending only logarithmically on the condition number of the problem. Our scheme uses a Cyclical Learning Rate where we periodically take one large unstable step and several small stable steps to compensate for the instability. These findings also help explain the empirical observations of [Smith and Topin, 2019] where they claim CLR with a large maximum learning rate leads to “super-convergence”. We prove that our scheme excels in the problems where Hessian exhibits a bimodal spectrum and the eigenvalues can be grouped into two clusters (small and large). The unstable step is the key to enabling fast convergence over the small eigen-spectrum.

 従来の通念では、勾配ベースのアルゴリズムが爆発しないように、学習率は安定した状態にある必要があります。 このノートでは、不安定な学習率スキームが超高速収束につながる単純なシナリオを紹介します。収束率は、問題の条件数に対数的にのみ依存します。 私たちのスキームは、不安定性を補うために、定期的に1つの大きな不安定なステップといくつかの小さな安定したステップを実行する循環学習率を使用します。 これらの調査結果は、[Smith and Topin、2019]の経験的観察を説明するのにも役立ちます。ここでは、最大学習率が高いCLRが「超収束」につながると主張しています。 私たちのスキームは、ヘッセ行列が二峰性スペクトルを示し、固有値を2つのクラスター(小さいものと大きいもの)にグループ化できる問題に優れていることを証明します。 不安定なステップは、小さな固有スペクトルでの高速収束を可能にするための鍵です。(Google翻訳

原理がわかっても、答えはわからない。個々の条件/状況によって実際に適用するときの数値は異なる。 

15エポックの場合に、3エポックで学習率が最大になるように、pct_startを0.3から0.2に変更してみた。(upが3エポックで、downが12エポック)

OneCycleLR(SGD, max_lr=2.0, epochs=15, pct_start=0.2) : loss (0.0272, 0.0320) : LB=0.865

最後に、12エポックを試しておく。pct_start=0.25としておけば、3エポックで学習率が最大になる。

OneCycleLR(SGD, max_lr=2.0, epochs=12, pct_start=0.25) : loss (0.0289, 0.0325) : LB=0.866

 

得られた結果を並べてみよう。3エポックまでは、全く同じであることがわかる。

OneCycleLR(SGD, max_lr=2., epochs=10, pct_start=0.3) : loss (0.0310, 0.0315) : LB=0.866

  1│ 0.1526│ 0.2327│ 1.12
  2│ 0.0623│ 0.0656│ 1.10
  3│ 0.0517│ 0.0459│ 1.11
  4│ 0.0494│ 0.0451│ 1.10
  5│ 0.0426│ 0.0481│ 1.10
  6│ 0.0418│ 0.0406│ 1.11
  7│ 0.0369│ 0.0373│ 1.11
  8│ 0.0359│ 0.0387│ 1.10
  9│ 0.0320│ 0.0339│ 1.11
10│ 0.0310│ 0.0315│ 1.10

OneCycleLR(SGD, max_lr=2., epochs=12, pct_start=0.25) : loss (0.0289, 0.0325) : LB=0.866

  1│ 0.1526│ 0.2327│ 1.14
  2│ 0.0623│ 0.0656│ 1.11
  3│ 0.0517│ 0.0459│ 1.12
  4│ 0.0494│ 0.0452│ 1.12
  5│ 0.0430│ 0.0498│ 1.13
  6│ 0.0417│ 0.0451│ 1.12
  7│ 0.0374│ 0.0395│ 1.12
  8│ 0.0373│ 0.0427│ 1.12
  9│ 0.0334│ 0.0355│ 1.12
10│ 0.0320│ 0.0330│ 1.12
11│ 0.0299│ 0.0332│ 1.11
12│ 0.0289│ 0.0325│ 1.11

OneCycleLR(SGD, max_lr=2., epochs=15, pct_start=0.2) : loss (0.0272, 0.0320) : LB=0.865

  1│ 0.1526│ 0.2327│ 1.13
  2│ 0.0623│ 0.0656│ 1.11
  3│ 0.0517│ 0.0459│ 1.11
  4│ 0.0495│ 0.0452│ 1.11
  5│ 0.0430│ 0.0549│ 1.10
  6│ 0.0426│ 0.0649│ 1.11
  7│ 0.0397│ 0.0424│ 1.12
  8│ 0.0386│ 0.0389│ 1.12
  9│ 0.0345│ 0.0354│ 1.11
10│ 0.0330│ 0.0335│ 1.11
11│ 0.0315│ 0.0330│ 1.12
12│ 0.0301│ 0.0373│ 1.11
13│ 0.0284│ 0.0322│ 1.11
14│ 0.0275│ 0.0352│ 1.11
15│ 0.0272│ 0.0320│ 1.10

 

明日は、3エポックで学習率が最大になる条件で、最大学習率を極限まで上げてみよう。CyclicLRを使っているときに、最大学習率が大きすぎると、lossが一旦大きくなって下がった後、収束しなくなるので、そうならない最大の値に近い値に設定して、LBスコアがどうなるかを調べてみよう。

256 pixelでLB=0.875となった、3サイクル20エポックの場合は、2エポックで最大学習率が2.0となる条件であった。

512 pixelでLB=0.880となった1サイクル10エポックの場合は、3エポックで最大学習率が2.0となる条件であった。

素数によってもSuper-Convergenceの条件は異なるかもしれない。EfficientNetのB番号によってもSC条件は異なるかもしれない。FPNが収束しなかったのもSC条件が合わなかったことによるのかもしれない。

 

4月11日(日)

HuBMAP:1,429 teams, 30 days to go

エポック数10、12、15、は、それぞれ、up=3, down=7、up=3, down=9、up=3, down=12であった。これらの立ち上がりエポック数を2にして、立下りをup=3の場合と同じにすると、それぞれ、up=2, down=7、up=2, down=9、up=2, down=12となる。そうするためには、若干誤差を含むが、pct_startを、それぞれ、0.222、0.182、0.143とすればよい。以下の3通りの条件で計算してみよう。

OneCycleLR(SGD, max_lr=2., epochs=9, pct_start=0.222) : LB=0.861

OneCycleLR(SGD, max_lr=2., epochs=11, pct_start=0.182)

OneCycleLR(SGD, max_lr=2., epochs=14, pct_start=0.143

 

OneCycleLRは、デフォルトのコサインモード(anneal_strategy='cos')にしているが、CyclicLRは、"triangle"すなわち線形モード(anneal_strategy='linear')であった。

OneCycleLRでは、両方のモードが使えるので、その比較をやってみよう。

OneCycleLR(SGD, max_lr=2., epochs=9, pct_start=0.222, anneal_strategy='linear') : LB=0.863

OneCycleLR(SGD, max_lr=3., epochs=9, pct_start=0.222, anneal_strategy='linear') : 

max_lr=3と大きくしたことで、lossは(0.0608, 0.0494)までしか下がらなかったので、エポック数を増やしてみる。CyclicLRなら、downのエポックを増やすか、もう1サイクル追加すればlossはさらに下がるのだが、OneCycleLRでは、downのエポック数を増やすという選択肢だけである。

OneCycleLR(SGD, max_lr=3., epochs=14, pct_start=0.143, anneal_strategy='linear') :

2エポック目まで同じ条件のはずだが、2エポック目でlossが数桁大きくなり、収束しなくなった。

OneCycleLR(SGD, max_lr=3., epochs=14, pct_start=0.214, anneal_strategy='linear')

upを3エポックにしてみた。こういうことをしていると、もう、OneCycleLRを使う意味がないという気がしてきた。LB=0.856だった。コサインアニールに戻そう。

OneCycleLR(SGD, max_lr=3., epochs=14, pct_start=0.214, anneal_strategy='cos')

LB=0.857だった。低空飛行が続いています。

比較のために、1か月前のOneCycleLRのデフォルトを試して、OneCycleLRを終わろう。

OneCycleLR(AdamW, max_lr=1e-3., epochs=14) : LB=0.867

 

0.85+~0.86+をウロウロしていただけ!

OneCycleLRよりもCyclicLRの方が良さそうだ。上にも示した、次の論文に従って、CyclicLRに戻ろうか。 

Super-Convergence with an Unstable Learning Rate
Samet Oymak∗, arXiv:2102.10734v1 [cs.LG] 22 Feb 2021

Our scheme uses a Cyclical Learning Rate where we periodically take one large unstable step and several small stable steps to compensate for the instability.

one large unstable step and several small stable steps

 

256 pixel, 1サイクル10エポック、0.1-2.0, up=3, down=7, trfm_4, B2-Unet

  1│ 0.1422│ 0.0888│ 1.15
  2│ 0.0595│ 0.0557│ 1.13
  3│ 0.0519│ 0.1444│ 1.14
  4│ 0.0484│ 0.0510│ 1.12
  5│ 0.0414│ 0.0405│ 1.13
  6│ 0.0396│ 0.0499│ 1.13
  7│ 0.0372│ 0.0422│ 1.13
  8│ 0.0350│ 0.0343│ 1.13
  9│ 0.0315│ 0.0334│ 1.13
10│ 0.0308│ 0.0299│ 1.12 : LB=0.869

このデータもって、CyclicLRの再出発としよう。256 pixelで、LB=0.875を超えよう。

 

4月12日(月)

HuBMAP:1,435 teams, 29 days to go

SGDはCyclicLRではnesterov=Trueとして用いてきたが、これをFalseにしてみた。結果は、LB=0.867(v1)であった。Trueの場合のLB=0.869と大差なかった。以後もnesterov=Trueにしておこう。

max_lrを0.25に上げてみよう。結果は、LB=0.856(v2)となった。upが3エポック、downが7エポックで、変えていないのだが、lossがいったん下がってから上昇したときの最大値が4エポック目で、5エポック目もlossの下がりが少なく、最後の10エポックでもlossは十分下がらなかった(0.322, 0.314)。

次は、max_lrを1.5に下げてみよう。結果は、LB=0.865(v3)となった(0.0302, 0.0309)。

極大は、max_lr=2.0と1.5の間のようだ。

max_lrをどこまで上げられるかを調べることの方が重要なので、max_lr=3.0にしてみよう。3エポック目にval_lossが0.4を超えたが、10エポック目には(0.0315, 0.0302)となり、LB=0.867(v4)となった。max_lr=2.5でLB=0.856となったので駄目だろうなと思ったのだが、予想外の結果となった。

  1│ 0.1369│ 0.0986│ 0.5470│ 0.7288│ 1.14
  2│ 0.0601│ 0.0554│ 0.7964│ 0.8399│ 1.12
  3│ 0.0509│ 0.4107│ 0.8279│ 0.3687│ 1.13
  4│ 0.0524│ 0.0696│ 0.8217│ 0.7586│ 1.12
  5│ 0.0458│ 0.0572│ 0.8440│ 0.8088│ 1.12
  6│ 0.0449│ 0.0463│ 0.8454│ 0.8219│ 1.12
  7│ 0.0400│ 0.0525│ 0.8623│ 0.8356│ 1.11
  8│ 0.0355│ 0.0347│ 0.8782│ 0.8721│ 1.12
  9│ 0.0330│ 0.0346│ 0.8840│ 0.8820│ 1.12
10│ 0.0315│ 0.0302│ 0.8907│ 0.8912│ 1.12 : LB=0.867(v4)

それではと、max_lyを5.0にしてみとところ、val_lossが1.0を超え、train_lossもval_lossも0.28くらいから下がらなくなった。これはダメのようだ。

max_lr=4.0を試すことにした。val\lossが3エポック目に0.5以上、5エポック目に0.3以上となってどうなることかと思ったが、10エポック目には(0.0316, 0.0311)となり、LB=0.861(v5)となった。

  1│ 0.1368│ 0.0944│ 0.5481│ 0.7352│ 1.14
  2│ 0.0648│ 0.1624│ 0.7842│ 0.6723│ 1.12
  3│ 0.0546│ 0.5056│ 0.8184│ 0.5011│ 1.13
  4│ 0.0689│ 0.0789│ 0.7807│ 0.7328│ 1.12
  5│ 0.0472│ 0.3160│ 0.8415│ 0.2536│ 1.12
  6│ 0.0480│ 0.0460│ 0.8402│ 0.8534│ 1.12
  7│ 0.0388│ 0.0496│ 0.8685│ 0.8269│ 1.12
  8│ 0.0361│ 0.0363│ 0.8769│ 0.8597│ 1.13
  9│ 0.0337│ 0.0353│ 0.8818│ 0.8803│ 1.12
10│ 0.0316│ 0.0311│ 0.8897│ 0.8883│ 1.11 : LB=0.861(v5)

今日はここまで。

 

次はこれらを2サイクルにしてみよう。2サイクルにしてoverfittingするようであれば、downのエポック数を減らしてみよう。(up:3, down:7) x 2 --> (up:3, down:6) x 2 --> (up:3, down:5) x 2  

その前に、1エポックのままで、かつ、upは3エポックのままで、downを増やしてみようと思う。最終エポックの10エポック目で、train_lossよりもval_lossが小さいからであるが、downを1エポック増やしてみたら、val_lossの方が大きくなった。

 

*一向に進まない。次の論文を読もう。

GRADIENT DESCENT ON NEURAL NETWORKS TYPICALLY OCCURS AT THE EDGE OF STABILITY
Jeremy Cohen Simran Kaur Yuanzhi Li J. Zico Kolter1 and Ameet Talwalkar2
Carnegie Mellon University and: 1Bosch AI 2 Determined AI
Correspondence to: jeremycohen@cmu.edu

arXiv:2103.00065v1 [cs.LG] 26 Feb 2021, Published as a conference paper at ICLR 2021

 

4月13日(火)

HubMAP:1,445 teams, 28 days to go

 

上記の論文、難しくて理解が進まないのだが、勾配降下法で最適解に到達しようとするときに、従来の方法で到達する最適解とは違うところに、より汎用性の高い解が存在し、そこに到達するためには、従来のtraining方法とは異なる考え方が必要だということが書かれているように思う。

f:id:AI_ML_DL:20210413092141p:plain

max_lr=2, (up=3, down=7) x 2で、LB=0.875となった。

  1│ 0.1422│ 0.0888│ 0.5264│ 0.7703│ 1.13
  2│ 0.0595│ 0.0557│ 0.8006│ 0.8261│ 1.12
  3│ 0.0519│ 0.1444│ 0.8270│ 0.5969│ 1.13
  4│ 0.0484│ 0.0510│ 0.8348│ 0.8596│ 1.12
  5│ 0.0414│ 0.0405│ 0.8568│ 0.8779│ 1.12
  6│ 0.0396│ 0.0499│ 0.8632│ 0.8479│ 1.12
  7│ 0.0372│ 0.0422│ 0.8725│ 0.8453│ 1.13
  8│ 0.0350│ 0.0343│ 0.8806│ 0.8712│ 1.12
  9│ 0.0315│ 0.0334│ 0.8888│ 0.8898│ 1.12
10│ 0.0308│ 0.0299│ 0.8922│ 0.8917│ 1.12 : LB=0.869
11│ 0.0300│ 0.0350│ 0.8935│ 0.8831│ 1.13
12│ 0.0327│ 0.0377│ 0.8852│ 0.8755│ 1.11
13│ 0.0339│ 0.0381│ 0.8823│ 0.8691│ 1.12
14│ 0.0338│ 0.0362│ 0.8835│ 0.8727│ 1.14
15│ 0.0326│ 0.0337│ 0.8858│ 0.8754│ 1.14
16│ 0.0309│ 0.0336│ 0.8920│ 0.8885│ 1.12
17│ 0.0308│ 0.0480│ 0.8921│ 0.8323│ 1.13
18│ 0.0304│ 0.0320│ 0.8926│ 0.8868│ 1.14
19│ 0.0279│ 0.0399│ 0.9009│ 0.8760│ 1.14
20│ 0.0261│ 0.0325│ 0.9079│ 0.8883│ 1.14 : LB=0.875

 

3サイクル20エポックに加えて、2サイクル20エポックでもLB=0.0875になった。

1サイクル20エポックも試してみるかな。

 

max_lr=2.0を常用しているが、上限を確認するために3.0, 4.0, 5.0と変えてみた。upのエポック数は3である。upが2エポックの場合、max_lr=3ではlossが異常値を示して収束しなくなった。upを3エポックにすると、max_lr=5以外は、収束した。

SGDのnesterovはTrueで使っているが、画素数を多くしたときのoverfittingを抑制する効果があるかもしれないと思い、nesterov=Falseを試し始めた。

・収束は、1サイクル10エポックの場合、1エポックから2エポックくらい遅いようだ。

・384pixelの場合に、max_lr=3で異常値を示して収束しなかったが、nesterov=Falseにすると、異常値を示さず、収束した。

 

明日は、画素数の効果を調べる。

CyclicLRで最も簡単な1サイクル10エポックを用いる。

max_lrは、3または4を用いる。

 

4月14日(水)

HuBMAP:1,453 teams, 27 days to go

CyclicLRで最も簡単な1サイクル10エポックを用い、max_lrは3または4を用いて、画素数320, 384, 448, および512 pixelについてtrain, inference, commit, submitした結果、512 pixelの画像を用いた場合のLB=0.880が最良となった。ということで、またしても記録更新ならず。

SGDのnestrov=Falseは、max_lr=3でlossが異常値を示して収束しなかったものについて適用したところ、lossが順調に収束するということでは良かったのだが、スコアは向上しなかった。

 

4月15日(木)

HuBMAP:1,454 teams, 26 days to go

今日は、EfficientNetB2-UnetでLB=0.869が得られた条件のままで、B2を、B3, B4, B5, B6, B7と変えることにより、LBスコアがどうなるかを調べる。エポック数、サイクル数、Max_lr、upとqornの比率など、とても調べ切れるものではなく、最適値の組み合わせとは程遠いかもしれないが、ともかく、どういう傾向になるか調べてみよう。

256 pixel : 

B2-Unet : LB=0.869

b3-Unet : LB=0.858

B4-Unet : LB=0.873

B5-Unet : LB=0.860

B6-Unet : LB=0.875

B7-Unet : LB=0.868

LBスコアとしては、期待外れ。ちょっと面白いのは、この並びでは、でこぼこしていて傾向が見えにくいが、偶数組と奇数組に分けて並べると、各組の中ではモデルが大きいほどLBスコアが高くなっている、ということがわかる。

B2-Unet : LB=0.869

B4-Unet : LB=0.873

B6-Unet : LB=0.875

b3-Unet : LB=0.858

B5-Unet : LB=0.860

B7-Unet : LB=0.868

trainingの経過データをいくつか掲載しているが、overfittingといっても、train_diceは0.91止まり。これでは、トップレベルのLBスコアを出している人たちのval_diceである、0.92なんておぼつかない。

256 pixel : CyclicLR(SGD, up:down=3:7, lr=0.1-2.0), 2サイクル20エポックのtraining結果

  1│ 0.1489│ 0.0727│ 0.4805│ 0.7530│ 2.03
  2│ 0.0564│ 0.0646│ 0.8073│ 0.8146│ 2.02
  3│ 0.0567│ 0.0586│ 0.8260│ 0.8512│ 2.02
  4│ 0.0455│ 0.0428│ 0.8513│ 0.8492│ 2.02
  5│ 0.0386│ 0.0387│ 0.8714│ 0.8745│ 2.02
  6│ 0.0359│ 0.0394│ 0.8789│ 0.8570│ 2.02
  7│ 0.0333│ 0.0356│ 0.8855│ 0.8809│ 2.02
  8│ 0.0309│ 0.0304│ 0.8932│ 0.9017│ 2.01
  9│ 0.0284│ 0.0304│ 0.9003│ 0.8987│ 2.02
10│ 0.0272│ 0.0304│ 0.9039│ 0.8999│ 2.01 : LB=0.875
11│ 0.0267│ 0.0314│ 0.9051│ 0.8969│ 2.02
12│ 0.0292│ 0.0375│ 0.8988│ 0.8889│ 2.01
13│ 0.0304│ 0.0474│ 0.8982│ 0.8721│ 2.02
14│ 0.0316│ 0.0331│ 0.8939│ 0.8980│ 2.02
15│ 0.0285│ 0.0346│ 0.9011│ 0.8837│ 2.01
16│ 0.0264│ 0.0329│ 0.9074│ 0.8894│ 2.02
17│ 0.0258│ 0.0301│ 0.9091│ 0.9040│ 2.02
18│ 0.0256│ 0.0295│ 0.9104│ 0.9013│ 2.01
19│ 0.0239│ 0.0300│ 0.9146│ 0.9062│ 2.02
20│ 0.0245│ 0.0291│ 0.9149│ 0.9007│ 2.02 : LB=0.872

 
4月16日(金)

HuBMAP: 1,459 teams, 25 days to go

モデルのアンサンブルとTTAによって、LB=0.880の壁を突破したいと思うのだが、それよりも、まだ、CyclicLRで調べたいことがある。

 

4月17日(土)

GPU : 36 h

HuBMAP1,461 teams, 24 days to go

何度も同じ文献を見ているように思うが、都度、観点は異なる。今日は、サイクル数を繰り返すことによって改善される場合と、改善されない場合について整理してみようと思う。そのときに、思い出されるのが次の論文のFigure 2(b)である。1サイクルで最良値が得られ、サイクルを繰り返しても最初の値を超えていないように見える。

EXPLORING LOSS FUNCTION TOPOLOGY WITH CYCLICAL LEARNING RATES

L. N. Smith and N. Topin, arXiv:1702.04283v1 [cs.LG] 14 Feb 2017

f:id:AI_ML_DL:20210417091026p:plain

これまでに得られた結果が示唆するもの

1.1サイクルで良好な結果が得られる条件では、2サイクル、3サイクルと繰り返しても、1サイクルの結果を超えない。

2.3サイクルで良好な結果が得られる条件では、2サイクル、1サイクルでは3サイクルの結果を超えない。

3.画像解像度を上げることは、スコアアップにつながる。

4.Encoderのモデルサイズを大きくすることは、低解像度の画像を用いた場合に、スコアアップにつながる。

 

512 pixel, 1サイクル10エポック、lr=0.1-2.0で、(up=4, down=6)と、(up=down=5)について計算してみよう。

up=5, down=5 : LB=0.868

up=4, down=6 : LB=0.872

up=3, down=7 : LB=0.880

up=2, down=8 : LB=0.872

 

Cutoutの効果を調べる。

num_holes=1, max_h_size=int(0.316 * 512):(0.316 * 0.316 ≒ 0.1)

  1│ 0.1379│ 0.0758│ 0.5463│ 0.7905│ 3.02
  2│ 0.0502│ 0.0560│ 0.8334│ 0.8330│ 2.99
  3│ 0.0394│ 0.0866│ 0.8675│ 0.7177│ 3.01
  4│ 0.0403│ 0.0383│ 0.8618│ 0.8809│ 3.00
  5│ 0.0336│ 0.0388│ 0.8831│ 0.8766│ 3.01
  6│ 0.0320│ 0.0446│ 0.8899│ 0.8725│ 3.00
  7│ 0.0302│ 0.0448│ 0.8958│ 0.8498│ 3.02
  8│ 0.0279│ 0.0311│ 0.9022│ 0.8840│ 3.01
  9│ 0.0261│ 0.0292│ 0.9073│ 0.9017│ 3.00
10│ 0.0247│ 0.0271│ 0.9135│ 0.9030│ 3.02 : LB=0.865

比較データ:num_holes=10, max_h_size=int(0.1 * 512):LB=0.880

 

4月18日(日)

HuBMAP:1,466 teams, 23 days to go

 

Loss functionは、BCE(BCEWithLogitsLoss)で固定したままだった。

今日は、Dice, Jaccard, Lovasz, Focalを試してみよう。

B2-Unet, 512 pixel, CyclicLR(SGD, nesterov, lr=0.1-2.0, up=3, down=7, 10 epochs)

BCE : LB=0.880

Dice : 

  1│ 0.3138│ 0.2053│ 0.6862│ 0.7947│ 3.05
  2│ 0.1600│ 0.8500│ 0.8400│ 0.1500│ 3.02
  3│ 0.1658│ 0.3692│ 0.8342│ 0.6308│ 3.05
  4│ 0.1341│ 0.1762│ 0.8659│ 0.8238│ 3.02
  5│ 0.1147│ 0.1261│ 0.8853│ 0.8739│ 3.01
  6│ 0.1147│ 0.1424│ 0.8853│ 0.8576│ 3.04
  7│ 0.1035│ 0.1919│ 0.8965│ 0.8081│ 3.01
  8│ 0.1214│ 0.1200│ 0.8786│ 0.8800│ 3.02
  9│ 0.0917│ 0.0930│ 0.9083│ 0.9070│ 3.01
10│ 0.0851│ 0.1060│ 0.9149│ 0.8940│ 3.01 : LB=0.812

LBスコアは非常に低い。それでも、次は、downを7から12に増やしてみよう。

Jaccard : 

  1│ 0.5231│ 0.9143│ 0.6076│ 0.1578│ 3.05
  2│ 0.3025│ 0.7233│ 0.8190│ 0.4285│ 3.02
  3│ 0.2833│ 0.8238│ 0.8330│ 0.2968│ 3.05
  4│ 0.2603│ 0.3547│ 0.8485│ 0.7812│ 3.06
  5│ 0.2442│ 0.3780│ 0.8583│ 0.7605│ 3.02
  6│ 0.2029│ 0.3472│ 0.8861│ 0.7875│ 3.04
  7│ 0.1871│ 0.2345│ 0.8960│ 0.8621│ 3.02
  8│ 0.1695│ 0.1764│ 0.9068│ 0.9017│ 3.03
  9│ 0.1618│ 0.1593│ 0.9111│ 0.9126│ 3.04
10│ 0.1510│ 0.1796│ 0.9179│ 0.8991│ 3.03 : LB=0.814

Diceと同様、9エポックで止めた方がスコアは良さそうだ。次は、downを7から12に増やしてみよう。

Lovasz : 

機能せず。原因不明。

Focal : 

収束はするが、非常に遅い。train_Dice_coeff, Val_Dice_coeffともに、0.72を超えず。

Lovasz, Focal, ともに、期待していたのだが、使ってみなければわからないものだ。

SGDとの相性だろうか。

 

Dice_LossとJaccard_Lossは、どちらもスコアアップの可能性がありそうなので、最適条件を探索してみたいが、時間も資源も限られている。そこで、BCE_lossで良い結果を得ている、up=3, down=12の条件にするとともに、Cutoutも強め(num_holes=1, max_h_size=int(0.447 * 512), 0.447^2≒0.2)にして計算してみる。

Dice_Loss :

  1│ 0.3315│ 0.2272│ 0.6685│ 0.7728│ 3.04
  2│ 0.1863│ 0.9131│ 0.8137│ 0.0869│ 3.03
  3│ 0.1695│ 0.9015│ 0.8305│ 0.0985│ 3.00
  4│ 0.1760│ 0.3990│ 0.8240│ 0.6010│ 3.01
  5│ 0.1522│ 0.1426│ 0.8478│ 0.8574│ 3.03
  6│ 0.1270│ 0.1614│ 0.8730│ 0.8386│ 2.99
  7│ 0.1271│ 0.1413│ 0.8729│ 0.8587│ 3.01
  8│ 0.1161│ 0.1543│ 0.8839│ 0.8457│ 3.00
  9│ 0.1142│ 0.1338│ 0.8858│ 0.8662│ 2.99
10│ 0.1064│ 0.1156│ 0.8936│ 0.8844│ 3.02
11│ 0.1093│ 0.1155│ 0.8907│ 0.8845│ 3.00
12│ 0.1068│ 0.1251│ 0.8932│ 0.8749│ 3.03
13│ 0.0989│ 0.1062│ 0.9011│ 0.8938│ 3.03
14│ 0.0918│ 0.1090│ 0.9082│ 0.8910│ 3.00
15│ 0.0882│ 0.0841│ 0.9118│ 0.9159│ 3.05 : LB=0.842

downを5エポック増やして、Cutoutを加えてみたが、だめだった。

JaccardLoss :

  1│ 0.4901│ 0.9936│ 0.6367│ 0.0126│ 3.20
  2│ 0.3292│ 0.9128│ 0.8001│ 0.1601│ 3.17
  3│ 0.2946│ 0.9769│ 0.8245│ 0.0446│ 3.17
  4│ 0.2760│ 0.7785│ 0.8374│ 0.3552│ 3.17
  5│ 0.2781│ 0.7158│ 0.8355│ 0.4395│ 3.17
  6│ 0.2369│ 0.4669│ 0.8641│ 0.6888│ 3.16
  7│ 0.2201│ 0.2245│ 0.8749│ 0.8727│ 3.16
  8│ 0.2094│ 0.1894│ 0.8821│ 0.8944│ 3.15
  9│ 0.2038│ 0.2969│ 0.8852│ 0.8208│ 3.17
10│ 0.2022│ 0.2547│ 0.8866│ 0.8520│ 3.17
11│ 0.1978│ 0.1894│ 0.8893│ 0.8944│ 3.17
12│ 0.1827│ 0.1987│ 0.8986│ 0.8851│ 3.16
13│ 0.1775│ 0.1939│ 0.9019│ 0.8923│ 3.17
14│ 0.1749│ 0.1821│ 0.9035│ 0.8990│ 3.17
15│ 0.1663│ 0.1646│ 0.9087│ 0.9096│ 3.18 : LB=0.812

train_loss > val_loss and train_Dice < val_Diceとなったので、スコアの改善を期待したのだが、まったくだめ。どうなっているのか。

先日、Dice coefficientを計算できるようにしたときに、この値とLBスコアの対応が良くなかったので、計算が間違っているかもしれないと思って、使わなかったのだが、train_lossやval_lossとの対応が比較的良いので、また、使うようにした。

この結果は、受け入れがたい。どうなっているのだろう。

*JaccardLossよりは、DiceLossの方が、少し可能性を残しているように思う。

 

CyclicLRの1サイクル20エポック(up=3, down=17)で、512 pixel, BCE, 1 hole, area=0.25を試した。LB=0.875(v37)となった。up=3, down=12でLB=0.878だったので、これ以上は期待できないという結果となった。

 

4月19日(月)

HuBMAP:1,470 teams, 22 days to go

512 pixel, BCE, 1 hole, area=0.25を、これまでの何通りかのOneCycleLR, CyclicLRで試す。

v38 : OneCycleLR(AdamW), 20エポック : LB=0.870

v39 : OneCycleLR(SGD), 20エポック : LB=0.862

v40 : CyclicLR(SGD, up=2, down=5, 0.1-2.0) : 3サイクル:LB=0.858

v41 : Cyclic_LR(SGD, up=3, down=7, 0.1-2.0) : 3サイクル:収束が悪いのでcommitせず。

ここまでの検討結果:CyclicLRのサイクル数を増やすことによりスコアアップを図ってきたが、CyclicLRの1サイクルによって同等のスコアを得ることが可能であることがわかり、サイクル数を増やしても、1サイクルを超えるスコアは得られなかった。

気になることは、CyclicLRの1サイクルのスコアを、1サイクル専用の、OneCycleLRでは、まだ、同レベルに達していないことである。

ということで、明日は、OneCycleLRでLB=0.880に到達し、超えることを試みる。

 

4月20日(火)

HuBMAP: 1,469 teams, 21 days to go

512 pixel, BCE, 1 hole, area=0.25 ---> 10 hole, area=0.1

OneCycleLR(AdamW, maxlr=1e-3, epochs=10) : LB=0.872

OneCycleLR(SGD, maxlr=2.0, epochs=10) : LB=0.849

Blur, GaussNoiseの割合を増やして、同じ計算を行った。

OneCycleLR(AdamW), Blur 0.25 -> 0.5, GaussNoise 0.25 -> 0.5 : LB=0.881

OneCycleLR(SGD), Blur 0.25 -> 0.5, GaussNoise 0.25 -> 0.5 : LB=0.862

2週間ぶりに、ようやく自己新記録だ。わずか、0.001の改善であったが、augmentationの条件:BlurやGaussianNoiseなどを少し多くすることによってスコアアップしたことは、良かったと思っている。これを、CyclicLRで0.880が得られている条件に適用することで、もう少しスコアアップできる可能性があると思う。

これで、GPU割当時間はほぼ使い切った。

水、木、金は、これまでのデータを整理して、土曜日からのサイクルで行う実験の計画を立てようと思う。

 

4月21日(水)

HuBMAP:1,474 teams, 20 days to go

このコンペで使えるKaggleのGPUはあと90時間+α。1つの計算に90分かかるとすると、commitがあるので、submitまでに3時間かかる。ということは、あと30回チャレンジできる。

300回のトライで、0.83から0.88まで上がったので、このペースだと、0.885までということになる。

1月7日にRiiid!コンペが終了し、その後(その前にも少し)、HuBMAPにとりかかったので、もう3か月以上取り組んでいる。これも、あと20日で終了する。

qubvel/segmentation_models.pytorch

このsegmentation_modelsパッケージを使うことによって、様々なEncoder/Decoderの組み合わせ、いくつかのloss_functionの組み合わせ、を試すことができた。

https://www.kaggle.com/leighplt/pytorch-fcn-resnet50

このコードとその高速版を使わせていただき、そこに、segmentation_modelsを追加するとともに、いくつかのaugmentationのセット、optimizer, learning rate schedulerなどを追加した。TTAも組み込んだが毎回使うと時間のロスになるので、テスト的に使っただけである。KFoldとアンサンブルは、まだ、使っていない。それらは最後まで使わないかもしれない。

 

これまで、augmentationについて、画像をチェックしながら、その効果を検討したことが無かった。パラメータを変更してみて、スコアがどう動くかを見ていただけである。

あと20日間の間に、augmentationの効果について、具体的に、画像をチェックしながら、スコアとの関係を把握したいと思っている。

 

昨日確率を0.25から0.5に変更したBlurとGaussNoise:

GaussNoiseは、パラメータの設定値が非常に小さく、あまり効いていなかったと推測される。少なくとも、自分の目では変化を確認できなかった。パラメータの設定値を10倍にしても目視で変化を確認できなかった。

4月24日追記:GaussNoiseのパラメータは分散と平均で、デフォルトは、var_limit=(10.0, 50.0), mean=0となっている。

今日まで、画像をチェックしないで、得られた結果だけをみてパラメータを機械的に変更してきた。これでは、何も学んだことにならないと思う。

画像は、モデルに入力する段階で規格化されたり、他の演算が行われて、目視した画像とは全く違ったものになって演算が進むので、元画像に対するaugmentationの効果を目視で確認することが、augmentationの効果を理解するうえでどういう意味を持つかはわからないが、とにかくやってみることにする。

Blurは、blur_limit=3に設定している。この条件では、画像の解像度が1/2~1/3程度になっているようにみえる。これで効果があったのだから、(3, 5)とか(5, 5)くらいまでは、GPUが使えるようになれば計算してみるつもりだ。これ以上数字を大きくすると128とか64ピクセルレベルの画像になる。それでも意味が無いとは言い切れない。一度は試してみてもよいかもしれない。

明日は、Brightness, Contrast, Gamma等がtrain画像に対してどの程度の変化を与えているのかを自分の目で見て確認する予定。

 

4月22日(木)

HuBMAP:1,478 teams, 19 days to go

RandomGamma:gamma_limit=(80, 120):これがデフォルトだが、80と120の定義がわからない。

ウィキペディアには次のような記述がある。

入力値と出力値が直線の関係を示す場合、ガンマ値は1 (γ=1) となるが、γ<1の場合は階調が明るい出力に、γ>1の場合は階調が暗い出力になる。例えば、ガンマ値2.2のディスプレイで適正に表示される画像をガンマ値1.8のディスプレイに表示した場合、実際のガンマ値はγ=1.8/2.2≒0.82となり、意図したものよりも明るい画像となる。画像の入力から最終出力までの全体のガンマが1になるよう、適当なガンマ値のカーブに従って画像の階調を補正することをガンマ補正という。

Qiitaには画像を使ってパラメータと見え方の例が示されているが、その記事には、数値の意味は書かれていなかった。gamma_limit=(50, 50)は元画像より明るく、gamma_limit=(150, 150)は元画像より暗い。

デフォルト値、画像例から推測すると、100がノーマルで、数値を下げれば明るく、数値を上げれば暗くなり、2つの数値によって、最大値と最小値を指定する、ということになるのかな。ウィキペディアを英語に切り替えるとluminanceという単語が出てきて、1または100でnormalizeと書かれているので、これでよさそうだ。

 

RandomBrightnessとRandomContrast:いずれもデフォルトはlimit=(-0.2, 0.2)であり、マイナス側は、暗い、コントラストが低い(結果として暗く感じる)、プラス側はその逆となる。

これをどう使うか。

Cutoutもいくつか試したが、まだまだ、探索の途中である。

gamma, brightness, contrastなどがどう効くのか、1つ1つ試してみるしかない。

なんとなく、ものすごく、原始的な作業をしているような気がしてきた。どこが人工知能か。1つ1つが手作業というのは、何かおかしい。

F. Chollet氏のテキストの犬と猫の分類で、500枚づつのデータを使用するとoverfittingによってaccuracyが0.7くらいで頭打ちになり、augmentationでデータ数を増やすことによって、0.85くらいまで上がるということから、augmentationの効果を体感するというのがあった。

今使っているaugmentationは、画像の枚数は変わらずに、部分的に画像を加工しているだけのような気がする。このことがずっと気になっている。

KaggleのコンペのDiasussionで、誰かが、PyTorchよりもKerasの方がスコアが高いように思う。なぜだろう、と問いかけていたことがあるのを思い出した。もしかすると、このことが原因となっていたということではないだろうか。

F. Chollet氏のテキストでKerasを使っていたので、augmenrationは、画像枚数を増やすものだと思っていた。

しかし、今使っているPyTorchのコードでは、train_dataの数は、augmentationを使っても増えない。指定した確率で、加工されているだけである。たとえば、加工がAだけで、その確率を0.25と指定すると、元の画像に、Aという加工がされた画像の25%が追加されるのではなく、元画像が75%で、Aという加工をした画像が25%で、合わせて100%となり、合計枚数は増えないのである。

これまでは、PyTorchでaugmentationを使っていても、augmentationを含む前処理をしながらモデルにデータを投入していたので、augmentationによって画像が増えていたかどうかはわからないが、今回は、augmentationを含む前処理を済ませてからモデルにデータを投入しており、加工した画像の枚数が表示されるので、augmentationによって画像枚数が増えていないことは、確かだと思う。

KerasかPyTorchかということではなく、プログラム作成者の意図によるのだろうと思う。元データ+transformed_dataがよいのか、元データを所定の確率でtransformしたデータがよいのかを選んだ結果なのであろう。プログラミング技術と計算資源の制限によって、どちらかを選ばないといけない状況になることもある。現状をわかったうえで次の手段を考え、準備しているつもりだが、今は、プログラミング技術がボトルネックになっている。

 

明日は、有効なaugmentation方法の探索をやってみよう。使っていない手法が山ほどある。

 

AutoML: A Survey of the State-of-the-Art
Xin He, Kaiyong Zhao, Xiaowen Chu, arXiv:1908.00709v6 [cs.LG] 16 Apr 2021

Abstract
     Deep learning (DL) techniques have obtained remarkable achievements on various tasks, such as image recognition, object detection, and language modeling. However, building a high-quality DL system for a specific task highly relies on human expertise, hindering its wide application. Meanwhile, automated machine learning (AutoML) is a promising solution for building a DL system without human assistance and is being extensively studied. This paper presents a comprehensive and up-to-date review of the state-of-the-art (SOTA) in AutoML. According to the DL pipeline, we introduce AutoML methods –– covering data preparation, feature engineering, hyperparameter optimization, and neural architecture search (NAS) –– with a particular focus on NAS, as it is currently a hot sub-topic of AutoML. We summarize the representative NAS algorithms’ performance on the CIFAR-10 and ImageNet datasets and further discuss the following subjects of NAS methods: one/two-stage NAS, one-shot NAS, joint hyperparameter and architecture optimization, and resource-aware NAS. Finally, we discuss some open problems related to the existing AutoML methods for future research.

Keywords: deep learning, automated machine learning (AutoML), neural architecture search (NAS), hyperparameter optimization (HPO)

概要
ディープラーニング(DL)技術は、画像認識、オブジェクト検出、言語モデリングなどのさまざまなタスクで目覚ましい成果を上げています。ただし、特定のタスクのために高品質のDLシステムを構築することは、人間の専門知識に大きく依存しており、その幅広いアプリケーションを妨げています。一方、自動機械学習(AutoML)は、人間の支援なしでDLシステムを構築するための有望なソリューションであり、広く研究されています。このホワイトペーパーでは、AutoMLの最先端(SOTA)の包括的で最新のレビューを紹介します。 DLパイプラインによると、現在AutoMLのホットなサブトピックであるため、NASに特に焦点を当てて、データ準備、機能エンジニアリング、ハイパーパラメータ最適化、ニューラルアーキテクチャ検索(NAS)をカバーするAutoMLメソッドを紹介します。 CIFAR-10およびImageNetデータセットでの代表的なNASアルゴリズムのパフォーマンスを要約し、NASメソッドの次の主題についてさらに説明します:1/2ステージNAS、ワンショットNAS、共同ハイパーパラメータとアーキテクチャの最適化、およびリソース認識NAS。最後に、将来の研究のために、既存のAutoMLメソッドに関連するいくつかの未解決の問題について説明します。 by Google翻訳

f:id:AI_ML_DL:20210423004754p:plain

f:id:AI_ML_DL:20210423004905p:plain

f:id:AI_ML_DL:20210423005008p:plain

2.3. Data Augmentation
     To some degree, data augmentation (DA) can also be regarded as a tool for data collection, as it can generate new data based on the existing data. However, DA also serves as a regularizer to avoid over-fitting of model training and has received more and more attention. Therefore, we introduce DA as a separate part of data preparation in detail. Figure 3 classifies DA techniques from the perspective of data type (image, audio, and text), and incorporates automatic DA techniques that have recently received much attention. 
     For image data, the affine transformations include rotation, scaling, random cropping, and reflection; the elastic transformations contain the operations like contrast shift,
brightness shift, blurring, and channel shuffle; the advanced transformations involve random erasing, image blending, cutout [89], and mixup [90], etc. These three types of
common transformations are available in some open source libraries, like torchvision 5, ImageAug [91], and Albumentations [92]. In terms of neural-based transformations, it can be divided into three categories: adversarial noise [93], neural style transfer [94], and GAN technique [95].

 

4月23日(金)

HuBMAP:1,492 teams, 18 days to go

少し前に見ていた文献を、昨夜なんとなくながめていて、少し気になる箇所があった。それは、trainingの初期状態が、trainingの結果に大きな影響を及ぼすということである。ImageNetなどによる学習済みモデルを用いる場合には、小さな学習率から始めることによって、モデルの事前学習が生かされて、良いtraining結果が得られると学んだ。しかし、この論文の趣旨は、SGDでtrainingする場合に、trainingの初期に、小さくない学習率でtrainingすると、良いtraining結果が得られるということのようである。

THE BREAK-EVEN POINT ON OPTIMIZATION TRAJECTORIES OF DEEP NEURAL NETWORKS
Stanisław Jastrz˛ebski, Maciej Szymczak, Stanislav Fort, Devansh Arpit, Jacek Tabor
Kyunghyun Cho, Krzysztof Geras,  Published as a conference paper at ICLR 2020

ABSTRACT
The early phase of training of deep neural networks is critical for their final performance.
In this work, we study how the hyperparameters of stochastic gradient descent (SGD) used in the early phase of training affect the rest of the optimization trajectory. We argue for the existence of the “break-even" point on this trajectory, beyond which the curvature of the loss surface and noise in the gradient are implicitly regularized by SGD. In particular, we demonstrate on multiple classification tasks that using a large learning rate in the initial phase of training reduces the variance of the gradient, and improves the conditioning of the covariance of gradients. These effects are beneficial from the optimization perspective and become visible after the break-even point. Complementing prior work, we also show that using a low learning rate results in bad conditioning of the loss surface even for a neural network with batch normalization layers. In short, our work shows that key properties of the loss surface are strongly influenced by SGD in the early
phase of training. We argue that studying the impact of the identified effects on
generalization is a promising future direction. 

概要
ディープニューラルネットワークのトレーニングの初期段階は、最終的なパフォーマンスにとって重要です。この作業では、トレーニングの初期段階で使用される確率的勾配降下法SGD)のハイパーパラメーターが残りの最適化軌道にどのように影響するかを調べます。この軌道上に「損益分岐点」が存在することを主張します。それを超えると、損失面の曲率と勾配のノイズがSGDによって暗黙的に正則化されます。特に、大規模な学習を使用することを複数の分類タスクで示します。レーニングの初期段階でのレートは、勾配の分散を減らし、勾配の共分散の調整を改善します。これらの効果は、最適化の観点から有益であり、損益分岐点の後に見えるようになります。以前の作業を補完して、次のことも示します。低い学習率を使用すると、バッチ正則化層を備えたニューラルネットワークでも損失面のコンディショニングが悪くなります。要するに、私たちの研究は、損失面の主要な特性がトレーニングの初期段階でSGDの影響を強く受けることを示しています。正則化に対する特定された影響の影響を研究することは、有望な将来の方向性です。by Google翻訳

 

この論文の記述と関係がありそうな実験結果を眺めてみよう。

CyClicLRのパラメータ、base_lrを、0.1, 0.001, 0.00001として計算してみた。

v29 : 2 cycles, 20 epochs:0.1-2.0 : LB=0.839 : (train_loss=0.0258, val_loss=0.0301)

v31 : 2 cycles, 20 epochs:0.001-2.0 : LB=0.853 : (train_loss=0.0256, val_loss=0.0311)

v32 : 2 cycles, 20 epochs:0.00001-2.0 : LB=0.847 : (train_loss=0.0255, val_loss=0.0339)

この結果(LBスコア)からは、base_lrとして、0.1よりも0.001や0.00001の方が良いと判断するところだが、別の観点から0.1が良いと判断した。それは、最終エポックでのtrain_lossとval_lossである。base_lrを小さくすると、train_lossはあまり変わらないのに、val_lossが明らかに大きくなっていることから良くないと判断した。今見ると、これだけの結果で、0.1の一択にしてしまったのは早計だったようであり、上記論文の内容を見ていると、lrの最小値における一桁の違いは大きく、base_lr=0.01も調べておく必要がありそうだと思う。ということで、base_lr=0.1, 0.01, 0.001の比較を、512 pixelの場合について、実施してみよう。

 

4月24日(土)~ 4月30日(金)の予定

・base_lr=0.1, 0.01, 0.001の比較

・GaussNoise, Blur, (gamma, contrast, brightness)の効果確認

・Cutoutは、オリジナルの論文に示されている、ホール数1、面積率0.25にこだわってその効果を調べていたが、ホール数10で、面積率0.1, 0.15, 0.2と変えて、その効果を調べてみる。

 

4月24日(土)

HuBMAP:1,503 teams, 17 days to go

GPU:38 h

今日は、「base_lr=0.1, 0.01, 0.001の比較」をやってみよう。

Baseは、LB=0.880(v2/v25)で、512 pixel, CyclicLR(SGD, 0.1-2.0, up=3 epochs, down=7 epochs), BCELoss, augmentationは、flip, rotateの他に、cutout(hole_num=1, total_area=0.1), Blur(limit=(3,3), p=0.5), GaussNoiseはデフォルトでp=0.5, brightness, contrast, gamma等はデフォルトでp=0.5など。

trfm_4 = A.Compose([
A.Resize(512, 512),
A.OneOf([
A.RandomBrightness(limit=(-0.2,0.2), p=1),
A.RandomContrast(limit=(-0.2,0.2), p=1),
A.RandomGamma(gamma_limit=(80,120),p=1)
], p=0.5),
A.OneOf([
A.Blur(blur_limit=(3,3), p=1),
A.MedianBlur(blur_limit=(3,3), p=1)
], p=0.5),
A.GaussNoise(var_limit=(10.0,50.0), mean=0, p=0.5),
A.RandomRotate90(p=.5),
A.HorizontalFlip(p=.5),
A.VerticalFlip(p=.5),
A.Cutout(num_holes=10, max_h_size=int(.1 * 512), max_w_size=int(.1 * 512), p=.25),])

結果:

  1│ 0.1406│ 0.1000│ 0.5418│ 0.7483│ 3.98
  2│ 0.0462│ 0.0695│ 0.8463│ 0.7611│ 3.96
  3│ 0.0389│ 0.0504│ 0.8689│ 0.8558│ 3.97
  4│ 0.0357│ 0.0364│ 0.8777│ 0.8743│ 3.93
  5│ 0.0336│ 0.0363│ 0.8822│ 0.8813│ 3.96
  6│ 0.0318│ 0.0323│ 0.8903│ 0.8976│ 3.94
  7│ 0.0280│ 0.0321│ 0.9020│ 0.8903│ 3.96
  8│ 0.0267│ 0.0353│ 0.9055│ 0.8749│ 3.94
  9│ 0.0256│ 0.0271│ 0.9086│ 0.9073│ 3.98
10│ 0.0241│ 0.0322│ 0.9152│ 0.8960│ 3.96 : LB=0.883

これは、自己新記録だ。0.002だけ上がった。

overfittingになっていると思うので、もう少しaugmentationの強度を上げても良さそうに思うのだが、・・・。

予定していなかったが、損失関数の組み合わせをやってみよう。時間がかかって、効果が出ないことを覚悟で実験する。

最初に、BCEとDiceとJaccardを等分で組み合わせてみる。

上記のLB=0.883の条件を踏襲するが、画素数512 pixelではGPUモリーが15.8 GBとギリギリなので、448 pixelとする。結果は次の通り、LBスコアは、非常に低い。

  1│ 0.3207│ 0.2839│ 0.6660│ 0.7603│ 3.17
  2│ 0.1688│ 0.4044│ 0.8523│ 0.6247│ 3.15
  3│ 0.1431│ 0.1717│ 0.8758│ 0.8555│ 3.14
  4│ 0.2095│ 0.2449│ 0.8339│ 0.7640│ 3.11
  5│ 0.1360│ 0.3452│ 0.8833│ 0.7496│ 3.12
  6│ 0.1273│ 0.1305│ 0.8908│ 0.8872│ 3.14
  7│ 0.1062│ 0.1581│ 0.9089│ 0.8672│ 3.13
  8│ 0.1032│ 0.1118│ 0.9114│ 0.9015│ 3.13
  9│ 0.0983│ 0.0969│ 0.9158│ 0.9168│ 3.14
10│ 0.0901│ 0.0890│ 0.9225│ 0.9232│ 3.12 : LB=0.840

train_dice_coeff=0.9225とval_dice_coeff=0.9232から、新記録を期待したのだが、非常に残念な結果となった。何がおきているのだろうか。同じことは、DiceLossとJaccardLoss単独のときにも生じていた。いずれも、val_dice_coeffは0.90を超えていたが、LB=0.842とかLB=0.812という値になっていた。

あきらめきれないので、downのエポック数を7から11に増やしてみた。

  1│ 0.3207│ 0.2839│ 0.6660│ 0.7603│ 3.19
  2│ 0.1688│ 0.4044│ 0.8523│ 0.6247│ 3.16
  3│ 0.1431│ 0.1717│ 0.8758│ 0.8555│ 3.15
  4│ 0.1337│ 0.1880│ 0.8842│ 0.8265│ 3.14
  5│ 0.1258│ 0.1937│ 0.8908│ 0.8218│ 3.13
  6│ 0.1209│ 0.1141│ 0.8952│ 0.9038│ 3.16
  7│ 0.1083│ 0.1476│ 0.9061│ 0.8691│ 3.14
  8│ 0.0986│ 0.1044│ 0.9151│ 0.9085│ 3.14
  9│ 0.0992│ 0.1300│ 0.9141│ 0.8923│ 3.16
10│ 0.0963│ 0.0974│ 0.9170│ 0.9158│ 3.15
11│ 0.0925│ 0.0941│ 0.9201│ 0.9201│ 3.14
12│ 0.0881│ 0.1002│ 0.9237│ 0.9146│ 3.16
13│ 0.0825│ 0.0915│ 0.9289│ 0.9214│ 3.15
14│ 0.0799│ 0.0912│ 0.9311│ 0.9222│ 3.14 : LB=0.855

 

明日、BCE:Dice:Jaccard=8:1:1を試してみよう。

 

4月25日(日)

HuBMAP:1,517 teams, 16 days to go

train_dataは15件ある。今使っているのは、当初の8件+2件である。未使用のTrain_dataとpublic_LBのpublic_test_dataに大きな違いがあれば、val_dice_coeffとLBスコアの間に大きな乖離があっても不思議ではない。

このことを確認するために、train_dataの追加2件を変えてみる。

以下に示すのが、2月初旬にデータが更新されたときに追加されたtrain_dataである。pub_testと書いてある5件が、データ更新前の、public_LBスコアの計算に用いられていたpublic_test_dataである。これまで使ってきた追加2件のデータは紫色で示した。この後、茶色で示した2件のデータに変えてみる。

'26dc41664': 1.6e9 245 pub_test
'4ef6695ce': 2.0e9 439
'8242609fa': 1.4e9 586
'afa5e8098': 1.6e9 235 pub_test
'b2dc8411c': 4.6e8 138 pub_test
'b9a3865fc': 1.3e9 469 pub test
'c68fe75ea': 1.3e9 118 pub test
8件のtrain_dataはそのままで、追加の2件をどう選ぶかによって、収束の仕方もLBスコアも全く違ったものになった。

紫色の2件追加:LB=0.883

黒色の3件追加:LB=0.850

カーキ色の2件追加:LB=0.846

驚きだ、8件まで同じで、残り7件のうちのどれを追加するかによってLBスコアがここまで違うとは、どういうことなのか。

private_dataに対するLBスコアも、また、違ってくるのだろう。こういうものなのか、それとも、自分のやり方が間違っているのか。こういうものだ、だから、KFoldもモデルのアンサンブルも、TTAも広範囲にやって平均をとらないとダメなんだよ、ということか。

3件のデータを追加した場合は、次に示すように、完全にoverfittingになっている。LBスコアが低いのはoverfittingだから、augmentationを強くしてみるということがLBスコアの向上につながるだろうと思う。

  1│ 0.1138│ 0.0595│ 0.5990│ 0.7940│ 4.24
  2│ 0.0379│ 0.0420│ 0.8618│ 0.8733│ 4.20
  3│ 0.0327│ 0.0420│ 0.8800│ 0.8787│ 4.20
  4│ 0.0282│ 0.0350│ 0.8954│ 0.8733│ 4.16
  5│ 0.0258│ 0.0381│ 0.9029│ 0.8676│ 4.14
  6│ 0.0242│ 0.0329│ 0.9089│ 0.8896│ 4.15
  7│ 0.0221│ 0.0338│ 0.9152│ 0.8974│ 4.14
  8│ 0.0209│ 0.0368│ 0.9199│ 0.8764│ 4.19
  9│ 0.0200│ 0.0304│ 0.9229│ 0.8987│ 4.16
10│ 0.0192│ 0.0305│ 0.9254│ 0.9039│ 4.19 : LB=0.850

次に示す、カーキ色の2件のデータを追加した場合のtrainingの結果は、良さそうに思うのだが、LBスコアは低い。LBスコアが低い原因の1つには、trainingに使ったデータと、public_dataに違いがある、ということが考えられる。

  1│ 0.1592│ 0.0940│ 0.4803│ 0.6938│ 3.42
  2│ 0.0533│ 0.0547│ 0.8175│ 0.8650│ 3.39
  3│ 0.0442│ 0.0510│ 0.8506│ 0.8180│ 3.41
  4│ 0.0441│ 0.0430│ 0.8490│ 0.8539│ 3.38
  5│ 0.0359│ 0.0555│ 0.8762│ 0.7945│ 3.39
  6│ 0.0320│ 0.0404│ 0.8885│ 0.8592│ 3.37
  7│ 0.0299│ 0.0361│ 0.8945│ 0.8478│ 3.34
  8│ 0.0282│ 0.0347│ 0.9003│ 0.8770│ 3.38
  9│ 0.0262│ 0.0311│ 0.9068│ 0.8877│ 3.37
10│ 0.0258│ 0.0273│ 0.9058│ 0.9042│ 3.35 : LB=0.846

追加データを3つに分けた時に、LBスコアに違いが生じたということは、現状の方法では、予測モデルの一般性:generalityが低いということを示唆しているように思う。

最初の8件のデータに、8件のデータと類似したデータを追加すると、overfittingが生じやすく、8件のデータとは違うデータを追加すると、overfittingは生じにくい、ということになっているようである。

今、3種類の予測モデルができた。1つは、overfittingしてLBスコアが悪いもの。1つは、overfittingせず、LBスコアがよいもの、1つは、overfittingせず、LBスコアが悪いもの。train_dataの選び方によって、異なる予測モデルが生じる。

どうすれば、糸球体を正確に補足することができる予測モデルをつくることができるのか、train_dataを眺めながら、考えてみよう。

 

メモ:今日、AtCoderに登録した。プログラミングをゼロから学びなおすために。C++の入門編(APG4b : AtCoder Programming Guide for beginners)から始めよう。

 

4月26日(月)

HuBMAP:1,533 teams, 15 days to go

CyclicLRのbase_lr=0.1を0.01, 0.001とする。使うのは、LB=0.883となったコード。

lbase_lr=0.1 :     LB=0.883

base_lr=0.01 :   LB=0.875

base_lr=0.001 : LB=0.870

こうなると、base_lrを0.1より大きくしてみたくなる。0.2を試してみよう。

base_lr=0.2 :    LB=0.865

 

面白いが、役に立たない!

 

今後のことを考えて、モデルのアンサンブルをやってみよう。

明日は、B0-UnetとB2-Unetのアンサンブルに挑戦してみようと思う。

 

AtCoder: 初心者用のC++コースを学習中。EX1からEX26まである練習問題のうち、EX10まで進んだ。

 

4月27日(火)

HuBMAP1,540 teams,14 days to go

Effb0-UnetとEffb2-Unetの2つの予測モデルを作ってアンサンブルをするには、どうすればよいのか。

公開コードに学ぼう。

 

4月28日(水)

HuBMAP:1,553 teams, 13 days to go

 公開コードのチューニング

 

4月29日(木)

HuBMAP: 1,566 teams, 12 days to go

今日も公開コードのチューニング。

trainコードとinferenceコードの両方が公開されていて、使いやすく、よくできていて、LBスコアも高く、そのチューニングに、はまっている。

 

4月30日(金)

HuBMAP:1,571 teams, 11 days to go

今日も、チューニング。

4月27日に得たLBスコアのまま、進展なし。

Lookaheadが使われているのだが、パラメータの最適化に時間がかかりそうだ。 

 

5月1日(土)

HuBMAP:1,570 teams, 10 days to go

Lookaheadの論文を見よう。

f:id:AI_ML_DL:20210501101146p:plain

arXiv:1907.08610v2 [cs.LG] 3 Dec 2019

Abstract
The vast majority of successful deep neural networks are trained using variants of
stochastic gradient descent (SGD) algorithms. Recent attempts to improve SGD can be broadly categorized into two approaches: (1) adaptive learning rate schemes, such as AdaGrad and Adam, and (2) accelerated schemes, such as heavy-ball and Nesterov momentum. In this paper, we propose a new optimization algorithm, Lookahead, that is orthogonal to these previous approaches and iteratively updates two sets of weights. Intuitively, the algorithm chooses a search direction by looking ahead at the sequence of “fast weights" generated by another optimizer. We show that Lookahead improves the learning stability and lowers the variance of its inner optimizer with negligible computation and memory cost. We empirically demonstrate Lookahead can significantly improve the performance of SGD and Adam, even with their default hyperparameter settings on ImageNet, CIFAR- 10/100, neural machine translation, and Penn Treebank.

成功したディープニューラルネットワークの大部分は、確率的勾配降下法SGDアルゴリズムの変形を使用してトレーニングされています。 SGDを改善する最近の試みは、大きく2つのアプローチに分類できます。(1)AdaGradやAdamなどの適応学習率スキーム、および(2)ヘビーボールやネステロフ運動量などの加速スキームです。この論文では、これらの以前のアプローチに直交し、2セットの重みを繰り返し更新する新しい最適化アルゴリズムであるLookaheadを提案します。直感的に、アルゴリズムは別のオプティマイザーによって生成された「高速重み」のシーケンスを先読みして検索方向を選択します。ルックアヘッドが学習の安定性を向上させ、計算とメモリコストを無視して内部オプティマイザーの分散を低減することを示します。先読みは、ImageNet、CIFAR- 10/100、ニューラル機械翻訳、およびPenn Treebankのデフォルトのハイパーパラメーター設定を使用しても、SGDとAdamのパフォーマンスを大幅に向上させることができます。<Google翻訳

f:id:AI_ML_DL:20210501111813p:plain

こういう図表を見ると、Lookaheadよりも、SGDとADAMの性能の違いの方が気になる。さらに、SGDに対しては、Lookaheadの効果はわずかである。

 

5月2日(日)

HuBMAP:1,570 teams, 9 days to go

Lookaheadのsync_periodを、文献に示されている範囲(5, 10, 20)で変えてみた(6を12にしてみた)が、目に見える違いは、殆ど認められなかった。初期の20~30エポック以内で振動構造が認められる場合に、その周期が変化したように見えなくもないが、そう見えるのは先入観によるものかもしれない。LBスコアはわずかに下がった。

 

5月3日(月)

HuBMAP

learning_schedulerのパラメータを変更しようとしたが、PyTorchと比べると、設定(変更)できるパラメータが少ないと感じた。最近のKerasについての学習不足によるものかもしれない。

 

5月4日(火)

HuBMAP

TPUの30時間を使い果たしたので、GPUに切り替えてtraining条件を検討しようとしているが、計算速度が圧倒的に遅い(1/20-1/30)ことと、Batch_sizeの極端な違いなどのために、TPUでの計算結果をフォローするのが難しい。

Lookaheadのsync_periodの効果を調べたいのだが、GPUでは無理かな。

GPUで試していて思ったのだが、TPUでは、計算速度が速いので100エポックでも200エポックでも試すことができるので、エポック数を増やしすぎていたかもしれない。

GPUだと、12エポックでも5Foldだと6時間くらいかかる。それが、TPUだと、100エポックの5 Foldが2時間半くらいで計算できる 。

学習率の初期値、バッチサイズ、などを変えてみたが、val_dice_coefficientが0.80を超えないので、GPUでのトライは断念する。

あとは、TPUの最後の30時間をどう使うか、よりよいトレーニング条件を探すために、これまでに試みた10件弱のトレーニング結果を振り返って、検討してみよう。

 

5月5日(水)

HuBMAP:1,554 teams, 6 days to go

進展なし。

 

5月6日(木)

HuBMAP:1,564 teams, 5 days to go

 

進展なし。

土曜日の朝にTPUが使えるようになるのを待つのみ。

 

5月7日(金)

HuBMAP1,570 teams, 4 days to go

5件のpublic_test_dataのうちの1件は、糸球体の内部構造がつぶれているように見えるものが多いようで、そのために、正しく囲うのが難しく、結果としてLBスコアが上がらないということになる。このtest_dataに対して、ハンドラベリングして、train_dataに追加すれば、LBスコアは上がる。ハンドラベルのデータは公開されていて、今回のコンペではこのような手段は規則違反でないことも公式に確認されている。

train_dataとの類似性の低いデータに対して、どれだけ予測性能を上げることができるかということで争っているチームのスコアが、0.93+のレベルで、5件のうちの1件に対してハンドラベルを用いると0.934くらいになることは、ハンドラベルデータを公開した方が報告していたように思う。これ以外にも、予測困難な例(試料が薄いために、明るくてコントラストが小さかったように思う)がDiscussionで紹介されていたように思う。

5件のpublic_test_dataに対するハンドラベルや擬ラベルを用いることによって、train_dataが増えるので、public_test_dataに対する予測精度が向上するだけでなく、private_test_dataに対する予測精度も良好であることが期待される。おそらく、0.935+のチームの方々は、そうしているのであろうと思う。

自分(公開コードを借用してチューニング中)もそうだが、5件のpublic_test_dataをtrain_dataに加えることができないチームは、高いpublic_LBスコアも、高いprivate_LBスコアも、難しいのではないかと思う。

とはいえ、せっかく公開していただいた優れたコードなので、なんとか、top 10%以内に留まれるようにしたいのだが、どうしたものか。

 

<雑談>今使っているコードはKerasで書かれていて、callbacksが使えるレベルまでには理解できていないことに気付き、F. Chollet氏のDeep Learningのテキストを読み返すことにした。画像処理分野は、Chapter 5のDeep Learning for computer visionまで勉強していたが、Chapter 7のAdvanced deep-learning best practicesは、殆ど読んでいなかった。7.2に面白い記述がある。大きなデータセットに対してmodel.fit( )またはmodel.fit_generator( )を用いて何十エポックものトレーニングの計算をすることは、紙飛行機を飛ばすようなもので、一旦手を離れると飛行経路も着陸位置も制御できない。これに対して、紙飛行機ではなくドローンを飛ばせば、環境情報を把握することができ、その情報をオペレータに伝えることによって状況に即した飛行をさせることができる。それがcallbacksの機能ということである。keras.callbacksとして、ModelCheckpoint, EarlyStopping, LearningRateScheduler, ReduceLROnPlateau, CSVLoggerなどの説明が続く。

 

TPU:バッチ数を多くすることによる高速化のイメージがある。Flower Classification with TPUsというコンペで、チュートリアルモデルでは、128バッチで計算していて、Adamを用い、学習率は0.00001からスタートし、5エポックくらいで0.0004まで上げ、12エポックで0.00011くらいまで下げるというような感じであった。なんだかCyclicLRに似ている。

これがそのまま適用できるとは思わないが、次の一手が見つからなかったので、明日は、このバッチ数と学習率でどうなるか、試してみようと思う。

 

5月8日(土)

HuBMAP:1,162 teams, 3 days to go:昨日より、400チームくらい少なくなっている。何がおきたのだろうか。データセットを更新する前の状態のまま放置しているチームがいなくなったようだ。自分のsubmit回数も、そのぶん、減っている。ということで、母数が減ったのでメダル圏内に該当するチーム数が40ほど減った。それゆえ、一気にメダル圏外に押し出され、やる気が失せた。残念だな。

とはいうものの、最後までチャレンジしないと、もったいない。

バッチ数を小さくして、少し、検討してみた。ここまでは1024だったのを、512、256、128、および64について検討した。バッチ数が小さくなるほど、収束は早くなるが、train_lossとval_lossの反転が速くなり、この中では1024がベストであった。

それならばと、1024以上(2048、1536、1280など)に設定しようとしたが、エラーとなって停止した。1024が設定可能な最大値のようである。

 

5月9日(日)

HuBMAP1,172 teams, 2 days to go

明日で終わり(明後日の午前9時)だが、もうスコアアップの手立てはなくなった。

ダメもとで計算(主に、TPUを使ったtraining)しているが、テキトーにパラメータを変えても何も(val_diceやLBスコア)改善されなかった。

今から条件を検討するだけの計算資源も時間もないので、今回のコンペは、これでおしまい。

*前処理とsubmitのコードを借用し、trainingu部分をSemantic Segmentationのコードを使って種々検討したが、単独モデルでは、LB=0.883(val_dice_coefficientは0.91程度)までであった。

*最後の2週間は、LB=0.927の公開コードを借用し、最初はLB=0.920だったが、training条件を検討して、0.932になった。といっても、特段の工夫をしたわけではなく、最終的には、公開コードのオリジナルの条件を追い越すことはできなかった。

*今回のコンペは、最初の論文調査の段階で、複雑なモデルを使う必要はなさそうだという感触を得たが、途中段階では、様々なモデルの組み合わせを試し、比較的新しい論文に出てくるモデルをGitHubから借用してみたりもした。スコアへの影響が大きかったのは、augmentation(albumentation)と、KFoldであった。TTAの効果はよくわからなかった。モデルのアンサンブルは、何度かやりかけたが、結局、借用も含め、試すことができなかった。擬ラベルも試すことができなかった。

*実質、3か月以上をこのコンペに費やした。

 

5月10日(月)

HuBMAP:1,172 teams, a day to go

あと2回、seed_numberを変えて丁寧にrainingした結果を用いてinferenceした結果を提出して終わり。

2回trainingし、それを用いてinferenceした結果、いずれも、LB=0.930となった。seedを変えたので、val_dicecoefficientは様々な値となり、OOF lossやOOF dice_coefficientも2つの場合で大きく異なっていたにもかかわらず、LBスコアが同一だったことに驚いた。重要なメッセージが隠れているように思うのだが、わからない。

これまでの結果では、0.932と0.931もあるので、最終的に提出するコードをどれにすれば良いのか、さっぱりわからない 。

 

以上で、今回のコンペは終了である。

明日からは、Bristol-Myers Squibb – Molecular Translationに参加するつもりである。

 

5月11日(火)

HuBMAP:

コンペの暫定結果が出た。public_LBの順位からは、130番下がった。

今回は、大波乱がおきた。

このコンペの目標がメダル狙いだけだったら、ほんとうに、がっかりするところだが、いろいろチャレンジできておもしろかった、ということにしておこう。

最終的に選択した2件のコードは、結果としては、適切ではなかったが、最後に選ぼうかなと迷ったコードでも、200~211位相当であった。

メダル圏に最も近かったのは、126~149位相当のコードであるが、自分の基準では、選ぶ理由はなかった(最終的に選んだコードと比べても、Public_LBスコアが0.015くらい小さかったから)。

最後に、今回のHuBMAPコンペは、最後に大波乱がおきて、とてもひどいことになったが、いろいろ学べて面白かった、ということにしておこう。

 

<雑談>HuBMAPのコンペが終わって、結果を見て、参加者のコメントを見ていると、みんなの努力はなんだったんだろうな、と思ってしまう。public_test_dataとprivate_test_dataとでスコアが大きく違うって、何なんだろうと思う。こんなtest_dataを使ってコンペをするのはどうなんだろう。どちらのtest_dataに対してもハイスコアになるモデルを表彰するならまだしも、偏ったスコアが出てしまうようなtest_dataを使って、片方のteat_data(private_teat_data)のスコアだけで評価するというのはものすごく不公平で、間違ったやり方ではないだろうか。このような偏りが生じた原因は、憶測だが、当初準備したデータセットに不備が見つかったため、急遽、データセットを作り直したためではないだろうか。このような現象が生じることを想定していたのだろうか。結果として、自分への影響は殆どなかったが、Kagglerの事後コメントを読んでいると、特にトップレベルのチームの方々にとっては、ほんとうに残念なコンペだったのではないかと思う。 

 

f:id:AI_ML_DL:20210301083105p:plain

style=164 iterations=500

f:id:AI_ML_DL:20210301083248p:plain

style=164 iterations=50

f:id:AI_ML_DL:20210301083347p:plain

style=164 iterations=5

 

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