02 Jan 2018, 05:31

KaggleのためのMOOCがcourseraに!How to win a Data Science Competitionを受けた

kaggleの攻略法について、以前調査した。あまり、学習教材がなかった。

Kaggleを初心者が進めるには、とにかくコンペに参加してKernelを読むしかないのかなと思っていた。そんな自分に朗報!この courseraが提供するものこそ、自分が求めていたものだ。

その名も・・・

How to Win a Data Science Competition: Learn from Top Kaggler

特徴

ロシアのカグルマスターが講師

この講座では、Yandexというロシアのgoogleが講座をサポートしている。そのため、ロシア切ってのデータサイエンティストから学ぶことができるのだ。

また、catboostなどの、ロシア魂がこもったライブラリを紹介される。これはかのxgboostよりも強力だった。

難易度高い…

正直、難しいです。quiz, assignment, 解けなかった。

この講座は機械学習の手法を教える講座ではない。それらはすでに身についているものとして、コンペで使える技や知識を教えてくれる。

kaggle コンペで腕試し

習ったことは即試してみようということで、練習用のkaggleコンペが用意されている。

ロシアのIT企業の売上予測を行う。時系列データコンペ。

各週の内容

week1:

recap&introduction ということで、データ分析コンペについて紹介される。

基本的な手法はもう知っているよねということで、MLの手法はサラッと紹介されて終わる。

そのあと、前処理についての紹介。これはよくまとまっている。数値変数、カテゴリ変数、時間の扱いと位置の扱い、欠損値の扱い。これは大事なので、なんども復習したいところだ。

assignmentはpandasについての演習。groupbyを多用する必要があり、初心者サヨウナラ感がとてもする。

week2:

EDAについての解説。これも一通りの手法は紹介される。とはいえ、すべてを網羅できるわけではなく、自分で習ったことを実践してみないとこれは身につかない気がした。

次に Validationということで、データ分割の戦略について紹介される。データ分割がなぜ必要か(過学習を避けるため)、その手法と注意点について。

最後に、Data Leakageが扱われる。具体的な事例を元に、DataLeakageにどうやって気づくかなどが紹介される、が、

ここはよくわからなかったな。。。Assignmentも Data Leakageについてなのだが。

week3:

Metrix(評価指標)について学ぶ。回帰、分類それぞれでよく使われる指標を学ぶ。MetrixとLoss functionの違いについて説明。ココらへん、理解していなかったので参考になる。

続いて、mean encodingという手法について紹介される。カテゴリカル変数を変換するための方法で、label/one-hot-encodingよりも、強力だとか。そして、その実装がassignmentとして課される。

week4:

ハイパーパラメータのチューニングについて、まず紹介される。ランダムフォレストやxgboost, ニューラルネットワークのパラメータチューニングについての実践的なアドバイス。また、自動チューニングツールの紹介(hyperoptなど)

次に、特徴量エンジニアリングの小ネタ第二弾。

  • Matrix Factorization
  • Feature Interaction
  • t-SME

最後に、一番むずかしい話題、アンサンブル学習が紹介される。weight average, bagging, stacking, boosting, stacknet…ムズい。assignmentはstackingの実装。

week5:

過去のコンペティションで講師の人が上位入賞をどうやってしたか、カグルマスターがその手法の種明かしをしてくれる。

ただ、これらの動画はおまけのようなもので、最後の週の本題は、用意されたKaggleコンペで上位スコアを取ること。

Assignmentがスコアのcsvデータの提出。一定以上のスコアを超えていないと、クリアとみなされない。そしてこの水準がとても高い。MSE1.0より低くないと、どうやら合格できないよう。LBを見ると、そんな人は30人くらいしかいない。

それに加えて、ペアレビューがある。以下のフォーマットに従って、自分がどうやってコンペに望んだかを説明するレポートを作成して、コードと一緒に提出する。

提出がすむと、他の人のコードをレビューできるようになる。

おわりに

この記事を執筆している時点では、私はコースを完了していない。

QuizもAssignmentも終わらなかった。

ただ、とてもこのコースはとても充実していた。かけた時間は現在95時間。kaggleのための実践的なテクニックが豊富に紹介されていて、吸収することがたくさんある。mean encodingや stackingなど、ネットにはほんとど情報がないが重要な手法も紹介されている

(assignmentにもなっている)

さらに、その知識を実践するする機会もコンペという形で与えられている。MOOCをいろいろと受けてきたけれども、そのなかでもかなり楽しい講座だった。それは、自分が今興味があることがデータサイエンスであり、ちょうど知りたい内容だったからだ。

この講座の内容をよくよく復習し、今後もKaggleに取り組んでいこう。Kaggle用のマシンも購入したことだし、まずはそれでグリッドサーチやアンサンブルを試してスコアを上げる。

31 Dec 2017, 13:14

機械学習/ディープラーニング用にウルトラ高性能ゲーミングPCを購入

2017年も残すところわずかですが、年末最後に羽目を外してしまったというか、やらかしてしまったことを書きます。

ネットで機械学習用のPCを買ってしまいました。。。

