世界の隅からhello world

情報系大学生の備忘録

ひらがなくずし字のMNIST,KMNISTを試してみた

ひらがなくずし字のデータセットKMNISTが公開されたので,早速試してみました.

KMNISTとは?

https://github.com/rois-codh/kmnist/blob/master/images/kmnist_examples.png?raw=true (画像引用元:https://github.com/rois-codh/kmnist

人文学オープンデータ共同利用センターから公開された,MNIST形式のひらがなくずし字データセットです.

「お,き,す,つ,な,は,ま,や,れ,を」計10種のひらがなくずし文字について,28x28のグレースケールの画像が訓練データ60,000枚,評価データ10,000枚収められています.このとおりMNISTの形式に揃えられており,Fashion-MNIST[1]のように,いわば"alt-MNIST"として利用できます.データセットは以下のgithubリポジトリからダウンロード可能です.

github.com

NeurIPS 2018のworkshopでお披露目されたようで,論文はarXivで公開されています[2] (https://arxiv.org/abs/1812.01718).

人文学オープンデータ共同利用センターのアナウンスページで,ひらがなくずし字のデータセットをMNISTの形式に合わせを公開した意図が説明されています.

codh.rois.ac.jp

しかしKuzushiji-MNISTは、10個の文字種と十分なサンプルを揃えており、機械学習の研究などにすぐ使えるデータセットとなっています。MNISTの変種としてのKMNISTを気軽に使ってみながら、くずし字を対象とした研究に興味をもつ研究者が増えていってほしいと思います。またこのデータセットは、文字認識に限らず文字生成など様々な研究にも利用できるため、自由な発想でデータセットを使いながらくずし字を対象とした研究の多様性が拡大することを望んでいます。さらにそうした研究の広がりを通して、くずし字×機械学習の研究に関する社会の認識が向上することで、KMNISTの基礎となるくずし字データセットへの協力と活用がさらに広がっていくことが、我々の長期的な目標です。

ぜひ元ページを読んでいただきたいのですが,中々にエモいマニフェストになっています.言葉の端々から,「機械学習界隈の人たちにも是非人文学の世界へ目を向けてもらい,新しい世界を一緒に作っていきたい」という熱い思いを感じます.

KMNISTを隠れ層2層の多層パーセプトロンで分類

それならば是非試してみよう,ということで,おなじみchainerのMNISTサンプルコードを改変し,KMNISTを試してみました.

chainer/examples/mnist at master · chainer/chainer · GitHub

モデルは1000ユニットの隠れ層が2層の多層パーセプトロンです.学習にはCPUを使います.

実験環境は以下の通りです.

Thinkpad X1 Carbon 2017 (intel Corei7 7th-Gen)
ubuntu 18.08 LTS
python 3.6.1
chainer 6.0.0b1

なお,大したものではないですが,本記事で使ったコードはGithubリポジトリで公開しています. github.com

データのダウンロード・データの確認

https://github.com/rois-codh/kmnistで公開されているデータセットから,npz形式のものをダウンロードしました.訓練・評価ごとに画像とラベルの計4つのnpzがあります.

$ mkdir -p data
$ wget http://codh.rois.ac.jp/kmnist/dataset/kmnist/kmnist-train-imgs.npz -P data
$ wget http://codh.rois.ac.jp/kmnist/dataset/kmnist/kmnist-train-labels.npz -P data
$ wget http://codh.rois.ac.jp/kmnist/dataset/kmnist/kmnist-test-imgs.npz -P data
$ wget http://codh.rois.ac.jp/kmnist/dataset/kmnist/kmnist-test-labels.npz -P data

データの形式を確認します.

>>> train_imgs = np.load("data/kmnist-train-imgs.npz")["arr_0"]
>>> train_imgs.shape
(60000, 28, 28)
>>> train_imgs.dtype
dtype('uint8')
>>> train_imgs[0]
array([[  0,   0,   0,   0,   0,   0,   0,   0,  10,   7, 233,  86,   0,
          0,  32,  99,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,  54, 255,  84,   0,
          0,   7, 151,  19,   0,   0,   0,   0,   0,   0,   0,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0, 152, 251,  14,   0,
          0,  25, 155,  98,   0,   0,   0,   0,   0,   0,   0,   0,   0,
          0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0, 129, 248, 188,   0,   0,
          0,  80, 250, 191,   1,  78,  51,   0,   0,   0,   0,   0,   0,
          0,   0], ...
  • 値は0-255のnp.unit8
  • 1画像は(28, 28)の2次元配列

で保存されているようです.

matplotlibで可視化してみた結果がこちら. や

データの前処理

chainer mnistのサンプルに合わせ,次の処理を行います.

  • 255.で割って [0, 1] に正規化
  • (28, 28)の2次元配列を(784,)の1次元ベクトルにflatten
    train_data = np.load(args.train_imgs)['arr_0'].\
                 reshape((60000, 784)).astype(np.float32)/255.
    train_labels = [int(n) for n in np.load(args.train_label)['arr_0']]
    train = TupleDataset(train_data, train_labels)

    test_data = np.load(args.test_imgs)['arr_0'].\
                reshape((10000, 784)).astype(np.float32)/255.
    test_labels = [int(n) for n in np.load(args.test_label)['arr_0']]
    test = TupleDataset(test_data, test_labels)

Datasetクラスは,mnistのサンプルと同様にTupleDatasetを使っています.

学習

以上でchainerのmnistサンプルの改変は終わりです.簡単です.では,学習を回してみます.

$ python train_kmnist.py
Device: <CpuDevice (numpy)>
# unit: 1000
# Minibatch-size: 100
# epoch: 20

epoch main/loss validation/main/loss main/accuracy validation/main/accuracy elapsed_time
1 0.301962 0.403972 0.9072 0.8797 19.6462
2 0.112909 0.344197 0.9651 0.9063 41.2962
3 0.0662489 0.326582 0.979183 0.9127 65.2197
4 0.0421354 0.363997 0.9866 0.9126 87.8175
5 0.0315507 0.428015 0.990017 0.9074 111.145
6 0.0290646 0.468858 0.99055 0.9088 134.062
7 0.0266913 0.439887 0.991733 0.9149 155.707
8 0.0216323 0.485592 0.993117 0.911 178.109
9 0.0213224 0.486939 0.9936 0.9149 200.794
10 0.0204854 0.460457 0.994033 0.9201 225.533
11 0.0177287 0.547921 0.994717 0.9106 249.207
12 0.017653 0.508776 0.99485 0.9183 272.926
13 0.0115246 0.521045 0.996683 0.9208 297.484
14 0.0167068 0.510293 0.995117 0.9251 330.113
15 0.0166416 0.544714 0.995233 0.9212 363.777
16 0.0128668 0.611589 0.996233 0.9147 390.308
17 0.0136382 0.545968 0.9963 0.9185 419.165
18 0.0130388 0.627543 0.996267 0.9132 446.094
19 0.0092608 0.570508 0.997167 0.9236 472.661
20 0.0103855 0.663491 0.99695 0.914 498.62

グラフはこちら.

kmnist_loss_cpukmnist_accuracy_cpu
KMNIST学習時のロスとaccuracyの変化(CPU)

validation accuracyは3 epoch前後で0.92付近に達し,それ以降のepochではvalidation lossは上昇していますね.

ちなみに,本家のMNISTの学習時のロスとaccuracyの変化はこちら.

元祖MNIST学習時のロスとaccuracyの変化(CPU)

KMNISTに比べ,元祖MNISTの方がaccuracyは高く,lossは小さくなっています.KMNISTのほうが難しいデータセットと言えそうです.

まとめ

ひらがなくずし字のデータセットKMNISTを,chainerのMNIST用サンプルコードをごく一部改変し,学習を行いました.

MNISTの形式に合わせくずし文字のデータセットを公開したのは,とても素敵なアイディアだと感じます. 本稿での実験のように,ほんの少しコード修正でAlt-MNISTとして使えますし, 日本で育った人間としては,くずし文字のデータセットを実験に使えるのはとてもわくわくするものです.

深層学習界隈は,精度競争をはじめとして,ときに心をすり減らすような場面も多々ありますが, 少し目を転じてみれば,童心に返るような,素敵なテーマはたくさんあるものだなと感じた一時でした.

reference

[1] Xiao et al, "Fashion-MNIST: a Novel Image Dataset for Benchmarking Machine Learning Algorithms", arXiv:1708.07747, 2017.

[2] Clanuwat et al, "Deep Learning for Classical Japanese Literature", NeurIPS 2018 Workshop on Machine Learning for Creativity and Design, 2018.

cookpad 実践型サービス開発 5-days internship 2016 に行ってきた! 前編

去る9月12日(月)から16日(金)までの5日間,cookpad 実践型サービス開発 5-days Internship 2016にエンジニアとして参加してきました.

8月末に行ったDeNAの3dayインターンと共に,自分のプログラム観が破壊され,そして再生した衝撃的な体験でした.なんとなくプログラムを書き散らしていた大学生が,たった5日間でプログラミングで人様の役にたつにはどうすればいいだろうか本気で考え始め,挙句の果てにそこらのアプリやウェブサービスにケチをつけ始めるようになった(偉そうに),またプログラムでものを作る楽しさを再認識し,何やら色々なものを作り始めた,そんな5日間...

cookpadインターンはどんなものであったか,この記事を紹介したいます.どこかインターンに行きたいとな思っており,cookpadインターンに興味がある方の参考になれば幸いです.


この前編では,cookpadインターンを詳しく知りたい人に向けて,インターンの5日間の生活を細かく振り返り,インターンでは具体的に何をするのか紹介します.後編では,インターンの中で学んだクックパッドのサービス開発の姿勢,またインターン選考,自分の感じたことなどを書くつもりです.手っ取り早くcookpadインターンで何が学べるのか,どうすれば受かるのか知りたい人は後編をどうぞ.

また,今後も何度か加筆修正するつもりです.

 

そもそもどういうインターン

実践型サービス開発・5-days Internship

エンジニア・デザイナーで小さなチームを組み、サービス開発を行う5日間のインターンシップです。
クックパッドのサービス開発の考え方に基づきながら、小さなチームでスピーディーにものづくりを体験することができます。期間中は社員がメンターとなり、毎日フィードバックを受ける機会を設ける予定です。
 
"ユーザーファーストなモノづくり"をクックパッドの社員と一緒に体験しましょう。

 
インターン生のエンジニア1人,デザイナー1人でペアを組み,与えられたお題を基にサービス開発を行います.初日の午前中にはcookpadのサービス開発についての講義,また定期的に社員の方からフィードバックがあります.今年は「一人暮らしの料理が楽しくなる施策」というテーマでした.大体,始めの2,3日がアイディアの練り込み,残りの2,3日,実装といったスケジュールです.今年は特にプラットフォームの指定はなく,作るサービスはウェブサービスでもiPhoneアプリでもオッケーでした.

ここで注意.社員さんの言葉を借りれば,「Cookpadのサービス開発を学ぶ」ことがこのインターンの目的ではありません.本当の目的は「5日間,(事実上の)cookpadの社員」として,本気で「価値のサービスを開発する」ことです.全力でサービス開発を行う中で「サービス開発とはなんぞや」を掴みとる,という意味でまさに実践的です.

因みに,お昼ごはんは社員の方が作ってくれます.これが本当に美味しくて美味しくて...5日間で健康になった気がします(本当に).

また,毎日お昼はインターンに参加してくださる エンジニアやデザイナー,ディレクターなどの方と文字通り机を囲んで食べます.自分は機械学習の勉強をしているので,cookpadでは機械学習はどう用 いられているか聞いたりしました.

5日間の記録

インターン

前週の土日にインターンのSlackに招待されました.インターン担当の人事の方に促されて各々が自己紹介.参加するメンバーは,エンジニア5人,デザイナー5人の計10人でした.また,このタイミングでエンジニアとデザイナーのペアが発表されました.


1日目 - キックオフ

1日めは,イントロダクションと,講義,そしてサービス開発開始です

午前

9時頃@恵比寿ガーデンプレイス12階でインターン生が初顔合わせ.場所を移動して,午前中は自己紹介,インターン概要説明,クックパッドのサービス開発についての講義などがありました.ここでサービス開発のテーマが示されます.先述したとおり,今年は「一人暮らしの料理が楽しくなる施策」でした.

講義では,cookpadが「サービスかくあるべし」と思っている姿と,それをいかに実現しているかが説明されます.cookpadは,使う人が本当に使いたいと思っているもの(しかも本人が意識しているとは限らないもの)を作ろうとします.しかし,それを実現する真の答え,最も良い方法は誰にも分からない.そこで,トライアンドエラーを繰り返す方法によってそれを見い出そうとしているそうです.


ちなみに,方法論としてはリーン開発という考え方をベースにしているようです.参考として次の書籍を勧められました.

 

Lean Analytics ―スタートアップのためのデータ解析と活用法 (THE LEAN SERIES)

Lean Analytics ―スタートアップのためのデータ解析と活用法 (THE LEAN SERIES)

 

 
知っている人は知っている内容だと思いますが,このインターンではそれを実際に実行し,しかも成功させている方々の話を聞け,さらにその人たちにフィードバックまでもらえます.すごいことだ.
これら,講義を受けたcookpadの方法論は後編でもう少し詳しく触れる予定.

相方とも初の顔合わせ.大学では,(上手く表現出来ないけれど)ソフトウェア開発の人間的な側面を研究されているそう.UXやチームビルディング,等々,自分の知らない話を色々聞かせてもらい勉強になりました.色々な人がいて色々な分野の話を聞ける,というのも実践型インターンのいいところかも.

午後

一人ぐらしの友人二人に電話で,また料理好きなエンジニアの社員の方に直接インタビュー.聞き取った内容から,一人暮らしの人が料理するときどんな問題を抱えているだろうか,どうすればそれを解決できるだろうか話し合いました.

18時半で一応は終わりですが,20時半ぐらいまで残れます.一日ごとに,その日何をやったかなどを書いた日報をメールで提出します.それに対してメールで人事の方からフィードバックを頂けます.

f:id:mofumofuchan1:20161019174327j:plain

cookpadのデザイナーの方が書いたスマホのデザインの本をもらいました!うれしい.エンジニアにもわかりやすくとてもためになります.本当にいい本でした.

 

 

 

中々いいサービスのアイディアが見つからないため,家に帰ってからLINEで数人にインタビューをするなかで,本当に簡単な料理はクックパッドで中々見つけられない,という問題を発見.そこで,いわゆる”ズボラ飯”を扱ったサービスを作ろう,という方向性が決まりました.

2日目 - アイディア出しの罠にまんまとはまる

2日目もサービスのアイディアを練ります.午後には,考えたサービスのアイディアを社員の方に説明し,アドバイスを頂くフィードバックの時間と,チームごとのメンターの方との相談タイムがあります.

午前

深夜決まった”ズボラ飯”レシピサイトというアイディアを基に,このサービスの具体像を詰めてゆきます.”ズボラ飯”は誰のためのものか,どのような価値があるのか,どのような使われ方をするのか,cookpadで実際に用いられている価値仮説シート,EOGS(Emotion Oriented Goal Setting)などという枠組みを使って考えました.
ただ,次第に考えることが目的になってしまい,そもそもこのサービスはなんのために作るのかを忘れていってしまいました.


午後

午後,勇んで「ズボラ飯サイト」のアイディアを持って行き,講師の社員の方からフィードバックを頂きました.ですが,返ってきたフィードバックは「何をしたいのかはっきりしない」.アイディアを作りこむのに熱中した結果,そもそも「誰が,どういうことをしたいけど,こういう課題があるから,このサービスに価値がある」という,一番大切な基本(価値仮説)をすっかり忘れていたのでした.
もう一度価値仮説シートを引っ張り出し,そもそも何をやりたかったのかもう一度話し合うことに.メンターのディレクターさんと色々相談しました.

 

3日目 - 中間発表で作るものがようやく決まる

3日目には,プレゼンをきちんと用意して行う中間発表があります.今年は全てのチームではなく,人チームごとに行われました.大体3日目に作るサービスが決まります.
因みに,自分のチームでは3日目まで一行もコードを書いていません.他のチームも大体同じで,午後ぐらいから少しずつ実装を始めるチームが出始めました.
良いサービスを本気で作ろうとすると,本当に腹落ちするものを見つけるのは本当に難しい.

午前

前日のメンターさんとの相談などを受け,自分たちの班はどんぶり料理のレシピサイトを作ることに決まりました.ここに至るまで何度案を作り,検証し,壊したことか...もう一度,価値仮説やユーザーストーリーなどを作り直し,サービスのUI/UXのプロトタイピングを始めます.

午後

いよいよ中間発表です.最終日の発表と同じセッティングで,プレゼンを使って発表します.どんぶりレシピというアイディアに絞ったことは評価されたものの,そのどんぶりレシピサイトでどう料理が楽しくなるのかと聞かれる.また,どんぶりレシピに絞るのであれば,レシピ検索機能とかいらないのでは,とのアドバイス.アドバイスを受け,必要な機能を削り,”自分が作れる料理を”というコンセプトに行き着く.

ここでcookpad2016インターンのTシャツがプレゼントされる.最終日に着よう.

4日目 - 実装で手こずる

4日目は,ついに実装を始めました.

午前

まずどのように開発するか話し始める.必要な機能をリストアップし,それを付箋に書いて紙に貼ってゆきました.チケット駆動というものだそうです.
さて,ここからがエンジニアの腕の見せ所と意気込んでいたのですが,ミスを犯して午前中をポシャにしてしまいました.サービスが極めてシンプルになったので,html+css+javascriptだけで実装してみようとしたのですが,上手く行かず断念.結局rails+herokuで実装することにしました.今考えれば当然なのですが,限られた時間で実装する場合は,使い慣れた道具を使うべきでした.

午後

数時間ほどで基本的な機能は完成.ここでまたミス.サービスを実現するのには必要ない機能を追加しようとして,バグを出してしまいました.夕方,何も表示されない画面を見て相方呆然.そりゃそうだよな....操作感など,ユーザー体験に直接関わってくるような部分をチューニングすべきでした.

都心に済む友人宅に転がり込む事態に.結局またほとんど一から書き直し,何とか夜中完成.ほっと胸をなでおろしました.

その頃,相方はセレブシティ恵比寿@大都会東京で美容師さんに声を掛けられ(すごい),さらに髪切られながらPC開いてプレゼンしていたらしい(すごい)


5日目 - 完成,発表,終宴

いよいよ最終日.午後に発表と,最優秀チームの表彰,そして打ち上げです.


午前

自分が持ってきたrailsのソースに相方が作ってくれたCSSや素材を組み合わせます.ですが,なんだか上手く動かず...色々試行錯誤したあげく,なんとか昼前に動きました.ドツボにハマったとき,抜け出せるかどうかはやはり経験の数によりますね.DeNAインターンの経験に引き続き,学生のうちに何か一つ言語/フレームワーク/分野を極めようという気持ちになりました.

午後

いよいよ最終発表が近づきます.プレゼンは得意な相方に任せ,自分はデザインの修正に取り組みます.ただ,webデザインの経験がほとんどなかったため,四苦八苦...デザイナーの方に助けを求めましたが,やはりすごい.細かいアドバイスを頂けました.
そしてついに発表.プレゼンの得意な相方のおかげで,自分たちのやったことをきちんと伝えることが出来ました.

そして審査員の社員の方からのフィードバック.どんぶりを見せる,提案するというとこに絞ったのは悪くない.しかし,そこまで一点に絞ったのだから,それをどう見えるのか,デザインにもっともっとこだわって欲しかったとの意見.例えば,mp3プレイヤーは色々ありましたが,完璧に完成された形で提示したiPodによって世界は変わったよね,など.また,絞るのは良いけれども,どんぶりだと,料理と食材,両方とも縛ってしまって,広がりがないのではないか,とのアドバイスも.

他のチームはどこも素晴らしいクオリティでした.単に思いつきではなく,懸命に考えた結果のプロダクトであることが端々から伝わってくるプレゼンでした..優勝チームは実装力,デザインともに5日で(しかも徹底的なアイディアの洗練の時間まで含めて)創ったとは思えない圧倒的なクオリティでした.優勝も納得.そのスライドを引用させていただきます.

speakerdeck.com


そして,ついに終宴.普通のインターンではここでお店に出かけるものですが,ここはcookpad.宴を彩る豪華な料理の数々も社員の方が,しかもインターン担当の人事の方も!作っていただいたものでした.

f:id:mofumofuchan1:20161019174555j:plain


学生同士,社員の方,お酒も入って楽しく話しました.話はプログラミングの話から,愉快な話まで,自由に飛んでゆき,幸せな一時でした.頑張った充実感は何よりもの料理のスパイスですね.

びっくりなことに,冊子を用意して頂いていた!!!感動!

インターン生はそのあと居酒屋に繰り出して,お互いの検討を讃え合いました.
本当に楽しく,充実した5日間でした.

 

後編へ続く.

ブログ、はじめました。

はじめまして。現在、大学でコンピュータの勉強しているmofumofuです。

 

プログラミングについて、また趣味であるジャズ、読書などについて、あるいは日々の雑感、記録、等々を不定期にマイペースに書き綴るブログです。

 

以後、お見知りおきを。よろしくお願いします。