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

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

Kaggleの取り組みスケジュールを「ypad」でアナログ管理する。

今回は、私が毎年愛用している「ypad」についてご紹介したいと思います。

特に今年は、KaggleやSIGNATEなどのデータ分析コンペでのスケジュール管理にとても役に立ったので具体例を交えながら記載したいと思います。

KaggleやSIGNATEなどのデータ分析コンペに参加する際に、記録については、fkubotaさんの「Kaggle日記という戦い方」を参考にさせていただきながら、デジタルで管理しているのですが、スケジュールについては、パッと開いて俯瞰的に眺めたいため以下の「ypad」というノートを使いアナログで管理しています。 

では、具体的にどのように私がどのように利用しているかご紹介いたします。

あくまでも私の個人的な使い方なので、工夫次第でいろいろな使い方ができると思いますが、ご参考にしていただければと思います。

1.全体構成

「ypad」は、ipadとほぼ同じサイズの186mm×241mmの大きさのスケジュール管理用ノートになります。

見開きで2週間分のスケジュールが管理できて、1冊で1年と2週間分のページ数があります。

ページの種類は3種類あります。

見開きの左のページは、1日のスケジュールを管理するページになります。

日付は記入式なので、いつからでも開始することができます。

f:id:kanriyou_h004:20201229122531j:plain

見開きの左ページは、タスク毎に2週間分の予定を管理できます。

プロジェクトマネジメントでいうところの、WBSのようなものを作れます。

f:id:kanriyou_h004:20201229122725j:plain

2週間の見開きのページの裏はフリーページになります。

f:id:kanriyou_h004:20201229150512j:plain

番号が振られているので、管理がしやすくなっています。

f:id:kanriyou_h004:20201229150534j:plain

2.右ページの使い方①(目標設定)

まず、右ページの使い方です。

右上の日付欄に2週間の日付を記載して、その左側のフリースペースに、その2週間の目標を記載します。

私は、縦に10目盛りあるので、2目盛り1目標で5つの目標を立てるようにしています。フリースペースは、結構広いので、達成できた場合はどんどん追加します。

スペースが空いていると埋めたくなる性分なので、追加しすぎて達成できないときも多々ありますが・・・。

f:id:kanriyou_h004:20201229123758p:plain

3.左ページの使い方

 左ページは、各コンペサイトごとに自分が興味をもったコンペを締め切りとともに記載しておきます。

参加するかしないかは別として、興味が湧いたコンペは記載するようにしています。

こうすることで、空き時間ができたときに、今どんなコンペがあったかなというのが一目瞭然となります。

(*タスクの内容は、private sharingになってしまうかもしれないので、念のためぼかしを入れています。)f:id:kanriyou_h004:20201229124705p:plain

それぞれの列の下には、2週間で各コンペで試してみたいモデルや、思いついた特徴量のアイデアなどを記載しておきます。

この際、fkubotaさんの「Kaggle日記という戦い方」を参考にして記録しているKaggle日記を活用しています。Kaggle日記に記録していたモデルや特徴量のアイデアを、いつ実施するかを転記しています。

4.右ページの使い方➁(スケジュール設定)

次に右ページのスケジュール設定です。

各日付のTopic欄には、その日の目標を設定します。

スケジュールには、左ページで記載した各日付にやってみようと思っていた事項を、具体的な時間にはめ込みます。

時間へのはめ込みは、あらかじめ予定として設定するときもあれば、当日空き時間ができたら埋めるときもあります。

f:id:kanriyou_h004:20201229125651p:plain

スケジュールを埋めるときに気を付けているのは、まずは、本業や、家族との予定などをあらかじめ埋めておくことです。

これは当たり前のことなのですが、意外と忘れがちで、ついついコンペで時間を溶かしてしまうので、当日急に空き時間ができたときも、スケジュールに書いて時間を決めてから取り組むようにしています。

5.まとめ

私は、すべてデジタルで管理というところまで到達できてないので、デジタルの検索性や書き換えの容易さを享受しつつ、「ypad」という既製品を使ってアナログで俯瞰的なスケジュール管理・タスク管理を実施しています。

デジタルにはデジタルの良さ、アナログにはアナログの良さがあるので、一概にどちらが良いということはなく、うまく併用できています。

皆さんのご参考になれれば幸いです。

 

【過去記事】

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

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

【10位解法】ProbSpace開催「スパムメール判別」コンペの振り返り。

データ分析プラットフォームProbspace「スパムメール判別」コンペに参加し、10位に入賞しました!

今回は、初めて本格的に自然言語処理に挑戦したコンペとなりました。

セキュリティに関するドメイン知識はあったのですが、様子が違って、なかなか活かすことができず、苦戦しました。

参加中のコンペで、今年最後の締切となるコンペだったので、なんとか金トロフィー圏内に入れてよかったです。

f:id:kanriyou_h004:20201221200738j:image

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

1.全体構成

今回のコンペは、自然言語処理の分類課題でした。これまで、自然言語処理をじっくり取り組んだことがなかったので、とても勉強になりました。

オライリー社の、入門自然言語処理を片手に、勉強しながら取り組みました。

f:id:kanriyou_h004:20201216192807j:plain

全体構成としては、以下の図とおりです。

前処理として、テキスト文書のクレンジング処理を共通的に実施して、不均衡データ対策にアンダーサンプリングを実施したあと、特徴量として扱えるようベクトル化を実施しました。

モデルは、最終的には、2層のStackingモデルの出力を加重平均するモデルとなりました。

