子供の落書き帳 Remix

15/4/13:ひと月に一度更新するブログになってしまっている

DLLAB DAY 2018 ハッカソン部門感想 #dllab
2018/07/17(火) 01:02:30

6月21日、DLLAB DAY 2018(ハッカソン) @ 丸の内KITTEに参加してきた。

最初に言ってしまうと、あんまり満足の行く内容ではなかったので、以下の文章はけっこう批判的である。
このイベントはカンファレンス部門とハッカソン部門に分かれていた。
カンファレンスに参加者として登録したのは254人、ハッカソン部門に登録したのは64人であり、ハッカソンの状況を知る人は少ない。
ハッカソンのほうに参加して感想を書いている人はそれほど多くないようだったので、書いておく価値もあるだろうと思う。

概要



まず、どんなイベントか概要を書こう。
Preferred NetworksとMicrosoftが中心となって作った、DLLABというコミュニティがある。
公式ページには「ディープラーニングに関連する、開発事例や最新技術動向を情報発信するコミュニティ」と書かれている。
そのDLLABの一周年を記念して、東京駅のすぐそばのKITTEで開催されたのが今回の「DLLAB DAY 2018」である。「深層学習を使いこなす日」と銘打っている。
イベントの公式ページ DEEP LEARNING LAB | DLLAB DAY 2018

前述の通り、参加者は「カンファレンス部門」と「ハッカソン部門」に分かれる。
午前中に基調講演があり、これは両部門の参加者とも聴講できる。
昼休みを挟んで13:00~17:40までが別々になる。
カンファレンス部門の参加者は講演を聴く。(同じ時間に3つの講演が同時進行する)
ハッカソン部門の人は別室に移動となり、そこでハッカソンを行う。
なお、ハッカソンは更に「CV(Computer Vision)」と「NLP(Natural Language Processing)」の2つに分かれている。俺はCVに参加した。
運営が事前に、4~5人の組で1つのチームになるようにメンバー編成していた。

17:40以降は懇親会であり、再びカンファレンスとハッカソンの参加者が一緒になる。食べ物・飲み物が提供された。

事前課題


自分にとって不利な情報を隠すのはフェアじゃないと思うのでちゃんと書いとこう。
事前課題が与えられたが、あまりちゃんとやらなかった。
事前課題の中では、MNISTやCIFAR10をchainerでCNNを使って解くやり方を説明している。
ザッと目を通したが、自分の環境上で動かしたのは一部だけにとどまった。
直前にやり始めて時間が足りなかったこと、「chainerのtutorialは以前やったから大体分かるだろう」と考えたのがその理由である。


期間中に起きたこと、行動



課題は当日発表された。githubにも上がっている。
GitHub - DeepLearningLab/PotatoChips-Classification
説明資料はこちら。Deep Learning Lab Day 2018 - Hackathon Presentation
ポテトチップスの分類である。パッケージの画像から、その種類を当てる分類タスクであるが、画像がそっくりの物があり、そんなに簡単ではなさそう。

最初は講師の指示のもと、Dockerを使って全チーム一斉に環境構築……のはずだが、ここで問題が発生した。
Dockerを展開するのに必要な領域が不足していて、先に何チームかが環境を構築した時点でそれ以外のチームが構築できなくなったのである。
幸い、自分のチームは少しだけ早くDockerコマンドを打っていたので、ここでつまづくことはなかった。
(その後、運営スタッフが設定を変更したらしく、最終的には全てのチームが環境構築できた。自分自身は被害がなかったので、この点については不満を感じていない。しかし、懇親会で話をしたら「ハッカソン終了の30分前まで環境が構築できなかった」チームもあるらしい。)

