読み込み中...

Pythonを使った平均二乗誤差の基礎知識と活用10選

平均二乗誤差 徹底解説 Python
この記事は約38分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●Pythonで平均二乗誤差(MSE)をマスターしよう!

今回は、データサイエンスの重要な指標である平均二乗誤差(MSE)について深掘りしていきます。

MSEは、モデルの予測精度を評価する上で欠かせない道具です。

簡単に言えば、予測値と実際の値がどれくらい離れているかを数値化したものなんです。

○MSEの定義と重要性

平均二乗誤差、略してMSE。

聞き慣れない言葉かもしれませんが、実はとてもシンプルな概念です。

予測値と実際の値の差を二乗し、その平均を取ったもの。

それだけです。

でも、なぜこの指標がそんなに大切なのでしょうか?

理由は明快です。

MSEは、モデルの予測がどれだけ外れているかを教えてくれます。大きな誤差は二乗されるので、より重視されます。

つまり、大きく外れた予測に対して厳しい評価を下すんです。これにより、モデルの改善点が明確になります。

○平均二乗誤差の数式

数式を見てみましょう。

怖がる必要はありません。とてもシンプルですから。

MSE = Σ(y_pred - y_true)^2 / n

ここで、y_predは予測値、y_trueは実際の値、nはデータポイントの数です。

Σは合計を表します。

この数式、見た目は複雑そうに見えるかもしれません。

でも、実際にやっていることは、予測と現実の差を二乗して、全部足して、データの数で割るだけなんです。

簡単でしょう?

○誤差が教えてくれる機械学習の真実

MSEは単なる数字ではありません。

モデルの性能を映し出す鏡なんです。

低いMSEは、モデルが現実をうまく捉えていることを表します。

高いMSEは、改善の余地があることを教えてくれます。

例えば、住宅価格の予測モデルを作ったとします。

MSEが高ければ、予測価格と実際の価格に大きな乖離があることを意味します。

これは、モデルに何か問題があるサインかもしれません。

特徴量の選択が適切でないかもしれませんし、もしかしたらモデル自体を変える必要があるかもしれません。

MSEを通じて、モデルの弱点を見つけ、改善していく。

これが機械学習の醍醐味なんです。

●Pythonで簡単MSE計算!

さて、理論は分かったけど、実際にどうやってMSEを計算するの?

心配無用です。

Pythonを使えば、驚くほど簡単にMSEを計算できます。

今から3つの方法を紹介します。

どれも素晴らしい方法ですが、状況に応じて使い分けるのがコツです。

○サンプルコード1:numpyで高速MSE計算

まずは、numpyを使った方法です。

numpyは数値計算のためのライブラリで、大量のデータを高速に処理できます。

import numpy as np

# サンプルデータ
y_true = np.array([3, -0.5, 2, 7])
y_pred = np.array([2.5, 0.0, 2, 8])

# MSEの計算
mse = np.mean((y_true - y_pred)**2)

print(f"Mean Squared Error: {mse}")

実行結果

Mean Squared Error: 0.375

このコードでは、実際の値(y_true)と予測値(y_pred)をnumpy配列として定義しています。

そして、(y_true – y_pred)**2で各点での誤差の二乗を計算し、np.mean()でその平均を取っています。

たった1行でMSEが計算できてしまうんです。

素晴らしいでしょう?

○サンプルコード2:scikit-learnでMSE算出

次は、機械学習の定番ライブラリ、scikit-learnを使う方法です。

scikit-learnには、様々な評価指標が用意されています。

MSEもその一つです。

from sklearn.metrics import mean_squared_error
import numpy as np

# サンプルデータ
y_true = np.array([3, -0.5, 2, 7])
y_pred = np.array([2.5, 0.0, 2, 8])

# MSEの計算
mse = mean_squared_error(y_true, y_pred)

print(f"Mean Squared Error: {mse}")

実行結果

Mean Squared Error: 0.375

scikit-learnのmean_squared_error関数を使えば、簡単にMSEを計算できます。

この方法の利点は、他の評価指標と一緒に使いやすいことです。

scikit-learnには他にも多くの評価指標があるので、モデルの性能を多角的に評価したい場合に便利です。

○サンプルコード3:ゼロから実装するMSE関数

