俺人〜OREGIN〜俺、バカだから人工知能に代わりに頑張ってもらうまでのお話

俺って、おバカさんなので、とっても優秀な人工知能を作って代わりに頑張ってもらうことにしました。世界の端っこでおバカな俺が夢の達成に向けてチマチマ頑張る、そんな小さなお話です。現在はG検定、E資格に合格し、KaggleやProbSpaceのコンペに参画しながら、Pythonや機械学習、統計学、Dockerなどの勉強中です。学習したことをブログにアウトプットすることで、自分の身に着けていきたいと思います。まだまだ道半ばですが、お時間がありましたら見て行ってください。

【第2弾】 rinna社が公開した、日本語に特化した「GPT-2」「BERT」事前学習モデルをつかって昔話創作モデルを実装してみた!

今回も、rinna株式会社が8月25日に公開してくださった、日本語に特化した「GPT-2」と「BERT」の事前学習モデルを使ってモデルを実装してみました。

今回は、昔話の冒頭の文章を与えると、話の続きを創作してくれるモデルです。

corp.rinna.co.jp

 では、振り返っていきたいと思います。

日本語に特化した「GPT-2」「BERT」事前学習モデルをつかって昔話創作モデルを実装してみた!

1.今回実装した昔話創作モデル

今回実装した昔話創作モデルは、冒頭の文章を与えると、続きの文章を複数生成し、提案してくれるというモデルです。

本来であれば、膨大な量の文章を集めて、長時間学習させないと行けないところ、公開された事前学習モデルを使うことで、GPUも使うことなく簡単に実装することができました。

昔話創作モデルの仕様

  1. 昔話の冒頭の文章として「昔々あるところに、」という文章を入力する。
  2. 入力された文章をもとに、続きの物語を複数生成する。
  3. おもしろ文章を見つけて、日々の生活に役立てる。

2.全体像

コード全体は以下の通りで、Google colaboratory上で実行しました。

GitHubにも公開しています。

https://github.com/Oregin-ML/Fairy-tale-creation-model

!git clone https://github.com/rinnakk/japanese-pretrained-models

%cd /content/japanese-pretrained-models

!pip install -r requirements.txt

# ライブラリをインポートします。
from transformers import T5Tokenizer, AutoModelForCausalLM
# 学習済みモデルをダウンロードします。
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt2-medium")
tokenizer.do_lower_case = True
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt2-medium")

# 生成する文章の冒頭部分を設定します。
beginning = '昔々あるところに、'
# 文章を機械学習の入力とできるようコード化します。
input = tokenizer.encode(beginning, return_tensors="pt")

# 文章の生成処理を実施します。(出力はコードで出力されます。)
output = model.generate(input,do_sample=True, max_length=100, num_return_sequences=5)
# 出力されたコードを文章に戻します。
DecodedOutput = tokenizer.batch_decode(output)

# 生成された文章を表示します。
print('#'*40)
print(f'冒頭が「{beginning}」となる文章を出力します。')
print('#'*40)
for j in range(5):
 
print('#'*40)
 
print(f'### 文章案{j} ####')
 
print('#'*40)
 
i = 0
 
while i < len(DecodedOutput[j]):
  
print(DecodedOutput[j].replace('</s>','')[i:i+30])
  
i = i+30

では、コードを順番に見ていきます。

3.学習済みモデルをインストールする

GitHubより、学習済みモデルをダウンロードして、ダウンロードされたフォルダ内にある、「requirements.txt」を使えば、必要なライブラリが一発でインストールできます。 

!git clone https://github.com/rinnakk/japanese-pretrained-models 

%cd /content/japanese-pretrained-models

!pip install -r requirements.txt

4.学習済みモデルを定義する

学習済みモデル("rinna/japanese-gpt2-medium")を、読み込みます。

この数行を記載するだけで、莫大なデータやリソース、時間を必要とする学習を省略することができます。

# ライブラリをインポートします。
from transformers import T5Tokenizer, AutoModelForCausalLM
# 学習済みモデルをダウンロードします。
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt2-medium")
tokenizer.do_lower_case = True
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt2-medium")

5.生成の基となる昔話の冒頭部分を設定する。

昔話の冒頭部分として、'昔々あるところに、'を設定します。この部分を変更すれば、昔話に限らず、いろいろな文章が作れます。

なお、文章を機械学習の入力として使えるようにコード化する必要があります。

# 生成する文章の冒頭部分を設定します。
beginning = '昔々あるところに、'
# 文章を機械学習の入力とできるようコード化します。
input = tokenizer.encode(beginning, return_tensors="pt")

6.続きの物語を生成して出力する。

モデルのgenerate()を使って、続きの物語を生成します。

入力にはコードに変換済みの冒頭の文章(input)を指定します。

各オプションは以下のとおりです。

do_sampleをTrueとすることで、実行毎に出力を変化させることができます。

max_lengthは、生成する文章の最大の長さになります。

num_return_sequencesは、生成する文章の数になります。

