Skip to content

Commit

Permalink
スコア計算ロジックの公開
Browse files Browse the repository at this point in the history
  • Loading branch information
tktcorporation committed Jan 16, 2025
1 parent 2b5e559 commit be9fc81
Show file tree
Hide file tree
Showing 20 changed files with 1,386 additions and 13 deletions.
11 changes: 11 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM mcr.microsoft.com/devcontainers/base:bookworm

WORKDIR /workspace

# Install UV globally in /usr/local/bin
RUN curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh

COPY ./pyproject.toml ./pyproject.toml
COPY ./uv.lock ./uv.lock

CMD ["uv", "run", "-m", "examples.calculate_e_score_v2_from_rank_info_example"]
14 changes: 14 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "latest",
"enableNonRootDocker": "true",
"moby": "true"
},
"ghcr.io/devcontainers/features/github-cli:1": {}
}
}
22 changes: 22 additions & 0 deletions .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

name: Ruff

on:
push:

jobs:
ruff:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]

steps:
- uses: actions/checkout@v2
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Run ruff
run: |
uv run ruff check .
25 changes: 25 additions & 0 deletions .github/workflows/run-examples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Run Examples

on:
push:

jobs:
run-examples:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Run example scripts
run: |
uv run -m examples.calculate_e_score_v2_from_rank_info_example
uv run -m examples.calculate_raw_e_score_v2_example
65 changes: 65 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Virtual Environment
.env
.venv
env/
venv/
ENV/

# IDE
.idea/
.vscode/
*.swp
*.swo
.DS_Store

# Testing
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Jupyter Notebook
.ipynb_checkpoints

# uv
.uv/
.venv/

# Project specific
*.log
.env.local
.env.*.local

# ruff
.ruff_cache/
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.10
7 changes: 7 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Changelog

## [2.0.0] - 2025-01-16
### Added
- 初期リリース
- スコア計算ロジックの実装
- ドキュメントの追加
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# コントリビューションガイドライン

## LAPRASスコアv2へのご意見について

