天色グラフィティ

技術ちっくなことを書きます

初めて技術書典に出展して、新刊を300部売るまで

9/22の技術書典7で『ハマって覚えるデータ分析・機械学習の罠』を頒布しました。

BOOTHでの同時販売を含めると、書籍とPDFで合計300部以上買っていただけました。 買ってくださった方々、ありがとうございました。 感想や改善点などはTwitterで@SakuEjiにメンションを飛ばしていただけたらとても嬉しいです。

技術書典行けなかったという人にはBOOTHでもPDF版を頒布しています。頒価は会場と同じく1000円です。

sakueji.booth.pm

技術同人誌を書いたのは初めてでしたし、技術書典には参加者としてすら行ったことがなかったので不安9割でした。 そもそも完成できたのが奇跡としか言いようがありません。

売れ行きが全く想像できなかったのですが、「近頃話題の機械学習だし、なんとかなるやろ」とかなり強気に書籍は150部刷りました。 「売れ残ったらちょっと悲しいな」とも思っていましたが、 出だしからたくさんの方に買ってもらえて、14:00くらい(技術書典が11:00-17:00なので、だいたい半分の時間)に完売しました。

完売したことはすごく嬉しいのですが、「やっぱり書籍が欲しかった」という声も多くいただきました。 次回以降は気持ち多めに刷るくらいで良さそう、と思っています。 売れ残っても委託販売とかできますしね。

この記事では備忘録も兼ね、出展するに当たってやって良かったこと、やっておけば良かったことをまとめておきます。ぜひ参考にしてくださると幸いです。

何の本を出したか

『ハマって覚えるデータ分析・機械学習の罠』というタイトルからも分かる通り、データ分析や機械学習にまつわるアンチパターンをぎゅっと詰め込んだ本になっています。

機械学習初心者〜中級者が小規模な機械学習プロジェクト(研究とか、Kaggleを含む)に携わるという状況を想定しています。

機械学習プロジェクトを立ち上げるとき、データを眺めるとき、特徴量を作るとき、評価方法を決めるとき、学習するとき、と分析の各段階において気をつけるべき罠を一通り紹介した後、 分析サイクルを回すときに気をつけるべきことをTips的にまとめています。

会場に来てくださった方の中からも「あーこういうのあるよね」「これは知らなかった」という反応を多くいただき、嬉しい限りです。

より詳細な目次はこんな感じです。

はじめに
  本書の想定している読者
  あなたは誰ですか?
用語集
第1章 プロジェクトを始めるときの罠
  1.1 機械学習が有効な分野を見誤っている
  1.2 機械学習の結果をどう使うか想像できていない 
  詳しく知りたい方は
第2章 データを知るときの罠
  2.1 データの背景を把握せずに解析を始めてしまう
  2.2 データの統計量だけを見てしまう 
  2.3 可視化して満足してしまう
第3章 前処理・特徴量作成を行うときの罠
  3.1 泥臭い作業から逃げてしまう 
  3.2 典型的な処理を知らない
  3.3 特徴量作成にバグを埋め込んでしまう
  3.4 リークを埋め込んでしまう
第4章 モデルを評価するときの罠
  4.1 ベースラインを作成しない
  4.2 評価指標をよく考えずに選んでいる 
  4.3 バリデーションを適切に行っていない
第5章 モデルを訓練するときの罠
  5.1 モデルに適した形に前処理していない
  5.2 ハイパーパラメータ探索を適当に行っている
第6章 分析サイクルを回すときの罠
  6.1 ソースコードのバージョン管理を行っていない
  6.2 ライブラリのバージョンを固定していない
  6.3 乱数を適切に扱っていない
  6.4 モデルを保存していない
  6.5 Jupyter Notebook の収拾がつかなくなっている
  6.6 パラメータをソースコード中に書き込んでいる
参考文献 
おわりに

上の目次を読んで「あれ、これ良いかも?」と興味をもってくださった方はBOOTHからPDF版がダウンロードできます!笑

sakueji.booth.pm

ここからは、「自分も技術書典に出してみようかな」と思う人に向けて、覚えておくと良いことを解説していきます。

執筆前

親方Project『技術同人誌を書こう!』をめっちゃ読みました。

技術同人誌を書こう! アウトプットのススメ (技術の泉シリーズ(NextPublishing))

技術同人誌を書こう! アウトプットのススメ (技術の泉シリーズ(NextPublishing))

執筆から入稿、当日の準備まで網羅されていて、ほぼこれ一冊で同人誌が書けると思います。必携。

執筆環境

執筆環境にはRe:VIEWを採用しました。

Re:VIEW特有の記法を覚えなければいけませんが、同じ原稿から印刷用のPDFも、配布用のPDFも、電子書籍用のepubまで作成できるのはかなり魅力的です。 LaTeXMarkdown、Wordといった手段を使うこともできましたが、どれもどこかに難を抱えていました。

RedPenやtextlintといった校正ツールは使いませんでした。イケてる執筆環境を整えている時間がなかったからです。 次回執筆するときは使うと思います。

エディタはVSCodeを使い、yet another Re:VIEW extensionを入れました。一番人気のextensionを使わずyet anotherを使っているのは、 一番人気のextensionがソースディレクトリ変更に対応していなかったからです。

Re:View記法は@<code>{hoge}のような特殊な記法になっていて、ベタ打ちするのはストレスフルです。 絶対にスニペットを登録しておきましょう。大幅な作業時間短縮になるはずです。

表紙作成

表紙は本文とは別ファイルで作る必要があります。アプリケーションとしてはAdobe Illustratorを使うのが間違いないと思います。

表紙の出来はそのまま売れ行きに直結しますので、可能であればデザイナーさんにお願いして作ってもらうのが良いでしょう。 僕は時間がなかったので自分でデザインしました……

かわいいライオンの画像はUnsplashからダウンロードしました。

本文が40ページを超えたくらいから背表紙をつけることを検討しましょう。本棚に並べたときの見栄えが段違いです。

入稿

日光企画に2日遅れで入稿しました。費用が10%UPでしたが、直接原稿を持ち込んで現金で決済したので5%OFFになりました。

入稿は直接持ち込むのが圧倒的におすすめです。その場で確認して、おかしいところがあったら指摘してくれます。 オンラインで入稿した場合、電話越しに修正ポイントを指摘され、改めてオンラインで入稿し、それに対してまた指摘があり、と何往復もする必要があります。 店員の方も「持ち込んでくれたほうが嬉しいですねー」と言っていたので、可能であれば御茶ノ水店に行きましょう。

原稿の受け渡しのため、USBメモリを持っていくとスムーズです。 ない場合、店舗にいながらオンラインで入稿する羽目になります。日光企画にはWiFiがないので、泣きながらテザリングしました。

印刷・製本方式はオンデマンドの平トジフルカラーにしました。 印刷方式はオフセットとオンデマンドの2種類が選べます。 オフセットのほうが写真などが綺麗に出ますが、オンデマンドのほうが安く、〆切も1日遅いです。技術書であればオンデマンドで良いと思います。 製本方式は平トジと中トジが選べます。平トジが普通の本です。ある程度ページ数があれば平トジ一択です。 本文はグレースケールで良いと判断したため、表紙のみをフルカラーにしました。

同人誌はなぜかB5サイズで作られることが多いですが、A5サイズにしたほうが(ページ数が増えたとしても)かなり割安です。特にこだわりが無ければA5サイズで作るのも良いと思います。

他にも遊び紙や表紙コーティングといった細かいオプションがたくさんあるのですが、実店舗に行けばサンプルが見られますし、丁寧に説明してもらえます。

