AI: データの基礎

最終更新:2026-08-26

データは AI の燃料です―データがなければ、どんなに優れたアルゴリズムでも有効なモデルを学習できません。この章では、データ型、特徴エンジニアリング、データセット分割、そして「Garbage In, Garbage Out(粗悪な入力は粗悪な出力を生む)」という鉄則を理解します。

1. 学習目標



2. 機械学習プロジェクトの実話

(1) 悩み:1 ヶ月学習して精度が 60%

Bob のチームは 1 ヶ月かけて画像分類モデルを学習しましたが、精度はわずか 60% でした。調査すると、学習データの 70% が晴天の画像で占められており、実世界のシナリオには雨や霧、夜間など多様な天候が含まれていたことが判明しました。モデルがこれらの条件を「見たことがない」ため、当然認識できなかったのです。

(2) データ駆動の解決策

Charlie は言いました。「それは 'Garbage In, Garbage Out' だ―AI は与えたものしか学習できない。アルゴリズムのパラメータを調整するより、まずデータ分布を直すべきだ。」

▶ サンプル:データ分布の確認―偏りの発見(難易度:⭐⭐)

PYTHON
# データ分布の確認 — あらゆる AI プロジェクトの最初のステップ
import pandas as pd

df = pd.DataFrame({
    'weather': ['sunny'] * 70 + ['rainy'] * 15 + ['foggy'] * 10 + ['night'] * 5,
    'label': ['car'] * 50 + ['car'] * 5 + ['car'] * 3 + ['car'] * 2 +
             ['truck'] * 20 + ['truck'] * 10 + ['truck'] * 7 + ['truck'] * 3
})

print("天候の分布:")
print(df['weather'].value_counts())
print(f"\n晴天画像: {70/100*100:.0f}% — これは問題です!")
💻 出力:

TEXT 📖 参照専用
天候の分布:
sunny    70
rainy    15
foggy    10
night     5
Name: weather, dtype: int64

晴天画像: 70% — これは問題です!

(3) 効果:データファーストの考え方

Bob が各天候の画像を追加すると、精度は 60% から 85% に上がりました。彼は一つの鉄則を得ました:「モデルを調整するより、データを調整する方が効果的だ。」



3. データ型

(1) 構造による分類

説明 AI の処理方法
構造化 固定された形式(行と列)がある CSV、SQL テーブル、Excel 伝統的 ML モデルに直接入力
半構造化 部分的に構造化されているが形式は柔軟 JSON、XML、HTML、ログ フィールドを抽出してからモデルに入力
非構造化 固定形式がない 画像、音声、動画、自然言語 深層学習(CNN/RNN/Transformer)

(2) 数値型による分類

説明 モデルの処理
数値型 連続または離散の数値 価格、面積、年齢 そのまま使用
カテゴリ型 有限個の離散値 性別、都市、職業 符号化が必要(One-Hot)
テキスト型 自然言語の文字列 コメント、メール本文 埋め込み(embedding)が必要
時系列型 日付と時刻 注文時刻、ログ時刻 特徴抽出(年/月/時)


4. 特徴とラベル

特徴はモデルへの入力であり、ラベルはモデルが予測するターゲットです。

100%
graph LR
    A[特徴1<br/>面積 120 平方m] --> C[AI モデル]
    B[特徴2<br/>部屋数 4] --> C
    D[特徴3<br/>立地スコア 8] --> C
    C --> E[ラベル<br/>価格 $350,000]

(1) 特徴とは?

特徴とは、データの中で「予測に役立つ」属性です:

データセット 考えられる特徴 ラベル
住宅価格データ 広さ、部屋数、立地評価、階数 物件価格
メールデータ 送信者、キーワード頻度、添付ファイル数 迷惑メールか?
ユーザーデータ 年齢、ページビュー数、購入履歴 購入の可能性
画像データ 画素値(深層学習が自動抽出する特徴) 画像カテゴリ

(2) 特徴エンジニアリング―手動 vs 自動抽出

▶ サンプル:手動特徴エンジニアリング―テキストからの特徴抽出(難易度:⭐⭐)

