LIFULL Creators Blog

LIFULL Creators Blogとは、株式会社LIFULLの社員が記事を共有するブログです。自分の役立つ経験や知識を広めることで世界をもっとFULLにしていきます。

班分けAI

こんにちは、MAM開発グループの椎橋です。 MAMとはマーケティングオートメーションの略で、マーケティングに関する機械学習アルゴリズムを作ったり、データ分析をして改善につなげたりしています。

今回は社内制度のクリエイターの日を2日間利用して、社員旅行の班分けの最適化モデルを作りました。 以前はこの制度を利用してサーバ・ミドルウェアの勉強をしました。 nextdeveloper.hatenablog.com

弊社の社員旅行は多くの社員が参加し、最高に盛り上がる大イベントです。 社員旅行委員が予算の見積もりからスケジュールまで計画を立ててくれるのですが、 そのスケジュールの中にアクティビティと呼ばれるイベントがあります。 これは班に分かれて観光やスポーツなどを楽しむというもので、私は昨年そば打ちを体験しました。 複数あるアクティビティのうち参加できるのは一つだけな上に、人数の上限が設定されているために希望したアクティビティに参加できるかどうかは分かりません。 昨年は社員旅行委員が抽選と手動調整によって班分けを行いましたが、数時間かかったらしいので最適化モデルを作ることにしました。

データ抽出

まずは、計算に用いるデータを準備します。 Google フォームで社員の希望調査を行い、集計結果を以下のように変換します。

名前ID 性別 group_1 group_2 group_3 group_4
id_1 1 1 3 -1 2
id_2 -1 2 3 1 -1
id_3 -1 3 1 2 -1

性別カラムは男性なら1,女性なら-1を取るようにし、各アクティビティの希望順位をgroupカラムに記します。希望していないアクティビティには-1を割り当てました。

定式化

次にこの問題を数式に変換します。

定数

まずは定数を以下のように定めます。

説明 表記
参加する社員[人] $N$
班(アクティビティ)の種類 $ M $
班 $j$ の上限人数[人] $g_j$
社員 $i$ の班 $j$ への希望度 $h_{ij}$
社員 $i$ が男性なら 1, 女性なら -1 を取る $s_i$

$h_{ij}$は希望順位から算出した定数で、算出方法は割愛します。また、添え字集合を以下のように定義しておきます。 $$I \mathrel{\mathop:}= \{1,\ldots,N\}$$ $$J \mathrel{\mathop:}= \{1,\ldots,M\}$$

変数

次に、問題を解くための変数を以下のように設定します。

説明 表記
社員 $i$ が班 $j$ へ参加するなら 1, 不参加なら 0 を取る $x_{ij}$

これにより、$x_{ij}$を任意の $i$, $j$ に対して定めることで班分けを一意に決定できます。

モデリング

上記を用いてモデリングします。 まず、$x_{ij}$は 0 もしくは 1 を取る変数で、参加できる班は 1 つのみであることから、

$$ x_{ij} \in \{ 0, 1\},\ \forall i\in I,\ \ \forall j \in J $$ $$ \sum_{j \in J}{x_{ij}} = 1, \ \ \forall i \in I $$

という式を作れます。これは以下のような行列形式で考えるとわかりやすいです。

group$_1$ group$_2$ $\cdots$ group$_{M}$
社員 $i$ $x_{i1}$ $x_{i2}$ $\cdots$ $x_{iM}$

社員 $i$ は一つの班に属するのでいずれかが 1 でそれ以外はすべて 0 になり、それを上記の式で表しています。そして、すべての社員に対してこの式を満たさなければいけないので、各 $i$ に対して制約が設定されています。

各班には人数の上限が設けられているために、 $$ \sum_{i\in I}{x_{ij}} \leq g_j, \ \ \forall j \in J $$ を加えます。今度は班 $j$ についての制約で行列形式のデータを列で見るとわかりやすいです。