最後に、MSEをゼロから実装する方法です。

自分で実装することで、MSEの仕組みをより深く理解できます。

import numpy as np

def calculate_mse(y_true, y_pred):
    """
    平均二乗誤差(MSE)を計算する関数

    Parameters:
    y_true (array-like): 実際の値
    y_pred (array-like): 予測値

    Returns:
    float: 計算されたMSE
    """
    y_true = np.array(y_true)
    y_pred = np.array(y_pred)

    # 予測値と実際の値の差を計算
    errors = y_pred - y_true

    # 誤差を二乗
    squared_errors = errors ** 2

    # 平均を取る
    mse = np.mean(squared_errors)

    return mse

# サンプルデータ
y_true = [3, -0.5, 2, 7]
y_pred = [2.5, 0.0, 2, 8]

# MSEの計算
mse = calculate_mse(y_true, y_pred)

print(f"Mean Squared Error: {mse}")

実行結果

Mean Squared Error: 0.375

この方法では、MSEの計算プロセスを一つ一つ丁寧に実装しています。

予測値と実際の値の差を計算し、それを二乗し、最後に平均を取っています。

この方法は、MSEの内部動作を理解するのに役立ちます。

●MSEとRMSE/似て非なる2つの指標

機械学習の評価指標の世界は広大で、時に混乱を招くこともあります。

特に、MSE(平均二乗誤差)とRMSE(二乗平均平方根誤差)は、非常によく似た指標ですが、微妙に異なる特性を持っています。

両者の違いを理解することは、モデルの性能を正確に評価し、適切な改善策を講じる上で極めて重要です。

○RMSEとは?MSEとの違いを解説

RMSEは、MSEの平方根を取ったものです。

簡単に言えば、MSEに√をつけただけ。

でも、この小さな違いが、大きな意味を持つんです。

RMSEの最大の特徴は、元のデータと同じ単位で表現されること。

例えば、家の価格を予測するモデルを作っているとしましょう。

MSEは「円の二乗」という、直感的に理解しづらい単位になってしまいます。

一方、RMSEなら「円」という、元のデータと同じ単位で誤差を表現できるんです。

さらに、RMSEは外れ値に対してMSEよりも敏感です。

大きな誤差がある場合、RMSEの方がより顕著にその影響を反映します。

○MSE vs RMSE

では、どちらを使うべきでしょうか?

答えは「場合による」です。

MSEは、数学的な扱いやすさが魅力です。

微分が簡単なので、勾配降下法などの最適化アルゴリズムと相性が良いんです。

また、二乗することで、正負の誤差を同等に扱えるという利点もあります。

一方、RMSEは解釈のしやすさが強みです。

元のデータと同じ単位なので、モデルの性能を直感的に理解しやすい。

例えば、「平均して約1000円の誤差がある」といった具合に。

結局のところ、両方を計算して、状況に応じて使い分けるのがベストプラクティスです。

どちらか一方に固執せず、柔軟に対応することが大切です。

○サンプルコード4:PythonでMSEとRMSEを比較

理論を学んだところで、実際にPythonでMSEとRMSEを計算して比較してみましょう。

scikit-learnとnumpyを使って、簡単に両方の指標を計算できます。

import numpy as np
from sklearn.metrics import mean_squared_error

# サンプルデータ
y_true = np.array([3, -0.5, 2, 7])
y_pred = np.array([2.5, 0.0, 2, 8])

# MSEの計算
mse = mean_squared_error(y_true, y_pred)

# RMSEの計算
rmse = np.sqrt(mse)

print(f"Mean Squared Error (MSE): {mse}")
print(f"Root Mean Squared Error (RMSE): {rmse}")

実行結果

Mean Squared Error (MSE): 0.375
Root Mean Squared Error (RMSE): 0.6123724356957945

MSEからRMSEを計算するには、単純に平方根を取るだけです。

np.sqrt()関数を使えば、一瞬で計算できます。

結果を見ると、MSEは0.375、RMSEは約0.612となっています。

RMSEの方が値が大きいことがわかります。

RMSEは誤差の「平均的な大きさ」を元のデータと同じ単位で表現しているため、直感的に理解しやすいですね。

●機械学習モデルでのMSE活用術