出力は、コードで出力されるため、.batch_decode()を使って、文章にもどします。

表示にあたっては、改行をいれて出力させています。

# 文章の生成処理を実施します。(出力はコードで出力されます。)
output = model.generate(input,do_sample=True, max_length=100, num_return_sequences=5)
# 出力されたコードを文章に戻します。
DecodedOutput = tokenizer.batch_decode(output)

# 生成された文章を表示します。
print('#'*40)
print(f'冒頭が「{beginning}」となる文章を出力します。')
print('#'*40)
for j in range(5):
 
print('#'*40)
 
print(f'### 文章案{j} ####')
 
print('#'*40)
 
i = 0
 
while i < len(DecodedOutput[j]):
  
print(DecodedOutput[j].replace('</s>','')[i:i+30])
  
i = i+30

7.実行結果

このコードを実行した出力の例は以下のとおりです。

少し違和感のある文章もありますが、なかなか良い文章もできています。

中には、続きが気になってしまう文章案もあります。

手直しすれば、オリジナルの昔話も作れそうですね。

f:id:kanriyou_h004:20210827172901p:plain

8.感想

今回は、日本語に特化した事前学習モデルを使って、昔話創作モデルを作ってみました。

大したものは作れないと思っていたのですが、なかなか良い文章が出てくるので、創作文章を作るときの最初のアイデア出しに使えそうな気がしました。

もっと色々使ってみて、活用方法を考えていきたいと思います。

 

【第1弾】簡易大喜利モデル

oregin-ai.hatenablog.com

【これまでの道のり】

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

f:id:kanriyou_h004:20210826185619p:plain



 

rinna社が公開した、日本語に特化した「GPT-2」「BERT」事前学習モデルをつかって簡易大喜利を実装してみた!

元女子高生AI「りんな」などで知られるrinna株式会社が8月25日に公開してくださった、日本語に特化した「GPT-2」と「BERT」の事前学習モデルを使って、簡易大喜利(?)モデルを実装してみました。

日本語CC-100と日本語Wikipediaの計75ギガバイトのデータを、8つのNVIDIA Tesla V100 GPUで、45日間も掛けて学習しないと行けない事前学習モデルが、無料で簡単に使えるのは感動でした!

corp.rinna.co.jp

 では、振り返っていきたいと思います。

日本語に特化した「GPT-2」「BERT」事前学習モデルをつかって簡易大喜利を実装してみた!

1.今回実装した簡易大喜利モデル

今回実装した簡易大喜利モデルは、指定した文字列のうち、隠した部分の文字列を予測する機能を使って、面白い回答を期待するというモデルです。

本来であれば、いろいろと実装して、データを集めて、長時間学習させないと行けないところ、公開された事前学習モデルを使うことで、あっという間に実装することができました。

簡易大喜利モデルの仕様

  1. 穴埋めさせたい文章を入力する。
    例:「世界一うるさい人と言ったら、。」
  2. 簡易大喜利モデルが「」の部分を予測して、確率が高い順に出力する。
    例:「あなた
  3. おもしろ回答を見つけて、こっそり楽しむ。

2.全体像

コード全体は以下の通りで、Google colaboratory上で実行しました。

GitHubにも公開しています。

https://github.com/Oregin-ML/Simple_Ogiri_model

 

!git clone https://github.com/rinnakk/japanese-pretrained-models

%cd /content/japanese-pretrained-models

!pip install -r requirements.txt
import torch from transformers import T5Tokenizer, RobertaForMaskedLM # load tokenizer tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-roberta-base") tokenizer.do_lower_case = True # due to some bug of tokenizer config loading # load model model = RobertaForMaskedLM.from_pretrained("rinna/japanese-roberta-base") model = model.eval() print('#'*40) print('答えさせたい内容を「〜、何。」と聞いてみてください。') print('例;世界一うるさい人と言ったら、何。') print('※最後の「。」を忘れずに。') print('#'*40) # original text text = input() # prepend [CLS] text = "[CLS]" + text if '何' in text: # tokenize tokens = tokenizer.tokenize(text) # mask a token masked_idx = -2 tokens[masked_idx] = tokenizer.mask_token print('#'*40) print('#以下の[MASK]の部分を考えます。') print(tokens) print('#'*40) # convert to ids token_ids = tokenizer.convert_tokens_to_ids(tokens) # convert to tensor token_tensor = torch.tensor([token_ids]) # get the top 10 predictions of the masked token with torch.no_grad(): outputs = model(token_tensor) predictions = outputs[0][0, masked_idx].topk(10) print('#'*40) print('#思いついた答えは・・・') for i, index_t in enumerate(predictions.indices): index = index_t.item() token = tokenizer.convert_ids_to_tokens([index])[0] print(i, token) print('#以上です。') print('#'*40) else: print('何か聞いてくれないとわからないです。')

では、コードを順番に見ていきます。

3.学習済みモデルをインストールする

GitHubより、学習済みモデルをダウンロードして、ダウンロードされたフォルダ内にある、「requirements.txt」を使えば、必要なライブラリが一発でインストールできます。

 

