エンジニアインタビュー 第1回 齊藤さん編

エニグモBUYMA の中のひとを知ってもらおうと、エンジニアへのインタビューをしてみました。
第1回は、2011年3月入社の齊藤さんです。

インタビュアー
小澤:2011年4月入社。部長。
伊藤:2018年5月入社。新卒2年目。

f:id:enigmo777:20200415194907j:plain

エニグモに入社した理由・動機

伊藤: エニグモに入社したのはなぜですか?

齊藤: 自社サービスがいいなと思って会社を探していました。
盛り上がっていたのでゲーム会社も面接に行ったのですが、すごい機械的で、MySQL 運用したことありますか、とか、そういう質問ばかりで。
エニグモは(前)部長とエンジニアの人と面接して、自分のできることに興味を持ってもらって、最終含めて3回面接しました。
EC に興味があったのと、どうしようかと思っているところで Stylist というサービスを公開しました、というメールがきたので、面白そうだなと思い入社を決めました。
残念ながら Stylist は今はクローズしていますけど。

小澤: エニグモの前はイギリスですよね。

齊藤: もうやめて来ていました。
前の会社は受託で、スクラッチ&ビルドみたいなことを何回もやるんで毎回工夫できて面白かったんですが、自社でやっているサービスも見ていたのでソッチのほうが面白そうだなと思っていました。

現在担当している業務は

伊藤: 最近はどんな業務をされていますか?

齊藤: 4年前ぐらいにユニット化されてからは、自分たちでこれやったら良さそう、変えたほうが良さそう、面白そうだなって思うアイデアを提案してやっています。
自分で発案したものもありますし、浮いていて面白そうだなってのを拾ったりしてやってます。
その前はトップレベル会議みたいなのがあって、大きなテーマのものは誰がやるかみたいなのが決まっていました。

小澤: この3年ぐらい、主にパーソナルショッパー向けの機能の開発をしていますよね。

齊藤: そうですね、それが僕の担当しているロールっぽくて、

小澤・伊藤: ぽくて (笑)

伊藤: ぽくてって認識なんですね。

齊藤: お問い合わせリニューアルぐらいからそうですね。
お問い合わせ機能が、データベースの設計から見た目までひどかったんですよ。でも、それまでは機能しているものをあまり見直さなかったんですよね。
でもあれは、なんで変えていいってなったんですかね?

小澤: 3年ぐらい言い続けたからじゃないですかね。
お問い合わせでなにかしたいという要望はあったんですが、お問い合わせは触っちゃだめだってエンジニアはみんな思ってたんですよね。

齊藤: 改修内容が大きすぎるから触れなかったんですかね。データベースから見た目まで全部やりたくなっちゃうから。。 結局そのときは全部やり直しましたね。
初めてメイン以外のデータベースの導入を決めて、データベースを設計して、既存データの移行を考えて。 UI はそのとき React が盛り上がっていたので、やったことはなかったけどやるでしょってなって、Redux の設計も勉強して導入しました。

伊藤: どのぐらいかかったんですか?

齊藤: 最初は3ヶ月ぐらいかと思ってましたが、半年ぐらいかかりました。

小澤: 当初計画の3ヶ月ってのは、もう長いからそれ以上考えられないっていう、漠然とした3ヶ月です。

齊藤: それまで3ヶ月もかかるのはなかったですからね。大体長くて1ヶ月みたいなものが多かったですね。 性能検証もあとから追加したり、見積もりが随時変わっていったっていうのも理由としてありますね。
それからこのとき山本さんが入社して1ヶ月ぐらいでプロジェクトに参加して、1ヶ月ぐらいですでに何ヶ月も一緒にやっているような存在感で、インクリメンタルな実装を相互にレビュー・マージしていく作業フローもすぐにスムースにこなしていて驚きました。
そのプロジェクトのあとは、商品画像の差し替え、、、画像枚数からルールに従って URL を生成する処理になっていたので、画像が並べ替えられなかったんですよね。ショッパーや社内からも画像を変更したり並び替えたいという要望はずっとあったんですが、それも手を入れるのが大変だからってやってなかったんですよ。
ちょっとした改修では済まないものをそこからやるようになりました(笑)。
これも半年ぐらいかかりました。 管理画面(BUYMA 本体とは別の Java の Web アプリ)をいじらずに管理画面を改修するのもこの頃からやってます(笑)。

小澤: それもお問い合せ改修からですかね。

齊藤: そうですね、管理画面の変更(Java)がめんどくさかったんで。
画像の差し替えは半年メインラインと並走して開発したのでリリースでたくさんしくじりましたね。
今みたいに Git じゃなくて SVN だったという要因もあったり、商品画像はサイトのいろいろなところに出ているので色んな人が修正するんですよね。それでリリースマージが難しくなってしまって。。
お問い合わせ改修も半年かかったんですが、色んな所に表示される機能ではないので影響が小さかったんです。
余裕持ってやるつもりだったんですが、マージに労力を取られすぎて、マージ終わったらもうメンテじゃんていう感じで出してしまいました。
そのときはメンテ明けは普段は朝に帰るんですが、24時間ぐらい会社にいました。

小澤: その後にフィーチャーフラグとか、どんどん出していくように実装をしましたよね。

齊藤: そうですね。
その後はCSVでの一括出品機能でした。機能としてはあったんですが、100品しか更新できない、下書きにしかならない、変更できない項目があるとか、使いにくいところがいっぱいあったんですよ。
1万件を上限にしたので、一つのバグでショッパーさんの全商品が壊れてしまうようなリスクがありました。
これはテストを入念にしたので時間がかかりましたね。
大変でしたけど、商品数の多いショッパーさんにすごく使われているので良かったです。

伊藤: 直近は何をされていますか?

齊藤: 直近はとある機能をやっているんですが、これまで BUYMAモノリスなアプリなので改修自体が必要以上にめんどくさいなと感じていて、良い機会なのでマイクロサービスな設計で作ろうと思っています。 Kubernetes とか使ってインフラのメンバーにも協力頂いて進めたいです。

エニグモに入社してからの一番の思い出

伊藤: 入社してからの一番の思い出ってなんですか?社員旅行でハワイに行ったりしてますよね?

