Azure Machine Learningのデータアセットでpropertiesが保存されない原因と対処法(tags設計・サイドカー運用まで完全解説)

Azure Machine Learning(Azure ML)のデータアセットにYAMLでproperties:を書いたのに登録後は空になる――この「なぜ?」に明確な答えと、今日から現場で実践できる回避策・設計指針・運用パターンをまとめて解説します。CLIやYAMLのサンプル、検索クエリ、CI/CDへの組み込み例まで網羅し、メタデータを“失わない”ための実践ガイドとしてご活用ください。

目次

事象の要約

YAMLファイルに任意のメタデータをproperties:として記述し、az ml data create -f <file>.ymlでデータアセットを登録しても、az ml data showで確認するとpropertiesは空のままです。これは書式ミスやシステム予約キーの衝突ではなく、サービス仕様によってデータアセットのカスタムpropertiesが保存対象外になっているために発生します(2025年11月時点)。

症状

  • dataアセットのYAMLにproperties:を記述しても、登録後のaz ml data show出力では空。
  • 同じキーをtagsとpropertiesに二重に書いてもエラーにはならないが、返却値のpropertiesは空。
  • CLIバージョンやフォーマット、予約語の問題ではない。

再現手順(最小例)

name: demo_hr_dataset
version: 1
type: uri_file
description: "社員データ(学習用)"
path: azureml://datastores/wsdstore/paths/hr/hr-data.csv
# 保存されない(data assetでは無視される)
properties:
  source_system: HR
  pii_scan: passed
# 保存される
tags:
  meta.source_system: HR
  meta.pii_scan: passed

登録と確認:

# 登録
az ml data create -f data_asset.yml

# 確認(tagsだけが保持されていることを確認)

az ml data show -n demo_hr_dataset --version 1 --output yaml 

結論(仕様と設計方針)

データアセット(data asset)では、カスタムpropertiesは現在保存されません。そのため、任意メタデータを維持・検索・自動化に活用したい場合は、以下のいずれか(または併用)で設計します。

  1. tagsに格納する(推奨・第一候補)
  2. descriptionにJSONなどで埋め込む(軽量・補助)
  3. 別資産やサイドカー(補助)ファイルで管理する(構造化や大型メタデータ)

実務で使える回避策

1. tagsに格納する(最有力)

もっとも扱いやすく、CLI/SDK/ポータルのいずれでも閲覧・検索・フィルタが容易です。キーにmeta.などのプレフィックスを付け、命名規約と用途を明確にします。

name: hr_train_dataset
version: 2
type: uri_file
description: "人事データのトレーニング用抽出(2025-Q3)"
path: azureml://datastores/prod/paths/hr/train/hr-data.csv
tags:
  meta.resolvedDataPath: azureml://datastores/prod/paths/hr/train/hr-data.csv
  meta.source_system: HR
  meta.owner: [email protected]
  meta.pii_scan: passed
  meta.schema_version: "1.2.0"

登録・更新・閲覧の基本コマンド:

# 新規登録
az ml data create -f hr_train_dataset.yml

# 一覧(主要フィールドのみ表示)

az ml data list --query "[].{name:name,ver:version,type:type,tags:tags}" -o table

# 詳細(YAML)

az ml data show -n hr_train_dataset --version 2 -o yaml

# タグの追加・上書き(その場で)

az ml data update -n hr_train_dataset --version 2 --set tags.meta.reviewed_by=mlops@example 

よく使う検索クエリ例(JMESPath):

# HRシステム由来のデータアセットだけ抽出
az ml data list --query "items[?tags.'meta.source_system'=='HR'].[name,version,tags]" -o tsv

# PIIスキャン合格の最新版だけ

az ml data list --query "items[?tags.'meta.pii_scan'=='passed'] | reverse(sort_by(@,&version)) | [].{name:name,version:version}" -o table

# オーナー単位で棚卸し

az ml data list --query "items[?contains(tags.'meta.owner','data-platform')].[name,version]" -o table 

メリット

  • 登録後も確実に保持・表示される。
  • フィルタ・集計・自動化(スクリプト)との相性がよい。
  • 小さく始めて拡張しやすい。

留意点

  • キー/値はシンプルな文字列で設計する(巨大な構造体は避ける)。
  • 命名規約(meta.<領域>.<項目> など)をチームで統一する。

2. descriptionにJSON等を埋め込む(補助策)

タグでは表現しづらい階層や配列を、軽量に持たせたい場合に有効です。検索性はタグに劣るため、タグ+説明JSONの併用を推奨します。

description: |
  HRデータ(トレーニング用)。抽出ルールは sidecar JSON を参照。
  {
    "owner": "[email protected]",
    "lineage": {
      "src_datastore": "prod",
      "src_path": "hr/train/hr-data.csv",
      "transforms": ["drop_na", "encode_job_level"]
    },
    "quality": {
      "pii_scan": "passed",
      "null_ratio": 0.3
    }
  }

スクリプト側でdescriptionを取得し、JSON部分を抽出して利用できます。

