☁️

SIGNATE×GitHub Actionsでローカル環境なしのクラウドML実践ガイド

に公開

はじめに

SIGNATEのコンペティションに参加したいけど、ローカルPCのスペックが心もとない——そんな方に向けて、GitHub Actionsだけで完結する機械学習パイプラインの構築方法を紹介します。

データのダウンロードから前処理、モデル学習、SIGNATEへの提出まで、すべてクラウドで行います。

SIGNATE CLI (GitHub Actions)
    ↓ データダウンロード
前処理 + LightGBM学習
    ↓ 推論
提出ファイル生成
    ↓ signate submit
SIGNATEに自動提出

メリット:

  • ローカルPCのスペックに依存しない(RAM 4GBでもOK)
  • git push → 自動で学習&提出できる
  • 実行環境がubuntu-latestで統一される

前提条件

  • GitHubアカウント
  • SIGNATEアカウント(メール&パスワード認証)
  • Python環境(CLIインストール用、ローカルで一度だけ使用)

Step 1: SIGNATE CLIをインストール

pip install signate

Step 2: APIトークンを取得

以下のコマンドで ~/.signate/signate.json が自動生成されます。

signate token --email=your-email@example.com --password=your-password

成功すると以下のメッセージが表示されます:

The API Token has been downloaded successfully.

Step 3: コンペのtask_keyとfile_keyを確認

SIGNATE CLIでコンペのファイル一覧を確認します。

signate file-list --task_key <task_key>

task_key はコンペURLのパラメータから取得できます:

https://user.competition.signate.jp/ja/competition/detail/?...&task=ここがtask_key

実行結果の例:

public_key                        file_name          file_size
--------------------------------  -----------------  -----------
5f0e1ebb35af4963b1720557d31daf35  train.csv          482.43 KB
72f23ebe8f004fa0b35323c4f744e8c5  test.csv           476.92 KB
ad3502af26b94d5aad4785351f36aa7b  sample_submit.csv  84.86 KB

public_key がダウンロード時に使う file_key になります。


Step 4: GitHubリポジトリを作成

mkdir signate-comp && cd signate-comp
git init

.gitignore を作成(データファイルはgit管理しない):

data/
__pycache__/
*.pyc
.signate/

Step 5: SIGNATEトークンをGitHub Secretsに登録

トークンをBase64エンコードしてSecretに保存します。GitHub Secretsはトークン内の文字列をマスクすることがあるため、Base64エンコードが必要です。

# Base64エンコード
python -c "
import base64
with open('$HOME/.signate/signate.json', 'r') as f:
    token = f.read().strip()
print(base64.b64encode(token.encode()).decode())
"

出力されたBase64文字列をGitHub Secretsに登録します:

# リポジトリ作成(private推奨)
gh repo create your-username/signate-comp --private --source=. --push

# Secret登録
gh secret set SIGNATE_TOKEN_B64 --body "<Base64文字列>"

Step 6: GitHub Actionsワークフローを作成

.github/workflows/submit.yml を作成します:

name: Train & Submit

on:
  workflow_dispatch:
    inputs:
      memo:
        description: "Submission memo"
        required: false
        default: "GitHub Actions submission"

jobs:
  submit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: pip install pandas numpy scikit-learn lightgbm signate

      - name: Setup SIGNATE token
        run: |
          mkdir -p ~/.signate
          echo '${{ secrets.SIGNATE_TOKEN_B64 }}' | base64 -d > ~/.signate/signate.json

      - name: Download data
        run: |
          mkdir -p data
          cd data
          signate download --task_key <your_task_key> --file_key <train_file_key>
          signate download --task_key <your_task_key> --file_key <test_file_key>

      - name: Train and predict
        run: python train.py

      - name: Submit to SIGNATE
        run: |
          signate submit data/submission.csv \
            --task_key <your_task_key> \
            --memo "${{ github.event.inputs.memo }}"

      - name: Upload submission as artifact
        uses: actions/upload-artifact@v4
        with:
          name: submission
          path: data/submission.csv
          retention-days: 90