33万で。ヽ(`▽´)/

うぇーい。

どうしてこうなったか

大晦日ですが暇していたので、ふとした弾みで最新式のパソコンが欲しくなった。

どうせ買うならば、超高性能のPCが欲しくなってきた。もちろん、GPUつき。

とはいえ、GPU式のウルトラ高性能のPCはどうすれば手に入るのかもわからない程の素人。調べてみると、ゲーム用PC、ゲーミングPCというジャンルがあり、

そのキーワードで検索してみると、よさそうなPCが出てきた。

ネットで情報を漁っているうちにその気持ちが止められなくなって、

買っちゃえ買っちゃえという気分になってきた。年末年始のキャンペーンもやってるし。

高性能PCを作るには自作パソコンだろうと思っていたが、調べるとBTOという方法があるらしい。

BTOとは、Build To Orderの略で、PCのスペックを指定して注文することが出来るサービス。

以下の雑誌が参考になった。

「組む」時間がなくても大丈夫 第8世代Core搭載 買いのBTOパソコン

雑誌を片手に様々な、BTOを提供しているサイトで見積もりを実施。

以下のサイトが参考になった。

結局どこも大差はないのだけれども、納期が即日だったドスパラに決定!

なにを買ったか

というわけで、ドスパラ最強ゲーミングPC ガレリア(GALLERIA) ZZを購入。

ちなみにちなみに、BTOと自作では、30000円くらい差があるとのこと。なんだか高すぎて金銭感覚がなくなってきたお。

スペックはカスタマイズしたのだが、以下を指定。

  • CPU インテル Core i7-8700K
  • メモリ 64GB DDR4 SDRAM
  • GPU NVIDIA GeForce GTX 1080Ti
  • SSD 500GB
  • OSなし(Ubuntu予定)

以下のサイトを参考にスペックは選定した。

CPUは、なにをするにも重宝をするもの。なので、できるだけ高価なものを購入。第8世代とのことで、6コア12スレッド。機械学習の前処理でパワーがあるCPUで処理したいと思い購入。

GPUは、安定のNVIDIAの最新版 GoForce GTXシリーズ。GPUについて、1070Tiと1080Tiで価格が3,40000円違ったので、とても迷った。GALLERIAの ZVというモデルが売れ筋No.1だそうだ。性能の比較が気になるところだが、これと明記した記事は見つからなかった。とても悩んだあげく、高いほうを選択。最高スペックが欲しいという動機があったからだ。

メモリについて、画像データを大量に扱いたいという思いがあり、Memoryネックで計算できないことがないよう、64GBを選択。

OSはLinuxのほうがいろいろなライブラリを扱う上で良いだろうとおもい、Windowsのオプションは捨てた。Ubuntuを入れるぞ。

買ってなにをするか?

一言でいうと、Kaggleです。

2018年の目標は、Kaggleをすること。Kaggleを通じて、機械学習やディープラーニング(Deep Learning)の知識を身につけ、データサイエンス力を磨いていくこと。

今年受けたデータサイエンティスト養成講座で、カグルマスターの人にあったのだが、その方がkaggleはマシンゲーだよと言っていた。高スペックなマシンを持っている人が勝利するとか。自分は、知識も腕前もないのだけれども、まずは形から入ろうとして、マシンを購入した。お金を払うとやらざるを得ないというあれです(ジョギングをすると決意するときに、はじめに効果なシューズやウェアを買うのと同じ心理)

ドスパラは2日で即配達するとのこと。どうしてもお正月に設定を終わらせたかったので、ドスパラを選んだ。即日出荷というのがすごい。というわけで、次回はマシンの設定を書きます。

28 Dec 2017, 04:56

2017年の振り返りと2018年の目標

毎年恒例ですが、一年の振り返りと来年の目標を立ててみようと思います。

2017年の振り返り

TOEIC ほぼ900達成

まずは、2017年の振り返りから。一年前はTOEICをとにかく勉強していた。

そして、年初の目標は、TOEIC 900達成を目指すこと。技術的成長は諦めていた。

ソフトウェア開発よりも、2017 年は TOEIC の勉強に力を入れる。

そして、頑張った結果、895点を3月に取得した。目標達成、めでたしめでたし。

機械学習にかけた一年

今年、もうひとつ頑張ったテーマがAI, 機械学習、Deep Learning。世の中AIブームなので、ミーハーなボクも、流れに乗って勉強を進めたのだった。

AIの勉強をしていて、会社の産業医から、AIで会社にどう貢献するのですか?AIの勉強をしていたら復職させない!といわれ、上司からもうちの部署はAIとは関係ないといわれ、それでもめげずに勉強していた。ところが、世の中はAIブームが来て、会社でもいろんな人がAIの勉強を始めている。ブームは確実にやってきている。

休職中で暇すぎたので、ありあまる時間を使って数々の講座を受講した。

その結果、JDLAの G検定に合格するという成果が出た。基礎的なAIの知識はついた。

仕事に復帰しました

うつ病で休職していたが、9月からようやく仕事に復職できた。復職したら、きっとはじめは窓際な仕事で暇だーといいながらひっそりと過ごすことを期待していたのだけれども、炎上プロジェクトに放りこまれていきなり激務。これはヒド(ry.

今は、ストレージ装置のファームウェア開発をしている。具体的には、システム制御チームでRAIDコントローラーの閉塞処理とファームウェアアップデート機能の開発をしている。2ヶ月で15日遅延で、4ヶ月で1ヶ月遅延で、毎週進捗報告で怒られる。早くAI業務に異動したい。そのためには、今の仕事で成果を出さないといけないのだけれども、また潰されそう。

2018年の目標

2018年は、AIの勉強を引き続き実施していく。具体的には、以下。

kaggleやる

2017は、データサイエンスに入門した。2018は、実力をつける。実力をつけるために、kaggleをやる。kaggleをやることで、機械学習やディープラーニングの知識をつけていく。またよいkernelを公開することで、EDA力、人に説明する力もつけていく。

JDLA E検定を受ける

ディープラーニングの勉強を継続していくために、JDLAの E検定の勉強をすることを一つの目標にしようと思う。資格を取ることで、自分の知識を証明したい。

婚活する

ソフトウェア開発の勉強よりももっとやらなければいけないことがあるのだった。休日は勉強もいいのだけれども、婚活に時間を割く。早く結婚したい。

28 Dec 2017, 02:07

JDLAのG検定、初試験で一発合格

JDLA(日本ディープラーニング協会)のG検定というのが12/16(土)に実施された。

遅ればせながらツイッターに流れてきて試験日を知り、12/4に申し込んだ。

結構難しくて、落ちたかなと思った。

なんとか?合格していました。今回は、受験者1448人、合格者823人。合格率にして57%。

対策日数は10日間だけれども、やったことを書く。

受験の動機

受験の動機は、ディープラーニングの知識を持っていることを資格を保持することで示したかったから。社内にAIを扱っているプロジェクトがあり、そこに移りたいと何度も上司に言っているのだが、受け入れてくれない。なので、資格を持つことで、ディープラーニングの知識を有していることを示したいと思った。

G検定とは

以下の通り

  • 目的:ディープラーニングに関する知識を有し、事業活用する人材(ジェネラリスト)の育成
  • 概要:ディープラーニングを事業に活かすための知識を有しているかを検定する
  • 試験概要:120分、100問(表示される問題数は232問)、多肢選択式、オンライン受験(自宅受験)
  • 受験料:12,960円(税込)
  • 試験日:2017/12/16(土) 13:00-15:00

受験料が高い。あとは、オンライン試験ということで、自宅で受けることが可能なところがポイント。100問とかかれているが、実際は232問出されて、とても分量が多い。私は20分くらい余ってようやく問題を解ききったが、さくさく解いていかないと、時間がなくなる。

シラバス(201712)

まずは、シラバスをチェック。

協会活動 | 一般社団法人 日本ディープラーニング協会 Japan Deep Learning Association

  • 人工知能(AI)とは(人工知能の定義)
  • 人工知能をめぐる動向
    • 探索・推論、知識表現、機械学習、深層学習
  • 人工知能分野の問題
    • トイプロブレム、フレーム問題、弱いAI、強いAI、身体性、シンボルグラウンディング問題、特徴量設計、チューリングテスト、シンギュラリティ
  • 機械学習の具体的手法
    • 代表的な手法、データの扱い、応用
  • ディープラーニングの概要
    • ニューラルネットワークとディープラーニング、既存のニューラルネットワークにおける問題、ディープラーニングのアプローチ、CPU と GPU
    • ディープラーニングにおけるデータ量
  • ディープラーニングの手法
    • 活性化関数、学習率の最適化、更なるテクニック、CNN、RNN
    • 深層強化学習、深層生成モデル
  • ディープラーニングの研究分野
    • 画像認識、自然言語処理、音声処理、ロボティクス (強化学習)、マルチモーダル
  • ディープラーニングの応用に向けて
    • 産業への応用、法律、倫理、現行の議論

実際、どこがでるかというと、まんべんなく出る。このシラバス通りに出る。不明なキーワードはすべて調べ、関連する話題も読んでおかないと、解けない。

自分の対策

推薦書籍は3つある。

  • AI白書 2017 (編)独立行政法人情報処理推進機構 AI白書編集委員会 角川アスキー総合研究所
  • 人工知能は人間を超えるか ディープラーニングの先にあるもの 角川EPUB選書 (著)松尾 豊 KADOKAWA
  • 深層学習 機械学習プロフェッショナルシリーズ (著)岡谷 貴之 講談社

申し込みから試験まで、10日しかなかったので、とりあえず推薦本の一つである、人工知能は人間を超えるかを丁寧に読んだ。

ディープラーニングは今年から勉強を開始したので、ディープラーニングや機械学習の問題が出てくれれば解けるだろうと思っていた。その憶測は正しかった。ディープラーニングや機械学習の問題は簡単だった。

IA白書を買ったのだが、これは分厚く、とても読めなかった。ここから出題された問題もいくつかあったが、正直これは捨て問だと思う。この厚い本を読んで、その一部の情報が記憶に残るとは思わない。

よって、機械学習やディープラーニングで点を稼ぎ、 AIの歴史は松尾本でここも落とさずに点数をとり、それ以外のほとんどの人がわからない問題は捨てる、という戦略が必要。

感想

難しい・・・というか、正確にいうと知らない問題は全く知らない。わかる問題は解ける。とにかく、問題数が多いのだ。オンライン試験なので、調べようと思えば調べられるが、その余裕を与えないための配慮だと思う。調べていたら、時間切れになるようにできている。

とにかく、出題範囲が広いのと問題数が多いのが特徴。という意味で、難しい。

半分くらいはディープラーニングではなくて、その関連知識の問題だった。歴史についてだったりAIについての考え方だったり。このあたりは、知らない問題はまったく手が出せずに捨てた。AI白書を読めば載っていることだろうが、あの本は分厚いので読む気にはならない。機械学習とディープラーニングの問題は優しく、ここで点数を稼いだ。

E検定に向けて

G検定が受かったので、次はE検定を目指す。こちらは、推薦書籍の3つ目が中心に出題されることが予想される。

しかし、この本難しいので、自分は最近発売された以下の本を中心にまずは進めようと考えている。

それとともに、E検定では実技試験が課せられる。これはコーディングをするということなのだろうか?現時点での情報では、そこまでは読み取れないが。とはいえ、なんらかのフレームワークを使って実装するスキルを磨いておきたいところだ。

最近注目してる、PyTorchを学習することにする。チュートリアルやUdemyの動画で学習を進めていく。

23 Dec 2017, 10:12

データサイエンティスト養成講座を受けた感想(後半)

はじめに

データサイエンティスト協会が主催するデータサイエンテスィト養成講座を受けた。

前半の感想は以下です。今回は、後半の感想を書く。

各回の内容

第5回

中間発表会。銀行問題の成果発表。私の成績は、17位でした。各班の発表のあとは、先生のコメント。この銀行問題は、それほどデータ前処理をしなくても、random forestや xgboostのちからを借りると、そこそこのスコアがでてしまうとのこと。

ただし、それはコンペという特殊な世界で通用することであり、ビジネス的観点が抜けていることはよくない。業務でつかう多くのモデルは説明が求められる。

そして、後半のお題、Jリーグの観客動員数を予測せよ! が出される。

こちらは、単純にxgboostやrandom forest を 適用したたけでは、いい成果はでない。しっかり特徴量エンジニアリングをする必要がある。

第6、7回

後半は、目新しい知識の講義はなく、グループワーク中心で進む。チームでアイデアを出しながら特徴量を作成していく。

モデルの改善方法として、残差を見ながら分析する方法が紹介される。どの場合に、モデルの予測が結果を外しているかを並べて、傾向を見て、それをモデルに反映するというサイクルが紹介される。

チームでサッカーに詳しい人が一人いて、(ほかはそれほど詳しくなくて)、アイデアをもらいながら特徴量を作っていった。また、自分では、コーディング力がなくて作れない特徴量も他のメンバの手を借りて、作った。一人で考えているよりも、みんなで考えた方がよいアイデアが浮かぶ。協力が必要。

私ともう一人はpythonでデータ分析をして、他のメンバはRでデータ分析を進めた。あるメンバがRの分析力をメキメキつけて、驚いた。

という本を読んで力をつけたそうだ(これはウェブで無料公開されている)。python と Rで、どちらがよいかという議論をよく見かけるが、dplyr という強力な前処理ツールがあるので、モデルの前処理は R でやるほうがよいと感じた。前処理や視覚化は、pythonよりもRに軍配が上がる。

第8回

最終発表会。

私の成績は、なんと1位だ!

ネタバレになるので、作った特徴量は秘密だが、思いついた特徴量はすべて試した。

そして、最終秘密兵器、catboostを使った。

これは、ロシアのGoogleと言われているYandexが開発したOSS。これをつかったら、スコアがグーンと下がった。私は、データの視覚化をあまりしなかったのだけれども、同じ班のさきほどR力をグーンと伸ばした人がいろいろとデータを視覚化してくれた。

感想

データサイエンティスト養成講座にかけた勉強時間は100時間くらい。

当初の目的だったCSV形式のデータに対する解析技術がついた(Python力も)。

反省点としては、精度を求めるあまり、データの意味を考えることを怠った。データをプロットして、観察して、加工するというプロセスが踏めていなかった。なので、今後はデータを観察し表現する力、人に説明する力を身に着けたい。

これから

これからどうするかということも考えておこう。自分は他のひとと違って、業務ではデータ分析をしていない。なので、ここで学んだことを忘れないようにするためには、継続してデータ分析コンペに参加しようと思う。

DeepAnalyticsや Kaggleのコンペに参加して、腕を磨いていきたい。コンペでいい成績を取ることによって、力をつけていきたい。

今は、データサイエンスに興味があるが、転職をするかどうかは、まだもう少し見極めが必要。もう少し勉強してみて、この分野が本当に面白いと感じたら、転職を考えよう。

25 Nov 2017, 11:11

Logbackのログを見やすくする方法(ファイルをgrep, Lilith)

仕事で、Javaのロギングツールとして slf4j + logbackを使っている。

このログなのだが、IntelliJの出力画面から見ると、みにくい。

できれば、一連のログをgrepしたいのだが、それがIntellJではできないのだ。

そこで、出力されたログをフィルタする方法を調べたところ、2つ方法が見つかった。

ファイルに書き出してgrepする

まずは、簡単な方法から。ログをファイル出力して出力結果をキーワードでfilterする。

filterの方法は、さくらエディタだったり、秀丸エディタだったりの機能を使えば良い。

では、ファイルにログを出力する方法だけれども、以下をlogback.xmlに追加。

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/app.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/app.%d{yyyy-MM-dd}.log.tar.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="FILE"/>
    </root>
</configuration>

これで logs/app.logにログが出力される。

ログイベントビューアの Lilithをつかう

Lilithは OSSのlogback用ログビューア。

Lilithのために、以下のツールをインストールする。build.gradeのdependenciesに以下を追加。

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <appender name="LogbackClassic" class="ch.qos.logback.classic.net.SocketAppender">
        <RemoteHost>localhost</RemoteHost>
        <Port>4560</Port>
        <ReconnectionDelay>170</ReconnectionDelay>
        <IncludeCallerData>true</IncludeCallerData>
    </appender>

    <appender name="FILE2" class="ch.qos.logback.core.FileAppender">
        <file>logs/classic.lilith</file>
        <encoder class="de.huxhorn.lilith.logback.encoder.ClassicLilithEncoder">
            <IncludeCallerData>true</IncludeCallerData>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="LogbackClassic"/>
        <appender-ref ref="FILE2"/>
    </root>
</configuration>

Lilithを立ち上げておいて、アプリを実行すると、Lilithにログが表示される。

19 Nov 2017, 08:04

データサイエンティスト養成講座を受けた感想(前半)

はじめに

データサイエンティスト協会が主催するデータサイエンティスト養成講座を受けている。

受講の動機

受講の動機は、データサイエンスに興味があり、勉強したかったから。

今まで、機械学習の勉強をしようとして、流行りのDeepLearningにばかり取り組んできた。

しかし、DeepLearningを学んでも現実の問題に適用するのは難しい。

急にAIが流行りだしたから、みんなDeepLearningを勉強し始めたが、

なんか違うというか、ズレている気がしている。

今はお祭り騒ぎのような気がしてならない。

なので、きちんとデータに向き合う力、

そしてそれを現実に応用できる力をつけるためにこの講座に申し込んだ。

裏の理由は、kaggleや DeepAnalyticsで、データがcsv形式で与えられた時、

分類問題や予測問題に取り組む力が欲しかったから。

こういう機械学習コンペの攻略法的な書籍やwebページが探しても見つからないのだ。

この講座では、DeepAnalyticsの練習問題に実際に取り組んでいくことで、

機械学習のモデル構築の手法を学ぶという実践的な講座。

受講生の人たちは、会社から派遣されてきたデータサイエンス部所属の人たちがほとんどだ。

自分は、趣味で自費(8万円!)で、しかも会社には受講していることを秘密にして受講している。

おそらくそんな人はほとんどいない。

概要

DeepAnalyticsのコンペにチームで取り組んでいく。

講座では、まずは講義がありそのあとに演習課題がだされてそれに取り組む。

演習課題はチーム内で相談しながら進めていくので、わからなくても教えあえる。

演習課題は、時間内に終わらないので、それが宿題になる。

チーム内や講義内容の情報共有は、グループウェアのサイボウズLiveが使われる。

各チームごとにグループが作成されて、情報共有できる。

各回の内容

第1回

初回の講座では、Rの基礎とモデルの評価方法が紹介される。

私は今までPythonを使ってきたので、Rのことがわからなかったので、

なれるまでは一苦労だった。

データの処理方法として、dplyrというライブラリが紹介される。

ちょうど、Javaでstreamについて勉強していたので、

dplyrはそれと比較すれば理解はしやすかった。でも、使いこなせる気がしない。。。

モデルの評価方法としてRMSEとAUCが紹介される。これらの指標は、

これからDeepAnalyticsで評価で使われるからだ。

RMSEは理解が容易だが、AUCはちょっと難しい。講座でも、AUCは時間をかけて説明された。

そのあとは、実際にDeepAnalyticsの銀行問題のデータをダウンロードして解析するという

課題が出された。そこまで難しくはない。後日、模範解答が配られ、dplyrをバリバリに

使ったかっこいい解法が紹介されていてちょっとびっくりした。

課題は、はじめは個人で考えるのだが、わからないときはチーム内で相談することができる。

なので、仲良くなる意味でも相談し合った。

第2回

機械学習アルゴリズムとして決定木が紹介される。

Rで決定木をつかうには、rpartというライブラリを使う。

決定木は、ライブラリをつかうとぱっと計算できてしまう。楽だ。

また、前回紹介されたAUCもrRocというライブラリを使うとすぐに計算できる。

そして、決定木でDeepAnalyticsの銀行問題をとりあえず解いて、

適当にパラメータチューニングしてコンテストに提出することをやった。

手元で計算したAUCよりも低い値がでる。なぜでしょう?という流れから、

過学習の説明が始まる。

過学習を防ぐために、ホールドアウト法とクロスバリデーション法が紹介される。

そのあと、パラメータチューニングの方法としてグリッドサーチが紹介される。

このあたりになると自力でのコーディングはちょっとむずかしい。

あたえられたサンプルコードを弄り回してグリッドサーチをする。

家に帰って、課題をPythonで解いてみた。scikit-learnの勉強にもなる。

しかし、どうもpythonで書いた決定木とRで書いた決定木の結果が一致しない。

なので、Rで書いていくことにした。

caretというライブラリを使うと、グリッドサーチが簡単にできるので試してみた。

しかし、caretは rpartモデルではcp, rpart2モデルでは maxdepthしかできない。

やりたいことは複数のパラメータを同時に探索することだ。

いろいろ調べたらmlrというパッケージでそれが実現できることがわかった。

mlr で グリッドサーチをして、目標だった AUC 0.9 以上を達成!

第3回

今回は、リニア系の手法ということで、ロジスティック回帰が紹介される。

kaggleのアンケート調査では、データサイエンティストが一番利用しているのは、

このロジスティック回帰だそうだ。二番目は、決定木。

その理由は、どちらも結果がわかりやすく、説明もしやすいからだそうだ。

そのままでもそこそこの精度はでるのだけれども、より精度を出すために、

データの加工方法が紹介される。

たとえば、絶対値をとったり、logをかましてデータを直線に近くなるようにする。

また、外れ値を削除した。決定木は条件を分岐していくので、外れ値はそれほど影響はないが、

このロジスティック回帰には影響がかなりある。

データをプロットして性質をつかみ、データを加工して、精度を見ていく。

だんだんデータサイエンティストっぽくなってきた。

最後におまけとして、Lasso回帰やRigde回帰も紹介される。

宿題は、ロジスティック回帰を利用して再度投稿してみること。

私は毎度のことながら、Pythonに課題を移植して取り組んだ。

データ加工は外れ値の除去をしてみたら精度が上がった。

が、他のアイデアはでなかった。しかし、そこはチームで取り組んでいるので、

他のメンバがアイデアを提案してくれた。

私は、事前に Pythonではじめる機械学習を読んでいたので、

そこにかかれていたLassoやRidge, Polynomial Featureを使って、精度を上げたがそれは注意された。

ツールを使えば簡単にいい精度がでるけれども、

それだとブラックボックスの機械を使っているだけになってしまいます。

この講座では、データの様子を良くみて、どう工夫するのかという基礎を講習しているつもりです。

なので、結果としてのスコアも大切ですが、何をしているのかを理解することはもっと重要です。

先生がたの熱意や優しさを感じたのだった。

第4回

集団学習(アンサンブル学習)について学ぶ。バギング、スタッキングが紹介される。

まずは、出力結果の平均をとる平均法が紹介される。

単純に今までの決定木系とリニア系の手法を足すだけで、精度が上がった。これは不思議。

次にバギングが紹介される。これも数式はないものの、

わかりやすい図とサンプルコードとともに紹介されるので、理解できた。

次にスタッキング。これは、理解が難しかった。

しかし、このスタッキングを紹介している書籍やウェブページはあまりないため、

この講座の資料はとても貴重なものだと言われる。たしかに、調べても検索で引っかからない。

こちらもわかりやすい図とサンプルコードが与えられるのだが、

会場にいる人のほとんどが理解できずポカーンとしてしまった。

私は、それから家に帰って4時間くらいうんうんうなってようやく理解できた。

課題は、アンサンブル学習を利用してさらなる精度向上を目指すこと。

最後にxgboostとランダムフォレストという究極秘密兵器が紹介され、頑張ってと言われる。

家に帰り、バギングとスタッキングをPythonで実装しなおした。

スタッキングがどうもバグって時間がかかったものの、

どちらもスクラッチでコーディングすることができた。

しかし、そうやって頑張って理解したものよりも、

xgboostとランダムフォレストをつかったほうが簡単にいい精度がでてしったのだった。

これはすごい。さすがはコンペで大活躍している手法のことだけある。

xgboostはパラメータチューニングが難しい。解説サイトがあったので、それを元にチューニング。

xgboostは GPUで走らせることができるので、Amazonの AWSの EC2インスタンスを借りて、

走らせた。自分のNotePCで走らせるのと比べて爆速でびっくり仰天。

最終的には、以下の結果となった。

`○投稿結果: 0.94031

○手法の工夫

○アンサンブルの工夫

  • ランダムフォレストとxgboostの結果を59:41の割合で足した。

次回は、中間発表と、後半の課題Jリーグ問題だ。後半へ続く。

18 Nov 2017, 13:53

JUnitとdbUnitを使ってPostgresのDBテストを実施する

はじめに

データベースの知識がなくって、DBのテスト方法がわからない。

そこで、データベースのテストを自動化するためのツール、dbUnitを調べてみた。

dbUnitをつかうと以下のようなことができる。

  1. JUnitのテスト実施前に、データをデータベースに投入。
  2. テスト実施後に、期待のデータと変更後のデータベースの値を比較。

データはxmlデータ, Excelデータ, csvデータが利用できる。

インストール

ビルドツールにgradleを利用しているので、gradleの設定を書く。

以下から、最新のバージョンをクリックして、gradleのコードをdependenciesに書く。

dependencies {   
    compile group: 'org.dbunit', name: 'dbunit', version: '2.5.4'
}

データのテーブル用意

データのテーブルを用意する。ここでは、flywayを使った。

buildscript {
    dependencies {
        classpath 'com.h2database:h2:1.4.191'
    }
}

plugins {
    id "org.flywaydb.flyway" version "4.2.0"
}

flyway {
    url = 'jdbc:postgresql://localhost:5434/sampleDB'
    user = 'postgres'
    password = 'postgres'
}

本題ではないので、ここでは参考リンクを貼って詳細はそちらに譲る。

以下のようなテーブルをflywayMigrateで作成。V1__create_table.sql

CREATE TABLE HOGE (
    ID INT,
    NAME VARCHAR(255),
    STATE VARCHAR(10)
);

投入データと期待データの準備

データはxml形式のものを用意する。テスト前、テスト後のデータを用意。ID=3の stateを normal から errorに書き換える。

Before.xml

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <HOGE ID="1" STATE="normal" NAME="name#1"/>
    <HOGE ID="2" STATE="normal" NAME="name#2"/>
    <HOGE ID="3" STATE="normal" NAME="name#3"/>
    <HOGE ID="4" STATE="normal" NAME="name#4"/>
    <HOGE ID="5" STATE="normal" NAME="name#5"/>
</dataset>

After.xml

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <HOGE ID="1" STATE="normal" NAME="name#1"/>
    <HOGE ID="2" STATE="normal" NAME="name#2"/>
    <HOGE ID="3" STATE="error" NAME="name#3"/>
    <HOGE ID="4" STATE="normal" NAME="name#4"/>
    <HOGE ID="5" STATE="normal" NAME="name#5"/>
</dataset>

テスト対象コード

テスト対象コードをいかに示す。やっていることは、SQL文を実行しているだけ。

package sample;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class DbUnitSample {
    private static final String SQL = "update HOGE set state = 'error' where name = 'name#3';";

    public void execute() {
        try(Connection conn = DriverManager.getConnection(
                "jdbc:postgresql://localhost:5434/sampleDB", "postgres", "postgres");
        ) {
            PreparedStatement stmt = conn.prepareStatement(SQL);
            stmt.executeUpdate();
        } catch(Exception e) {
            System.out.println("failed.");
        }
    }
}

テストコード

テストコードをいかに示す。

package sample;

import org.dbunit.Assertion;
import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.SortedTable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.File;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

public class DbUnitSampleTest {
    private static IDatabaseTester databaseTester;
    private DbUnitSample sample;

    @Before
    public void setUp() throws Exception {
        databaseTester = new JdbcDatabaseTester("org.postgresql.Driver",
                "jdbc:postgresql://localhost:5434/sampleDB",
                "postgres",
                "postgres",
                "public");

        IDataSet dataSet = new FlatXmlDataSetBuilder().build(
                new File("src/test/resources/db/dbunit/Before.xml"));
        databaseTester.setDataSet(dataSet);
        databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);
        databaseTester.onSetup();

        sample = new DbUnitSample();
    }

    @After
    public void tearDown() throws Exception {
        databaseTester.setTearDownOperation(DatabaseOperation.NONE);
        databaseTester.onTearDown();
    }

    @Test
    public void state更新() throws Exception {
        sample.execute();
        IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(
                new File("src/test/resources/db/dbunit/After.xml"));
        ITable expectedTable = expectedDataSet.getTable("HOGE");

        IDataSet databaseDataSet = databaseTester.getConnection().createDataSet();
        ITable actualTable = databaseDataSet.getTable("HOGE");
        ITable sortedTable = new SortedTable(actualTable, new String[]{"id"});

        Assertion.assertEquals(expectedTable, sortedTable);
    }

    @Test
    public void state更新2() throws Exception {
        sample.execute();
        IDataSet databaseDataSet = databaseTester.getConnection().createDataSet();
        ITable actualTable = databaseDataSet.getTable("HOGE");

        String actualState = "normal";
        for(int i=0; i < actualTable.getRowCount(); i++) {
            if (actualTable.getValue(i, "name").toString().equals("name#3")) {
                actualState = actualTable.getValue(i, "state").toString();
                break;
            }
        }
        assertThat("error", is(actualState));
    }
}