3. 別資産やサイドカー(補助ファイル)を使う

より厳密なスキーマや大型のメタデータ、監査証跡を扱う場合は、データストアにサイドカーJSONを置き、データアセットからタグでひも付けるのが堅実です。あるいはpropertiesをサポートする別種アセット(例: model / environment)でメタ情報を管理し、データアセットとは相互参照する設計も選択肢になります。

# サイドカー例(/paths/hr/train/hr-data.meta.json)
{
  "schema_version": "1.2.0",
  "dq_report_uri": "azureml://datastores/prod/paths/hr/train/reports/dq_2025Q3.html",
  "pii_scan_artifact": "azureml://datastores/prod/paths/hr/train/reports/pii_scan_2025Q3.json",
  "slack_channel": "#ml-data-hr",
  "approvers": ["alice", "bob"]
}

データアセットのタグ:

tags:
  meta.sidecar_uri: azureml://datastores/prod/paths/hr/train/hr-data.meta.json
  meta.dq_report_uri: azureml://datastores/prod/paths/hr/train/reports/dq_2025Q3.html

比較表:どこに何を入れるべき?

保管場所向いている情報検索性構造表現規模想定用途
tagsキー=値の属性(例:owner、system、schema_version、pii_scan)◎(CLI/ポータルで容易)△(平坦。配列/階層は非推奨)小〜中検索・フィルタ・自動化の主軸
description補助的な詳細、JSONスニペット、注意事項△(全文検索は困難)◯(自由記述で表現可能)小〜中人間向けの文脈+軽量な構造の併記
サイドカーJSON大きいメタデータ、レポートURI、配列・階層・監査証跡◯(タグでURIを索引化)◎(完全自由)中〜大厳密なスキーマ、監査、外部連携
別アセット(model/env)アーティファクト単位の厳密メタ(properties活用)◯◎中アセスメントや承認ワークフローと連動

運用パターン別・設計ガイド

  • クイック検索が最優先:tags中心。meta.<領域>.<項目>で命名を統一。
  • 人が読む説明も必要:タグで索引、descriptionにJSON+説明文を併記。
  • 監査・長期保存・外部連携:タグは索引に専念、本文はサイドカーJSONへ。
  • 厳密なスキーマが必須:別アセットのpropertiesも活用し、データアセットから参照。

YAML/CLI 実例(そのまま使えるテンプレート)

テンプレート:データアセット定義

name: {{project}}_{{domain}}_dataset
version: {{semver}}
type: uri_folder  # or uri_file / mltable
description: |
  {{domain}}ドメインの学習用データセット。
  {
    "owner": "{{team_mail}}",
    "schema_version": "{{schema_ver}}",
    "lineage": {
      "src_datastore": "{{datastore}}",
      "src_path": "{{path}}"
    }
  }
path: azureml://datastores/{{datastore}}/paths/{{path}}
tags:
  meta.domain: "{{domain}}"
  meta.owner: "{{team_mail}}"
  meta.schema_version: "{{schema_ver}}"
  meta.sidecar_uri: "azureml://datastores/{{datastore}}/paths/{{path}}.meta.json"

登録・更新・検索

# 登録
az ml data create -f dataset.yml

# タグの一括付与(パッチ的に)

az ml data update -n {{project}}_{{domain}}_dataset --version {{semver}} 
--set tags.meta.lifecycle=prod tags.meta.pii_scan=passed

# 最新版のみ一覧

az ml data list --name {{project}}_{{domain}}_dataset --query "max_by(items,&version)" 

CI/CDへの組み込み(GitHub Actions例)

name: register-data-asset
on:
  push:
    paths:
      - "assets/data/**.yml"
