Cloud Run 使ってみた

こんにちは。サーバーサイドエンジニアの平井です。

今年もあと1ヶ月ですね。リモートワーク中心の生活スタイルに変わり、より一層時が過ぎるのを速く感じています。

もう年末ということで、弊社では今年もAdvent Calendarを開催します!!

題して、Enigmo Advent Calendar 2020です!!

記念すべき1日目は、私、平井の「Cloud Run 使ってみた」になります。 プロジェクトで簡単なAPIをCloud Run(フルマネージド)上に実装したので、それについて話したいと思います。

構成

会員毎にパーソナライズされたコンテンツ情報を返すAPIをCloud Runを使って実装しました。 とてもシンプルですが、構成図は以下のようになります。

f:id:enigmo7:20201124163920p:plain Cloud Run上にRuby on RailsAPIを実装し、Datastoreに格納されている情報を取得します。 Datastoreには、会員毎のコンテンツ情報が格納されていて、この情報はBigquery上に格納されている機械学習のデータを元に生成されています。 そして、クライアントからAPIにアクセスして情報を表示させています。

Cloud Run(フルマネージド)について

Knativeを基盤として構築されたGCPのサーバーレスサービスの一つで、コンテナをサーバーレスで実行してくれます。 スケーリングなども自動で行われるため、開発者はアプリケーションの開発に専念することができます。

Cloud Runには二種類あり、Googleが管理するKubernetes環境で動作するCloud Runと自身の管理するGKEで動作するCloud Run for Anthosがあります。 今回は、より簡単に利用できるCloud Runを使いました。

準備

Dockerfile

Cloud Run上で動かすコンテナを用意する必要があるので、 Dockerfileを用意します。

cloudbuild yaml

Cloud Runへのデプロイ関連のタスクはcloudbuild.yamlで管理しました。 公式ドキュメントにも記載されているやり方と同じです。 ファイルの中身は、コンテナイメージのbuildとCloud Runへのデプロイなどのタスクが記載されていて、 実際の内容とは違いますが、以下のような感じになります。

steps:
# コンテナイメージのビルド
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/PROJECT_ID/IMAGE', '.']
# コンテナレジストリーにpush
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'gcr.io/PROJECT_ID/IMAGE']
# コンテナレジストリー上のイメージを使って、Cloud Runにコンテナをデプロイ。
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: gcloud
  args: ['run', 'deploy', 'SERVICE-NAME', '--image', 'gcr.io/PROJECT_ID/IMAGE', '--region', 'REGION', '--platform', 'managed']
images:
- gcr.io/PROJECT_ID/IMAGE

cloudbuild.yamlを作成したディレクトリによりますが、

gcloud builds submit

を実行するとファイルに書かれたタスクが実行され、Cloud Run上にサービスがデプロイされます。

基本的には、Cloud Run上でコンテナを起動するために必要な準備は以上になります。

その他

ドメイン

Cloud Runでサービスを作成すると自動でデフォルトのドメインが発行されます。 ただ、実際のサービスで利用する際にはカスタムのドメインを設定したくなると思います。 Cloud Runにはカスタムドメインのマッピング機能が実装されているので、使いたいドメインマッピングすることができます。 実際にカスタムドメインを設定してみましたが、ドキュメントを読んで簡単に設定することができました。

GCPサービスとの連携

APIのデータ取得先として、Datastoreを使用しています。 今回は、Cloud Runのサービス とDatastoreのデータが同じプロジェクト上で管理されていたので、二つのサービスが連携する際に、認証の設定は必要ありませんでした。

感想

実際にCloud Runを使ってみた感想は以下です。

  • インフラ関連を意識せず開発できて、アプリケーションの実装に集中できた。
  • デフォルトのメトリクスが充実していた。
    • リクエスト数、コンテナのメモリ使用率
  • ログも充実していた。
    • キーワード検索、 重要度によるフィルタリング
  • GCPサービスとの連携が楽だった。

最後に

今回のプロジェクトの方針で、なるべく早くユーザーの行動をみたいという背景もあり、Cloud Run上にAPIだけを実装するという最低限の選択をしました。 今後の長期運用を考えて、機械学習のデータからAPI用のデータを生成する部分もCloud Run上に乗っけていこうと考えています。

最後まで読んで頂き誠にありがとうございました。

明日の記事の担当は、UXDグループの本田さんです!!


株式会社エニグモ 正社員の求人一覧

hrmos.co

男性インフラエンジニアが育児休業を取得した話

こんにちは。インフラグループの夏目です。

前回のエントリーより3ヶ月、エントリー投稿から2週間ほどで無事子供が誕生し育休期間を経て先日復職しました。

今回のエントリーでは実際に育休を取得してみてどうだったのか?といった内容を書いていきます。開発者ブログというお題目にも関わらず育休話が続いてしまい恐縮ですがお付き合いください。

f:id:enigmo7:20201001224429p:plain

育休っていつから取るの?

いざ育休を取るぞ!と意気込んで最初に感じたのが「いつから育休を取ればいいの?」という、開始時期についての疑問でした。

女性の場合出産予定日の1ヶ月少々前から産前休業に入り、予定日が多少前後しても産後休業を経て育児休業、という流れになるのでさほど開始時期について悩む部分は少ないと思うのですが、男性は産前休業がありません。

予定日から育休取得開始ということで社内調整はしていたものの、いざ予定日になっても兆候がなかったためなし崩しに「生まれた翌日から休みます」という本人も周囲もどうしたら良いのかわからない宣言後、1週間ほど後ろ倒して生まれたので育休開始、というスケジュールになってしまいました。