前日準備・当日設営

f:id:ejinote:20190924233142j:plain

長机の半分のサイズが各サークルに割り当てられます。スムーズに販売するためにはいろいろ必要なものがあるので、前日に慌ててハンズと100均(キャンドゥ)に駆け込みました。

①ブックカバー

キャンドゥとハンズの両方で買いましたが、100均のものはペラペラだったので捨てました。見本は心地よく読んでほしいですし、金額差も大したことは無いので良いものを選ぶべきだと思います。

②ブックスタンド

2つ必要だったので、キャンドゥとハンズの両方で買いました。一長一短。 迷ったら100均のもので良いと思います。

③布

布を敷くと見栄えがかなり良くなるので、絶対に買ったほうがいいです。

同人界隈ですと「あの布」が人気のようですが、僕は100均で端切れ布を買いました。十分でした。 たぶん何かしら敷かれていれば良いと思います。

④nu board

ホワイトボードやスケッチブックはその場で書き換えられるという点でなにかと便利です。

僕は結婚祝いで頂いたnu boardというノート型ホワイトボードをブックスタンドに立ててお品書きにしました。おすすめです。

Amazon限定 nu board (ヌーボード) B5判 NAB503BK08

Amazon限定 nu board (ヌーボード) B5判 NAB503BK08

他に買ったもの

  • 名札
    • 絶対あったほうがいいです。お客さんとのコミュニケーションが増えます
  • ハードクリアファイル
    • 公式から配られる「サークル便利カード」は便利ですが、かんたん後払い用のQRコードが小さいです。お品書きとQRコードをでかでかと紙に印刷して、クリアファイルに入れておくとスムーズです
  • カード立て
    • 今回は使いませんでしたが、頒布する書籍が複数ある場合、値札を立てておけるので便利だと思います
  • メッシュポーチ
    • お札の管理に使いました

あったらよかったもの

  • 名刺
    • 名刺をいくつかいただきましたが、プライベート用の名刺を作っていなかったのでお返しできませんでした……

その他こまごまとしたTips

執筆・印刷

  • ダウンロードカードは用意する
    • 準備が面倒なので今回はやらなかった
    • かんたん後払い利用者のみ、公式の機能としてダウンロード機能があるのでそれを使った
    • 「ダウンロードカードもらってません」という問い合わせが頻発した
  • 気持ち多めに刷る
    • 余ったからと言って即座に赤字なわけではない
    • ダイレクト入庫というサービスを使うことで、とらのあなやBOOTHに簡単に委託することができる
    • 手元にある程度残しておけば「ほしい」と言われたときに渡すことができる
    • なにより、「もう本ないんですか……」という悲しい顔を見ずに済む
  • お問い合わせ用の連絡先や、ツイートするときのハッシュタグを本文に書いておく
    • ないと反応が全然見えなくてつらい
    • 間違いの指摘も来ないので、次版の修正ができない可能性がある

準備

  • サークルカットは早めに作っておく
    • 一般の人がサークルリストにアクセスできるまでに作っておくと被チェックの伸びが良いと思う
  • 書き終えたら宣伝が命
    • ちょっとしつこいぐらいツイートした。特に前日〜当日にかけて。その甲斐あって被チェック数はぐぐっと伸びたし、BOOTH版も伸びた
  • 公式の推し祭り(Twitterイベント)には必ず参加する
    • かなり被チェックが伸びる
    • 他の出展者の方からフォローされ、交流が始まることも
  • 値段設定は1000円にしておくとめっちゃ楽
    • 書籍とPDFのセットは1500円に設定して、支払い方法をかんたん後払いのみにした

当日

  • 交代要員は絶対用意する
    • ワンオペだとトイレ行くだけで詰みかねないし、自分の買い物もできない
    • 隣のブースだったカレーちゃん(@currypurin)がワンオペで捌いていてマジですごいと思った

終了後

  • 出納をつける
    • いくら使って、いくら入ったのか把握して次回の部数設定に活かす
  • 翌日以降もPDF版などを宣伝する
    • 技術書典行けなかったけど評判いい本があったら買いたいという人はたくさんいる
    • ちゃんと宣伝すると、技術書典と同じくらい売れる
  • 振り返りブログを書く
    • 思いついた反省点をさっぱり忘れてしまうともったいない

最後は時系列で技術書典を振り返っていきます。

ツイートで振り返る経緯

機械学習アンチパターン集ってあんまりないな、と思ってツイートしてみたら、なんとなくいい反応だったので軽い気持ちで書いてみようかと思う。 何なら技術書typoするという体たらく。

ただ、実はその日、技術書典の〆切当日。

フォームを必死に記入しながら、技術書典経験者のu++さんとカレーちゃんに聞いてみる。 大丈夫だよーみたいな反応を貰ったので必死に申し込み作業を行う。

ギリギリ申し込み終了。

なんと当選。この日のうちにRe:VIEWの執筆環境を整える。後から考えると、ここで環境をきちんと作っていなかったら本は出てなかった。

ちなみに、本当にほとんど何も進んでいない。

Kaggle Meetupに参加した時、『Kaggleのチュートリアル』を執筆したカレーちゃんと会う。「書いてます?」という問いに対し、苦笑いで返す。 「えじさんの本売れると思いますし、たくさん刷ったほうがいいですよ! 600部とか!」と言われ、「この人、俺を殺しに来てるんじゃないか」と思った記憶がある。

エルピクセルさんの勉強会に行ったり、もくもく会を主催したり、KDD行ったり、他の記事を執筆したりでしばらく原稿の進捗がない日々が続く。

カレーちゃんのブースが隣だということが分かる。カレーちゃんは超人気サークル主。しかもジャンルが近いので、一緒に買っていってくれる人が多いに違いない。勝利を確信する。ちなみにこの時点で進捗は3割くらい。

「完成しさえすれば勝ち」と自分に言い聞かせながら必死に原稿を書く。Twitterへの浮上が減る。もちろんTwitterをしていないのでモリモリ原稿ができていく。

そして完成。

以後は技術書典当日。

開始前にBOOTHで10人以上に購入いただき、びっくりする。

12:00ごろ、開始1時間で半分売り切れてビビる。

13:00ごろ、早々に完売が見えてくる。

無事14:00ごろに売り切れ、PDF版をゆるゆる頒布。

かなり身軽にブース運営していたので、5分で撤収完了。カレーちゃんに「撤収速いですね!」と言われてドヤ顔で撤収するも、駅までの道で迷う。

たくさん買い物した。

翌日以降もたくさん買っていただいています!

まとめ

完成が危ぶまれた時期もありましたが、それを含めてすべて楽しかったです!また次回も(新刊をつくって)参加したいと思います!

技術書典8で会いましょう!

自作キーボード沼への第一歩。Lily58を組み立てました!

みなさんは遊舎工房をご存知でしょうか?

遊舎工房とは、秋葉原(御徒町)にある自作キーボードの専門店です。 おそらく日本唯一の専門店で、かつ店内に工作スペースがあり、購入したキーボードを組み立てて帰ることができます。

開店当初から行きたいと思っていたのですが、なかなかきっかけが掴めずにいました。 しかし、社内でセパレートキーボードを使っている同期をみているうちにキーボード欲が刺激されてしまいました。

Lily58を作っている様子

今回購入したのはLily58という、自作キーボード界隈でも人気のセパレートキーボードキットです。

f:id:ejinote:20190826220353j:plain
Lily58

Lily58には基盤や電子部品はすべて含まれていますが、キースイッチ(入力を感知するスイッチ部分)とキートップ(実際に指が当たる部分。印字されてたりする)は別に購入する必要があります。