ポイント:

  • workflow_dispatch で手動トリガー(メモ付き)
  • Base64デコードでトークン復元
  • signate downloadtrain.pysignate submit の一気通貫
  • Artifactにも提出ファイルを保存(後から確認可能)

Step 7: 学習スクリプトを作成

train.py の例(LightGBM 5-fold CV):

import pandas as pd
import numpy as np
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import roc_auc_score
import lightgbm as lgb

def main():
    train = pd.read_csv("data/train.csv")
    test = pd.read_csv("data/test.csv")

    # --- 前処理(コンペに応じて実装) ---
    # train = preprocess(train)
    # test = preprocess(test)

    target = "ProdTaken"  # ターゲット列名
    features = [c for c in train.columns if c not in ["id", target]]
    X, y = train[features], train[target]
    X_test = test[features]

    # --- LightGBM 5-fold CV ---
    params = {
        "objective": "binary",
        "metric": "auc",
        "verbosity": -1,
        "n_estimators": 1000,
        "learning_rate": 0.05,
        "random_state": 42,
    }

    skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
    oof_preds = np.zeros(len(X))
    test_preds = np.zeros(len(X_test))

    for fold, (tr_idx, val_idx) in enumerate(skf.split(X, y)):
        model = lgb.LGBMClassifier(**params)
        model.fit(
            X.iloc[tr_idx], y.iloc[tr_idx],
            eval_set=[(X.iloc[val_idx], y.iloc[val_idx])],
            callbacks=[lgb.early_stopping(50), lgb.log_evaluation(0)],
        )
        oof_preds[val_idx] = model.predict_proba(X.iloc[val_idx])[:, 1]
        test_preds += model.predict_proba(X_test)[:, 1] / 5
        print(f"Fold {fold+1}: AUC = {roc_auc_score(y.iloc[val_idx], oof_preds[val_idx]):.5f}")

    print(f"Overall OOF AUC: {roc_auc_score(y, oof_preds):.5f}")

    # --- 提出ファイル作成(ヘッダなし) ---
    submission = pd.DataFrame({"id": test["id"], "pred": test_preds})
    submission.to_csv("data/submission.csv", index=False, header=False)
    print(f"Saved: data/submission.csv ({len(submission)} rows)")

if __name__ == "__main__":
    main()

Step 8: 実行する

GitHub Actions画面から手動実行するか、CLIで実行します:

gh workflow run submit.yml -f memo="Baseline LightGBM v1"

実行状況の確認:

gh run list --limit 1

ログの確認:

gh run view <run_id> --log

SIGNATE CLI コマンド早見表

コマンド 説明
signate token --email=xxx --password=xxx APIトークン取得
signate file-list --task_key <key> ファイル一覧表示
signate download --task_key <key> --file_key <key> データダウンロード
signate submit <file> --task_key <key> --memo <memo> 提出

ハマりポイントと対策

1. GitHub Secretsのトークンマスキング

現象: Invalid header value エラーで認証失敗

原因: GitHub SecretsがJWTトークン内の文字列をマスク(***に置換)してしまう

対策: Base64エンコードしてSecretに保存し、ワークフロー内でデコードする

2. --path オプションの挙動

現象: [Errno 21] Is a directory エラー

原因: signate download --path data/ のようにディレクトリを指定すると失敗する

対策: cd data && signate download ... のように、カレントディレクトリを変更してからダウンロードする

3. GitHub Actions無料枠

GitHub Freeプランでは月2,000分の実行時間があります。小〜中規模のデータセットなら十分です。1回の学習&提出に約40秒程度なので、余裕を持って運用できます。


まとめ

SIGNATE CLI + GitHub Actionsで、ローカル環境に依存しない機械学習パイプラインを構築しました。

git push → GitHub Actions → データDL → 学習 → 提出

この仕組みがあれば、低スペックPCでも、スマホからでも、コードをpushするだけでコンペに参加できます。


関連記事

この記事の手順をCLIで自動化するツールを作りました:

参考リンク

GitHubで編集を提案

Discussion