さて、MSEとRMSEの違いを理解したところで、実際の機械学習モデルでMSEをどう活用するか見ていきましょう。

MSEは単なる数字ではありません。モデルの性能を評価し、改善するための羅針盤なんです。

○サンプルコード5:モデル評価にMSEを使う

まずは、線形回帰モデルを例に、MSEを使ってモデルを評価する方法を見てみましょう。

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import numpy as np

# サンプルデータの生成
np.random.seed(42)
X = np.random.rand(100, 1)
y = 2 + 3 * X + np.random.randn(100, 1) * 0.1

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデルの訓練
model = LinearRegression()
model.fit(X_train, y_train)

# 予測
y_pred = model.predict(X_test)

# MSEの計算
mse = mean_squared_error(y_test, y_pred)

print(f"Mean Squared Error: {mse}")

実行結果

Mean Squared Error: 0.009947018555687173

このコードでは、まず人工的なデータを生成し、それを訓練データとテストデータに分割しています。

LinearRegressionモデルを訓練し、テストデータで予測を行った後、MSEを計算しています。

得られたMSEは約0.00995です。

この値自体は、データの特性やモデルの性質によって変わるので、絶対的な良し悪しを判断するのは難しいです。

むしろ、他のモデルや異なるハイパーパラメータでの結果と比較することで、相対的な性能を評価するのが一般的です。

○サンプルコード6:MSEで過学習を防ぐ

MSEは過学習(オーバーフィッティング)を検出するのにも役立ちます。

訓練データとテストデータのMSEを比較することで、モデルが過学習していないか確認できるんです。

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import numpy as np

# サンプルデータの生成
np.random.seed(42)
X = np.random.rand(100, 1)
y = 2 + 3 * X + np.random.randn(100, 1) * 0.1

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデルの訓練
model = LinearRegression()
model.fit(X_train, y_train)

# 訓練データでの予測と評価
y_train_pred = model.predict(X_train)
train_mse = mean_squared_error(y_train, y_train_pred)

# テストデータでの予測と評価
y_test_pred = model.predict(X_test)
test_mse = mean_squared_error(y_test, y_test_pred)

print(f"Training MSE: {train_mse}")
print(f"Test MSE: {test_mse}")

実行結果

Training MSE: 0.010431471714771616
Test MSE: 0.009947018555687173

このコードでは、訓練データとテストデータの両方でMSEを計算しています。

理想的には、両者の値が近いことが望ましいです。

訓練データのMSEが著しく小さく、テストデータのMSEが大きい場合、過学習の兆候かもしれません。

今回の結果では、訓練MSEとテストMSEがほぼ同じ値になっています。

つまり、このモデルは過学習していない可能性が高いと言えます。

○サンプルコード7:学習曲線の可視化

最後に、MSEを使って学習曲線を描画する方法を見てみましょう。

学習曲線は、訓練データ量とモデルの性能の関係を可視化するもので、過学習や過少学習を診断するのに役立ちます。

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import learning_curve
from sklearn.metrics import mean_squared_error
import numpy as np
import matplotlib.pyplot as plt

# サンプルデータの生成
np.random.seed(42)
X = np.random.rand(1000, 1)
y = 2 + 3 * X + np.random.randn(1000, 1) * 0.1

# 学習曲線の計算
train_sizes, train_scores, test_scores = learning_curve(
    LinearRegression(), X, y, cv=5, scoring='neg_mean_squared_error',
    train_sizes=np.linspace(0.1, 1.0, 10))

# MSEに変換(scikit-learnは負のMSEを返すため)
train_scores_mse = -train_scores
test_scores_mse = -test_scores

# 平均と標準偏差の計算
train_scores_mean = np.mean(train_scores_mse, axis=1)
train_scores_std = np.std(train_scores_mse, axis=1)
test_scores_mean = np.mean(test_scores_mse, axis=1)
test_scores_std = np.std(test_scores_mse, axis=1)

# プロット
plt.figure(figsize=(10, 6))
plt.title("Learning Curves")
plt.xlabel("Training examples")
plt.ylabel("Mean Squared Error")
plt.grid()

plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
                 train_scores_mean + train_scores_std, alpha=0.1, color="r")
plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
                 test_scores_mean + test_scores_std, alpha=0.1, color="g")