画像分類ということで、まずはVGG16の転移学習を作ってみるのが良いかなという相談をチーム内でした。
運営側はchainerを使うと良いよという話をしていた(注:Preferred NetworksとMicrosoftのコミュニティによるイベントである)。
しかし、5人チームのうち1人は、Keras+Tensorflowの方が慣れているというので、それでコードを書き始めた。
俺はCNNのコーディングは殆どやっていなかったので、運営におとなしく従ってchainerで取り掛かった。
もう1人も同様にchainerで書き始めた。
5人のうち残り2人は、最初に自己紹介した感じではあまり深層学習の経験がないようだった。
特にチーム内で教え合うようなこともなかったので、おそらく何をすればいいか分からない手持ち無沙汰な状態だったと思う。
(リーダーシップを取る人がいなかったので、役割分担が全く無く、個人がめいめいに作業する形になったことは反省している。)

自分自身は1から転移学習のコードを書き上げる能力は無いので、
「chainer VGG16 転移学習」などのキーワードでググって、出てきたページからコピーペーストをして、何とか無理やりコードを書いた。
しかし、切り貼りのしかたを間違えたらしく、よくわからないエラーに悩まされ続けて終わった。
Kerasで書いていたチームメイトもコードがどこか間違えていたらしく、動くことは動いたものの学習が全くできていなかった。
最終的にはKerasの結果を提出した。

我々のチームは実質的に成果なしだったが、
全体で見れば最終的に何らかの学習モデルを提出できたチームが大半であった。
VGGとかResnetなどの転移学習で書いたチームもあるし、全結合の3層MLPで提出したところもあったと思う。

途中から「ハッカソン、こんなに放置されるんか……」という境地に陥った。
「今回のイベントはハッカソンなんだから、教えてもらうもんじゃない、参加者が能動的に動くものなんだ。
手取り足取り教えてほしけりゃハンズオンのセミナーに行けよ」と言われてしまえば確かにその通りなのだが。
(注:俺はハッカソン形式のイベントに初めて参加した)

事前予告との相違点



Dockerの環境構築失敗は予想外のアクシデントだったので、致し方ない部分もあると思う。
しかしながら、事前予告と実際とで異なっている点が2点あった。

connpassのページでは

運営側から提供するもの
・課題、ベースとなるNNモデル

と書いてある。しかし実際には、ベースとなるNNモデルは提供されなかった。

そして、connpassを通じて送られてくるメールには

・また、本番の課題ですが、イベント数日前に公開予定です。

と書いてあった。しかし実際には、課題は本番開始時に公開された。


特に問題なのは1点目だと思っている。
なぜなら、「入力から出力まで正しく動くニューラルネットワークのソースコード」があれば、
あとは機械学習のアルゴリズム部分の改良に専念できたからである。
しかし実際には「0からコードを書いてね」だったので、
「入力データを読み込み、機械学習のアルゴリズムに入力できるように変換する」部分を間違って書いてはエラーになる、ということを自分は繰り返してしまった。

(実際には上記の部分も必要であり、重要である。それは間違いない。
しかし、例えばkaggleのコンペの期間は数ヶ月あるが、今回のハッカソンの期間は4時間程度である。
しかもその4時間の中に環境構築の時間も含まれている。
時間の短さを考えれば、この部分は正解を与えておき、調査や試行錯誤やミス修正に要する時間を省くべきではなかったか。)

疑問に思った点


そろそろ収拾がつかなくなってきたので走り書き。

connpass説明より

・17-18時は各チームの成果発表(2分ずつ)、その後、専門家からベストプラクティスを紹介いただきます。

→正解例のコードはgist上のを見せてもらったけど、
「中身の説明はしませんので、各自で読んでください」だったのでそれは「紹介」なのか?

もし運営側がこの記事を見ていたら、お願いがあります。
正解例のコード、確かgistのプライベートリポジトリだったと思うのですが、URLを資料の所に置いてもらえませんでしょうか。
URLをメモったのですが、間違ってPCの電源を落としてしまってメモを無くしました。



- Example から一歩進んで、実際に深層学習を使う方法を学ぶことができる

→今回は何を学んだというのだろう……

コードをコピペして繋ぎ合わせる力を学んだ、とかですかね……?
(繋ぎ合わせるの結局失敗したけど)