実のところ育児休業の法令上は予定日から取得可能なため、気兼ねなく育休開始としてもまったく問題ないのですが、生まれていないのに休業して日がな一日何をしていたらいいんだ…?という戸惑いがあり、育休に踏み出せませんでした。

ただ、人事総務的な観点からはいたずらに後ろ倒しをすると給与計算などで面倒な調整が発生するような(というか発生した)ので、やることがあろうがなかろうが当初予定日から変更するべきではなかったかな、と反省しています。

なお予定日から育児休業は取得可能なものの、育児休業給付金は出産日から起算となるようなので(詳しくは育児休業に関する各種法律をご参照ください)、そのあたりも踏まえて調整するのがベターだと思われます。

育休ってどれくらい取るの?

いざ育休が始まり、体力がまだ本調子でない妻のサポートをしつつ日々の育児におおわらわになって1ヶ月が経過したあたりで、次は「これ育休期間2ヶ月の予定だったけど全然足りないんじゃないか…?」という疑問が生じました。

新生児期は授乳やおむつの回数が多く手がかかるから、大変な時期を乗り越えれば…と思ったのですが、乳児期になっても手がかかることには変わりなく、大変じゃない時期など存在しません。

たとえば「首が座るまで」といった身体的な発達状況を目安にするのもわかりやすくて良いかなとは思ったのですが、いつ頃にできるようになるかはまちまちで、「復職時期は子供次第です」という状態は自分も周囲もどうしたら良いのかわからなくなってしまいます。

自分の場合は結局1ヶ月半頃に不安を感じた妻から「もっと伸ばせないの?柔軟に調整できるんでしょ?」と聞かれたものの「いや2ヶ月って一応決めてたし仕事の勘も忘れちゃうから…」とやや強引に押し切って当初予定通り2ヶ月で育休終了としました。

これは振り返ってみれば良い判断ではなかったと反省しています。生まれた時期や家庭環境によってまちまちになるかとは思いますが、極力調整して取れる限り取るのが家庭内平和のためにも最善です。

育休取ってみてどうだった?

当初育休を取るぞ!と決意したときの自分のスタンスは「妻には育児に専念してもらって、他の家事は全部自分が巻き取る」という、振り返ってみれば寝言のような方針だったのですが、当然ながら育児を1人でやりおおせるわけがなく。

2人がかりで育児の合間にそれぞれできる範囲で家事をするという状態がしばらく続き、育休終了1週間前くらいからワンオペ状態を意識して徐々に分担して、という形で慣らし運転をして育休を終えたものの、生活のスタイルについては現在も模索しているところです。

近隣にサポートしてくれる家族や友人がいたり、里帰り出産をするのであれば負担も軽減できるかと思いますが、核家族な我が家の事情と現在の社会状況を鑑みると、育児休業を取って(取れて)本当に良かったなと感じています。

人によっては出産後数日や1週間程度ちょっと手伝う程度というパターンも少なくないとは思うのですが、自分の場合は子供と接している期間が短いといざというときに勝手がわからず、足手まといになったであろうことは想像に難くありません。

また、取得前に予期していた通り…というか予期していた以上に生活のすべてが子供を中心として回るようになり、そのことに慣れるためにも育休期間は大変有用でした。

業務面ではどうだった?

育休取得前のエントリーではカオスエンジニアリングが云々と言っていましたが、メンバーが一人抜けた程度で大きな支障が出るわけもなく、引き継ぎが十分だったかどうかはさておき概ね問題はなかったという認識です。

自身の関わっているプロジェクトがある程度峠を越えたタイミングだったこともありますが、それ以上にタスクを引き継いでくれたチームメンバーがよしなに捌いてくれた部分が大きく、あらためて環境に恵まれているなと思いました。

他方で、リモートワークが定着したことと育児の疲弊からついつい社内Slackを眺めてちょっかいを出してしまうことが二度三度あり、これについては労務管理の観点からは褒められた行為ではないため、業務への未練をすっぱり断ち切る強い心が必要だという学びがありました。

準備は足りた?

以前のエントリでは必要なものをSpreadSheetで管理、TodoをTrelloで管理してこれで十分…と思っていたのですが、準備はまったく足りていなかったため現在進行系で色々と公的な申込み手続きをしたり育児グッズを買い足したりしています。

育児ブログではないので仔細には書きませんが、大雑把に導入して良かったものを以下に挙げます。

導入して良かったもの

  • ベビーモニター
    • 大きな戸建て住宅に住んでいるわけでもなし、狭小マンションで目の届くところにいるから必要ないかと思っていました。しかし、逆に生活圏内に子供がいるからこそ生活音や照明に気を使う日々に疲れ果て、適切な距離を保ちつつ様子を見るためにRaspberryPiでベビーモニターを作りました。
    • RPi Cam Web InterfaceというWebインタフェースを導入したため、市販のベビーモニターと違って専用のモニターユニット不要でPCやスマートフォンでどこからでも子供の様子が見れる、という完璧なソリューションが実現しました。
  • 育児記録アプリ:ぴよログ
    • 授乳時間や睡眠時間などありとあらゆる育児項目を夫婦間で記録共有・グラフで可視化できるのはもちろん、Apple Watchウィジェットからも記録ができるといった便利さで、このアプリなしでの育児は考えられないほどです。

f:id:enigmo7:20201001225224j:plainf:id:enigmo7:20201001225327j:plain
ベビーベッド側面から俯瞰する形でカメラを取り付けています。カメラとは別の位置から赤外線LEDも照射しているため、夜間でも様子が見えて安心です

