🦔
天気予報で学ぶ「情報量」と「クロスエントロピー」〜中学生でもわかる機械学習の基礎【第1回】〜
天気予報で学ぶ「情報量」と「クロスエントロピー」〜中学生でもわかる機械学習の基礎【第1回】〜
はじめに
こんにちは!今日は「情報量」と「クロスエントロピー」という、データサイエンスでとっても大切な概念を、Pythonを使って楽しく学んでいきましょう!
「えっ、難しそう...」と思った人も大丈夫!天気予報やサイコロ、ガチャゲームなど、身近な例を使って説明するので、中学生でも理解できます🎯
なぜこれを学ぶの?
AIや機械学習では、「予測がどれくらい正確か」を数値で表す必要があります。その時に使うのが今日学ぶ概念です!
例えば:
- YouTubeのおすすめ動画
- 天気予報アプリ
- ゲームのガチャ確率
これらはすべて「確率」と「情報」を使っています。
1. 情報量ってなに?〜驚きを数値化しよう!〜
身近な例で考えてみよう
# 必要なライブラリをインポート
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# 日本語フォントの設定(グラフで日本語を使うため)
plt.rcParams['font.family'] = 'DejaVu Sans'
想像してください:
- 「今日の給食はカレーだよ」(毎週金曜はカレー = 確率100%)
- 「今日は臨時休校だよ」(めったにない = 確率1%)
どっちが驚きますか?もちろん2番ですよね!
情報量を計算してみよう
def calculate_information(probability):
"""
情報量を計算する関数
確率が低いほど情報量は大きくなる!
"""
if probability == 0:
return float('inf') # 無限大
return -np.log2(probability)
# いろいろな確率で情報量を計算
events = {
"給食がカレー(金曜日)": 1.0,
"晴れ(夏)": 0.8,
"コイン投げで表": 0.5,
"サイコロで6": 1/6,
"宝くじ1等": 0.000001
}
print("【情報量の比較】")
print("-" * 40)
for event, prob in events.items():
info = calculate_information(prob)
print(f"{event}: {info:.2f} ビット")
視覚的に見てみよう
# 確率と情報量の関係をグラフ化
probabilities = np.linspace(0.01, 1, 100)
information = [-np.log2(p) for p in probabilities]
plt.figure(figsize=(10, 6))
plt.plot(probabilities, information, linewidth=3, color='blue')
plt.xlabel('確率', fontsize=14)
plt.ylabel('情報量(ビット)', fontsize=14)
plt.title('確率が低いほど情報量は大きい!', fontsize=16)
plt.grid(True, alpha=0.3)
plt.axhline(y=1, color='red', linestyle='--', label='1ビット(コイン投げ)')
plt.legend()
plt.show()
2. 実際に問題を解いてみよう!
問題1:いろいろな確率の情報量
def solve_problem1():
"""問題1の解答をPythonで実装"""
# (1) P(A) = 0.8 のとき
p1 = 0.8
i1 = calculate_information(p1)
print(f"(1) 確率80%の情報量: {i1:.3f} ビット")
# (2) P(A) = 0.5 のとき
p2 = 0.5
i2 = calculate_information(p2)
print(f"(2) 確率50%の情報量: {i2:.3f} ビット")
# 比較のために他の確率も計算
print("\n【おまけ:他の確率との比較】")
other_probs = [0.9, 0.1, 0.01]
for p in other_probs:
print(f"確率{p*100}%の情報量: {calculate_information(p):.3f} ビット")
solve_problem1()
3. クロスエントロピー〜予想の下手さを測ろう!〜
天気予報士の例
def cross_entropy(true_dist, predicted_dist):
"""
クロスエントロピーを計算する関数
true_dist: 本当の確率分布
predicted_dist: 予想した確率分布
"""
ce = 0
for i in range(len(true_dist)):
if predicted_dist[i] > 0: # log(0)を避ける
ce -= true_dist[i] * np.log2(predicted_dist[i])
return ce
# 問題2を解いてみよう
print("【問題2:天気予報の精度】")
print("-" * 40)
# 真の分布(実際の天気)
true_weather = [0.5, 0.5] # [晴れ, 雨]
print("実際の天気: 晴れ50%, 雨50%")
# 予報士の予想
prediction = [0.9, 0.1] # [晴れ, 雨]
print("予報士の予想: 晴れ90%, 雨10%")
# クロスエントロピーを計算
ce = cross_entropy(true_weather, prediction)
print(f"\nクロスエントロピー: {ce:.3f} ビット")
# 完璧な予想の場合
perfect_prediction = [0.5, 0.5]
perfect_ce = cross_entropy(true_weather, perfect_prediction)
print(f"完璧な予想の場合: {perfect_ce:.3f} ビット")
print(f"予想の悪さ: {ce - perfect_ce:.3f} ビット分")
いろいろな予報士を比較してみよう!
# 複数の予報士を比較
forecasters = {
"完璧な予報士": [0.5, 0.5],
"楽観的な予報士": [0.9, 0.1],
"悲観的な予報士": [0.1, 0.9],
"普通の予報士": [0.6, 0.4],
"最悪の予報士": [1.0, 0.0]
}
results = []
for name, prediction in forecasters.items():
ce = cross_entropy(true_weather, prediction)
results.append({
"予報士": name,
"晴れ予想": f"{prediction[0]*100}%",
"雨予想": f"{prediction[1]*100}%",
"クロスエントロピー": round(ce, 3)
})
# データフレームで見やすく表示
df = pd.DataFrame(results)
df = df.sort_values("クロスエントロピー")
print("\n【予報士ランキング】")
print(df.to_string(index=False))
グラフで可視化
# 予報士の成績を棒グラフで表示
plt.figure(figsize=(10, 6))
names = df["予報士"].values
scores = df["クロスエントロピー"].values
bars = plt.bar(names, scores, color=['green', 'lightgreen', 'yellow', 'orange', 'red'])
plt.ylabel('クロスエントロピー(低いほど良い)', fontsize=12)
plt.title('天気予報士の成績比較', fontsize=16)
plt.xticks(rotation=45)
# 1ビットのラインを追加
plt.axhline(y=1, color='blue', linestyle='--', alpha=0.5)
plt.text(0, 1.05, '理論的最小値(1ビット)', fontsize=10)
plt.tight_layout()
plt.show()
4. 実践!ガチャゲームで学ぶ情報理論
def gacha_information():
"""ガチャの当たりやすさと情報量の関係"""
gacha_rates = {
"★★★★★ (激レア)": 0.003, # 0.3%
"★★★★ (レア)": 0.03, # 3%
"★★★ (やや珍しい)": 0.15, # 15%
"★★ (普通)": 0.35, # 35%
"★ (よくある)": 0.467 # 46.7%
}
print("【ガチャの情報量】")
print("-" * 50)
for rarity, rate in gacha_rates.items():
info = calculate_information(rate)
print(f"{rarity}: 確率{rate*100:.1f}% → {info:.2f}ビットの驚き!")
# シミュレーション
print("\n【10連ガチャシミュレーション】")
np.random.seed(42) # 結果を再現可能にする
rarities = list(gacha_rates.keys())
probabilities = list(gacha_rates.values())
total_info = 0
for i in range(10):
result = np.random.choice(rarities, p=probabilities)
info = calculate_information(gacha_rates[result])
total_info += info
print(f"{i+1}回目: {result} (情報量: {info:.2f}ビット)")
print(f"\n合計情報量: {total_info:.2f}ビット")
print(f"平均情報量: {total_info/10:.2f}ビット")
gacha_information()
5. 機械学習での活用例
def ml_example():
"""機械学習でクロスエントロピーを使う例"""
# 画像認識の例(犬・猫・鳥の3クラス分類)
print("【AIの画像認識】")
print("-" * 40)
# 正解ラベル(これは猫の画像)
true_label = [0, 1, 0] # [犬, 猫, 鳥]
# AIの予測
ai_predictions = {
"自信満々AI": [0.1, 0.8, 0.1],
"迷っているAI": [0.3, 0.4, 0.3],
"間違えたAI": [0.7, 0.2, 0.1],
"完全に外したAI": [0.0, 0.0, 1.0]
}
print("正解: 猫の画像\n")
for ai_name, pred in ai_predictions.items():
ce = cross_entropy(true_label, pred)
print(f"{ai_name}:")
print(f" 予測 - 犬:{pred[0]*100:.0f}%, 猫:{pred[1]*100:.0f}%, 鳥:{pred[2]*100:.0f}%")
print(f" クロスエントロピー: {ce:.3f}ビット")
print()
ml_example()
まとめ
今日学んだことを整理しましょう!
📊 情報量
- 確率が低い = 情報量が大きい(驚きが大きい)
- 確率が高い = 情報量が小さい(驚きが小さい)
- 計算式:
I = -log2(確率)
🎯 クロスエントロピー
- 予測の下手さを測る指標
- 値が小さい = 予測が上手
- 値が大きい = 予測が下手
💡 実世界での応用
- AI/機械学習の精度評価
- データ圧縮
- 通信の効率化
- ゲームバランスの設計
次のステップ
- 練習問題を作ってみよう:自分の好きなゲームやスポーツの確率で情報量を計算してみましょう
- データ収集:実際の天気データを集めて、天気予報の精度を測ってみましょう
- 機械学習入門:簡単な画像認識や文字認識に挑戦してみましょう
最後まで読んでいただきありがとうございました!
この記事が面白かった・役に立ったと思ったら、ぜひ「いいね」をお願いします🎉
質問やコメントもお待ちしています!
Discussion