PYTHON
# 例:手動特徴エンジニアリング
import pandas as pd

df = pd.DataFrame({
    'text': ['Free iPhone winner!', 'Meeting at 3pm', 'URGENT: Claim now'],
    'label': ['spam', 'ham', 'spam']
})

# 手動特徴抽出:特定単語をカウント
df['has_free'] = df['text'].str.lower().str.contains('free').astype(int)
df['has_urgent'] = df['text'].str.lower().str.contains('urgent').astype(int)
df['exclamation_count'] = df['text'].str.count('!')
df['text_length'] = df['text'].str.len()

print(df)
💻 出力:

TEXT 📖 参照専用
                  text label  has_free  has_urgent  exclamation_count  text_length
0  Free iPhone winner!  spam         1           0                  1           19
1     Meeting at 3pm    ham         0           0                  0           14
2  URGENT: Claim now   spam         0           1                  0           17
💡 ヒント: 伝統的 ML は手動の特徴設計(特徴エンジニアリング)を要しますが、深層学習は生データから特徴を自動学習できます。これは深層学習革命の核心的利点の一つです。



5. データセット分割

AI モデルを学習する際、データは互いに排他的な 3 つの集合に分割しなければなりません:

100%
graph TB
    A[全データセット<br/>1000 件] --> B[学習セット<br/>800 件<br/>80%]
    A --> C[検証セット<br/>100 件<br/>10%]
    A --> D[テストセット<br/>100 件<br/>10%]
    
    B --> E[モデルを学習]
    C --> F[ハイパーパラメータを調整]
    D --> G[最終評価<br/>学習中は使用しない]
集合 操作 比率 重要なルール
学習セット モデルを学習(パラメータを学習) 60〜80% モデルはこの集合から直接学習
検証セット ハイパーパラメータ調整(最適構成の選択) 10〜20% モデルに間接的に関与するが直接学習はしない
テストセット 最終評価(報告される性能) 10〜20% 学習中に使用してはならない

(1) Python でのデータ分割

▶ サンプル:学習・検証・テストセットへの分割(難易度:⭐⭐)

PYTHON
# データセットを学習/検証/テストに分割
from sklearn.model_selection import train_test_split
import pandas as pd

# サンプルデータセット
df = pd.DataFrame({
    'area_sqm': [50, 80, 120, 65, 200, 90, 55, 110, 75, 150,
                 60, 85, 130, 95, 180, 70, 100, 45, 140, 105],
    'price_usd': [150000, 280000, 350000, 220000, 500000, 260000,
                  165000, 320000, 240000, 420000, 175000, 270000,
                  380000, 290000, 460000, 210000, 300000, 135000,
                  400000, 310000]
})

# 第 1 分割:80% を学習+検証、20% をテスト
train_val, test = train_test_split(df, test_size=0.2, random_state=42)

# 第 2 分割:train_val の 75% = 全体の 60% 学習、25% = 全体の 20% 検証
train, val = train_test_split(train_val, test_size=0.25, random_state=42)

print(f"全データセット:  {len(df)} 件")
print(f"学習セット:  {len(train)} 件 ({len(train)/len(df)*100:.0f}%)")
print(f"検証セット: {len(val)} 件 ({len(val)/len(df)*100:.0f}%)")
print(f"テストセット:      {len(test)} 件 ({len(test)/len(df)*100:.0f}%)")
💻 出力:

TEXT 📖 参照専用
全データセット:  20 件
学習セット:  12 件 (60%)
検証セット: 4 件 (20%)
テストセット:      4 件 (20%)
⚠️ 注意: テストセットは学習中に絶対に使用してはいけません。モデルがテストセットのデータを「見た」ことがあると、評価結果は客観的でなくなります―まるで試験前に解答を見てしまったように、得点は真の実力を反映しません。



6. データ品質 ― Garbage In, Garbage Out

データ品質は AI 性能の上限を直接決定します。アルゴリズムがどれほど優れていても、粗悪なデータを補うことはできません:

品質問題 説明 影響 検査方法
欠損値 一部のフィールドが空 モデルは欠損入力を処理できない df.isnull().sum()
重複データ 同じレコードが複数回出現 モデルが重複サンプルに過学習 df.duplicated().sum()
クラス不均衡 一つのクラスが他より遥かに多い モデルが多数クラスを優先 df[label].value_counts()
ノイズ/誤り データ値が明らかに不合理 モデルが誤ったパターンを学習 統計的外れ値検出
ラベル付け誤り 不正なラベル付け モデルが誤ったマッピングを学習 手動スポットチェック

(1) データ品質問題の特定

▶ サンプル:データ品質検査レポート(難易度:⭐⭐)

PYTHON
# データ品質チェックリスト
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'age': [25, 30, np.nan, 45, 200, 28, 30, 30, 35, np.nan],
    'income': [50000, 60000, 45000, np.nan, 80000, 55000, 60000, 62000, 70000, 48000],
    'label': ['buy', 'no', 'buy', 'no', 'buy', 'no', 'no', 'no', 'buy', 'no']
})

print("=== データ品質レポート ===")
print(f"総行数: {len(df)}")
print(f"\n列ごとの欠損値:")
print(df.isnull().sum())
print(f"\n重複行: {df.duplicated().sum()}")
print(f"\nラベル分布:")
print(df['label'].value_counts())
print(f"\n不審な値 (age > 120):")
print(df[df['age'] > 120])
💻 出力:

TEXT 📖 参照専用
=== データ品質レポート ===
総行数: 10

列ごとの欠損値:
age       2
income    1
label     0
dtype: int64

重複行: 0

ラベル分布:
no     6
buy    4
Name: label, dtype: int64

不審な値 (age > 120):
   age  income label
4  200   80000   buy
💡 ヒント: age=200 は明らかに不正なデータです。このような外れ値を清掃しないと、モデルは「200 歳の人は購入する」といった不条理なルールを「学習」します。



7. よく使われる公開データセット

AI 実験に自前のデータ収集が必須とは限りません;多くの高品質な公開データセットがすぐに使えます:

データセット タスク サンプル数 特徴
Iris 分類 150 最もシンプルな入門用 ML データセット
Titanic 分類 891 古典的な Kaggle 入門チャレンジ
MNIST 画像分類 70,000 手書き数字、コンピュータビジョン入門
CIFAR-10 画像分類 60,000 10 クラスのカラー画像;MNIST より難易度が高い
California Housing 回帰 20,640 カリフォルニアの住宅価格予測
IMDb Reviews 感情分析 50,000 映画レビューのポジ/ネガ分類


8. 総合例:Titanic データ準備パイプライン

Titanic データセットで、以下の手順を完了します:データ概要 → 欠損値チェック → カテゴリ分布統計 → 学習/テスト分割。これで完全な「データ準備パイプライン」を構成します:

▶ サンプル:Titanic データセットの完全なデータ準備パイプライン(難易度:⭐⭐⭐)

PYTHON
# ============================================
# 完全なデータ準備パイプライン
# データセット: Titanic(シミュレート)
# ============================================
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

# Titanic 風のシミュレートデータセット
np.random.seed(42)
df = pd.DataFrame({
    'pclass': np.random.choice([1, 2, 3], 100, p=[0.2, 0.3, 0.5]),
    'sex': np.random.choice(['male', 'female'], 100, p=[0.6, 0.4]),
    'age': np.where(np.random.rand(100) > 0.15,
                    np.random.randint(1, 80, 100), np.nan),
    'fare': np.round(np.random.uniform(10, 500, 100), 2),
    'survived': np.random.choice([0, 1], 100, p=[0.6, 0.4])
})

# ステップ 1: 概要
print("=== ステップ1: データ概要 ===")
print(f"Shape: {df.shape}")
print(df.head(5))

# ステップ 2: 欠損値
print("\n=== ステップ2: 欠損値 ===")
missing = df.isnull().sum()
missing_pct = (df.isnull().sum() / len(df) * 100).round(1)
print(pd.DataFrame({'count': missing, 'percent': missing_pct}))