齊藤: 一番か、難しいですね。。。。ハワイも思い出ですけど、 僕はメンテナンスが好きで、

小澤・伊藤: え、そうなんですか!

齊藤: メンテナンスでリリースするのって、サービスをコントロールしている実感が強いじゃないですか。
深夜にサービスを止めて、ソースコードをリリースして、明け方徐々に使われだしていくその現場にいる感じが好きですね。
最近はリリースでサービスを止めるような機会は減ったのであまりないですけど。

伊藤: 一番の思い出はメンテナンス。

齊藤: 長期間開発してリリースしたメンテナンスは印象にとても残ってます。
頻繁にできる仕事ではないですけど、その分区切りにもなるし、達成感になりますね。

どういう人と働きたいですか

伊藤: これから、どういう人に来てほしいですか。どういう人と働きたいですか。

齊藤: アイディアがある人が良いですね。自分だったらこう変えるとか、これは良くないとか、自分の意見が言える人がいいですね。
あとは、人の変更見て、塩梅を汲み取って柔軟に実装できる人がいいですね。
例えば「そんなに作り込まなくてもいいです」っていう感覚が分かる人。

伊藤: 一気にハードル上がりますね。

齊藤: 思っている塩梅で、書けてないというか、「工数削るためにユニットテスト書きませんでした」って来られると、そうじゃないよなと思いますし。

小澤: そうですね。

齊藤: チームで上手に動ける人がいいですね。不必要に足引っ張るようなレビューコメントで全体のリズムが悪くなることもあるので。
作業分担してても自分事になっている人がいいですね。
僕は年長者ですけど、経験者とばかり働きたいわけじゃないんですよ。
人のコードや動きを見て、良いと思うとか、これはこうじゃないですかってはっきり言える人がいいですね。

伊藤: 初心者とまではいかないですけど、あまり経験がなくてもいいと。

齊藤: そうですね。センスが良ければ関係ないと思います。

これまでにした一番大きなミス

伊藤: これまでにした一番大きなミスってなんですか?

齊藤: それは、画像差し替えプロジェクトのメンテナンス開けでバグがいっぱい出たときですね。

小澤: げんなりしたっていう。

齊藤: こんなに考慮漏れができるのかって思いましたね。
まあ、障害がでるとチーム感が出るというか、協力者が出てきてものすごいスピード感で解消していく過程はそれで楽しいですけどね。

小澤: すぐ直せっていうバグ修正はアドレナリンがでて楽しいですよね。

今後

小澤: 20年ぐらいプログラマーやっていて飽きないですか?

齊藤: 飽きないですね。

小澤: 次から次へあたらしい技術やアイディアが出てきてすごいなと思うんですよ。

齊藤: そうっすね。楽しい仕事です。

伊藤: ライバルはいるんですか?

齊藤: ライバル意識することはないですけど、、、、。 影響を受けるメンバーはいます。
小澤さんは調べるのはやいなと。バグがあったら「そこじゃない?」って速効性があってミニマムな修正を思いつくのが早いですし。

小澤: おぉぉ(笑)

齊藤: 浅香さんは作業の精度がずっと安定していてレスポンスも早いですよね。インフラ面から全体を見られていますし。 メンテナンスのバグ対応でもたくさん助けていただきました。
大川さんは無駄に作らないでツールがあるじゃんていって、新しいツールを使いこなすのも早いですし、考え方がスマートですね。真似できない。
木村さんも勉強熱心で、時代にそって変えて行くべきことを実行してますよね。最近マネージメントよりですけど。
皆さんとても良い刺激になります。

伊藤: みんな最近マネージメントよりな印象ですけど。
マネージメントには興味ないですか?

齊藤: 僕はミーティングがいっぱい入ってくると違うなって思ってしまいます。
リーダーシップはとりたいとは思いますけど、自分も動きたいですね。指示を出すようなロールではなくてメンバーでいたいです。
もっと上手な人が設計や案を出せばそれを実装したいってなると思います。
マネージメントするよりも、足を引っ張るようになるまでは開発を続けていきたいですね。

伊藤: オープンソースに貢献するのは興味ないんですか?

齊藤: そうですね、フォーカスしてやってみたことはないですね。
Rails とか開発しているのは楽しそうですけど、、ユーザーフェイシングな開発している方が面白いと思います。
あとは BUYMA ってレガシーなところがいっぱいあるから、新しいものに変えたいですね。

小澤: アイディアはいっぱい出てきますよね。

齊藤: 悔しいですけど「あれ、C社はできているのにうちはできていないなって」思うところがいろいろあって、そういう負債が消えていってほしいと思ってます(笑)。

若手になにかありますか

伊藤: 若手になにか思うことはありますか?

齊藤: 遠慮しないほうがいいと思います。なにか思うことがあったら提案しておいて、すぐにはできないことも多いですが提案すればだいたい自分がやることになるんで。
あとは障害とかあったら参加してみるとか。オンタイムに障害を克服することが開発者としてサービスに近づく一歩のようなところもあると思います。
うちの人って調べたことのログ張ったりするじゃないですか。それってここまでやったってのもあるし、他の人にもここ見ればいいって伝えたことになってて。

伊藤: 次同じことがあったらそれを見ればいいと。

齊藤: 思い出したらそれを真似してみれば良いんですよ。
昔はそうでした。人も少なかったんで誰もそんな親切には教えてくれなくて。見てればわかるっしょって感じでした。

小澤: 怖い会社ですね。

齊藤: はいったときからそうでした。 (※今も昔も聞けばやさしく答えてくれる優しい人ばかりです)

小澤: 齊藤さんのはじめのころのエピソードで面白かったのは、明日やろうと思ってたものが起きたらできていたって言う話。

伊藤: なんすかそれは。

齊藤: はじめのプロジェクトが二人でこんなサービスを作ってみてっていうのだったんですよ。
その人はやりましたとか言わないでしれっとプッシュしてありました。

伊藤: それは齊藤さんに割り当てられたタスクだったんですか?

齊藤: 今みたいに計画してやっていく感じじゃなくて、ざっくりしてたんですよ。
もうひとりの人は誰に頼らなくても一人でできちゃう人なんで、ついでにやっておきましたという感じです。
それで、やんなかったら全部作られちゃうなと思いました。

