Quantcast
Channel: クックパッド開発者ブログ
Viewing all 801 articles
Browse latest View live

データ分析からUI改善

$
0
0

こんにちは。サービス開発部デザイナーの平塚です。

クックパッドでは一部のデザイナーは日々の業務でSQLを書いて数値を見たり、リリースした施策の分析を行っています。 このエントリーでは機能をリリースしてデータ分析し、そこからUI改善を行った事例について紹介したいと思います。

なぜデザイナーがデータ分析?

サービスやプロダクトを改善するには現状について定性的・定量的の両方を理解しておく必要があります。
そのため、自分が進める施策やデザインするものを数値で把握しておくことで、より納得感を持って施策を進められます。
データ分析というと数学や分析の深い知識が必要そう…と構えてしまう印象ですが、日頃から自分の担当分野の基本的な数値を見ておくだけでもデザインで悩んだときの判断材料として使えるなど、デザイナーが数値をみる利点は多々あります。

分析の流れ

私は最近からデータ分析に取り組み始めたのですが、今はこのような流れで分析しています。

1.分析に必要な数値・グラフを決める

GitHubで分析用issueを立てて何を知りたいのか、そのためにはどんな数値をどんな形で見れると良いかを決めてから数値出しに進みます。

2.数値を出す

数値を出したらSQLが正しいかエンジニアにレビューしてもらいます。 レビューが通ったら数値から考えられることをチームで話しながら分析します。

3.分析レポートにまとめてGitHubのPull Request(以下PR)をだす

f:id:tsukasio:20170911145527p:plain

分析レポートを「仮説・試算・実数・考察・次のアクション」で整理してPRを出します。
レビューを受けることでさらに理解を深めるきっかけになったり、客観的な意見でアイディアをもらえたりします。
また、サービス開発部ではディレクター定例で施策の共有を行っていて、施策の分析結果はこのPRを共有しています。
ディレクター定例についてはこちらで詳しく説明されています。

つくれぽを簡単に送れる機能の分析

一部のユーザ向けに、よく見たレシピを利用したつくれぽを簡単に送れる機能を公開し、仮説通りの効果はえられたのか?どのように使われているのか?などを分析しました。

f:id:tsukasio:20170911145848p:plain

分析を進めていくうちに、アプリを起動してかたつくれぽを送るまでの推移をファンネルグラフでみたところ、離脱ポイントが2つあることがわかりました。

  • 「投稿する」の分岐で離脱
  • レシピをフリックしてから離脱

f:id:tsukasio:20170911145750p:plain

まず「投稿する」の分岐での離脱はどんなユーザーが離脱しているのか調べました。結果はつくれぽを送ったことがないユーザーがほとんどで、興味本位で「投稿する」をタップしていた可能性がありそうです。
次に、つくれぽしようと思ってこの画面に来たのにフリックした後離脱してしまうのはなぜかを考えました。

  • つくれぽを送れるレシピがなかった
    • 実際には作っていなかった?
  • 料理画像がなかった
    • レシピをみて料理を作ったが料理画像を撮り忘れた?
  • つくれぽしようと思うレシピがわからなかった
    • 似たようなレシピが複数並んでいた?
    • レシピ名をきちんと覚えていなかった?

いくつか仮説を立てた中で、3つ目はUIで解決できそうだということになり改善を進めました。

UI改善

この機能のデザインをした時に考えたことは、新しい機能とはいえつくれぽを送るというアクションなので、ユーザーが戸惑わないように既存のつくれぽ画面を参考にデザインしました。また、さくさく送れる感じを出したかったのでレシピをフリックして見れるようにしました。
ただ、既存のレシピ詳細画面からのつくれぽはすでにレシピを決めているので、つくれぽ画面ではレシピ名だけでもスムーズにつくれぽできていたという違いに気づきました。
この機能はつくれぽ送信画面に来てからつくれぽするレシピを探すので、どのレシピかがきちんと分かるUIが良いのではと思い、レシピ画像とレシピ作者名を入れたUIに変更しました。

beforeafter
f:id:tsukasio:20170911150004p:plainf:id:tsukasio:20170911150637p:plain

まとめ

現在は施策を企画する段階とリリース後の2つのタイミングで定量データを見ることを心がけています。
漠然とした「使いづらい」「分かりづらい」から改善を進めるのではなく、定量的なデータからその機能がどう使われているかを把握した上で仮説を立てると、より良い改善に繋がります。
ただ数値がすべてというわけではなく、定量データから見えない課題はユーザーテストで掘り下げるなど定量分析・定性調査をバランスよく見ていくと良いと思います。


料理きろくにおける料理/非料理判別モデルの詳細

$
0
0

研究開発部の菊田(@yohei_kikuta)です。機械学習を活用した新規サービスの研究開発(主として画像分析系)に取り組んでいます。 最近読んだ論文で面白かったものを3つ挙げろと言われたら以下を挙げます。

クックパッドのアプリには「料理きろく」という機能があります。 携帯端末から料理画像のみを抽出して表示することで自分が食べたものを振り返れるようになっており、ここからレシピ投稿やつくれぽを送ることもできるようになっています。

20170914153231

料理きろくはユーザ数が約12万8千人、累積の写真判別枚数が約7900万枚、そのうち料理と判別された画像が約960万枚(数字は20170912時点)と多くの方々に使っていただいている機能です。 本記事では、その料理きろくのコアの技術部分である、機械学習による料理/非料理判別の詳細に関してお伝えします。 料理きろく全体のアーキテクチャに関してはここでは述べませんが、ご興味のある方は AWS Summit Tokyo での発表資料をご覧ください。

料理きろくの背景と機械学習の役割

我々は、新しい技術を駆使してユーザ体験をより良いものに改善することで、クックパッドの使用頻度を増やしてもらったり、ユーザからもっとレシピやつくれぽを投稿してもらう、などの目標を持っています。 料理きろくはその目標に資する一つの施策であり、これは携帯端末に大量の食事情報が記録されていることから、それを活用してクックパッドのサービスに連携することを狙いとしています。 過去の自分の食事を振り返ることで食への楽しみや関心を高めてもらい、そこからレシピやつくれぽ投稿につなげたいというのが最初のターゲットとなっています。

ちなみに料理きろくではユーザのプライベートな画像を判別することになるため、全てサーバ上で処理がなされ、我々はユーザの画像を一切閲覧できないようになっています。

料理きろくにおける機械学習の役割は、料理/非料理を判別する高性能のモデルを提供することです。 機械学習によって正確に画像の料理/非料理が判別できるかどうかがサービス全体の質に直結するため、ここに Convolutional Neural Network (CNN) を用いたモデルを適用しました。 一口に CNN と言っても実に多様なので、データも拡充しながら、様々なモデルを試行錯誤をして改善を図りました。

以降では本番環境にデプロイしたモデルを中心に、どのような試行錯誤で改善をしていったのかをご紹介します。

最初にデプロイしたモデル

  • モデル:CaffeNet
  • データ:{料理,非料理}の二値ラベルの画像データ
  • フレームワーク:Chainer

最初のリリースでは CaffeNetというモデルを使っています。 これは ILSVRC2012で優勝した AlexNetを少し変更したもので、pooling が Local Response Normalization の前に来ています。

最初の段階では、素早くリリースまで持っていきたい、社内に画像分析の知見がまだ蓄積していなかった*1、などの理由で、事例も多いこのモデルを採用しました。 データはシンプルに料理画像と非料理画像をとりあえず手当たり次第に集めたものを使用しました。 テストデータも集めた画像の一部をテスト用に切り出して、料理判別の精度と再現率をチェックするというごくごく基本的な手法でした。

本番運用に際しては、精度が低いと料理ではないものが表出されてユーザ体験が悪くなるという考えのもと、再現率をある程度犠牲にしても精度を高めるという方向で閾値を調整しました。 単純な二値判別では softmax の出力が0.5を超えれば料理と判別されることになりますが、このモデルでは閾値を0.9で設定しました。 これは閾値を変えながらテストデータでの結果を目視でチェックしながら定めたものです。

最初のモデルは手探りの部分も多かったですが、素早くリリースまで到達できたことは非常に良かった点で、継続的改善を遂行していける土台が整えることができたので後の改善につながりました。

一回目のモデルアップデート

  • モデル:Inception-v3
  • データ:{料理,非料理,複数の間違えやすい非料理カテゴリ}の多値ラベルの画像データ
  • フレームワーク:TensorFlow

最初にデプロイしたモデルでも結構精度が高かったのですが、自分たちでも使っていくうちに間違いやすい画像があることが分かってきました。 具体的には植物や赤ちゃんの画像などが間違いやすい傾向があることが判明したため、これらの画像にもロバストなモデルを作りたいという要望が出てきました。 また、CNN のモデルも様々な発展があるため、それらを検証してより基本的な性能が高いモデルを採用したいという考えもありました。

そこで、まずは様々な CNN のモデルを比較検証をして良いモデルを探すという実験をしました。 この頃には画像分析ができる人員も増えていたため、手分けをして実験をして GHE の wiki に情報を集約し、最終的に我々のデータセットに対して最も良い結果を出した Inception-v3を採用することにしました。 モデルとして試したのは、{Inception-v3, GoogLeNet, ResNet, VGG, GAN を使った classification, NIN(軽量なモデルにも興味がある), …}、です。

フレームワークに関しても、TensorFlow を使う人が多くなったため、Chainer から切り替えました。 モデルの学習には Keras with TensorFlow backend を使っていますが、本番にデプロイする時は TensorFlow のみで動かすようにしています。 料理きろくのアーキテクチャはモデル部分を疎結合にしてあるので、この変更はそれほど大きなコストもなく実現できました。

次に単純な二値判別では問題として単純化しすぎているのではという考えのもと、多値判別に切り替えるという実験をしてみました。 思考回路としては、仮に世の中の料理画像の全集合が手に入ればその補集合が非料理画像だがそれは不可能→モデルは我々が集めた(非)料理画像の集合から(非)料理らしさを学習→これらは多様なので一つのカテゴリに集約し切るのは無理がありそう→特に間違いやすいものに関しては陽にカテゴリを作ってそちらに誘導したほうが我々が望むモデルができそう、という感じです。 料理/非料理ともに画像(二値ではなく多値のラベルを付与したもの)を追加収集して、それぞれが単一カテゴリ(この場合は多値の情報を潰して二値として扱う)の場合と複数カテゴリの場合とで性能を比較しました。 モデルの出力は一般に多値になりますが、判別結果としては多値の情報を潰して料理/非料理の二値判別として扱うようにしています。 全体的な性能を上げつつ特に精度を高めるものとして、料理は単一カテゴリとして非料理は多値カテゴリ(具体的には植物や人物を含む5カテゴリ)として扱うことに決定しました。

これらの改善によって、手元のデータで試験したところ、精度も再現率も向上し、特に間違えやすかった植物の画像に対しては間違いが約 1/3 に、赤ちゃんの画像に対しては間違いが約 1/20 ほどになりました。

これの取り組みは以前クックパッドで開催された Cookpad Tech Kitchenでも発表しています(発表資料)。

また、2017年度 人工知能学会全国大会やIJCAIのワークショップとして開催された 9th Workshop on Multimediafor Cooking and Eating Activitiesなどの学術的な場でも発表をしています。

二回目のモデルアップデート

  • モデル:Inception-v3 + patched classification
  • データ:{料理,非料理}の二値ラベルの画像データ、それらを14×14のパッチにしたもの
  • フレームワーク:TensorFlow

一回目のアップデートで大きく改善はしましたが、画像中に人と料理が同時に写っている場合はモデルが判断に迷う(人と判断すべきか、料理と判断すべきか)という問題が残っていました。 我々は「画像中の一部を切り取ってクックパッドのレシピとして掲載できそうなものは料理と判断する」という基準で料理/非料理を判断しているので、十分に料理が写っているのにモデルが非料理と判断されているものは改善の余地がありました。

この問題に取り組むために、まずはマルチラベルの判別をすることを考え、そのために Keras の ImageDataGenerator 辺りを改修したりもしましたが、データ準備のコストが高いため一旦保留としました。 次に、問題の根本は複数のものが写っているのにそれらをまとめて判別してしまっていることだと考え、画像をパッチに分割してパッチ毎に料理/非料理を判別するというモデルを構築しました。 具体的には、通常の Inception-v3 の出力付近で使う GlobalAveragePooling と Dense を、Conv2D や Dropout などを組み合わせて出力が 14×14×1 にするように置き換えて、sigmoid の出力で binary cross entropy を計算するようにしています。 パッチに分けることで料理と非料理を区別しやすくなることが分かったため、再び二値分類のモデル(ただしパッチ毎)になっています。 パッチサイズの 14×14 に関してはいくつかのパターンを実験した結果最も良い結果を返すものを選択しました。

このモデルの学習にはパッチ毎にラベルが付与されたデータが必要ですが、これは単純に元データをパッチに分割して、全パッチに元データと同じラベルを付与するという作り方でデータ準備を簡略化しました。 ただしこの作り方だと特に画像の端の部分が悪さをする可能性があるので、適切なラベルが得られるように一部の画像を crop したりもしています。

また、本番にデプロイした場合の性能を見積もるために、本番でのデータ分布に近くなるように社員から許諾を得て携帯端末のデータを提供してもらいました。 プライベートな画像のため、閲覧権限を絞って、特定の人が正解ラベルを付与してそれを使ってモデルの詳細な性能検証を実施しました。

このような改善を経て本番環境にデプロイされたモデルの結果の一例が以下の図となります。 色がついている領域が料理らしさが高い領域で、閾値以上のパッチを取り出してその領域が一定以上であれば料理と判別するというモデルになっています。

20170914153255

この改善によって、テストデータに対して精度を落とさずに再現率を5%以上改善することができました。 料理きろくは1000万というオーダーで画像を処理しているので、改善のインパクトは大きなものとなります。

モデル構築に使用したデータ

クックパッドには大量の料理画像があるので正例のデータには事欠きませんが、モデルの学習には負例のデータも重要になるため Creative Commons のデータや社員からデータを集めたりして様々な画像を収集しました。 プロジェクトの進行と共に画像を追加して試行錯誤してという作業を繰り返し、結果としてトータルで数十万枚程度の画像を扱いました。

どのような画像が重要になったかは上述のモデルアップデートでもご紹介しましたが、改めてモデルの性能向上に重要であった特徴的なデータをいくつか挙げたいと思います。

  • 料理 
    当然ながら正例としての料理画像は最重要のデータとなります。 クックパッドの豊富な料理画像データを用いて充実したデータセットを構築することができました。
  • 人(特に赤ちゃん) 
    人物画像は判別を間違えた場合のリスクも高い(ユーザ体験の観点から)ため、負例の中でも特に気をつけて画像を収集して学習に用いました。
  • 植物 
    想像に難くないですが、色合いや形状から誤判別される場合が多かったのが植物の画像でした。
  • 植木鉢 
    植物と似ていますが、植木鉢の場合は器もあるためにより一層誤判別されるものが多かったです。 そのため意識して負例としてデータを収集しました。
  • 料理が乗っていない空の皿
    料理には皿がつきものなので、皿があれば正例と勘違いしかねないため何も乗っていない皿も負例としてデータに追加しています。
  • 本番運用時にモデルが扱うデータ分布に近いテストデータ
    本番ではユーザの携帯端末中の画像が対象ですが、学習は収集したラベル付きの限定的なデータを用いているので、モデルの正しい性能が測りづらいという問題があります。 ユーザの画像は我々も閲覧できないため、この問題はオフライン/オンラインに限らず原理的な問題です。 そこで、許諾を得た社員のスマホのデータを使い、人力でラベルを付け、これを使ってモデルの評価を実施しました。 プライベートな画像であるため、閲覧権限を必要最低限の人間に絞って詳細な性能評価をして、他の人には統計情報のみを共有するという手法を採りました。

やはり学習データは最重要ですね。 料理きろくにおいては、多くの人の協力によって様々なデータを収集することができたので、非常に心強かったです。

今後の展望

料理きろくのプロジェクトを通じて、やはり継続的な試行錯誤に基づいた適切な改善策を講じることが重要であることが再認識できました。 それゆえに、これで完成ではなく、日進月歩の Deep Learning 技術を取り込んだり、データを拡充したりして、よりユーザにとって有用なモデルを構築し続けるのが大事だと考えています。

例えば最新の SENetや料理ドメインに特化した 横方向に広くスライスした畳み込みを試してみたり、自分たちで使いながら判別を間違った画像を収集してその傾向を探る、より高速に動作するモデルを構築するなど、改善の方向性は様々です。

「自分ならもっと良いモデルが作れる!」という人がいましたら是非一緒にやりましょう。

おまけ

以前 Twitter で話題になっていた画像として、犬と食べ物の区別が難しい画像というものがありました。 みなさんは下の画像のどれが犬でどれが食べ物かが判別できるでしょうか? 遠目で見ると判別はかなり難しい感じがします。

20170914153246

画像は以下から引用させていただきました。
左の画像:https://twitter.com/teenybiscuit/status/707727863571582978
右の画像:https://twitter.com/ohmycorgi/status/867745923719364609

これらの画像に我々の料理/非料理判別モデルを適用して、料理画像だけを抽出してもらうとしましょう。

20170914153237

見事に料理画像だけを選び出すことができました! Deep Learningのモデルが適切に料理とそれ以外を区別できていることを伺い知ることができます。

これ以外にも、近い内容の話として 弁護士の柿沼太一先生との対談などもあります。 ご興味があれば是非ご覧ください。

まとめ

クックパッドアプリの料理きろくという機能で用いている料理画像判別技術に関してお伝えしました。 CNN のモデル自体はもの凄く特殊なものを構築しているわけではありませんが、試行錯誤を経たモデルの変遷やその過程で遭遇したタスク特有の問題点などに興味を持っていただけたなら幸いです。 本記事でお伝えしたのは一例であり、クックパッドでは様々なサービスにおいて、発展著しい機械学習の技術をユーザに有益なものへと昇華させる取り組みに日々励んでいます。

いかがでしたでしょうか。 クックパッドでは、機械学習を用いて新たなサービスを創り出していける方を募集しています。 興味のある方はぜひ話を聞きに遊びに来て下さい。 クックパッド株式会社 研究開発部 採用情報

*1:このプロジェクトが始まった段階では私はまだ入社していませんでした

Cookpad Tech Kitchen #10を開催しました。

$
0
0

f:id:tsukasio:20170915160252p:plain

こんにちは、サービス開発部デザイナーの平塚です。

2017年9月13日(水)に、クックパッドオフィスにてデザイナー向けイベント「Cookpad Tech Kitchen #10」を行いました。

f:id:tsukasio:20170915160042j:plain

今回は「自社サービスで取り組むデザイン」をお題に、開発現場での実践事例を交えながら各社の文化やデザイナーの働き方についてご紹介しました。

お集まりいただいた皆さまの熱量も高く、イベントスタート時からQAセッション、懇親会に至るまで、とても充実した時間を過ごさせていただきました。 ご来場いただいた皆さま、本当にありがとうございました。

また今回は多数応募をいただいたため残念ながら抽選に漏れてしまった皆さま、たいへん申し訳ありません。 こういったイベントは今後も開催していきたいと思いますので、またのご参加を心よりお待ちしております!

一部ですが、イベントで行った各プレゼンテーションの概要をご紹介します。

「"料理の追体験"を実現するデザイン」

  • 若月 啓聡(Cookpad/デザイナー)

新機能タイムラインのデザインや、チームのユーザーとの関わり方についてお話を聞くことができました。

f:id:tsukasio:20170915160058j:plain