plt.plot(train_sizes, train_scores_mean, 'o-', color="r", label="Training score")
plt.plot(train_sizes, test_scores_mean, 'o-', color="g", label="Cross-validation score")

plt.legend(loc="best")
plt.show()

このコードは、異なるサイズの訓練データセットでモデルを訓練し、それぞれのMSEを計算しています。

結果はグラフとして可視化されます。

学習曲線を解釈する際は、訓練スコアと交差検証スコアの両方に注目します。

両者が近づいていけば、モデルが十分に学習できていると判断できます。

逆に、訓練スコアが著しく良く、交差検証スコアが悪い場合は過学習の兆候かもしれません。

●MSEとMAE・どちらを選ぶ?

MSE(平均二乗誤差)とMAE(平均絶対誤差)は、よく比較される二大指標です。

両者の特徴を理解し、適切に選択することは、モデルの性能を正確に評価し、適切な改善策を講じる上で極めて重要です。

○サンプルコード8:MAEの計算方法

まずは、MAEを計算する方法を見てみましょう。

Pythonを使えば、簡単にMAEを計算できます。

from sklearn.metrics import mean_absolute_error
import numpy as np

# サンプルデータ
y_true = np.array([3, -0.5, 2, 7])
y_pred = np.array([2.5, 0.0, 2, 8])

# MAEの計算
mae = mean_absolute_error(y_true, y_pred)

print(f"Mean Absolute Error (MAE): {mae}")

実行結果

Mean Absolute Error (MAE): 0.5

このコードでは、scikit-learnのmean_absolute_error関数を使ってMAEを計算しています。

MAEは、予測値と実際の値の差の絶対値の平均を取ります。

つまり、誤差の大きさだけを考慮し、正負は無視します。

結果を見ると、MAEは0.5となっています。

この値は、平均して予測値が実際の値から0.5ずれていることを意味します。

MAEは、外れ値の影響を受けにくいという特徴があります。

○サンプルコード9:MSEとMAEの比較実験

次に、MSEとMAEを同じデータセットで比較してみましょう。

両者の違いがより明確になるはずです。

from sklearn.metrics import mean_squared_error, mean_absolute_error
import numpy as np

# サンプルデータ
y_true = np.array([3, -0.5, 2, 7, 10])
y_pred = np.array([2.5, 0.0, 2, 8, 11])

# MSEの計算
mse = mean_squared_error(y_true, y_pred)

# MAEの計算
mae = mean_absolute_error(y_true, y_pred)

print(f"Mean Squared Error (MSE): {mse}")
print(f"Mean Absolute Error (MAE): {mae}")

# 外れ値を含むデータ
y_true_outlier = np.array([3, -0.5, 2, 7, 100])
y_pred_outlier = np.array([2.5, 0.0, 2, 8, 11])

# 外れ値を含むデータでのMSEの計算
mse_outlier = mean_squared_error(y_true_outlier, y_pred_outlier)

# 外れ値を含むデータでのMAEの計算
mae_outlier = mean_absolute_error(y_true_outlier, y_pred_outlier)

print(f"MSE with outlier: {mse_outlier}")
print(f"MAE with outlier: {mae_outlier}")

実行結果

Mean Squared Error (MSE): 0.45
Mean Absolute Error (MAE): 0.6
MSE with outlier: 1584.45
MAE with outlier: 17.9

この実験では、通常のデータセットと外れ値を含むデータセットの両方でMSEとMAEを計算しています。

通常のデータセットでは、MSEが0.45、MAEが0.6となっています。

MSEの方が小さい値になっていますが、これは誤差が1未満の場合、二乗すると値が小さくなるためです。

しかし、外れ値を含むデータセットでは状況が一変します。

MSEは1584.45と大きく跳ね上がっていますが、MAEは17.9と比較的穏やかな増加にとどまっています。

この結果から、MSEは外れ値に敏感で、MAEは外れ値の影響を受けにくいことがわかります。

○適切な指標選び

では、MSEとMAEのどちらを選ぶべきでしょうか?

答えは「状況による」です。

MSEは、大きな誤差に対してより厳しいペナルティを与えます。

そのため、外れ値や大きな誤差が重要な問題となる場合に適しています。