f:id:kanriyou_h004:20201220174845p:plain


前半はSolafuneの「衛星画像から空港利用者数を予測」に注力していたので、あまり精度があがりませんでしたが、最終週以外は、とにかくシングルモデルでの精度向上に注力しました。

最終週は、いつもどおり物量での試行錯誤になってしまい、自然言語処理の部分でスコアが向上できなかったので、もっとじっくり自然言語処理についても学びたいと思いました。

2.前処理

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

【共通処理】 この処理は、cha_kabuさんのベースモデルを参考にしました。    

前処理

処理内容

ストップワードの削除

'i','me','at','by','is'など、どんな文章にも一定量出現し、特徴量として不要な情報となりうる「ストップワード」に該当する単語を削除.

句読点の削除

',', '.', ';',などの句読点や括弧などの記号を削除。

HTMLの分解

HTMLのタグで囲まれた部分については、要素に分解。

URLの削除

URLを削除。

ブラックリスト等との突き合わせができれば、活用できたかも。今回は外部データの申請をしなかったので、利用しませんでした。)

[ ]で囲まれた文の削除

[ ]で囲まれた注釈などの文章は割り切って削除。

 【不均衡データ対策】

前処理

処理内容

アンダーサンプリング

今回のデータは、スパムメールの数に対して、非スパムメールが非常に少ないとても偏った不均衡データだったため、適切に学習できるようスパムメールと非スパムメールのデータ数を均衡化する必要がありました。

均衡化には、RandomUnderSamplerを使用しました。

from imblearn.under_sampling import RandomUnderSampler

# アンダーサンプリングしながら訓練用データの作成
sampler = RandomUnderSampler(random_state=5)
X_resampled, y_resampled = sampler.fit_resample(X,y)

【ベクトル化】

前処理

処理内容

CountVectorizer

出現する単語をカウントすることで、単語の出現数を特徴量にする手法です。出現した単語を純粋にカウントします。

from sklearn.feature_extraction.text import CountVectorizer

# 単語の出現回数取得
vec_count = CountVectorizer(min_df=3)
vec_count.fit(X['contents'])
    
# 訓練データをベクトル化
X_resampled_vec = vec_count.transform(X_resampled['contents'])
TfidfVectorizer

TF-IDF(索引語頻度逆文書頻度)という手法で特徴量を作成します。
TF(単語の出現頻度)とIDF(単語のレア度)を掛けたものになります。

TFは、【文書内の該当する単語の出現回数】÷【文書内の全単語の出現回数】となります。

IDFは、【全ての文書数】÷【該当する単語を含む文書数】のLogを取ったもので表されて、値が大きければ大きいほどレアな単語であることになります。

このTFとIDFをかけ合わせた値を単語の特徴量とします。  

from sklearn.feature_extraction.text import TfidfVectorizer

# 単語のTFI-IDを算出
tfi_count = TfidfVectorizer()
tfi_count.fit(X['contents'])
    
# 訓練データをベクトル化
X_resampled_vec = tfi_count.transform(X_resampled['contents'])

3.モデル構築

 今回のモデル構築は、最初、LightGBM、XGboost、RandomForestとMLPRegressorの単体のモデルを大量に作成して、LBの成績が良かったモデルを1層目とする2階層のStackingモデルとしました。

その後、2層目も複数作成して、最終的には、1層目、2層目の出力の加重平均を試行錯誤しました。

f:id:kanriyou_h004:20201220174845p:plain

BERTなどの自然言語処理の学習済みモデルは、今回は、勉強不足のため、採用できませんでした。

終盤は、自然言語処理とは関係なく、アンサンブルの試行錯誤になってしまったので、次回の機会に向けて、自然言語処理も学んでいきたいと思いました。

4.感想

今回のコンペは、初めて、本格的に、自然言語処理に挑戦したコンペとなりました。本格的にとはいったものの、テキストデータのクレンジングと、ベクトル化のみしかできませんでした。

実際は系列データの学習など、もっと深いところまで取り組まないと、太刀打ちできないと思いますが、今回は2値分類ということで、なんとかこれまでの手法も活用してそれなりのスコアを残すことができました。

今回はコンペなので、これで良かったのですが、実業務に活かしていくことを考えると、もっと勉強しないとならないと考えています。

引き続き精進していきたいと思います。

5.謝辞

最後となってしまいましたが、本コンペを運営してくださいました、Probspace の運営の皆様、一緒にコンペに取り組んでいらっしゃった皆様、挫けそうになったときにTwitter上でお声がけくださった皆様に心より感謝申し上げます。

引き続き、いろいろなコンペに参加させていただきたいと思いますので、今後ともよろしくお願いいたします。

 

【過去記事】

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

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

2020年10月~11月の振り返り(入賞ラッシュから、さらなる積み上げへ)

今年の10月~11月は、これまでの積み上げが、結果として現れ始めるとともに、あらたな取り組みを開始した2ヶ月でもありました。

CDLEハッカソンでの初のオンライン表彰式や、最後数分まで、首位争いに参加したSolafuneの衛星データコンペなど、エキサイティングな出来事ばかりでした。

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

【目次】

 1.Nishika Jリーグプレイヤーの出場時間予測 2位入賞(2020年10月14日終了)

10月の入賞の1つめは、データサイエンスコンペティションサイトのNishikaで開催されたJリーグプレイヤーの出場時間予測の2位入賞となります。

 

f:id:kanriyou_h004:20201209113416p:plain