「はてなブログの世界観になじむ機能デザイン」

  • 松井 沙織(はてな/デザイナー)

はてなブログの新機能やUI変更の中で、書くことを邪魔しないデザインについてお話を聞くことができました。

f:id:tsukasio:20170915160114j:plain

「温度のあるサービスづくり」

  • 木坂 名央(GMOペパボ/デザイナー)

minneの、作家に向き合った温かみのあるデザインについてお話を聞くことができました。

f:id:tsukasio:20170915160133j:plain

「自然さを追求した音楽体験のためのUX」

  • 冨樫 晃己(CyberAgent/デザイナー)

AWAの、現実世界にありえる自然な動きについてお話を聞くことができました。

f:id:tsukasio:20170915160153j:plain

QAセッション

パネルディスカッションでは、

「UIデザイナーとUXデザイナーは兼任していますか? 実際の所UIとUXの兼任は難しいと思うのですがどのように分業や兼業していますか?」

「ドッグフーディングをチーム内で浸透させるのにはどうしていますか?」

といった参加者からの質問について、各社の取り組みについてより深く触れていただきました。

f:id:tsukasio:20170915164720j:plain

これからも楽しいイベントを企画していきます。 今後ともよろしくお願いします!


【クックパッドではデザイナー/エンジニアを積極採用中です】
ユーザー体験に向き合ってサービス開発をしたいデザイナーやエンジニアの方は、下記をご覧ください。

クックパッド採用情報 | UX/UIデザイナー
https://info.cookpad.com/careers/jobs/careers/ux-ui-designer
クックパッド採用情報 | エンジニア
https://info.cookpad.com/careers/jobs/careers/type/engineer

Synthetic Monitoring を活用したグローバルサービスのネットワークレイテンシの測定と改善

$
0
0

