1
0

KaggleのLBとCVで相関のあるデータセットの作り方(Probe)

Posted at

KaggleのLLM系のコンペでは、コンペのホストから提供されるデータがほとんどないor全くない場合が多いです。
そんなとき、サブミッションした時のLB(リーダーボード)のスコアと、手元で検証した時のCVのスコアで相関のあるデータセットが手元に作れれば、よりスコアの改善に役立てることができます。(サブミットによってKaggle側のデータがどのようなものかを探る行為をProbeと呼ぶらしいです)
今回はそのようなデータセットの作り方を紹介しようと思います。

まずは品質をあまり気にせず大量のデータと集める

ChatGPTのAPIなどを利用して大量のデータを作ります。
ただしコンペの参加者の方々が、自分の作ったデータセットを公開してくれることが多いので、それらを拝借するのが手っ取り早いと思います。
なお、この時点でそこまで高い品質のデータは求めていません。
明らかに形式が間違っていたりするようなデータでなければとりあえずOKです。
玉石混交みたいな感じのデータセットになるイメージです。

いくつかのモデルでサブミットをした時のスコアを控えておく

ここでは例として、model_Amodel_Bmodel_Cmodel_Dmodel_Eのような5種類のモデルを使ってそれぞれをサブミットして、そのそれぞれのLBでのスコアを得ることができたとします。
以下のようにして、モデルとそれをサブミットした時のLBのスコアを対にした辞書を作成します。

scores = {
    # key→サブミットした時に使ったモデル
    # value→サブミットした時のスコア
    model_A: 0.71,
    model_B: 0.68,
    model_C: 0.70,
    model_D: 0.68,
    model_E: 0.65
}

集めたデータ群からLBとCVで相関のあるデータ群を抽出する

基本的なアイデアとしては、
「サブミットした時のスコア」と「ローカルデータでのスコア」
の差が小さくなるように、ローカルデータの抽出を繰り返して洗練していくイメージです。

実装例としては以下のようになります。

def fitness(features, targets):
    """
    各モデルでサブミットを行った時のスコアと、
    そのモデルでサンプルデータの推論を行った時のスコアの差の累積値を計算する。
    """
    score_losses = np.array(list(scores.values()))

    # 各モデルで部分集合の推論をした時の損失を計算する。・・・①
    predicts = np.array([model.predict(features) for model in scores.keys()])
    local_scores = metric(np.array(predicts - targets))

    return np.abs(local_scores - score_losses).sum()


def find_best_sample(all_collected_data : pd.DataFrame, sample_size: int = 100, iterations: int = 500):
    """
    集めた全てのデータセット(all_collected_data)の中から、Kaggle側のデータと似ている部分集合を抜き出す。
    """
    best_sub_data = None
    best_loss = float('inf')

    for _ in range(iterations):
        # all_collected_dataからランダムに部分集合(sub_data)を取り出す。
        sample_indices = np.random.choice(len(all_collected_data), sample_size, replace=True)
        sub_data = all_collected_data.loc[sample_indices]
        features = sub_data["特徴量"]
        targets = sub_data["正解"]

        # 上記のfitness関数を使って、部分集合sampleの損失を計算する。
        current_loss = fitness(features, targets)

        # 現在の部分集合の損失が暫定で1番小さくなったら、現在の部分集合をベストなものとして更新する。
        if current_loss < best_loss:
            best_loss = current_loss
            best_sub_data = sub_data
            best_idx = sample_indices

    return best_sub_data, best_loss, best_idx

上のコードについてはここを参考にさせていただきました。

fitness関数の①ではscikit-learnのモデルのインターフェース風に推論を行って損失計算していますが、適宜目的に沿って書き換えれば所望のデータセットを作ることができます。
言うまでもないことですがall_collected_dataもデータフレームである必要はありません。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0