伊藤: そんなこともあったんですね。

齊藤: そうですね。それで折れてやめたいとは思いませんでしたが、頑張んなきゃなと思いました。

ちなみに

齊藤: 僕が一番目に指名されたのは(年長者なので)気を使ってですか?

伊藤: そうじゃないです。

小澤: そうじゃないですね(笑)。 誰に聞いてみたいって聞いたら、真っ先に齊藤さんが出てきました。

Enigmo 開発合宿2019 in 湯河原

こんにちは。気が付けば入社から一年が経ち、 新卒の肩書きを失った@sean0628_i です。

4月4日(木)、4月5日(金)の日程で開発合宿を行ってきました。 場所は前回と同じく、おんやど恵さんにお邪魔しました。

前回の開発合宿が2017年だったようなので、2年ぶりの開催ですね。

テーマ

今回は『チーム力のアップ』をテーマに設定しました。

前回は個人個人好きなことを行うスタイルだったようですが、 今回はテーマが『チーム力のアップ』でしたので、基本的にはチーム開発で取り組むことにしました。

参加者の希望を聞き入れつつ、実行委員が1-3人のチームに分けました。 そして、チームごと取り組む内容を決定し、合宿に臨みました。 合宿一ヶ月ほど前にチームを発表し、準備期間も設けました。

スケジュール感:

  • 3月初 - チーム発表
  • 3月中 - 内容決定・下準備
  • 4月4日、5日 - 合宿開催

合宿でやったこと

内容に関しては、業務に関する範囲であれば基本的になんでもOK です。 最終的にそれぞれ以下の内容に取り組んでいました。

内容:

  • 1班:STYLE HAUS フロントの性能改善(画像リサイズ)
  • 2班:BUYMA フロントの性能改善
  • 3班:商品画像分類
  • 4班:STYLE HAUS タグのサジェスト
  • 5班:Jenkins のデプロイジョブのGitLab-CI 化
  • 6班:GitLab Runner Autoscale on AWS

当日の様子

東京駅出発

皆さん遅れてくるかなぁと思い15分前集合にしましたが、まさかの全員5分前行動。 出発の20分前には全員集まりました、、、さすがです!!!

開発開始

湯河原駅周辺で昼食をとって、開発開始です。 テーブルはチームごとです。

キーボード作成が趣味のメンバーは、自作キーボード持参で合宿に臨んでいました。

BUYMA パーカーを着て開発するメンバーも!

夕食

夜は宴会!!! テンションの上がったメンバーがコスプレをし、晩酌をしていると、、、 密告され、部長殿におこられてしまいました。。。

宴会の後は反省して、黙々と開発に励んでおりました。。。

記念撮影

宿の前でパシャり。 2日目はお昼まで開発を行い、湯河原駅周辺で昼食を食べ帰路につきました。

まとめ

当日は大きく成果を出せたチーム、あまり成果を出せなかったチームとありました。 ただ、事前準備の期間をおよそ1ヶ月用意したこともあり、どのチームも最低限の成果は出せていたように思います。

また、通常の業務を離れて普段あまり関わることのないメンバーと開発を行うことができて、 参加者それぞれ新たな気づきがあったことと思います。

『チーム力のアップ』という点で見ても、縦・横両方の意味で向上することができました。

私個人としても一日中シニアエンジニアの方に手取り足取り教えていただき、 Serverless、Docker などの知識を深めることができました。

またとない貴重な時間を過ごさせていただきました。

今後も積極的に社内勉強会、開発合宿を開催していきたいと思います。

最後まで読んでいただきありがとうございます。

iOSアプリのデザインをしてみて

はじめまして。BUYMAiOSアプリチームでデザインを担当しています。 この記事を読んでくださりありがとうございます。

2019年2月に、お問い合わせ機能をネイティブ化しました。 より使いやすくするために、Webviewからネイティブ化し、あわせてリデザインすることになりました。

Webとアプリを作業する上で、デザイナーとして苦労した部分を、新しいデザインと一緒に書いていきたいと思います。

 

まず、BUYMAiOSアプリってどんな感じ?

 

BUYMAはショッピングサービスなので必要なページがたくさん。

f:id:enigmo777:20200415195548j:plain

現状、アプリの半分くらいが、Webviewです。

ネイティブ化されたページとWebviewのページが混在しているため、ページによってデザインテイストが異なっていることを課題のひとつとして感じています。 ユーザーがアプリを起動してから目的を達成するまで、気持ちよく使えるよう統一されたデザインにしていきたいと考えています。

 

実際にデザインするときに考えていること2つ

 

1・デザインのトレンドを押さえたユーザーインターフェース

古っぽいデザインは、扱っているコンテンツさえ古く感じさせてしまうのでもったいないです。特にBUYMAでは、日本未入荷のレアアイテムを揃えていたり、最新のトレンドを発信しているサービスのため、サービスブランディングの観点からも、とても大事になってくるポイントだと考えています。

そのためまずはとにかく他社リサーチに時間をかけています。国内外の人気アプリのデザインをチェックしてよく使われているUIを参考にしたり、海外のデザインギャラリーを漁ってアイディアの引き出しを増やしています。

よく参考にしている海外デザインサイト

2・ユーザーが目的を達成するためのデザイン

トレンドだけ追いかけて「とりあえず流行りのデザインを取り入れたけど、実は使いにくかった」となっては本末転倒です。そのため、ユーザーが目的を達成しやすいデザインかどうか、という視点が重要になってきます。

そのページではユーザーに何を達成してほしいのかを明確にすること、そしてそれを達成するためには、ユーザーにどういうアクションをしてほしくて、きちんとアクションしやすいデザインになっているか、ということを考えながらデザインを行っています。

 

お問い合わせ画面の目的

 

BUYMAはCtoCサービスです。注文がはいるとパーソナルショッパーが買い付けに行き、商品を送ってくれるサービスです。 商品によって、配送日数が異なっていたり、買い付けに行ったけど在庫が無かったというケースが発生する場合があります。

もしユーザーがBUYMAを、在庫を持つ一般的なECサイトだと思って使っていた場合、「想定よりも配送日数が長かった」「注文したのにキャンセルされた」といった体験はユーザーのペインポイントになりかねません。