インフラ部 SRE グループの渡辺(@takanabe)です。普段はクックパッドのグローバルサービス (https://cookpad.com/us) のインフラの開発や運用をしています。

クックパッドは、21 言語・67 カ国以上を対象にサービスを展開しています ( 2017 年 6 月末時点)。今後もその数を増やしていく予定です。 世界中で使われるサービスのインフラを開発していく上で、乗り越える必要がある課題は沢山ありますが、その中でも、ユーザが利用するクライアントとクックパッドのインフラをむすぶネットワークのレイテンシは特に大きい課題です。 本稿ではなぜグローバルに利用されるサービスにおいて、ネットワークレイテンシが問題になるのか、また、クックパッドではネットワークレイテンシをどう計測し改善しようとしているかについて解説します。

ネットワークレイテンシとは

ユーザがサービスにリクエストを送ってからレスポンスを受け取るまでにかかる時間 (レスポンスタイム) は、主にネットワークレイテンシとアプリケーションの処理時間の合計です。 アプリケーションの処理時間短縮もサービスのレスポンスタイム改善には有用ですが、グローバルに展開されたサービスにおいてはネットワークレイテンシも大きなオーバーヘッドになりえます。この両方を改善していくことがユーザ体験向上のために重要です。本稿ではネットワークレイテンシについてご紹介します。

ネットワークレイテンシは大きく分けると以下の 4 つから構成されています。

  • 伝播遅延: クライアントがパケットを送出してから私達の管理するサーバに到達するまでの時間(あるいはその逆方向の通信にかかる時間)
  • 伝送遅延: パケットがリンクに載るまでの時間
  • 処理遅延: ルータがパケットのヘッダをチェックして宛先を決定するまでの時間
  • キューイング遅延: ルータのパケット処理待ち状態の際にバッファキューで待機する時間

一方で私たちが普段ネットワークレイテンシという言葉を使う場合は、往復の伝搬遅延、つまり Round-trip-time を意味することが多いです。本稿でもネットワークレイテンシ(以下レイテンシ)を Round-trip-time (以下 RTT ) の意味で使います。

グローバルサービスとレイテンシ

クックパッドのグローバルサービスのサーバは現在 AWS の米国東部リージョンに集約されているため、サービスの通信は基本的にはユーザの居住地と米国との間を往復することになります。

サーバが米国東部リージョンに集約されていることで、米国や米国近辺に住んでいるユーザはレイテンシが小さくなります。一方で、アジアや中東など地理的に遠い国に住むユーザにとってはレイテンシを悪化させる要因の一つとなっています。例えばリクエストがネットワークを伝わる速度を光速( 300,000 km / sec)とし、日本から米国東部までの距離を 11,000 km としたとき、レイテンシは約 73.3 ms になります。現実には、サーバまでのネットワークの経路は一直線ではありません。加えて、伝送において 300,000 km / sec もの速度が出ることはないためレイテンシはさらに大きくなります。*1

f:id:takanabe_w:20170920163049p:plain

例として、東京の私の家から Amazon S3 の東京リージョンのエンドポイントと米国東部リージョン( us-east-1 )のエンドポイントに ping を打つと以下のように平均レイテンシは前者は約 22.2 ms、後者は約 186.2 ms でした。

# AWS の東京リージョンのエンドポイントに ping を打った場合
> ping -t 5 s3-ap-northeast-1.amazonaws.com
PING s3-ap-northeast-1.amazonaws.com (52.219.68.108): 56 data bytes
64 bytes from 52.219.68.108: icmp_seq=0 ttl=50 time=21.811 ms
64 bytes from 52.219.68.108: icmp_seq=1 ttl=50 time=20.666 ms
64 bytes from 52.219.68.108: icmp_seq=2 ttl=50 time=24.138 ms
64 bytes from 52.219.68.108: icmp_seq=3 ttl=50 time=22.797 ms
64 bytes from 52.219.68.108: icmp_seq=4 ttl=50 time=21.750 ms

--- s3-ap-northeast-1.amazonaws.com ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 20.666/22.232/24.138/1.167 ms

# AWS の米国東部リージョンのエンドポイントに ping を打った場合
> ping -t 5 s3.us-east-1.amazonaws.com
PING s3.us-east-1.amazonaws.com (54.231.120.114): 56 data bytes
64 bytes from 54.231.120.114: icmp_seq=0 ttl=43 time=179.987 ms
64 bytes from 54.231.120.114: icmp_seq=1 ttl=43 time=208.230 ms
64 bytes from 54.231.120.114: icmp_seq=2 ttl=43 time=176.016 ms
64 bytes from 54.231.120.114: icmp_seq=3 ttl=43 time=182.457 ms
64 bytes from 54.231.120.114: icmp_seq=4 ttl=43 time=184.399 ms

--- s3.us-east-1.amazonaws.com ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 176.016/186.218/208.230/11.357 ms

164 ms のレイテンシの差がユーザに与える影響

HTTP がクライアントとサーバ間の通信の往復から成っていることを考えると、この 164 ms のレイテンシの差がユーザが快適にサービスを使えるかに大きな影響を与えます。例えば、クックパッドは HTTPS を利用して暗号化された安全な通信をユーザに提供しています。 HTTPS に利用されている TLS 接続を確立するには下図のように TCP ハンドシェイクに 1.5 往復、 TLS ハンドシェイクに 2 往復の通信が必要です。

f:id:takanabe_w:20170920163203p:plain

(https://hpbn.co/transport-layer-security-tls/#tls-handshake Figure 4-2. TLS handshake protocol より引用)

TLS ハンドシェイクの Client Hello メッセージは TCP ハンドシェイクの ACK と同じタイミングで送出されることから、 TLS 接続には正味 3 往復必要になります。 つまり RTT の 3 倍の時間がかかります。

この TLS 接続が成立するまでの時間を先程例に上げた東京と東京リージョンの往復で換算すると、22.2 x 3 = 66.6 msの時間がかかることになります。一方で、東京と米国東部リージョンの往復で換算すると、186.2 x 3 = 558.6 msの時間がかかることになります。

その差は 492 ms です。 この数値は一見問題にならないようにも感じられますが、Jakob Nielsen の著書 Usability Engineering ではレスポンスタイムには3つの境界値が存在すると言われています。

0.1 second is about the limit for having the user feel that the system is reacting instantaneously, meaning that no special feedback is necessary except to display the result.

1.0 second is about the limit for the user’s flow of thought to stay uninterrupted, even though the user will notice the delay. Normally, no special feedback is necessary during delays of more than 0.1 but less than 1.0 second, but the user does lose the feeling of operating directly on the data.

10 seconds is about the limit for keeping the user’s attention focused on the dialogue. For longer delays, users will want to perform other tasks while waiting for the computer to finish, so they should be given feedback indicating when the computer expects to be done. Feedback during the delay is especially important if the response time is likely to be highly variable, since users will then not know what to expect.

(Jakob Nielsen, “Usability Engineering”, 1993, pp 135)

これによると人間はリクエストを送出して 100 ms 〜 1 sec 以内のレスポンスでも遅延を感じるとされています。つまり、 164 ms のレイテンシの違いが生む 492 ms の差はユーザの体験を悪化させる要因に成り得るのです。

今までのクックパッドのレイテンシ対策

クックパッドのグローバルサービスは、日本のサービスとは使われているリージョンやコードベースが異なりますが、cookpad.com ドメインを共有しています。 同じドメインにおいて異なるアプリケーションにリクエストを振り分けるため、ロードバランサ (ELB) 下のリバースプロキシでリクエストがグローバルサービスのもの (/uk, /id など) か日本のサービスのものかを判定してルーティングをしています。 ただ、アプリケーションがリージョンを跨いでいるのにリバースプロキシを 1 リージョンに置くだけではリバースプロキシが無いリージョンへのリクエストが遅くなってしまうため、 同様の設定がされたリバースプロキシを東京 (ap-northeast-1) と米国東部 (us-east-1) リージョンに配置し、Amazon Route 53 のレイテンシベースルーティング*2を利用して DNS ベースでユーザーからレイテンシの低いリージョンへ最初にリクエストを送信させるようにしています。 これにより、ユーザーから近いリージョンのロードバランサにアクセスできるというメリットがあります。

以上のようにレイテンシを増加させる要因はサーバと利用するユーザの所在や使っている技術により異なります。クックパッドの場合サービス利用者が多いインドネシアなどではこのレイテンシの問題は顕著に現れてきています。

レイテンシの計測方法

レイテンシを改善するにはレイテンシがどのような要素から成っており、何をした時にどのくらい改善されたのか、あるいは悪化したのかを定量的に評価しなければなりません。これを実現するにはレイテンシやレスポンスタイムなどのメトリクスを計測し続ける必要があります。

サービスのレイテンシを計測する方法を大別すると、以下の二つが挙げられます

  • Synthetic Monitoring
  • Real User Monitoring(RUM)

Synthetic Monitoring は専用の監視サーバからリクエストを送出して計測します。一方で RUM はユーザのクライアント上で実際にかかった時間そのものを収集します。この2つの方法はどちらが良いと言うわけではなく、集計の粒度も計測する対象も異なるため組み合わせて使うものです。今回は平均的な統計情報をまず取得し、その上でレイテンシを悪化させている要因を分析するという目的があり、Synthetic Monitoring を導入することにしました。

Synthetic Monitoring “Catchpoint”

クックパッドは Catchpoint Systems の Synthetic Monitoring サービス(以下 Catchpoint )を利用しています。 Catchpoint を選択した理由は他の Synthetic Monitoring ツールと同様の日別パフォーマンスの比較ができる点、 Waterfall Chart などの基本的な機能を有している点、 UI がシンプルである点で条件を満たしており、加えて監視サーバのノード数とロケーションの数が他社のものより多いためです*3。サービスの世界展開を目指しているクックパッドにとってこれは重要な機能のひとつです。

Catchpointによるパフォーマンスの分析

パフォーマンス解析機能による全体像の把握

Catchpoint では計測対象のエンドポイント、監視サーバ群、監視の頻度など監視に関する条件を定義するテストを作る必要があります。この記事では https://cookpad.com/usに対して複数の国の監視サーバからアクセスする “Global top page” というテストを用意しました。

パフォーマンス解析の機能を使うことでこの Global top page テストで定義した各国の監視ノードから https://cookpad.com/usにアクセスした際のレスポンスタイム(ms)を確認できます。例えば、2017年2月25 - 27日の3日間を対象に横軸を日時、縦軸をレスポンスタイムにして描画するとこのようなグラフが得られます。

f:id:takanabe_w:20170920163403p:plain

ご覧の通りテストで選択した監視サーバの国別のレスポンスタイムを俯瞰することができています。これをみるとインドネシア、アルゼンチン、エジプトなどの国のレスポンスタイムが相対的に悪いですね。グラフの上にポインタを乗せると他のメトリクスを確認できたり、この時間帯の Waterfall chart に飛ぶこともできます。 Waterfall chart については後述します。

また、 Geo chart という機能を使うと監視サーバそれぞれでパフォーマンスメトリクスの一つを地図上で可視化できます。以下ではサーバにリクエストを行って最初の1バイトが到着するまでの時間を示す Time To First Byte(TTFB)を表示しています。インドネシアは TTFB が他国と比較して長いことがわかります。物理的な距離が影響しているかもしれません。

f:id:takanabe_w:20170920163426p:plain

このようにおおまかなパフォーマンスメトリクスをパフォーマンス解析機能で確認し、当たりをつけ、その後より細かい分析を行うのが自然な流れかと思います。次は上記で確認したインドネシアのパフォーマンスを Waterfall chart で分析していきたいと思います。

Waterfall chartを使ったパフォーマンスボトルネックの分析

Waterfall chart の画面では特定のエンドポイントに特定の監視サーバからアクセスしたときのパフォーマンスメトリクスの詳細な分析ができます。例えば、2017年2月26日12時にインドネシアのジャカルタの監視サーバから https://cookpad.com/us ( Global top page テストを利用)にアクセスした時の Waterfall chart の画面はこのような感じです。ご覧の通り、名前解決や TLS 接続などを含む TTFB 、レンダリング開始、対象のページのレンダリングが完了したことを表す Document Complete などの時間が確認できます。 f:id:takanabe_w:20170920163450p:plain

また Waterfall chart を見るとどのリクエストがパフォーマンスに悪影響を与えているかが簡単にわかります。 Global top page テストの場合 cookpad.com/us にアクセスした際の最初のリクエストの TTFB で全体の約1/3の時間を要しています。さらに、TTFB の内訳を確認すると名前解決や TLS 接続に多くの時間を割いている事がわかります。本稿の最初に TLS ハンドシェイクについて言及しましたが、ここで計測された TLS 接続に必要な時間を短くする事は、すなわちレイテンシの改善につながります。

f:id:takanabe_w:20170920163504p:plain

またいわゆるクリティカルレンダリングパスが赤く塗りつぶされているのでどのリクエストをパフォーマンス改善のターゲットにすれば良いのかが分かりやすくなっています。以上が Cacthpoint の基本的な機能と使い方の紹介になります。他にもダッシュボードを作って public url で共有できたり、トランザクション処理のあるリクエストのボトルネックを解析したりと様々なことができます。

クックパッドでの Catchpoint の使用例

ここまでわかればこれらをどのように改善すべきかという手段の話ができるようになりますね。当初の目的の通りレイテンシを改善するのであれば相関関係が強い名前解決、TLS 接続、TTFB などを改善する方法を少し検討してみます。

サーバのマルチリージョン展開によるレイテンシ改善効果の調査

米国東部に集約しているサーバをインドネシア付近のデータセンタにも展開した場合 RTT はどのように変わるでしょうか。簡単な効果測定は Catchpoint の Instant Test 機能(定期的な計測ではなく任意の監視サーバから任意のエンドポイントに単発のリクエストを実行する機能)を使うことでできます。インドネシアの監視サーバから AWS の米国東部( us-east-1 )、東京( ap-northeast-1 )、シンガポール( ap-southeast-1 )の各リージョンに対して ping を打った結果を比較すると、インドネシアは米国東部や東京よりシンガポールの方が RTT は小さくなることがわかります。

f:id:takanabe_w:20170920163546p:plain

AWS のシンガポールリージョンを使うことでインドネシアのレイテンシは改善されそうですね。わざわざ現地に行かずとも世界中の監視サーバからのリクエストのパフォーマンスが計測できる Instant Test はとても便利です。

CDNの導入によるレスポンスタイム改善効果の調査

CDN の導入もレイテンシの改善に効果があります。CDN は主にキャッシュ用途で使われることが多いですが、今回は TCP と TLS の 終端のためだけに使っています。ユーザーとの接続を近いサーバで終端することで、レイテンシに大きく寄与する TCP および TLS ハンドシェイクの時間を短縮します。CDN のエッジサーバからオリジンとなるアプリケーションサーバへの TLS 接続は HTTP Keep-Alive により再利用することで、さらにレイテンシを短縮することができます。

クックパッドのグローバルサービスでも全てのリクエストを CDN を経由させる施策を進めています。しかし、全てのユーザに大きな影響がある上、それなりにコストをかける必要があるため、 CDN 導入後に改善効果がありペイするのか、 どの CDN を導入すれば良いかなどの検証を Catchpoint で行いました。 以下は CDN 利用前と Fastly と X 社の CDN を利用した場合のある API のレスポンスタイムの比較です。

f:id:takanabe_w:20170920163619p:plain

これを見るとインドネシアのユーザに対しては Fastly と X 社 共にレスポンスタイムの改善効果があるとわかります。現在はグローバルサービスには部分的に Fastly を導入しています。TLS 接続や全体のレスポンスタイムは以下のようになりました。期待していた通り、 TLS ハンドシェイクの短縮やレスポンスタイムの改善がされています。

f:id:takanabe_w:20170920163639p:plain

余談ですが、2017年7月中頃までは Fastly を導入するとアルゼンチンのユーザのレスポンスタイムは悪化するという計測結果が出ていました。その時点で Fastly もブラジルにデータセンタ、 いわゆる Point of Presence(POP) を持っていたのですが期待した結果が得られなかったため原因を調べました。 すると、当時アルゼンチンからのトラフィックではブラジルの POP が使えない状態であることがわかりました。その代わりに米国西部の POP が使われていたのです。計測せずに導入していた場合、大きなコストをかけてユーザ体験を悪化させていた可能性がありました。現在は Fastly でもブラジルの POP のキャパシティが拡張*4されて POP 数も増えました*5。南米のユーザのレスポンスタイムを改善する際の一つの手段となり得ると思います。

おわりに

この記事ではクックパッドのグローバルサービスにおいてなぜレイテンシが問題になっているのか、それを Catchpoint でどのように計測改善しようとしているのかについて書きました。

Catchpoint で日々レイテンシの計測をしているため問題の解決に集中できる環境が整いましたが、グローバルサービスのパフォーマンス改善はまだ始まったばかりです。今後は RUM の導入やパフォーマンス計測によって得た結果をレイテンシやレスポンスタイムの改善に活かし、世界中のユーザがサービスをより快適に使えるようにしていきたいと思っています。

参考文献

  • Jakob Nielsen, “Usability Engineering”, 1993
  • A・S・タネンバウム, “コンピュータネットワーク第4版”, 2003
  • 竹下隆史, 村山公保, 荒井透, 苅田幸雄, “マスタリングTCP/IP 入門編 第5版”, 2012
  • Ilya Grigorik, “High Performance Browser Networking”, https://hpbn.co/

たのしくなるコードレビュー

$
0
0

こんにちは!サービス開発部でAndroidアプリの開発をしている加藤(@k0matatsu)です。

みなさんコードレビューしていますか?
最近ではとりいれているチームも多いと思いますが、良い効果をもたらしてくれる一方で、負荷の高い作業でもあります。
また、コードレビュー自体に馴染みの薄かった人はなにをどうしたらいいのか難しいですよね。
同僚から得たアドバイスと自分なりのノウハウをあわせて、コードレビューの指針を考えていたので公開してみようと思います。

前提として、クックパッドではGitHub Enterpriseとプルリクエストを使った開発プロセスを採用しています。
また、コードレビューの前には自動テストと静的解析ツールによる単純なフォーマット、コードスタイル、頻出バグのチェックは行われているものとします。
静的解析による機械的なチェックはコードレビューよりも低コストで有効な方法ですので是非取り入れてみてください。

コードレビューの目的

なにをやるかの前に、なぜやるかをハッキリさせておくことはとても大事です。
目的を明確にしておくことで、判断が必要になった際に指標になります。

コードレビューの目的は会社やチーム、レビュアーとレビュイーの関係性などによって様々ですが、私は次の二軸に比重を置いています。

  • 品質向上
  • スキルアップ

品質向上

プログラムを書いているのは人間なので、ミスが発生します。
コンパイラや静的解析をすり抜けて来るものもありますし、全体の設計に沿っているかなど、人間でなくては確認が難しい要素もあります。
コードレビューを行うことで、複数人の違う視点が入るため、ミスを検出し「読みにくい」などの感覚的な部分のフィードバックも得ることができます。
ここで言う品質とは、バグの量ではなく、可読性やメンテナンスのしやすさも含めたソースコード全体の品質をさします。

スキルアップ

コードレビューの中で疑問を解決したりアドバイスを得ることで自分自身が知り得なかった情報を得ることができます。
自分のスキルに不安があっても、疑問を感じた部分を積極的に質問していくことで多くの学びが得られます。
一方的な査読ではなく、双方向コミュニケーションの場と捉えることでレビュアーとレビュイー双方のスキルアップが期待できます。

何に注意するべきか

チェックすべき項目は多岐に渡りますが、次のような部分を重点的に確認します。
ここであげる項目の他に、ドメイン知識など他の開発者よりも詳しい分野があれば、その知見を使ってフィードバックを行います。

  • アーキテクチャ・設計
  • 挙動
  • 改善

それぞれどのようなチェックを行うか、掘りさげて見ていきましょう。

アーキテクチャ・設計

目的に沿った設計がされているか、全体のアーキテクチャに沿った設計になっているかを確認します。
具体的には次のようなところを重点的に確認しています。

  • 単一責任原則: ひとつのメソッドに違う目的の処理を入れない
  • 命名: 一連の処理の中で統一されているか
  • 粒度: プルリクエストを分割した方がいい部分はあるか

また仕様に疑問を感じた場合も、コードレビューと一緒にその仕様で問題ないか確認してもらいます。

挙動

主に準正常系を見ていきます。
Androidの場合はとくに次の場合に予期せぬ挙動をすることが多いので注意しています。

  • バックキーが押されたとき
  • バックグラウンドから戻ったとき
  • 画面回転をしたとき

改善

より良い書き方があれば指摘します。
AndroidではSDKにTextUtilsやDateUtils、Uri.Builderなどの便利クラスが存在します。
この手のクラスは存在自体が知られてない場合もあるため、積極的にオススメしていきましょう。
標準ライブラリ以外にも、チーム内で運用している便利クラスやメソッドは新しいメンバーは知らないことが多いです。

手順

ここまで、コードレビューの内容部分をみてきました。
次はどのような手順でレビューを行っているかを記します。
人によってやりやすい方法は様々ですが、参考になれば幸いです。

  1. 内容を把握する

    • どのような目的で書かれたコードなのか、主な変更点などをdescriptionを読んで確認します
    • 必要な情報が足りなければ追加をお願いすることもあります
  2. 軽いチェックを行う

    • typoや粒度、明らかな間違いなど、ブラウザから差分を見ただけですぐに判断できる問題が無いか確認します
    • この時点でたくさん問題が見つかった場合は一旦修正を待ってから次のステップへ進みます
  3. 挙動を確認する

    • 実際の挙動を確認します
    • 前に上げたとおり、準正常系をメインに正常系と、切断などの簡単な異常系も確認します
    • 挙動が確認できないものや、確認する必要がないもの、微細な修正の場合はスキップする場合もあります
  4. 細かいチェックを行う

    • 挙動が問題なければソースを読んで細かいチェックを行います
    • 必要があればコードを手元に持ってきて、呼び出し箇所を調べることもあります
  5. 修正後の確認

    • 修正差分の確認を行います
    • 修正量によりますが、コミット内容だけをチェックする場合と、ステップ2からチェックしなおす場合があります

このように、コードレビューを軽いチェックと細かいチェックの2層に分けています。
作業の合間などに軽いチェックを行い、まとまった時間が取れるときに細かいチェックをすることで、レビュイーに素早くフィードバックが返せるように心がけています。
他にも、なるべくポジティブなコメントもつけるようにすることで心理的負担を減らす工夫をしています。
冒頭で軽く触れた、静的解析による機械的なチェックもレビュアーの負担を軽減するための取り組みのひとつです。

おわりに

コードレビューは業務の中でも集中力を要する大変な作業のひとつではないでしょうか?
技術によって人間が負担する部分を減らしていくのが理想ではありますが、コードレビューは多くの学びを得られるチャンスでもあります。
自分なりの手順を決めてこなせるようになってくると、今まで気が重かったタスクも楽しく進められると思います。
やっていきましょう。

Cookpad Ruby Hack Challenge 開催報告

$
0
0

f:id:koichi-sasada:20170929111101j:plain

技術部の笹田です。Ruby インタプリタの開発をしています。先日、RubyKaigi 2017 のために、広島に行ってきました(その話はまた別途)。

本記事では、2017/08/30, 31 に弊社で開催した Cookpad Ruby Hack Challenge (RHC) の模様についてご紹介します。

短いまとめ:

RHC の概要

Cookpad Ruby Hack Challenge は、Ruby インタプリタ(MRI: Matz Ruby Interpreter)に対して機能を追加したり、性能向上させたりする方法、つまり Ruby インタプリタを Hack する方法を、二日間かけてお伝えするイベントでした。細かい中身の話はせずに、最低限必要となる手順を一通り体験してもらう一日目と、自由にハックを行う二日目にわけて行いました。

イベント申し込みページにて6月末から7月末まで募集をしたところ、10人の定員に100名近くのご応募を頂きました。急遽、定員を5名追加し、15名定員としました。加えて、記事を執筆いただくために池澤あやかさんにご参加いただき、また弊社から4名の希望者が(サポート要員をかねて)参加しました。当日欠席は1名のみで、19名+私、という体制で行いました。

参加者とのコミュニケーションは Gitter を用いました。https://gitter.im/rubyhackchallenge/Lobbyという場所で連絡を行ったり、質問を受け付けたりしました。また、Ruby コミッタの集まる場所を https://gitter.im/ruby/rubyにも作り、Ruby の質問ができる状態にしましたが、遠慮したためか、参加者からの質問は、あまりありませんでした。

イベントの流れ

初日は基礎編、二日目は応用編という流れでした。

一日目は基本的に座学で、資料に沿って進めて頂きました。 解散が 17:00 と早いのは、私が保育園へお迎えに行かなければならないからでした。

二日目に、好きなテーマに挑戦してもらいました。また、その間にサブイベントとして、「まつもとゆきひろ氏 特別講演」「Ruby開発者との Q&A」を行いました。これらを開催するために、毎月行っているRuby開発者会議を、裏番組として同時開催してもらいました。

8/30 (水) 一日目

  • 10:00 オープニング
  • 10:30 ハックに必要となる事前知識の講義
  • 12:00 ランチ
  • 13:00 共通課題
  • 16:00 発展課題の紹介と割り振り
  • 17:00 解散

8/31 (木) 二日目

  • 10:00 発展課題の開始
  • 11:30 まつもとゆきひろ氏 特別講演
  • 12:00 Ruby開発者を交えてのランチ
  • 13:00 Ruby開発者との Q&A セッション
  • 14:00 発展課題の再開
  • 18:30 打ち上げパーティー

一日目 基礎編

f:id:koichi-sasada:20170929111031j:plain

https://github.com/ko1/rubyhackchallengeにある資料をもとに、説明を聞いてもらい、演習を行ってもらう、というように進めました。

資料をざっとご紹介します。

  • (1) MRI 開発文化の紹介
    • MRI の開発は、誰がどのように行っているのか、大雑把に説明しています。
    • バグ報告の仕方など、一般的な知識も含んでいます。
  • (2). MRI ソースコードの構造
    • MRI のソースコードの構造を紹介し、演習として、MRI をビルドしてもらいました。
    • 演習といっても、実際に行う手順は書いてあるため、その通りに手を動かしてもらう、というものになっています。ここで扱った演習一覧を抜き出します。
      • 演習: MRI のソースコードを clone
      • 演習: MRI のビルド、およびインストール
      • 演習:ビルドした Ruby でプログラムを実行してみよう
      • 演習:バージョン表記の修正(改造)
  • (3) 演習:メソッドの追加
    • 実際に、MRI に機能を追加していきます。
    • 次のようなメソッドを、演習として追加してもらいました(手順はすべて記述してあります)。
      • Array#second
      • String#palindrome?
      • Integer#add(n)
      • Time#day_before(n=1)
    • また、拡張ライブラリの作り方や、デバッグに関する Tips を補足しています。
  • (4) バグの修正
    • バグの修正方法と、バグの報告の方法について紹介しています。
    • 次の二つのケースについて、具体的な話を紹介しています。バグ発見の技術的な方法に加え、心構えみたいなことも書いているので、そこそこ実践的な内容だと思いますが、どうでしょうか。
      • 他の人のバグ報告を見る場合(Kernel#hello(name)という架空のメソッドを例に)
      • バグを自分で発見してしまった場合(Integer#add(n)という架空のメソッドを例に)
  • (5) 性能向上
    • 性能向上についての諸々の話を書いています。
    • このあたりは、最後の方に書いたので、だいぶ雑になっています。演習もありません。

読むだけで進められるように書いたつもりなので、興味がある方は、読んで実際に手を動かしてみてください(読んでもわからない、という場合は、どの辺がわかりづらいか、こっそり教えてください)。

二日目 応用編

発展課題として、いくつか課題の例をあげておきましたが、これに限らず好きなことに取り組んで頂きました。ただ、こちらにリストした内容を選んだ人が多かった印象です。取り組んで頂いたテーマは、GitHub の issue でまとめてもらいました https://github.com/ko1/rubyhackchallenge/issues

いくつかご紹介します。

Hash#find_as_hash の実装

Hash#findの返値が配列なので、Hash を返す版が欲しい、という新規メソッド開発の挑戦です。が、1要素の Hashを返しても使いづらい、ということに気づいたそうで、nice try! ということで、終わりました。

フレームスタックの可視化

VM の状態を可視化するために、各フレームの状態を JSON で出力する仕組みを作り、そしてそれを表示するビューア https://github.com/kenju/vm_stackexplorerを作ってくださいました。懇親会でデモまで行ってくださいました。一日でここまでできるとは。

help に --dump オプションを追加

ruby -hで出てくるメッセージに不足があったので、足しましょう、という提案です。この挑戦を行ったのは Ruby コミッタの sonots さんで、さすが手堅い、実際に困ったんだろうな、という提案です。

なお、参加者に Ruby コミッタの sonots さんも混ざっているのは、サポート役としてお願いしたためです。後で伺ったら、曖昧にしていたことが多く、得るものは多かったということです。

Procに関数合成を実装

Proc#composeという、二つの Procを合成する、いわゆる関数合成を行うためのメソッドを提案されました。一度試したことがあったそうで、C で書き直し、似たような提案のチケットにコメントとして追記してくださいました。コミッタを交えたパーティーでは、この仕様についていろいろと議論が盛り上がりました。

ビルドしたRubyでのGemのテスト

開発中の Ruby で、任意の gem のもつテストを行うことができる、という仕組みの提案です。私がほしーなー、と言っていたら、作ってくださいました。

最近の Ruby には bundled gem という仕組みで、いくつかの Gem をインストール時に同時にインストールする仕組みがあるのですが、それらの Gem のテストを簡単に行う方法がありませんでした。また、人気の Gem(例えば、Active Support とか)も、同様に試すには、一度インストールして、bundleして、... といくつかの手順を必要としていました。この提案では、これらのテストを、Ruby をインストールせずに makeコマンド一発でできるようになります。MRI 開発者が(人気の)Gem を動かせなくなるような変更を入れる前に気づくことができるように(多分)なります。

サブイベント

二日目の途中に、Ruby 開発者会議で来ている Ruby コミッタに頼んで、下記のイベントを行いました。

まつもとさんゆきひろさんによる特別講演

f:id:koichi-sasada:20170929111037j:plain

大雑把に「30分でいい話をしてください」と依頼したら、いい話をしてくださいました。話の詳細は、池澤さんのレポート記事( Rubyのなかを覗いてみよう!「Cookpad Ruby Hack Challenge」に参加してみた )をご参照ください。

昼時だったので、発表を行ってもらった場所に隣接するキッチンで、社員の昼食を作っていました。料理しているところで発表するのは、多数の発表経験のあるまつもとさんでもさすがに初めての経験だったとのこと。

Ruby開発者との Q&A

f:id:koichi-sasada:20170929111044j:plain

Ruby 開発者を並べて、参加者および弊社社員を含めた質疑応答大会を行いました。RubyKaigi での企画 Ruby Committers vs the World の前哨戦でした。

パーティー

f:id:koichi-sasada:20170929111051j:plain

最後に、開発を終えた参加者の皆さんと、開発者会議を終えた Ruby コミッタが合流し、パーティーを行いました。

パーティーでは、二日目に行った挑戦を発表してもらいました。その場で、まつもとさんをはじめ Ruby 開発者と本気のディスカッションが発生していました。

まとめ

本記事では、2017/08/30, 31 に弊社で開催した Cookpad Ruby Hack Challenge (RHC) の模様についてご紹介しました。

参加者の皆様へのアンケートからは、良かったという感想を多く頂きました。 ただし、いくつか反省する点があり、次回以降で改善していきたいと思っています。

今回は(多分)成功したので、今後も続けて行ければと思っています。 初回だったので、まつもとさんに特別講演をお願いするなど、だいぶ力を入れてしまいました。 次回以降は、もうちょっと力を抜いていこうと思います。

参加したかったけど、定員オーバーで参加出来なかった方、そして、今回知って、興味を持たれた方、次回以降にぜひご期待ください。 調整次第ですが、出張して行うことも可能かと思います。 また、Ruby 以外にも広げられるといいですね。夢(だけ)は広がります。

本イベント開催にあたり、Ruby コミッタや、多くの弊社社員に助けて頂きました。 この場を借りて、御礼申し上げます。

最後にご案内です。フォローアップイベントとして、RHC もくもく会を弊社にて開催します(2017/10/11 (水) 18:30-、申し込みは Ruby hack Challenge もくもく会)。Ruby コミッタとして遠藤と笹田がサポートします。 RHC 参加者に限らず、Ruby のハックに興味のある方がいらっしゃいましたら、ぜひご参加ください。

料理の追体験を実現する「タイムライン」のデザイン

$
0
0

こんにちは、サービス開発部のデザイナー若月(id:puzzeljp)です。

すでにご利用していただいている方もいらっしゃると思いますが、iOS / Android アプリにタイムラインという機能が登場しました。

f:id:puzzeljp:20170929172254p:plain

先日そのタイムラインのデザインについての登壇しました。 (イベントレポートはこちら)
今回はその時話しきれなかったこと、タイムラインの開発時のデザインの工夫や苦労についてご紹介します。

タイムラインとは

フォローしているユーザーさんやすべてのユーザーさんの新しいレシピ投稿やつくれぽが見られるようになりました。 レシピ検索では出会えなかった料理に出会うことができ、実際にレシピが見られるので料理をすることができます。

どんな使い方があるかと言うと例えば「Aさんがパエリアを作っている!私作ったことないけど、Aさんが作っているなら私でも作れそう。作ってみよ!」のような料理の追体験ができるようになります。

f:id:puzzeljp:20170929172351p:plain

新しい見え方

タイムラインを開くと、「レシピのカード」と「つくれぽのカード」があります。検索結果と比べて料理の写真を大きく見やすく表示しています。ユーザーさんのアイコンや名前がカードに表示されているので、誰がどんな料理をしているかわかるようになりました。

f:id:puzzeljp:20170929172408p:plain

登壇資料

当日の登壇資料については、以下で見ることができます。

デザインアプローチ〜工夫と苦労〜

つくれぽカードのデザイン

タイムラインでは、「つくれぽのカード」で料理の追体験ができるような様々な工夫をしています。

工夫した点

つくれぽとレシピ投稿を比較すると、つくれぽは気軽に投稿できます。そのため、タイムラインを見ると「つくれぽのカード」の方が多く存在します。もう1つに、つくれぽは作った直後に送るため、今日何の料理を作ったこともわかるようになります。 そのため、レシピ投稿と違い「誰のレシピを作ったのか」「何のレシピを作ったのか」が必要となります。

「誰のレシピを作ったのか」「何のレシピを作ったのか」がタイムライン上でより伝わる物は何かをWebプロトタイピングで検証をしました。Webプロトタイピングのメリットして、以下があげられます。

  1. 実データを利用できること
  2. アプリよりもより高速に検証できること
  3. デザインプロトタイピングよりも正確に検証できること

実際に検討したレイアウトについてご説明します。

A案
作者名やレシピ名を同じ文章として扱いました。文字の大きさは同じですが、色はそれぞれ分けています。1文として見えるので文章としては見やすくしました。
B案
A案と似ていますが、レシピ名を目立たせるために、作者名を小さくすることでバランスを取りました。1文というのは同じですが、文章内で優先度がつきました。

f:id:puzzeljp:20170929172428p:plain

他にもレイアウトを考えましたが、最終的には以下のレイアウトになりました。
理由としては、タイムラインでカードが並んでいる場所に、文章があっても読まないのでは?という仮説がありました。それを解決するために、写真の上に「誰のレシピなのか」、写真の中に「何のレシピなのか」というレイアウトにしました。このレイアウトにしたことにより、適度な文章量と写真も目立つように、カードの高さも少なくなりました。

f:id:puzzeljp:20170929172450p:plain

苦労した点

今回のWebプロトタイピングは、メリットを活かした検証ができました。 問題点として、細かいデザインはアプリと異なるため、実際のアプリに実装してみたらイメージと異なったことやWebプロトタイピングも実装の時間がかかり、アプリの実装にも時間がかかってしまうことでしたが、デザインのプロトタイピングよりは検証は正確にできる点はやはりメリットだと感じました。

誰が作ったがわかる機能

フォローユーザーさんが既につくれぽを送ったレシピに対して、自分自身がつくれぽを送ると、送ったつくれぽが、フォローユーザーさんの「つくれぽのカード」に表示されるようになります。他のフォローユーザーさん同士でも同じレシピにつくれぽを送っていても「つくれぽのカード」に表示されます。

工夫した点

表示される内容は、「誰が作ったかわかる見出し」、それぞれのアイコン・名前とつくれぽの写真です。 例えば見出しには、「○○さんと△△さん他n人が作りました」や「○○さんがn回リピートしています」等と表示され、「誰が作っているか」「誰が何回作っているのか」「自分自身が何回作ってるか」がわかるような文言を20パターンほど用意しています。パターンが多いことで、より正確に「誰が作っているか」「誰が何回作っているのか」「自分自身が何回作ってるか」がわかるようになりました。

f:id:puzzeljp:20170929172510p:plain

苦労した点

見出しの部分が一番苦労しました。まず起こりうる組み合わせを考え、その後実際に表示される文言を考えましたが、「カード投稿者が他人の場合は他人をテキスト内に含めない」や「テキストがカード投稿者が自分の場合と異なる」などのカードの見た目は共通しているものの表示される文言が違うと複雑になってしまいました。 複雑になってしまったことで、テストケースを回した時に、その起こりうる組み合わせを出すことが難しく、専用のアカウントを作成し、ログインし確認を行う作業を20回以上しました。
もし次回こういった文言を考える時には、ユーザーさんに最低限伝わる文章を考えようと思いました。ユーザーさんにわかりやすいものをと思いましたが、開発が遅くなってしまいユーザーさんに届くのが遅くなってしまうよりも早くリリースを行い、検証をしたほうが良いためです。

まとめ

タイムラインは、時間をかけて開発を行ってきました。新しい機能のため、実装に時間がかかるのはもちろんですが、デザイン的にも様々な工夫を行ったためです。 そんなにデザインを工夫する必要があるの?…といった部分があるかもしれませんが、「タイムラインを見て料理がしたくなる」「タイムラインを見ていて、料理をしたくなったらレシピを見たら料理ができる。」そんな体験が自然とできるようにと開発を行いました。
タイムラインがリリースされたことによって、みんながどんな料理をしていることがわかるようになりました。 気になった作者さんをフォローをすると、よりタイムラインが楽しく、料理がしたくなるようになると思います。ぜひタイムラインを使ってみてください!

Ruby の脆弱性を見つけた話

$
0
0

こんにちは、技術部の遠藤(@mametter)です。フルタイム Ruby コミッタとして、クックパッドにあたらしく入社しました。よろしくお願いします。

最近、Ruby や RubyGems の脆弱性を発見して、その結果セキュリティリリースにつながるということを経験しました。どういう動機でどのように脆弱性を発見したか、どのように通報したか、などについてまとめてみます。Ruby の脆弱性を見つけたけどどうしよう、という人の参考になれば幸いです。

HackerOne について

HackerOneという脆弱性情報の通報と公開のためのプラットフォームをご存知でしょうか。

OSS にとって脆弱性情報の管理は面倒なものです。脆弱性の通報を秘密裏に受け付け、関係者だけで議論しなければなりません。そのため、通常のバグトラッカとは別のコミュニケーションチャンネルを用意する必要があります。

そこで HackerOne が使えます。HackerOne は簡単に言えば、脆弱性情報の管理に特化した非公開のバグトラッカサービスです。登録されたOSSプロジェクトに対して誰でも脆弱性情報を通報できます。また、プロジェクトメンバ間や報告者の間で非公開の議論もできます。問題が解決された際には議論の内容が公開されます。

さらに、Internet Bug Bounty (IBB) programがインターネットを維持するために特に重要なソフトウェアと指定している一部のプロジェクトについては、通報されたバグが開発者によって脆弱性と認定された場合、IBB から報告者に報奨金が支払われます。

ただ、報奨金が出るのは良し悪しです。良い通報をしてくれた人が報われるのは当然良いことなのですが、報奨金目当ての雑な指摘がたくさん来るという副作用があります。完全に見当違いな例を上げると、「SVN が公開状態だぞ!」とか、「バグトラッカの issue 一覧が丸見えだぞ!」とか 1。もちろん有益な通報も来るのですが、通報を受ける側としては、もうちょっとノイズが減るといいなあ、と思っています。

そこで、 Ruby ユーザの方々に HackerOne を紹介したいと思い、そのために一回、私自身が通報者としてのプロセスを経験してみました。

ターゲットの選定

自分が一番慣れている OSS プロジェクトは Ruby なので、Ruby のソースコードから脆弱性を探すことにしました 2。Ruby に標準添付されたライブラリの中で、「脆弱性といえば WEBrick」。という直観にもとづき、そのへんをターゲットにしました。

探す脆弱性の選定

「Ruby の脆弱性」に明確な定義はありません。ある Rails アプリに任意コード実行(外部から攻撃コードを送り込んで実行させられる)があれば、どこかに脆弱性があることは確かですが、Ruby の脆弱性かもしれないし、Rails(またはサードパーティ)の脆弱性かもしれないし、はたまたユーザの書いたプログラムの脆弱性かもしれません。極端な例では、system("ls " + user_input)みたいなプログラムがあると OS コマンドインジェクションができますが、これを Ruby の systemのせいだと言われても困ります。Ruby 本体かユーザプログラムかの切り分けは、わりと揉めやすいところです。

今回はここで揉めないよう、言い逃れしにくい脆弱性を探すことにしました。それは、そのプロジェクト自身が過去に脆弱性と認めたバグに近いバグを見つけることです。

WEBrick の過去の脆弱性を探したら、『WEBrick にエスケープシーケンス挿入の脆弱性』が見つかりました。要するに、ログにエスケープシーケンスを紛れ込ませることができたら脆弱性のようです。個人的には「このくらいで脆弱性なんだ」という驚きがありますが、一部のターミナルエミュレータはエスケープシーケンスで危うい挙動を起こせることがあるそうです。詳しくはリンク先を読んで下さい。

脆弱性の発見

実際に脆弱性を探します。過去の脆弱性の修正コミットを手がかりに WEBrick のログ出力まわりを読解すると、WEBrick::AccessLog.escapeというメソッドでエスケープシーケンスを除去(サニタイズ)し、WEBrick::BasicLog#error#warnなどのメソッドで実際にログを書き出すらしいことがわかります。ここで、AccessLog.escapeWEBrick::HTTPStatus::Status#initializeの中でしか呼ばれていないことに気づきました。つまり、この例外経由でしかサニタイズがされないらしいということです。

そこで、#error#warnを直接呼び出すところを探したところ、WEBrick::HTTPAuth::BasicAuth#initializeに見つかりました。不正なユーザ ID で BASIC 認証すると、そのユーザ ID がサニタイズなしでログに流れ出るようです。

(あっさり見つけたように書いてますが、実際にはいろいろ探したり試行錯誤したりしながらだったので 2 晩くらいはかかったと思います)

脆弱性の確認

この脆弱性が実際に exploit 可能であることを確かめます。WEBrick の BASIC 認証のコードを Web 検索しながら書きます。

require "webrick"
require "webrick/httpauth"

srv = WEBrick::HTTPServer.new({ Port: 34567 })
db = WEBrick::HTTPAuth::Htpasswd.new("dot.htpasswd")
authenticator = WEBrick::HTTPAuth::BasicAuth.new(UserDB: db, Realm: "realm")
srv.mount_proc("/") do |req, res|
  authenticator.authenticate(req, res)
    res.body = "foobar"
  end
srv.start

↓サーバを起動した様子 f:id:ku-ma-me:20171004180721p:plain

このサーバに対して、エスケープシーケンスを混入した不正なユーザ ID でログインを試みます。ここでは、"\e]2;BOOM!\a"というエスケープシーケンスで実験しました。これは、端末のタイトルを BOOM!という文字列に変える命令です。

require "open-uri"

open("http://localhost:34567/login",
  http_basic_authentication: [
  "ESCAPE SEQUENCE HERE->\e]2;BOOM!\a<-SEE WINDOW TITLE",
  "passwd"
]).read

↓クライアントを起動する様子 f:id:ku-ma-me:20171004180728p:plain

この結果、WEBrick サーバを動かしている端末のタイトルが、BOOM!に変わることが確認できました。

↓攻撃成功した様子(タイトルバーが "BOOM!"になっているところがポイント) f:id:ku-ma-me:20171004180738p:plain

脆弱性の報告

めでたく(?)脆弱性を確認できたので、HackerOne に投稿します。Weakness や Severity は該当すると思うものを選ぶだけですが、よくわからなかったら空欄でもよさそうです。重要なのは Proof of Concept です。といっても、普通のバグ報告と同じです。どういう問題であるかと、再現手順をきっちり書けば十分でしょう。問題の重大さを書くとさらに親切です。今回の脆弱性は過去の脆弱性の修正漏れなので重大さに議論の余地はないと考え、ほとんど再現手順だけを簡単に書きました

あとは普通のバグ報告と同じ対応です。よほど致命的な問題でない限り(あるいは致命的な問題であっても)、開発者はなかなか返事をしてくれないものです。パッチを書いて送ったり、ときどき催促したりしながら、気長に待ちます。今回は、4 月に報告して、セキュリティリリースは 9 月でした。

セキュリティリリース

普通の報告者ならここで終わりですが、今回は私が Ruby コミッタでもあるということで、セキュリティリリースに少しだけ参加しました。といっても私がやったのは、ブランチマネージャや公式サイト管理人たち(@unakさん、@nagachikaさん、@hsbtさん)の指示の下、私が書いたパッチをコミットしただけです。あとは彼らが一生懸命 tar ball を作ってリリースするのを応援していました。

コミットしてからリリースアナウンスを出すまでの時間を最小化するため、リアルタイムのコミュニケーションを取りながら進める必要があります。Ruby のブランチマネージャたちは、セキュリティリリースのたびに命を燃やして頑張っています。敬礼。

報奨金の獲得

無事セキュリティリリースがなされたということで、IBB から報奨金として $500 をいただきました。このプロセスも簡単に説明しておきます。

まず、初めて報奨金をもらう場合、税務上の書類 W-8BENを作成して提出します 3。すべてオンラインの手続きなので難しいことはありませんでした。

それから支払いの受取方法を登録します。PayPal 、Bitcoin via Coinbase 、銀行間振替がサポートされていました。私は銀行間振替を選んだので、口座情報を入力するだけでした。4

RubyGems の脆弱性

同じようなプロセスで、RubyGems にも通報をしました。

詳細は割愛しますが、CVE-2015-3900という過去の脆弱性が適切に修正されていないというものでした。ただ、こちらはすでに他の人が通報済みだったので、Duplicate でクローズされました。

ただ、コードを読んでいるうちに次の 3 つの問題を新規発見しました。こちらの方の通報は認められたようです。

これらの通報に対する修正は、RubyGems 2.6.13としてリリースされています。特に 3 つめの問題は、WEBrick の問題よりもう少し重大だと思うので、バージョンアップすることをおすすめします。なお、Ruby 2.4.2 は RubyGems 2.6.13 の修正を含んでいるので、Ruby 2.4.2 にするのでも大丈夫です。

まとめと所感

Ruby の脆弱性を探して HackerOne に通報した事例を紹介しました。

セキュリティ報告をすると、多くの場合、公式サイトでクレジットに載せてもらえるので、承認欲求が満たされますし、HackerOne ならちょっとした報奨金までもらえます 5

最初に触れたとおり、今のところ HackerOne 経由で Ruby にくる通報は、雑な通報が多くて Ruby 開発者的にはノイズが多いと感じられています。この記事を見た人が、(Ruby に限らず)有意義な通報を増やしてくれるといいなと思います。

最後になりましたが、クックパッドでは脆弱性のない Rails アプリを作れる Web アプリケーションエンジニアを募集しています。詳しくは募集要項ページをご覧ください。


  1. Ruby はオープンソースプロジェクトなので、もちろん意図的に公開しています。

  2. IBB の FAQによると、プロジェクトの開発者自身でも、(1) そのプロジェクトで収入を得ていないこと、(2) 問題のコミットに関わった人間でないこと、の条件を満たせば報奨金がもらえます。私はフルタイムコミッタになったので、もう無資格のようですが、今回の通報は入社前にやりました。

  3. 米国非居住者が米国の人から支払いを受け取るときに、源泉徴収の金額を低減してもらうための書類。

  4. 正確には、海外からの送金を受け取るために、銀行にマイナンバーの登録をする手続きもありました。

  5. エスケープシーケンスインジェクションでは大した金額にはなりませんでしたが、もっと重大な脆弱性ならそれなりに高額になるはずです。たとえば有名な Shellshock だと $20,000も支払われたそうです。


Cookpad Tech Kitchen #9 〜1行のログの向こう側〜 を開催しました!

$
0
0

こんにちは! @yoshioriです。

2017/07/26、技術系イベント「Cookpad Tech Kitchen #9 〜1行のログの向こう側〜Cookpad Tech Kitchen #9」を開催しました。 (はい。僕が記事公開するの忘れててだいぶ遅くなっちゃいました>< ごめんなさい)

クックパッドの技術的な知見を定期的にアウトプットすることを目的とする本イベント。第9回目となる今回は「ログの活用方法」をテーマに開催しました。(月に1回程度開催しています)

月間6000万ユーザが使っているクックパッドには大量のログが集まってきます。そのログを効果的に活用してサービスやユーザに還元するための取り組みについて、インフラ、広告事業、サービス開発それぞれの視点で知見の発表を行いました。

発表資料を交えてイベントのレポートをしたいと思います。

f:id:cookpadtech:20171003220443p:plainイベントページ:

Cookpad Tech Kitchen #9 〜1行のログの向こう側〜 - connpass

発表内容

「クックパッドのログをいい感じにしているアーキテクチャ」

一人目の発表者であるインフラストラクチャー部部長の星(@kani_b)は、SRE としてAWSやセキュリティ関連でのサービスインフラ改善に携わっています。

今回は AWS Summit Tokyo 2016 Developer Conference で発表した内容の続きとして発表を行いました。 具体的な数字として Fluentd に流れているログベースで言うとデータ総量は 400 〜 600GB / 日、レコード数は 8 億レコード以上 / 日(秒間 8,000 〜 25,000 レコードくらい)という規模のデータを扱っています。これをどのように集めて処理しているのかを紹介しました。

資料

「広告ログのリアルタイム集計とその活用」

二人目の発表者であるマーケティングプロダクト開発部の渡辺(@wata_dev)は、主に配信基盤の改善やマーケティングプロダクト開発部で開発しているサービスの基盤周りのサポートを行っています。

クックパッドでは広告の配信も自社で行っており、そのためにどのようにログを活用しているのかを、過去どういった問題点があってそれをどのように解決していったか、異常検知だけではなく配信制御や在庫予測などなど広告配信というドメインで実際に必要になるケースを出しながら紹介しました。

資料

「ログを活用したサービス開発」

3人目の発表者であるサービス開発部の外村(@hokaccha)は、バックエンドからWebフロントエンド、モバイルアプリの開発など幅広い分野でCookpadのサービス開発に携わっています。

発表ではモバイルアプリのロギングのやりかたから始まり、実際のログの活用方法としてサービス開発側でログをどのように扱っているか、どう活かしているかを紹介しました。 行動分析としてログの設計、ログの分析やその可視化によってサービス改善の意思決定に使われていること、ログを利用した機能開発として調理予測という実際にログがサービスとして使われている事例を紹介しました。

資料

「ログ」をテーマにしたご飯も登場!

クックパッドのイベントではご来場の感謝を込めて、会場で手作りしたご飯でおもてなしをします(食べながら飲みながら発表を聞いていただくスタイル)。今回はテーマである「ログ」にちなんだメニューを用意してもらいました。

f:id:cookpadtech:20171003220752j:plain

こちらはメッセージ入りのライスケーキ。クックパッドのインフラエンジニアが大切にしている言葉に「1行のログの向こうには1人のユーザがいる」というものがあります。画面で見るとたった1行のログだけど、その向こうには大切にすべき1人のユーザがいる、ということを思い出させてくれる合言葉です!

f:id:cookpadtech:20171003221913j:plain

川嶋シェフの粋な心意気で、素敵なメッセージもテーブルに並びました。

f:id:cookpadtech:20171003221721j:plain

こちらはログ=丸太をイメージした湯葉のデザートです。中に入っているのは甘すぎないところがおいしいあんこです。

まとめ

いかがでしたか。クックパッドでは毎月テーマを変えて技術イベントを開催しています。ご興味のある方は是非ご応募ください。

cookpad.connpass.com

新しい仲間を募集中

■ 日本最大の食のビッグデータを扱う「データ基盤」の開発に興味がある方 https://info.cookpad.com/careers/jobs/careers/data-infra-engineer

■ 広告事業の「Webアプリケーション開発」に興味がある方 https://info.cookpad.com/careers/jobs/careers/marketing-product-engineer

■ クックパッドアプリの「Webアプリケーション開発」に興味がある方 https://info.cookpad.com/careers/jobs/careers/software-engineer

クックパッドのデータ活用基盤

$
0
0

インフラ部 & 技術部の青木峰郎です。 クックパッドでは全社的にAmazon Redshiftを中心としたデータ活用基盤を構築しています。 今日はその全体像についてお話ししたいと思います。

データ活用基盤の全体像

まず、以下にクックパッドのデータ活用基盤の全体像を示します。

f:id:mineroaoki:20171005230822p:plain

大きく分けると入力が2系統、内部処理が1系統、出力が3系統あります。 入力はMySQLからのインポートとログのロードがあり、どちらも独自に構築したシステムで行われています。 DB内部のデータ処理はSQLバッチのみです。 そして出力は管理画面やBIツールからのアクセスとバッチ処理によるエクスポートに大別できます。

以下1つずつ説明していきましょう。

入力その1: MySQLインポートシステム

MySQLからRedshiftへのマスターテーブル取り込みにも独自のインポートシステムを使っています。 このインポート処理には、つい最近まではごく普通のバッチジョブを使っていたのですが、 現在は独自開発の専用システム(pipelined-migrator)に乗り換えつつあります。

専用システムを作った理由は、インポートするテーブルの追加を誰でも簡単にできるようにするためです。 pipelined-migratorにはウェブベースの管理画面が付いており、 この画面からボタン1つでインポートするテーブルの追加や削除が行えます。 またインポート状況などを確認することもできます。

バッチとpipelined-migratorのいずれにしても、 MySQLからテーブルを取り込む方法としてはごく単純な全行ダンプ・全行ロードのみを実装しています。 分析システムの構築当初はbinlogを使った差分更新も検討したのですが、運用が面倒すぎることと、 「全行ロードでも間に合うから」という消極的な理由によってこの実装になりました。 将来的にパフォーマンスが間に合わないなどの理由があれば差分更新にするかもしれません。

入力その2: ログをロードするStreaming Loadシステム

ログのロードには自前で開発した bricolage-streaming-loaderbricolage-streaming-preprocessorを使っています。 loaderはRuby製でpreprocessorはJava製です。

このシステムは、一言で言うと、fluentdからS3に書き込んだJSONファイルを前処理しながらロードするシステムです。 またRedshiftはコミットの遅延が比較的大きいため、そこを軽減するためにバッファリングも行っています。 このシステムの設計方針については本ブログの過去の記事 「Amazon Redshiftへ継続的にデータをロードする際に気をつけること」で詳しく説明しているので、そちらをごらんください。

このStreaming Loadシステムには専用の管理画面が用意されており、 ログが処理されていく様子を1オブジェクトずつ丁寧に見守ることができます。

入力その3: Redshift Spectrum向けロードシステム(未リリース)

さきほどの図には存在しませんでしたが、 RedshiftからS3のデータをアクセスできる「Redshift Spectrum」への対応も計画しています。 Spectrumはまだ東京リージョンに来ていないので計画に留めていますが、来た瞬間に稼働させるつもりです。

Spectrumを使う目的は、第1にログのロードのレイテンシを短縮すること、第2にディスク節約です。 特に、巨大なわりにあまりアクセスのない過去ログなどは、Spectrum(S3)に逃してやると、 Redshiftの高速性とS3の安価なストレージをいいとこ取りできるので大変いい選択肢だと思います。

データの加工: SQLバッチ

いったんRedshiftにデータを取り込んだら、あとは原則としてすべての処理をSQLで記述します。 このSQLによるバッチ処理はBricolageというSQLバッチフレームワークと、 ジョブ管理システムKuroko2の組み合わせで構築しました。

この2つについては過去にだいぶいろいろ書きましたので、 Bricolageについては 「巨大なバッチを分割して構成する 〜SQLバッチフレームワークBricolage〜」を、 Kuroko2については 「クックパッドのジョブ管理システム kuroko2 の紹介」を、それぞれごらんください。

Redshift内のデータアーキテクチャ

SQLバッチは全体で一番地味ですが、最も重要な部分でもあります。 データ分析基盤と言うとデータを取り込むところばかりが注目されがちですが、 データ取り込みは本番前の準備にすぎません。 その後ろに連なるデータの統合と分析こそがデータ「活用」の本丸です。

クックパッドではRedshift内を論理的に3層に区切り、 1つめを入力層、2つめを論理DWH層、3つめを論理データマート層としています。

入力層は名前の通り、他のデータソースからデータを入力する層です。 基本的に送られてきたデータが元のままの形でそのまま入っています。

論理DWH層は、いわゆるデータウェアハウス(Data WareHouse)です。 入力層のデータをクレンジングし、複数システムのデータを統合し、場合によっては集計もして、 全社の分析基盤となるデータを作ります。

……と書くとかっこいいですが、まだこの層はあまり成長させられていません。 まだここまで手が回っていないというのが正直なところで、今年末から来年にかけての最大の課題だと考えています。

最後の論理データマート層は特定のデータ分野ごとの特化領域です。 例えばクックパッドの場合だと、レシピ検索、広告、有料会員、レシピサービス、などの分野が存在します。

またこの層は対応する部がはっきり決まるので、その部に全権を委任しています。 逆に言うと、入力層とDWH層はインフラ部が管理しており、 他の部のメンバーが何か変更したい場合はpull requestが必須ということです。

これらの主要領域以外に、それぞれのメンバーは自分専用のスキーマを持つことができ、 その中では自分の自由にデータを加工・保存することができます。いわゆるサンドボックスです。 エンジニアはもちろん、ディレクターやプランナーも場合によっては自分のスキーマを持ち、 自分でSQLを書いて分析することがあります。 最近の社内におけるSQL熱の高まりを受けて、先日はインフラ部メンバーによる社内向けSQL講座も行われました。

出力その1, 2: BIツールと管理アプリからの参照

データベースへの入力と加工について話したので、残るは出力系です。 まずBIツールと管理アプリ(社内用ウェブアプリ)について話しましょう。

BIツールと管理アプリのアクセスは傾向が似ており、 ごく少量のメタデータ読み書きと、大量の統計データ読み込みが発生します。 前者はO/Rマッパーによる構造化されたアクセス、 後者は直SQLとカーソルを使ったアクセスが主になるでしょう。

Redshiftにおけるカーソルの特徴と使いかたについては過去の記事 「ActiveRecordを使ってRedshiftから大量のデータを効率的に読み出す」を参照してください。

なお、BIツールとしては現在のところ、社内で動かしているRedashをメインに使っています。 しかし正直なところRedashはキューまわりのできが悪すぎて、 アドホックな社内ローカルパッチを大量に当ててなんとか回しているような状況です。 いま真剣に移行を検討しています。

移行先の第一候補はなんだかんだでTableauでしょうか。 Tableauは以前から細々と使ってはいたのですが、 ついにTableau ServerのLinux版が出そうなのでいよいよ本格導入の時かもしれません。

ところで、RedashやTableauは共有ダッシュボードを作るために使われることが多いですが、 それ以外に個人単位のアドホックな分析も多く行われます。 そのような目的には、Posticoのような普通のPostgreSQLクライアントや Jupyter、 それに弊社社員の外村が開発したbdashなどを使っています。 bdashは手軽にグラフが書けることと、過去のクエリーを記録しておける点が非常に便利で、 個人的にも気に入っています。

出力その3: バッチからの参照

3つめの出力系統は、主に他システムへのエクスポートを目的とした、バッチからの参照です。 以前はこの処理のためには単純にRedshiftへ接続してselectさせていたのですが、 最近はQueueryというHTTP APIシステムを挟むようにしています。

Queueryは、APIでselect文を受け付けて結果をS3にUNLOADし、そのURLを返すだけの単純なシステムです。 このシステムを作った一番の理由は、バッチからの読み込み方法をRedshiftのUNLOADだけに限定したかったという点です。

Redshiftのカーソルはleader nodeにデータをマテリアライズするうえに、カーソルがクローズされるまでコネクションを占有しつづけます。 いずれの特徴もleader nodeにかなり負荷をかけることになります。 そこを考えると、長時間に渡って大量のデータを転送する可能性のあるバッチアクセスは、ぜひともUNLOADにしておきたいのです。 UNLOADはcompute nodeからS3へ直接に、並列でデータを転送するので安心です。

また特に、Redshiftで作ったサマリーをMySQLへ単純転送する用途のためには、 redshift-connectorというRubyのライブラリ(gem)を用意して対応しました。 むろん、このredshift-connectorも抜かりなくQueueryに対応しています。

データベースのドキュメント: dmemo

さて、ここまでで、データを入れて、きれいにして、サマリーも作り、 他のシステムから参照・利用できるようになりました。ではそれで終わりでしょうか?

当然、違います。データを作ったら、それを使えるように説明する必要があります。 ようするにドキュメントがいるのです。

データのドキュメントのためには、これまた弊社社員の小室が開発したdmemoを使っています。 これにも過去記事があるので、詳しくは下記の記事をごらんください。

まとめ

今回はクックパッドのデータ活用基盤について、その全体像をお話ししました。 これまでそれぞれの部分について書いたり話したことはたくさんあったのですが、 よくよく考えてみると全体を説明したことがなかったので、この機会にまとめてご紹介しました。 過去に書きためてきたブログ資産も生かすことができて一石二鳥ですね! ネタが思い付かないときはまたこの手で行こうと思います。

[宣伝] 『ふつうのLinuxプログラミング』の第2版が出ました

www.amazon.co.jp

わたしが12年前(!)に書いた書籍『ふつうのLinuxプログラミング』の第2版が出版されました。 第2版には、各方面からリクエストされまくっていたKindle版もついに出ています。 よっしゃ、いっちょ久しぶりにLinuxでCでも書いたるか! などという(わりと珍しい)機会がありましたらぜひご活用ください。

しかし、なぜわたしがブログ当番のときに限ってこう毎年毎年新しい本が出るのか…… まったく狙っていないのに、本当に不思議です。

Alignment and Autonomyな組織づくり

$
0
0

はじめに

サービス開発部部長の勝間(@ryo_katsuma)です。 普段は、エンジニア、デザイナ、ディレクターを含む様々な職種のメンバーのマネジメントを行っています。 今日は、私の部署における組織づくりの取り組みについてお話いたします。

背景

現在、私が所属しているサービス開発部は、年初の組織改編時に発足しました。レシピをさがす、のせるなどを含むレシピサービス、いわゆる「クックパッド」において、広告事業、会員事業など事業にまつわる開発以外のユーザーに触れる部分の開発を行っています。 クックパッドはPCウェブ、モバイルウェブ、モバイルアプリといくつかのプラットフォームをサポートしていますが、ここ最近の部署での開発はモバイルアプリを中心に行っています。

メンバーの数も他の部署と比較しても多く、学生アルバイトも含めて約45人が所属し、役割ごとに分割されたグループにも10人前後のメンバーが配置される、全社で見ても大規模な部署となっています。

課題感

モバイルアプリ「クックパッド」は2009年に最初のリリースが行われました。iOS, Android共に何度かリニューアルを経て今に至り、コードベースも関わる人の規模も大きなアプリです。部署としてはモバイルアプリの開発にフォーカスを行う中、このような環境下で価値を早く多く生み出していきたいという思いはあるものの、部署が立ち上がって2, 3ヶ月ほど経過した時点で次のような課題感を抱きました。

チーム内での課題

前述の通り、チーム規模も大きいものになっていることからか、なかなか開発のスピードが上がらないという現象が生まれていました。純粋に開発そのものの速さについての課感もありましたが、マネジメントの観点での課題が目立ちました。例えば、方向性の確認、デザインのすり合わせ待ちなど、チーム内でコミュニケーションの渋滞が起きるケースも少なくなく、「もっと意思決定を早く行い進めることができるはず」という考えを持っていました。

チーム外での課題

クックパッドでは、部署内の役割や施策の目的に応じて「グループ」という単位で組織を分割を行うケースが多くあります。たとえば私の部署では、レシピ検索の体験向上を目的にした「さがすグループ」調理後の料理の記録体験を目的にした「きろくグループ」など、期初の段階で幾つかのグループを設置していました。

一方、グループで分割されたメンバーは、良くも悪くもグループでの施策に閉じてしまう傾向がありました。たとえば「レシピをさがす観点で記録系プロダクトはどうあるべきか」「レシピの調理という観点で、記録のあるべき姿を考える」など、グループをまたいでサービスを捉え、どのような体験をユーザーに提供すべきか?という議論は十分に実施できていませんでした。

個人の成長の課題

前述のような観点での課題に対する取り組みを進め、部署の目標達成を目指す中、個人の成長を促す機会もしっかりつなげたい思いがありました。つまり、ただ業務効率の最適化を目指すだけではなく、業務を通じて個人の役割と責任範囲を広げ、結果として各メンバーが成長している状態を目指したいと考えました。

Spotifyモデルの適用

このような課題を解決する上で、自分たちだけでいろいろ試行錯誤を行うことも可能でしたが、まずは他社の「うまく回っている」開発スタイルについて事例調査をすすめることにしました。そんな中、Spotifyの考え方、カルチャーにたどり着きました。

この中で、特に注目したものは「Alignment and Autonomy」という考え方です。

f:id:ryokatsuma:20171009162924p:plain
図1: Alignment and Autonomy / Spotify engineering culture (part1) より引用

ここでの「Alignment」とは、いろいろなものや人を1つの考えのものに一致させていくこと、「Autonomy」とは、自律的に動いていくことです。これらの概念は、相反するものといっても過言ではないですが、「リーダーがどの課題をなぜ解くのかということにフォーカスし、どのように解くか?はチームに任せる」というアプローチによって、両立を目指そうとする考え方です。

会社の方向を向きながら、チームメンバーは自律的に垣根を超えて協力体制を作り進んでいく。これは、前述の課題に対して最適なアプローチで、理想の姿の1つとして目指していく価値はあるのでは?と考えました。

なぜSpotifyか?

Spotifyは以下のような特徴を持っています。

  • 組織の人数規模が数百人
  • グローバルな開発チームを構成
  • 音楽プレイヤーという1つのアプリケーションを多くのプラットフォームで展開

これらは、エンジニアが国内だけでも約100人、レシピサービス「Cookpad」をグローバルで展開するクックパッドの今の状況と非常に似ています。

また、Spotifyの取り組みについて研究、および言及されている文献も非常に数多くあります。たとえばHarvard Business Schoolでもその開発スタイルについて言及されており、アジャイル開発における1つのスタイルとして、デファクトスタンダードと言っても過言ではありません。

国内外含めていくつかの企業の事例を調査していましたが、これらの背景からSpotifyのモデルの導入検討は十分に価値があるものとして考えました。

Spotifyモデルの導入

以下の3つのステップでSpotifyモデルの導入を試みました。

ミッションの棚卸し

期初でも会社の方向性とそれに基いた部署で実施していくことのすり合わせは実施していましたが、Alignmentを改めて強化する観点で

  • 会社としてやるべきこと
  • 部やメンバー自身がやりたいと考えていること

を再整理しました。

前者は、「Spotify Rhythm」と呼ばれる全社的な戦略立案のフレームワークをそのまま採用しました。Data→Insight→Belief→Betという観点で現状を整理し、サービス開発の観点で「Company Bets (会社として賭けるもの)」について、上長(本部長)との議論を通じてお互いの認識を揃えました。また、後者は、私自身の考えや部署のグループリーダーたちの考えをもとに再整理しました。

結果として、部署で進めるテーマは期初に計画していたものと大きく変わることはありませんでしたが、Spotify Rhythmによって関係者の認識を改めて整理し、揃えることに大きく貢献をしました。

グループを撤廃した少人数のチーム編成

前述の通り、部署において「グループ」という構造を置くことで、メンバーは「これはxxグループの担当だから」と、グループ間の線引きを無意識に行ってしまうことがありました。 マネージメントの観点では、グループを作ることが重要ではなく、KPI達成に向けて目標管理を含めメンバーの日々のマネージメントを行うことが重要です。 そこで、思い切って組織構造上のグループを全て撤廃することにしました。メンバーは全て部付けにして、「みんな同じ立場である」ということを組織構造上で再認識してもらいました。

とはいえ、45人前後の部付けメンバーを全て直接私がマネジメントすることは不可能なので、さすがにチームの概念は導入します。チームはAutonomyを向上させる観点で以下の戦略で構成しました。

  • Spotify Rhythmで再定義した部署で開発をすすめるいくつかのテーマを「ミッション」と定義
    • たとえば「日本中の料理を記録する」「日本中の人がクックパッドで毎日の料理を見つけている状態にする」などのミッション
  • 各ミッションには、リーダー役として「ミッションオーナー」を設置する
  • ミッションに応じて1~2のチームに分割
  • 1チームは最大で5人前後
  • ロールは下記の人たちで構成し、チームによってはエンジニアはiOSエンジニアのみ、ディレクターはなしのようなケースも
    • チームリーダー(1チームの場合はミッションオーナーと同義)
    • エンジニア (バックエンド / iOS / Android)
    • デザイナ
    • ディレクター

f:id:ryokatsuma:20171010225406p:plain
図2: 組織構造の変更

人数を5人前後に絞っているのは、既存の10人前後のグループでの構成において、コミュニケーションに渋滞を引き起こし意思決定のスピードを下げていると判断したことが背景です。人数を絞った上で、ミッションに紐づくチームの役割を明確化することで、チーム内での意思決定を推し進めてAutonomyの強化を図りました。

余談ですが、ここでの「チームリーダー」のロールはエンジニアやデザイナ含めて若いメンバーにもどんどん挑戦してもらっています。チーム規模を小さくすることで、チームをまとめることが最悪うまくいかなかったとしても影響範囲を小さく留めることで、「将来的にミッションオーナーを任せたい人」「ミッションオーナーに興味がある人」「個人の役割を広げてもらいたい人」などに、積極的にトライをしてもらっています。

チームをまたいだ横断会の実施

小さいチームに分割しただけでは、結局既存のグループを分割しただけでチーム間の連携を取る、チームを俯瞰してユーザー体験を考えることは大きく変わらないと考えました。

そこで、ディレクターのチーム横断会、デザイナーのチーム横断会、Androidエンジニアのチーム横断会など、職種別の横断会を設けて、参加者のコンテキストを揃えた上で、お互いの持つ課題を解決できる環境を作ることにしました。各横断会では責任者を立て、それぞれの会ごとに最適な運営を実施しています。たとえば、ディレクター会ではチームを横断した知見共有を目的において、互いの施策に活かしたりスキルの向上に役立て、 iOSエンジニア共有会では、普段抱えている開発上での課題感や設計方針について議論をするなど、技術力の向上に繋がる取り組みを行っています。

このように、横断会を通じて、俯瞰して物事を捉え各メンバーのスキル向上の実現を試みています。

導入の結果

Spotifyモデルを導入し、組織構造に手を入れてから3ヶ月ほど経過しました。全て数字で測れるものではありませんが、次のような変化が見えてきました。

意思決定の速度向上

少人数のスモールチームを推し進めたことで、関係者とのコミュニケーションパスの数が減り、チームの中での意思決定を早く進められるようになりました。あわせて、少人数化を進めることによって施策における1人当たりの責任感が増すことになることで、施策における課題の定義の議論も徐々に活発になってきたように感じられます。

チーム間の協調

そもそもSpotifyモデル導入にあたって「もっとチーム間の協調を推し進めよう」という話をしていたという前提もありますが、「これはXXチームとやろうとしていることが似てるから、声をかけて一緒に進めよう」「XXチームが次の方向性を掘り下げようとしているみたいだから、話を聞きに行こう」のような会話が増えてきました。施策を進めるに上で、相乗効果を生み出すために、お互いに気を配る姿が見受けられます。

これらの効果の1つ1つはまだ小さいものではありますが、当初から期待している効果でした。継続的に取り組みを磨き込むことで、より高いレベルの「Alignment and Autonomyな組織」を目指したいと考えています。

新たな課題感

一方で、今回の取り組みを実施しても、また新たな課題感も感じています。

数字レベルでの成果

施策を遂行するスピードは上がってきていますが、まだまだ十分に数字レベルで目に見える効果が出てきているものは多くありません。より数字や効果の規模を意識した施策の進め方を考える必要がある、言い換えれば、Autonomyは高い状態になっているものの、施策の方向性についてのAlignmentはまだ高いレベルを目指す必要があると言えるでしょう。

もちろん、チームリーダーを含めて若いメンバーも多く、経験が十分に無いということもあると思いますが、同時にミッションに対して目指す方向性と高さについて、自分を含めてマネジメント側がメンバーと認識をもっと合わせていく必要があるでしょう。

開発そのもののスピード向上

作るものを決める、リリース計画を立てるなど、開発以外のマネジメントの観点において今回の取り組みによって開発のスピードの改善は進みました。 一方で、マネジメント以外での開発のスピード向上、つまり開発そのもののスピード向上については、今回の取り組みのスコープ外ではありますが、まだまだ工夫の余地があると考えています。

アプリ開発とWeb開発は当然、単純に比較することはできませんが、アイディアを形にしてユーザーに届けるまでに現状は大きな差があることは事実です。この点については、技術部など他部署を巻き込み、コードレビューや採用などいろんな観点で課題の整理と解決方法の模索をしているところです。スピードを上げることは同時に品質の問題も発生することになるので、なかなか難しいテーマですが、継続的に改善を目指していきたいです。

まとめ

規模が大きな組織において、意思決定のスピード向上や個人の成長を目指すために、Spotifyの開発モデルを自分たちなりに導入し、「Alignment and Autonomyな組織」を目指した経緯を述べました。背景として抱えていた課題感は少しづつ解決されてきたものもありますが、理想として目指したい状態とはまだまだギャップがあるのも事実です。

組織は生きもの」と(2年前から同じことを)言いますが、組織のサイズもメンバーも常に変化し続ける中、同じ取り組みをし続けても効果はありません。課題に対して、常に最適なアプローチを考え、時には外部から適切な手段を導入するなど、トライし続ける必要があります。読者の皆さんの周りでも規模はともかく、組織的な課題感があると思いますが、本エントリがそのトライの手助けになると幸いです。

また、「もっと良い組織を目指せるんじゃないの?」と思ってもらえた方は、ぜひ一緒により良い組織作りを目指しましょう!)

高速な研究開発を支えるGPU計算機環境

$
0
0

研究開発部の染谷 ( @ayemos_y ) です。好きな ImageNetのラベル(Synset)は "Eccentric, eccentric person, flake, oddball, geek"です。

クックパッドの研究開発部は2016年7月に発足し、現在はアルバイトを含め13名の体制となっています。その中で、こちらの記事でも紹介されている料理/非料理判別モデルを開発するなど、機械学習/ディープラーニング分野に特に力を入れて取り組んでいます。

最近は、モデルを開発し改善する手法などについて多くの情報にアクセス出来るようになり、このような技術をプロダクトに応用していきたいという気持ちが高まっている現場が多いかと思います。しかし一方で、分析の為のデータへのアクセスや画像認識モデルの実装や実験を行うためのGPU環境の整備など、現場の都合に対応するコストによって開発の勢いが鈍化してしまうような状況もめずらしくありません。

特にそのようなコストがチームのサイズに従って増えていくような場合は(つまり多くの場合においては)、組織のスケーラビリティを損なう重大な問題です。

クックパッドの研究開発部では、このような研究開発、特に機械学習における開発基盤にまつわる課題の解決にも積極的に取り組んでいます。今回はそのような取り組みの一部を紹介したいと思います。

研究開発専用AWSアカウントの利用

クックパッドには技術部開発基盤グループ/モバイル基盤グループなどの組織があり、開発基盤の整備や改善に取り組んでいますが、最近ではこのような組織が部署横断的かつ中央集権的に請け負っていた仕事を、部署ごとに分散出来るような体制に移行しつつあります。(この辺りの詳しい話はAWS Summit Tokyo 2017でも発表しました。 資料動画 )

その取り組みの一環として、研究開発目的で利用するAWSアカウントを本番アカウントと別に用意し、研究開発部のメンバーの一部(現在は私だけですが)にAdminに近い権限を付与した上で、部署の責任範囲において開発基盤を積極的に改善するという体制が敷かれています。

オンデマンドGPUインスタンス

アカウント分離以前にも研究開発目的でGPUを利用したいという案件がありました。その際にはインフラストラクチャー部への依頼に始まり、必要なコンポーネントなどの要件のすり合わせと実際の作業が行われ、その間コミュニケーションが数往復しました。

結果として、本番アカウントに g2.2xlarge インスタンスが立ち上がり、必要コンポーネントがインストールされて利用可能になるまで4週間程かかりました。このような作業を部内で消化出来るようにするというのがアカウント分離の目的の中心でしたので、アカウントを分離後早速GPU環境の整備に取り組みました。

GPU環境とはつまり、GPUの搭載されたEC2インスタンスで、GPUを利用した開発が出来るものですが、OS環境が(不可逆に)壊れてしまった場合や、2台以上のGPUが必要になった時などを想定すれば、このような環境を低コストで繰り返し用意出来るような状況が望ましいです。手動でセットアップする従来の手法ではこれが実現出来ていないという課題がありました。ドライバーやCUDA Toolkitなど比較的低レイヤなセットアップ作業が多く、手間と時間もかかります。

そこで、最低限のコンポーネントを揃えた状態からAmazon Machine Image(AMI)を作成し、同じ状態のインスタンスを繰り返し立ち上げられるようにしました。

Packer を利用したAMIの構成管理

またさらに、各コンポーネントのバージョンアップや、異なるバージョンでセットアップされた複数のAMIを安定して管理するために、Packerを利用し、機械学習で利用するAMIを作成/構成管理しています。

PackerのChef Solo Provisioner)を利用し、Chefのrecipeと呼ばれるセットアップ手順を定義することで、これを自動で実行し、実行後の状態をAMIとして保存することが出来ます。これにより、手順をコードとして管理しておけるだけでなく、recipeを適切にパラメータ化することで、CUDA8/9をインストールしたAMIをそれぞれ別の名前で作成する等の作業を簡単に行うことが出来ます。(下図)

Slack Chat Botを利用したインスタンスの操作

AMIを用意した事で、必要なコンポーネントがインストールされた状態のGPUインスタンスを繰り返し作成することが出来るようになりました。しかしながらEC2インスタンスをオンデマンドで立ち上げる際には、VPCと特定のサブネット(のうち1つ)、キーペアやセキュリティグループを適切に選んでやる必要があります。またクックパッドではEC2インスタンスへの接続を適切に経由するためにインスタンスへのタグ情報を利用しており、これもまた設定してやる必要があります。

このような一連の操作を繰り返さない為に、Slack上で動作するChat Botから、より抽象度の高い操作によりインスタンスの作成や停止/再開を行えるようにしました。Chat Botの開発にはLitaを利用しました。

蛇足ですが、このような問題を解決するためにコマンドラインで動作するツールを配る事もできますが、Slackをインターフェースにする事で実行環境が統一されるので、開発者ごとの環境の差異を気にしなくて良くなり、また、利用されている様子から使い方を自然に見て覚えられたり、改善のヒントが得られるなどの利点があります。

インスタンスの自動停止

AMIとChat Botを整備したことにより、必要なGPU環境が数分で手に入るようになりました。一方副作用として、立ち上げたインスタンスの落とし忘れにより、アイドルなインスタンスから発生するコストが増えてきました。例えば金曜日の退勤前に実行した実験が深夜に終了し、その後週末の間なにもせずに立ち上がったままである、といったことが頻繁に起こるようになりました。

これ自体はコスト面で致命的な問題になるほどではないのですが、EC2インスタンスの課金も秒単位になったことですし、使用していないインスタンスはなるべく早く停止したいところです。

そんな時は、Amazon CloudWatch EventsとAWS Lambdaを組み合わせることで、「一定時間以上アイドルなインスタンスを停止させる」Pythonスクリプトを「5分毎に実行する」といった構成を非常に簡単に実現することが出来ます。

ちょっとした考察

計算機コストの最適化を考えた時に、例えばコンテナによって仮想化され、場所透明性を持ったワークロードをインスタンスのグループ(あるいはプール)において実行する事で、よりインスタンスのアップタイムを効率的に利用出来るといった手法も考えることが出来ます。

しかしながら複数のワークロードでGPUを共有する場合には、コンテナ化するだけではなく、ワークロードのスケジューリングなどの複雑性を導入する必要が出てきます。またコンテナ仮想化それ自身も、実験環境の可搬性を高めるという点で便利な一方で、ネットワーキング、ロギング、データ永続化など、いくつかの複雑さが導入されるという意味で、実験環境において必要でなければ使わないという姿勢が適切なようにみえます。

そのような理由で現状は、個人に対して個人が専有出来るインスタンスを用意して必要に応じて動かすという構成を取っています。しかしながら今後も使用感やコスト面の課題を探しながら継続的に改善を進めて行くことになります。

まとめ

というわけで、今回はクックパッドの機械学習基盤についてお話しました。 Packerを利用して必要な環境をAMIとして作成/管理し、Chat Botを利用して作成/停止/再開する事で、チームメンバのそれぞれが、長くとも数分で必要なGPU環境を利用出来るという環境を整えました。

研究開発部というと、どうも実際のプロダクトと距離があるという印象ですが、チーム単体で見た時にもそれはやはりユーザーに価値を届け続ける組織である必要があると考えています。言い換えれば、ユーザーとの接点であるプロダクトに繋がるアウトプットをし続ける事が必要であり、その為にすばやい実験や実装が出来る環境があることも重要です。

そのような考えから、機械学習/ディープラーニングを中心とした最新技術へのキャッチアップとその応用はもちろん、チームの成果を最大化するための運用の改善にも積極的に取り組んでいます。

クックパッドで機械学習を利用して新たなサービスを創り出していける方に加え、研究開発部の開発環境を改善していく方も募集しています。 興味のある方はぜひ話を聞きに遊びに来て下さい。

クックパッド株式会社 研究開発部 採用情報

追記(お知らせ)

11月27日-12月1日にラスベガスで開催される AWS re:Invent 2017にインフラ部のと一緒に登壇します。 "Containerized Machine Learning on AWS"というテーマで料理きろくで利用されている画像判定システムののアーキテクチャを中心に話します。乞うご期待!

Encoder-Decoder でレシピの材料名を正規化する

$
0
0

研究開発部の原島です。部のマネージメントのかたわら、自然言語処理関連の開発に従事しています。本エントリでは、最近社内で開発した自然言語処理システムを紹介します。

■ 「しょうゆ」のバリエーションは 100 種類以上

クックパッドで以前から解決したかった課題の一つに材料の名前(以下、材料名)の正規化があります。

f:id:jharashima:20171030074621j:plain

クックパッドのレシピは複数の材料から構成され、各材料は名前と分量から構成されています。例えば、上のレシピの一つ目の材料は「豚薄切り肉」が名前で、「200g」が分量です。

さて、この材料名はこのレシピでは「豚薄切り肉」という表現でした。しかし、他のレシピでは「豚うす切り肉」という表現かもしれません。「豚うすぎり肉」や「ぶた薄切り肉」、「豚薄切り肉」等の表現もありえますね。

これは異表記同義(いわゆる表記揺れ)の問題ですが、同様の問題は他にも沢山あります。例えば、以下のようなものです。

  • 同義表現系の問題
    • 異表記同義(上述)
    • 異形同義(e.g.「じゃがいも」と「馬鈴薯」)
    • 略記(e.g.「ホットケーキミックス」と「HM」)
    • 綴り間違い(e.g.「アボカド」と「アボガド」)
  • 付属表現系の問題
    • 記号(e.g.「★味噌」)
    • 括弧表現(e.g.「油(炒め用)」)
    • 接頭辞(e.g.「お砂糖」)
    • その他(e.g.「お好みでローズマリー」)

面倒なことに、これらの問題は複合的に発生することも珍しくありません。その結果、例えば、クックパッドにおける「しょうゆ」には、分かっているだけで、100 種類以上のバリエーションが存在しています。

時に、これがサービス開発において問題となります。

例えば、あるレシピのカロリーを計算するとしましょう。そのためには、そのレシピ中の全ての材料名のカロリーが必要です。つまり、材料名ごとにカロリーを登録したデータベースが必要です。

しかし、クックパッドには数百万種類の材料名が存在します。これらの全てに人手でカロリーを登録するのは途方もない作業です。「しょうゆ」は大さじ 1 杯で約 13 kcal ですが、あらゆる「しょうゆ」のバリエーションにこの情報を登録するのは大変です。

こういった時に、「材料名を正規化したい」という考えに至ります。あらゆる「しょうゆ」のバリエーションを全て「しょうゆ」に正規化できれば、「しょうゆ」にだけカロリーを登録すれば良いわけです。大分コストを削減できそうですね。

このように、材料名の正規化は、以前から解決したいと思っていた課題の一つでした。

■ 正規化しよう!とは言え...

どうすれば材料名を正規化できるのでしょうか。

最初に検討すべきは正規表現です。例えば、材料名の冒頭の記号と末尾の括弧表現を除去するというのはどうでしょう。しかし、この方法だと、同義表現系の問題は全く解決できません。

クラウドソーシングはどうでしょう。人手で正規化すれば、全ての問題を解決できそうです。しかし、1 個の材料名を 10 円で正規化できたとしても、数千万円が必要です。仕様変更等でやり直しが発生すれば、さらに必要ですね。

機械学習の出番かもしれません。例えば、何らかの語彙を定義できれば、SVM や Random Forest 等で各材料名を語彙のいずれかに分類できそうです。しかし、そもそも語彙を定義するのが困難です。未知語とかどうしましょう。

材料名の各文字について CRF で「必要」もしくは「不要」というラベルを付与して、必要な文字だけを抽出するというのはどうでしょう。しかし、この方法でも、同義表現系の問題は解決できません。

いずれの手法にも何かしらの問題がありそうです。

■ Encoder-Decoder で正規化しよう!

そこで、クックパッドでは Encoder-Decoder を利用することにしました。

Encoder-Decoder は、おおまかには、「入力の情報を何らかのベクトルに集約し、そのベクトルから出力を生成するモデル」です。前半を処理する部分が Encoder で、後半を処理する部分が Decoder です。

このモデルの利用例としては機械翻訳が代表的です。日英翻訳であれば、日本語文が入力で、その英訳が出力です。入力と出力は一般的には単語列です。正解データ(この場合は日英対訳)さえあれば、翻訳モデルが構築できます。

材料名を正規化する場合、材料名が入力で、その正規化後の表現が出力です。イメージは下図の通りです。上述の通り、Encoder-Decoder の一般的な設定では入力も出力も単語列ですが、我々の設定では文字列になります。図の EOW は End-of-Word の略です。

f:id:jharashima:20171030074722p:plain

Encoder-Decoder は入力から出力を抽出するわけではなく、生成します。そのため、付属表現系の問題だけではなく、同義表現系の問題も解決できます。また、正規化のパターンが学習できれば、未知語にもある程度は対応できます。

なお、このように Encoder-Decoder を正規化に利用するのは我々が最初ではありません(業務に導入したのは我々が最初かもしれません)。例えば、以下の 2 本の論文で同様のアイデアが提案されています。

  • Japanese Text Normalization with Encoder-Decoder Model(Ikeda et al. 2016)
  • 疑似データの事前学習に基づくEncoder-decoder型日本語崩れ表記正規化(斉藤ら 2017)

■ 全体像はどうなってる?

正規化システムの全体像は大きく三つに分割できます。正解データ収集とモデル開発、バッチ実行です。以下でそれぞれについて概説します。

f:id:jharashima:20171030074818p:plain

正解データ収集

Encoder-Decoder を学習(と検証、テスト)するには正解データが必要です。そこで、スタッフが毎日利用する社内ツール(クックパッドと同様、Rails 製)に、正解データを収集するための仕組みを追加しました。普段の業務をこなすと、正解データが自然と MySQL に蓄積されるようにしました。

本エントリの執筆時点で、約 12,000 個の正解データが収集されていました。

モデル開発

開発環境には p2.8xlarge を、フレームワークには Chainer を利用しました。やや詳細な話になりますが、Encoder と Decoder には Stacked Uni-directional LSTM(3 層)を使用しました。なお、我々のタスクでは Bi-directional LSTM や Attention はあまり効果がありませんでした。

PR がマージされると Jenkins が起動して、プログラムの実行環境をまとめた Docker イメージが社内の Docker レポジトリに登録されます。このイメージは後述するバッチで利用されます。

バッチ実行

クックパッドは主に Rails で構築されているため、そのデータの多くは MySQL に蓄積されています。さらに、これらはログデータ等とともに Redshift に集約されています。正規化バッチはこれらのデータをもとに動作しています。

まず、正規化の対象とする材料名を Redshift から取得して、S3 に保存します。次に、Docker イメージをもとに Encoder-Decoder の実行環境をインスタンスに準備した後、材料名を正規化します。最後に、S3 を経由して、結果を MySQL に保存します。

■ 正答率はどれくらい?

最後に、簡単な実験結果を紹介します。実験では正解データの 10% をテストデータに、別の 10% を検証データに、残りの 80% を学習データに使用しました。

手法正答率
Baseline A(変更なし)20.8%
Baseline B(正規表現)28.6%
Encoder-Decoder71.2%

まず、ベースラインの結果を確認しましょう。Baseline A は、入力をそのまま出力した場合の結果です。正答率(正解との完全一致率)は 20.8% でした。これは、テストデータの約 80% に何らかの正規化が必要ということを意味しています。

Baseline B は正規表現です。冒頭の記号と末尾の括弧表現を入力から除去した場合の結果です。正答率は 28.6% でした。「検討すべき手法」の節でも議論したように、正規表現だけで正規化するのはやはり困難でした。

最後に、Encoder-Decoder の正答率は 71.2% でした。同義表現系の問題(e.g. 桜エビ → サクラエビ)や付属表現系の問題(e.g. ※牛乳 → 牛乳)、それらの複合的な問題(e.g. ☆ローリエ → 月桂樹)に幅広く対応できたので、ベースラインより圧倒的に高い正答率となりました。

補足として、この数字はあくまでもテストデータでの値です。我々のテストデータ(と言うより、正解データ)は、テストのため、低頻度の材料名を少なからず含んでいます。現実のデータにおける数字はもう少し高いです。

また、実際に正規化結果を利用する際はスタッフがざっと確認して、明らかな間違いは修正しています。なお、修正されたデータは新たな正解データとして利用できます。

■ Appendix

以下は少し発展的な話題です。Encoder-Decoder でも失敗するのはどういうケースでしょうか。そして、それらのケースはどうすれば改善できるのでしょうか。

探索範囲が狭い

Decoder が N 文字目を出力する際は、その時点での生成確率が一番高い文字を選択します。しかし、確率が二番目に高い文字は無視して良いのでしょうか。N+1 文字目以降を出力する際に後悔しないでしょうか。

そこで、ビームサーチです。N 文字目を出力する際、確率が高い文字を M 個キープしておきます。そして、最終的に生成確率が一番高い文字列を出力としましょう。追加実験では、M = 10 の時、正答率が 72.3% になりました(統計的に優位でした。以降の数字も同様)。

存在しえない文字列を出力

例えば、「こめ油」を「米油」と正規化すべきところ、「コー油」と正規化してしまうケースです。「コー油」という文字列は少なくともクックパッドには存在しません。機械翻訳でも、Encoder-Decoder がおかしな文(単語列)を出力してしまうのはよくある話です。

そこで、このような文字列を出力しないように、Decoder を制御してみました。具体的には、ビームサーチの途中でクックパッドに存在しない文字列が生成された場合、その文字列を正規化候補から除外してみました。トライ木を利用すれば簡単に実装できます。正答率は 72.8% になりました。

入力と無関係の文字列を出力

例えば、「トーモロコシ」を「とうもろこし」と正規化すべきところ、「とろろこんぶ」と正規化してしまうケースです。「とろろこんぶ」は世の中に存在する文字列ですが、もちろんこの正規化は間違いです。

そこで、ビームサーチで取得した正規化候補を入力との類似度(と Encoder-Decoder のスコア)でリランキングしてみました。類似度の計算には word2vec を、その学習データにはクックパッドの全レシピを利用しました。正答率は 73.3% になりました。

その他

さて、まだまだ改善の余地があります。しかし、調査してみたところ、これらの多くは学習データの不足に起因するものでした。ここから先はモデルを改善するよりも、学習データを追加する方が楽かもしれませんね。

■ おわりに

本エントリでは、Encoder-Decoder でレシピの材料名を正規化するシステムについて紹介しました。

このモデルには、レシピの材料名だけでなく、EC サイトの商品名や不動産サイトの物件名等も正規化できる可能性があります。本エントリが、正規化に頭を抱える誰かのお役に立てば幸いです。

最後に、クックパッドの研究開発部では自然言語処理や画像認識の専門家を募集しています。あなたの知識・スキルで世界中の毎日の料理を楽しみにしませんか。ご興味がある方は採用ページを是非ご覧ください。ご連絡をお待ちしております。

クックパッド株式会社 研究開発部 採用情報

料理画像判定のためのバックエンドアーキテクチャ

$
0
0

サービス開発部の外村 (@hokaccha)です。

クックパッドのアプリには「料理きろく」という機能があります。 モバイル端末から料理画像のみを抽出して記録することで食べたものが自動的に記録されていくという機能です。

f:id:hokaccha:20171108125806p:plain

今回はこの料理きろくで画像判定をおこなっているバックエンドのアーキテクチャについて紹介します。なお、実際に判定をおこなう機械学習のモデルのはなしは以下の記事に書かれているのでそちらを参照してください。

料理きろくにおける料理/非料理判別モデルの詳細 - クックパッド開発者ブログ

また、以下のスライドでも料理きろくのバックエンドについて紹介されているのでこちらも参照してみてください。

処理の概要

ざっくりとした画像判定のフローとしては、次のようになります。

  1. クライアントアプリは端末内の画像を判定用に縮小してサーバーにアップロードする
  2. サーバーはアップロードされた画像を機械学習を用いて料理画像かどうかを判定する
  3. クライアントアプリは判定結果を受け取る

クライアントアプリが結果を受け取った後にオリジナルの画像をアップロードしたり、RDBMSにデータを保存するといった処理もありますが、今回は判定処理をクライアントアプリが受け取るまでの流れに絞って解説します。

初期のアーキテクチャ

プロトタイプの段階ではこの処理を単純に料理画像判定用のHTTPのAPIエンドポイントを用意し、そこに画像をアップロードして判定処理を行い、結果をレスポンスで返すという構成で実現していました。

f:id:hokaccha:20171108125340p:plain

Web APIはRailsとUnicornで動いているサーバーで、その後ろに実際に判定をおこなうPythonのサーバーがたっていてRailsのアプリケーションはそこと通信しています。

この処理は画像アップロードに加えて、料理画像判定の処理にディープラーニングを用いているのでそれなりに重たい処理になります。APIサーバーで利用しているUnicornは仕組み上プロセスがリクエストを処理している間他のリクエストをブロックするため、大量のアクセスがきた場合にI/O待ちによりworkerを使い切ってしまいます*1

機能の性質上、端末にある画像をすべてアップロードする*2ので利用者が増えると判定の処理が大量にくる可能性は高かったため、アーキテクチャを変更する必要がありました。

現状のアーキテクチャ

そこでシステムの安定性を高めるため、以下のような方法を取ることにしました。

  • 画像はAPIサーバーにアップロードせず、S3に直接アップロードする
  • サーバー側は料理画像の判定処理をバックグラウンドワーカーで非同期に行う

APIサーバーで重い処理を受けないようにすることでアクセスが集中してもAPIサーバーが詰まらないようにし、バックグラウンドワーカーをスケールアウトさせればサービスがスケール可能になるアーキテクチャを目指しました。

他にもI/O多重化ができるサーバーを導入するであったり、コストを覚悟でUnicornのサーバーをスケールアウトするという方法も考えられますが、今回は社内のノウハウなども加味して一番安定して稼働できそうという判断のもと、このアーキテクチャを採用しました。

最終的な構成としては次のようになります。

f:id:hokaccha:20171108125343p:plain

順に説明していきます。

S3に直接画像をアップロードする

まず、画像アップロードの負荷を軽減するため、S3に直接アップロードすることにしました。そのためにS3のPre-Signed URLを利用しています。

Uploading Objects Using Pre-Signed URLs - Amazon Simple Storage Service

クライアントがアップロード処理を開始するときにAPIサーバーにリクエストし(1)、アップロード可能なS3のURLを取得します。このときAPIサーバーはRDBMSにレコードを作成し、アップロードの状態管理を開始します。クライアントアプリは返ってきたURLに対して画像をアップロードすることでS3に画像がアップロードされます(2)

S3のイベント通知でSQSにエンキューする

S3にはEvent Notificationsという機能があります。

Configuring Amazon S3 Event Notifications - Amazon Simple Storage Service

この機能を使うと、S3にファイルアップロードされたり、変更されるといったイベントが発生されときに、特定のサービスに通知を送ることができます。これを利用し、S3にファイルがアップロードされたときにSQSにエンキューが行われるようにします(3)

バックグラウンドワーカーの処理

バックグラウンドワーカーはSQSのキューをポーリングしていて、エンキューされたメッセージはバックグラウンドワーカーがデキューすることで処理を行います(4)

メッセージのペイロードにはS3にアップロードされたオブジェクトのキーなどの情報が入っているので、その情報を元にバックグラウンドワーカーはS3からアップロードされた画像を取得し(5)、機械学習による判定を行い(6)、結果をAPIサーバーにHTTPで送信し(7)、メッセージの処理を完了させます。

このワーカーはPythonで書かれていて、hakoを利用しECS上で動いており、オートスケールの設定もhakoでおこなっています。

結果の取得

最後にクライアントアプリは結果をAPIサーバーから取得(8)してフローは終了です。

ただ、処理を非同期にした場合に難しいのがこの結果の取得です。同期的に判定ができるのであれば、クライアントアプリは判定結果が返ってくるのを待ってから次の処理に進めばいいのですが、非同期の場合はいつ処理が終わるかクライアントアプリにはわかりません。

今回はクライアントアプリが定期的に結果取得のAPIエンドポイントにリクエストすることで結果を取得するようにしています。料理きろくという機能はユーザーが写真を撮って、後で見た時に自動で写真が記録されている、という機能なのでそのケースではリアルタイム性が求められないので数十分に一回程度のリクエストで後から結果が取得できれば問題ありません*3

ただ、クライアントアプリでそういった処理を定期実行するのは簡単ではなく、様々な苦労がありました。詳しくは料理きろくのAndroidの実装を行った吉田の以下の資料にまとまっています。

まとめ

料理きろくの料理画像判定部分のアーキテクチャについて解説しました。現時点で一日あたり約50万枚以上の画像を判定していますが、大きな問題はなく安定して稼働しています。基本的にはよくあるジョブキューを利用した非同期処理のアーキテクチャですが、S3やSQSはこういったシステムを組むのにとても便利です。

また、最近ではモバイル端末でも機械学習のモデルが動くようになってきています。まだ実用段階まではいっていませんが、それが実現すればこのようなシステムは一切いらなくなり、クライアントの実装も非常にシンプルになるので、できるだけ早く実現してこのシステムがいらなくなる日がくればよいと思っています。

*1:Railsを噛ませずにPythonのサーバーで直接受けてもHTTPサーバーの仕組みがUnicornと同じであれば大きな違いはありません

*2:料理画像以外も判定のために一旦サーバーに保存しているため、ユーザーのプライバシーについては十分に配慮し、判定後には画像は完全に削除し、開発者であってもどのような画像が判定に使われたかを見ることがはできないようになっています

*3:ユーザーが最初に料理きろくを利用する場合に数十枚の画像の判定を進捗を見せながら表示するという要件もあり、この場合は間隔の短いポーリングを行っています

【出張開催レポ】Cookpad tech kitchen #11, #12 in 京都・福岡

$
0
0

こんにちは!人事部の冨永です。

2017/09/28~29の二日間に渡って、技術系イベント「Cookpad Tech Kitchen」を開催しました。クックパッドの技術的な知見を定期的にアウトプットすることを目的とする本イベント。#11, 12の今回は株式会社はてなさん(京都)とGMOペパボ株式会社さん(福岡)のお力をお借りして、京都・福岡での出張開催を実現しました!

テーマは一夜限りのPremium Talkと題して「各社開発の裏側」を発表。本イベントで初めて公開する情報や、ここだけでしか聞けない裏話など、興味深い内容が盛り沢山なイベントとなりました。

発表資料を交えてイベントのレポートをお届けします。

f:id:mamiracle:20171115180848j:plain

9月28日【京都開催 feat.はてな】Cookpad Tech Kitchen #11

f:id:mamiracle:20171115174411p:plain(Premium Talk in Kyoto)

京都のはてなオフィスにお邪魔しての開催。実は登壇者同士が学生時代のインターンシップ同期で良き仲間でありライバル(!)だったこともあり、和気あいあいとしながらも白熱した登壇となりました。

f:id:mamiracle:20171115174335j:plain(大盛り上がりだったQAディスカッションの様子)

それでは登壇内容をご紹介します。

「ScalaとPerlでMicroservices in production」中澤 亮太/株式会社はてな

1人目の登壇者である中澤 亮太さん(@aereal)は、アプリケーションエンジニアとしてご活躍されています。静的解析や静的型付けがお好きで、はてなブログチームのテックリードをお務めになられています。この日は、ScalaとPerlを使ったマイクロサービス化について登壇をしてくださいました。

speakerdeck.com

「イカリング2におけるシングルページアプリケーション」加藤 尋樹/株式会社はてな

2人目の登壇者である加藤 尋樹さん(@cockscomb)は、アプリケーションエンジニアとしてご活躍されています。モバイルアプリからWebサービスの開発まで積極的に取り組まれており、あの「イカリング2」の開発も担当されています。この日は、「イカリング2」の開発の裏側を教えて下さいました。

speakerdeck.com

f:id:mamiracle:20171115174355j:plain(美味しくておしゃれなケータリングに大喜び!)

はてなさんがいつもお世話になっているという京都のケータリングご飯を用意していただきました!発表を聞きながらでも楽しめるピンチョススタイルです。 イベントの後は、仕事終わりのはてなメンバーの方々と、行きつけだという居酒屋で打ち上げもしましたよ!はてなさん、ありがとうございました。

9月29日【福岡開催 feat.ペパボ】Cookpad Tech Kitchen #12

f:id:mamiracle:20171115174432p:plain(Premium Talk in Fukuoka)

翌日は、福岡のGMOペパボオフィスにお邪魔して開催!弊社社員は福岡初上陸のメンバーが多く、みんなのテンションが高かったことをよく覚えています。笑

f:id:mamiracle:20171115174808j:plain(こちらでもQAセッションが大盛り上がりでした)

それでは登壇内容をご紹介します。

「コンテナたちを計測すること - マネージドクラウドの今まさに開発中の裏側」近藤 うちお/GMOペパボ株式会社

3人目の登壇者である近藤 うちおさん(@udzura)は技術基盤チームに所属されています。mruby製のLinuxコンテナエンジン「Haconiwa」をリリースされたり、『パーフェクトRuby』『パーフェクトRuby on Rails』などを共著されたり広くご活躍されています。この日は、コンテナ計測について登壇してくださいました。

speakerdeck.com

「ムームードメイン ショッピングカート機能を支える技術」中村 光佑/GMOペパボ株式会社

4人目の登壇者である中村 光佑さん(@litencatt)ホスティング事業部ムームードメイングループに配属。Webサービス開発においてPHPやRuby、サービス知識など福岡支社の凄腕エンジニアたちに囲まれて日々多くのことを学ばれながら、毎日を全力で楽しんでいるそうです。この日は、ムームードメインに新しく追加されたショッピングカート機能の裏側についてお話してくださいました。

speakerdeck.com

f:id:mamiracle:20171115174515j:plain(ペパボさんのケータリングご飯もボリュームたっぷりで大満足!)

この日のご飯には、「minne」に出品されていたクラフトチーズも登場。お洒落で美味しくて感動の一言でした…。ペパボさん、ありがとうございました!

また今回、クックパッドからは2名が登壇しました。

「機械学習でサービスの常識を破壊する」杉本 風斗/クックパッド株式会社

サービス開発部エンジニアの杉本 風斗(@uiureo)。機械学習を使ったプロダクト開発に携わっています。入社当初はAndroid開発を担当するはずが、気づいたらPythonやRedshiftを使ったバックエンド開発が中心になっていたそうです。この日は機械学習を活用したクックパッドの新機能「料理きろく」について登壇しました。

speakerdeck.com

「巨大アプリにおける新規開発とチームビルディング」勝間 亮/クックパッド株式会社

現在サービス開発部長を務める勝間 亮(@ryo_katsuma)は、これまで新規事業、検索、投稿、会員事業などの部門での開発およびエンジニアリーダーを担当してきました。著書に「Webサービス開発徹底攻略」「すべての人に知っておいてほしいJavaScriptの基本原則」などがあり、この日は大規模なチーム開発におけるチームビルディングの方法について登壇をしました。

speakerdeck.com

f:id:mamiracle:20171115174454j:plain(楽しかった2日間の様子です♪)

まとめ

いかがでしたか?とても実りが大きい出張イベントだったため、また開催したいと思っています。次はどこの会社にお邪魔させていただこうかと考え中です…!

クックパッドでは毎月テーマを変えて技術イベントを開催しておりますので、ご興味のある方はイベント Connpassページをご覧くださいね。

▼イベントページ

cookpad.connpass.com

新しい仲間を募集中

クックパッドではレシピサービスの更なるパワーアップと、新規事業の開発に注力をしています!少しでも興味のある方は、まずお気軽にご連絡をお待ちしております!

■ Android アプリエンジニアの募集はこちらhttps://cookpad.wd3.myworkdayjobs.com/ja-JP/jobs/job/-/Android---_R-000145

■ iOS アプリエンジニアの募集はこちらhttps://cookpad.wd3.myworkdayjobs.com/ja-JP/jobs/job/-/iOS---_R-000162

■ Web アプリエンジニアの募集はこちらhttps://cookpad.wd3.myworkdayjobs.com/ja-JP/jobs/job/-/Web--_R-000095


クックパッドのAmazon Echo向けサービスをリリースしました 〜開発で得られた音声操作の知見〜

$
0
0

こんにちは。研究開発部エンジニアの山田(@y_am_a_da)です。ついに日本でも Amazon Echo の発売が始まりましたね。

今回は Amazon Echo 向けにリリースをしたクックパッドのスキル( Amazon Echoではアプリと呼ばずにスキルと呼びます)についての紹介と、開発をしてみてわかった音声操作の強みと弱みについて紹介をしていきたいと思います。

Amazon Echoとは

Amazon Echo は、Amazon 社の販売するスマートスピーカーです。声で命令をすることで、端末に内蔵されている Alexa と呼ばれる音声アシスタントが処理を行ってくれます。 特徴として、基本的に操作は全て音声で行い、レスポンスも音声で返ってくる点が挙げられます(海外では液晶が搭載されており、そこへレスポンスを返すモデルも存在します)。

すなわち、スキルの開発者は、 PC やスマートフォン上と違い、基本的には全てを音声のみで完結させる必要があるという前提で開発を進めていく必要があります。 この制約のもと開発を進めて得られた音声でのユーザーインターフェース、いわゆる Voice User Interface についての強みと弱みについて紹介をします。

Voice User Interface の強み

  • 情報の入出力が早い

端末を手に届く範囲に持ってくる必要がないため、使いたいと思った瞬間に命令を行い、その結果を受け取ることが出来ます。

  • 操作が直感的

音声アシスタントのインタラクションは基本的に人間を模倣しているため、人間とのコミュニケーションを取るように操作が出来ます。

  • ハンズフリー

入出力は音声なので、キッチンや車内、フィットネス中には嬉しい利点です。

Voice User Interface の弱み

  • 一覧性に乏しい

視覚での情報と比較して処理できる情報量は少ないため、一度に多くの情報を返す用途には向いていません。何かの検索結果を30件読み上げられる状況を想像してみるとその難しさがわかると思います。

  • 情報のフィルタリングが難しい

視覚的な情報であれば、慣れてくると流し読みのように必要な情報だけを受け取ることができるのですが、音声では読み上げ側に工夫をしないとこれが出来ません。

  • 全体のインタラクションはそこまで早くない

入出力こそ早いものの、出力された情報をフィルタリングすることが難しいことから、工夫をしないと全体のインタラクションは早くなりません。

また、強みか弱みかはケースバイケースなのですが

  • インタラクションは基本的に全てオープンである

という点も大きな違いです。

クックパッド 〜使いたい材料だけで、すぐに作れる人気の料理レシピ提案〜

上記の点を踏まえた上で、さらに

  • Amazon Echoは基本的に屋内、特に個人での購入であれば家に置かれることが多いだろう
  • 聞かれるタイミングは料理をする直前、もしくは最中である

という仮説を立てて、わざわざ買い物に行かなくてもすぐに料理を始められるよう、冷蔵庫にある食材1つだけで美味しい料理のインスピレーションを与えるスキルを開発しました。

スキルの具体例は、明日弊社デザイナーの倉光が投稿する記事にございますのでこちらでは省略致します。

現在プレミアムサービスユーザーでない方は、スキルの起動時にプレミアムサービスが最大2ヶ月無料になるクーポンをプレゼントしておりますのでこの機会にぜひお試しください。

工夫をした点

スキルを開発する上で意識をしたことを紹介します。

モバイルアプリの代替は目指さない

Voice User Interface の特性上、一貫した情報が取得しにくく、フィルタリングも難しいため一度に提供できる情報はかなり少ないです。また、スマートスピーカーはスマートフォンとハードウェアの特性が異なり、おそらく購入の用途も異なることが多いと思います。

そのため、スマートフォン用に提供されているモバイルアプリをそのまま移植しようとせず、音声操作の利便性をできる限り活かせるよう意識して開発を進めました。

インタラクションをできる限り減らす

せっかく情報の入出力が早いという利点を持つ Voice User Interface を使っても、インタラクションを増やしてしまうと全体としてはスマートフォンを使ったほうが早いし便利ということになりかねません。

そうならないように、クックパッドのスキルでは無駄なインタラクションを省きシンプルにすることを目指しました。これは、例えば読み上げる文章を短くするというだけのことではなく、そもそもスマートスピーカーには向いていないような機能は実装せず、できることを思い切って減らすということもしています。

例えば、何でも検索できるフリー検索機能でユーザーの望む検索結果を提供するためには、スキルは提案の量を増やすか聞かれた内容の意図を絞り込むためにユーザーに質問をする必要があります。これではユーザーに長い文章を我慢して聞いてもらうか、多くの質問に答えてもらうことが必要となってしまい離脱の原因となるおそれがあります。

聞かれた内容によって提案のフローを変える

無駄なインタラクションを減らしつつもできる限り多くのニーズに応えられるよう、聞かれた内容によってレシピを提案するロジック、インタラクションを変更しています。大まかには

  • 食材1つの場合 もともとのコンセプトである「使いたい材料だけで、すぐに作れる人気の料理レシピ提案」に準じて聞かれた材料だけで簡単に作ることのできるレシピを提案します。
  • 食材2 or 3つの場合 インスピレーションを得ることを目的としていると想定し、食材が1つの場合よりも幅広くレシピを提案します。
  • 料理名を聞かれた場合 その料理の作り方を思い出したい(もしくは知りたい)と想定し、その料理で一番人気のレシピを提案します。

これら3パターンにおいて、それぞれユーザーが聞く状況の仮説を立て、適切な提案ができるようロジックを組み立てています。 あくまでも仮説をベースとしているので、利用のされ方を見ながら検証と改善を進めていく必要があると思います。

このような工夫をすることで、モバイルアプリのような万能さはなくても、特定のシーンではより役に立てるよう意識しています。 PCとスマートフォンの関係のように、シーンごとに使い分けられる存在になることを目指しています。

日常的に使えるものを目指す

Amazon Echo には液晶が存在しないため、ユーザーはスキルのインストール時以外にそのアイコンを目にする機会がありません。

すなわち、一度ユーザーにスキルの存在を忘れられてしまうと再び見つけてもらうことが困難であるため、リテンション率が低くなってしまいます。 そのためにも、日常的に使ってもらうことでその存在を覚えていてもらえることを目指しました。

まとめ

いかがでしたでしょうか。スマートスピーカー向けに提供するサービスは、その制約の厳しさにより、ユーザーやその周辺情報へのより深い理解が必要となります。

今回は仮説と検証にもとづき開発を進めていきましたが、機械学習やIoTを活用することでよりユーザーフレンドリーなサービスを開発できる可能性があると考えています。弊社ではこのような課題を解決できる機械学習、IoTの知識を持つエンジニアを募集しています。 クックパッド株式会社 研究開発部 採用情報

明日は弊社デザイナーの倉光よりスキルの開発にあたって実際に行ったプロトタイピングなどについて紹介致します。

対話のデザインプロセス〜Amazon Echoのスキル開発〜

$
0
0

f:id:transit_kix:20171121225937p:plain

デザイナー倉光です。先日ついに日本語に対応した Amazon Echo!エンジニア山田の記事に引き続き、今日は音声操作のデザインプロセスについて紹介します。

💬 Amazon Echoとは

f:id:transit_kix:20171121225949p:plain

Amazon Echoは、音声だけでリモート操作できるスマートスピーカーです。「アレクサ」と話しかけることで、様々なスキルを実行することができます。音声操作の特徴は「命令はことばで実行し、結果は音声で受け取る」こと。そのため、視覚や触覚の情報なしでもコンピューターと対話可能なデザインが求められます。

🍳 クックパッドのスキルについて

「使いたい材料だけで、すぐに作れる人気の料理レシピ提案」

このスキルでは、Amazon Echoを使って使いたい材料だけですぐに作れる人気の料理レシピを教えてくれます。

f:id:transit_kix:20171121225953p:plain

「晩ごはん用意したけどなんかちょっと物足りない...」 「冷蔵庫になすが余っているけど、スマホでレシピさがすのは面倒…」

そんな時は使いたい材料をクックパッドに呼びかけてください。クックパッドが材料にあった食べ方やレシピを一緒に考えて、今日作る料理を考えているあなたに提案します。レシピが決まったらiOS/Androidアプリへ自動でそのレシピを送信します。*1

✍️ 初期コンセプト

日々の料理に役立つスキルとしては、レシピ読み上げ/調理補助/ニュースなどいくつかの構想がありましたが、

  • 日常で繰り返し使える
  • インスピレーションを与えることで、「今日は料理するぞ!」というモチベーションを与える
  • クックパッド上にある278万品のレシピを活用

といった点を念頭に置き、検証活動を通し現在のスキルができあがりました。

[図]初期に構想していたユーザーストーリー図

f:id:transit_kix:20171121230007p:plain

🏃 Let's プロトタイピング

音声操作の可能性を探るために、さまざまな検証活動を行いましたが、その中で特徴的だったものを紹介します。

Case1. Alexaになりきる

登場人物は、作り手役とAlexa役の2名。作り手役は、Alexa役に話しかけてレシピを読み上げてもらいながら料理してみるといったもの。人間が擬似的にAlexa役をする*2ので、一行もコードを書かずとも検証可能です。(音声アシスタントの検証方法としては、相性が良いですね)

結果は…あまり芳しくはありませんでした。音声入力は便利でも、音声出力はやはり認知の面でハードルがあります。とはいえ実際に体験してみると、「食材を切って…と言われてもどう切るの?写真がないとわからない」「想像していた見た目と全然違った」など、何がどう不便なのかが可視化された点では収穫がありました。

Case2.音声対応レシピを自分で書いてみる

つぎに「音声で聴いた時に理解しやすい料理の表現とは何か?」を知るために、自分で音声対応レシピを書いてみました。以下は「ツナと枝豆のマヨネーズ和え」というレシピの手順です。音声で聞き取りやすいようリライトしてみると、いくつかの表現のコツが見えてきます。

f:id:transit_kix:20171121230000p:plain

クックパッドに存在するレシピは基本的に目で読み取りやすいフォーマットで書かれたレシピが大半です。先ほどのCase1の検証結果も合わせて、既存レシピをそのまま音声で読み上げるだけでは実際に料理をする行動まで導くことは現段階では難しいことがわかりました。

そのため、今回のスキルではAmazon Alexaは料理するきっかけを生み出す存在として捉え、全ての行動を音声で完結させるのではなく、スマートフォンのクックパッドアプリと連携することでユーザーの目的を達成する設計に変更しました。

Case3.いざ食材を目の前にすると、人々はどう行動するのか?

スマートフォンのクックパッドアプリと連携をするという方針も決まり、理想的な発話フローは設計できました。つぎに確かめたのは「スキルを使ってみようかなと思う場面に遭遇した時、人は何を話しかけるのか?」についてです。

開発中のスキルのユーザーテストを実施するにあたって、Amazon Echo/スキルページ…そしてちょっとした小道具を用意しました。

f:id:transit_kix:20171121230013p:plain

段ボールを横置きして食材を入れただけの簡易冷蔵庫です(紙で書いた冷蔵庫をつかうことをもありました)。こんな粗末な小道具でも、テストユーザーは真剣に食材と向き合ってくれて自由にAlexaに話しかけ始めます。

  • 「(スキル紹介ページを見ながら恐る恐る)アレクサ、クックパッドでアボカドでできる料理教えて…?」
  • 「アレクサ、高野豆腐で作れる料理を教えて…あ!クックパッドって言ってない!」
  • 「アレクサ、たまご わかめ スープ 作りたい」

数人のユーザーテストの結果、1つの問題が発覚しました。全員が複数食材からレシピを探す発話を試みたのです。当初このスキルはレシピ提案の精度の問題から食材1つだけからレシピを探す仕様だったのですが、複数食材対応の作業優先をあげて集中的に改良を加えることにしました。

なおリリース後の現在、ユーザーからの全発話のうち44%が複数食材からレシピを探すリクエストだったため、これは事前に発見できてよかった気づきでした。

💡 音声デザインのポイント

音声に関するデザインプロセスについては、amazonが提供している音声デザインガイドを一読していただくのが良いと思いますが、今回の開発を通して特にポイントと感じたのは以下です。

音声認識結果はユーザーにフィードバックしよう

音声操作UIはまだまだ発展途上であり、ありとあらゆる問いかけに万能に対応できるわけではありません。また、環境音やユーザーのイントネーションなど様々な要因で誤認識が発生してしまうこともあります。

ユーザーテストの中でも、ユーザーとアレクサが違う食材を想起したまま気づかず会話が進んでしまい、最終的にレシピを見たときに「間違ってた!」と気づく例もありました。

音声の認識結果は、「…ナスですね。それでは次の中から気になる食べ方を教えてください。」など、つぎの応答で伝えるなどの工夫をしましょう。

シングルタスク、シンプルセンテンス

音声操作UIは、人とコンピューターの対になる言葉のキャッチボールで成立します。そのためスキルの全体像を俯瞰して見るのは難しく、ユーザーは今この瞬間の応答に神経を集中しています。モバイルスクリーン上で動作するUIと違い、前の画面に戻る/中断/スキップといった行為が容易にはできません。3つ以上の長い文章が連なると、何をしていたのかわからなくなります。

極力シンプルなフィードバックを心がけましょう。前述のガイドラインでは「普通に会話する速度で一息にそのセリフを読み上げることができたら、適切なセリフの長さと考えてよいでしょう。」とされています。

人間味のあるセリフはほどほどに

実は開発当初は「人っぽい対話感」を重視するあまり、返答のたびに「それではこちらはいかがでしょうか?」といったコンシェルジュのような丁寧な問いかけを使っていました。

しかしスキルの利用回数を重ねると「もうわかってて、早く次の命令を出したいのに、話しかけるのを待たなければならない…」とWebページのローディング待ちのような苛立ちを感じるようになったため、あまり意味を持たないフィードバックテキストは極力カットしました。

…以上、是非Amazon Echoをお持ちの方はクックパッドを使ってみて、何か気になる点ございましたら是非私たちにフィードバックをいただければ幸いです。 それでは、皆さん楽しいスマートスピーカーライフを。

様々な領域でデザインしたい仲間を募集中です

クックパッドでは、新しい領域におけるインターフェイスデザインも手掛けたいデザイナーを絶賛募集中です。 こちらから是非コンタクトお待ちしています。

*1:こちらのスキルはクックパッドプレミアムサービスご利用の方に提供されております。プレミアムサービス会員ではない方も、クックパッドのスキルを使うとプレミアムサービスがご利用いただけるクーポンが発行されますので、ぜひこの機会にお試しください。

*2:サービスデザインの分野では、オズの魔法使いやアクティングアウトと呼ばれることもあります

2017 Lifestyle Product Award by Cookpad のお知らせ

$
0
0

いつもお世話になっております。エンジニア統括マネージャーの高井です。

クックパッドは 2017 Lifestyle Product Award by Cookpadを開催いたします。このアワードは「生活をより良くする」をテーマに、個人と社会と地球がかかえるさまざまな課題を見つけ、考え、解決するインターネットサービス、もしくはモバイル・アプリケーションを応援し、表彰するアワードです。

世の中には多くのサービスやアプリケーションがあります。そのようなサービスやアプリケーションの中でも、生活に根差したアプリケーションというのは、必ずしも多いというわけではありません。クックパッドは、そういったサービスやアプリケーションが少しでも増えればという気持ちから、このアワードを開催することを決定いたしました。

アワードの対象は、2017年に初めてリリースされたインターネットサービス、モバイルアプリケーションです。応募いただいた作品の中から優秀賞を3作品選出いたします。さらにその中から最優秀作品には Life Style Product Award として、賞金100万円を贈呈いたします。また、応募は個人、もしくは3名程度までのグループに限らせていただいています。

ぜひ、みなさまからのご応募をお待ちしております。アワードの詳細は下記のサイトをご覧ください。

【開催レポ】Cookpad Tech Kitchen #13 〜クックパッドにおける研究開発のサービス活用事例〜

$
0
0

こんにちは!人事部の冨永です。

2017年11月15日に「Cookpad Tech Kitchen #13 〜クックパッドにおける研究開発のサービス活用事例〜」を開催しました。クックパッドではこのイベントを通して、技術的やサービス開発に関する知見を定期的に発信しています。

第13回のテーマはずばり「研究開発」です。クックパッド 研究開発部では、既存技術ではなかなか難しかった事を新しい研究などをもとに解決して、ユーザにより高水準な価値を届けることを目標としています。研究成果としても、既にいくつかの技術がプロダクトに組み込まれているものがあります。そこで今回は発足から1年*1が経った研究開発部の、研究成果のサービス活用事例に焦点をあてました。

それでは各登壇についてご紹介します。

f:id:cookpadtech:20171126172143p:plain

Encoder-Decoder にもとづく材料名の正規化(原島)

最初は研究開発部長 原島(jun-harashima.net)がクックパッドにおける自然言語処理について発表しました。

クックパッドのレシピはユーザの自由記述によって作成されています。そのため、材料名に種々のバリエーションがあります。例えば、「しょうゆ」には 100 種類以上のバリエーションがあります。

これらのバリエーションを吸収するため、クックパッドでは Encoder-Decoder を利用しています。レシピ中の材料名(e.g. ★醤油)を入力に、その正規化された表現(e.g. しょうゆ)を出力にして、Encoder-Decoder を学習しています。学習されたモデルを使用すれば、様々な材料名を正規化できます。

この発表については以下のエントリでも解説しているので、よろしければご覧ください。

画像分析によるレシピのカテゴリ分類(菊田)

次は画像分析の発表で、研究開発部 菊田(@yohei_kikuta)が画像分析を用いたレシピのカテゴリ分類に関して話しました。 ここで言うレシピのカテゴリとは {カレー, から揚げ, ...} などの料理の種類に対応しています。

クックパッドのアプリでは「料理きろく」というユーザの携帯端末から料理の画像のみを抽出してカレンダー形式で表示するサービスを提供しており、2017年9月28日時点で料理と判定された画像が1000万枚 *2に達しています。 これらの画像を活用してユーザにとってより良いサービスを創っていきたいわけですが、そのためには色々な情報(レシピのカテゴリ、朝昼晩、カロリー、...)を付与することが助けとなります。

ユーザの画像はプライバシーの観点から我々が目でチェックすることはできないため、機械学習を用いてレシピのカテゴリ分類をしよう、そしてそのためにはどんな工夫をしているか、ということが発表の主旨となります。

資料内では実サービスにおける画像分析の難しさや、サービスとして成立する precision をどう実現するか、などを紹介しています。
難しい問題でまだまだ改善すべき点も多いですが、面白い内容ですので、どこかのタイミングでまた詳しく解説をしたいと考えています。

また今回は、料理を提供してくれたシェフにお願いをして、料理の中にレシピのカテゴリ分類の対象となるから揚げを入れていただきました。 菊田の携帯で写真を撮ったところ、適切にから揚げと判別され結果が表示されました。

f:id:cookpadtech:20171126141646j:plainつくっていただいたから揚げの写真がこちらです。

f:id:cookpadtech:20171126154923p:plainこの時の写真がから揚げと認識されて、サムネイル画像として選出されたときのスクリーンショットがこちらです。

また、レシピのカテゴリ分類の前段となる「料理きろく」に関して興味のある方は、以下の過去エントリをご覧下さい。

Alexa Skill 開発のあれこれ(山田)

最後は最近日本に上陸したばかりの Amazon Echo 向けにリリースしたクックパッドのスキル( Amazon Echo ではアプリと呼ばずにスキルと呼びます)について研究開発部 山田(@y_am_a_da)が発表をしました。内容としては開発の際に意識をしたこと、またAmazon Echo の特徴である音声インターフェースの強みと弱みについて話をしました。

Amazon Echo はAmazon社から発売された音声アシスタント搭載デバイスで、基本的に入出力は音声のみです。サードパーティにより提供されているスキルを有効化することでさまざまなことができるようになりますが、スキルのアイコンを目にするタイミングが有効化の時のみなので一度存在を忘れられてしまうと再び利用してもらうことが困難です。そのため、ある統計の結果でスキルのリテンション率は3%とも言われています。

また、視覚による情報の取得と比較して、聴覚による情報の取得は一覧性の乏しさやフィルタリングの難しさなどからいわゆるモバイルアプリケーションとして提供しているサービスをそのまま移植しても上手くいきません。

そのため、プロトタイピングを重ねつつ音声インターフェースに適したサービスを提供できるよう開発を進めました。

スキルの開発について、以下に詳しくまとめられているので興味のある方はぜひご覧ください。

イベントの様子をご紹介

f:id:cookpadtech:20171126170325j:plain Cookpad Tech Kitchenでは、よりリラックスした状態で発表を聞いていただくために、イベントの開始とともに乾杯をします!この日は中華料理をメインとした絶品ご飯が登場しました♪

f:id:cookpadtech:20171126165844j:plain中でも目玉はクックパッドのロゴをあしらったライスケーキ。ご飯が2層になっていて間に具材が挟まれているんです。見た目がきれいなことはもちろん、美味しくてお腹いっぱいになるので大人気なメニューとなりました。

f:id:cookpadtech:20171126170449j:plainご飯を食べながら発表を聞いた後には、付箋方式でのQAディスカッションを行います。発表を聞いて気になったことをその場でメモをしていただくことで、より新鮮な質問を気兼ねなくできるように工夫しています。

まとめ

いかがでしたか?クックパッドではテーマを変えて定期的に技術イベントを開催しています。みなさんも是非遊びに来てくださいね。

👇イベントページはこちらクックパッド株式会社 - connpass

また今回登壇したメンバーが所属する研究開発部では新しい仲間を募集しています!ご興味がある方は是非ページをご覧になってください。👇研究開発部では仲間を募集しています🔍・リサーチエンジニア・研究員

*1:クックパッドの研究開発部は2016年7月に発足しました

*2:https://info.cookpad.com/pr/news/press_2017_0928

サービスイメージをより魅力的に見せる写真撮影

$
0
0

国内事業開発部のデザイナー、木村です。私が現在携わっている「おうちレッスン」*というサービス上で利用する写真を撮影するために、久しぶりにプロのカメラマンさんとお仕事をする機会がありました。

今回は、外部のカメラマンさんとサービスのイメージ写真を撮影する際に参考になりそうなことをブログに残そうと思います。

ヒアリング

まず写真撮影の目的を定めます。どういった目的で、ユーザーにどんな印象を与えたいか、ゴールはなにか、といった項目を洗い出し、オーナーと話し合いました。

今回は「ランディングページやサービス上で、サービスの魅力をユーザーに伝えたい」「楽しさや親しみやすさが増幅されるようなイメージ」「気取らない、日常の延長線上で」といった要望が上がりました。

イメージを固める

ヒアリングが終わったら、次はサービスのイメージを固めます。

以下は私がチームに参加した際に、競合・類似サービスなどをまとめ、ポジショニングしたデザインのマトリクス図です。

f:id:mura24:20171201152034p:plain

また、撮影する写真のイメージをキーワードとして書き出し、イメージに齟齬はないかも合わせて確認しました。

f:id:mura24:20171201152041p:plain

これらのすり合わせの作業をどこまで深掘りするかは、プロジェクトへの携わり方で調整するとよいでしょう(今回はサービス全体設計からの参加だったので結構がっちりやっています)。

トンマナのすり合わせ

並行して、写真のトンマナのサンプルをPinterestのシークレットボードを利用して収集しました。方向性をオーナーに確認してもらい、問題なさそうであれば、具体的なカットのラフ作業へ進みます。

f:id:mura24:20171201152044p:plain

絵コンテの作成

サービスのイメージを踏まえながら、ユーザーストーリーに沿って、デザイン上必要なカットを割り出し、絵コンテに起こしていきます。

f:id:mura24:20171201174301p:plain

テキストを交えながら、オーナーやカメラマンに、おうちレッスンのリラックスした和やかな雰囲気が伝わるよう気を配りました。

なお、イラストが不得手、イメージ通りのサンプル写真が用意できない場合などは、既存のストックフォトをコラージュしたり、自分やメンバーを素材としてスマホで撮影してコンテを用意するのもよいでしょう。

方法はなんでもよいので、なるべくコストをかけず、頭の中のイメージをスピーディーにメンバーに共有できる方法を選ぶことが重要です。

実際に写真をデザインに当て込んだデザインカンプなどがあれば、より完成形をイメージしやすくなるので、準備しておくとよいでしょう。

カメラマンとの打ち合わせ

写真のイメージ・必要カットが確定したらカメラマンと打ち合わせをします。

サービスの概要説明、写真のイメージ、絵コンテなどを元に、スケジュール、撮影場所や衣装、必要な機材などの相談と確認を行いました。

画角について

今回は、一部、9:16(スマートフォン縦サイズ)での利用を検討しておりましたが、コンテでその場合の指定が不十分であったことが判明しました。

複数の画角で撮影を予定している場合は、予めリストアップし、そのフレームに応じてコンテを切るようにしましょう。

撮影場所・衣装・小物について

今回は実際のユーザーさんのお宅にお邪魔して撮影することになっていたので、当日の間取りの確認、ユーザーさんの衣装(服装や髪形のかぶりがないか、サービスのイメージに沿った服装の依頼など)、当日のメニューの確認などを行いました。

撮影

撮影日当日は、プロダクトオーナー・カメラマン・デザイナーの3名でユーザーさんのお宅に伺い、撮影に協力してくださるユーザーさんに、絵コンテを見せながら撮影のイメージを伝え、撮影に望みました。

撮影立会時に、今回は私が撮影の進行管理・写真の確認などを担当しました。

進行管理では、撮影順の調整、カットの抜け漏れがないかのチェック、時間帯や天候により撮影状況が変わってしまった際の判断(カット数の増減、ほかのシチュエーションへの変更)なども行います。今回の撮影では、天候に恵まれ滞りなく進行できました。

カットごとに撮影時間を確保する

今回はユーザーさんが実際にお料理する流れに沿って、リラックスした自然な様子を撮影したいと考え、撮影に望みました。

ですが、被写体が複数人の場合、状況をコントロールしないと、誰かが目をつぶってしまっている、画面に対し立ち位置が左右一方に寄りすぎてしまうということが発生しがちです。

サービスの利用シーンを撮影する場合は、手順ごとに手を止めて、撮影時間を確保してから進行させたほうが結果的にスムーズに撮影が進みました。

写真確認

撮影終了後、追ってカメラマンから確認用のデータが送られてくるので、その中から納品用のカットを指定します。

f:id:mura24:20171201152053j:plain

私は昔から利用しているAdobe Bridgeを使用して、写真選別を行っております。Finderでも似たようなことは可能ですが、ビューワー機能のあるツールを利用し、効率よく写真を選別してゆくのがオススメです。

納品

納品してもらう写真が決まったら、納品形式(ファイル形式、カラープロファイル、画像サイズなど)を指定して、撮影データを受け取ります。

進行・撮影ともに、カメラマン、そして参加してくださったユーザーさんにかなり助けていただだいたおかげで、めちゃんこエモい写真に仕上がったので、一部公開します。

f:id:mura24:20171201152517j:plain

Photo by 福田 栄美子

おわりに

目的を定め、最小限のコストでチーム内で合意を取りながらユーザーに届ける…というプロセスは、写真撮影でもサービス開発でも、そう違いはありません。

自社サービス以外にも、採用募集やイベント用の写真などで、デザイナーに写真撮影の相談が入ることも多いと思います。みなさまの参考になれば幸いです。


*…「おうちレッスン」は現在クローズドテスト中のCtoC料理教室プラットフォームです。

Viewing all 801 articles
Browse latest View live