ストーリー
田
田中VPoE
データガバナンスの全体像は理解できたな。では次の問題だ。「このデータは品質が高い」と言われたとき、何を根拠にそう判断する?
田
田中VPoE
正確性は品質の一面に過ぎない。たとえば住所データが100%正確でも、30%の顧客に住所が入っていなければ、それは「品質が高い」と言えるか?
あなた
完全性も重要ですね。他にもいろいろな観点がありそうです
あ
田
田中VPoE
その通り。データ品質には6つの次元がある。さらにAIでは従来にない品質要件も加わる。バイアスの検出、データドリフト、ラベルの品質 — これらを体系的に管理する方法を学ぼう
データ品質の6つの次元
基本の6次元
| 次元 | 英語名 | 定義 | AI活用での影響 |
|---|
| 正確性 | Accuracy | データが現実を正しく反映しているか | モデルの予測精度に直結 |
| 完全性 | Completeness | 必要なデータが欠損なく存在するか | 欠損値がモデルのバイアスを生む |
| 一貫性 | Consistency | 異なるシステム間でデータが矛盾していないか | 学習データの矛盾が学習を阻害 |
| 適時性 | Timeliness | データが十分に新しいか | 古いデータでのRAGは不正確な回答を生成 |
| 有効性 | Validity | データが定められたルール・形式に従っているか | パイプラインのエラー原因 |
| 一意性 | Uniqueness | 重複データが存在しないか | 重複は学習データのバイアスを増幅 |
各次元の測定方法
from dataclasses import dataclass
from typing import Optional
@dataclass
class DataQualityMetrics:
"""データ品質の6次元を測定する"""
# 正確性: 既知の正解データとの一致率
accuracy_score: float # 0.0 - 1.0
# 完全性: NULL/欠損でないレコードの割合
completeness_score: float # 0.0 - 1.0
# 一貫性: システム間で矛盾のないレコードの割合
consistency_score: float # 0.0 - 1.0
# 適時性: 鮮度基準を満たすレコードの割合
timeliness_score: float # 0.0 - 1.0
# 有効性: バリデーションルールに適合するレコードの割合
validity_score: float # 0.0 - 1.0
# 一意性: 重複のないレコードの割合
uniqueness_score: float # 0.0 - 1.0
@property
def overall_score(self) -> float:
"""加重平均による総合品質スコア"""
weights = {
"accuracy": 0.25,
"completeness": 0.20,
"consistency": 0.20,
"timeliness": 0.15,
"validity": 0.10,
"uniqueness": 0.10,
}
return (
self.accuracy_score * weights["accuracy"]
+ self.completeness_score * weights["completeness"]
+ self.consistency_score * weights["consistency"]
+ self.timeliness_score * weights["timeliness"]
+ self.validity_score * weights["validity"]
+ self.uniqueness_score * weights["uniqueness"]
)
測定例
顧客データ品質レポート
┌────────────┬───────┬─────────────────────┐
│ 次元 │ スコア │ 基準 │
├────────────┼───────┼─────────────────────┤
│ 正確性 │ 0.92 │ 住所照合サービスで検証 │
│ 完全性 │ 0.87 │ 必須フィールドの充足率 │
│ 一貫性 │ 0.78 │ CRM-DWH間の不一致率 │
│ 適時性 │ 0.95 │ 24h以内更新の割合 │
│ 有効性 │ 0.99 │ スキーマ適合率 │
│ 一意性 │ 0.96 │ 重複検出率 │
├────────────┼───────┼─────────────────────┤
│ 総合スコア │ 0.91 │ AI利用基準: 0.80以上 │
└────────────┴───────┴─────────────────────┘
AI向けデータ品質の特殊要件
従来のデータ品質に加え、AIシステムには固有の品質要件があります。
1. バイアス検出
from typing import Dict, List
def detect_demographic_bias(
dataset: list[dict],
target_column: str,
sensitive_columns: list[str],
) -> dict[str, dict]:
"""
データセットの人口統計バイアスを検出する
Args:
dataset: 分析対象データセット
target_column: 予測対象のカラム
sensitive_columns: 保護属性のカラム(性別、年齢層等)
Returns:
各保護属性ごとのバイアスメトリクス
"""
bias_report: dict[str, dict] = {}
for col in sensitive_columns:
# 各グループの分布を計算
group_distributions = {}
for record in dataset:
group = record[col]
target = record[target_column]
if group not in group_distributions:
group_distributions[group] = {"positive": 0, "total": 0}
group_distributions[group]["total"] += 1
if target == 1: # positive class
group_distributions[group]["positive"] += 1
# Disparate Impact Ratio の計算
rates = {
g: d["positive"] / d["total"]
for g, d in group_distributions.items()
if d["total"] > 0
}
if rates:
min_rate = min(rates.values())
max_rate = max(rates.values())
disparate_impact = min_rate / max_rate if max_rate > 0 else 0
bias_report[col] = {
"group_rates": rates,
"disparate_impact_ratio": disparate_impact,
"is_biased": disparate_impact < 0.8, # 4/5ルール
}
return bias_report
| バイアスの種類 | 説明 | 検出方法 |
|---|
| 選択バイアス | サンプルが母集団を代表していない | 人口統計との分布比較 |
| 測定バイアス | 特定グループでデータ品質が低い | グループ別欠損率の分析 |
| ラベルバイアス | アノテーションに偏りがある | アノテーター間一致率の計測 |
| 歴史的バイアス | 過去の差別が反映されている | 保護属性と結果の相関分析 |
| 表現バイアス | 特定グループの過小・過大表現 | Disparate Impact Ratio |
2. データドリフト検出
from scipy import stats
import numpy as np
def detect_data_drift(
reference_data: np.ndarray,
current_data: np.ndarray,
threshold: float = 0.05,
) -> dict:
"""
KS検定によるデータドリフトの検出
Args:
reference_data: ベースライン(学習時)のデータ分布
current_data: 現在のデータ分布
threshold: p値の閾値
Returns:
ドリフト検出結果
"""
ks_statistic, p_value = stats.ks_2samp(reference_data, current_data)
return {
"ks_statistic": ks_statistic,
"p_value": p_value,
"drift_detected": p_value < threshold,
"severity": (
"HIGH" if ks_statistic > 0.2
else "MEDIUM" if ks_statistic > 0.1
else "LOW"
),
"recommendation": (
"モデルの再学習を推奨"
if p_value < threshold
else "現行モデルで継続可能"
),
}
| ドリフトの種類 | 説明 | 監視方法 |
|---|
| データドリフト | 入力データの分布変化 | KS検定、PSI(Population Stability Index) |
| コンセプトドリフト | 入力と出力の関係変化 | モデル精度の時系列監視 |
| ラベルドリフト | 正解ラベルの分布変化 | ラベル分布の定期チェック |
3. ラベル品質
| 指標 | 計算方法 | 基準値 |
|---|
| Inter-Annotator Agreement | Cohen’s Kappa / Fleiss’ Kappa | >= 0.8 |
| ラベルエラー率 | サンプル抽出による再ラベリング | < 5% |
| ラベルカバレッジ | ラベル付きデータ / 全データ | 用途による |
| クラスバランス | 最大クラス / 最小クラスの比率 | < 10 |
データプロファイリングと品質スコアリング
データプロファイリングのプロセス
# データプロファイリング実行定義
data_profiling:
schedule: "daily at 02:00 JST"
targets:
- dataset: "customer_profile"
checks:
- type: "completeness"
columns: ["name", "email", "phone"]
threshold: 0.95
- type: "uniqueness"
columns: ["customer_id", "email"]
threshold: 0.999
- type: "validity"
rules:
email: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
phone: "^\\d{2,4}-\\d{2,4}-\\d{4}$"
threshold: 0.98
- type: "freshness"
column: "updated_at"
max_age: "24h"
- type: "statistical"
columns: ["age", "purchase_amount"]
checks: ["mean", "stddev", "min", "max", "percentiles"]
- dataset: "product_catalog"
checks:
- type: "completeness"
columns: ["product_id", "name", "price", "description"]
threshold: 0.99
- type: "consistency"
cross_reference:
source: "product_catalog.category_id"
target: "category_master.id"
threshold: 1.0
品質スコアリングの自動化
Great Expectations を用いた品質チェックの実装例です。
import great_expectations as gx
# データコンテキストの作成
context = gx.get_context()
# Expectation Suite の定義
suite = context.add_expectation_suite("customer_data_quality")
# 品質ルールの定義
expectations = [
# 完全性
{
"type": "expect_column_values_to_not_be_null",
"kwargs": {"column": "customer_id"},
},
{
"type": "expect_column_values_to_not_be_null",
"kwargs": {"column": "email", "mostly": 0.95},
},
# 有効性
{
"type": "expect_column_values_to_match_regex",
"kwargs": {
"column": "email",
"regex": r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
"mostly": 0.98,
},
},
# 一意性
{
"type": "expect_column_values_to_be_unique",
"kwargs": {"column": "customer_id"},
},
# 範囲チェック
{
"type": "expect_column_values_to_be_between",
"kwargs": {"column": "age", "min_value": 0, "max_value": 150},
},
# 参照整合性
{
"type": "expect_column_values_to_be_in_set",
"kwargs": {
"column": "status",
"value_set": ["active", "inactive", "suspended"],
},
},
]
データクレンジング戦略
クレンジングのレベル
| レベル | 内容 | 手法例 | リスク |
|---|
| Level 1: 検出 | 問題のあるレコードを特定 | プロファイリング、異常値検出 | 低 |
| Level 2: 除外 | 問題レコードを除外して利用 | フィルタリング、サンプリング | データ量減少 |
| Level 3: 修正 | 問題を自動/手動で修正 | 正規化、欠損値補完、名寄せ | 誤修正リスク |
| Level 4: 強化 | 外部データで品質を向上 | エンリッチメント、照合 | コスト、依存性 |
AI向けクレンジングのベストプラクティス
class AIDataCleansingPipeline:
"""AI向けデータクレンジングパイプライン"""
def execute(self, dataset):
# Step 1: 重複除去
dataset = self.deduplicate(dataset, strategy="fuzzy_matching")
# Step 2: 欠損値処理
dataset = self.handle_missing(
dataset,
strategy="domain_aware", # ドメイン知識に基づく補完
# AI学習用は「欠損」を明示するのが安全
# 安易な平均値補完はバイアスを生む
)
# Step 3: 異常値処理
dataset = self.handle_outliers(
dataset,
method="isolation_forest",
action="flag", # 削除ではなくフラグを付ける
)
# Step 4: 正規化
dataset = self.normalize(
dataset,
text_columns=["description", "comment"],
# Unicode正規化、全角半角統一
)
# Step 5: PII検出とマスキング
dataset = self.detect_and_mask_pii(
dataset,
pii_types=["email", "phone", "name", "address"],
)
# Step 6: バイアスチェック
bias_report = self.check_bias(
dataset,
sensitive_columns=["gender", "age_group", "region"],
)
return dataset, bias_report
データ品質SLOの設定方法
SLOの設計原則
| 原則 | 説明 | 例 |
|---|
| ユーザー影響に基づく | AIの出力品質に影響する指標を選ぶ | RAG精度が90%以上 → データ完全性95%以上 |
| 測定可能 | 自動計測できる指標にする | 品質スコアを日次で自動算出 |
| 段階的に引き上げ | 現状+αの目標から始める | 完全性80% → 85% → 90% |
| エラーバジェット連動 | SLO違反時の対応を定義する | 品質スコアが基準を3日連続で下回ったら改善タスクを起票 |
データ品質SLOの設定例
data_quality_slos:
customer_profile:
target: "AI推薦エンジンの精度維持"
slos:
- metric: "overall_quality_score"
target: 0.85
window: "7d rolling"
error_budget: "7日間で品質スコアが基準を下回る日数 <= 1日"
- metric: "completeness"
target: 0.95
columns: ["name", "email", "purchase_history"]
window: "daily"
- metric: "freshness"
target: "< 24h"
column: "updated_at"
window: "daily"
- metric: "bias_score"
target: "disparate_impact_ratio >= 0.8"
sensitive_columns: ["gender", "age_group"]
window: "monthly"
alerts:
- condition: "overall_quality_score < 0.80"
severity: "critical"
action: "RAGパイプラインを一時停止し、データスチュワードに通知"
- condition: "completeness < 0.90"
severity: "warning"
action: "データエンジニアに改善チケット起票"
- condition: "bias_score.disparate_impact_ratio < 0.8"
severity: "critical"
action: "AI利用を停止し、データオーナーに即座にエスカレーション"
品質ダッシュボードの構成
┌──────────────────────────────────────────────┐
│ データ品質ダッシュボード │
├──────────────────────────────────────────────┤
│ │
│ 総合品質スコア: 87/100 [===========---] │
│ │
│ ┌─────────────────┬─────────────────┐ │
│ │ 正確性: 92% ✓ │ 完全性: 87% ▲ │ │
│ ├─────────────────┼─────────────────┤ │
│ │ 一貫性: 78% ▼ │ 適時性: 95% ✓ │ │
│ ├─────────────────┼─────────────────┤ │
│ │ 有効性: 99% ✓ │ 一意性: 96% ✓ │ │
│ └─────────────────┴─────────────────┘ │
│ │
│ AI固有指標: │
│ ├ バイアススコア: 0.85 (DI ratio) ✓ │
│ ├ ドリフト: 未検出 ✓ │
│ └ ラベル品質 (Kappa): 0.82 ✓ │
│ │
│ SLO状態: 7日間エラーバジェット残: 86% │
│ │
└──────────────────────────────────────────────┘
まとめ
| ポイント | 内容 |
|---|
| 品質の6次元 | 正確性、完全性、一貫性、適時性、有効性、一意性 |
| AI固有の品質要件 | バイアス検出、データドリフト、ラベル品質 |
| プロファイリング | 定期的なデータプロファイリングで品質を可視化 |
| クレンジング | 検出→除外→修正→強化の段階的アプローチ |
| 品質SLO | ユーザー影響に基づく定量的な品質目標の設定 |
チェックリスト
次のステップへ
次は「プライバシーとコンプライアンス」を学びます。AIシステムにおける個人情報保護と法規制対応の実践的な方法を深掘りしましょう。
推定読了時間: 30分