!git clone https://github.com/rinnakk/japanese-pretrained-models 

%cd /content/japanese-pretrained-models

!pip install -r requirements.txt

4.学習済みモデルを定義する

学習済みモデル("rinna/japanese-roberta-base")を、読み込みます。

この数行を記載するだけで、莫大なデータやリソース、時間を必要とする学習を省略することができます。

import torch
from transformers import T5Tokenizer, RobertaForMaskedLM

# load tokenizer
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-roberta-base")
tokenizer.do_lower_case = True  # due to some bug of tokenizer config loading

# load model
model = RobertaForMaskedLM.from_pretrained("rinna/japanese-roberta-base")
model = model.eval()

5.大喜利させたい文章を入力する

大喜利させたい文章を標準入力で受け付けます。

ポイントは、文章の頭に[CLS]を追加するところです。

print('#'*40)
print('答えさせたい内容を「〜、何。」と聞いてみてください。')
print('例;世界一うるさい人と言ったら、何。')
print('※最後の「。」を忘れずに。')
print('#'*40)

# original text
text = input()

# prepend [CLS]
text = "[CLS]" + text

6.「何」の部分を予測して、出力する。

「何」の文字列が含まれていれば、「masked_idx」で指定した箇所の単語を予測して、確率が高い単語を10個出力します。今回は、文末が「何。」となっていることを前提に、後ろから2つ目の単語を予測することにしています。

赤字下線の部分で、穴埋めの予測処理を実施しています。

if '何' in text:
  # tokenize
  tokens = tokenizer.tokenize(text)
  # mask a token
  masked_idx = -2
  tokens[masked_idx] = tokenizer.mask_token
  print('#'*40)
  print('#以下の[MASK]の部分を考えます。')
  print(tokens)  
  print('#'*40)
  # convert to ids
  token_ids = tokenizer.convert_tokens_to_ids(tokens)

  # convert to tensor
  token_tensor = torch.tensor([token_ids])

  # get the top 10 predictions of the masked token
  with torch.no_grad():
      outputs = model(token_tensor)
      predictions = outputs[0][0, masked_idx].topk(10)

  print('#'*40)
  print('#思いついた答えは・・・')
  for i, index_t in enumerate(predictions.indices):
      index = index_t.item()
      token = tokenizer.convert_ids_to_tokens([index])[0]
      print(i, token)
  print('#以上です。')
  print('#'*40)

else:
  print('何か聞いてくれないとわからないです。')  

7.実行結果

このコードを実行して、「世界一の天才といったら、何。」と入力した場合の実行結果は以下の通りです。

なかなかいい味を出している回答を返してくれています。

f:id:kanriyou_h004:20210826203630p:plain

 

8.感想

今回は、日本語に特化した事前学習モデルを使って、簡易大喜利モデルを作ってみました。このモデル自体が何かの役に立つかというと、そうでもないのですが、こんなに簡単に穴埋め予測モデルが作れてしまうので、この事前学習モデルの有用性を身を持って知ることができました。

今後は、このモデルをどの様に活用できるかの視点でも考えていきたいと思います。

 

 

【これまでの道のり】

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

f:id:kanriyou_h004:20210826185619p:plain



 

2021年上半期+αの振り返り(機械学習の積み上げ~さらなる高みを目指して~)

2021年上半期は、昨年に引き続き、機械学習の積み上げの成果を試すため、いろいろなデータ分析サイトのコンペティションに挑戦しました。

中でも、念願のKaggleでの初メダル獲得や、ProbSpaceでの初優勝など、自分内「初」の記録を残せた半期でした。

いろいろな制約があり、なかなか思うようにならないことが多いご時世ですが、自身のできることを、できる範囲でコツコツと進めてきた成果だと思っています。

引き続き、「ゆっくりでも止まらなければ結構進む」の精神で頑張って行きたいと思います。

 

【目次】

【コンペ関連】

 1.Kaggleで初メダル獲得!(Cassava Leaf Disease Classification)

2021年上半期で印象に残った出来事の1つ目は、念願のKaggleにて初メダルを獲得できたことになります。

2月に終了した鳥蛙コンペ(Rainforest Connection Species Audio Detection)では、善戦したものの、Top16%でメダル獲得ならずだったのですが、直後に結果がでたタロイモコンペ(Cassava Leaf Disease Classification)にて、Top6%に入ることができ、初の銅メダル獲得となりました!

残念だったのは、強化学習に本格的に取り組んだじゃんけんコンペ(Rock, Paper, Scissors)では、Top11%と、あと7つ上位に届かず、メダル&Expert昇格を逃してしまったことでした。

とはいえ、メダル獲得が夢ではなく手に届くところまできたのは、大きな進歩でした。

なんとか今年中に、もう一つメダルを獲得して、Expertを目指します!

f:id:kanriyou_h004:20210812142757p:plain

2.ProbSpaceで初優勝!総合ランキング1位をキープ