jobs:
  register:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: azure/login@v2
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
      - name: Azure ML CLI install
        run: pip install azure-ai-ml azure-identity
      - name: Validate YAML (naming &amp; required tags)
        run: |
          python scripts/validate_tags.py assets/data
      - name: Register
        run: |
          for f in assets/data/*.yml; do
            az ml data create -f "$f"
          done

ベストプラクティス

  • 必須タグ(meta.owner、meta.schema_version、meta.source_systemなど)を静的解析で検査。
  • スキーマ(JSON Schema)でサイドカーJSONを検証し、PR時に失敗させる。
  • 命名規約(プロジェクト・ドメイン・用途・semver)をREADMEに明文化。

トラブルシューティング

  • propertiesが空のまま:仕様です。tags等の代替策へ設計変更。
  • タグが反映されない:YAMLのインデント/引用符/エンコードを再確認。数値は文字列化(例:"1.2.0")。
  • 検索でヒットしない:JMESPathのキー名にドットがある場合、tags.'meta.schema_version'のように引用。
  • 巨大なJSONを入れたい:タグではなくサイドカーJSONに退避し、URIだけタグに保持。

監査と可観測性:クエリ集

# 直近30日で作成/更新のデータアセット
az ml data list --query "items[?to_number(substring(updatedOn,0,10)) >=`date +%s`-30*24*3600]"

# ドメイン別の最新バージョン一覧

az ml data list --query "items | sort_by(@,&[name,version]) | reverse(@) | 
[].{name:name,version:version,domain:tags.'meta.domain'}" -o table

# サイドカーレポートURIが欠落している資産

az ml data list --query "items[?!tags.'meta.sidecar_uri'].[name,version]" -o table 

よくある質問(FAQ)

Q. propertiesは今後サポートされますか? A. 仕様は将来変わる可能性があります。設計はタグ中心にしつつ、将来propertiesが使えるようになった場合の移行手順(タグ→プロパティの同期スクリプト)を用意しておくと安心です。

<dt>Q. タグキーの命名はどう決めればよいですか?</dt>
<dd>A. <code>meta.&lt;領域&gt;.&lt;項目&gt;</code>の3階層(例:<code>meta.quality.pii_scan</code>)を推奨。英小文字・数字・アンダースコア・ハイフン・ドットに限定すると運用が安定します。</dd>

<dt>Q. 同じ情報をタグと説明の両方に書いても良い?</dt>
<dd>A. 問題ありません。検索性の高いタグを“正”とし、説明には読み物や補足JSONを載せる方針が実務上扱いやすいです。</dd>

<dt>Q. データ品質レポートなど成果物のURIはどこに?</dt>
<dd>A. タグに<code>meta.dq_report_uri</code>などのキーで保持し、実体はデータストアのHTML/JSONに置くのが管理しやすいです。</dd>

<dt>Q. 既存資産を新方針へ揃えるには?</dt>
<dd>A. 一括移行スクリプトで<code>az ml data list</code>→タグ欠落検出→<code>az ml data update</code>の反復を自動化します。移行前後で一覧を差分比較し、監査ログを保存しましょう。</dd>

チェックリスト(貼って使える)

  • [必須]meta.owner/meta.source_system/meta.schema_versionを付与したか。
  • [必須]サイドカーURI(必要時)をmeta.sidecar_uriに設定したか。
  • [推奨]descriptionに簡潔な説明+最小限のJSONを併記したか。
  • [推奨]CIでタグの必須性・形式・重複を検証しているか。
  • [推奨]クエリ(JMESPath)をチーム標準化し、定期棚卸しを自動化しているか。

サンプル:移行・同期スクリプト(概念例)

# 目的:旧来のdescription内JSONの一部をタグに昇格させる
# 方針:descriptionからowner/schema_versionを抽出→tagsへ反映

#!/usr/bin/env python3
import json, subprocess

def list_assets():
out = subprocess.check_output(["az","ml","data","list","-o","json"])
return json.loads(out)

def show_asset(name, version):
out = subprocess.check_output(["az","ml","data","show","-n",name,"--version",str(version),"-o","json"])
return json.loads(out)

def update_tag(name, version, key, value):
subprocess.check_call(["az","ml","data","update","-n",name,"--version",str(version),"--set",f"tags.{key}={value}"])

for it in list_assets().get("items",[]):
name, ver = it["name"], it["version"]
detail = show_asset(name, ver)
desc = detail.get("description","")
try:
payload = json.loads(desc[desc.index("{"):desc.rindex("}")+1])
except Exception:
continue
owner = payload.get("owner")
schema = payload.get("schema_version")
if owner:
update_tag(name, ver, "meta.owner", owner)
if schema:
update_tag(name, ver, "meta.schema_version", schema) 

ベストプラクティス(要点)

  • タグ主導:検索・自動化に強い。URIや可観測性の要点をタグで索引化。
  • 説明は読み物+最小JSON:ヒトが理解しやすい文脈を提供。
  • サイドカーで拡張:大きい・複雑なメタは外出しし、規約で結合。
  • CIで強制:レビュー任せにしない。必須タグ・スキーマ・命名規約を自動検査。
  • 将来変化への余白:将来propertiesが有効化されても移行可能な同期スクリプトを用意。

まとめ

データアセットのpropertiesは現在保存されません。任意メタデータはtagsで保持し、必要に応じてdescriptionにJSONを併記、またはサイドカーJSONで構造化・拡張しましょう。設計の肝は「索引はタグ、本文はサイドカー」。この分離により、検索・自動化・監査のすべてがシンプルになります。

付録:コピペ用スニペット

最小YAML(タグ中心)

name: gmatheus01rmlwhrmodel_train_dataset
version: 1
type: uri_file
description: "学習用HRデータ"
path: azureml://datastores/wsdstore/paths/hr-data.csv
tags:
  meta.resolvedDataPath: azureml://datastores/wsdstore/paths/hr-data.csv
  meta.source_system: HR

登録・確認

az ml data create -f data_asset.yml
az ml data show -n gmatheus01rmlwhrmodel_train_dataset --output yaml

棚卸しクエリ(代表例)

az ml data list --query "items[?tags.'meta.source_system']=='HR'].[name,version,tags]" -o table

この記事を書いた人

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

コメント

コメントする

目次