# ステップ 3: ラベル分布
print("\n=== ステップ3: ラベル分布 ===")
print(df['survived'].value_counts())
print(f"生存率: {df['survived'].mean()*100:.1f}%")

# ステップ 4: 学習/テスト分割
train, test = train_test_split(df, test_size=0.2, random_state=42,
                                stratify=df['survived'])
print(f"\n=== ステップ4: データ分割 ===")
print(f"学習: {len(train)} 件, 生存率: {train['survived'].mean()*100:.1f}%")
print(f"テスト:  {len(test)} 件, 生存率: {test['survived'].mean()*100:.1f}%")
print(f"\n層化分割により両集合で同じ生存率を確保!")
💻 出力:

TEXT 📖 参照専用
=== ステップ1: データ概要 ===
Shape: (100, 5)
   pclass     sex   age    fare  survived
0       3  female  47.0  339.89         1
1       3  female  63.0  361.38         0
2       1  female  44.0  309.18         0
3       3    male  28.0  385.59         0
4       1    male   8.0  477.95         0

=== ステップ2: 欠損値 ===
         count  percent
pclass       0      0.0
sex          0      0.0
age         14     14.0
fare         0      0.0
survived     0      0.0

=== ステップ3: ラベル分布 ===
0    58
1    42
Name: survived, dtype: int64
生存率: 42.0%

=== ステップ4: データ分割 ===
学習: 80 件, 生存率: 42.5%
テスト:  20 件, 生存率: 40.0%

層化分割により両集合で同じ生存率を確保!

❓ よくある質問

Q データ量が増えると AI は精度が上がりますか? A: 必ずしもそうとは限りません。データ品質は量より重要です。1 万レコードの清潔なデータは、100 万レコードのノイズだらけのデータより優れたモデルを学習させる可能性があります。重要なのはデータ量、品質、多様性、代表性―全てが不可欠です。
A なぜ学習セットとテストセットを重複させてはいけないのですか? A:
Q データ偏りとは何ですか?どう対処しますか? A: データ偏りとは、異なるクラス間でサンプル数に大きな格差があることです(例:正常 99% 対 異常 1%)。解決策:① 少数クラスからより多くのデータを収集;② 少数クラスのオーバーサンプリング(SMOTE);③ 多数クラスのアンダーサンプリング;④ クラス重みの調整;⑤ 評価に正解率ではなく F1 スコアを使用。
A 特徴エンジニアリングとは?なぜ行うのですか? A:
Q 無料のデータセットはどこで見つかりますか? A: Kaggle(kaggle.com/datasets)、UCI Machine Learning Repository、Google Dataset Search、Hugging Face Datasets、政府のオープンデータプラットフォームなど。本チュートリアルは sklearn 付属のデータセットを使用するため、追加ダウンロードは不要です。
A 層化分割(stratified split)とは? A:

📖 まとめ

  • データは AI の燃料;高品質なデータがなければ良いモデルはない―Garbage In, Garbage Out
  • データは 3 つに分類:構造化(表)、半構造化(JSON/XML)、非構造化(画像/テキスト/音声)
  • 特徴はモデルの入力、ラベルはモデルが予測するターゲット;特徴エンジニアリングは伝統的機械学習の核心技術
  • データセットは学習・検証・テストに分割しなければならない;テストセットは学習中に絶対に使用しない
  • データ品質の問題(欠損値、重複、偏り、ノイズ、不正ラベル)は上流工程で解決すべき;モデル学習では悪いデータを直せない
  • 公開データセット(Iris、Titanic、MNIST)は AI 学習を始めるのに最適な場所

📝 練習問題

  1. 基本問題(難易度 ⭐): Python で CSV データセット(または sklearn 付属データセット)を読み込み、df.info()df.describe() で基本情報をまとめなさい。
  2. 応用問題(難易度 ⭐⭐): 欠損値を確認し、データ内のカテゴリ分布を調べ、特定の列のヒストグラムを描きなさい(ヒント:df[column].hist())。
  3. 挑戦問題(難易度:⭐⭐⭐): train_test_split で 80/20 の割合に分割し、標準分割と層化分割でカテゴリ比率が同じになるか比較しなさい。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%