気軽に育児休業を取ろう

家庭によっていろいろと事情はあるかと思いますが、上に挙げたように社会的な潮流や時勢からもこれまで以上に育休を取ることが推奨され、社会制度も整備されて金銭面の不安も軽減されていくことと思われます。

デメリットよりもメリットが多く、家族で濃密な期間を過ごせるのは間違いないので、ぜひ気軽に育児休業を取得されてみてはいかがでしょうか。

ちなみにこれはまったくの余談なのですが育休の2ヶ月間で3kg痩せました。日々成長するダンベルを使っていると強制的に鍛えられるので健康面でも育休はおすすめです。


株式会社エニグモ 正社員の求人一覧 hrmos.co

男性インフラエンジニアが育児休業取得までにやったこと

こんにちは。インフラグループの夏目です。

今回は技術的な話ではなく、ちょっとプライベートに込み入った話というかエンジニアのワークライフバランス的なお話です。

まったくの私事なんですがこのたび子供を授かることになりまして、ついては育児休業を取ってみようかな?ということで、育休取得までの流れと業務面でどういった対応をしていったのか、といったことを書いていきます。

育児休業を取ってみよう

f:id:enigmo7:20200616134043p:plain

今回育休の取得に至った経緯は色々とあるのですが、ひとつにワークライフバランスを見直す良いきっかけになるかな、という意図があります。

時短勤務やリモートワークではなく一旦完全に業務から離れてみて、日常生活における育児の占める割合はどの程度のものなのか(全部だよという意見はごもっともです)ということを理解しておくべきだろう、と。これを把握せずに、妻が産休・育休で子供の面倒を見るのに対して自分だけこれまでどおりの働き方をしていくのは、先々を考えると良いスタンスではないように思えたため、第一子のタイミングで育休を取ることにしました。

エニグモでは裁量労働のメンバーが多いこともあり、育児都合で勤務時間を調整する様子が日常的に見受けられます。このため、いざ自分に子供が生まれますよということになっても、育休を取得すること自体は自然と受け入れてもらうことができました。

受け入れるも何も労働者の権利の行使なので、本来拒否権はないはずでしょうという話なのですが、そうもいかない会社が多くあることもまた事実です。この点についてはエニグモの風土に助けられた部分が大きいなと感じています。

取得までの流れ

さて、では実際に育休を取りましょうとなってからどういった行動を取ったか、時系列に沿って大雑把ですが書いてみます。

2019年10月に妊娠確定となり、ここから家庭内協議に入りました。自分の稼働状況など鑑みて育休が果たして取れるのか、取れるのであればどれほどの期間で収入面で問題がないのか、などについて妻と喧々諤々やり合いました。

法制度の話をするのであれば1年以上取得することも可能ですが、現実問題として夫婦共に育休となった場合の収入への影響は無視することができず、第一子で不安を抱える妻に多少折れてもらいつつも2ヶ月取得してみましょう、ということになりました。

結論が出たのが11月末、ひとまずチームリーダーへ相談です。自分がアサインされているプロジェクトの今後の見通しや、その他担当タスクのチームメンバーへの委譲可否などを考慮のうえ、積極的に育休を取得してほしいとの言葉を頂きました。チーム内の調整は大丈夫(な状態にするしかない)となったので、後は部長や人事総務の方に掛け合うだけ、というところまで持っていきました。

年が明けて2020年の2月、自身のタスクを育休までにどう調整するかといった大まかな線表を作成して部長へ共有し、社内の具体的な育休取得手続きに入ります。

というタイミングで、全世界的に新型コロナウィルス感染症が広がり、エニグモでもリモートワークに突入し手続きはいったいどうすれば…?という状態になってしまいました。幸い事前手続きはほぼないことと、書類のためにわざわざ出社する必要なく郵送してねということで柔軟な対応をして頂けました。ありがたい限りです。

タスク調整どうしたの

タスク調整は実際問題どのようにしたかという点については特筆すべきことはなく、予定日までに大きなタスクを終わらせつつドキュメントを整理したり、自動化可能なタスクは自動化、間に合わない場合は手順書を作るといった形で粛々と対応を進めました。不穏当な表現ですが、トラック係数やバス係数といったものをあらためて意識することができました。

また、カオスエンジニアリングとまではいきませんが、どれだけ自分が準備をして引き継ぎをしたところで不測の事態は発生しうるので、そのあたりはチームメンバーになんとか拾い上げてもらうしかないかな、と自分勝手なことを考えています。

私生活で準備したこと

育休とはあまり関係なく、プライベートで準備したことについては基本的に世間の皆さんと同じです。強いて言えば、以下のようなエンジニアチックな手法で試行錯誤をしています。

  • 書籍や雑誌などから育児に関する必要なものリストをピックアップしてGoogle SpreadSheetへ書き出し、購入期限や数量、消耗品か否かといったメタ情報を付与して購入状況を管理
  • 公的な手続きなど、忘れがちなものはTrelloのカンバンを作って進捗管理

f:id:enigmo7:20200616134313p:plain
Trelloのボードイメージ

おそらくこういったことに対応するための専用アプリやサービスもあるかと思うのですが、それらの使い方を覚えている暇があったら使い慣れたツールを使ったほうが早いだろう、と横着をしている状況です。

今後の見通し

