Azure Custom Visionの学習が「Training…」で終わらないときの対処法|REST APIでイテレーション削除と再発防止チェックリスト

Azure Custom Vision でトレーニングを開始したのに、ポータルの表示がいつまでも「Training…」から進まず、学習のやり直しもできない――そんな現場の“詰み”を最短で解消するための実践ガイドです。原因の多くはバックエンド混雑やリソース制約に起因します。本記事は、即効性のある復旧手順(REST API でのイテレーション削除)から再発防止の設計指針まで、運用に耐える具体策を網羅します。

目次

Azure Custom Vision の学習が「Training…」のまま終わらない現象とは

少量画像(例:24 枚)でクイックトレーニングを実行したにもかかわらず、通常は数分で完了する処理が、数時間~数日、場合によってはさらに長い時間、ポータル上は「Training…」のまま進捗しないことがあります。さらに困るのは、進行中イテレーションをキャンセルできず、新しいトレーニングが開始できない点です。スタンダード系のリソース階層や、Advanced(予約)トレーニングの予算 1hでも発生し得ます。

典型的な困りごと

  • ポータルに途中停止ボタンが存在しないため、ぶら下がったイテレーションを止められない。
  • 該当イテレーションを削除できず、新しい学習がブロックされる。
  • 課金がどうなるか不安(予算の上限やキュー待ち中の扱いが不明)。

まず押さえるべき要点(要約)

対処詳細
① 原因の大半はバックエンド混雑/リソース不足高トラフィックやリージョンの一時的なリソース枯渇で、学習ジョブが長時間キュー滞留することがある。
② ポータルからのキャンセルは不可現在、ポータル UI に途中停止機能はない。Advanced(予約)トレーニングの「予算(Reserved Budget)」は上限として機能する。
③ 応急処置:REST API で該当イテレーションを削除DELETE /customvision/v3.3/Training/projects/{projectId}/iterations/{iterationId} を実行して強制削除。新規トレーニングが再び実行可能になる事例が多い(モデルとメトリクスは失われるため、必要に応じて事前エクスポート)。
④ 再発防止のヒント混雑時間帯を避ける/上位 SKU(S 系列のより高い層)や別リージョン活用/画像を分割して小刻みに学習/事前にサービス正常性を確認/継続発生ならサポートに相談。
⑤ サービス状況の読み方一時的なリージョン混雑やメンテナンス、既知のインシデントの影響を受ける場合がある。再試行やリージョン切替で改善することがある。
⑥ 課金面Advanced 予算を設定していれば上限超過課金は抑制される。キュー待機時間は原則計算時間に含まれない。とはいえ、コスト管理で使用量を都度確認するのが安心。

即効性のある復旧:REST API でイテレーションを削除する

最短で現状を打破する方法は、Custom Vision Training API で問題のイテレーションをDELETE することです。削除後は新規トレーニングの実行が可能になります。以下では、安全に特定 → 退避(必要に応じて)→ 削除までを段階的に示します。