ハッカソンはハンズオンではないので、「教えてくれる人がいて、教材があって、そこから学ぶ」ではない。
「何も教えないので勝手にやって」で学ぶとしたら……他のチームメイトから学ぶ、ということだろうか?




事前課題から比べて、難易度が一気に高くなったな、と思った。
より具体的に言うと、機械学習アルゴリズムの手前の段階が必要だということである。

chainerだとget_mnist関数を使って一発でMNISTのデータをロードできる。
他の深層学習フレームワークもほぼ同様である(たぶん)。
また深層学習以外では、scikit-learnにはload_irisなどの関数があり、サンプルデータを関数1つでロードすることができる。
これらは大変便利ではあるのだが、慣れすぎてしまうと、いざ他のデータを入力すると苦労する羽目になる。
機械学習モデルに入力する前の段階も、ちゃんとできるようにならなきゃいかんな……と、今回のイベントで痛感した。



最後に一つ。
Dockerによる環境構築失敗に対して
「色々と(トラブルが)ありましたが、進めますね」という言い方が何度かあったことである。
金を返せなどと要求するつもりは別に無い。
せめて「ご迷惑をおかけしました、すみません」という一言が欲しかったと思うのである。、
そういう台詞はついぞ聞くことが無かったし、無かったせいで心象がより一層悪くなってしまったので、今こうして書いている。

参加費との釣り合い



無料~低価格のイベントならば、「ま、しょうがないか」と納得することもできた。
どうにも釈然としないのは、このイベントの参加費が10000円だったからであろう。

PyConとかRubyKaigiとかに出たことなかった俺には
イベント一発で1万円は余裕の過去最高金額であった。
scikit-learnとTensolFlowの本を買うときもいくぶん躊躇してたけど、その2倍以上する。
俺は個人的にイベントに申し込みしていて、会社から費用を出してもらっていないので、つまり自腹である。
自腹を切って行った結果がこれか……!!
(余談であるが、「会社から費用を出してもらった」「上司に『勉強しに行ってこい』と言われて申し込んだ」という人も多く、普段俺が行くような勉強会とは客層がやや違っていたように思う。)


ブレインパッドとかキカガクとかのハンズオンセミナーで手取り足取り教えてもらおうとすれば、
1万円なんてものでは済まない。
(機械学習による問題解決実践 (データサイエンティスト入門研修) | データ活用人材育成サービス by BrainPad:2日216000円)
(ディープラーニング ハンズオンセミナー | 株式会社キカガク:3日216000円)
それに比べりゃ遥かに安いと思うべきなのか。

ちなみに、dllabのイベントがいつも高額というわけではない。このイベントの次の週にもイベントがあった。
Microsoft Machine Learning Meetup - connpass
この参加費は500円である。……ちきしょー。
ええ、分かってます。
普段は品川のマイクロソフト本社で開催するから会場費がかからないんですよね。
それと比べて今回のDLLAB DAY 2018は東京駅近くの会場を借りたから会場費がかかっています。そのためには参加費を上げる必要があったんですよね。

ハッカソン参加者の感想レポート


他のハッカソン参加者の感想レポートを見つけたので、最後に貼っておきます。

DLLAB DAY 2018 ハッカソンに参加してきた - OKKAH NET
DLLAB DAY 2018行ってきました | 彌冨 仁研究室
DLLAB Dayのハッカソンに参加してきたよ(実装編) - テキトー
  1. 2018/07/17(火) 01:02:30|
  2. プログラミング
  3. | トラックバック:0
  4. | コメント:0

sedでスペースをタブに置換 (連続スペースは1文字とみなす)
2018/07/08(日) 12:57:29

きっかけ


Linuxのmpstatで取ったパフォーマンスの記録をExcelに貼り付ける必要があった。
Excelでは空白区切りを認識しないので、空白(半角スペース)をタブに変換したい。
このとき、連続する空白は1つのタブ記号に置換したい。
(連続しない1つだけ単独の空白も1つのタブ記号に置換したい。)