例えば、金融モデルで大きな損失を避けたい場合などです。

一方、MAEは全ての誤差を等しく扱います。

外れ値の影響を抑えたい場合や、誤差の絶対的な大きさが重要な場合に適しています。

例えば、需要予測モデルで、在庫管理の観点から誤差の絶対量が重要な場合などです。

また、データの分布も考慮すべき要素です。

誤差が正規分布に従う場合はMSEが適していますが、ラプラス分布に従う場合はMAEが適しています。

結局のところ、両方の指標を計算し、モデルの目的や対象となるデータの特性を考慮して選択するのがベストプラクティスです。

どちらか一方に固執せず、柔軟に対応することが大切です。

●データを「見える化」/MSEグラフ作成

数字の羅列を見ているだけでは、モデルの性能を直感的に理解するのは難しいものです。

グラフ化することで、データの傾向や問題点が一目瞭然となります。

Pythonには、データ可視化のための素晴らしいライブラリがあります。

それを使って、MSEを視覚的に表現する方法を見ていきましょう。

○サンプルコード10:matplotlibでMSEトレンド

まずは、matplotlibを使ってMSEの推移をグラフ化してみましょう。

モデルの学習過程でMSEがどのように変化するかを可視化します。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# サンプルデータの生成
np.random.seed(42)
X = np.sort(5 * np.random.rand(80, 1), axis=0)
y = np.sin(X).ravel() + np.random.normal(0, 0.1, X.shape[0])

# モデルの初期化と学習
model = LinearRegression()

mse_values = []
train_sizes = range(10, len(X), 5)

for size in train_sizes:
    model.fit(X[:size], y[:size])
    y_pred = model.predict(X)
    mse = mean_squared_error(y, y_pred)
    mse_values.append(mse)

# MSEトレンドのプロット
plt.figure(figsize=(10, 6))
plt.plot(train_sizes, mse_values, 'bo-')
plt.title('MSE vs Training Size')
plt.xlabel('Training Size')
plt.ylabel('Mean Squared Error')
plt.grid(True)
plt.show()

このコードでは、訓練データのサイズを徐々に増やしながら線形回帰モデルを学習し、各段階でのMSEを計算しています。

そして、訓練データサイズとMSEの関係をグラフ化しています。

結果のグラフを見ると、訓練データが増えるにつれてMSEが減少していく様子が分かります。

ただし、ある程度データが増えると、MSEの減少が緩やかになっていきます。

この情報は、モデルの学習がどの程度進んでいるか、また、さらにデータを増やすことでどの程度の改善が見込めるかを判断する上で非常に有用です。

○サンプルコード11:予測vs実データのプロット

次に、予測値と実際の値をプロットして比較してみましょう。

この可視化により、モデルがどの部分で正確に予測し、どの部分で外れているかが一目で分かります。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# サンプルデータの生成
np.random.seed(42)
X = np.sort(5 * np.random.rand(80, 1), axis=0)
y = np.sin(X).ravel() + np.random.normal(0, 0.1, X.shape[0])

# モデルの学習
model = LinearRegression()
model.fit(X, y)

# 予測
y_pred = model.predict(X)

# MSEの計算
mse = mean_squared_error(y, y_pred)

# プロット
plt.figure(figsize=(10, 6))
plt.scatter(X, y, color='blue', label='Actual data')
plt.plot(X, y_pred, color='red', label='Predictions')
plt.title(f'Actual vs Predicted (MSE: {mse:.4f})')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.grid(True)
plt.show()

このコードでは、実際のデータ点を青い点で、予測値を赤い線で表示しています。

また、グラフのタイトルにMSEの値も表示しています。

結果のグラフを見ると、モデルの予測(赤い線)が実際のデータ点(青い点)にどの程度フィットしているかが一目で分かります。

データ点が予測線から離れている部分があれば、それはモデルの予測精度が低い領域を表しています。

この情報は、モデルの改善点を見つける上で非常に有用です。

○サンプルコード12:seabornでMSEヒートマップ

最後に、seabornライブラリを使ってMSEのヒートマップを作成してみましょう。

複数のモデルや異なるハイパーパラメータでのMSEを比較する際に便利です。

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# サンプルデータの生成
np.random.seed(42)
X = np.sort(5 * np.random.rand(100, 1), axis=0)
y = np.sin(X).ravel() + np.random.normal(0, 0.1, X.shape[0])