こちらは、前処理として過去の試合出場実績など、複数のファイルのデータを結合しながら、各選手の出場時間を予測するという課題でした。

バラバラに散らばったデータを集計したりしながら特徴量を作成していくプロセスがとても勉強になりました。

また、チーム名、選手名など実際のデータを使ったコンペだったので、機械学習の学びもさることながら、サッカー観戦が好きな私にとっては、とても楽しめるコンペでした。

詳細は、以下に投稿しましたので、ご参照ください。

oregin-ai.hatenablog.com

2.CDLEハッカソン2020表彰式 予測性能部門 「画像データに基づく気象予測」優秀賞受賞(2020年10月17日)

2つ目は、すでに順位は2位で確定していたCDLEハッカソン2020予測性能部門 「画像データに基づく気象予測」(SIGNATE開催)の表彰式が執り行われ、優秀賞をいただくことができました。

また、チームで参加していたアイデア部門でも、企業賞をいただくことができました。

f:id:kanriyou_h004:20200926175529p:plain

こちらは、衛星ひまわりから得られた画像データをもとに、未来の雲画像を予測するという課題でした。

入力としては、画像データだけでなく、気温、水温、風、などの諸元データもあり、どのように活用していくか、工夫しどころ満載のコンペでした。

出力としては、画像データということで、ある意味画像生成の要素も含まれていて、いろいろと勉強となりました。

また、衛星のデータを扱うということで、宇宙のロマンを感じながら取り組めた、とてもよいコンペでした。

このコンペの解法は以下でも紹介していますので、ご参照ください。

oregin-ai.hatenablog.comまた、1位の解法を、@pometa0507さんが公開してくださっています。

lotti.info

3.Probspace 対戦ゲームムデータ分析甲子園  9位入賞(2020年10月19日終了)

 3つ目は、データ分析プラットフォームProbspaceで開催された対戦ゲームムデータ分析甲子園(通称:スプラトゥーンコンペ、イカコンペ)の9位入賞でした。

f:id:kanriyou_h004:20201209114528p:plain

このコンペは、スプラトゥーンというNintendo Switchのゲームの勝敗を、武器やステージなどのデータから推測するという課題でした。

私はこのゲームをプレイしたことがなく、ドメイン知識が全くなかったので、Python機械学習クックブック [ Chris Albon ]を使って、掲載されている手法をいろいろ勉強するつもりで参加しました。

f:id:kanriyou_h004:20201020023926j:plain

結果としては、9位に入賞することができましたが、PublicLBで4位であったところが、PrivateLBでは9位となり、いわゆるShakeDownを起こしてしまいました。

汎用性の確保が重要だとあらためて認識したコンペとなりました。

このコンペの解法は以下でも紹介していますので、ご参照ください。

oregin-ai.hatenablog.com

4.Solafune 衛星画像から空港利用者数を予測 2位入賞(2020年11月30日終了)

4つ目は、アジア初の衛星データ解析コンテストプラットフォーム「Solafune 」で開催された「衛星画像から空港利用者数を予測」の2位入賞でした。

f:id:kanriyou_h004:20201209115432p:plain

このコンペは、衛星から得られた空港の画像から、空港の利用者数を予測するという課題でした。画像処理系の課題は、分類が多かったので、利用者数を予測する回帰の課題は、新鮮でした。

画像処理関係についてはSIGNATEの雲画像予測コンペ、回帰にあたってのアンサンブルやスタッキングについては、ProbSpaceの不動産コンペNishikaのサッカー出場時間予測コンペで培ったノウハウをフル活用して取り組みました。

ある意味、今年の私の積み上げの総決算というべきコンペとなりました。

また、CDLEハッカソン2020に引き続き、衛星データを扱ったコンペへの参加となりました。容易に宇宙からのデータを扱うことができて、宇宙が身近になってきていることが肌で感じられました。

このコンペの解法は以下でも紹介していますので、ご参照ください。

oregin-ai.hatenablog.com

5.SIGNATE AI Quest 第一ターム(2020年11月28日終了)

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

f:id:kanriyou_h004:20201209120340p:plain

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

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

signate.jp

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

f:id:kanriyou_h004:20201209121309p:plain

 

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

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

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

gacco.org

7.おわりに

以上が、10月~11月の振り返りになります。

いろいろ盛りだくさんの2ヶ月でした。

現在、ProbSpaceのスパム判定コンペと、KaggleのRFCXコンペ(鳥蛙コンペ)、AIQuest第二タームに取り組み中です。

引き続き、インプット、アウトプットを両立しながら進めてまいりたいと思います!

 

【これまでの道のり】

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

f:id:kanriyou_h004:20201209122737p:plain 

 

 

【2位解法】Solafune開催「衛星画像から空港利用者数を予測」の振り返り。

アジア初の衛星データ解析コンテストプラットフォーム「Solafune 」で開催された「衛星画像から空港利用者数を予測」に参加し、2位の成績を残せました!

SIGNATEの雲画像予測コンペNishikaのサッカー出場時間予測コンペに続き、またもや、僅差での2位というということでとても惜しい思いがありますが、開催から終了まで、いろいろな皆さんとTwitterなどで、コミュニケーションをとって、お互いよい刺激を与えながら取り組めたとても楽しいコンペでした。

また、今回は画像処理関係についてはSIGNATEの雲画像予測コンペ、アンサンブルやスタッキングについては、ProbSpaceの不動産コンペNishikaのサッカー出場時間予測コンペで培ったノウハウをフル活用して取り組んだ、ある意味、今年の私のとりくみの総決算というべきコンペとなりました。