Linuxコマンドのsedを使ってやってみた。
(Excelの「テキスト ファイル ウィザード」を使えば可能ではあるが、GUIで大変なので)

環境 (sedのバージョン)


GNU sed、BSD sed、POSIXとかで微妙に挙動が違うらしい……

BSD sed などに代表される POSIX に準拠した sed は OS X などで標準で使用されているが、一般的な Linux で用いられる sed は後述する GNU sed であることが多い。ゆえに、Linux ユーザが OS X の sed を使用するとオプションなどのいわゆる「方言」的な違いに混乱することでしょう。
sed コマンドの用法 - Qiita


この記事では、以下の環境で確認した。

cygwin 64bit版

$ sed --version
sed (GNU sed) 4.2.2
Copyright (C) 2012 Free Software Foundation, Inc.
(後略)



「正規表現を有効にする」には?


正確には「拡張正規表現(extended regular expressions)を有効にする」らしい。
拡張正規表現なしでsedを使っても一部の正規表現は使えるが、普段の正規表現のやり方と微妙に違ったり、使えない演算子があったりして、かえってややこしい。
拡張正規表現を有効にしておいたほうが分かりやすい。

「-r -eを使おう」と書いてあるサイトと、
「-Eを使おう」と書いてあるサイトがある。

-eは「コマンドの指定をする」オプションであるため、
「-r -e コマンド」だと正しく動くが、「-e -r コマンド」だと-eとコマンドが離れているためエラーになる。
しか実のところ、-eは省略しても良いらしい。謎だ……。

置換の指定コマンド



以下のどれか1つ。
's/ +/\t/g'
's/\s+/\t/g'
's/ {1,}/\t/g'
's/\s{1,}/\t/g'


s : 置換
g : 行の全体で置換を実行 (つけないと行内で最初に出てきたスペースだけ置換される)

\s 空白とタブ両方に対応する
+ 1回以上の連続
{n,} で「n回以上の連続」を指定できる。

\sを使った方法は、入力にタブが無ければ期待通りに動く。

まとめ



最終的に、
「入力ファイルのスペースをタブに変換して出力する、ただし連続したスペースは1つのタブに変換する」
コマンドは、以下の通りである。

以下のどれか1つ。(ファイル名をinput.txt, output.txtとする)
sed -E 's/ +/\t/g' input.txt > output.txt
sed -E 's/\s+/\t/g' input.txt > output.txt
sed -E 's/ {1,}/\t/g' input.txt > output.txt
sed -E 's/\s{1,}/\t/g' input.txt > output.txt

「-E」の代わりに「-r -e」でもよい。「-r」でもよい。
  1. 2018/07/08(日) 12:57:29|
  2. プログラミング
  3. | トラックバック:0
  4. | コメント:0

pythonの正規表現のmatch, search, findall関数の違いを調べて整理した
2018/07/01(日) 22:18:41

以下のサイトが役に立った。自分で調査した結果も併せて整理しておく。
Pythonでの正規表現の使い方 - Qiita
正規表現 HOWTO ? Python 3.6.5 ドキュメント

共通


pythonのバージョンは3.6.0。

正規表現でマッチするものが見つかったときには、matchオブジェクトというオブジェクトが使われる。
matchオブジェクトの中に、マッチした箇所の情報が格納される。
(今回はmatchオブジェクトの中身の構造については触れない)

match関数 文字列の先頭だけを探す


これは検索対象の先頭からだけ検索して、マッチするものがあるか判定する。
探しているパターンが先頭にあればマッチするが、途中に含まれていてもマッチしない。

・マッチしなかったらNoneが返る。
・マッチした場合はmatchオブジェクトが返る。
・matchオブジェクトの中にはマッチした箇所の情報が入っている。

以下は特殊なシンタックスを使わない、ごく単純な例だ。
下の例の2つ目では、では"regular expression"の中に"lar"は含まれているが、最初ではないのでマッチせず、Noneが返っている。


import re