このペインポイントは注文前に商品について事前問い合わせをすることで解消できます。 お問い合わせ画面では、このようなペインポイントを解消することを目的とし、2点を達成することが必要だと考えました。

  1. BUYMAはCtoCサービスだと伝えられていること
  2. パーソナルショッパーへ在庫や商品詳細についてお問い合わせがしやすいデザインであること

 

現状のお問い合わせ画面の課題

 

それでは本当にCtoCサービスということが伝えられているのか、お問い合わせがしやすいデザインになっているのかということを念頭におき、現在のデザインから改善できるポイントがないかを考えていきます。

▼現状のデザイン

f:id:enigmo777:20200415195615j:plain

▼現状の課題

  • CtoCサービスということが伝えられているのか

→ 1 パーソナルショッパーへの問い合わせフォームだということが伝わりづらいため、CtoC感がなくハードルが高い印象を与えかねない。

  • お問い合わせがしやすいデザインになっているのか

→ 2 商品ページからお問い合わせボタンをもっとタップしてもらいたいので、現状よりもボタンに気づきやすくしたい。

→ 3 お問い合わせ一覧ページは、なんのアクションをしてほしいページなのか分かりづらい。

以上の課題に対してリデザインしていきます。

 

課題に対するアプローチ

 

▼改修後のデザイン

f:id:enigmo777:20200415195634j:plain

▼課題に対する変更点

1 ・CtoC感がなくハードルが高い印象を与える。

  • メッセンジャーアプリに寄せたUIで問い合わせのハードルを下げ、気軽さを出しました。チャット形式のUIは、サイトへの問い合わせではなく、パーソナルショッパーとの人対人のコミュニケーションであることを意識づけられたと思います。
  • パーソナルショッパーのアイコンをナビゲーションバーの右位置に表示し、常に目に入るようにして、パーソナルショッパーの存在感を出しました。アイコンをタップすると、パーソナルショッパーページや出品アイテム一覧を見ることができます。
  • 他人のお問い合わせ内容を見やすくしました。改修前はお問い合わせ内容がトグルに包まれて一文しか出ていなかったものを、全文出してひとめでわかるようにしました。他人のお問い合わせ内容が目に入ることで、BUYMAはCtoCサービスであり、在庫確認などの問い合わせが必要であることを伝えられたのではないかと考えています。

 

2 ・商品ページのお問い合わせボタンをもっとタップさせたい。

  • 商品ページのお問い合わせボタンの領域を広め、件数を表に出すことで、他の人の活発なお問い合わせのやりとりに気づきやすくなるようにしました。結果、問い合わせボタンのタップ数を130%増やすことができました。

 

3 ・お問い合わせ一覧ページは、なんのアクションをしてほしいページなのか分かりづらい。

  • 新規問い合わせボタンをアイコン化して視覚的に認知しやすいようにしました。また、スクロールしてもボタンを画面右下のポジションでフィックスさせることで、ユーザーがどのタイミングでも問い合わせフォームへ進めるようにしました。
  • 新規問い合わせボタンと同レベルで目立っていた「指名リクエスト(※)」のボタンの優先順位を下げて奥へ場所を変更しました。指名リクエストボタンの優先順位を下げたことで、クリック数は減りましたがリクエスト数に影響は無かったため、ページで誘導したいアクションをよりシンプルにできました。

※「指名リクエスト」とは、自分が探している商品を世界中にいるパーソナルショッパーにリクエストすることで自分の代わりに欲しい商品を探してもらうことができるサービスのこと。

 

Webデザインとアプリデザインの違い

 

Webページのデザインの場合はPhotoshopでデザインし、コーディングまで担当しますが、 アプリデザインに関してはSketchで作成したデザインをZeplinにエクスポートして、エンジニアに実装してもらっています。

ちなみに、Webデザインの頭でアプリデザインをしてもエンジニアからの手戻りが発生することが多いです。 わたしはWebとアプリの違いを理解しないまま、アプリのデザインをはじめてしまったので修正対応に苦労しました。

たとえば…

・このボタンを押したときのボタンの挙動は?アニメーション入れる? ・ここはページの遷移はモーダルなのか?プッシュなのか? ・可変要素で無いパターンの場合、高さを詰めるか? ・アラートやアクションビューの要不要 ・タブバー隠すか出すか ・なんか実装してみたらここの動きがヘン

Webページのデザインでは考慮しないようなポイントのため、アプリのデザインをするときはアプリの仕様をおさえておくことが必要です。 わたしは、モーダルとプッシュの役割の違いから勉強しなおしました。

わたしが今回特にお世話になった記事はこちらです。

わたしと同じように、これからiOSのアプリデザインに挑戦するという人がいたら、ひとまずAppleのヒューマンインターフェースガイドラインは必読です。 アプリの仕組みを理解することで、エンジニアとの共通言語が増え、コミュニケーションもより円滑になります。

 

BUYMAiOSアプリチーム

 

とこんな感じで、iOSエンジニアに助けてもらいながら、お問い合わせ画面を新しいデザインにすることができました。

Webデザインをするとき、HTMLやCSSのコーディングのことまで考えながらデザインしますが、 同じようにアプリデザインでもアプリエンジニアの実装のことも考慮してデザインできるデザイナーでありたいなと思います。

デザイナーだけでデザインをするというよりは、チームみんなで良いプロダクトになるよう日々ディスカッションしています。 BUYMAiOSアプリチームのメンバー構成は、デザイナー・エンジニア・MDでアプリの改修やブラッシュアップをおこなっています。

わたしたちと一緒にiOSアプリをつくっていくメンバーを募集しています。 現在ディレクターが不在のため、特にディレクター職の応募をお待ちしています!

www.enigmo.co.jp

いまさら聞けない!?プロダクトマネージャー・ディレクターが機械学習の案件を始めるまで

はじめに

この記事はEnigmo Advent Calendar 2018の25日目です。

BUYMAでプロダクトマネージャー・ディレクターのようなことをしています。 機械学習に関する案件を初めて進めてみようと思い、 プロダクトマネージャー・ディレクター目線で 、やってきたことや学んだことをまとめます。

知識がなくてもプロジェクトや案件は進めれるとは思いますが、ある程度理解があることで、プロジェクトの幅も広がりますし、エンジニアとのコミュニケーションも円滑になりますし、 何より自分も楽しいです