f:id:kanriyou_h004:20201201154319p:plain
 

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

1.全体構成

今回のコンペは、画像処理系で回帰の課題でした。これまで、画像処理といえば分類が中心だったので、画像→回帰の流れは、なかなか手応えがありました。

画像処理では、SIGNATEの雲画像予測での経験を活かし、取り組んでいたのですが、データ量が少なくて同じような画像も多くかなり厳しい戦いでした。

基本的には、学習済みのモデルをFinetuningし、組み合わせて、アンサンブル、スタッキングすることで構築していきました。

f:id:kanriyou_h004:20201130142126p:plain

「学習用画像データやラベルデータを画像処理手法により自動で水増しすることや、加工して学習用データとして利用することは可能です」というルールに則り、RandomResizedCropと、RandomHorizontalFlipを実施してデータ量を増やしました。

前処理としては、二値化やエッジ抽出した画像を重ねて、あとは複数のモデルの出力を特徴量とすることで、データ不足を補うことにしました。

結果として、前半は、シングルモデルで、それなりの精度が出せるモデルを大量に作って、終盤近くで、スタッキングした結果、グイグイ精度があがったので、戦略としては正解だったと考えています。


Score推移は以下の通りで、前半はLBスコアを向上させるためのアンサンブルをぐっとこらえて、とにかくシングルモデルでの精度向上に注力しました。

その後、シングルモデルでの精度向上に限界が見え始めたころに、二値化、エッジ抽出、加重平均をとりつつ、最後は、ProbSpaceの不動産コンペのときに効果を発揮した、Stackingで最後のひと押しに成功しました。

前半で、モデル自体のパターンを大量に作ったことが、後々でいろいろ試せたので結果としては良かったと思っています。

f:id:kanriyou_h004:20201201155721p:plain

2.前処理

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

【共通処理】         

前処理

処理内容

中心部の切り取り

中心部1700x1700を切り取り。

(この処理は、mygleさんのベースモデルを参考にしました。)

 【個別処理】

前処理

処理内容

グレイスケール変換

OpenCVのcv2.IMREAD_GRAYSCALEや、Pillow(PIL)のconvert("L")を使ってグレイスケールに変換

疑似二値化 グレイスケールに変換後、200以下は0にして、200より大きい値はそのままとする、擬似的な二値化

 

エッジ抽出

OpenCVのcv2.Cannyを使ってエッジの抽出

多重化

グレイスケール画像、二値化画像、エッジ抽出画像をそれぞれ1チャンネルずつを多重化し、3チャンネルの画像を作成

3.モデル構築

 今回は、モデル構築には、上記の前処理画像と、いろいろなモデルの組み合わせで、精度が良いモデルを探索しました。

試したモデルは以下のとおりです。Pytorchを使いました。

バリデーションは、ホールドアウト法を使っていましたが、CVスコアとLBスコアの乖離が激しかったので、とにかくLBスコアが向上できるよう、大量にサブミットを実施しました。(通算300個以上のモデルを作って、選抜したモデルの出力をほぼ毎日提出しました。)

  • VGG-16,VGG-19,VGG-16bn,VGG-19bn
  • ,ResNet-18,ResNet-34,ResNet-50,,ResNet-101,ResNet-152
  • Wide-Resnet101
  • ResNeXt-50-32x4d,ResNeXt-101-32x8d
  • Dencenet-201,Dencenet-161
  • efficientnet-b5,efficientnet-b7

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

  • そのままの画像→efficientnet-b7 モデル1
  • 二値化画像→ResNeXt-50-32x4d モデル2
  • エッジ抽出画像→ResNet-34 モデル3
  • 多重化画像→efficientnet-b7 モデル4

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

精度の良かったモデルの加重を大きめにするなど、いろいろな組み合わせを試した結果以下を採用しました。

  • モデル2、モデル3の加重平均
  • モデル1、モデル2、モデル3の加重平均
  • モデル1、モデル2、モデル3、モデル4の加重平均

その後、上記7つのモデルの出力をインプットとするスタッキングを構成しました、二層目のモデルにはLightGBM、XGBoost、ニューラルネットワーク(MLPRegressor)を試してみた結果、3層のニューラルネットワーク(MLPRegressor)を採用しました。

最終的な構成は以下のとおりです。

バリデーションはクロスバリデーションを使いました。最終提出のモデルのFold数は、12になります。前半と比べてCVスコアとLBスコアの乖離が小さくなったものの、余りCVスコアの信頼性がなく、相対的な評価として利用し、一つ一つLBスコアを確認していくアプローチで対応しました。

f:id:kanriyou_h004:20201130142126p:plain

4.感想

今回のコンペは、SIGNATEの雲画像予測につづいて、衛星画像データを使ったコンペに挑戦となりました。奇しくも、取り組んでいる最中に野口宇宙宇宙飛行士が民間企業SPACE-X社のクルードラゴンで国際宇宙ステーションに到着したり、若田宇宙飛行士、古川宇宙飛行士が国際宇宙ステーションに行くミッションが決まったり宇宙ネタが多い1ヶ月だったので、テンションがあがりました。

データ分析としても、画像処理あり、回帰ありと、これまで取り組んできたコンペの要素の総決算でした。

データの少なさについては、Data Augmentationと、複数のモデルを片っ端から検証し、その出力を特徴量として採用した回帰とすることで、うまく精度を上げることができました。