group$_j$
社員 $1$ $x_{1j}$
$\vdots$ $\vdots$
社員 $N$ $x_{Nj}$

列で和を取れば班 $j$ に属する人数を計算できるので、これが班 $j$ の上限人数以下になるようにします。 そして、目的は希望度を最大化しつつ班の男女の人数の比率をできるだけ等しくすることで、以下のようにします。 $$maximize: \sum_{i\in I}\sum_{j\in J}h_{ij}{x_{ij}} - \alpha\max_{j\in J}\left({\left|\dfrac{\displaystyle \sum_{i\in I}{s_ix_{ij}}}{g_j}\right|}\right)$$

第一項は希望度の総和、第二項は疑似男女比差を表しています。 班 $j$ に属する男性、女性の比率の差は $\displaystyle \left|{\sum_{i\in I}{s_ix_{ij}}}\big{/}{\sum_{i\in I}{x_{ij}}}\right|$ で表せますが、計算を容易にするために班の合計人数を班の上限人数に置き換えて疑似男女比差とみなし、定数 $\alpha>0$ を掛けています。標準形に変換する際は新たな変数 $y$ と以下の制約を加えれば実現できます。

$$ y \geq \dfrac{\displaystyle \sum_{i\in I}{s_ix_{ij}}}{g_j}, \ \ \forall j\in J$$ $$ y \geq -\dfrac{\displaystyle \sum_{i\in I}{s_ix_{ij}}}{g_j}, \ \ \forall j\in J $$

これにより $y$ は $\displaystyle \max_{j\in J}\left(\ {\left|\sum_{i\in I}{s_ix_{ij}}\big{/}g_j\right|}\ \right)$ 以上の値を動くことができますが、目的関数値を極力下げないようにするために最適解で $y^*$ は$\displaystyle \max_{j\in J}\left(\ {\left|\sum_{i\in I}{s_ix_{ij}}\big{/}g_j\right|}\ \right)$ になります。

以上をまとめますと、以下のモデルで書けました。

\begin{align} maximize && \sum_{i\in I}\sum_{j\in J}h_{ij}{x_{ij}} - \alpha y && \\ subject\ to && \sum_{j\in J}{x_{ij}} = 1, && \forall i \in I\\ && \sum_{i\in I}{x_{ij}} \leq g_j, && \forall j \in J\\ && g_jy \geq \sum_{i\in I}{s_ix_{ij}}, && \forall j \in J\\ && g_jy \geq - \sum_{i\in I}{s_ix_{ij}}, && \forall j \in J\\ && x_{ij} \in \{ 0, 1\}, && \forall i\in I,\forall j \in J\\ && y \in \mathbb{R} && \end{align}

実装

設計ができたので、Pythonで実装します。

import pulp
'''省略'''
problem = pulp.LpProblem("problem", pulp.LpMaximize)
x = pulp.LpVariable.dicts("x", (range(n), range(m)), 0, 1, "Continuous")
'''省略'''

ポイントは$x_{ij}$を0-1変数(Binary)ではなく$[0,1]$ の実数変数(Continuous)にしていることです。理由は行列のユニモジュラ性を利用していて、最適解で $x_{ij}$ は整数になることが保証されているためです。組み合わせ問題は変数を増やすと爆発的に計算量が増加しますが、この緩和を適用できると変数が増えても比較的容易に最適解を求められます。

結果

最後に最適化と抽選式で結果を比較します。抽選式は、希望人数を加えても班の上限に達しないならば抽選せずに確定させ、そうでなければ抽選によって班に加えるメンバーを選出する決め方です。比較は希望した班に割り当てられた人数を集計して行い、実行環境はIntel® Core™i5-6200U CPU @2.3GHz, メモリ8GB でした。

昨年の社員旅行で用いられたデータ(一部加工, $N=411, M=14$)で計算すると以下のようになりました。