result = re.match("reg", "regular expression")
print(result)
print(type(result))
# 出力:
# <_sre.SRE_Match object; span=(0, 3), match='reg'>
#

result = re.match("lar", "regular expression")
print(result)
print(type(result))
# 出力:
# None
#



search関数 文字列の全ての位置を探す。


これは検索対象の位置にかかわらず検索する。


result = re.search("reg", "regular expression")
print(result)
print(type(result))
# 出力:
# <_sre.SRE_Match object; span=(0, 3), match='reg'>
#

result = re.search("lar", "regular expression")
print(result)
print(type(result))
# 出力:
# <_sre.SRE_Match object; span=(4, 7), match='lar'>
#


文字列の途中でもマッチしているのが、match関数と違う点である。
また、マッチしない場合は、match関数と同様にNoneが返る。

search関数の注意:パターンにマッチするのが2つ以上ある場合は最初の1つだけが返る。

"regular expression"の中で、「アルファベットが1文字以上連続する箇所」を探してみよう。
これは「\w+」と書き表せる。
(厳密には、\wはアルファベット、数字、およびアンダースコアの集合である)
このパターンに該当するのは「regular」と「expression」の2つだが、返り値を見ると最初の「regular」の部分だけが入っている。


result = re.search("\w+", "regular expression")
print(result)
print(type(result))
# 出力:
# <_sre.SRE_Match object; span=(0, 7), match='regular'>
#



findall関数 パターンに当てはまるもの全てをリストにして返す



マッチする箇所が複数あったら、1つ目だけではなく全て返してほしい、という場合もあるだろう。
このような場合ではfindall関数を使う。

返り値の決まり方は結構ややこしい。
Python 3.6.5 ドキュメントのre.findallの箇所にはこう書かれている。
「Return all non-overlapping matches of pattern in string, as a list of strings. (中略) If one or more groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group. 」
3つの場合分けがある。順に見ていこう。

まず、1つ目の場合。パターンの指定時にグルーピングの( )を使わない場合、返り値は文字列のリストである。

result = re.findall("\w+", "regular expression")
print(result)
print(type(result))
print(type(result[0]))
# 出力:
# ['regular', 'expression']
#
#



グルーピングの( )を使う場合、まずパターン内に( )が1つだけであれば、グループ(内にある文字列)のリストになる。
下の例の2つ目では、マッチングは1つ目の例と同様になるが、( )の中にeが入っていないので返り値にeが含まれていない。

result = re.findall("(e.)", "regular expression")
print(result)
print(type(result))
print(type(result[0]))
# 出力:
# ['eg', 'ex', 'es']
#
#

result = re.findall("e(.)", "regular expression")
print(result)
print(type(result))
print(type(result[0]))
# 出力:
# ['g', 'x', 's']
#
#


そしてパターン内に( )が2つ以上ある場合、グループ(内にある文字列)をタプルにしたもののリストになる。
下の例の2つ目では( )がネスト(入れ子)になっているが、タプル内の順序は左括弧の登場順である。

result = re.findall("(e)(.)", "regular expression")
print(result)
print(type(result))
print(type(result[0]))
# [('e', 'g'), ('e', 'x'), ('e', 's')]
#
#

result = re.findall("(e)((.)..)", "regular expression")
print(result)
print(type(result))
print(type(result[0]))
# 出力:
# [('e', 'gul', 'g'), ('e', 'xpr', 'x'), ('e', 'ssi', 's')]
#
#



最後に、返り値の方式にかかわらず、マッチしない場合は空のリストが返る。

result = re.findall("AAAAA", "regular expression")
print(result)
print(type(result))
# 出力:
# []
#



まとめ