また、もし機械学習に関して知見がない会社でプロジェクトを進めていく場合の参考になればと思います。

この記事の対象者

非エンジニアプロダクトマネージャー・ディレクター  向けの記事です。

  • プロジェクトや案件で機械学習を利用しようと検討しているがどうしたらよいかわからない
  • 自分で機械学習学びたい!せっかくなら、プロジェクトや案件にしたい!(自分はこのタイプです) という方向け。

対象ではない方

  • 技術的な話とかかわらない方
  • 既に機械学習を利用してプロジェクトを推進している方
  • 機械学習に関わるプログラミングを実施している方
  • エンジニアの方

全体の流れ

1.基本知識のインプット 2.実際にコーディングもやってみる 3.プロジェクト・案件にするまで

基本知識のインプット

ゼロからスタートする場合は、何から初めてよいのか?と悩むことも多いと思います。

一番最初にやってみた

まず参考にしたのが下記の記事 【保存版・初心者向け】独学でAIエンジニアになりたい人向けのオススメの勉強方法

網羅されていて、わかりやすいが、プロダクトマネージャー・ディレクターとしては、ここまではいらない。(実際にやってみて途中でいろいろ挫折。時間もかかる)

その中で、やってきたことをプロダクトマネージャー・ディレクター向けに書きます。 下記に出てくる記事や本を読めば、最低限は大丈夫ではないかなと思います。

STEP1:まず機械学習を知る

例に漏れずここから。流し読みでもかなり面白い。 人工知能は人間を超えるか (角川EPUB選書)

読み終わると

  • AIってなんかすごそうってなる
  • なんかすごくAIがわかった気持ちになれる
  • エンジニアが言っていることが何となくわかるようになる

STEP2 : Pythonを知る

実際にコーディングもやることを考えると、ディレクターでもPythonは必須です。 全く触れたことがなかったので、本当に簡単なところから。

ドットインストール

動画を通勤中や移動中に見る。理解しようとせず最初は、流し見でよいと思う。 3回ほど聞くと、なんとなくわかってくる。

終わると

  • 動画なら、なんでも良いと思う
  • Pythonがわかった気になれる
  • Pythonを書いてみたくなる
  • エンジニアの言っていることがわかるようになる

Python3入門ノート

非常にわかりやすかった。 エンジニアではないので、日々コーディングしないと言語は習得が難しいので、なんとなく理解する程度で、読み飛ばす。 その中でも、読んでおくとよさそうのは、 Part3の「Numpyの配列」 ただ、読んでもほぼ忘れる。

あと、読み進める中で気になるところは、写経して実際にコードを書いみると良い。 一番重要なのは、 あとから困ったときに調べるために使うこと 。

読み終わると
  • Pythonがかけて嬉しくなる
  • エンジニアの仲間に入れてた気がする

STEP3(+α):Courseraのmachine-learning

無料 でここまで使える学習ツールはすごい!

機械学習のロジック部分で、実際にはCourseraを全くやっていなくてもコーディングはできる。知っておくとパラメーターチューニングの意味を理解できる面白い。 通勤中などの移動中に聞ける。 英語できなくても、日本語も用意されているのでほぼ問題ない。

こういう記事からも力をもらいながら、完了。

Courseraのmachine-learning

学習を終えると
  • なんか機械学習の理論がわかった気になれる
  • ただ、本当にすぐに忘れる
  • アンドリュー先生(講師の先生)が優しすぎて好きになる

実際にコーディングもやってみる

PandasとMachineLearning

KaggleのLearnがめちゃくちゃ良い。しかも 無料。 英語だけれど、Google翻訳を使えばほぼ問題なく進められる。

機械学習を実際に行う際のベースとなる部分なので、これはやっておくことをおすすめする。ただ、使わないと忘れるので注意。

本を読みながら深掘りしてみる

pythonで始める機械学習 を読んで、気になるところは写経してみる。

実際のプロジェクトをする際は、機械学習のパラーメーターチューニングなどはディレクターには求められていないと思うので、1章から3章くらいまでやれば十分だと思う。

読み終わると
  • 機械学習のコードが書けて、嬉しくなる
  • なんか実際のデータでやってみたくなる

(補足)コーディングに利用するツール

自分で環境構築できる方はぜひそちらで。 環境構築ができない/しない方は、GoogleColaboratoryでやるのがおすすめ。 これも無料で簡単なので、僕もこれを使いました。めっちゃ楽です。

プロジェクト・案件にするまで

はじめに

プロマネとして、機械学習プロジェクトを始めるならこれは必読書です。

仕事ではじめる機械学習

本書では、機械学習やデータ分析の道具をどのようにビジネスに生かしていけば良いのか、また不確実性が高いと言われている機械学習プロジェクトの進め方について 整理しています。 本書はもともと、機械学習の初学者向けに書いた文章からはじまりました。入門者のために書きはじ めたのですが、実際には理論を軽めにしたソフトウェアエンジニア向けの実践的なカタログのような形 になっています。 アルゴリズムの話などは他の書籍でも数多く取り上げられているので、本書ではプロジェクトのはじ め方や、システム構成、学習のためのリソースの収集方法など、読者が「実際どうするの?」と気にな るであろう点を中心にしています

とある通り、 プロジェクト始めたいけど、でどうするの? ということが書いてありますので、実施にプロジェクトを進める方にはすごく学びが大きいかと思います。 実際に、「その作業必要?」のようなリソース判断をすることや、全体像を理解することで手戻りを少なくする一助にもなるかと思います。

この要約がわかりやすかったです。

読み終わると

  • 機械学習のプロジェクトは思っているよりも多くのことがあるのだと知る
  • 実際にプロジェクトをやってみたくなる

実際にやったこと

本書の中で重要だと思ったのは、機械学習を使うことを目的化しないということでした。 機械学習の本なのに、 別に機械学習を使う必要は必ずしもない  と書いてあり驚きました。

実際に案件化していくステップとしては、 1.ユーザーの課題を明確にする 2.機械学習を使わずに解決する方法を考える 3.どうしても必要な場合は機械学習を活用する です。