前述したように雪崩式にリモートワークとなり、当初想定していた育休へのロードマップとは少々異なる現状なのですが、反面リモートワークでも業務への支障はほぼゼロに近いということがわかりました。2ヶ月間の育休取得後に世間がどういった状態になっているのか(おそらくあまり変化はないでしょうが)推測できませんが、リモートワークへの敷居が下がったこともあるので、たとえば保育園に入れるまではセミリモートワークや半育休といった形態で、柔軟な働き方を選ぶこともできれば良いなと思っています。

このエントリーを書いてる今現在、出産まであと数日といった状況です。2ヶ月後にこのエントリーを読み返して「全然準備できてへんやんけ!なに余裕ぶっとるんじゃ!」となりそうな気配が漂っていますが、2ヶ月後に改めて育児休業の間に起きたことや感想についてのエントリー投稿を予定していますので、そちらをお楽しみに。

結びに

少々自己矛盾してしまうのですが、冷静に考えるとこのエントリーのタイトルは筋が悪いなという印象があります。こんなタイトルのエントリーが企業ブログのバリューとならず、掃いて捨てるようなエントリーとして扱われる時代にしていきたいものですね。


株式会社エニグモ 正社員の求人一覧 hrmos.co

GitLabのプロジェクトラベルとグループラベルを重複させてしまって困った話

こんにちは。インフラグループの夏目です。

エニグモではメインのGitサービスとしてGitLabを使ってソースコードを管理しています。 GitLabはGitHubと同様に、IssueやMR(PR)にラベルを付与して作業の優先度やステータスを表すことができるのですが、このラベルの運用でちょっと困ったことが発生して泥臭く解消するはめになったので、経緯と顛末含めてご紹介します。

プロジェクトラベルとグループラベル

GitLabのラベルは、プロジェクト(リポジトリ)とプロジェクトを束ねたグループとでそれぞれ個別に定義できます。 グループラベルとして定義したものは配下のプロジェクトでも使用できるため、基本的にはグループ側で汎用的なラベルを設定して、プロジェクト固有のメタ情報としてプロジェクト名の省略形(例:Enigmo Greatest ProjectEGP)や、リリースバージョン(例:v1.4.3)などをプロジェクトラベルで定義するというのがベターな運用方法だと思われます。

グループラベルを設定しよう

ところがこのグループラベル、エニグモではあまり認識されていなかったため

  1. 各プロジェクトで汎用的な名前のプロジェクトラベルを個別に設定
  2. プロジェクトラベルを使ってIssueやMRを管理
  3. プロジェクトごとに同じラベルを定義するのが手間だったので、プロジェクトラベルと同じ名前のグループラベルを設定

という流れで最近になってようやくグループラベルが設定されました。各プロジェクトは個別にラベルを定義する必要がなくなってめでたしめでたしかと思いきや、そうではありません。さきほどのフローに妙なところがありませんでしたか?

プロジェクトラベルと同じ名前のグループラベルを設定

ここです。同じ名前のラベルを設定しましたね。グループラベルとプロジェクトラベルは別のオブジェクトとして扱われるため、同じ名前のラベルが設定できます。設定できるのは問題ないのですが、いざ使ってみようとすると

f:id:enigmo7:20200522105830p:plain

こんな感じでまったく区別のつかないラベルがラベル付与の候補として表示されるようになってしまいました。どうしてくれるんだ。しかも厄介親切なことにこのラベル候補、グループラベルかプロジェクトラベルかという情報は表示されません。

重複したらどうする?

区別がつかなくても同じ意味合いだったら別にどっちでもいいじゃん、と思わないでもありませんが、ラベルを付与するたびに「なぜ2つあるのか?どちらを付与したらいいのか?表示のバグ?」とチラッと考える時間が無駄ですね。じゃあこの重複を解消しましょう、と迂闊に既存のプロジェクトラベルを削除してしまうと、これまで該当のラベルを付与していたIssueやMRからラベルが削除されてしまいます。

仮にreview requestedなどのアクションが必要なラベルの場合、削除によって対応が漏れてしまうおそれがあります。この事象に対して、GitLab.orgのIssueで対応方法が提案されていました。

  1. 重複しているプロジェクトラベルかグループラベルをリネームする
  2. プロジェクトラベルが付与されたIssueやMRに、グループラベルを追加する
  3. プロジェクトラベルを削除する

たとえばin reviewという名前のプロジェクトラベルとグループラベルが設定されている状態では、以下のような対応になります。

  1. プロジェクトラベル:in reviewin review(project)へリネーム
  2. in review(project)が付与されたIssueやMRに、グループラベル:in reviewを付与
  3. プロジェクトラベル:in review(project)を削除

リネームと削除はグループ設定画面やプロジェクト設定画面から容易に対応できますが、活発に開発が行われているプロジェクトにおいて、Issue一覧やMR一覧で重複しているラベルが付与されているものを探してIssueやMRの編集画面でラベルを設定する、という流れを1つ1つ対応するのはそれこそ時間の無駄です。

APIを使ったラベルの修正

幸い、GitLabではプロジェクトラベルやグループラベル、MRを操作するAPIが提供されています。

これらのAPIを利用して以下のようなスクリプトを作成しました。

#!/bin/bash
# require
# - httpie
# - jq
# - GitLab Administrator Role & User Token 