最適化 抽選式
第一希望 339 349
第二希望 62 20
第三希望 10 13
希望外 0 29
最大男女差比 30% 15%
計算時間 0.6秒 0.3秒

抽選式では希望外の班に割り当てられた社員がいるので、この後手動で調整する必要があります。一方で最適化の結果ではその現象は起きていません。次にデータの規模を大きくして$N=10000, M=100$としました。

最適化 抽選式
第一希望 8318 8512
第二希望 1591 620
第三希望 91 270
希望外 0 598
最大男女差比 33.3% 30%
計算時間 162秒 16秒

この規模になると最適化の効果が顕著になりますね。

まとめ

クリエイターの日を利用して社員旅行の班分け最適化モデルを作りました。整数条件を不要としたモデルにすることで変数が増えても比較的容易に計算できるのが特徴でした。エンジニア支援制度が充実したネクストでは鋭意エンジニア採用中です!新卒・中途問わず、ご興味を持たれた方は是非下記ページを御覧ください。

http://recruit.next-group.jp/

zipkinのバックエンドをAmazon Elasticsearch Serviceに変更してみた

こんにちは、AmazonESでElasticsearch2.3を使っての環境構築が終わった直後にElasticsearch5.1が利用可能になってショックを受けてる技術基盤部の磯野です。

ちょっとだけ時間ができたのでzipkinのバックエンドをAmazon Elasticsearch Serviceに差し替えてみました。

CassandraとElasticsearchどっちにしようかなぁと悩んでいたのですが、zipkinがいつの間にかElasticsearch Serviceに対応していたのでサーバー構築したくない病発症中のためノータイムでElasticsearch Serviceに決定しました。

続きを読む

海外のカンファレンスに参加するということ

エンジニアの鈴木です。主にAWS周りのことをやってます。

11月末から1週間ほど、AWS(Amazon Web Service) が主催するカンファレンス re:Invent 2016に参加してきました。開催場所はラスベガスでした。

今回得た経験を踏まえ、海外のカンファレンスに参加するということについて思うことをまとめましたのでフィードバックします。

ただし、「海外のカンファレンスに参加すること」という意味合いで汎化して書いたつもりですが、実際はre:Inventにバイアスが掛かっています。 なので、re:Inventに参加するということと読み替えてもらったほうが適切かもしれません。(その判断は読者の皆様におまかせします。) また、たった一度のre:Inventへの参加という偏った主観であることと、re:Inventで得た技術的な内容のフィードバックはこの記事に含まれないことにご留意ください。

海外のカンファレンスに行ったことがない企業所属のエンジニアの方や、そのエンジニアの上司の方に読んでいただけたら嬉しいです。

まずはじめに、「なぜ海外のカンファレンスに参加するのか?」という問いについてです。

主観ですが、端的に「現地でしか得られないものがあるから」になります。(当たり前)

では、現地でしか得られないものとはなんでしょうか?

それは個人の主観になるのでコレだ!というものに限定できません。 ですが、それは確実に存在し参加者へ影響を及ぼすと思います。

これだとフワッとしているので、少し視点を変えます。

シンプルに メリット・デメリット を考えていった時に、最終的に送り出した企業・実際に行った人の両方にメリットがあると感じました。 その理由を「参加させる企業のメリット」、「参加者のメリット」として以下にまとめます。

参加させる企業のメリット

まず初めに、費用を持つ立場から見た視点で見ていきます。企業(上司)サイドの話です。

企業が海外のカンファレンス参加を経費として認めてくれるパターンがあります。自分もそのパターンでした。

海外のカンファレンスに参加するにはコストがかかります。

実際にかかる経費は、普通に考えて 渡航費用・イベント参加費・現地での滞在費・出張中の人件費等があります。 日常的なコストと相対的に比較すると”安い”とは声を大にして言えません。

それでも自分は参加したほうがメリットが大きいと感じました。