しかしながら、たまたま選んだ戦略がうまくいっただけで、なぜうまくいったのかも理解できていませんし、どのようなデータの場合、今回の戦略が適用できるかもわかっていません。

まだまだ、勉強不足なので、もっと理論も勉強して、最初にデータを分析した上で、根拠をもって、「この戦略でいったほうがよい」と判断できるようになりたいと思います。特に画像処理系コンペでは、計算時間にものすごく時間がかかるので、戦略をミスると、やり直しが効かず、終了してしまいますので。。。

今回のコンペでの教訓も今後に活かしていきたいと思います。

5.謝辞

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

また、データのもととなっている衛星データのご提供関係者の皆様、宇宙に関して夢と希望を、そして様々な衛星や宇宙での実験結果による多大なる恩恵をもたらしてくださいまして誠に感謝しております。

私も、皆様に夢と希望を与えられるような実績を残せるよう精進してまいりたいと思います。

 

【過去記事】

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

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

【2位解法】Nishika開催「Jリーグプレイヤーの出場時間予測」の振り返り。

データサイエンスコンペティションサイトのNishikaで開催されたJリーグプレイヤーの出場時間予測に参加し、2位の成績を残せました!

今回は、PublicLBの6位から、PrivateLBでの2位の初めてのShakeUpでの入賞でした。ShakeUpしたということは、汎用性能が出てないともとれるので、モデル精度的には望ましくないかもしれないですが、心情的にはとてもうれしいです!

f:id:kanriyou_h004:20201019184613p:plain

 

スポーツコンペは、プレイしている選手たちを想像しながら取り組めるので、とても楽しく参加することができました。

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

1.全体構成

今回のコンペは、複数のファイルのデータを結合しながら取り組むコンペティションでした。

時系列データとしてもとらえることができたかもしれませんが、単純に結合したテーブルデータとして前処理したデータを複数のモデルに学習・予測させてアンサンブルをとるという手法をとりました。

その代わり、データの前処理については、いつも以上に力を入れて取り組みました。

(実際一番、精度がアップしたのは前処理を入れたときでした。)

f:id:kanriyou_h004:20201019210637p:plain

Score推移は以下の通りで、特徴量追加でぐっと下がっりました。

それ以降、クロスバリデーションなどいろいろ試したのですが、時系列データに近いということもあり、うまく分割できず思うようにスコアが伸びませんでした。

終盤で他のコンペで利用したハイパーパラメータをモデルに適用することで最後の一押しの精度向上ができました。

f:id:kanriyou_h004:20201019213803p:plain

2.前処理

前処理については、最初はいつもの通り、欠測補完とターゲットエンコーディング程度の学習データで実施していたのですが、それでは不十分と思い、以下のような前処理を行って特徴量を追加しました。

【eventデータ】         

データ種類

処理内容

出場記録

選手毎にフル出場, 途中出場, 途中退場,途中出場途中退場, 出場停止,ベンチ入りの回数を集計し、試合数で割って正規化したデータを年度ごとのファイルに保存しました。

 【trainデータ】

データ種類

処理内容

選手名、登録ボジション、国籍 

sklearnの LabelEncoderで、数値化。

国籍については、Nullの場合は日本として補完。

チーム名、過去シーズン在籍チーム

辞書を作成し、数値化。

また、過去のシーズン在籍チームについては、'・'の有無で、チーム移籍有無を表す特徴量として追加。

生年月日

年を抽出して誕生年の特徴量を追加。

ユース出身

0または1で数値化。

過去シーズン出場試合数、得点数、出場時間

欠測[-]を-1で補完。

過去シーズン所属リーグ

欠測[-]を0で補完。

推定年俸

欠測[na]を中央値で補完。

3.モデル構築

 今回は、モデル構築には、LightgbmとRandomForestとXGboostを使いました。

ニューラルネットワークも活用したり、時系列処理も試してみたかったのですが、時間の関係で、木モデル中心の構成となりました。

クロスバリデーションについては、KFold等いろいろ試してみましたが、うまくいかず、評価は2018年度のデータを検証データとするホールドアウト法などで行いました。

また、ハイパーパラメータについては最終的に、過去のコンペで使用したパラメータを用いることで良い結果がえられました。

f:id:kanriyou_h004:20201019210637p:plain

 

5.感想

今回のコンペは、実際に実名の選手のデータが登場するコンペだったので非常に盛り上がりました。サッカーは、中継での観戦が中心なのですが、時差の関係で深夜や早朝になる国際大会であってもリアルタイムで見る派なので、知っている名前が出てくる度に嬉しくなっていました。

データ分析としても、欠測の補完のパターンやラベリングのパターン、数値を正規化したりしなかったり等、基本的な手法をいくつも試すことができて面白かったです。

ただ、同時期に取り組んでいたスプラトゥーンコンペとは対象的に、モデルのパターンは余り試せなかったのは心残りでした。

一方で、過去のコンペで使用したモデルのパラメータが活用できたのは、最後の追い込みで非常に役に立ちました。コンペ毎に完結するのではなく、コンペで培った資産は、次に活かしていくことも大切と改めて感じました。

また、今回は、ガイドラインhttps://www.nishika.com/guidelines)に従った成果物の提出が必要であったため、提出物の作成に非常に苦戦いたしました。

順位等確定後、提出物が即時に提出できるよう普段から成果物の管理を実施しておくことの重要性も再認識いたしました。