3つの関数の仕様を整理しておこう。
■match関数は文字列の先頭だけを探す。
■search関数は文字列の全ての位置を探す。パターンに当てはまるものが複数ある場合は最初のものを返す。
■findall関数は文字列の全ての位置を探す。パターンに当てはまるもの全てをリストにして返す。返り値は以下の3通りある:
  -パターンの指定にグルーピングの( )を使わない場合、返り値は文字列のリストである。
  -パターンの指定にグルーピングの( )を使う場合、パターン内に( )が1つだけであれば、グループ(内にある文字列)のリストになる。
  -パターンの指定にグルーピングの( )を使う場合、パターン内に( )が2つ以上であれば、グループ(内にある文字列)をタプルにしたもののリストになる。


書いたきっかけとおまけ



正規表現でsearchを使うべきところでmatchを使っていて、ずっとNoneが返ってきてしまい、だいぶ時間を費やした。

何も考えずに「python 正規表現」でググったとき、python公式ドキュメントで最初に見つかるのはこれだ。
6.2. re ? 正規表現操作 ? Python 3.6.5 ドキュメント
これはリファレンスであり、初めて使う人が参考にするには厳しい。
終わり近くの6.2.5.3. search() vs. match()という箇所で一応言及はしているのだが、最初に見た人がここにたどり着くのは難しい。
同じ公式ドキュメントなら、以下のほうがオススメである。
正規表現 HOWTO ? Python 3.6.5 ドキュメント
  1. 2018/07/01(日) 22:18:41|
  2. プログラミング
  3. | トラックバック:0
  4. | コメント:0

scikit-learnとTensorFlowによる実践機械学習 輪読会4章
2018/06/24(日) 00:40:00

2018/06/15(金)に、scikit-learnとTensorFlowによる実践機械学習輪読会#4で発表してきた。

scikit-learnとTensorFlowによる実践機械学習/原題:Hands-On Machine Learning with Scikit-Learn and TensorFlow」の4.1 - 4.2の説明を担当した。資料はこちら!



勾配降下法の3つの方式:バッチ勾配降下法、確率的勾配降下法、ミニバッチ勾配降下法



この本では4.2.1でバッチ勾配降下法、4.2.2で確率的勾配降下法を扱い、その後の4.2.3でミニバッチ勾配降下法を取り扱っている。

scikit-learn_42.jpg

この順序で話が進むので、3種類の方法の関連性や相違点を把握しやすかった。

「関連性や相違点」を具体的に挙げると、「ミニバッチ勾配降下法はバッチと確率的の中間の特徴を持つ」という点である。また、ミニバッチでバッチサイズが1の特殊な場合が確率的勾配降下法であり、バッチサイズが全体の特殊な場合がバッチ学習である、という見かたもできると気づいた。

今までの理解では、「どうやら通常はミニバッチを使うらしい」ということは分かっていた。しかし、すべてのインスタンスについて勾配を計算して学習するバッチ学習と比べて、どう違うのかがきちんと理解できていなかった。

scikit-learnとTensorFlowによる実践機械学習」ではまずバッチ勾配降下法を説明して、その後で確率的勾配降下法が出てくる。その中で確率的の方は
・1回のイテレーションが高速
・アウトオブコア(=メモリに乗りきらないデータ)に対応している
・最適解で止まることがない
といった特徴があることに触れている。
また、4.2節の最後にはアルゴリズムの比較表があり、4.1と4.2の全体を見渡して概要をつかむことができる。全体的に説明の流れが上手いと感じた。

インスタンスの選ぶ方法による収束速度の違いについて


輪読の最中に「本に書いてある内容が分からない」と話題になった箇所がある。

P.120
(筆者補足:確率的勾配降下法では)インスタンスが無作為に選ばれるため、一部のインスタンスはエポックの中で複数回選ばれることがあるのに対し、ほかのインスタンスは全然選ばれないことがあることに注意しよう。各インスタンスですべてのインスタンスを処理するようにしたければ、訓練セットをシャッフルしてからインスタンスを逐次的に取り出し、終わったら再びシャッフルするという方法もある。しかし、この方法は、一般に収束まで余分に時間がかかる。
(※太字は筆者による)



