テックブログ2023-08-22

GitHub活動量スコア化の設計思想と数理

nunuki


LAPRAS のプロダクトマネージャー・R&D責任者の鈴木(ぬぬき)です。
LAPRASでは、先日技術力スコアにGitHub でのプライベートリポジトリを含む日々の活動量(いわゆる草の情報)を反映するリリースを行いました
今回は要望の大きかった機能なこともあり、X (旧Twitter)上でも多くの反響をいただいております。
本記事では、開発後記として、GitHub活動量のスコアをどのように反映しているのか、また、なぜそのようにしているのかを、背景の設計思想も踏まえて紹介したいと思います。

GitHub での日々の活動量のスコア化

プレスリリースにも記載されている通り、GitHub での日々の活動量のスコア化は、次の計算式でスコアに反映されています。

どうしてこの数式を採用したのか、以下では、この背景にある思想や数理を詳しく紹介していきます。

活動量をスコア化する時に満たすべき要件

GitHub のいわゆる「草」の情報をスコア化するとき、特に以下の2点を満たす必要があります。

  1. エンジニアの経験やスキルを表すものとして、納得できる数値であること
  2. 数値的にロバスト(頑強)であり、容易にはハックしづらいこと


1について、今回はプライベートリポジトリでの活動も含めてスコア化するため、リポジトリの内容を参考にするわけにはいきません。したがって、コードの品質やプルリクエストの内容などからスキルを推定することはできません。一方で、GitHub の「草」は、活動の歴や継続性、量を可視化しているものですから、これを技術力としてスコア化するにあたっては、 「エンジニアとしての経験量」 を定量化するものであると位置付けました。

エンジニアとしての経験量を数値化するにあたって、古典的ながらいまだによく使われる指標として「エンジニア歴〇〇年」というものがあります。エンジニア歴の長さを技術力として用いることの問題点は、その期間でどれくらいの量・質の経験をしているのかを考慮していない点にあります。一方で、エンジニアとしての活動を長く継続している方がエンジニアとしての経験量が蓄積されるという観点は一定の合理性があると考えられます。同じ「エンジニア歴1年」でも、活動が疎らな状態よりも、毎日欠かさずに活動してビッシリと草が生えている状態の方が、多くの経験をしていると言えそうです。
この観点から、 「GitHub上での活動日数」 をベースにGitHub活動量を数値化することにしました。

また、活動日数をベースにスコア化することについて、2のロバスト性の観点からも合理的であると考えられます。
例えば、特定の日(例えば活動量が最大の日)の活動量だけを勘案するスコアとした場合、ある日たまたま大量のコミットを行った場合にスコアが大きく変動してしまったり、逆に、毎日活動していても全然スコアが変化しないといったことになってしまいます。また、スコアを故意に高めようとした場合も、特定の日に大量の活動をするよりも、過去にわたって活動を改変する方が難しいため、活動日数をベースとした方がハックのしづらさという観点からもメリットがあります。

ちなみに、LAPRASユーザーにおけるGitHub での過去にわたる活動日数と全Contribution数の関係は次のようになっています。

  • 総Contribution数は活動日数にほぼ比例している。
  • 活動日数が多い(活動歴が長い)人ほど、活動日1日あたりの活動量が多い。


このため、活動日数をベースに数値化をするのは、総Contribution 数を数値化することにかなり近いものとなっています。
しかしながら、同じ活動日数でも、総Contribution数の多い人と少ない人とでは数倍〜10倍程度の差がある場合があるため、活動日数をベースとしつつも、Contribution数も考慮してスコアに反映する必要があります。

日々の活動量の導出

以下では、上述の要件を満たすスコアの具体的な表式を導出します。
入力としては草の情報、すなわち、i日目に行ったContribution数の数列 {𝑐𝑖} (𝑖=1,⋯,𝑁) を用います。
すなわち、スコアの元となる「日々の活動量」の値 S は次のように表されます。

𝑆 = 𝐹({𝑐𝑖})


ただし、活動量が全くない場合はS=0とし、活動がある場合はS>0の値を取るものとします。
それでは、上述の要件から関数𝐹に課される条件をもとに、𝐹の形を絞り込んでいきます。


(a) 時間に関する並進対称性

「エンジニアとしての経験」を数値化するため、過去の経験も最近の経験も同じ経験として扱います。
例えば、最近活動をしていない場合であっても、他の人の活動が増えて「相対的な経験値」は下がるかもしれませんが、経験自体が失われるわけではないという観点から、時間が経過してもSの値は減少しないものとします。
すなわち、関数𝐹は時間(日)に対して並進対称性を持ちます。

𝐹({𝑐𝑖+𝑑}) = 𝐹({𝑐𝑖})


(b) 活動日に対する加法性

