-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2b5e559
commit be9fc81
Showing
20 changed files
with
1,386 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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": {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 . | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
3.10 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Changelog | ||
|
||
## [2.0.0] - 2025-01-16 | ||
### Added | ||
- 初期リリース | ||
- スコア計算ロジックの実装 | ||
- ドキュメントの追加 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)にてお気軽にご投稿ください。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
2.0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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での活動も、(その重みに違いはあれど) 同様に足し算として扱われることになります。 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Oops, something went wrong.