機械学習の有無にかかわらず、 ユーザーの課題を明確にする ことからスタートして、 機械学習を解決策の一つ として持っておく感覚かと思います。

STEP1:ユーザー課題を明らかにする

プロジェクトを進めるにあたり、課題を明確化します。 実際に僕らが進めた場合は、経営陣やビジネスサイドの方と、

1.経営陣が認識している事業課題 2.現状現場が認識しているサービス課題 3.サービス以外にも、現場メンバーの作業に関する課題

など、様々なレイヤーでサービス課題/業務課題に関するディスカッションする機会を取りました。 課題を俯瞰して考えることで、課題理解も広がり、実際モチベーションも上がりました。

このステップを終えると
  • やっぱり〇〇はすごい解決したいよね〜(サービスの大きな課題)を再認識できます
  • 普段そんな作業をしてるのか。。。という現場のリアルを知れるます
  • 他の部署の人と仲良くなります
  • 実際にやる前提で話をするので、すごく楽しいです。

STEP2:課題の解決策を考えて、進める

初めて案件を進めるとなれば、どのように案件を進めるかが難しいかと思います。

はじめての機械学習関連のプロジェクトということもあり意識したのは、いかに ライトに着地させて一定の効果を出す かでした。

そのための課題設定と解決策を決めます。

本当は、これが理想。 ただ、簡単に見つからないですよね。。。

実際に進めていくなかで、最初の案件として一番しっくりきたのはこういう施策でした。

機械学習を取り入れる理由が明確にあり 、且つ工数も比較的小さいもの。 ここを見つけてプロジェクト化していくことで、進みやすくなるかと思います。

実は、ここで言う開発工数とは、機械学習の基盤を作成する工数は除いて考えています。 機械学習の運用基盤を作成するのは工数がもちろん高いので、

  • できるだけ使い回せるロジックにすること
  • 一度作成すれば、それほどアプリケーション開発の工数が変わらないこと

が重要なので、複数案件化できる状態にしておくことで基盤を作りやすくなるかと思います。

STEP3:巻き込む人を間違えない

前出のまとめ記事にもありましたが、案件を進める上で上記のメンバーは巻き込む必要があります。 そこで間違えると話が進まないので、初めてプロジェクトを進める場合は気にしてみてください。

まとめ/終わりに

ここまでお読みいただきありがとうございました。 はじめての記事でしたが、少しでも参考にしていただければ嬉しい限りです。

  • 基本的なインプットから、コーディング、プロジェクト化など一通りやってみて非常に勉強なりました。
    • 実際にコーディングもプロジェクトもやってみることが一番だと思いました。
  • 案件を考えるときに「機械学習」という選択肢を持てるのは、プロマネとしては強みにな今後なりうるのだろう思います。
    • ただ、選択肢の一つということを意識することは重要
    • 機械学習を使う!と言いながら、やはりいちばん大切なのは、「ユーザーの課題は何か?」という問いに尽きると改めて思いました。
  • 実際に、知見がない中で初めてプロジェクトを進める場合は、関わるメンバーや案件は慎重に進めるとよいと思います。
    • 時代の後押しはあるので、比較的会社も挑戦を応援してくれると思います。

関数型言語、聞いたことあるけど結局何なの?

概要

エニグモ サーバーサイドエンジニアの @gugu です。 この記事はEnigmo Advent Calendar 2018の24日目です。

関数型言語って結局何なの?と思ったので調べてみました。私が疑問に思ったことをベースに調べた内容を記載していこうと思います。

関数型言語として主にHaskellをメインに調べているので、関数型言語すべての話ではない記述があるかもしれません。

対象者

参考書

参考サイト

ありがとうございます!

関数型言語の疑問

「関数型」っていうけど手続き型でもオブジェクト指向でも関数を書くじゃん?

私がはじめに思った疑問です。みなさんもそう思いませんか? 下記のようです。

  • 関数型言語の関数というのは副作用のない純粋な関数のこと。(詳しくは後述)
  • すべてが関数でできている。Haskellだとif文も関数なのでelseの省略は不可。※言語によってそれぞれ例外あり。(そもそも何か値を返すのが「関数」、返さないのが「プロシージャ」と呼ぶ。C言語からプロシージャも含めて「関数」と呼ぶようになったとか。)
  • オブジェクト指向ではクラス内に関数を書く。(お作法的に。なぜこんな話をするのかは後述)

関数型言語の中でもマルチパラダイム言語って両方使えて最強じゃね?

結論から言うとそうでもないらしいです。

その前に関数型言語の種類について説明。。。

オブジェクト指向が備わっているということは副作用が発生する可能性が増えるということ、つまり関数型言語の本来の目的とズレてしまっていることになります。(もちろん適材適所でオブジェクト指向と関数型で使い分けられるメリットはあるかと。)

別に関数型言語でなくてもオブジェクト指向で副作用なく作れば良いのでは?

まずは先に副作用がないとはどういうことか

雑な説明かもしれませんが、変数が途中で変わらず参照透明であることです。

束縛

関数型言語で変数に「代入」することを「束縛」と呼びます。代入と違う点は一度値を入れると変更できません。

x = 1
x = 2 -- error

参照透過性

引数が同じなら返り値も必ず同じになる関数のことを「参照透過性」と言います。

で、オブジェクト指向でも参照透明に書けば良いのでは?

その通りで、オブジェクト指向でも副作用を避けて書くことは大事です。ですが、そもそも言語としてのアプローチが異なります。

関数型言語は副作用が起きづらい?だから?

下記メリットがあります。

  • テストや保守を容易にする
  • バグがおこりずらい
  • 再利用可能な部品を作りやすい
  • (注目)遅延評価

遅延評価

副作用がないので実現可能に。 使用するときに一度だけ計算されキャッシュされます。無駄な処理を省くことができます。

関数型言語ってどうやって書くの?

これが代表例なのかわかりませんが、私が一番なるほどと思ったのはループ文です。 関数型言語は関数がメインなのでループをさせる際はfor文ではなく再帰を使用します。(Haskellだとそもそもforもwhileも無いみたいです。)

Wikipedia(関数型言語)

で、オブジェクト指向関数型言語どちらで書くべき?