その理由を見ていきます。

参加者の変化を促せる

普段と違う環境は、個人に対し確実に影響を与えます。

参加するイベントが提供する情報は、もともとその個人にとって興味のある分野のはずです。なので、限られた時間の中で、新しい知識を得たり新しいリレーションを築くことは、必然的にポジティブな方面への変化を促せると感じました。

自社の抱える社員がポジティブに変化することは、企業にとって大きなプラスになると思います。

採用においてメリットを生む

昨今のエンジニアの争奪戦は人事的には頭の痛い問題です。 ビジネスをドライブしていける人材を確保していくことは大変重要ですが、優秀なエンジニアは複数社からの内定が出ることが多いので、どうやって自社を差別化するかがポイントになります。 その際、積極的に海外のイベントに参加することができる体制がある会社であることをアピールできれば、採用の後押しとしてのメリットを生むことができると思います。

社内エンジニアへの影響

会社で参加実績が作れると、自分も来年もしくは再来年は行けるかもしれないという期待がエンジニアに膨らみます。 期待が膨れれば、その技術に対してもっとコミットしようと思うし、スキルが上がれば生産性にも影響があるでしょう。 素直で謙虚なエンジニアほどしっかりスキルを身につけて次のチャンスをものにしようと行動すると思います。

参加者のメリット

次に、参加者側からの視点です。 毎晩飲みにいけます。って話ではありません。(あながち間違っていませんが)

百聞は一見にしかずとはまさにこのことで、普段とは全く違う角度から経験値が上がります。 特に初参加であればその傾向は顕著でしょう。

参加者が得られるメリットとその理由を見ていきます。

海外とは無縁な人ほど、良い意味で変化の振り幅が大きい

普段、外に出て行く機会が少なく社内で黙々とプロダクトを開発しているエンジニアには、カンファレンスへの参加で受ける影響が大きく、それに比例するように変化の振り幅が大きくなると感じました。

自分に起きたわかりやすい例でいうと、英語に対するハードルが下がったり、新しい分野への興味が湧いたり、諸々ありますが、はっきりとした変化が感じられました

普段得がたいリレーションが築ける機会がある

前提として、今回はツアーでの参加になります。ツアーにはそもそもリレーション強化の懇親会などがインクルードされていました。 なので、何のリレーションのない個人が現地で0からリレーションを築いたという内容ではありませんのでご留意ください。

海外までイベントに参加しにいくと言うことはそれなりに労力がかかります。その労力をかけても参加したい人たちが集まっているので、みんな話が通じやすくフレンドリーだと感じました。そのイベントが提供する技術的な分野に対し、最初から多くの共通項を持っているからなのかもしれません。

同じ時期、同じ場所に集まると思いもがけない出会いがあったりします。

自分の場合、カンファレンス最終日にとあるレジェンド的な方とたまたま席が隣になりお話しさせていただく機会がありました。その会話の中で自分が感じていたことの誤解が解けたり、海外のカンファレンスへの参加について同じような思いを抱いていることがわかったり、自分の行動範疇では到底得ることのできないようなお話をさせていただくことができました。

世界の広さを感じられる

本当にいろんな人がいます。そして、参加者全員がその分野に興味があって集まってきています。 世界中から集まってくるエンジニアと一緒にセッションを受けていると、公表されているサービス利用者の数字から想像できる以上のインパクトがありました。 参加人数が多いカンファレンスであればあるほど、その傾向は顕著だと思われます。

英語へのハードルが下がる

出国前は何かと不安でした。自分はそんなに英語ができる方ではないからです。 ですが、行ってみたら意外となんとかなりました。なんとかなると自信がつきハードルが下がるのを感じました。

セッションのスライドはわかりやすく簡易な英語で書かれていることが多いし、登壇者にはプレゼン慣れしている方も多いです。その登壇者が簡易な英語のスライドをベースにして話が進むので、セッションの内容も理解しやすかったです。(実際、街中のブロークンな英語の方が理解するのに苦労しました。)