前提:必要な情報

  • Endpoint(例:https://<region>.api.cognitive.microsoft.com)
  • Training Key(Training-Key ヘッダーで使用)
  • Project ID(ポータルのプロジェクト設定または API で取得)
  • Iteration ID(該当イテレーションを API で列挙して確認)

ステップ 1:イテレーション一覧を取得し、問題の ID を特定

# 例:環境変数をセット
export ENDPOINT="https://<region>.api.cognitive.microsoft.com"
export TRAINING_KEY="<YOUR_TRAINING_KEY>"
export PROJECT_ID="<YOUR_PROJECT_ID>"

# イテレーション一覧

curl -sS -H "Training-Key: ${TRAINING_KEY}" 
"${ENDPOINT}/customvision/v3.3/Training/projects/${PROJECT_ID}/iterations" | jq '.[] | {id, name, status, created, lastModified}' 

status が Training のまま動かないイテレーションを確認します。必要に応じて 最新の完成済みモデル(Completed) の情報を控えたり、エクスポート対応モデルであれば事前にエクスポートを検討してください(削除するとそのイテレーションのメトリクスやモデルは失われます)。

ステップ 2:イテレーションを削除(強制解除)

export ITERATION_ID="<HUNG_ITERATION_ID>"

# 強制削除

curl -X DELETE -sS -H "Training-Key: ${TRAINING_KEY}" 
"${ENDPOINT}/customvision/v3.3/Training/projects/${PROJECT_ID}/iterations/${ITERATION_ID}" 

削除が成功するとレスポンスは空(204 No Content 相当)または簡素な内容になります。ポータルをリロードし、該当イテレーションが消えていることを確認したら、新規トレーニングを再実行できます。

PowerShell 例

$endpoint     = "https://<region>.api.cognitive.microsoft.com"
$trainingKey  = "<YOUR_TRAINING_KEY>"
$projectId    = "<YOUR_PROJECT_ID>"

# イテレーション一覧

$iterations = Invoke-RestMethod -Headers @{ "Training-Key" = $trainingKey } `  -Uri "$endpoint/customvision/v3.3/Training/projects/$projectId/iterations"`
-Method GET

$iterations | Select-Object id, name, status, created, lastModified | Format-Table

# 問題のイテレーションを削除

$iterationId = ""
Invoke-RestMethod -Headers @{ "Training-Key" = $trainingKey } `  -Uri "$endpoint/customvision/v3.3/Training/projects/$projectId/iterations/$iterationId"`
-Method DELETE 

Python(requests)例

import os, requests

endpoint     = os.getenv("ENDPOINT")
training_key = os.getenv("TRAINING_KEY")
project_id   = os.getenv("PROJECT_ID")
iteration_id = os.getenv("ITERATION_ID")  # 問題のID

headers = {"Training-Key": training_key}

# 確認

r = requests.get(f"{endpoint}/customvision/v3.3/Training/projects/{project_id}/iterations",
headers=headers)
r.raise_for_status()
for it in r.json():
print(it["id"], it["name"], it["status"])

# 削除

d = requests.delete(f"{endpoint}/customvision/v3.3/Training/projects/{project_id}/iterations/{iteration_id}",
headers=headers)
print(d.status_code)  # 204など 

C#(.NET SDK)例

SDK を使うと、CustomVisionTrainingClient で一覧取得や削除が簡潔に書けます。

using Microsoft.Azure.CognitiveServices.Vision.CustomVision.Training;
using Microsoft.Azure.CognitiveServices.Vision.CustomVision.Training.Models;

var endpoint    = "https://.api.cognitive.microsoft.com";
var trainingKey = "";
var projectId   = Guid.Parse("");
var iterationId = Guid.Parse("");

var client = new CustomVisionTrainingClient(
new ApiKeyServiceClientCredentials(trainingKey)) { Endpoint = endpoint };

// 一覧
var iterations = await client.GetIterationsAsync(projectId);
foreach (var it in iterations)
{
Console.WriteLine($"{it.Id} {it.Name} {it.Status}");
}

// 削除
await client.DeleteIterationAsync(projectId, iterationId); 

注意:SDK のバージョンによりメソッド名・名前空間が異なる場合があります。ビルド時の IntelliSense を優先してください。

なぜ「Training…」が長引くのか:技術的背景

想定原因解説対処の方向性
リージョン混雑・キュー滞留同一リージョンにトレーニング要求が集中し、ジョブが長時間キューで待機。UI は「Training…」のまま。時間帯変更(混雑回避)/別リージョンのリソース利用/上位 SKU 検討。
リソース上限・同時実行制約リソースの同時学習枠やスロットが上限に達すると待機が発生。ジョブ分割、小刻み実行、並列度を落とす。古いイテレーションの整理。
データセット構成の重さタグ数/画像数/解像度や前処理により、想定以上に計算量が増える。解像度の適正化、画像の分割投入、タグの整理、ドメイン選択の見直し。
一時的なサービス側障害メンテナンスや障害時、ジョブが停滞・再試行ループに入る可能性。時間を置いて再試行/別リージョン/サポートチケットでの状況確認。

課金の考え方(安心材料と注意点)

  • Advanced(予約)トレーニング:reservedBudgetInHours で指定した予算が上限。その枠を超えて課金が膨らむことは抑制されます。
  • Quick(通常)トレーニング:主に実際の計算時間が課金対象。キュー滞留時間は計算時間に含まれないのが一般的です。
  • いずれの場合も、コスト管理でメーターを確認するのが安全運用。異常値があれば速やかにサポートへ。

再発防止のための運用設計チェックリスト

項目推奨効果
画像投入の粒度一度に大量登録しない。スプリント単位で小刻みに学習。ジョブ時間・失敗時の影響を局所化、キュー滞留の抑制。
リソース階層(SKU)ワークロードに応じて S 系列のより高い層へ拡張を検討。スロット・性能に余裕を持たせ、待機を減らす。
リージョン選択近接性と混雑バランスを考慮。冗長構成として別リージョンを用意。障害/混雑時にフェイルオーバー。
学習スケジュール混雑時間帯(各地域の午前帯など)を回避し夜間バッチ化。待機時間の短縮、成功率の向上。
データ設計解像度・タグ数の適正化。ドメイン選択の見直し。無駄な計算を削減し所要時間を短縮。
イテレーション整備不要なイテレーションを定期削除。命名規約を導入。管理性向上、誤操作や再学習の混乱を防止。
監視とアラートトレーニング時間・コストのしきい値監視。異常の早期検知、迅速な切り戻し。

「削除前に」やっておくと安心なこと

  • モデルの退避:対象イテレーションのエクスポート可否を確認し、可能ならエクスポート。
  • メトリクスの保存:Precision/Recall/mAP 等のスクリーンショットや JSON 取得。
  • 実験ノート:画像セット・タグ変更・ドメインの履歴を残し、再現性を担保。

削除後のリカバリー手順(おすすめのやり直し方)

  1. ポータルをリロードし、ぶら下がりイテレーションが消えたことを確認。
  2. まずは少量(例:10~30 枚)でクイックトレーニングし、動作確認。
  3. 問題が解消していれば、段階的に画像を追加して再学習。必要に応じて Advanced(予算 1~2h から)へ。
  4. 時間帯をずらす・別リージョンで再試を行い、安定性を比較。

Quick と Advanced の使い分けメモ

項目Quick(通常)Advanced(予約)
狙い短時間でモデルの当たりを確認精度追求・ハイパラ探索を含む本格学習
時間/コスト制御短時間・低コスト(ただし混雑の影響を受けやすい)予算(Reserved Budget)で上限管理
詰まり時の対応DELETE で解放→時間帯/リージョン変更DELETE で解放→予算・時間帯・リージョン最適化

トラブル時の深掘り診断ポイント

サブスクリプション/リソースの状態

  • リソースのキーやエンドポイントの誤りがないか(Training と Prediction の取り違え等)。
  • RBAC(アクセス権)やリソース移行直後の整合性問題がないか。

データセットの特性

  • 画像解像度が極端に大きすぎないか(無駄な計算増)。
  • タグが過剰に多くないか、クラス不均衡が極端でないか。
  • ドメイン(General/Compact 等)の選択が用途に合っているか。

学習ジョブの並列度とスケジュール

  • 複数プロジェクトで同時にトレーニングしていないか。
  • 混雑時間帯(多地域の業務時間帯)への投下を避ける。

よくある質問(FAQ)

Q1. ポータルにキャンセルボタンはありますか?
A. 現時点ではポータル UI に途中停止やキャンセルはありません。REST API によるイテレーション削除が実質的な解放手段です。

Q2. 削除すると何が消えますか?
A. そのイテレーションのモデルとメトリクスが失われます。必要であれば事前にエクスポートやメトリクスの保存を行ってください。

Q3. 課金はどうなりますか?
A. Advanced では予算時間が上限として働きます。Quick でもキュー待機自体は計算時間ではないのが一般的です。いずれにせよ、コスト管理でのモニタリングが安心です。

Q4. 別リージョンに作り直すと改善しますか?
A. 一時的な混雑の影響を回避できる場合があります。ベンチマーク的に試す価値があります。

Q5. 画像が少ないのに遅いのはなぜ?
A. 遅さの主要因は計算だけではなくキュー滞留です。画像が少量でも混雑の影響は受けます。

現場で役立つ運用レシピ

レシピ 1:学習パイプラインを“こまめに”回す

  1. 新規画像はバッチサイズ小さめ(例:50~200 枚)で投入。
  2. Quick で当たりを確認 → Advanced で最終精度出し。
  3. 完了イテレーションを命名規約に沿って整理・退避・不要分削除。

レシピ 2:二段リージョン運用

  1. 主力リージョン:通常運用。
  2. 待機リージョン:混雑・障害時のみ切替。API の接続先をパラメータ化。

レシピ 3:自動解放スクリプト

「status == Training で一定時間を超えるイテレーション」を検出したら通知し、承認後に DELETE を流す仕組みを用意しておくと復旧が速くなります。

削除が失敗する/応答が返らない場合のヒント

  • ヘッダーは Training-Key を使用(Prediction-Key と混同しない)。
  • projectId と iterationId は GUID。打ち間違いに注意。
  • ネットワーク経路(プロキシ/ファイアウォール)の制約を確認。
  • 時間を置いて再試行(短時間での連打は避ける)。
  • 最終手段として、新規プロジェクトを作成し学習を移行(データはエクスポート/再インポート)。

サポートに問い合わせるときの情報テンプレート

・発生日時(JST/UTC を明記)
・リージョン(例:japaneast / eastus 等)
・リソース階層(SKU)
・プロジェクト ID と問題のイテレーション ID
・学習種別(Quick / Advanced)と Advanced なら予算時間
・画像枚数/タグ数/ドメイン(General / Compact 等)
・直前の変更(データ追加、タグ変更、ドメイン変更など)
・試した回避策(時間帯変更、別リージョン、DELETE 実行可否)
・課金メーターの状況(異常の有無)

まとめ(運用の勘所)

  • まずは REST API の DELETE で該当イテレーションを解放:これが最短の復旧ルート。
  • 混雑回避・上位 SKU・リージョン分散・小刻み学習で再発を抑止。
  • Advanced 予算で時間上限を明確化し、コストも同時にコントロール。
  • 継続する場合はサービス正常性の確認とサポート相談をセットで。

Custom Vision の学習はクラウドの共同利用資源上で動くため、混雑や制約に左右されます。設計段階で“詰まったら即切り戻すライン”を決め、削除 → 再試行を自動化・標準化しておくと、現場のダウンタイムを最小化できます。


付録:よく使う API エンドポイント早見表(v3.3)

目的HTTPパス(${ENDPOINT} からの相対)備考
プロジェクト一覧GET/customvision/v3.3/Training/projectsProject ID の確認用
イテレーション一覧GET/customvision/v3.3/Training/projects/{projectId}/iterationsstatus / id を確認
イテレーション削除DELETE/customvision/v3.3/Training/projects/{projectId}/iterations/{iterationId}復旧の切り札
学習実行(例)POST/customvision/v3.3/Training/projects/{projectId}/trainAdvanced の場合は { trainingType:"advanced", reservedBudgetInHours: 1 } 等の JSON をボディに指定

付録:学習ジョブが詰まりにくいデータ設計のコツ

  • 画像解像度は用途に応じて適正化(無暗に高解像度にしない)。
  • クラス(タグ)を整理し、極端な不均衡を避ける。
  • 物体検出はアノテーションの質が計算量にも影響。外れ値の除去を徹底。
  • ドメイン選択(General / Compact / 物体検出など)は要件に合致させる。

付録:自動監視サンプル(擬似コード)

/**
 * 擬似コード:長時間 "Training" のイテレーションを検出 → 通知
 */
const THRESHOLD_MIN = 60; // 60分
const iterations = listIterations(projectId); // API 呼び出し
const hung = iterations.filter(it =&gt; it.status === "Training" &amp;&amp; minutesFrom(it.created) &gt; THRESHOLD_MIN);
if (hung.length &gt; 0) {
  notifyOwner(hung);
  // ここで人の承認後に DELETE を実行する運用を推奨
}

最後に

「Training…」で進まない問題は、DELETE による強制解放 → 条件を変えて再挑戦が王道です。運用の設計と自動化を進め、混雑や制約に揺らがない ML ライフサイクルを築いていきましょう。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次