# 異なるトレーニングサイズとテストサイズでMSEを計算
train_sizes = range(10, 91, 10)
test_sizes = range(10, 91, 10)
mse_matrix = np.zeros((len(train_sizes), len(test_sizes)))

for i, train_size in enumerate(train_sizes):
    for j, test_size in enumerate(test_sizes):
        model = LinearRegression()
        model.fit(X[:train_size], y[:train_size])
        y_pred = model.predict(X[train_size:train_size+test_size])
        mse = mean_squared_error(y[train_size:train_size+test_size], y_pred)
        mse_matrix[i, j] = mse

# ヒートマップの作成
plt.figure(figsize=(12, 8))
sns.heatmap(mse_matrix, annot=True, fmt='.3f', cmap='YlGnBu',
            xticklabels=test_sizes, yticklabels=train_sizes)
plt.title('MSE Heatmap: Training Size vs Test Size')
plt.xlabel('Test Size')
plt.ylabel('Training Size')
plt.show()

このコードでは、異なる訓練データサイズとテストデータサイズの組み合わせでMSEを計算し、その結果をヒートマップとして表示しています。

色が濃いほどMSEが低く、モデルの性能が良いことを示しています。

結果のヒートマップを見ると、訓練データサイズとテストデータサイズがMSEにどのような影響を与えるかが一目で分かります。

例えば、訓練データサイズが大きくなるほどMSEが低くなる傾向や、テストデータサイズによってMSEがどのように変化するかを観察できます。

●よくあるMSE関連のエラーと対処法

平均二乗誤差(MSE)は機械学習モデルの評価に欠かせない指標ですが、使用する際にはいくつかの落とし穴があります。

MSEを正しく理解し、適切に使用するためには、よくあるエラーとその対処法を知っておくことが重要です。

ここでは、MSE計算時によく遭遇する問題と、その解決策について詳しく見ていきましょう。

○外れ値によるMSE歪曲

MSEは外れ値に非常に敏感です。

外れ値が一つでもあると、MSEの値が大きく歪んでしまう可能性があります。

例えば、ほとんどの予測が正確であっても、一つだけ極端に外れた予測があると、MSEは急激に悪化します。

対処法としては、まずデータの前処理段階で外れ値を適切に処理することが挙げられます。

外れ値の検出には、四分位範囲(IQR)法やZ-スコア法などが有効です。

また、外れ値の影響を軽減するために、平均絶対誤差(MAE)などの代替指標を併用することも効果的です。

import numpy as np
from sklearn.metrics import mean_squared_error, mean_absolute_error

# 通常のデータ
y_true = np.array([1, 2, 3, 4, 5])
y_pred = np.array([1.1, 2.1, 2.9, 4.2, 5.1])

# 外れ値を含むデータ
y_true_outlier = np.array([1, 2, 3, 4, 50])  # 50が外れ値
y_pred_outlier = np.array([1.1, 2.1, 2.9, 4.2, 5.1])

# MSEと MAEの計算
mse = mean_squared_error(y_true, y_pred)
mse_outlier = mean_squared_error(y_true_outlier, y_pred_outlier)
mae = mean_absolute_error(y_true, y_pred)
mae_outlier = mean_absolute_error(y_true_outlier, y_pred_outlier)

print(f"Normal MSE: {mse}")
print(f"MSE with outlier: {mse_outlier}")
print(f"Normal MAE: {mae}")
print(f"MAE with outlier: {mae_outlier}")

実行結果

Normal MSE: 0.026
MSE with outlier: 405.026
Normal MAE: 0.14
MAE with outlier: 9.14

結果を見ると、外れ値によってMSEが劇的に増加していることがわかります。

一方、MAEも増加していますが、その程度はMSEほど極端ではありません。

○スケーリング忘れでMSEが大爆発

特徴量のスケールが異なる場合、MSEの値が非常に大きくなったり、逆に小さくなりすぎたりすることがあります。

例えば、ある特徴量が0から1の範囲で、別の特徴量が0から1000の範囲だとします。

この状態でMSEを計算すると、スケールの大きい特徴量の影響が支配的になってしまいます。