ちょっと注意するところは、sqlのupdateを実行すると、updateしたid=3が、rowの一番最後になってしまうところ。なので、テスト1では、わざわざソートして対応、テスト2では、for文で名前をキーにして検索をしている。

        ITable sortedTable = new SortedTable(actualTable, new String[]{"id"});

おわりに

手動でデータベースを書き換えてテストするのではなくて、flywayやらdbunitやら、使えるものは使って効率よく開発すべき。

しかし問題は、テストを書く時間すら今は確保できないくらい追い詰められていること。

進捗ヤバメです。(´・ω・`)

code:

18 Nov 2017, 08:27

PowerMockを使ってJavaコードをテストしてみた

はじめに

仕事で JavaのTesting Frameworkとして Spockを利用する予定があったので、一生懸命勉強していたが、政治的な理由によって Spockではなく JUnitが採用されてしまった!

というわけで、急遽 JUnitで利用できそうな Mockフレームワークを調査。

PowerMockというのがなかなかいけているので、それを調べた。

今回のテスト対象コードは、以前書いたSpock Frameworkのときのと同じです。

package sample;

public class MockSample {
    private MessageManager mgr;

    public void setMgr(MessageManager mgr) {
        this.mgr = mgr;
    }

    public MockSample() {
        mgr = new MessageManagerImpl();
    }

    public void sendMsg(String msg) {
        mgr.send(msg);
    }

    public int sendMsg2(String msg) {
        return mgr.send2(msg);
    }

    public void sendMsg3(String msg) {
        MessageManager mgr2 = new MessageManagerImpl();
       mgr2.send(msg);
    }

    public static int sendMsg4(String msg) {
        return MessageManagerStatic.send(msg);
    }

    private void sendMsg5(String msg) {
        mgr.send(msg);
    }
}
package sample;

public interface MessageManager {
    void send(String msg);
    int send2(String msg);
}
package sample;

public class MessageManagerImpl implements MessageManager {
    @Override
    public void send(String msg) {
        System.out.println(msg);
    }

    @Override
    public int send2(String msg) {
        System.out.println(msg);
        return 0;
    }
}
package sample;

public class MessageManagerStatic {
    public static int send(String msg) {
        System.out.println(msg);
        return 0;
    }
}

PowerMock Install w/ gradle

Gradleをビルドツールで利用しているので、gradleの方法を書く。

公式wikiには、Mavenのやり方が書いてあるので、そちらを参照。

build.gradleの dependenciesに以下を追加する。

もっと最新バージョンが出ているらしいが不安定だとwikiに書いてあったので、安定バージョンを。

dependencies {
    testCompile 'junit:junit:4.12'
    testCompile 'org.powermock:powermock-module-junit4:1.6.2'
    testCompile 'org.powermock:powermock-api-mockito:1.6.2'
}

テスト!テスト!テスト!

テストする内容は、比較のためSpock Frameworkと同じにしてます。

まずは、お決まりのおまじないアノテーション2つを書く

  • @RunWith(PowerMockRunner.class)
  • @PrepareForTest({MockSample.class, MessageManagerStatic.class})

    • MockSample.class … メソッド内のインスタンスモック用
    • MessageManagerStatic … メソッド内のスタティックメソッドモック用

      呼び出し引数と回数をチェック

  • times で 呼び出し回数をチェック

  • Mockito.veirfy(spy).send(“Hello”) で引数にHelloが来たかチェック

@Test
public void 呼び出し引数をチェック() {
    MessageManager spy = PowerMockito.spy(new MessageManagerImpl());

    sample.setMgr(spy);
    sample.sendMsg("Hello");
    sample.sendMsg("Hello");

    Mockito.verify(spy, times(2)).send("Hello");
}

戻り値を返す

  • when(spy.send2(“Hello”)).thenReturn(1) で 1を返す.
@Test
public void 戻り値を返す() {
    MessageManager spy = PowerMockito.spy(new MessageManagerImpl());
    when(spy.send2("Hello")).thenReturn(1);
    sample.setMgr(spy);

    int ret = sample.sendMsg2("Hello");

    Mockito.verify(spy, times(1)).send2("Hello");
    assertThat(1, is(ret));
}

メソッド内で生成されるインスタンスをモックに置き換える

  • PowerMockit.whenNiewでMessageManagerImplがnew されたときに、作成したmockオブジェクトにすり替える。

この機能は、いろんなフレームワークを試しきたが、PowerMock/Mockitoで初めて見た。

@Test
public void メソッド内で生成されるインスタンスをモックに置き換える() throws Exception {
    // https://github.com/powermock/powermock/wiki/MockConstructor
    MessageManagerImpl mock = PowerMockito.mock(MessageManagerImpl.class);
    PowerMockito.whenNew(MessageManagerImpl.class).withNoArguments().thenReturn(mock);

    sample.sendMsg3("Hello");

    Mockito.verify(mock).send("Hello");
}

staticなメソッドをテストする

オブジェクト内のメソッドからstaticメソッドを呼んでいたって、モックを利用することで、戻り値を書き換えることができる。

@Test
public void staticなメソッドをテストする() {
    // https://github.com/powermock/powermock/wiki/Mockito#mocking-static-method
    PowerMockito.mockStatic(MessageManagerStatic.class);
    Mockito.when(MessageManagerStatic.send("Hello")).thenReturn(1);

    int ret = sample.sendMsg4("Hello");

    assertThat(1, is(ret));
}

例外を発生させる

モックのメソッドが呼ばれたら例外を発生させることもできる。 PowerMockito.doThrow(new Exception).when(mock).send(“Hello”)で実現している。

@Test
public void 例外が発生しないことを確認する() {
    try {
        sample.sendMsg("Hello");
    } catch (Exception e) {
        fail(e.getMessage());
    }
}

@Test(expected = IllegalStateException.class)
public void 例外が発生したこと確認する() throws Exception {
    MessageManagerImpl mock = PowerMockito.mock(MessageManagerImpl.class);
    PowerMockito.doThrow(new IllegalStateException()).when(mock).send("Hello");
    PowerMockito.whenNew(MessageManagerImpl.class).withNoArguments().thenReturn(mock);

    sample.sendMsg3("Hello");
}

おわりに

PowerMock, メソッド内で生成されるインスタンスをモックに置き換える機能がとても強力。

しかし、最大の問題点は、ドキュメントが少ないことだ。いろいろネットで情報を漁ってみたものの、情報量が少ない。

やっぱりSpockを使いたいなあ。

今回のコードはgithubにもあげています。

08 Oct 2017, 03:25

mlrを使って決定木(rpart)の複数パラメータのグリッドサーチをする

はじめに

Rでグリッドサーチをするためのパッケージとしては、caretが有名なのだが、

決定木でグリッドサーチをしようとすると、一つのパラメータについてしかできなかった。

  • rpartモデルではcpのみ
  • rpart2モデルではmaxdepthのみ

やりたいことは、cp, maxdepth, minbucketパラメータを同時にグリッドサーチをしたい。

自力でやろうとすると、for文が3つの入れ子構造になって大変だ。

いろいろ調査したら、mlr(Machine Larning for R)というパッケージで

複数パラメータに対して、グリッドサーチがかけられるとわかったので、そのメモを残す。

今回のJupyter Notebookは gistにあげています。以下抜粋。

mlrでグリッドサーチ

今回の題材は、毎度おなじみの kaggleタイタニック問題を利用する。

前処理を自分でやるのがだるかったので、以下の記事の内容を利用することにした。

以下の記事を参考にして、タイタニック問題のためのコードを書いた。

以下の範囲を指定してグリッドサーチ。

gs <- makeParamSet(
    makeDiscreteParam("cp", values = c(1e-4, 1e-5)),
    makeDiscreteParam("maxdepth", values = seq(5,10,1)),
    makeDiscreteParam("minbucket", values = seq(10,100,10))
)

すると、指定した範囲の組み合わせを総当りに計算していく。

最終的に、best scoreとなった値が出力されて終了。

それを提出したら、titanicのランキングでスコアが上がった。やった。