まとめ

いままで延べてきた通り、海外の技術系イベントに参加するということは、企業にとって短期的に見ても長期的に見ても良い投資だと思います。 それは情報の鮮度的なメリットもありますが、もっと大きな要因として、現地に行くことでしか得られない人の成長を加速させる可能性がいろんな側面に秘められていると感じるからです。

ただ、上記に記述しましたメリットを享受するには、一つ重要な前提条件があります。

それは、参加者が自らの言葉でフィードバックすることが必要だということです。

企業にとって、費用対効果のあるなしはフィードバックの質や熱に大きく依存すると思います。そのフィードバックが次回に向けた参加判断基準になります。

昨今では日本にいても情報が得られるタイミングは同じになりました。 なので、日本に居て情報をキャッチアップすることは容易であり、費用もかかりません。

ですが、現地でしか得られないものがあります。 だから、自分で感じることが重要で自分の言葉でフィードバックすることが大切だと思います。

もし海外の技術系イベントに参加したいと考えているエンジニアの方は、いまから積極的にアピールしましょう。ひょっとしたら会社が経費を持ってくれるかもしれません。 (仮に会社の選考から漏れたとしても自腹来てらっしゃる方もたくさんいます。)

企業や決済者は、エンジニアにどんどん旅をさせることをオススメします。さまざまな面で短期的にも長期的にも割のいい投資になると思います。

そして、参加者は、社内・社外・自分・次に行くかもしれない人のためにフィードバックをしましょう。

あなたのフィードバックがみんなを少しづつ良い方向にナビゲートする最初の一歩になるかもしれません。

このフィードバックが誰かの役に立てば幸いです。

【クリエイターの日】社内クラウドファンディングシステムを開発したお話

はろーはろー!チバです。 今回は、22期2Q(7-9月の間)で「クリエイターの日」制度を利用しておこなった、社内クラウドファンディングシステム「FU-SHA」の企画〜リリースまでの取り組みの様子をお送りします!

クリエイターの日制度を利用するに至った経緯

2016年11月に、「アイデアアワード」という社内アワードに応募していたところ、グランプリを受賞することができました\わーい!/

そのときの応募していたアイデアが「社内クラウドファンディング」。一般社員の投票で選ばれたネタなので、みんなの期待を感じられてとても嬉しかったです。

f:id:nextdeveloper:20161129205730p:plain

続きを読む

Androidアプリ宣伝用画像のA/Bテストを通して学ぶものづくり

f:id:homes_designers:20161020155550p:plain

こんにちは、新卒デザイナーの五十嵐です。
私はアプリチームに配属になり、主にアプリのストア内の画像・動画や集客バナーの制作をしています。
何事にも根拠が必要ということを学びながら、日々ものづくりライフに励んでおります。
今回は、私が携わったAndroidアプリの宣伝用画像におけるA/Bテストについてお話したいと思います。

続きを読む

社内クラウドファウンディング・W3C Push API・ぬいぐるみハック・マウスになる椅子など最新技術や新しいアイデアてんこ盛りの社内プロダクト展示会を開催しました!

こんにちは! 新卒1年目エンジニアの佐藤茉弥(さとうまや)です。

今回は、先日10/4(火)に開催されたネクストの社内イベント「第3回創民祭」の様子についてレポートさせていただきます。

創民祭(そうみんさい)とは

聞き慣れない言葉かと思いますが、「創民祭」は、業務内外で作ったプロダクトを発表し合うお祭りです。 各展示ブースでは、プロダクトに関して説明を聞くのみではなく実際に触れることもできます。 半年に1回のペースで開催されていますが、とても刺激になる楽しいお祭りです!お酒と軽食も出ます!

前回までの開催の模様はこちらの記事をご覧ください。

続きを読む