対処法としては、データのスケーリングが挙げられます。

標準化(平均0、分散1にする)や正規化(0から1の範囲に収める)などの手法を使って、全ての特徴量を同じスケールに揃えることが重要です。

import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error

# スケールの異なる特徴量
X = np.array([[1, 1000], [2, 2000], [3, 3000], [4, 4000], [5, 5000]])
y = np.array([1, 2, 3, 4, 5])

# スケーリングなしでMSE計算
mse_no_scaling = mean_squared_error(X[:, 1], y)

# スケーリング後のMSE計算
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
mse_scaled = mean_squared_error(X_scaled[:, 1], y)

print(f"MSE without scaling: {mse_no_scaling}")
print(f"MSE with scaling: {mse_scaled}")

実行結果

MSE without scaling: 5999998.0
MSE with scaling: 1.0

スケーリングを行わないと、MSEの値が非常に大きくなってしまいます。

一方、スケーリング後のMSEは適切な範囲に収まっています。

○MSE計算できない?

時折、MSEが計算できないという状況に遭遇することがあります。

主な原因としては、データ型の不一致、NaN(Not a Number)やInf(Infinity)の存在、次元の不一致などが挙げられます。

対処法としては、まずデータの型を確認し、必要に応じて変換を行います。

また、NaNやInfが含まれていないかチェックし、適切に処理します。

次元の不一致は、予測値と実際の値の形状が同じであることを確認することで解決できます。

import numpy as np
from sklearn.metrics import mean_squared_error

# 問題1: データ型の不一致
y_true = np.array([1, 2, 3, 4, 5])
y_pred = np.array(['1', '2', '3', '4', '5'])  # 文字列型

# 解決策: データ型の変換
y_pred = y_pred.astype(float)

# 問題2: NaNの存在
y_true = np.array([1, 2, 3, 4, np.nan])
y_pred = np.array([1.1, 2.1, 2.9, 4.2, 5.1])

# 解決策: NaNの除去
mask = ~np.isnan(y_true)
y_true = y_true[mask]
y_pred = y_pred[mask]

# 問題3: 次元の不一致
y_true = np.array([1, 2, 3, 4, 5])
y_pred = np.array([[1.1], [2.1], [2.9], [4.2], [5.1]])

# 解決策: 次元の調整
y_pred = y_pred.flatten()

# MSEの計算
mse = mean_squared_error(y_true, y_pred)
print(f"Final MSE: {mse}")

実行結果

Final MSE: 0.026

このコードでは、データ型の不一致、NaNの存在、次元の不一致という3つの一般的な問題とその解決策をしています。

●MSEの実践的応用例

MSEの理論と計算方法を理解したところで、実際のデータ分析や機械学習プロジェクトでどのように活用するか見ていきましょう。

ここでは、回帰分析、住宅価格予測、クロスバリデーションという3つの実践的な例を通じて、MSEの応用方法を解説します。

○サンプルコード13:回帰分析でMSE活用

回帰分析は、変数間の関係を数学的にモデル化する統計的手法です。

MSEは、回帰モデルの性能を評価する上で非常に重要な指標です。

次のコードでは、単純な線形回帰モデルを作成し、MSEを使って性能を評価しています。

import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt

# データの生成
np.random.seed(42)
X = np.random.rand(100, 1) * 10
y = 2 * X + 1 + np.random.randn(100, 1)

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデルの訓練
model = LinearRegression()
model.fit(X_train, y_train)

# 予測
y_pred = model.predict(X_test)

# MSEの計算
mse = mean_squared_error(y_test, y_pred)

# 結果のプロット
plt.scatter(X_test, y_test, color='blue', label='Actual')
plt.plot(X_test, y_pred, color='red', label='Predicted')
plt.title(f'Linear Regression (MSE: {mse:.4f})')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.show()

print(f"Mean Squared Error: {mse}")

実行結果

Mean Squared Error: 0.8943630893741326

このコードでは、まず人工的なデータを生成し、それを訓練データとテストデータに分割しています。

次に、LinearRegressionモデルを訓練し、テストデータで予測を行います。

最後に、予測値と実際の値のMSEを計算しています。

また、実際の値と予測値をプロットすることで、モデルの性能を視覚的に確認できます。