本では、確率的勾配降下法でインスタンスを選ぶとき、2通りの選び方があるよ、と言っている。
1つ目は、毎回ランダムに選ぶ方法である。例えばインスタンスが5個で、1~5の番号がついているとしよう。(普通はもっと多いが、説明のため簡単にする。)選び方の例は以下のようになる。毎回、1~5の中からランダムで1つの数を選んでいる。

3, 5, 4, 3, 4, 2, 4, 1, 3, 4, 4, 3, 1, 2, 4, ……

2つ目は、インスタンスの集合を一度シャッフルして取り出して、終わったら再度シャッフルする、という方法である。さっきの例でいえば、選び方の例は以下のようになる。分かりやすいように5つごとにカッコでまとめた。カッコの中が1~5の並び替えになっている。

[2, 3, 1, 4, 5], [3, 5, 4, 1, 2], [1, 4, 2, 3, 5], ……

この2つの選び方では収束の速度に差があり、前者が速くて後者が遅いらしい。何でだろう?
直感的には、ランダムで選ぶ限り、どのような選び方だろうと収束速度に差は無いように思える。
輪読会に来ている方が知っているかなと思ったが、誰もその理由を知らないようだった。重要な箇所ではないからそれほど気に留めなくても良いとは思うが、ちょっと気になる。

GitHub上のサンプルコードについて



ありがたいことに、本に掲載されているコードはGitHub(下記)に上がっている。
GitHub - ageron/handson-ml: A series of Jupyter notebooks that walk you through the fundamentals of Machine Learning and Deep Learning in python using Scikit-Learn and TensorFlow.

残念ながら、スライドを作る方で手一杯だったので、
GitHub上のコードを見たりダウンロード・実行するところまで手が回らなかった。反省である。

ソースコードは全体的に平易であり、本の内容が理解できていればそれを素直にコードに直したものである。
とはいえ、コードが書けなきゃ実際の機械学習処理ができないので手を動かさなきゃいけない。
俺はコーディングよりも理論の方についつい寄ってしまうので、気をつけなければ……

それでは。
  1. 2018/06/24(日) 00:40:00|
  2. プログラミング
  3. | トラックバック:0
  4. | コメント:0

kaggle初心者はカーネルを読むだけでも勉強になったよ
2018/06/17(日) 20:59:31

はじめに



機械学習を少しずつ勉強している。
その中で先月kaggleに登録して、そこから少しずつkernelを写して書いている。
「このやり方、結構いいんじゃないか」と思ったので、kaggleのkernelの良さについて書く。

対象読者



「kaggle登録はしたけどどうすればいいかよく分からん」
「いきなり問題を解けといったって、いい解法が思いつかない」
くらいの人を想定しています。
kaggleのコンペティションにガンガン出て順位を競っているような人は対象外です。

Kernelとは何か?



少し分かりにくいところにあるが、kaggle公式では以下のように説明されている。
Titanic: Machine Learning from Disaster | Kaggle

What are kernels?
Kaggle Kernels is a cloud computational environment that enables reproducible and collaborative analysis. Kernels supports scripts in R and Python, Jupyter Notebooks, and RMarkdown reports.

拙訳:
kernelとは何ですか?
Kaggle Kernelは、クラウド上の計算環境であり、再現性のある共同の解析ができます。RとPythonのスクリプト、Jupyter Notebook、そしてRMarkdown reportをサポートしています。

pythonに限れば、kaggle上でJupyter Notebook形式でコードを書いて実行することができる。
また、ここに他の参加者がソースコードを投稿・公開している。
上手い人のコードを読んで参考にすることができるというわけだ。

このkernelを見て学習をするメリットは以下のとおりである。

利点1:Pythonの各種ライブラリの実用的な使い方がわかる



俺自身はPythonを普段あまり使っていないので、文法や関数が分からないこともある。
たまにRubyの書き方をしてしまったりするし。
そもそもライブラリをどう使うか、どういったことが可能なのか、という知識があまりない。
機械学習をやっていく上では、Numpy・Pandas・Matplotlibなどのライブラリは避けて通れない。
機械学習の勉強を進めるときは素のpythonだけではなく、これらのライブラリも使えるようにならなければいけない。何種類かのライブラリの知識も必要になるという点は、ちょっとハードルが高いと思う。