いつもLAPRASをご利用いただき、ありがとうございます。
スコアに関するご意見、ご要望は、LAPRASユーザーコミュニティの[「スコアについてのご意見・議論」カテゴリ](https://github.com/lapras-inc/lapras-user-community/discussions/categories/%E3%82%B9%E3%82%B3%E3%82%A2%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%AE%E3%81%94%E6%84%8F%E8%A6%8B-%E8%AD%B0%E8%AB%96)にてお気軽にご投稿ください。
47 changes: 34 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
# lapras-score-v2

これは[LAPRAS](https://lapras.com)の「技術力スコア」の公開予定リポジトリです
スコア算出ロジックのコード、およびドキュメントをこちらのリポジトリに公開していきます
これは[LAPRAS](https://lapras.com)の「技術力スコア」の算出ロジックの公開リポジトリです
スコアに関するご意見や議論は、ぜひ[LAPRASユーザーコミュニティ](https://github.com/lapras-inc/lapras-user-community/discussions)に投稿ください


コード公開にあたり、新しくなった技術力スコア「v2」を先行体験いただけるモニターユーザーを募集しています。
[LAPRAS](https://lapras.com/person)にログイン後、画面右下のポップアップよりご応募ください。

スコアに関するご意見や議論は、ぜひ[LAPRASユーザーコミュニティ](https://github.com/lapras-inc/lapras-user-community/discussions)に投稿いただけたらと思います。


# スコア算出ロジックの公開にあたり
## スコア算出ロジックの公開にあたり

### LAPRASが目指すスコアの形

Expand All @@ -31,8 +25,35 @@ LAPRASの技術力スコアをより理想に近づけるためには、公平
スコアロジックを公開し、多くの目に触れることで、スコアリングの透明性と信頼性が高まると考えています。


# 今後の予定
### 技術力スコアv2 について

*詳細は「[3.技術力スコアv2における変更点](./doc/3_changes_in_v2.md)」をご覧ください*

スコアロジックの公開にあたり、ユーザーコミュニティにおける議論の中で継続的な改善ができるよう、スコアリングロジックの改修を行いました。
従来のスコアはサービス開発当初からあるロジックに修正を続けることで、拡張性が低くなってしまっていましたが、技術力スコアv2では、ロジックを整理し簡略化することで、今後のロジック変更をより頻繁に安定して行えるようにしました。
また自分の市場の中でのポジションがわかりやすいよう視認性も向上しました。


## サンプルスクリプトの実行方法

本リポジトリには、LAPRASスコアv2の計算ロジックの動作を確認するためのサンプルスクリプトが`examples/`ディレクトリに用意されています。
[DevContainer](https://code.visualstudio.com/docs/devcontainers/containers) を利用して環境構築を行うことも可能です。

### 推奨環境

* uv (https://github.com/astral-sh/uv)

### サンプルスクリプトの実行

```bash
# 各種サンプルスクリプトの実行例
uv run -m examples.calculate_raw_e_score_v2_example
uv run -m examples.calculate_e_score_v2_from_rank_info_example
```

## 公開スケジュール

* 2024-12-19: 技術力スコアv2の先行モニタユーザーへの提供開始
* 2025-01-16: 技術力スコア「v2」の全ユーザーへの提供開始 & コード公開
* 2025-01以降: ユーザーのフィードバックにもとづくスコアの継続的改修

* 2024年12月: 新しい技術力スコア「v2」のモニターユーザーへの提供開始
* 2025年1月: 技術力スコア「v2」の全ユーザーへの提供開始 & 算出ロジックのコード公開
* 2025年1月以降: ユーザーのフィードバックにもとづくスコアの継続的改修
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.0.0
56 changes: 56 additions & 0 deletions doc/3_changes_in_v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# 技術力スコアv2における変更点

技術力スコアv2 では、リポジトリコード公開にあたり、ユーザーコミュニティにおける議論の中で継続的な改善ができるよう、ロジックの改修を行いました。

従来の技術力スコアは、サービス開始以来修正を繰り返し、これ以上の拡張が難しい状態となっていました。
技術力スコアv2 では、これまでのロジックを整理・簡略化して実装し直すことにより、今後のロジック変更をより頻繁に、安定して行えるようにしました。

技術力スコアv2における主な変更点は以下の通りです。


### バージョン情報の付与

スコアリングロジックにバージョンを付与するとともに、サービス内でのスコア計算処理の各段階においてバージョンが更新されることを前提とした実装とすることで、スコアリングロジックを頻繁に安定的に更新できるようにしました。
2025年1月のロジック公開時点でのバージョンは v2.0.0 になります。

v2.0.0 以降の変更点は [CHANGELOG](../CHANGELOG) をご覧ください。


### 相対評価ロジックの簡略化

技術力スコアでは、「偏差値」のように、統計情報を用いた相対評価を採用しています。
このためには、アウトプット状況などから計算した「生スコア」を相対的なスコアに変換する処理が必要です。

従来の変換処理では、定期的に母集団の生スコアの統計情報を計算することで、変換処理ロジックを更新していました。
しかしながら、従来の方式には以下のような問題点がありました。

* 統計情報の計算に乱数が使われていたため、何もしなくてもスコアが変動してしまう
* 新規ユーザーが増えることで平均点が下がり、既存ユーザーは何もしなくてものスコアが上昇してしまう
* 統計情報更新のタイミングで非連続的にスコアが変化してしまう

実際には、これらの問題が顕著になってきたため、近年はこの分布の更新処理は停止していたのが実情です。
また、この更新処理を停止した状態でスコアに新しい要素を追加すると、全体のスコアが上昇してしまう問題もあり、スコアロジックの変更を妨げる一因となっていました。


これらの問題を解消するため、技術力スコアv2では、相対評価ロジックを以下のようにしています。

* 相対的な立ち位置を正しく反映するため、母集団の中での順位情報からノンパラメトリックに決定する方式とした
* 相対評価の母集団となる参照ユーザーとして固定した
* 参照ユーザーのスコア変動による効果(分布の変化)をスコア計算時にリアルタイムに反映するようにした


順位情報から相対的なスコアを計算するコンセプトおよびロジックの詳細については、[こちらの記事](https://qiita.com/nunukim/items/e4470f984bee85fbb136) を参照してください。
また、スコア計算の母集団となる参照ユーザーは、2024年12月現時点でのLAPRAS登録ユーザーおよびクローリングによって得られた未登録ユーザーの中からサンプリングした約2万人としています。


### 子指標の集計方法の変更

現在の技術力スコアには4つの子指標(GitHub、TechArticle、TechEvent、TagCount)がありますが、従来の技術力スコアではこれらの子指標のスコアの重み付き平均を取っていました。
このため、ある子指標がどんなに高くても、他の子指標が足を引っ張ってしまうという問題がありました。例えば、GitHubでOSS活動をどんなに頑張っていても、技術イベントへの参加を全くしていなかった場合はそれに引っ張られてスコアが減ってしまうことが起きていました。これは多様なエンジニア活動を応援するという観点では好ましくありません。
また、スコアロジック修正により新しいSNSを追加する際に、そのSNSで活動していないユーザーのスコアが大きく下がってしまうことになり、ロジック変更の障壁となっていました。

これらの問題を解決するため、技術力スコアv2では、子指標から総合の技術力スコアを計算する集計処理に減点方式ではなく加点方式を採用しました。
具体的には、相対評価をする前の「生スコア」の段階で各子指標の重み付き和を取り、その後に相対的なスコアを計算することとしました。
(従来は、子指標ごとに生スコアから相対的なスコアを計算した後に重み付き平均を取っていました)
これにより、あるSNSでのアウトプット活動も他のSNSでの活動も、(その重みに違いはあれど) 同様に足し算として扱われることになります。

89 changes: 89 additions & 0 deletions examples/calculate_e_score_v2_from_rank_info_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
ランク情報を使用した技術力スコア(E Score)の計算例
このスクリプトは、以下の要素を考慮して技術力スコア(E Score)を計算する例を示します:
- Raw技術力スコアとその詳細値
- 各スコアにおけるユーザーの順位情報(上位・同位・下位の人数)
- リファレンス対象者かどうかの情報
"""

from lib.lapras_score_v2.calculate_e_score_v2 import (
calculate_e_score_v2,
CalculateEScoreV2Args,
RankInfoWithinReferenceFunctions,
RankInfo,
)
from lib.lapras_score_v2.calculate_raw_e_score_v2_detail import RawEScoreV2Detail


def main():
# 1. スコア計算に必要な入力データの準備
score_data = calculate_e_score_v2(
args=CalculateEScoreV2Args(
# リファレンス対象者かどうか
is_reference_person=True,
# Raw技術力スコア
raw_e_score_v2=100.0,
# 各カテゴリーのRawスコア詳細
raw_e_score_v2_detail=RawEScoreV2Detail(
github_value=100.0, # GitHubスコア
tech_article_value=50.0, # 技術記事スコア
tech_event_value=30.0, # 技術イベントスコア
tag_count_value=20.0, # 技術タグスコア
),
# 各スコアにおけるランク情報を取得する関数群
rank_info_within_reference_functions=RankInfoWithinReferenceFunctions(
# 総合技術力スコアのランク情報
get_e_score_v2_rank_info=lambda args: RankInfo(
lower_count=10, # 自分より下位の人数
higher_count=20, # 自分より上位の人数
same_rank_count=5, # 同じランクの人数
),
# GitHubスコアのランク情報
get_github_score_rank_info=lambda args: RankInfo(
lower_count=10,
higher_count=20,
same_rank_count=5,
),
# 技術記事スコアのランク情報
get_tech_article_score_rank_info=lambda args: RankInfo(
lower_count=10,
higher_count=20,
same_rank_count=5,
),
# 技術イベントスコアのランク情報
get_tech_event_score_rank_info=lambda args: RankInfo(
lower_count=10,
higher_count=20,
same_rank_count=5,
),
# 技術タグスコアのランク情報
get_tag_count_score_rank_info=lambda args: RankInfo(
lower_count=10,
higher_count=20,
same_rank_count=5,
),
),
)
)

# 2. 結果の表示
print("\n=== 正規化スコア ===")
print(f" GitHubスコア: {score_data.github_score:.2f}")
print(f" 技術記事スコア: {score_data.tech_article_score:.2f}")
print(f" 技術イベントスコア: {score_data.tech_event_score:.2f}")
print(f" 技術タグスコア: {score_data.tag_count_score:.2f}")

print("\n=== パーセンタイル情報 ===")
print(f" GitHub: {score_data.github_score_percentile:.1f}%")
print(f" 技術記事: {score_data.tech_article_score_percentile:.1f}%")
print(f" 技術イベント: {score_data.tech_event_score_percentile:.1f}%")
print(f" 技術タグ: {score_data.tag_count_score_percentile:.1f}%")

print("\n=== 最終結果 ===")
print(f"技術力スコア(E Score): {score_data.e_score_v2:.2f}")
print(f"パーセンタイル: {score_data.e_score_v2_percentile:.1f}%")


if __name__ == "__main__":
main()
Loading

0 comments on commit be9fc81

Please sign in to comment.