こんにちは。
FindyでMLエンジニアをしているyusukeshimpo(@WebY76755963)です。
今回は直近で公開する「スキル偏差値ver.3」機能について、その内容や具体的な機械学習モデルの作成方法について紹介します。
Findyのスキル偏差値とは?
スキル偏差値の概要
まずはプロダクトの概要を説明いたします。
「スキル偏差値」は、Findyに登録されているユーザーのGitHubリポジトリ(※Open-access repositoryのみ)を解析し、 コミット量、OSSプロジェクトへの貢献度、他者からのコードの支持などに基づいて技術力をスコアリングする機能です。
GitHubの解析は機械学習技術を用いて実施しており、これまでに何度かアルゴリズムや学習データのアップデートを行ってきましたが、 今回は2017年のリリース以降で最も大幅なリニューアルを行なっており、大元のアルゴリズムや学習データの作り方自体をガラッと変更しています。
アップデートすることになった背景
アップデートの背景には、大きく分けて2つの理由が存在します。
- リリースから数年が経過する中でユーザーの方からの要望が増えてきたから。
- 特に「言語別」のスコアに対する要望が強く、言語別のスキル判定の精度改善を求めるニーズが強かったため。
- 2023年以降、LLMやAI Agentが登場し、エンジニアリング(特にコーディング)の領域でも、それが当たり前に使われるようになってきたから。
- 今後エンジニアに求められる「スキル」も環境に合わせて変わっていくことが予想される中で、よりサービス開発や運用に直結する能力を評価できるモデルに進化させていく必要があったため。
上記「ユーザーボイス」と「開発を取り巻く環境変化」を受けて、このタイミングで新たな「スキル偏差値」を作ることを決めました。
スキルの見える化する、スキル偏差値ver.3の詳細
今回のスキル偏差値の開発では次の3つの手順でスキルの見える化をしています。
- 学習データの作成
- ランキング学習
- 学習モデルによるスコアリング
この3つの手順について詳しく解説します。
1.学習データの作成
ランキング学習を支えるのは「質の高いデータ」です。
GitHubリポジトリから収集したデータを加工し、言語ごとに特徴量を整備することで、正確なモデル構築を目指しました。
1-1.使用言語ごとのデータ準備
GitHubリポジトリを次の主要言語ごとに分類しました。
- Python
- JavaScript
- TypeScript
- Go
- Ruby
- PHP
各言語ごとで重視される特徴量に違いがあり、言語ごとにデータを分ける方針にしました。
1-2.ペアワイズ形式のデータ構築
ランキング学習するために、今回は「ペアワイズ形式」のデータを用意しました。これは、2つのエンティティ間でどちらが優れているかを比較する形式です。
今回のケースではGitHubユーザー間のリポジトリ情報を比較し、相対的なスキル勝敗データを生成しました。また、ペアはバイアスが生まれないようにランダムでペアを作るようにしています。
1-3.勝敗アノテーションの付与
生成したペアデータに対して、上の図のようにスキルの「勝敗」をラベリングしました。
特にラベル基準をある程度明確化しておくと担当者間でのクロスレビューの際の議論がまとまりやすかったです。
2.ランキング学習
次に、上で用意した学習データに対して、次の2つのステップを経て、「ランキング学習」の手法を用いて特徴量間の比較します。
「ランキング学習」(Learning to Rank)は、複数ある事象の「順位」を目的変数とした場合に用いられる機械学習の手法で、身近な例としては「検索エンジン」などで使われています。
機械学習を用いた「ランキング学習」の実装にはいくつか方法がありますが、今回は上述したペアワイズなデータ間の「勝敗」を学習し、
2-1.ペアワイズデータの特徴量生成
2-2.機械学習モデルによる勝敗予測
以下、それぞれのステップを解説していきます。
2-1.ペアワイズデータの特徴量生成
ランキング学習するために、まずは各々のデータを機械が認識できる形にする必要があります。
具体的には、各データを「特徴化」し、ベクトル化した数値で比較できるようにしています。
当初はこの「特徴」抽出のプロセスについては、言語を問わずある程度一元化できると考えていましたが、 実験過程で、言語間の「特徴」に大きな違いが見られました。
詳細は社外秘情報にあたるため公開できませんが、一例として、ある言語では「Readmeなどのテキストの長さ」が重要な意味を持ちます。 別の言語だとボイラープレート内にReadme用のテキストが充実しているため「Readmeの長さ」を特徴として重視しない方が好ましい、という傾向が出ていました。
上記のように、言語ごとに利用者を取り巻く環境が大きく違う点も考慮し、現段階では「言語ごとに異なる特徴を採用する」という意思決定をしています。
2-2.機械学習モデルによる勝敗予測
データを特徴化したら、機械学習モデルによるランキング学習をし、当該データ間の順位を予測します。
検討初期にはより複雑なモデルを利用することも検討しましたが、「言語ごとに個別のモデルを動かす」という仕様上の制約や、特徴抽出の工夫によりシンプルなモデルでも十分な精度が実現できたため採用しています。
上記のアルゴリズムにペアワイズの学習データとその勝敗を学習させ、勝敗の判定を行なっています。
モデルの精度についてはこちらも非公開ですが、検証方法としてはこちらも「複数人が判断した際の判断と同様の出力(=勝敗)を出せるか」を基準に評価しています。
リリース時点で、対象としている6言語はいずれも人間の判断を8割以上の精度で模倣できており、一定正確なジャッジができていると判断しています。
3.モデルによるスコアリング
学習モデルを作成したら、その推論結果を元にユーザーのスキルをスコアリングしていきます。
学習したのは、ペアワイズデータの勝敗ですので、計算したいユーザーと他のユーザーとの勝敗をシミュレーションして、それを元にユーザーのスキルスコアを算出します。
このスコアを一般的に偏差値計算をする数式に当てはめ、最後に調整(言語ごとに異なる尺度を正規化するなど)をしたものを「スキル偏差値」としています。
実装で苦労した点と解決策
上記を実装する上で困難な点が多々ありました。
今回は次の苦労した点と解決としてどんなことをしたかも説明していきます。
- モデル精度の担保
- 言語ごとの特徴量
1.モデル精度の担保
アノテーションしたデータを使用しているので、モデルはアノテータに影響を受けます。
アノテータのバイアスを極力抑えて客観的に良いモデルを作成するための工夫が必要だったため、次の工夫をすることで精度改善を試みました。
アノテーションの工夫
データ作成時のアノテーションには次のような手順を導入しました。
- 言語経験者による判断: 経験者がアノテーションをすることで正確性を担保
- ラベル基準の明確化: ラベル基準を言語化してアノテータに共有
- クロスレビュー: 複数人がレビューすることでバイアスを極力抑える
例として、社内でRubyを日常的に利用する有識者へアノテーションの基準づくりを依頼しました。筆者は普段の業務でRubyを使用しないため、このように経験者から合意を得ることで、より良質な正解データを作成できました。
評価設計
アノテーションという定性的な評価を学習データにしているため、ただ単に評価関数の良し悪しで判断できません。
そんな中どのようにモデルの精度を評価したのかも非常に重要かつ難しいポイントでした。
そこで、アノテーションとモデルの精度を担保するために定性と定量の両方で確認しました。
- 定量評価: 正解率や偏差値の分布を測定
- 定性評価: 偏差値の妥当性を人間が確認
勝敗の正解率を確認したのち、Ratingや偏差値を実際に算出しますが、正規分布に基づいているか、ユーザーはこの数値で妥当かを定性的に評価しました。
これによるアノテーション結果の正当性を確保しつつ、モデルの方向性も正しいと確認できました。実際には次のサイクルでモデル評価とアウトプット評価をして都度アノテーションから見直すこともしました。
2.言語固有の特徴量設計
また、言語ごとに特徴量設計をするのも苦労したポイントです。同じ特徴量では表現できなかったため、言語ごとに最適な特徴量設計を見つける必要がありました。
言語特徴の言語化をしてデータ化
言語ごとにどんな特徴を持っているのかを言語化し異なる特徴を設計しました。
例えば、あるプログラミング言語ではボイラーテンプレートが充実しているため独自ロジックにスキルが出やすい傾向にあったり、ライブラリの利活用が盛んなプログラミング言語など特徴量が変わってくることがわかりました。
この特徴量の言語化のフローは大きく4つのポイントに分かれます。 まず、仮説の立案し、各言語の特性を調査し、スキルの違いを反映するための特徴を言語ごとに仮説立てを行います。その後実験を重ねて、仮説に基づいて特徴量を作成し、推論結果や評価指標を確認します。 確認した結果に違和感があれば、仮説を見直して新たな特徴量を追加・修正します。これらを繰り返し、最後に評価基準と実際の結果にズレがあれば、特徴量の設計を見直し、適正化という流れを繰り返しました。
最後に
以上がスキル偏差値の開発についてでした。参考にしていただければ幸いです。
また、弊社では機械学習エンジニア・データエンジニアなど一緒に働いてくれるメンバーを募集しております。
興味がある方は↓からご応募していただければと思います。