すみません、わからないです。。。(汗) 個人的な意見だと、やはり堅牢でテストコードの書きやすい関数型言語がベターなような気がしますが、オブジェクト指向のほうが「オブジェクト」を自然と意識して作れるので設計しやすいような気もします。ただ書き慣れているだけかもしれないのでやはり関数型言語なのでしょうか。

関数型言語の勉強にScalaは向いていないかも。。

関数型言語の勉強でScalaを勉強していたのですが、結局はオブジェクト指向脳を使ってオブジェクト指向で書いてしまうので、なにが関数型言語の特徴なのか理解しづらいです。関数型言語を学びたければ純粋型を学ぶのが良いかと思います。

まとめ

実際私が関数型言語への疑問を中心に書いたので、偏った知識かもしれません。しかし同じような疑問を持っている方に少しでも役にたてばと思って書いてみました。

調べた感じだと関数型言語は良いことづくしなような気もしますが、数学的でやはりとっつきにくいイメージも大きいかと思いました。結局は「関数型言語を知りたければ関数型言語で書くべし!」なんでしょうね。。関数型言語と仲良くなれるようにがんばります!

Codableいいよ!

この記事はEnigmo Advent Calendar 2018の23日目です

こんにちは。iOSチームでエンジニアをやっています。

Codable使ってますか?

iOSチームでは、 Alamofire + Codable で ネットワークまわりの実装を行なっています。

最初はいいのかわからなかったのですが、今ではなくてはならないものになっています。

すごく便利すぎて、Codable無しじゃ開発できない!そんな生活を送っています。

Codableについて軽く説明からの、実際使ってみて、Codableの得意なところと苦手なところを書いていこうと思います。

TL;DR

  • Codable良いから使ってみて!
  • Codableになれると、Enumをたくさん使うようになる

Codableとは

Swift4からFoundationに追加されたtypealiasです。 ( Codableは、プロトコルではありません )

EncodableDecodableの二つプロトコルに準拠します。

https://developer.apple.com/documentation/swift/codable

Codable、何に使うの?

JSONを扱う際の、エンコード / デコード を Codableを使い、簡易に表現します

どうやって使えばいいの?

例えば

itunes.apple.com から取得できるJSONから今リリースしているアプリのVersion知りたい!という時に、使えます。

JSON:

{
    "resultCount": 1,
    "results": [
        {
            ....
            "sellerUrl": "https://www.buyma.com",
            "trackName": "BUYMA(バイマ) - 海外ファッション通販アプリ",
            "currentVersionReleaseDate": "2018-12-12T06:02:14Z",
            "version": "3.3.0",
            "minimumOsVersion": "10.0",
            ...
        }
    ]
}

Codable:

struct AppInfoResponse: Codable {

    let results: [Results]

    struct Results: Codable {
        let version: String
    }
}

すごい簡単ですね。

Codableの良さ

Foundation 純正

  • 純正なので、Swiftのバージョンが上がった際に、オンタイムでアップデートされている
  • サードパーティのライブラリの場合、そのライブラリのアップデート対応が終わるまでXcode/Swiftのバージョンを上げれない

JSONDecoderのカスタムもいける

  • APIのレスポンス内のデータで、Date / DateTimeクラス が 2018-11-4 23:592018-06-24T23:59:59+09:00のように揃っていないケースがあります JSONDecoderdateDecodingStrategy.customにすることで、様々なケースのFormatに対応することができます
    decoder.dateDecodingStrategy = .custom {
        let container = try $0.singleValueContainer()
        let string = try container.decode(String.self)
    
        let formatter = DateFormatter()
    
        /// Date format: ISO_8601
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
        if let date = formatter.date(from: string) {
            return date
        }
        formatter.dateFormat = "yyyy-MM-dd HH:mm"
        if let date = formatter.date(from: string) {
            return date
        }
    
        return Date()
    }
    

Codableの苦手なところ

nilで返さず、空文字で返すと失敗する

  • URLがあるけど、URLになっていない
struct UserResponse: Codable {

    let name: String
    let imageUrl: URL?

    enum CodingKeys: String, CodingKey {
        case name
        case imageUrl = "image_url"
    }
}

成功:

{
    "name": "P",
    "image_url": "https://www.buyma.com/image"
}
</pre>

失敗:

<pre>
{
    "name": "P",
    "image_url": "" // 空文字
}

対応策

  • image_urlを 空文字ではなく、nilにしてもらう
  • init(from decoder: Decoder) を実装する

e.g.:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    name = try container.decode(String.self, forKey: .name)
    imageUrl = try? container.decode(URL.self, forKey: .imageUrl)
}

Arrayの中に、様々な Classが混ざっているケース

"topics"の各Objectの"type"を見ないといけない:

{
    "topics": [
        {
          "type": "sale",
          "title": "夏のセール開催中!",
          "products": [
          ]
        },
        {
            "type": "news",
            "title": "夏のセール開催中!",
            "image_url": "https://www.buyma.com/image",
            "link": "https://www.buyma.com/"
        },
        {
          "type": "topic",
          "title": "韓国ブランド集めました!",
          "search_url": "https://www.buyma.com/search"
        }
    ]
}

対応策

  • type見るCodableを使って、一度どのtypeになるのかを判定してから再度デコードする

チームでCodableをどうやって使っているか

開発フロー

  • APIcURLで叩いてjsonを取得
  • Codable準拠したstruct Responseを作成する
  • cURLで取得したjsonファイルを使用してstruct Responseにデコードされるかテストを実装する

サンプルコード

ネットワーククライアントのデコード処理:

func decode(_ type: T.Type, from data: Data) -&gt; T? {
    do {
        return try decoder.decode(type, from: data)
    } catch {
        print("---- API Parse Error ---")
        print(String(bytes: data, encoding: .utf8) ?? "")
        print("Error Description: \(error)")
        return nil
    }
}

Codableができているかどうかのテスト:

class ResponseTests: TestCase {

    func testDecodeResponse() {
        guard let path = Bundle(for: type(of: self)).path(forResource: "ResponseSample/sample", ofType: "json"), let fileHandle = FileHandle(forReadingAtPath: path) else {
            fatalError()
        }

        guard let response = decoder.decode(SampleResponse.self, from: fileHandle.readDataToEndOfFile()) else {
            fatalError()
        }

        XCTAssertNotNil(response)
    }

}