TOKEN=************
total_pages=$(http --ignore-stdin 'https://gitlab.example.com/api/v4/groups/1/merge_requests?labels='"review requested(project)"'&per_page=100' Private-Token:$TOKEN --verbose | grep X-Total-Pages | awk {'print $2'} | sed -e 's/
//g')
for page in $(seq 1 ${total_pages})
do
   http --body --ignore-stdin \
   'https://gitlab.example.com/api/v4/groups/1/merge_requests?labels='"review requested(project)"'&per_page=100&page='${page}'' \
   Private-Token:$TOKEN | jq '.[]|{ id: .id, iid: .iid, project_id: .project_id, labels: .labels}'
done  > request.json

jq -c '.' request.json | while read mr
do
  id=$(echo ${mr} | jq '.id')
  iid=$(echo ${mr} | jq '.iid')
  pid=$(echo ${mr} | jq '.project_id')
  labels=$(echo ${mr} | jq '.labels|join(",")')
  replaced_labels=$(echo ${labels} | jq -r 'sub("review requested\\(project\\)";"review requested")')
  http --body --ignore-stdin \
      PUT 'https://gitlab.example.com/api/v4/projects/'${pid}'/merge_requests/'${iid}'?labels='"${replaced_labels}"'' \
      Private-Token:$TOKEN
  sleep 5
done

今回は重複しているラベルが少なかったため、ラベル名は引数ではなく直接定義してしまっています。大雑把には以下のようなフローです。

  1. 対象グループ内でリネーム後のプロジェクトラベルが付与されたMRの一覧(ラベル定義の変更に必要なメタ情報を含むJSON)を作成
  2. ラベル定義を修正したJSONを使って各MRの情報を更新
    • スクリプト内ではラベルの置換をしていますが、前述の対応方法に記載されているようにプロジェクトラベルを削除することで更新されるため、置換ではなく単純な追加でもOKです

各プロジェクトのラベル一覧を確認して重複しているラベルがあったらスクリプトを適宜修正して実行、という対応で重複を解消しました。

すべてのグループやプロジェクトに対してラベル重複のチェックをして解消したい場合は、以下のような各言語向けのモジュールを使ったスクリプトを作成するのも良いかもしれません。

結論

  • 汎用的なラベルはグループラベルに定義すること
  • 既存のラベルと同名のラベルを適当に作らない
  • 実際にラベルを使う場面をちゃんと考えましょう

株式会社エニグモ 正社員の求人一覧 hrmos.co

CA × atmaCupに参加しました

はじめに

こんにちは、初投稿になります。
今年の1月からエニグモでデータサイエンティストをしている堀部と申します。

1/25(土)に行われたCA × atmaCup というオフラインのデータコンペティションのイベントに参加しました。

【東京・大阪同時開催】CA × atmaCup - connpass

85チーム中、Public 12th/Private 5th*1とKaggle Expertとしてはまさかの最上位という結果でした。

コンペ前、コンペ中、コンペ後に分けて振り返ります。

※本記事ではコンペのデータやタスクについては情報公開が難しいため触れません。

コンペ前

コード整理

以前のコンペや業務で使っていたコードをなるべくクラス・メソッド化してgitにまとめて整理しました。綺麗なコードとは言えないですがまとめておいたおかげで、新しい特徴量の作成やタスクに特化したデータの前処理に時間を割くことができました。主に汎用的な特徴量生成の処理やGBDTモデルの実験をやりやすくする下記のようなコードをまとめていました。

  • EDA

  • 特徴量生成

    • 1種類しかないカラムを削除
    • 集約特徴量の生成(mean, median, max, min, std)
    • label encording
    • count encording
    • target encording
  • 学習(モデル)

    • ベース:lightgbm 5-fold
    • オプション:random seed averageやlightgbm tunerをオンオフできるように追加

コンペ中

素敵な環境でした

サイバーエージェントさんのできたてほやほやのオフィスのスクランブル交差点の見える席でもくもくと作業しました。頭を使いすぎて最後2時間くらいは少し頭がぼーっとしてました。 f:id:enigmo7:20200203165320j:plain

コンペティションサイトの出来が素晴らしかったです。○aggleと違ってすいすいsubmitができストレスなく作業に集中することができました。

コンペ中の作業方針

  1. 必要最低限の特徴量でベースライン作成してsubmit
  2. EDAやfeature importanceを見て特徴量追加
  3. CVもpublic LBも伸びたら採用
  4. ひたすら、2,3を繰り返す

モデルはずっとlightgbmシングルでアンサンブルはしませんでした。lightgbmのハイパーパラメータはcat_smoothのみ手動チューニングしました。
そして、特徴量のアイディアが一旦つきたところで lightgbm tunerを使って一度パラメータ探索をした結果を最後まで使いました。

コンペ後

表彰式、懇親会

コンペが終わってすぐ結果発表&表彰式がありました。上位3名の方の解法を聞くことができました。 その特徴量効きましたよねと共感したり、そのアイディアは思いつかなかったなとメモしたりすぐに情報共有できるオフラインコンペならではのよさを実感しました。

その後の懇親会でも当日のコンペだけでなく別のコンペについての取り組みについても話を聞くことができ、普段からコンペに参加しておくメリットも感じました。

次の日

次の日は日曜日だったので表彰式や懇親会での話を受けて思いついたアイディアを実装して追試をしていました。少し考えればこの特徴量は要らないかもと思ったものを削除しただけで、スコアが伸びたりとなぜコンペ中に気がつかなかったのかと後悔もありました。

また、上位の方が公開してくれたコードやgitを見て自分のコードの汚さに愕然としました。
普段から綺麗なコードを書く、他の人のコードを見て学ぶということを日頃から意識しようと胸に刻み込みました。

最後に

(真剣に取り組んだ)コンペの数だけ強くなる、強い人に会いに行くという大切さ、オフラインコンペならではの大変さ、楽しさを味わうことができたとても充実した一日でした。次回があればまたぜひ参加したいです。

また、エニグモ に入社して1ヶ月が経ちましたが楽しい日々を過ごしています。ABテストの効果検証×傾向スコア、商品のクラスタリング、回帰予測モデリングなど、自分で思いついてビジネスに貢献できそうなものであれば自由に取り組んでよいボトムアップの環境です。

個人的には、

  • ファッションEC × CtoCというドメインならでは多様性のあるデータ(テーブル、テキスト、画像)が扱えること
  • 社内の半数以上の方がSQLをかけデータをビジネスに活用する文化が定着していること
  • BigQuery, AWS, Lookerなど、ツールへの投資が当たり前のように行われていること

によさを感じています。

コンペ以上に業務も楽しく取り組める強いチームをつくれたらと思っております。興味のある方はぜひ気軽にご応募ください。選考とは別にカジュアル面談も受け付けております。データサイエンティスト、データアナリスト、データエンジニア、検索エンジニアなど各種募集中です。

株式会社エニグモ 正社員の求人一覧 hrmos.co

*1:ランキングシステムがPublicとPrivate で分かれていて、コンペティションが終了するまではテストデータの一部だけを使ってスコアを算出されたPublicのみのランキングが公開されます

BUYMAの検索システムを刷新したお話

こんにちは。主にBUYMAの検索周りを担当しているエンジニアの伊藤です。

BUYMAではSolrを利用した検索システムがいくつかあります。
BUYMAの検索というと検索ボリュームが一番大きな商品検索を想像されると思いますが、
今回はデータボリュームが一番大きい検索システムをターゲットとして、インフラ周りを含め全面的にシステムの刷新を行いました。

ここでは、

  • 既存の検索システムがどういったものだったのか
  • なぜシステム更改が必要だったのか(どういう課題があったのか)
  • 更改後の検索システムはどういったものか
  • 今後の課題について

等々についてご紹介したいと思います。

既存の検索システムについて

既存の検索システムは下記の通り、シンプルという点ではとても素晴らしいものでした。

f:id:pma1013:20200203151456p:plain

ただし下記のような問題を抱えている状況でした。

  • スケールアウトしない構成である
  • スケールアップの限界
  • Solrのバージョンが古い
  • 本番環境のデータを利用した検証が難しい
  • 開発担当者にもSolrの知識が必要とされる
  • 問題に気付けない

以降でその内容について補足していきます。

スケールアウトしない構成である

  • 検索システムはデータ増とアクセス増の2軸でスケールアウト構成を取る必要があります。
  • アクセス増にはSolrサーバを追加することで対応できるようにはなっていましたが、該当の検索システムはアクセス数というよりデータが多いことが特徴でこのデータ増に追従出来なくなっていました。

スケールアップの限界

  • 該当の検索システムは元々オンプレ環境で運用していましたが、ヒープサイズ不足やFull GCが頻発するようになっていたため、暫定対処としてAWS側に移行し、GCチューニングを行いました。
  • ただしこの対応も一時的なもので、データ数自体は日々増加している状況の中で使用しているGCアルゴリズム的に、メモリを増やしてどうこうできる状況ではなくなっていました。
    • データ増に伴いOOM Killer、ヒープサイズ不足が発生 → ヒープサイズを拡張 → STWのインパクトが大きくなるという負のループに陥る

Solrのバージョンが古い

  • 既存の検索システムで利用しているSolrのバージョンは3.2.0でした
  • バージョンが古くても通常時の運用にはそれほど支障はありませんが、何か問題があった場合の調査が大変でした(ドキュメントが見つからない)
  • またSolrのバージョンupに伴いindexing/検索性能はupしていますので、性能面でのデメリットであったり
  • 以降のバージョンで提供された様々な機能が利用できない等のデメリットがありました

本番環境のデータを利用した検証が難しい

  • 既存システムで本番環境相当のデータで検証する際にはindexing処理だけで数日かかるという状況で、環境構築自体がハードルとなっていました。

開発担当者にもSolrの知識が必要とされる

  • Solrへの検索時はphprubyといったクライアント側でSolrのクエリを組み立てて実行していました。
  • クライアント側を担当する開発担当者はその時々で変わり、ある程度はSolrを知っている人もいれば、全く知らない人まで様々です。
  • 一方Solrのクエリは書き方によってはキャッシュを使えていなかったり、または逆にキャッシュを無駄に汚してしまったりと、同じ検索結果を得るにしてもある程度Solrの知識を必要とします。

問題に気付けない

  • 必要なデータやログが適切に可視化され監視されていないため、サービス影響、ユーザ問い合わせがあって初めて問題に気付くケースがありました

更改後の検索システム

上記で挙げた課題感を解決するために設計したアーキテクチャが下記になります。

f:id:pma1013:20200203172549p:plain

  • 変化に強いシステムへ

    • SolrCloud構成に変更しつつ、データ増にはデータsharding、アクセス増にはデータreplicationでスケールアウト可能な構成に変更
  • 環境再現性

    • 全てコンテナベースのアプリケーションとなっているため、本番と同じマシンスペック、構成を簡単に構築可能
    • 本番データを利用した検証も短時間で可能となった
    • indexing処理についてもBUYMAで利用しているメインのDBにアクセスする必要がなく、中間DBを利用することで数時間でfull-import可能
  • 耐障害性の向上

    • プラットフォームにKubernetesを採用し、想定外のアプリケーション停止、ノードdown時にもセルフヒーリングで自動復旧可能
  • マイクロサービス化(隠蔽化)

    • アプリケーション〜Solr間に検索APIを新たに用意。これによりアプリケーション側はSolrの独自クエリを意識することなく、検索APIを介したシンプルなI/Fをベースとした開発が可能に。
    • Solrの独自クエリなど、専門的な知識を開発者が持つ必要がなくなり、学習コストが抑えられることで開発効率が上がる
    • 不適切なクエリにより、Solr側のキャッシュをうまく使えないなどの問題回避
  • 障害検知

    • 監視、ログ運用基盤としてDatadogを利用し、インフラ/ミドル/アプリケーションのメトリクス情報やログを統合的に管理可能とした
  • 属人性の排除

    • 検索システム間でバラバラだったスキーマ定義を汎用的なものにし、複数の検索システムをシームレスに対応可能に
    • dynamicフィールドをベースとしているため、スキーマ定義自体も運用上ほぼ変更する必要がない
  • GitOps対応

    • 全てのシステム設定をコードとしてGit上で管理
    • 運用上変更頻度が高いものはコマンド実行不要でCI/CDで可能

苦労した点

今回せっかくシステム更改するならCloudNativeなシステムにしたいという思いがありこのような構成にしました。
SolrのようなstatefulなアプリケーションをコンテナとしてKubernetes上で扱うのも初めてでしたし、 監視、ログ運用周りも今回の対応と合わせて刷新したことで対応範囲が広くなり苦労した点も多くありました。
ここではいくつかピックアップして紹介したいと思います。

  • Solr/ZookeeperをKubernetes上に構築、運用した経験がない

    • Solrに関してはあまり構築事例もなく問題に遭遇した際の解析に難航
    • リソース設計、ログ周りなど、コンテナ/Kubernetesだからこそプラスαで考慮しなければ行けない点が多々あった
  • 監視、ログ運用基盤の検討

    • コンテナ/Kubernetesベースのシステムをどう監視すべきか?
    • ログはどう扱うべきか?
  • 検索APIの設計、開発

    • I/F仕様どうするか?
    • 開発しながらSolr/Zookeeper周りの設定や問題対応をするのが辛い
  • Solrバージョンアップによる未知の問題対応

    • indexing処理周りで問題多発
    • SolrCloudかつDIHで並列indexing処理を行うこと自体が事例がなく、色々とはまる

今後に向けて

システム更改により当初挙げていた課題感というのは概ね解決することが出来ました。
ただし今回のようなシステムを構築、運用したことでてきた新たな課題や、まだまだ改善が必要だなと思えるところもあります。

  • indexing処理などはクライアント側の処理と密になっている箇所がまだまだあり、今後もブラッシュアップが必要
  • Solrのような複雑かつstatefulなアプリケーションは運用がやはり大変。Kubernetes operatorを利用するなどして運用をもっと楽にしつつ、属人性もなくしていきたい。

さいごに

今回は検索のインフラ面を中心としたお話を紹介させていただきましたが、 弊社では検索のサービス向上(ex パーソナライズサーチなど)や自然言語処理機械学習を活用したサービス導入なども積極的に行っています。
今回技術的なところにはほぼ触れませんでしたが、ここどうなってるの?など少しでも興味、関心を持たれたら是非お気軽にお話だけでも聞きにいただければと思います。

株式会社エニグモ 正社員の求人一覧 hrmos.co

データサイエンティストとしてアウトプットを改善するために必要な4つの力

はじめに

エニグモでデータサイエンティストを名乗っている庄子です。こちらは Enigmo Advent Calendar 2019 の25日目の記事です。 今年の振り返りも兼ねてのポエムとなります。

さて、データサイエンティストが活躍するためのスキル要件として、いくらでも切りようがあると思いますが、特に自分自身に感じている課題について、4つの力という観点で書きたいと思います。

その1 提案力

  • PoCとして小規模のデモを行う
    • そのデータサイエンスのアウトプットが使えそうか、事業に詳しい人に想像してもらう

実際にデータサイエンスを使って問題解決できそうな場合も、実際にやってみないと分からないですし、得られたアウトプットが事業に有効かどうかを、事業に詳しい人に意見をいただいた方が良いでしょう。筋が悪そうな分析は早めに判断してもらうためにも、なるべく小規模でPoCを行います。 本年度の振り返りとしては、このPoCの手数がもっとあった方が良いと感じました。

また、データサイエンティストが使う手法でできることは、データサイエンティストがもっとも良く分かるはずです。もちろん、使われる手法に関して詳しい人がデータサイエンティスト以外のポジションを担っているケースもあると思いますが、そのケースはここでは考えないことにします。

なお、課題設定が済んでおり、入出力が決まっているテーブルデータに対しては、AutoMLを十分ですし、AutoMLに変えられるようなタスクをこなすだけであれば、データサイエンティストは価値を発揮できません。 課題設定と分析を繰り返し、仮説検証を繰り返しながら課題設定の質を上げるスキルこそがデータサイエンティストの価値を差別化すると思います。

  • 提案を誤解なく伝えるために、共通言語を関係者と揃える
    • 使う手法や方法論を伝える概念を伝える
    • 伝えたことをドキュメントとして残し、説明の場にいなくてもそのドキュメントを読めば共通言語が理解できるようにする
    • 関係者が運用している具体的なデータを使って示す

共通言語を揃える場合は、最初に自分が受ける説明として、こんな説明ならすっと理解できそうというのを思い出しながら、説明するということは普段気をつけているつもりでしたが、後から考えると考慮が不十分だと思うことは多々ありました。特に、背景や経緯を共有できている前提から資料を作ってしまう場合です。 分析レポートの報告の際に、なるべく普段気をつけていたはずだと思いますが、ドキュメントの作成や整備も、振り返るともっとやりようがあると思います。 質問された点について補足を付け加えていくなどして、社内のナレッジの質を高め、リテラシーを共有できるのかと思います。

その2 ヒアリング力

  • 定期的に情報交換の場を現場のメンバーと設ける

こちらの取り組みを参考にし、ざっくばらんにデータ活用で解決してほしい課題について話すというランチミーティングを設定しました。

データ民主化を加速させる「分析ワクワクタイム」 - pixiv inside

このランチミーティングをきっかけにとあるPoCに取り組みましたが、中途半端なところで頓挫してしまっている状況です。 さらに、定期的にということも実現できていません。やったら効果的かもしれないと思うことをすぐに実現できず、せっかくヒアリングしたのに形にできないということに負い目を感じてしまった部分もあります。

いずれにせよ、定期的にコミュニケーションを行うことで、風通しをよくする、心理的安全性を担保することが重要だったりするので、またどこかの機会で復活させていきたいと思います。

  • 現場での運用について体験させてもらう

今年は取り組めなかったですが、ビジネス理解をもっとも得られる方法が実際に体験することにあると思います。データサイエンティストが共通言語の理解を得にいくということで矢印の向きは反対になりますが、先に挙げた共通言語を揃えるということにもつながると思います。

その3 タスク依頼力

  • 得意な領域に専念し、タスクを切り出してより得意な人に任せることを考える
    • 実験的なコードを書くことに場合に専念する
    • 仕様が固まる、あるいはプロダクトに関わる部分はエンジニアに任せる

プロダクトに乗るべきコードの要件はここで詳しく触れませんが、手元で自分が扱うコードが読みやすく、条件や機能の拡張がしやすいものだったら良いなと何度も思いました。そのようなコーディングを行うためには言語やフレームワークのベストプラクティスを踏まえている、専門家に任せた方がよいです。

データサイエンスに関するプロジェクトを実行するにあたり、必要なスキルで全てに秀でるのは多くの人にとって現実的ではないでしょう。依頼をする内容を、その領域を詳しい人へ誤解なく橋渡しができるくらいの知識があるという前提は置きますが、なるべく、得意な領域に専念した方が、組織としてのアウトプット力は上げられるはずです。

個人の領域として広くやれるのが弊社の良いところでもあるのですが、実験のためのコードを書く時間の割合を多くすることが、現在ネックになっていると思いました。

  • タスクを分解する
    • 分解した単位で、インプットとアウトプットを明確にする

こうやって書くと、基本的な仕事の進め方の話になりような気がします。。達成基準が明確な、細切れなタスクに分解できるということは、仕事の依頼もしやすくなり、今後育成という観点でも必要になってくる力です。

その4 採用力

  • 来て欲しい人に、その会社に来る魅力をきっちり伝える
    • 具体的なタスクや、データサイエンティストの要件を上手く伝える

人的リソースを増やすために、データサイエンティスト自体の人員を増やすということも当然選択肢に入ると思います。今年度は、データサイエンティスト、および、データアナリストの採用にも、面接などを通し関わらせていただきました。

もちろん活躍できそうな人を採用することが目的になりますが、活躍を期待できる人材ほど、他社からも内定が出ることは容易に想像できます。給与といった待遇面以外で考えるとすると、仕事内容やその会社で働くことの魅力を伝えるかどうかにかかっていると思います。

そこで、ミスマッチをなくすということに務めてきました。課題と思っているとこと、なるべく包み隠さず伝えたということはできていたと思います。実際に業務を行うイメージを固めるために、面接官以外のメンバーとの面談の場を設けることも実現することができました。

  • 応募者の良いところを引き出して聞き出す

会社のフェーズを考えると、データサイエンスに関する施策をドライブしてくれる人が活躍できそうという思いがあったため、提案力に優れている人を通す傾向が強かったですが、応募要件を上げてしまう大きな要因となっていたような気がします。

今後は、始めは提案が少々不得意でも、技術力を活かして活躍できる人も採用したいという想いがあります。課題はたくさんある中で、その人の経験と相性が良さそうなタスクの質問をして、考えを掘り下げる、という質問の組み立てについても、改善していきたいと思います。

一方、できていた部分としては、データサイエンティストの業務経験が想定より不足していても、社内のメンバーとコミュニーケーションが安心して任せられ、学習やそれまでの業務への取り組みを伺い、間違いなく必要なスキルはキャッチアップできると判断できる方は面接を通していました。このケースでは応募者の良いところを上手く引き出せていたのではないかと思います。

さいごに

その1,2がコミュケーションに関する話題、その3,4が人的リソースに関する話題になります。大きな枠組の話題としては、如何にスキルや知識をアップデートするか、という日々のインプット・アウトプットも挙げられますが、また機会があれば書くかも、、しれません。

なお、今回できていないことを中心に書いてしまったせいか、ちょっと胃もたれしそうな気分になりました。ただし、やりたいのにやれてないことが多いということは、伸び代がすごい!とも言えるのかと思います。一つ一つやるべきことに取り組んでいくしかしないですね! こんな私でも暖かく受け入れてくださり、(きっと)裁量を最大限に与えてくれる弊社なので、共に切磋琢磨してEnigmoをグロースさせたい仲間を絶賛募集中です。

株式会社エニグモ 正社員の求人一覧

hrmos.co