2021年上半期で印象に残ったもう一つの出来事は、データ分析プラットフォームProbspaceで開催された、プロ野球データ分析チャレンジで、初優勝できたことでした。これまで、コンペで2位や3位になったことはあったのですが、優勝は初めてだったので、感無量でした。

また、3月に終了した、論文の被引用数予測コンペでは、41位と散々な成績だっただけに、喜びもひとしおでした。

この優勝で、ProbSpace内ランキングにおいて、トピック、コンペティション、総合の3部門全部で1位を達成することができました。(総合ランキング

各コンペでの記録は以下の通りです。

f:id:kanriyou_h004:20210812143337p:plain

f:id:kanriyou_h004:20210812145252p:plain

3.Solafune、Nishikaで宇宙・航空系コンペに挑戦

宇宙・航空系に興味をもっている私は、宇宙・航空系のコンペにも参加しました。

具体的には、衛星データ分析サイトのSolafuneで開催された「夜間光データから土地価格を予測」、データサイエンスコンペティションサイトのNishikaで開催された「航空機ターボエンジンの残存耐用時間予測」の2つに挑戦し、以下の結果を残すことができました。

また、昨年から宇宙関連のコンペに参加していたこともあり、宇宙関連の情報サイト宙畑さんの取材を受け、以下の記事にしていただけました。

Kaggle では、まだまだヒヨッコなので、ランカーというのはお恥ずかしい限りなのですが、良い経験をさせていただきました。

sorabatake.jp 

 【積み上げ関連】

1.AIQuest2020受講(〜2021年2月)

経済産業省が実施しているAI Quest 2020|SIGNATEに昨年から参加し、無事終了することができました。

f:id:kanriyou_h004:20210812154756p:plain

守秘義務があり、詳細は記載できませんが、要件定義あり、コンペ形式でのAI開発あり、経営層向けのプレゼンありで、実業務に即した、かなり濃厚な講座でした。

結果としては、以下の通り、第1タームAI課題優秀賞&総合賞、第2タームプレゼン課題優秀賞&総合賞の表彰を受けることができました。

f:id:kanriyou_h004:20210812162853p:plain


signate.jp

2.実践データサイエンスシリーズ(講談社サイエンティフィク)当選!

講談社サイエンティフィク (@kspub_kodansha) さんのキャンペーンに応募して、以下の3冊をちょうだいいたしました。

Kaggleでの戦い方から、ベイズ統計モデル、データの可視化まで、実践を交えながら一通り学習できて、とても有意義な時間を過ごすことができました。

講談社サイエンティフィクの皆様ありがとうございました!

f:id:kanriyou_h004:20210812171823p:plain

おわりに

2021年に入ってからも、引き続き、なかなか思うように活動できない日々が続いていますが、できる範囲の中で、チャレンジ精神を忘れずに、活発に行動していきたいと思います。

また、コンペに限らず、実社会でも貢献できるように引き続き精進してまいります。

さまざまなチャネルで、交流させていただいたり、繋がらせていただいたりしている皆様、本当にお世話になっております。

ささやかながら、皆様の活動の一助 となれるよう頑張ってまいりますので、今後ともよろしくお願いいたします。

 

【これまでの道のり】

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

f:id:kanriyou_h004:20201209122737p:plain 

 

 

【1位解法】ProbSpace開催「プロ野球データ分析チャレンジ 」の振り返り。

データ分析好きが集まる交流プラットフォーム「ProbSpace」で開催された「次の一投の行方を予測! プロ野球データ分析チャレンジ」に参加し、1位の成績を残せました!

現在、オープンレビュー中のため、賞金獲得は未確定ですが、解法について公開させていただきます。確定できれば、昨年のNishika開催の「Jリーグプレイヤーの出場予測」(参考;【2位解法】Nishika開催「Jリーグプレイヤーの出場時間予測」の振り返り)に続き、スポーツ関連で2個目の賞金獲得になります。

また、今回1位が確定できれば、ProbSpace内で、トピック、コンペティション、総合の3分野で1位になることができます!

【後日談】無事オープンプレビューが完了し、優勝が確定しました!

2021年上半期+αの振り返り(機械学習の積み上げ~さらなる高みを目指して~)

 

今回のコンペは、様々な手法の前処理を適用するとともに、回帰、2値分類、多値分類の複数の種類のモデルを駆使し、持てる力を十二分に発揮することができました。

f:id:kanriyou_h004:20210623222431p:plain

では、振り返って参りたいと思います。

1.全体構成

今回のコンペは、日本のプロ野球で、投げられた1球が、ストライクになったか、ヒットになったかなどの投球結果を予測するテーブルコンペでした。

データの特徴として、球速や、投げられたコースなどは、trainデータにしかなく、testデータから予測する際には、一度、testデータに不足している特徴量を予測するモデルで予測してからひと工夫が必要でした。

【trainデータにしかない特徴量】

f:id:kanriyou_h004:20210608172353p:plain

また、当然といえば当然なのですが、ストライクやボールに比べ、ヒット、2塁打、3塁打、ホームランの数が非常に少なく、分類されるデータ量が偏ったデータとなっていました。testデータも同様の分布になると過程し、数が少ない分類については、個別に予測モデルを作成することにしました。

【trainデータの「投球結果」の度数分布】

f:id:kanriyou_h004:20210608172132p:plain

上記のような状況を踏まえ、最終的には以下のような構成のモデルを作成しました。

f:id:kanriyou_h004:20210608164651p:plain

前処理済みのデータは2種類用意して、以下の2種類のモデルで予測し、多値分類を行った予測値に、頻度が少ない値を2値分類として予測し予測値を上書きすることで、最終的に提出する予測値を作成しました。

  • trainにしかないSpeedの予測値をtestデータの特徴量に追加して多値分類を行うモデル
  • その1球が「ヒットになるかならないか」、「2塁打になるかならないか」、「3塁打になるかならないか」、「本塁打になるかならないか」の2値分類を行うモデル

2.前処理

前処理については、以下の2通りで実施いたしました。

【前処理A】

こちらは、ProbSpaceのトピックで公開させていただいたベースラインの前処理となります。[トピックはこちら→改良版-LightGBM Base line−コメント付き (CV= 0.14834 / LB= 0.13733)]

前処理

処理内容
年月日、曜日、時分秒を追加

'startDayTime'から、試合の開始年月日、曜日、時分秒を作成してそれぞれを特徴量として追加。

回数と裏表を追加

'inning'から、回数と裏表を作成して、それぞれを特徴量として追加。

ボール、ストライク、アウトの合計値を追加

ボール、ストライク、アウトのカウントの合計値、およびボール、ストライクの合計値を特徴量として追加

ベース上のランナーの数を追加

1塁、2塁、3塁のベース上のランナー数の合計値を特徴量として追加

バッターのチームを追加

表の場合は'topTeam'を、裏の場合は'bottomTeam'を、バッターのチームとして追加

ピッチャーのチームを追加

表の場合は'bottomTeam'を、裏の場合は'topTeam'を、ピッチャーのチームとして追加

 【カテゴリカル変数の処理】

前処理

処理内容

カテゴリカル変数をカウントエンコード

 xfeat の CountEncoder を使用して、各カテゴリ変数をカウントエンコードした特徴量を追加

カテゴリカル変数をターゲットエンコード xfeat の TargetEncoder を使用して、各カテゴリ変数をターゲットエンコードした特徴量を追加

 【その他】

前処理

処理内容

pivot tabel を用いた特徴量を追加

Pandas の pivot_table を使用して、"gameID"をインデックスとした各種ピボットデータを特徴量として追加

【前処理B】

こちらは、ProbSpaceのトピックでDT-SNさんが公開してくださいましたベースラインの前処理となります。

詳細は、DT-SNさんが公開してくださったトピックをご参照ください。

[トピックはこちら→LightGBM Base line(CV=0.2228,LB=0.16746)]

3.モデル構築

 今回は、大きく分けて、目的となる分類の全クラスを分類するモデルと、頻度の少ないヒット、2塁打、3塁打、ホームランのそれぞれを予測するモデルを作成いたしました。

f:id:kanriyou_h004:20210608164651p:plain

【全体の多値分類】

前者は、2段階のモデルを組み合わせています。

1段階目は、前処理Aのデータを用いて、訓練データのみにあるspeedの特徴量をMLPRegressor(回帰)で予測するモデルを作成し、TestデータにもSpeedの特徴量を追加しました。

2段階目は、前処理AのデータにSpeedの特徴量を追加した特徴量からLightGBMで多値分類を行うモデルを作成しました。 

【頻度の少ないクラスの2値分類】

後者は、ヒットになるかならないかの2値分類を行うモデル、2塁打になるかならないかの2値分類を行うモデル、3塁打になるかならないかの2値分類を行うモデル、ホームランになるかならないかの2値分類を行うモデルを、それぞれ作成しました。

2値分類については、過去にProbSpace実施された、「スパムメール判別コンペ」の1位解法で利用されていた「ダウンサンプリング」や「MultinomialNB」などを採用させていただいたり、「対戦ゲームデータ分析甲子園」で武器ごとの予測を試したことを応用して、チームごとの予測を採用したりしました。

最終的には、後者のそれぞれのモデルで「なる」に分類されたデータを前者のモデルでの予測値に上書きすることで、最終的な予測値としました。

(通算500個以上のモデルを作って、いろいろな組み合わせを試し、そのうち約170回の提出を実施しました。後半はほぼ毎日提出しました。)


4.感想

今回のコンペは、プロ野球選手の実名のデータが登場するコンペだったので、実際の状況を想像しながら楽しんで取り組むことができました。

野球は、スポーツの中でも戦略やゲーム性が高いスポーツなので、こういった分析が実際の試合でも使われていると考えると、これからますます機械学習が応用されるのではないかと感じました。

今回も、とにかくいろんなモデルを作成しては、出力を提出して、LBスコアを確認しながら、とりくみました。

コンペの前半で、多値分類のモデルだけでなく、出現頻度の低いクラスについては、2値分類のモデルを採用することを思いついたことが、スコアの向上に大きく貢献しました。

2値分類については、過去いろいろなのコンペで取り組んでいたので、これまでの資産が十分に効果を発揮しました。改めて、コンペ毎に完結するのではなく、コンペで培った資産は、次に活かしていくことも大切と感じました。

また、今回は、Open Review Competitionということで、公開することも考慮しながらコードを作成いたしました。途中で、トピックにベースラインを公開して、皆さんのご指摘もいただきながら修正して、なんとか提出ができました。

あとは、レビュー結果が楽しみです。

5.謝辞

最後となってしまいましたが、本コンペを運営してくださいました、ProbSpace の運営の皆様、一緒にコンペに取り組んでいらっしゃった皆様、Twitter上でやりとりを実施させていただいた皆様に心より感謝申し上げます。

今回学ばせていただいた事項を糧に、社会貢献できるよう引き続き精進してまいりたいと思います。

 

【過去記事】

G検定、E資格の取得から、これまでに取り組んできた道のりは以下にまとめております。何かのご参考にしていただければ幸いです。

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

【9位解法】Solafune開催「夜間光データから土地価格を予測」の振り返り。

アジア初の衛星データ解析コンテストプラットフォーム「Solafune 」で開催された「夜間光データから土地価格を予測」に参加し、9位の成績を残せました!

賞金獲得はなりませんでしたが、前回開催の「衛星画像から空港利用者数を予測」の2位受賞に続き、連続でのToP10入でした。

今回のコンペは、使えるデータが実質2カラム分しかなく、特徴量の活用が非常に難しいコンペでした。全体的にShakeが発生していたのもこのあたりが影響しているのかなぁと思いました。

f:id:kanriyou_h004:20210408192910p:plain

f:id:kanriyou_h004:20210408192833p:plain


 

では、振り返って参りたいと思います。

1.全体構成

今回のコンペは、テーブルコンペなのですが、与えられた生の特徴量が少ないため、特徴量をいかに増やすかが考えどころでした。

あとは、CVの工夫と、2段のStacking、加重平均で構築していきました。

f:id:kanriyou_h004:20210408193239p:plain

2.前処理

前処理については、以下の通りで実施いたしました。
(この処理は、cha_kabuさんのベースモデルを参考にしました。)

【四則演算等】         

前処理

処理内容
Area

その地域の合計の光量が「SumLight」で、平均の光量が「MeanLight」であることから、「SumLight ÷ MeanLight」が、その地域の面積であるとみなし、特徴量としました。

MeanLightが63となった回数

MeanLightは「63」が上限値となっていて頭打ちとなっていたので、上限値の「63」を超えた回数を特徴量としました。

 【統計情報】

前処理

処理内容

PlaceIDをキーとした統計情報

PlaceIDをキーとして、min,max,median,mean,std,max-min,q75-q25を特徴量として追加しました。

Yearをキーとした統計情報 Yearをキーとして、min,max,median,mean,std,max-min,q75-q25を特徴量として追加しました。

 【その他】

前処理

処理内容

同一PlaceID内の年ごとの差分

同一のPlaceID内で、年毎のMeanLighetの差分,年毎のSumLighetの差分を特徴量として追加しました。

同一PlaceID内の年ごとの差分

同一のPlaceID内で、年毎のMeanLighetをShiftした値,年毎のSumLighetをSiftした値を特徴量として追加しました。

同一PlaceID内の相関係数

同一のPlaceID内で、MeanLighet,SumLighet,Areaと年の相関係数を特徴量として追加しました。

ピボットテーブルを用いた特徴量

pandasのpivot_tableを使って、特徴量を水増ししたうえで、sklearn.decompositionのPCAを利用して、特徴量の選択を実施しました。

3.モデル構築

 今回は、モデル構築には、2階層のStackingでモデル構築をしました。

1層目は、LighetGBMで構築し、検証はGroupKfoldを用いました。

2層目は、MLPRegressorで構築し、検証はホールドアウト法を用いました。

1層目、2層目ともに、いろいろなモデルを試してみたのですが、あまり精度のよいモデルを構築できなかったのが残念でした。もっと多様なモデルで精度が出すことができていれば、もう少し上位を狙えたかもしれません。

(通算300個以上のモデルを作って、そのうち130個以上の提出を実施しました。後半はほぼ毎日提出しました。)

最終的には、以下の4つの組み合わせを採用しました。

1層目

  • LGBM GroupKfold Fold数5 × 6モデル
  • LGBM GroupKfold Fold数11 × 1モデル
  • エッジ抽出画像→ResNet-34 モデル3
  • 多重化画像→efficientnet-b7 モデル4

2層目

  • MLPRegressor ホールドアウト × 2モデル

その後、この2つの組み合わせで加重平均をとりました。

f:id:kanriyou_h004:20210408193239p:plain

4.感想

今回のコンペは、カラム数が非常に少ないデータから特徴量を作り出すというアプローチの勉強になりました。

画像データの様にデータ量が多くないので、学習に時間がかからないという利点があるのですが、精度を出すための特徴量づくり、特徴量選択が非常に難しかったです。

いろいろなみなさんのベースラインを拝見しながら、よいモデルを作成することができました。

他の皆さんのベースライン等は以下にまとめました。とても勉強になったベースラインばかりでした。

oregin-ai.hatenablog.com

5.謝辞

最後となってしまいましたが、本コンペを運営してくださいました、Solafune の運営の皆様、一緒にコンペに取り組んでいらっしゃった皆様、Twitter上でやりとりを実施させていただいた皆様に心より感謝申し上げます。

いつもながら、宇宙からのデータについて分析できるというのは、とてもワクワクします。今回学ばせていただいた事項を、社会貢献に活用できるよう引き続き精進してまいりたいと思います。

 

【過去記事】

G検定、E資格の取得から、これまでに取り組んできた道のりは以下にまとめております。何かのご参考にしていただければ幸いです。

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

Solafune 夜間光コンペの公開情報まとめ(2021年2月27日)

衛星データ分析サイトのSolafuneで現在開催されている「夜間光データから土地価格を予測」コンペで現時点で公開されている情報をまとめてみました。

f:id:kanriyou_h004:20210227223652p:plain

Solafuneでは、KaggleのDiscussionやSIGNATEのフォーラムのような情報共有の場はなく、各自のメディアを利用して自由に公開できるルールとなっています。

このため、公開情報が散在しているので、現時点で私が認識している公開情報をまとめてみました。

現在コンペに取り組み中の皆さんも、これからコンペに参加される皆さんも、参考にしていただければと思います。

もちろん、私も参考にさせていただきます!

【目次】

1.[solafune] 夜間光データから土地価格を予測 BaseLine(mst8823さん公開情報)

masato8823 (@mst_8823) | Twitterさんが公開してくださっているベースラインです。

ベースラインとは思えない、ハイスコアなコードを公開してくださっています。

特徴量の生成から、特徴量の重要度の検討、クロスバリデーションの実施、今後の検討すべき事項など、とても示唆に富んだ資料です。

zenn.dev

2.Solafune 夜間光コンペ Baseline(xgb,lgb,cat)(tuboさん資料)

tubo (@213tubo) | Twitterさんが公開してくださっているベースラインです。

欠損値の確認や、時系列データの過不足の確認、テストデータと訓練データのplaceIDの重複がないことの確認など、データの分析を実施されています。

また、XGboost、LightGBM、CatBoostの複数モデルで予測したあとridge回帰でStackingする手法がとても参考になりました。

qiita.com

3.Solafune 夜間光コンペ StratifiedGroupKfold(回帰)(tuboさん資料)

こちらもtubo (@213tubo) | Twitterさんが公開してくださっている情報になります。

GroupKfoldによる分割と、tratifiedGroupKfoldによる分割の比較が行われています。

それぞれの特徴がコメントされています。

qiita.com

4.[solafune] 夜間光データから土地価格を予測ベースモデル(cha_kabuさん資料)

ちゃかぶ (@cha_kabu) | Twitterさんが公開してくださっているベースモデルです。

コンペサイトに記載されたデータの引用元の考察から始まり、pandas-profilingを利用せずに自力でデータの分析などを実施され、データ分析の結果をもとに特徴量の作成を実施されています。

学習・予測の内容について、「何を実施している」だけでなく、対数変換をする理由や、GroupKFoldにする理由など、「なぜ実施している」まで言及されていて、今後のコンペにも役立つ情報が満載です。

qiita.com

5.【solafune】「夜間光データから土地価格を予測」のLSTMベースライン(daikiclimate(sylk)さん資料)

daikiclimate (Dai) · GitHubさんが公開してくださっているベースラインです。

2時間で作ったとおっしゃっているコードが掲載されています。

LSTMを利用して系列データが処理されています。

このコードを参考にいろいろな工夫ができそうです。

qiita.com

6.おわりに

このSolafuneで開催されている「夜間光データから土地価格を予測」コンペは、目的変数も含めてカラムが5列しかないテーブルデータなので、非常に参戦しやすいコンペだと思います。

また、参加者の議論や情報共有も活発で、とても勉強になります。

私も皆さんの情報を参考にして、引き続き頑張ります。

f:id:kanriyou_h004:20210227223652p:plain

【過去の記事】

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

2020年の振り返り(機械学習の積み上げ~データ分析コンペに挑戦・入賞~)

2020年は、昨年から取り組み始めた機械学習の積み上げの成果を試すため、いろいろなデータ分析サイトのコンペティションに挑戦しました。

日々の積み上げの結果が実を結び、複数のコンペティションで入賞することができました。

いろいろと環境が激変し、大変な1年でしたが、自身の成長においては、とても有意義で濃厚で、思い出深い1年となりました。

では、振り返っていきたいと思います。

【目次】

【コンペ関連】

 1.ProbSpaceで総合ランキング1位に(金:3個、銀:2個)

今年、最も結果をのこせたのは、データ分析プラットフォームProbspaceで開催されたコンペでした、以下の通り、金:3個、銀:2個を獲得することができて、総合ランキングでも1位(2020年12月31日時点)になることができました。

各コンペでの記録は以下の通りです。(Youtubeコンペの振り返りを投稿していなかったことに今気づきました・・・。)

f:id:kanriyou_h004:20201231175710p:plain

2.SIGNATE、Solafuneで衛星画像コンペに挑戦

宇宙にとても憧れをもっている私は、衛星画像を利用したコンペはとても魅力てきでした。

具体的には、CDLEハッカソン2020予測性能部門 「画像データに基づく気象予測」(SIGNATE開催)と、衛星データ分析サイトのSolafuneで開催された「衛星画像から空港利用者数を予測」の2つに挑戦し、以下の結果を残すことができました。

3.Nishikaで初の賞金獲得

また、データサイエンスコンペティションサイトのNishikaで開催されたJリーグプレイヤーの出場時間予測に参加し、2位にランクインし、初の賞金を獲得しました。

PublicLBの6位から、PrivateLBでの2位にShakeUpしての入賞だったので、とても驚きました。

賞金圏に入ると、コードの検収等の手続きがあり、自身のコードを確認いただくために整理するという初めての取り組みが、とても良い経験になりました。

 【積み上げ関連】

1.GCI 2019 Winter(東京大学グローバルインテリジェンス寄付講座)受講

2019年12月から2020年3月まで、GCI 2019 Winter(東京大学グローバルインテリジェンス寄付講座を受講しました。

こちらは、東大生だけでなく、社会人も受講可能なデータサイエンスの基礎から、機械学習スキルまで、習得できる講座です。この講座は、3カ月にわたる講座にもかかわらず、「無料」で受講できました。

全8回のカリキュラムで、1回ごとに期限付き宿題の提出や、kaggle形式のコンペティション、事業提案を実施する課題など、修了するためには、かなりハードな取り組みとなりましたが、確実に自身のスキルアップにつながりました。

今年、各種コンペで結果を残せたのもこの講座のおかげだと思っています。

2.E資格の復習

また、E資格で学習した、LSTMや、GRUなどのグラフ図を自分の手で何度も書いてみて、復習をしました。

一度理解したつもりになっていても、誰かに説明するつもりで整理すると、あいまいに理解していた部分が出てきて、確認することで、さらに理解を深めることができました。

3.Dockerの習得(米国AI開発者がゼロから教えるDocker講座受講)

機械学習そのものの学習ではないのですが、様々なコンペでとても役に立ったのが

Dockerの習得でした。習得にあたってはオンライン学習プラットフォーム「Udemy 」の「米国AI開発者がゼロから教えるDocker講座 」を受講いたしました。

コンペは、テーブルコンペ、画像処理コンペ、自然言語処理コンペなどなど、いろいろなコンペがあり、コンペ毎に開発環境を変えたりする必要がありました。

そんな時にDockerを使って簡単に開発環境を構築・複製・変更できたのは、非常に有意義でした。

4.AIQuest受講(現在も受講中

さらなる積み上げとしての8月に募集が開始された経済産業省が実施しているAI Quest 2020|SIGNATEにも応募し、アセスメントに参加した結果、受講資格が得られました。

f:id:kanriyou_h004:20201209120340p:plain

守秘義務があり、詳細は記載できませんが、要件定義あり、コンペ形式でのAI開発あり、経営層向けのプレゼンありで、実業務に即した、かなり濃厚な講座です。

なんとか、第一タームをクリアすることができたので、12月からの第二タームも取り組中です。

signate.jp

5.社会人のためのデータサイエンス演習 (2020年11月29日終了)

f:id:kanriyou_h004:20201209121309p:plain

 

 さらなる積み上げとしての取り組みとしてもう一つ、総務省統計局提供の「社会人のためのデータサイエンス演習」を受講しました。

こちらは、いわゆる機械学習というわけではないのですが、エクセルを使った統計的な集計方法や、データをどのように確認・評価していくかについて、実際に手を動かしながら学習できる講座でした。

約2ヶ月間、動画で学習→演習課題に取り組むを繰り返し、とても有意義な時間を過ごすことができました。しかも無料なので、とてもお財布に優しい講座でした。

gacco.org

おわりに

今年は、本当にいろいろなことを学び、いろいろなことに挑戦し、いろいろな皆さんと巡り合い、とてもとても有意義な一年でした。

これからも、積み上げ・挑戦を続けて、自身のスキルアップをするとともに、世の中に貢献できる人材になっていきたいと思います。

本年は、本当にいろいろな皆様にお世話になりました。誠にありがとうございました。

来年もよろしくお願いいたします!

 

【これまでの道のり】

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

f:id:kanriyou_h004:20201209122737p:plain