まとめ

  • Codableにすることで、CodingKeyに準拠したCodingKeysを書かないといけない手間はありますが、それを書いてもメリットが大きいです
  • 苦手はありますが、API設計に起因する部分が多いと思うので、チームでAPIを相談する際に、何が苦手なのかを伝えるといいと思います
  • SwiftyJson, ObjectMapperと使っていましたが、ほぼCodableに移せました

LiNGAM入門。気軽に因果関係を推定する(統計的因果探索)

この記事はEnigmo Advent Calendar 2018の22日目です。

はじめに

https://atarimae.biz/archives/7374 交番と犯罪件数が正の相関があるからといって、交番を減らして犯罪件数は減らないですよね。

さて、データ分析を行う上では、相関関係と因果関係を切り分けることが重要になることがあります。 例えば、KPIとある数値xが相関しているとします。 x → KPI という因果関係であれば、xの操作でKPI向上の施策を検討することができます。 逆に、KPI → x という因果関係であれば、xを操作してもKPIは変化しません。 y → x なのか、x → y なのか、xとyの相関関係の有無だけでは、因果関係は分かりません。

この記事では、機械学習ブロフェッショナルシリーズ、統計的因果探索を参考にしています。

なお、、z → x , z → y という未観測の共通原因(交絡因子とも呼ばれる)zが存在する場合についても、書籍では扱われていますが、今回の記事では未観測の共通原因については扱わないことにさせていただきます。

LiNGAM

x_{1}, x_{2}の2変数の関係bを以下のように構造方程式とう呼ばれるモデルであると仮定します。

x_{1} = b_{12}x_{2} + e_{1}

x_{2} = b_{21}x_{1} + e_{2}

x_{1}, x_{2}の2変数で現れ、e_{1}, e_{2}は外生変数がノイズ項です。 なお、LiNGAMでは非ガウス分布として扱います。 因果関係の推定の結果、x_{1} -> x_{2}という因果関係がある場合は、b_{12} = 0となり下記のようになります。

x_{1} = e_{1}

x_{2} = b_{21}x_{1}+e_{2}

ここで、LiNGAMは以下の方法があります

  • (1)独立成分によるによるアプローチ
  • (2)回帰分析と独立性によるアプローチ

独立成分によるによる推定

既にPythonで実装している方がいらっしゃるので、このアプローチに関してはそちらを参考にさせていただきます。

https://github.com/ragAgar/LiNGAM

モジュールとともに、lingam.pyをimportします。

import pandas as pd
import numpy as np
from lingam import LiNGAM

scikit-learn付属のボストン不動産データセットを使います。 価格をyにするのが自然ですが、敢えて 価格:x 部屋数:y とします。

boston = load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
x = boston.target
y = df.RM.values

推定を実行します。

data = pd.DataFrame(np.asarray([x, y]).T, columns=['target', 'rooms'])
lg = LiNGAM()
lg.fit(data)

推定結果

rooms ---|9.102|---&gt; target

部屋数が上がると、価格が上がる。という正しそうな因果関係を推定することができました。

回帰分析と独立性によるアプローチ

本をPythonで実装しました。ここでは、因果の向きのみの推定を行います。 なお、エントロピーは近似であることが本では述べられており、近似式の導出については、参考文献を読む必要があります。

def calc_r(x, y):
    return ((x - np.mean(x * y) - np.mean(x)*np.mean(y)) / np.var(y) * y,
            (y - np.mean(x * y) - np.mean(x)*np.mean(y)) / np.var(x) * x)

def normalize(x):
    return (x - np.mean(x)) / np.std(x)

def entropy(u):
    Hv = (1 + np.log(2 * np.pi)) / 2
    k1 = 79.047
    k2 = 7.4129
    gamma = 0.37457
    return Hv - k1*(np.mean(np.log(np.cosh(u))) - gamma)**2 - k2 * (np.mean(u * np.exp(-1 * u**2 /2)))**2

def lingam_reg(x, y, columns):

    xr, yr = calc_r(x, y)
    m = entropy(normalize(x)) + entropy(normalize(xr) / np.std(xr)) \
        - entropy(normalize(y)) - entropy(normalize(yr) / np.std(yr))

    if m &gt;= 0:
        print('{0} ---&gt; {1}'.format(columns[0], columns[1]))
    else:
        print('{0} ---&gt; {1}'.format(columns[1], columns[0]))

推定を実行します。

data = pd.DataFrame(np.asarray([x, y]).T, columns=['target', 'rooms'])
lg = LiNGAM()
lg.fit(data)

推定結果

rooms ---&gt; target

こちらも正しそうな推定結果を偉ました。

部屋数以外の変数でもやってみる

  • INDUS: 小売業以外の商業が占める面積の割合
y = df.INDUS
X = pd.DataFrame(np.asarray([x, y]).T, columns=['target', 'INDUS'])
lg = LiNGAM()
lg.fit(X)
lingam_reg(x, y, columns=['target', 'INDUS'])

推定結果

INDUS ---|-0.648|---&gt; target
INDUS ---&gt; target

小売業以外の商業、つまりオフィスの面積の割合が増えると、不動産価値は上がる。正しい気がする。

  • 税率
y = df.TAX
X = pd.DataFrame(np.asarray([x, y]).T, columns=['target', 'TAX'])
lg = LiNGAM()
lg.fit(X)
lingam_reg(x, y, columns=['target', 'TAX'])

推定結果

target ---|-8.586|---&gt; TAX
target ---&gt; TAX

不動産価値が高いと、税率が上がる。今までは逆の因果関係だが、この場合は正しそう。

最後に

ごく簡単な例ですが、統計的因果探索であるLiNGAMを体験することができました。 前述の構造方程式の通り、変数間の関係が線形である等、仮定があることは注意しなければいけませんが、あくまで因果関係の向きを推定する上では、その仮定の上でも議論が進められると思います。

また、こちらの取り組みについても興味深いです。 https://qiita.com/MorinibuTakeshi/items/402cb905e70655724d35

未観測の共通要因については今回割愛してしまいましたが、LiNGAMは因果推論という枠組みの一つの取り組みであり、傾向スコアやグレンジャー因果性といった取り組みについても今後学習を進めていきたいと思います。