箱の左に置いてあるのがキースイッチです。キースイッチには 癖のない赤軸、スイスイ打てる茶軸、めっちゃ軽い白軸、重みのある黒軸、カチカチ音がなる青軸といろいろあり、おそらく沼ポイントのひとつです。

僕は赤軸で、静音性を重視したものを選びました。HHKBのスコスコ音も嫌いではないですが、やはり静かな空間に行くと浮いてしまいます(セパレートなんて持っていったらもっと浮くというツッコミは無しでお願いします)

f:id:ejinote:20190826221533j:plain
一通りはんだ付けが終わったところ

高校以来のはんだ付けでした。中高6年間やっただけあって、腕は鈍っていなかったよう。ミスひとつなく作れました。

Lily58ははんだ付けをするポイントが結構多いので、はじめての人は店員の方にサポートしてもらいながら作ると良いと思います。

f:id:ejinote:20190826222219j:plain
はんだ付けする妻

はんだ付けをする妻です。「えっえっ大丈夫かなねえこれ本当に大丈夫?」と大騒ぎしていましたが、終わってみれば彼女の担当した場所もノーミスでした。すごい。

f:id:ejinote:20190826221808j:plain
キースイッチを一通りはめたところ。急にキーボード感が増す

今回購入したのは正確にはLily Proというもので、キースイッチを後から付け替えることができるタイプになっています。

要するに、キースイッチ沼にはまりやすい代物ということですね。

f:id:ejinote:20190826221846j:plain
キートップをはめたところ。白くてかっこいい

キートップは白の無刻印を選びました。

Lily58を始めとする自作キーボード群には、レイヤーという機能が存在します。これは、一部のキーを押すと配列がガラッと切り替わって、記号やファンクションキーなどをホームポジション付近で押せるようになるというものです。

要するに、初期のキー配置なんて、書いてあっても書いてなくても一緒なのです(と僕は解釈しました)

まとめ

作業時間の内訳は、

  • キットを選ぶ(30分)
  • はんだ付け(2時間)
  • 動作確認(30分)
  • キートップをはめる(45分)
  • 眺めてうっとりする(15分)

で総計4時間といったところでしょうか。はんだ付けに慣れていない場合は+2時間くらいを見積もっておくと良いかもしれません。

使ったお金は、

  • Lily58 Pro MX 15984円
  • Gateron Silent スイッチ 赤軸 75円×58個 = 4350円
  • TRRSケーブル(左右をつなぐやつ) 324円
  • USBケーブル 540円
  • キートップセット 2640円

で、合計23838円です。だいたいキットの値段+8000円くらいと思っておくと良いでしょう。

肝心の使ってみての感想ですが、

  • 最初は慣れない。特にエンターとバックスペースを親指で取るのが耐えられない
  • column staggered(列ごとに揃っている)配列なので、CVBNMあたりをめちゃめちゃミスタイプする

といった感じのつらみがあります。最初は。1日実戦投入したらだんだん慣れてきたので、1週間くらいしたら使いこなせると思います。

一方、さっきMac備え付けのキーボードを短時間触ったら、すげー変な感触とともに大量のミスタイプが発生しました。共存はだいぶ厳しいかもしれません。

一度入ってしまったら戻れない。沼たる所以はこんなところにもあったのです。

セパレートにしたいけど、普段のキーボードも使わなきゃいけない事情がある。そんな人にはMint60という素晴らしいキーボードがあるようです。 遊舎工房の通販サイトにはありませんが、実店舗では売っていました。

みなさんも、楽しい自作キーボードの世界に飛び込んでみませんか?

ICNR: Sub-Pixel Conv使用時のcheckerboard artifactを防ぐ初期化

f:id:ejinote:20190729202002p:plain

ニューラルネットワークで画像を拡大(アップサンプリング)する際、Transposed ConvolutionやSub-Pixel Convolutionという手法を使います。

しかし、これらの手法を用いた場合、拡大した画像に格子状の模様(checkerboard artifact)が発生することが知られています。

以前のLTのスライドも併せてご覧いただけると良いかと思います。

checkerboard artifactの主要な原因として挙げられているのは2つです。

1つ目はfilter overlapです。filter overlapとは、kernel_sizeやstrideの設定によっては出力に寄与する画素数が異なってしまう(フィルタが重なってしまう)現象のことです。 特にTransposed Convを利用した場合に発生します。

Sub-Pixel Convolutionの場合、原理上出力に寄与する画素数が異なることはありませんが、kernelの初期化によってcheckerboard artifactが発生することが指摘されています。これが2つ目の原因です。

Sub-Pixel Convolution使用時、初期化によるcheckerboard artifactを防ぐ方法として、ICNRという初期化方法が提案されています *1。 ICNRを利用することで超解像タスクにおいて(向上幅はわずかですが)綺麗な画像が生成されることが報告されています。

今回はPyTorchでICNRを実装し、ICNRの動きについて簡単な可視化を行いました。

ICNRの挙動

ICNRの基本的な発想は「Sub-Pixel ConvolutionでNearest Neighborを再現する」です。

Nearest Neighborで拡大した画像にはcheckerboard artifactは出ないので、それを初期値として学習を始めることでcheckerboard artifactを抑えて学習をすすめることができると期待されます。

Sub-Pixel ConvolutionはConv2dPixelShuffleからなります。Conv2dの初期化を下図のように行うことで、PixelShuffleした後の画像がNearest Neighborと同様になります。

f:id:ejinote:20190728165735p:plain

直感的ではないと思いますので、これを実験によって確かめてみます。

実験

設定

32x32のRGB(3チャネル)の画像を nn.Conv2d で畳み込み、12チャネルに増やした後 nn.PixelShuffle で並べ替えて64x64のRGB画像を作るという問題設定にします。

f:id:ejinote:20190728154213p:plain
元画像

元画像は以下のようなコードでPyTorchで読み込み可能な形式に変換します。

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

import torch
import torch.nn.functional as F
from torch import nn

image = Image.open('dog.jpg')
image = np.asarray(image, np.float32) / 255

x = image[np.newaxis, :, :, :].transpose(0, 3, 1, 2)
x = torch.from_numpy(x)

通常の初期化を行った場合

out = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=3, stride=1, padding=1)(x)
out = nn.PixelShuffle(2)(out)

f:id:ejinote:20190728155037p:plain
通常のConv2d→PixelShuffle

ご覧のとおり、それはそれはキレイなcheckerboard artifactが出ていることが分かるかと思います。もちろんこれは全く学習を行っていない状態なので、学習を進めていけば徐々に消えてはいきます。

ICNRで初期化した場合

ICNRの実装例は以下のとおりです。2倍に拡大する場合は出力チャネル数を1/4で初期化したあと、チャネル方向に4倍に引き伸ばしたものをConv2dの初期値として使います。

通常であればreshapepermuteを組み合わせて行列演算だけで書くのですが、初期化処理は何度も呼ばれるものではないので可読性重視でfor文を使っています。