今回のコンペでの教訓も今後に活かしていきたいと思います。

6.謝辞

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

また、データのもととなっているJリーグ関係者の皆様には、いろいろと大変な時期ではございますが、エキサイティングなゲームをご提供いただけることに感謝を申し上げます。

私も、皆様に感動を与えられるような実績を残せるよう精進してまいりたいと思います。

 

【過去記事】

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

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

【9位解法】ProbSpace開催「対戦ゲームデータ分析甲子園」(スプラトゥーンコンペ)の振り返り

データ分析プラットフォームProbspace対戦ゲームムデータ分析甲子園(通称:スプラトゥーンコンペ、イカコンペ)のに参加し、9位に入賞しました!

今回もPublicLBでは4位だったのですが、Shake downしてしまい、汎用性をもったモデルの構築の難しさを改めて実感しました。

f:id:kanriyou_h004:20201020114811p:plain

今回のコンペは、スプラトゥーンというNintendo Switchのゲームの勝敗を、武器やステージなどのデータから推測するというタスクでした。

私はこのゲームをプレイしたことがなく、ドメイン知識が全くなかったので、Python機械学習クックブック [ Chris Albon ]を使って、掲載されている手法をいろいろ勉強するつもりで、取り組みました。

f:id:kanriyou_h004:20201020023926j:image

この本では手法の1つ1つを"レシピ"という単位でまとまっていたので、どのレシピをどこで使ったかも、紹介していきたいと思います。

では、振り返ってまいります。

1.全体構成

今回は、前述の通り、ゲーム自体の知識がなかったので、データ自体の分析はそこそこに、とにかく、いろんな手法を使ってみました。

今回初めて使ったモデルもあり非常に勉強になりました。

全体像としては、以下のとおり3つの前処理をした特徴量を使った6種類の予測結果を加重平均したモデルが最もprivateスコアが高かったモデルとなりました。

f:id:kanriyou_h004:20201020101139p:plain

2.前処理

前処理は、以下の3通りを用意しました。

【前処理①】

こちらは、Probspace のトピックで公開させていただいたベースラインで使用している前処理になります。

欠損値には、全て-1を設定しています。

また、カテゴリ変数は全てターゲットエンコードしています。

 

【前処理②】

上記、前処理①で作成した特徴量を、feature tools を利用して、水増ししました。

具体的には、それぞれの特徴量を足し算、引き算、掛け算した特徴量を追加しました。

featuretoolsについては、@momijiameさんの以下の記事を参考にさせていただきました。

blog.amedama.jp

【前処理③】

こちらは、カテゴリ変数のうち、武器関係の特徴量はOne-Hotベクトルに変換して、それ以外の変数はラベルごとの数値に変換しています。

欠損値については、どちらも欠損値を表す文字列に変換しておいて、1つのカテゴリとして上記の変換を行いました。

 武器関係のOne-Hotベクトルに変換については、Python機械学習クックブック [ Chris Albon ]の「レシピ5.1 名義カテゴリ特徴量の数値化」にあった複数クラスのエンコーダーMultiLabelBinarizer()を利用しました。

また、それ以外のカテゴリ変数はの数値に変換については、Pandasのfactorize()を使用しました。factorize()については、@QUANONさんの以下の記事を参考にさせていただきました。」

qiita.com

3.モデル構築

 今回は、前述の通りPython機械学習クックブック [ Chris Albon ]のモデルをいろいろと組み合わせて試していきました。

この中で、今回privateスコアが最も高かったのは、以下の6つ入力とモデルの組み合わせからの出力を加重平均したもとなりました。

前処理①の特徴量→GaussianNBを1層目、BernoulliNBを2層目にしたStacking

1つ目は、ガウシアンナイーブベイズクラス分類器(GaussianNB())と、ベルヌーイナイーブベイズクラス分類器(BernoulliNB())をStackingした構成になります。

ナイーブベイス分類機は、ベイズの定理を利用した、単純ベイズ確率モデルとのことです。(理論等についてはこれから勉強します!)

ガウシアンナイーブベイズクラス分類器(GaussianNB())は、分布が正規分布になることを前提として分類する分類機で、Python機械学習クックブック [ Chris Albon ]の「レシピ18.1 連続値特徴量に対するクラス分類器の訓練」にあった、GaussianNB()を利用しました。

ベルヌーイナイーブベイズクラス分類器(BernoulliNB())は、分布がベルヌーイ分布になることを前提として分類する分類機で、Python機械学習クックブック [ Chris Albon ]の「レシピ18.3 2クラス特徴量に対するナイーブベイズクラス分類器の訓練」にあった、BernoulliNB()を利用しました。

前処理②の特徴量→LogisticRegression

2つ目は、ロジスティック回帰(LogisticRegression)を利用した構成となります。

言わずとしれた2値分類のモデルになります。「回帰」と名前がついていますが、分類モデルに使えるモデルです。

Python機械学習クックブック [ Chris Albon ]の「レシピ16.1 2クラス分類器の訓練」にあった、LogisticRegression()を利用しました。

 

3つ目以降は、定番の勾配ブースティング決定木 (Gradient Boosting Decision Tree) の精度が良かったので採用しています。

前処理③の特徴量→XGboost

3つ目は、勾配ブースティング決定木 (Gradient Boosting Decision Tree) の一つである、XGboostになります。

XGboostについては、@momijiameさんの以下の記事を参考にさせていただきました。

blog.amedama.jp

前処理①の特徴量、前処理②の特徴量、前処理③の特徴量:LightGBM