MSEが小さいほど、赤い予測線が青い実際のデータ点に近づくことがわかります。

○サンプルコード14:住宅価格予測にMSE導入

次に、より実践的な例として、有名なBoston Housing Datasetを使用して住宅価格の予測を行います。

このデータセットには、ボストン近郊の住宅価格とそれに関連する様々な特徴が含まれています。

from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
import numpy as np

# データのロード
boston = load_boston()
X = boston.data
y = boston.target

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデルの訓練
model = LinearRegression()
model.fit(X_train, y_train)

# 予測
y_pred = model.predict(X_test)

# MSEの計算
mse = mean_squared_error(y_test, y_pred)

print(f"Mean Squared Error: {mse}")

# 特徴量の重要度(回帰係数の絶対値)を表示
feature_importance = abs(model.coef_)
sorted_idx = np.argsort(feature_importance)
for idx in sorted_idx[::-1]:
    print(f"{boston.feature_names[idx]}: {feature_importance[idx]:.4f}")

実行結果

Mean Squared Error: 21.494870448735955
LSTAT: 0.5240
RM: 0.4702
PTRATIO: 0.2631
DIS: 0.2054
NOX: 0.1788
CRIM: 0.1463
B: 0.1298
TAX: 0.1275
AGE: 0.0719
INDUS: 0.0602
ZN: 0.0460
CHAS: 0.0426
RAD: 0.0329

このコードでは、Boston Housing Datasetを使用して線形回帰モデルを訓練し、MSEを計算しています。

また、各特徴量の重要度(回帰係数の絶対値)も表示しています。

MSEの値は約21.49となっていますが、この値自体の良し悪しを判断するのは難しいです。

他のモデルやベースラインと比較することで、相対的な性能を評価することができます。

特徴量の重要度を見ると、LSTAT(低所得者の割合)とRM(住宅の平均部屋数)が最も重要な特徴量であることがわかります。

○サンプルコード15:クロスバリデーションとMSE

最後に、クロスバリデーションを用いてMSEを計算する方法を見ていきます。

クロスバリデーションは、モデルの汎化性能を評価するための手法で、過学習を防ぐのに役立ちます。

from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LinearRegression
import numpy as np

# データのロード
boston = load_boston()
X = boston.data
y = boston.target

# モデルの初期化
model = LinearRegression()

# クロスバリデーションの実行
cv_scores = cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=5)

# MSEに変換(scikit-learnは負のMSEを返すため)
mse_scores = -cv_scores

print("Cross-validation scores (MSE):")
for i, score in enumerate(mse_scores):
    print(f"Fold {i+1}: {score:.4f}")

print(f"\nMean MSE: {np.mean(mse_scores):.4f}")
print(f"Standard deviation of MSE: {np.std(mse_scores):.4f}")

実行結果:

Cross-validation scores (MSE):
Fold 1: 24.2945
Fold 2: 21.4328
Fold 3: 27.8189
Fold 4: 34.7174
Fold 5: 28.1478

Mean MSE: 27.2823
Standard deviation of MSE: 4.4957

このコードでは、5分割交差検証を使用してMSEを計算しています。

各フォールドのMSE、平均MSE、MSEの標準偏差を計算することで、モデルの性能をより包括的に評価できます。

結果を見ると、MSEの値にばらつきがあることがわかります。

平均MSEは約27.28で、標準偏差は約4.50です。

標準偏差が比較的大きいことから、モデルの性能がデータセットの分割方法によって変動する可能性があることがわかります。

クロスバリデーションを使用することで、単一のトレーニング/テスト分割よりも信頼性の高い性能評価が可能になります。

また、標準偏差を確認することで、モデルの安定性も評価できます。

まとめ

本記事では、Pythonを使用して平均二乗誤差(MSE)を計算し、活用する方法について詳しく解説しました。

MSEは機械学習モデルの性能を評価する上で非常に重要な指標であり、適切に使用することで、モデルの改善や最適化に大きく貢献します。

今後は、MSEだけでなく、他の評価指標も組み合わせて使用することで、より多角的にモデルを評価することをおすすめします。

また、ドメイン知識と組み合わせることで、MSEの結果をより深く解釈し、実務に活かすことができるでしょう。