def ICNR(tensor, scale_factor=2, initializer=nn.init.kaiming_normal_):
    OUT, IN, H, W = tensor.shape
    sub = torch.zeros(OUT//scale_factor**2, IN, H, W)
    sub = initializer(sub)
    
    kernel = torch.zeros_like(tensor)
    for i in range(OUT):
        kernel[i] = sub[i//scale_factor**2]
        
    return kernel

使用例です。conv.weight.data.copy_を使用してICNRで生成した初期値を与えています。

conv = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=3, stride=1, padding=1)
kernel = ICNR(conv.weight)
conv.weight.data.copy_(kernel)

out = conv(x)
out = nn.PixelShuffle(2)(out)

f:id:ejinote:20190728162641p:plain
Conv2d(ICNR)→PixelShuffle

checkerboard artifactは出ていないことがわかります。

ICNRで初期化したConv2dを適用した後にPixelShuffleで拡大を行った場合、畳み込んだものをNearest Neighborで拡大したのと同様の処理が実現できることが確認できました。

まとめ

ICNRを利用することで、学習の初期からcheckerboard artifactを抑えて画像の拡大を行えることを確認しました。

この記事は技術アウトプットもくもく会の成果物です。ご参加いただいた方々、ありがとうございました! 次回もたくさんの方に参加いただけると幸いです。

実験に使用したnotebookはGistにアップロードしてあります。

Sub-Pixel Conv with ICNR · GitHub

Sub-Pixel Convolutionについて#5【画像処理&機械学習】論文LT会!で発表しました

エルピクセル株式会社で開催された #5【画像処理&機械学習】論文LT会! で発表しました。 題材に選んだのはSub-Pixel Convolutionで、関連する論文をいくつか紹介したという感じです。

ちょっと前だけど定番な論文から最新の論文まで、幅広い論文が紹介される良い会でした。運営のfam_taroさん、okamotoさん、ありがとうございました。 次回は残念ながらすでに締切が過ぎているようですが、次次回以降でタイミングが合えばまた参加させてください!

資料はSpeaker Deckにアップロードしています。7分の発表枠だったのですが、文量の調節をミスってだいぶオーバーしてしまったので反省です。

他の方の発表メモ (資料は随時追加します)

When Does Label Smoothing Help? (Appianさん)

  • よく使われる割にはあまり理解されていないよね
  • penultimate layer(dense layerの1つ前)の出力を可視化して確認
  • hard labelを使った場合logitが極端な値を取るし、間違ったラベル同士もかけ離れてしまう
  • knowledge distillationとの組み合わせはよくない
  • データの種類に関する言及はあったか?
    • ラベルノイズがある場合、学習に寄与すると考えられる
  • 情報量が失われるというのは、2次元のmappingを見てのことか?
  • label smoothingは他のラベルの情報も持たせているのだから、分布は広がるのでは?
    • lossが極端な値を取らないので、penultimate layerも広がりが小さくなる

Unreproducible Research is Reproducible (紺さん)

  • 再現性を細かく定義した
  • シード、データセット、ハイパーパラメータ、順番などを変えると結果は大きく変わってしまった
  • 1つのシードで比較しただけだと結論は出せない
  • exploratory researchが多いが、empirical researchが増えるべき
  • この論文にネガティブに引用されている論文はあるか?
    • この論文中にはないが、そういう言及をしている論文もある
  • ばらつきを考慮できる評価指標があるといいですよね
    • random seed averageはよくやる

Move Evaluation in Go Using Deep Convolutional Neural Networks (msnrさん)

  • Alpha Goの前身となる論文
  • CNNで盤面状態を評価する
  • 現在の状態の評価値と、次に取るべき行動を出力する
  • 参加者の段位を持つchennelが存在するところが面白い
  • 段位をchannelで表現するメリットはあるのか?
    • アーキテクチャをいじるアプローチではなく、汎用的に使えるアプローチを好んでいるのではないか

Gait Recognition via Disentangled Representation Learning (twtwrさん)

  • 歩き方は人に固有
    • ユーザーの協力が不要で、遠くから判定できるが、服装や手荷物に大きく左右される
  • 外観と歩様を分離するアプローチ
  • 以下の3つの部分からなる
    • 歩様特徴から画像を復元
    • 歩様特徴に外観特徴が流れ込むのを抑制する部分
    • 別の人物を識別できるようにする部分
  • 人間的にはもつれていても、モデル的にはもつれていないことがあるのでは?
    • 最初に「これが異なっていても同じに分類されてほしい」というような願望がある。それにあわせていくためには情報を分離する必要がある

Interpretation of Neural Networks is Fragile (klnWさん)

  • NNの予測に対する解釈性へのAdversarial Attack
  • 予測結果を保ちつつ、解釈だけを変更することができる
  • 法律・医療など、意思決定を重視する領域では重要
  • DNNの決定境界は区分的に線形なので、ロスに対する勾配の向きを変えることが容易
  • どの次元が寄与したかだけではなく、どの学習データが予測に寄与したかという解釈もハックできる
  • オリジナルとの非類似度が大きくなるように更新し、距離が大きくかつラベルが一緒になるものを採用
  • じゃあどうすればいいのかも付録に書いてある
  • 自然に乗るノイズでも判断根拠がブレることが起こりうるか?
    • あり得る。今出ている特徴マップがたまたま出ている可能性があることを考慮しなければいけない

Mask Scoring R-CNN (fam_taroさん)

  • bounding boxが綺麗についていて、予測も正しいのに、セグメンテーションがうまくいかないケースがある
  • 分類の質とマスクの質は相関がなかった
  • Mask R-CNNにマスクのIoUを予測するサブネットワークを追加して精度向上
  • セグメンテーション一般で評価指標を予測するサブネットワークを追加するアプローチは有効かも
  • dice lossを追加するのとは何が違うか分からない

Learning to Generate Synthetic Data via Compositing (phalanxさん)

  • 自然な合成画像を作る手法の提案
  • 画像を合成するネットワークと、合成された場所を見破るネットワークをE2Eで学習
  • 本物の画像と合成画像を見分けるdiscriminator
  • synthesizer networkは前景をどう変換して重ねるかを出力

Distilling the Knowledge in Neural Network (kaerururuさん)

  • アンサンブルモデルの出力を蒸留したら軽量モデルで表現可能
  • 教師生徒の両モデルについて、温度付きsoftmaxのKL divergenceが小さくなるように学習を進める
  • 温度付きを使うのは、どのクラスとどのクラスが間違いやすいかも学習したいので、温度パラメータをつけることで出力をマイルドにする
  • 温度はどう決める?
    • 論文中ではいくつか試して選んでいた

【質疑応答付き】Kaggle Tokyo Meetup #6 に参加しました

f:id:ejinote:20190713175727p:plain

DeNAで開催された、Kaggle Tokyo Meetup #6の参加記です。YouTube配信の視聴を含めるとMeetup参加は3回目ですが、回を増すごとに情報量も発表内容の多様性も増しているように思います。

本当にすばらしい発表を皆様ありがとうございました。僕も発表やLTでコミュニティに貢献していきたいと思います。

この記事では、各発表について僕自身が面白い・知らなかったと思ったポイントを中心にまとめ、可能な限り出典などのリンクをつけています。 内容を網羅しているわけでは必ずしもありませんので、もとの資料を併せてご覧になることを強くおすすめします。素晴らしい資料なので。

それでは、15000文字を超える長い記事ですが、最後までお読みくださると幸いです。

Opening Talk (threecourseさん)

  • イキっている人もちゃんとバリデーションを切っている
  • Kaggle Masterもまぁ間違える。カバーしている知識も違う
  • いまはソリューションの発表が多いが、それはそちらのほうが準備が楽だから。Tipsなども歓迎。アウトプットしていきましょう

Petfinder 2nd Place Solution (Wodoriチーム)

  • 特徴量作成から学習、予測まで2hに収めるkernel onlyコンペ
  • 3種類の特徴量を作成し、4モデル(NN/LGBM×2/XGBoost)のridge stacking
    • LGBMしか使っていない人が多かった。モデルの多様性が差別化ポイント

takuoko part

  • テキストの処理
    • 前処理を施したあと、BOW/tf-idfをして、それを行列分解にかける
    • できるだけembeddingにおさめて、embeddingの平均を特徴量にした
  • 画像の処理
    • Kerasのdensenet121とInceptionResNetV2を採用
    • KerasとPyTorchで精度が全然違う
  • テーブルの処理
    • 基本的なアグリゲーション
    • 平均との比、平均との差などの特徴を作成
    • カテゴリの共起を取り、行列分解
    • 交差項の作成
    • 絵文字の情報やマレーシアの州の情報などをexternal dataとして利用
  • Kernelは間違っていることもあるので、自分で考えよう
    • (これはほんとそう!)
  • 特徴量は合計4000-5000ほど作成。importanceのTOP1000を利用
  • NNはAdam/CLRを利用

kaerururu part

  • CNNの出力、doc2vec、tfidfを利用した
    • これらはすべて高次元。低次元にいろいろ潰してみて、スコアが伸びたものだけを利用
  • 画像のサイズ、幅、高さを特徴量にする
  • 「cute」で検索して出てきた犬猫画像データセットで学習したモデルで予測したcute特徴を入れたが、効かなかった
    • クレンジングが足りなかったからでは?
    • (アイディア自体は面白いので、外部データを利用できるコンペではやってみるといいかも?)
    • (そこそこめんどくさそう)

gege part

  • はじめてのコンペだった(!?)
  • Kernelをベースに粛々と進めた
  • testっぽくないtrainデータを10%程度削ったが、精度向上はしなかった
  • 基本なにしてもダメだった

ynktk part

  • 4モデルをstackingした
    • LGBM < Average < Ridge だったのでRidgeを採用
  • Ridgeに入れる前の前処理でランク変換を行った
    • foldごとに予測値の分布が異なりがあったのでは?
    • ランク変換によって予測値分布の差を吸収
    • QWKは閾値に敏感。予測分布の差があると悪影響がある
  • 後処理
    • ImageHashを使って重複画像を探索→train/testで重複している画像はtargetで置き換える

u++ part

  • 泥臭いこと担当
  • クレンジング
    • 綴りの間違いを人力で修正

質問

  • 1位との大きな差はなに?(smlyさん)
    • まじでわからん
    • 外部データが効いたらしいが、再現してみたら全然効かなかった
  • ultimate model作ろうとしたらいまのtrainにoverfitするんじゃ?(smlyさん)
    • 今はロバスト/lightweightなモデルを作ろうとするムーブはあんまりない
    • あくまでボランティアとしてやっているので、他の参加者もそこまでモチベーション高くはない
  • interaction featureは何を意識して作ったの? 普通はビジネスセンスが必要(smlyさん)
    • 今回は総当たりで効きそうなのを試した。列が少ないからいける
    • 全然効いていない特徴量は総当たりの対象から外した
  • ods.aiに有用な情報はあった?(koukyoさん)
    • petfinderのときには、ods.aiにしかない情報はなかった
    • これが話題だから見よう、みたいな情報は取れた。取れてしまった
  • テキストの情報をクラスタリングしたら効く、みたいな話があったが、やった? (pocketさん)
    • やってないです
  • 閾値が大事という話だが、どう決めた? (pocketさん)
  • 実際閾値はprivateでも最適だったの?(onoderaさん)
    • 検証はできていない
    • QWKが0.4くらいになるので、それって全然あたってないよね。タスクとして難しかった
  • 各FoldでQWKの閾値はどれくらい変わるのか? データの分布が違うと閾値はかなり敏感にスコアを変えるのでは? (maxwellさん)
    • ログとしては取っているが、詳しくは調べていない
    • RescuerIDを利用したGroupKFoldを利用した
    • 最終サブミットはFoldの切り方を変えた2つを提出した

iMet 7th Place Solution & 画像コンペのアプローチ (phalanxさん)

壺コンペソリューション

  • 推論だけKernelで回すタイプのKernel Onlyコンペ
  • 2nd stageでテストデータが5倍になるので、それを考慮して提出しなければいけない
  • アノテーションがまぁまぁ雑。ラベルが欠けている画像が多くある
  • class imbalanceがある
  • モデルをひたすら積み続けた。ResNet34も最後まで生き残った
  • ラベルごとに最適なモデルが違ったので、アンサンブルが効くと思った
  • cultureとtagで根本から別々のモデルにした
    • Grad-CAMを見ても見ている画像の部分が違う
    • 全結合層だけ分けるのが普通だが、それだとあまり上がらなかった
    • すべてのモデルにこれをやると時間が足りないので、強いモデルだけやった
  • 蒸留を頑張っていたけど、効かなかった
    • 蒸留をがんばればモデルが小さくなるので推論時間を稼げるのでは?
    • attention transfer (activation-based method)を使った
    • studentのattention mapをteacherのattention mapに近づける手法
  • focal lossとlovasz lossを採用したが、ほんの少し良くなっただけ
  • 頻度が少ないクラスはdropしたが、意味がなかった
    • 過去にGibaがやっていた
  • 長い画像には特に何もせず、resizeして突っ込んだ
    • 上位の人を見ても対処している人はいなかった
  • CNNでstackingした
    • 過去コンペでKeepLearrningがやっていた
    • 1000クラスあるので、全部ridgeはやってられない
    • CNNでモデル間の相関を学習し、denseで特徴間の相関を学習する
  • チームメイトの予測をスタッキングに載せた
  • 1st place solutionの紹介
    • batchsizeを1000-1500と大きい値を設定(ノイズの軽減?)
    • 誤差が大きい画像を弾く
    • ImageNetのpredictionや画像の長辺の長さなどの特徴をLightGBMにかける
  • psuedo labelingとhard example miningをちゃんとやれば精度が上がった

画像コンペのアプローチ

  • yamlを書いたら全部走るpipelineがある
    • 壺コンペはyamlを書き換えつづけるだけ
  • 初日
    • ルールとかOverviewとかをちゃんと読む
    • mean, std, min, maxをRGB, HSVのチャンネルごとに確認する
      • めちゃくちゃ明るい/暗い画像のチェック
    • 画像サイズのmean, std, min, maxなどを確認
    • targetの分布を確認
    • 画像を目で見る
    • resnet18, 34などの小さいモデルを作った後、resnet101, 152に進む
    • optimizerはAdamを使う。 3e-3 〜 1e-4 の範囲をコンペによって変える
    • image_sizeは (mean/2, mean/2) , (mean, mean), (mean*2, mean*2)を試す
  • ベースラインの予測を作ったら、予測を確認する
    • CVとLBの違いや、attentionを可視化
  • サーベイ
    • ドメインの論文が効くことがある
    • 読むだけじゃなくて実装もする
  • パイプラインは作ろう
  • 時間を効率的に使う。学習回している間に論文を読んだりコーディングをしよう
  • 終盤
    • ドメイン特化の論文を読む(10%)
    • アンサンブルに備えていく

質問

  • ラベルが信用出来ないとき、ルールで許されていたらハンドラベリングしたりするか?(kaerururuさん)
    • 1103クラスに対してはハンドラベリングはだるすぎるのでやってない
    • 今回はpseudo-labelingをやれば十分だった
  • optimierをAdam固定にはどんな意図があるか?(koukyoさん)
    • そこは本質的な価値じゃないので、Kagglerとしては本質的なところで戦うべき
  • 蒸留がうまくいかなかったのはなぜ?
    • 予測に対してL2ノルムで最適化した。しかし、出力が小さいところまで合わせる必要はなかった
    • 今回はpseudo-labelingで十分
  • 早い段階からたくさんモデルを作るという戦略か?
    • 最近のコンペはだいたい、多くのモデルを混ぜればうまくいく
    • 今回は特にラベルごとに最適なモデルが違った。ちゃんとそれを確認している
  • CNNでアンサンブルするとき、モデルの並べ順によって差が出るのでは?(Jackさん)
    • 学習時に順番をぐちゃぐちゃにしても学習可能なのでよくわかりません
  • パイプラインについて。1080TiとKaggle Kernelで両方実行可能にするのはどうする?(flowlightさん)
    • Kernelで実行する時は、モジュールをべた張りしている
  • pseudo-labelingについて工夫を教えてほしい(u++さん)
    • LBが最も高くなるような閾値で切ってpseudo-labelとして使う
    • もともとのラベルをhard-label、pseudo-labelをsoft-labelとする。soft-labelの方はlossの寄与を小さくする
  • phalanx-pipelineはどうやって完成した?(koukyoさん)
    • segmentation/detection/recognitionでそれぞれパイプラインがある
    • detectionはmmdetectionというライブラリがあるので、それに似た形にしている
    • コンペごとに進化していっている
    • 作り始めたのはタンパク質コンペのとき。新しいタスクに挑戦する時は、最初はパイプラインが崩壊することもあるけど、そうしたら組み直す

Quora Insincere Questions 10th Place Solution & 昔話 (tksさん)

Quoraコンペの解法

  • 外部データ利用不可のKernel-Only
  • Embeddingが4種類与えられている
    • これをどう使うかがひとつのポイント
  • BERT発表後初めてのNLPコンペ
  • モデル構造はかなりシンプル
    • 層を複雑なモデルを作ったことはない
    • 小さいモデルをアンサンブルさせてスコアを取っている
    • Embeddingの組み合わせで4C2=6個のモデルをアンサンブルしている
  • CVをきちんとすることが勝利の秘訣だった
  • 最初からaveragingすることは決めていたので、averageでのスコアで評価
  • モデル構成が定まるまではtrain/dev/valの3分割を5-foldで行う
    • trainで学習、devで閾値選択、valで評価
    • ここで閾値を何種類かに絞っておく
  • スペル修正はしなかった(面倒だったので)
  • ラベルノイズも多かった
  • モデルの安定化のため、Exponential Moving Averageを利用する
  • Embeddingの扱い
    • concatすると次元が大きくなってしまうので、重み付き平均を使う
    • Projection Meta Embedding
      • concat後低次元に射影して、ReLUする
  • 実行時間制限が大切
    • EMAの更新回数を減らした
    • 長さが近いものを同じバッチに入れると早くなるが、トライしなかった
    • そんなに気分が乗らなかったからだと思う
  • 反省点
    • 長さが近いものをバッチに入れる、は最初に実装すべき
    • statistical feature (質問の長さ、大文字だけの単語数、など)を入れておけばよかった
    • 早期に選択肢を狭めている
  • Local CVを信じれば、たまに良い順位に入れる

昔話

  • Kaggle歴5年以上の人どれくらいいる?→ほんの少し
  • Submission Limitも変わっている。個人的な意見としてはFinal Submissionは1個にしてほしい
  • なにか問題があったら、オープンなフォーラムで話し合う文化は昔からあった
  • 要望・提案があればどんどん出していきましょう

質問

  • QuoraのEMAについてもう一度説明してほしい
  • EMAは学習率を単純に下げるのとは違いがあるのか?(upuraさん)
    • 自分はoptimizerは据え置きでやるようにしている
    • BERTではEMAは全然効かなかったので、チューニングは必要
  • 同じ長さの文を同じバッチに入れるとなぜ早くなるのか?
    • 長さをまとめなかったら最大長でpaddingする必要がある
    • 同じ長さでまとめたら、バッチ単位でpaddingすることができるので早くなる
    • 精度はほとんど変わらないはず
  • Freesoundでやったとき、paddingが長すぎると精度が下がりました(osciiartさん補足)
  • 出るコンペはどういう基準で選んでいる?(koukyoさん)
    • 基本、簡単そうなやつ
  • 今と昔だと上位に行く難易度に違いはあるのか?(pocketさん)
    • 昔の方が断然簡単だった
    • 昔はいけたけど、今は悩んでいる人はたくさんいると思う
    • 昔はツールを作ってるリサーチャーが多かったからそれに勝つにはツールを作るしかなかった(smlyさん補足)

(おまけ)僕の参加記

amalog.hateblo.jp

PLAsTiCC 3rd Place Solution (nyanpさん)

公開してくださっているGitHub

解法

  • 特徴量エンジニアリングが好き
  • 突発天体・変動天体のように、明るさが変わるような天体を見つけたい
  • いままでは漏らしていたけど、LSSTの運用で発見できるようになるはず
  • これまで人類が発見した天体は1万くらいしかないのに、LSSTは10年間で1000万程度発見してしまう
  • 突発天体を早期検出して、後続の観測機器で精度良く観測する
  • LSST自身でも自動分類したい
  • Light Curveから天体を特定する多クラス分類
  • かなりimbalanceなデータセットで、少数クラスは30件程度
  • minority classほど1データの重みが大きいので、sample_weightなどで補正しないと良いスコアが出ない
  • 超新星の爆発のときには観測ができていなくて、残り滓しか見えないようなケースもあるので難しい
  • trainは既存の観測データ、testはLSSTが観測するもの、という問題設定だった
  • ノイズの大きい観測データをどうするかが争点
    • Gaussian Process
    • NN
    • Template Fit
  • Class 99をどうするかもスコアを大きく左右したが、Kernelに準じても金メダルは取れた
  • LSST Science Bookという文献を読むことで、ドメインのエキスパートがどこに注目して分類しているかがわかった
  • マージした時点でnyanpさんは200特徴量だったが、mamasくんは80000個作っていた(!?)。yuvalは1個も作っていなかった(!?!?!?)
  • CNN、LightGBM、CatBoostのアンサンブル
  • CNN
    • 欠損を線形補間/detected=1だけ抜き出して線形補間/最近傍の有効データとの時間差 をCNNに突っ込む
    • 1DConvを数回行い、GlobalMaxPoolingにした後、メタデータの特徴量とくっつけてDenseに通す
    • 時間方向のshiftについてクラスは変わらないはずなので、CNNが効きそうだし、augmentationとしても使える
    • 特徴量なしでも金が取れた(!?)
  • Template Fitting
    • 遅い。テストデータに対しての計算は30日くらいかかった
    • 並列化が効かなかったので、インスタンスを30個立てて30倍速にした
    • コマンドは心をこめて手打ちした
    • sncosmoというライブラリで試せるものだけで数十個ある
    • 全部やった。CVであたりをつけてから、よいものを試した
  • preemptible instanceの牧場管理をがんばった。最終的には60個まで増えた
  • Gaussian Processも試した。時間がかかるのでやっぱり30インスタンス立てた
  • tsfreshやfeetsといった時系列の特徴抽出ができるライブラリを使った
    • ベースラインとしては使える
  • pseudo-labeling
    • class 90, class 42に絞ってラベルを付けた
    • class 99はtestにしかなく、class 99に間違ったpseudo-labelをつけると大きくスコアを落としてしまう。class 99と遠いクラスのみラベルを付けた
  • Adversarial Pseudo Labeling
    • training dataに似ているサンプルを使ってtraining
  • クラスごとに異なる重みでアンサンブルした
    • OOFのpredictionの精度で決めた。サブミット数が残り少なかったため
  • LB Probingでclass 99を決めた
    • one-class SVMなどを利用した通常の異常検知はうまく行かない
    • class 99はどんな天体なのか考えた
      • class 99はすべてのクラスから均等に遠いことはないはず
      • クラスごとに異なる重みを付けてみた
  • モデルの方向性がみんな全然違ったのが良かった

質問

  • Template Fittingのハイパーパラメータはどう決めた?(akiyamaさん)
    • コードが見たい人はopenにしているkernelを見てほしい
    • 時間がなかったので、あまり調整はしていないが、一部のパラメータはちゃんとlsstと設定しないといけない
    • Fittingによって出てくるパラメータをそのまま特徴量として使う
  • 1位との違いは何ですか?(u++さん)
    • 1位はdata augmentationをやっていた。これが一番の差分
    • train dataをtest dataの分布に合わせるため、遠方にシフトさせるaugmentation
    • これをやっていれば1位いけたかも
    • 上位解法のばらつきが大きく、上位の答えをアンサンブルをするだけでスコアが上がる
  • サーバー代はいくらですか?
    • 8コアくらいのcheapなインスタンスをたくさん立てた。トータル5万くらい
    • Seed Averageのために立てたインスタンスを止め忘れ、7万くらい請求された。悲しい
  • CatBoostはなぜ強かった?
    • データにカテゴリ変数はぜんぜんなかった
    • かなりoverfitしやすいデータだった。CatBoostに含まれているsymmetric treeとordered boostingという機構がコンペにマッチしていた
    • ordered boosting
      • t番目のデータに対する残差を計算するとき、t-1番目までのデータで学習したモデルを使う
      • サンプルが少ないときに特に有効
      • 比較した結果としても、ordered boostingが良かった
    • 使う特徴量によってLightGBMとCatBoostでどちらが良いかは変わった
    • 最近はCatBoostも使いやすくなっているので、スモールデータコンペだったら試す価値がありそう
  • データ数が少ないとき、NNはoverfitしやすい。augmentationはどう選んでいる?
    • そのクラスは何に対して不変なのかを考えるべき。cyclic shiftは自然な発想
    • 観測ノイズが載っているので、ノイズを乗せても良さそう
    • そんなにアクロバティックじゃないとは思う
  • psuedo-labelingについて。コードは公開している? OOFでやるなど実装方法もいろいろあるが、どれを使った?(pocketさん)
    • GitHubを公開しているので、どこかに埋まっているはず
    • ラベルを付けた数がtrainの10倍になるくらいにした。基準は実験的に決めた
  • Gaussian Processはどうした?(onoderaさん)
    • fittingして、そのまま特徴量として突っ込んだ。そんなに寄与は大きくなかった
    • 1位はGaussian Processでデータを補完してその波形上で集約して特徴量を作っていた

スポンサーセッション (hoxoshさん)

  • DeNAの事業は多岐に渡っていて、Kagglerが各地で活躍している
  • 合宿(magic camp)に行きました。今度も行きます
  • @DeNAxAI_NEWSをフォローしてください

Neural Network のご機嫌取りがしたい(tawatawaraさん)

  • テーブルより画像のほうがメダル取りやすいのでは?
  • batchsizeが小さいと一部のサンプルに引っ張られがち。batchsizeを大きくしたらlrも大きくする
  • 基本的にbatchsizeは大きく取りましょう
  • lrはLR-RangeTestで決めよう
    • fastaiのライブラリでlr_findとして実装されている
  • 学習率のスケジューリングは正直好みでは? warmupは有効だとは思う
  • 学習率が不変 or AdamならEarlyStopping
  • initializerはscaleを小さめに
  • TuningのためのCourseraもある

質問・コメント

  • fastaiのfind_lrはモデルやデータで良いlrは変わる?(osciiartさん)
    • chainerで自分で実装しているからfastaiのは実はわからない
    • 実際モデルやデータで変わりそうではある
  • scaleを小さくすると学習は安定するが、結果はscaleが大きい方が結果は良くなりそう。回数を打てるならscale大きいほうがよさそう(owrubyさん)
  • batchsizeが大きすぎると汎化性能が下がるのでは? BERTだとそのためのoptimizerがある

kagglerのためのAllenNLPチュートリアル (tamakiさん)

資料

内容

  • 最近はテキストが有害かどうかのコンペが多い
  • かなり分割がうまくいっていて、書いていて気持ちいい
  • DatasetReaderがテキストファイルからInstanceのリストを返してくれる
  • Modelがtorch.nn.Moduleのサブクラスを返す
  • AllenNLPはjsonから実験ができる

質問・コメント

  • NLPコンペで初心者が詰まりがちなところを教えてほしい(u++さん)
    • NNと同様で、学習率どうする?みたいなポイントはある
    • ベースラインを作るまでにはハマりポイントはあんまりない。それ以降何をするかが大事

Freesound Audio Tagging 2019 4th Place Solution (oumedチーム)

  • 医学部6年なので、実はKaggleしてる場合ではない
  • domain adaptationも必要
  • 人間の聴覚はlog-scaleなので、それを反映したlog-melspectrogramが主力
  • スペクトル画像に変換したらほぼ画像分類として扱える
  • 時間方向に圧縮すると意味が変わってしまう
  • 波形とlogmelの両方使った
  • 波形についてはEnvNet-v2を使った
  • MixUp/BC learning
    • 画像と違い、音声は2つの音声が混ざるのはかなり自然
  • cropするより、全長を使ったほうが良かった
    • 最初の方にクラスを決める要素が多かった
  • noisyの使い方がポイントだった
    • 多くの参加者はpretrainとして使ったが、OUMedではマルチタスク学習として使った
  • soft pseudo-labeling
    • マルチラベルに対応できないし、分布の差によって信頼性が高いラベルが得られない
    • 疑似ラベルを0, 1にしない
  • 長さの異なるモデルを複数用意してaveragingするのが有効だった
  • 外部ラベルデータダメなのにハンドラベリングOKだった→1位はそれ
  • 2位はlogmelの変換もlayerとして入れて、パラメータ探索した
  • 2位は時間軸方向はGlobalMaxPooling、周波数方向はGlobalAveragePooling
    • 意味合い的にも妥当
  • Kaggleだと半教師付き学習はpseudo-labelingが最強だよね
    • 論文で言ってるpseudo-labelingはKaggleのpseudo-labelingは全然違う
    • biasがかかっていた瞬間に論文のpseudo-labelingは死ぬ
    • Kaggleのpseudo-labelingは蒸留に近い

質問・コメント

  • BC learningについて。もとはマルチラベル対応ではなかったのでは?(koukyoさん)
    • このコンペはほぼシングルラベルみたいなものなので、えいやでやってしまう
    • powerだとそのままmixupしていいけど、dbでmixupするとおかしくなる
  • マルチタスク学習について。どういう学習方法を使っている?(koukyoさん)
    • noisy/cleanはそれぞれに対応したheadを使っている
    • 推定は別々でやって、backpropは同時にやっている
    • lossの足し合わせは1:1で行っている
  • 1次元側の工夫はあるか?
    • 基本は論文の実装をそのまま使った
    • 単体ではあまり精度は高くなかったので、あくまでアンサンブルの材料
    • 得意なクラスが違ったかも
  • 半教師付き学習について。本来は十分教師がない状況に使うためのものなのでは? 今年のlandmarkコンペでは半教師付き学習が使われている(smlyさん)
    • 適切な目的のところでは半教師付き学習は使える

Large-scale Landmark Retrieval / Recognition under a Noisy and Diverse Dataset (smlyさん)

  • 巨大なデータセットに対して学習
  • 半分以上のクラスが10枚以下というimbalanceなデータセットで、しかもノイズが多い
  • single modelでもbestfitting以上が出せるので、アンサンブルしないと勝てないのは甘え
  • 画像検索で大事なのは2つしかない
    • ArcFaceなどのcosine based softmax lossを使え
    • データセットをキレイにしろ
    • 識別モデルを検索のre-rankingに使え。決定境界から遠いものから順にrankingする
  • データセットをキレイにする
    • 去年のデータセットはキレイだったので、それをベースにクレンジング
      • (そもそも去年のコンペに参加していないと難しい)
    • 近傍を取ってきた後、spatial verificationでキーポイントが保存されていることを確認する
  • 1回recognitionのタスクを解き、ラベルが一致するものを上位に置く

質問・コメント

  • 計算リソースはどれくらいですか?(osciiartさん)
    • pairwiseの学習だとリソースがたくさん必要だが、ArcFaceなどならV100×1×1日くらいで済む

Santander Customer Transaction Prediction 2nd place solution (onoderaさん)

  • すべての特徴量が連続値で、正規分布していて、positiveとnegativeで分布が違う
  • fake rowsを抜いてcount encodingするだけで銀圏に行った
  • roundしてcount encodingしたらめっちゃ上がった
  • ゼルダの続編が開発されている

「結局、Kagglerは何を必死にやっているのか?」というLTをしました

弊社では毎週、新卒LT会が開催されています。 エンジニアがメインですが、同期が職種を問わず広く集まる場になっています。 僕もなにか話したいと思い、7/5(金)に発表しました。

タイトルは「結局、Kagglerは何を必死にやっているのか?」です。

スライドはSpeakerDeckにアップしていますので、何かに使いたい方がいらっしゃいましたらぜひどうぞ。「使ったよー」って言ってもらえるとめちゃめちゃ喜びます。

LTをしようと思ったきっかけ

「Kaggle」や「Kaggler」という単語はデータサイエンス界隈では通りが良くなってきており、Kaggleについて詳しく知っているという人も多いでしょう。

しかし、ビジネス職の方はKaggleについて知らないという方も多いですし、「Kaggle」という言葉を聞いたことがあっても、何が行われているのかきちんと理解している人は少ないのではないでしょうか。

Kagglerが適切に評価され、活躍していくためには「なんか内輪でワイワイやってる連中でしょ」という立ち位置から抜けていくことが大切だと考えています。 そのためには、Kagglerの得意なことや、どのような形で事業に貢献できるのか伝えていくことが重要なのではないでしょうか。

これがマジメな理由です。

マジメじゃない理由としては、「Kaggleってなんなの?」って聞かれたときに「ほらこれ見て」って言える資料を作っておきたかったという感じです。 Kagglerのみなさんはn回この質問をされているでしょうから、この資料が何かの助けになれば嬉しいです。

(おまけ)スライドを作るときに気をつけたこと

  • 聴衆が誰かを意識する
  • 話す目的が何かを意識する
  • 太くて大きい文字を使う
  • 真っ黒い文字は圧が強すぎるのであまり使わない。#333333くらいが個人的には好き
  • 線や矢印など、情報が少ないものは薄く表示する
  • Unsplashでキレイな画像を取る
    • 「laptop」「business」「mountain」とかはかなりそれっぽい
  • icooon-monoのアイコンを使う
    • アイコンの色は文字色に合わせる

なぜn_estimatorsやepochsをパラメータサーチしてはいけないのか

f:id:ejinote:20190630174727p:plain

ハイパーパラメータを探索するため、グリッドサーチやOptunaなどを利用することがあると思います。

しかし、「ハイパーパラメータ探索してみた」のようなQiita記事などでは間違って書かれていることも多いのですが、XGBoostやLightGBMの n_estimators ( num_boosting_rounds )やKerasの epochs をパラメータサーチの対象にしてはいけません。

いけません、というか、すごく無駄なことをしています

なぜ、n_estimatorsやepochsを探索すると無駄なのか

理由はシンプルで、これらのパラメータは「大きい値で精度確認する過程で小さい値の結果も分かる」からです。

LightGBMのn_estimatorsは構築する決定木の数を表しています。

f:id:ejinote:20190630173645p:plain

例として、n_estimators=5 (こんな小さい値で学習することはないですが、簡単のため)で学習を行ったとします。学習の過程で、n_estimators=1のスコアも、n_estimators=2のスコアも確認することができます。

f:id:ejinote:20190630173702p:plain

1, 2, ..., 5とn_estimatorsを振って確認した場合、合計15個の木を構築する必要がありますが、正しくやれば5個の木で十分です。単純計算で3倍、探索を高速化することができるでしょう。

n_estimatorsは学習率によっては5000程度になることもざらにあります。500, 1000, 1500, ... , 5000と500刻みに探索した場合、合計で27500個の木を構築することになります。本当なら5000個で済むのに。しかも、500刻みで探索していた場合、最適な点を見逃す可能性もあります。

Kerasのepochsに代表される、ニューラルネットワークのepoch数も同様です。

epochs=100で学習した場合、その過程で1epochから100epochまでのすべての学習状態を取得することができます。

では、どうすればいいのか?

一般的なのはEarlyStoppingを使用することでしょう。

テストデータとは別にバリデーションデータを用意し、バリデーションで対しての精度がサチったら(一定epochのあいだ向上が見られなかったら)終わりにするという方法です。

LightGBMのscikit-learn interfaceを使っているなら、eval_setearly_stopping_roundsを指定すれば動きます。n_estimatorsは大きめに取っておくとよいでしょう。

import lightgbm as lgb

params = {
    'n_estimators': 10000  # 大きめにとっておく
    # 他のパラメータは省略
}

model = lgb.LGBMClassifier(**params)
model.fit(X_train, y_train, 
          eval_set=[(X_valid, y_valid)], early_stopping_rounds=100)

scikit-learn interfaceを使っていないなら、lgb.train関数にvalid_setsearly_stopping_roundsを設定すれば動きます。num_boost_roundn_estimatorsと同様、大きめに取っておきましょう。

import lightgbm as lgb

train_set = lgb.Dataset(X_train, y_train)
valid_set = lgb.Dataset(X_valid, y_valid)
model = lgb.train(params, train_set, num_boost_round=10000, 
                  valid_sets=[valid_set], early_stopping_rounds=100)

KerasでEarlyStoppingを行うならkeras.callbacks.EarlyStoppingを使います。使う場合はkeras.callbacks.ModelCheckpointと組み合わせ、最も良いモデルを保存するようにしておくと良いでしょう。

from keras import callbacks

# モデルの定義とcompileは予めしておく

callbacks = [
    callbacks.ModelCheckpoint('best_model.h5', save_best_only=True)
    callbacks.EarlyStopping(patience=5)  # 5epoch改善が無ければ止める
]
model.fit(X_train, y_train, epochs=1000, callbacks=callbacks,
          validation_data=[(X_valid, y_valid)]

PyTorchなど、他のフレームワークの場合もEarlyStoppingの仕組みは実装されています。

まとめ

学習の途中経過が全て確認可能な手法を使うとき、n_estimatorsやepochsのような「学習回数」のパラメータを調整するのは時間がもったいないです。

他にもやりがちな例で各種ライブラリのverboseをチューニングしてしまう、というものがあります。verboseは学習中にどれくらいメッセージを吐き出すかというパラメータで、モデルの精度には一切影響を与えません。精度が変わらないので、もちろんチューニングする必要はありません。

機械学習モデルをチューニングする時はそれぞれのパラメータの意味を理解した上で行うようにしましょう。使っているアルゴリズムに対しての理解を深めることも助けになるでしょう。