4つ目から6つ目は、前処理①から③をそれぞれLightGBMで学習したモデルになります。

LightGBMについては、@codexa_netさんの以下の記事を参考にさせていただきました。

www.codexa.net

それぞれの予測結果の加重平均を最終的なサブミットとすることで、Publicスコアが0.567396Privateスコアが0.564008の精度を得ることができました。

 

4.まとめ

今回は、ゲームの勝敗予測ということで、ドメイン知識がなく辛いなと考えていたのですが、Python機械学習クックブック [ Chris Albon ]を活用させていただき、いろいろなレシピを活用させていただくことで、なんとか1桁台の順位を獲得することができました。

欲を言えば、今回もまたShakeDownしてしまったので、PublicとPrivateの精度を同等にできる汎用的なモデルを作成できなかったところが反省点です。こちらについては、血行続いているので、対策を勉強していきたいと思います。

5.謝辞

コンペを運営してくださいました、ProbSpaceの運営の皆様、コンペに参加してくださった皆様に心より感謝申し上げます。

また、今回、十二分に活用させていただいたPython機械学習クックブック [ Chris Albon ]の著者のChris Albon様、訳者の中田 秀基様、出版社のオライリー・ジャパンの皆様、ブログ等を参考にさせていただきました、@momijiameさん、@QUANONさん、@codexa_netさんに、この場を借りて厚く御礼申し上げます。

私も、皆さんの用に有用な情報発信ができるよう、これからも精進していきたいと思います。

 

【過去記事】

これまでの道のりは以下の記事をご参照ください。

oregin-ai.hatenablog.com

oregin-ai.hatenablog.com

 

Kaggle鳥コンペの上位者に学ぶ(鳥コンペ反省会資料を読む)

今回は、KaggleのPublicスコアで初めてコンペ終了まで銅メダル圏内に残ることができました。しかしながら、Privateスコアでは一気に下がり、268位と大きくShakeDownすることになりました。

その原因の一つとして、現在の私のアプローチは、自身の知りうるデータの前処理、及びモデルを組み合わせて精度が上がる組み合わせを見つけるという実験的アプローチが主体であることがあります。

やはり、上位を目指すためには、コンペ自体の情報や、データの情報から、論理的に考えて効果が出るデータの前処理や、モデル選択が重要であることを再確認しました。

そこで、今回は、「鳥コンペ反省会」にて公開されている資料を拝見し、今後に活かしたい知見を自身のメモとして残していきたいと思います。

【目次】

1.鳥コンペ反省会 6位解法(Hidehisa Araiさん資料)

6位入賞で金メダルを獲得され、鳥コンペを主催くださいましたHidehisa Arai | Kaggleさんの資料です。

speakerdeck.com

この資料を拝見しての気づき。

・コンペで解決すべき課題を十分に理解しておく必要がある。

  • TrainDataと、TestDataは、同じ条件下で取得、アノテーションされたデータであるとは限らない。→今回の場合、TrainDataとTestDataでは、入力の音声データが異なる性質をもつことはさることながら、ラベルの付け方に大きな差異があり、TrainDataの正解ラベルをそのまま使っても精度は上がらない
  • TrainDataのラベルが正しいとは限らない。→今回の場合、secondary_labelsというラベルがあったが、信頼性はない。(そもそも、ついていない場合もありました。)

・解決すべき課題を理解した上で、解決策は事象を分割して考える。

  • 今回の場合は以下で対処されていた。
  • TrainDataとTestDataの入力の性質の違い
    →DataAugumentationでありうるバリエーションを網羅
  • TrainDataとTestDataの正解ラベルの出現頻度の違い
    →ラベル比率を変えたデータで学習させたモデルのアンサンブル
  • TrainDataとTestDataのラベルの付け方の差異
    →TrainDataのラベルを正しい(と予測される)ラベルに修正する。

・Discussionを重点的に目を通す。

  • 参加者がやっていることを見るだけでなく、やっていないことを見つける上でも重要。
  • 投稿することでも自分に有利になることがある。→議論を進める主導権を握ることで、コンペの流れを支配できる。

この資料を拝見して、私自身がまだまだ素人だと感じたことは、TrainData,TestDataは、同じ条件下で作成されている前提で取り組んでしまったことです。

また、コンペに取り組むにあたって、Overviewや、Dataの出自などを十分に確認せず、Discussionも余り目を通さず、データやモデルしかみていなかったことも良くなかったと反省しました。

これまでのコンペで、そこまで考慮していなかったのですが、通常の業務で考えたら、集められた手元のデータ(TrainData)と、これから解決すべき課題で使用するデータ(TestData)が異なる条件下のデータであることは、当たり前のように発生することを再認識いたしました。

2.鳥コンペで惨敗した話とコンペの取り組み方(fkubotaさん資料)

タイトルでは「惨敗」と記載されていましたが、最後までLBに惑わされずに取り組まれ、最終的にメダル圏外から大きく躍進して銅メダルを獲得されたfkubota | Kaggleさんの資料です。

speakerdeck.com

この資料を拝見しての気づき。

・コンペに対する心構え。

  • 「Kaggleは長期戦」=「情報戦」
  • LBの上下に一喜一憂せず、愚直に知見を蓄積させる。

・アイデアの吐き出し場所を作る(issue boad)

  • 思いついたらなんでも記録する。
  • あとで読もうと思った論文や、DiscussionのURLを貼っておく。
  • 読み返して、実装する。
    → 実施前の記録をつける