「エンジニアとしての活動日数」をベースにスコア化を行うため、毎日同じ活動量であるならば、活動日数に比例した値になるべきです。
言い換えると、過去の2つの期間で全く同じ活動をした場合、全体の活動量の値は、それぞれの期間での活動量の和になるべきです (a.の並進対称性を仮定すると、これら2つの期間の活動量は等しくなります)。
これは、数式としては、次のような加法性として表されます。

𝐹({𝑐1, ⋯, 𝑐𝑛, 𝑐𝑛+1, ⋯, 𝑐𝑁}) = 𝐹({𝑐1, ⋯,𝑐𝑛}) + 𝐹({𝑐𝑛+1, ⋯, 𝑐𝑁})


上記の条件a(並進対称性), b(加法性)を仮定すると、𝐹の形は次のような形に限られます。

𝑆 = ∑𝑖=1𝑁 𝑓(𝑐𝑖)

ここで、𝑓 は 𝑓(0) = 0 となる(広義)単調増加関数です。

(c) 1日あたりの活動量に関する劣加法性

上述の要件で考察したように、日々の活動量のスコア化にあたっては、1日で大量のContribution を行うよりも、同じContribution数でも毎日継続的に活動を行っている方が多くの活動を行っていると捉えるべきです。
つまり、1日の中で何度もContribution を行うごとに、1回のContribution あたりのスコアへの寄与が逓減する必要があります。
つまり、fは次のグラフのように劣加法的(上に凸)な関数である必要があります。

𝑓(𝑥+𝑦) ≤ 𝑓(𝑥) + 𝑓(𝑦)


劣加法的関数fの例

条件を満たす関数

関数𝑓としては、条件(a)〜(c)を満たす任意の関数を選ぶことができます。
例えば、極端な例として、𝑓を階段関数 𝑓(0) = 0, 𝑓(𝑥) = 1 (𝑥 > 0) とすることができます。この場合、Sの値は「GitHub上での活動日数」と一致します。
もう一つの極端な例として、 𝑓 を恒等関数 𝑓(𝑥) = 𝑥 とするならば、Sの値は「GitHub Contribution の総数」と一致します。
上記の例はどちらも条件をギリギリ満たす場合であり、「活動日数」と「総Contribution数」のどちらかのみを用いるという点で両極端な例ですが、実際には、これらの中間的な性質をもつfを選ぶ必要があります。
今回は、そのような 𝑓 として次のような対数関数を採用しました。

𝑓(𝑥)=log(1+𝑥)


こうした場合、日々の活動量Sの値は、活動日数(𝑐𝑖 > 0 である 𝑖 の数) 𝑀 を用いて、次のように表すことができます。

式(※)


こうすることで、(a)〜(c) の条件を満たしつつ、活動日数と1日あたりの活動量の幾何平均という解釈性のある計算式とすることができました。
これが、冒頭に掲載した式になります。

日々の活動量の値の性質


日々の活動量の値 (※) の性質についてみていきます。
1日あたりの活動量は幾何平均を取っているため、活動日数、総Contribution数が同じなら、ある日にまとめてContribution するよりも、毎日同じだけContribution する方が高い値になります。
また、1日あたりの活動量は対数を取っているため、1日あたりの活動量を増やすよりも活動日数を増やす方がSの値は大きくなりやすくなります。
例えば、これまで1日あたり平均10回Contribution を行っていた場合、次の日に1回だけContributionを行った場合、活動量は増えますが、1日あたりの活動量は減ることになります。しかしながら、条件(b)を満たすため、式(※)全体の値は必ず増加します。
ちなみに、式(※)における対数の底は、全体を定数倍するだけの違いなので、Sの値から相対的に計算するスコアの値には影響を与えないため、任意に選ぶことができます。しかし、当然ですが、実装の中では対数の底の値を統一しなければなりません (不具合はすでに解消しております。ご迷惑をおかけしました)。

おわりに

本記事では、GitHub の日々の活動量のLAPRASの技術力スコアへの反映について、その背景にある考えや計算式の導出について詳細に紹介しました。
今回は久しぶりとなる大規模なスコアの改修となりましたが、なるべく合理的で透明性のあるスコアとするため、詳細の計算式まで公開することとしました。
LAPRASで技術力をスコア化していることと矛盾するようですが、エンジニアとしての能力は多岐にわたるため、それを1つの数式で表すというのは本質的に困難な問題であり、誰もが納得できる完璧な指標というものは存在しないかもしれません。
しかしながら、エンジニアの経験やスキル、性質や志向などをより多角的な視点から見える化し、今より少しでも適切に伝えられるようにすべく、今後もLAPRASの改善を進めていきます。
今後ともLAPRASをよろしくお願いします。

このエントリーをはてなブックマークに追加