kaernel上で、実際で使われているのを見ることで
「pandasってこういうことができるんだな」「numpyのこの関数ってこう使うのか」と分かる。
もちろんライブラリの公式ドキュメントを順番に見ても使い方を学ぶことはできると思うが、
しかしそれだと滅多に使わないものまで出てきてしまう。
実践に即した知識を習得できるのが良い点かと思う。

利点2:問題の解き方がわかる


kaggleでは機械学習のコンペティションが開催されている。
しかし「はい、これが問題です、解いてください」と言われても、初心者は解けないわけだ。
どういう解法でどういうパラメータを設定して解けば上手くいくかなんて分からないからである。

そしてある特定のアルゴリズムで解いてみようとしても、コードが上手く動かなくてエラーが出たりして、
「え、どこで間違えたんだ、分からない、困った」ということになる。
「解法が分からなくて詰む」「解法が分かってもコードが書けなくて詰む」の二重苦である。

SIGNATE(旧名:DeepAnalytics)というkaggleの日本語版のようなサイトがあり、同様にコンペティションが開催されている。
俺は3月に、初めてコンペティションに参加して
「取りあえず思いついた解法で解いて提出してみるか、きっと酷いスコアだろうけど」と思ってゼロから書き始め、
数多のエラーを喰らった末に疲労困憊しながら提出したが、予想していた以上に酷いスコアだった。
もちろん手を動かしたぶんの実力がついたとは思うが、しかし技術力をつける上では遠回りだった。

そこでkernelの出番である。

・(Jupyter Notebook形式の場合は)手法の説明+コードがある
・ちゃんと動くコードなので、エラーにハマらずに済む
・自分のkernelにコピー(fork)して動かせる
・そこから少しずつ書き換えてみて、どうなるかな、と試してみることも可能
といった利点がある。

なお、機械学習の初心者ではなく実力者であっても、
素晴らしく上手く解ける方法を最初から分かっているとは限らないので、
kernelに掲載された解法を参考にしているようだ。
以下の記事を参照。
Kaggleを取り掛かるまでにやったこととと、モチベーションの維持のために必要だったこと - にほんごのれんしゅう

どのkernelから見れば良いの?



コンペティションを決めていて、それに関する良い感じのkernelを探す場合は
ひとまずはVote数でソートすれば良さそうだ。
「このkerelは参考になった」と思った人がVote(投票)するので、Vote数の順にすれば人気のあるkernelを見られる。
(下の図の赤い四角の部分)

20180616_kaggle-kernels.png

投票数の多く人気のあるkernelの中でもどれを選ぶか、という点については、
タイトルやタグ名から以下のことが読み取れるので、それを参考に決めれば良いだろう。

・EDA:「Exploratory Data Analysis」の略、日本語に訳すと「探索的データ解析」となる。分かりやすくいうと「問題を解くより前に、入力として与えられたデータがどのようなものか、表やグラフに可視化しながら観察してみよう」くらいのニュアンスである。したがってこのタイトル/タグがある場合、問題そのものを解いていない場合が多い。
・解法名:「特定の解法を使って解いてるコードを見たいんだよなぁ」という場合にはそのアルゴリズムの名前があるものを選べばよい。
・スコア:そのkernelのコードを実行したときのスコアを表す。例えば上の図で上から2番目のkernelには「0.735」というタグが付いているので、submitすればそのスコアになるはずである。



参考・関連



kaggle初心者に向いている、kaggle内のコンテンツ、という切り口で考えると

Titanic コンペティションのtutorialをやる
Learn(機械学習やPandasやRなどの教材)をやる
あたりも良いだろう。

それでは。
  1. 2018/06/17(日) 20:59:31|
  2. プログラミング
  3. | トラックバック:0
  4. | コメント:0
次のページ

FC2Ad