・やったことを書き残す(Kaggle日記)

  • 作成したデータセットを記録する。
  • やったことのログをかく。
  • notebookの内容を関連するnotebookや、使ったデータセット、結果、感想などとともに記録しておく。
  • 読んだ論文やDiscussionについても、反映したnotebookなどとともに記録しておく。
    → 実施後の記録をつける
  • 記録した内容で思いついた内容は、issue boardに記録する。
  • 5日に1度見返す。

この資料を拝見して、「Kaggleは情報戦」という見解は、目からウロコの見解でした。(何を今更とご指摘を受けるかもしれませんが・・・。)

これまで、答えがあることを前提(ラベルデータがキレイであることを前提)で、取り組んできましたが、答えがあっているとは限らないという前提に立つと、答えに近づくためにはどうしたらよいかという情報をいかに蓄積していくかということが重要だと再認識いたしました。

(これは、コンペに限らず、実業務においても同じだと思います。)

また、「Kaggle日記」は、これからKaggleに取り組むにあたって、非常に有効なツールであると思いました。私も実践してみたいと思います。

Kaggle日記の詳細解説はこちらに公開いただいています。

Kaggle日記という戦い方 | Zenn

3.鳥コンペ反省会(Takamichi Todaさん資料)

こちらも500位以上大幅にShakeUpされ、鳥コンペでのモデルをWeb上にアプリも作成されていたTakamichi Toda | Kaggleさんの資料です。

docs.google.com

この資料を拝見しての気づき。

・計算リソースが確保できなくても工夫次第では取り組める。

  • スペクトログラム画像をjpgで保存。
    →情報が失われる、DataAugmentationが使えない等のデメリットを理解した上で進める。

・とにかくサブミットを実施して、検証する。

  • サブミット回数100回。
    →私は22回のみ・・・。
  • 検証している手法も、CutMix, Denoise(SoundEnvelope, noisereduce), Transformer, WaveNet 等、多岐に渡る。

この資料を拝見して、これまで自分が試しているパターンは、全くもって足りていないと感じました。

量の面では、3桁は超えないとだめだと思いました。質の面では、2〜3の手法の組み合わせや、パラメータのパターンを試すのではなく、手法自体のパターンをたくさん試す必要があると思いました。

手法自体のパターンをたくさん試せるように、手持ちの手法を充実させていきたいです。

4.鳥コンペ振り返り(Takamichi Todaさん資料)

終了1ヶ月前から手をつけ始めて、122位に入賞し銅メダルを獲得された

ymicky | Kaggleさんの資料です。

docs.google.com

この資料を拝見しての気づき。

・コンペのフェーズ毎の戦略を分けていた。

  • コンペ初期:Baselineカーネルからのパイプライン作成、信頼できるLocalCV作成の取り組み
  • コンペ中盤〜終盤:公開notebookの改良、モデルの検証、DataAugmentation実施、画像サイズの拡大、secondary_labelの使用

この資料を拝見して、他の皆さんの資料にも共通して、コンペ初期は、まずコンペ自体を理解し、検証に使うための武器を準備されている期間を用意されていることに気づきました。

私は、この資料の中盤〜終盤で実施するようなことから着手し始めていて、闇雲に取り組んでいました。今後は、まずは、コンペ、データを理解し、戦略的にすすめて行きたいと思います。

5.63rd_Kaggle鳥コンペソリューション紹介(bird_musicチーム資料)

63位に入賞し銀メダルを獲得されたjohann | Kaggleさん、nnnnio_pppira | Kaggleさん、Taro Masuda | Kaggleさん、yusuke_sato | Kaggleさんのチームでのご紹介いただいた資料です。

docs.google.com

この資料を拝見しての気づき。

・フィルタバンクをカスタマイズしていた。

  • メルスペクトログラムは、人間の聴覚の解像度を模倣しているので、鳥が鳴いている周波数帯にフィルタバンクを変更していた。

・モデル自体は公開notebookのスキームをそのまま利用していた。

・アンサンブルにおいては、F1値が0.6未満と推測した上で、アンサンブル元となる予測ラベルを全部予測値に入れていた。

・今回のコンペだけでなく、過去のコンペのソリューション(CVの切り方など)を確認していた。

この資料を拝見して、公開notebookのスキームをそのまま利用するにあたっても、特性を理解した上で、それ以外のところで勝負したほうが良いと割り切った上で利用するのと、私のように闇雲に、いろいろ試した結果、公開notebookのモデルを超えられない状況で利用するのでは、ここまで差が大きくでるのかと思い知りました。

評価指標の特性を理解し、効果的な手法を選択しているところがすごいと感じました。

6.おわりに

今回、鳥コンペ反省会資料を拝見して一番大きく感じたのは、自分が、コードばかりに目を向けて教科書と照らし合わせて、精度を良くする手法の組み合わせや、パラメータ設定に重きをおいていたのに比べ、上位の皆様は、コンペの主題や、解決すべき課題に目を向け、取り組んでらっしゃった点です。

これは、コンペに限らず、実業務でも自身の作っているシステムの不具合やバグばかりに目が行きがちですが、本来の目的や、解決すべき課題に目を向ける必要があることを、再認識いたしました。

本当に、この鳥コンペは学びの多いコンペでした。

今後も、いろいろなコンペに参加して、精進していきたいと思います。

f:id:kanriyou_h004:20200929151743p:plain

【これまでの道のり】

oregin-ai.hatenablog.com