この記事では、機械学習の回帰モデル作成の基本的な流れを解説します。対象データの理解から始め、特徴量の選択、モデルの作成と学習、そしてモデルの評価まで、一連のステップを具体的なコード例とともに説明します。この記事に沿って進めれば、回帰モデルを作成し、評価することができるようになるはずです。
データの読み込みと結合
機械学習に取り組むための最初のステップは、データの読み込みと最低限の結合処理です。Pythonとのライブラリであるpandasを使用して、データを読み込み、理解し、複数のinputデータを結合する方法を解説します。
データの読み込み
Pythonでcsvファイルのデータを読み込む方法は非常にシンプルです。pandasのread_csv
関数を使用します。この関数を使用すると、csvファイルのデータを読み込み、DataFrameという形式でデータを保持することができます。
import pandas as pd
data = pd.read_csv('filename.csv') # 同じフォルダにあるfilename.csvというファイルを読み込みます
データの概要把握
読み込んだデータの初歩的な確認を行います。まず、データの先頭を表示してみましょう。
print(data.head())
また、読み込んだデータの行数と列数を確認するために、shape
属性を使用します。
print(data.shape)
次に、各列のデータ型を確認します。これは、データの理解と前処理のために重要です。
print(data.info())
データの結合
データ分析では、複数のデータセットを結合することがよくあります。pandasでは、concat
関数やmerge
関数を用いてデータを結合することができます。
縦結合
concat
関数は、2つのDataFrameを縦に結合します。
combined_data = pd.concat([data1, data2])
横結合
merge
関数は、共通のカラムを基に2つのDataFrameを横に結合します。
merged_data = pd.merge(data1, data2, on='common_column', how='join_type')
また、異なるカラム名を基に2つのDataFrameを横に結合することも可能です。
merged_data = pd.merge(data1, data2, left_on="data1_column", right_on="data2_column", how='join_type')
不要カラムの削除
この時点で明らかに不要なカラムがあれば削除しておきます。pandasでは、drop
関数を使用してカラムを削除します。
data = data.drop(columns=['column_name']) # column_nameという名前のカラム(列)を削除します
作成または加工したデータフレームをcsvファイルとして保存することも可能です。後続作業をスムーズにするために削除しておくと便利です。
data.to_csv('new_filename.csv', index=None)
特徴量の理解とデータ前処理
データ分析に取り組む際、まず特徴量(データの各項目)を理解し、前処理が必要な項目を特定します。特に、一つのカラムに複数の情報が混在していたり、データの形式が適切でない場合(例えば、数値として扱いたいデータが文字列として格納されている場合など)は、前処理が必要となることが多いです。
特徴量の分割とデータ変換
特徴量の分割やデータ変換はデータ分析の重要なステップです。たとえば、複数の属性が一つのカラムにまとめられている場合、それぞれを個別のカラムに分割すると各特徴量の影響を個別に分析できます。また、データ型が適切でない場合も、適切なデータ型に変換することが求められます。
例えば日付はさまざまな形式で同じカラムに入っていることが多いので、処理しやすいように月、日などのカラムに分けて格納すると分析がしやすくなります。
# 例えば10/13など先頭2文字が月である場合にmonthカラムを作成する例
def get_month(x):
return int(x[:2])
# 月を表すmonthカラムを作成
data['month'] = data['対象日'].apply(get_month)
データ形式の修正
特定の形式(例えば、パーセンテージ)で格納されているデータがある場合、それを適切な形式(例えば、小数)に変換することで分析が容易になります。
# 特定の文字を除去し、適切な形式に変換
DataFrame['カラム名'] = DataFrame['カラム名'].str.replace('特定の文字', '').astype(適切なデータ型)
欠損値の確認と処理
データ分析を行う際には、データセット内に欠損値が存在しないか確認することが重要です。欠損値が存在すると、データの可視化やモデル作成が困難になるためです。pandasでは、isnull()
関数を使用して欠損値の有無を確認できます。
print(DataFrame.isnull().sum())
欠損値がある場合には、そのデータを削除する、何かの値(ゼロ、平均値、など)で埋めるなどの処理が必要になります。
説明変数の内容の確認と表記揺れの調整
各説明変数の詳細を理解するために、以下の方法を用いることができます。
値の一覧表示:
DataFrame['カラム名'].unique()
値の種類数の確認:
DataFrame['カラム名'].nunique()
各値の頻度の確認:
DataFrame['カラム名'].value_counts()
データ分析を進める上で、表記揺れは重要な問題となります。上の値の一覧の確認などで同一の事項が異なる表記で記録されていることがわかった場合、それらを統一する必要があります。これには、Pandasのreplace関数を用いることが一般的です。
DataFrame.replace('変換前の値', '変換後の値')
基本統計量の把握
モデル作成の過程において、データの特性や特徴を理解することは非常に重要です。その一助となるのが、データの散らばり具合や分布を確認する「基本統計量」です。これには、最大値、最小値、平均値、中央値、最頻値、標準偏差、四分位数などが含まれます。これらの統計量を理解し活用することにより、データの様々な特性を把握し、より精緻なモデル作成を行うことが可能になります。
基本統計量の確認とその解釈
データ分析における一環として、データの基本統計量の確認を行います。これはDataFrame.describe()
関数を使用することで可能です。その結果、各列に対する基本統計量が計算され、表形式で得られます。この表には、データの個数、平均値、標準偏差、最小値、第一四分位数、中央値、第三四分位数、最大値などが含まれます。
外れ値の削除とその方法
データ分析を行う上で、統計量の確認は重要なステップです。データセット内で発見された異常な値(外れ値)について取り上げ、その扱い方を考察します。外れ値を削除するには、PythonのPandasライブラリを用いて、以下のように記述します。
data = data[data['カラム名'] > 0]
上記のコード例では指定したカラムの値が0のデータだけが削除されます。
データの可視化方法:ヒストグラム
データの分布を確認し、それを可視化する方法について解説します。特に数値データの分布を確認するための一般的な手法として、ヒストグラムを用いる方法を紹介します。
DataFrame['カラム名'].plot.hist()
質的データの分析:頻度値の算出と棒グラフ
質的データの分析も重要です。質的データの分布を可視化する一つの方法として、棒グラフがあります。棒グラフを作成するためには、まず「どの値がどれくらいの数あるのか」という頻度値を算出する必要があります。
頻度値の算出は以下のコードでできます。
DataFrame['カラム名'].value_counts()
これを利用して棒グラフの作成するには以下の通りのコードとなります。
DataFrame['カラム名'].value_counts().plot.bar()
相関係数の確認
また、データの関連性を見る際に相関係数を用いることが一般的です。相関係数は-1から1までの範囲を持ち、その値が大きいほど強い相関があることを示します。Pandasでは、corr
関数を用いることで容易に相関係数を計算することができます。
DataFrame.corr()
これだけだと見にくい場合は、seabornライブラリを使用してヒートマップを作成すると見やすくなります。
corr = DataFrame.corr()
plt.figure(figsize=(10, 8)) # ヒートマップのサイズを指定
sns.heatmap(corr, annot=True, cmap='coolwarm') # ヒートマップを描画
plt.show()
次に、質的変数と量的変数の関係性を見る際には、箱ひげ図(ボックスプロット)が有用です。seabornライブラリを用いることで、以下のように箱ひげ図を描画することができます:
sns.boxplot(x='横軸に割り当てたいカラム', y='縦軸に割り当てたいカラム', data=分析対象のデータフレーム)
特徴量の選択・生成
特徴量の選択
データ分析の過程で特定のカラムが重要な特徴量であると判断された場合、それらのカラムを選択して分析を進めます。単一のカラムを選択するには以下の上段のようにし、複数のカラムを選択するには下段のようにカラム名をリストとして指定します:
DataFrame["列名"]
DataFrame[['列名1', '列名2', ...]]
この形を用いて、特徴量と目的変数に分割します。それぞれXとyという変数名を使うことが多いです。
X= DataFrame[['列名1','列名2','列名3']]
y= DataFrame['列名']
特徴量の生成
既存のデータから新しい特徴量を生成することはデータ分析における重要な手法の一つです。例えば、気温と湿度から不快指数を算出したり、文字列を解析して新しい変数を作り出したりします。
次に、質的な特徴量を数値型に変換するためには、ダミー変数化(ワンホットエンコーディング)を行います。Pandasのget_dummies関数を用いることで、全ての質的変数をダミー変数化することができます。
X = pd.get_dummies(X)
また、get_dummies関数の引数drop_firstをTrueに設定することで、生成するダミー変数の数を最小限に抑えることが可能です。
学習データと評価データの分割
機械学習モデルを作成する前の重要なステップとして、全体のデータを「学習データ」と「評価データ」に分割します。このステップの目的は、未知のデータに対するモデルの予測性能、すなわち「汎化性能」を評価するためです。モデルが学習に使用したデータだけでなく、新たなデータに対しても良い予測を行うことができれば、それは良い汎化性能を持つモデルと言えます。そのためには、モデルの学習に使用しないデータを確保し、それを評価データとして使用します。
データを学習データと評価データに分割するためには、Pythonの機械学習ライブラリであるScikit-learnのtrain_test_split
関数を利用します。まず、この関数を使用するためにはScikit-learnライブラリをインポートします。
from sklearn.model_selection import train_test_split
次に、train_test_split
関数にデータを与えて実行します。ここでのデータは、説明変数と目的変数に分けられたデータです。説明変数は予測の元となるデータで、目的変数は予測したいデータです。
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
のコードを実行すると、与えられたデータは以下の4つに分割されます。
X_train
: 学習データの説明変数X_test
: 評価データの説明変数y_train
: 学習データの目的変数y_test
: 評価データの目的変数
このとき、random_state
パラメータに整数値を設定することで、同じデータ分割を再現することが可能になります。機械学習モデルを作成する際には、評価結果の再現性が重要となるため、同じデータセットを使用してモデル作成を行うことが望ましいです。そのため、一貫性を保つためにrandom_state
を設定することを推奨します。
モデルの作成と学習(重回帰モデルの場合)
次のステップは、重回帰モデルを作成し、学習データを用いてそのモデルを学習させることです。様々な種類のモデルがありますが、ここでは重回帰モデルを用いた例を説明します。
重回帰モデルは、複数の説明変数から目的変数を予測するためのモデルで、以下のような形式を持ちます。
$$y = a_1X_1 + a_2X_2 + a_3X_3 + … + a_0$$
ここで、X1,X2,X3,…Xnは説明変数を、a1,a2,a3,…anは各説明変数に対応する係数(回帰係数)、そしてa0はモデルの切片(定数項)を表しています。
Pythonの機械学習ライブラリであるScikit-learnのLinearRegression
クラスを用いて重回帰モデルを作成します。まず、このクラスをインポートします。
from sklearn.linear_model import LinearRegression
次に、LinearRegression
クラスのインスタンスを作成します。これが、我々の重回帰モデルとなります。
model = LinearRegression()
そして、モデルを学習させます。これにはfit
メソッドを使用し、引数として説明変数と目的変数を渡します。
model.fit(X_train, y_train)
このコードを実行すると、重回帰モデルは学習データを基にして最適な回帰係数と切片を求めます。そして、それらのパラメータを用いて新たなデータの目的変数を予測することが可能となります。
モデルの学習が終わったら、各説明変数の偏回帰係数と切片を確認します。これらの値は、モデルがどのように予測を行っているかを理解する上で非常に重要です。
print('Coefficients: ', model.coef_)
print('Intercept: ', model.intercept_)
ここで、model.coef_
は各説明変数に対応する偏回帰係数を、model.intercept_
は切片を表しています。
さらに、どの説明変数がどの程度の影響を持っているのかを視覚的に理解するために、DataFrameを作成します。
coef_df = pd.DataFrame(model.coef_, index=X_train.columns, columns=['Coefficients'])
print(coef_df)
これにより、各説明変数に対応する偏回帰係数が一覧表示されます。
学習済みのモデルを使用して、未知のデータに対する予測を行うにはpredict
メソッドを使用します。
y_pred = model.predict(X_test)
ここで、X_test
は評価データの説明変数を表しています。このコードを実行すると、評価データの目的変数の予測値が出力されます。
モデルの評価:RMSEによる予測精度の測定
RMSEについて
機械学習モデルを作成する際には、モデルの予測精度を測定するための評価関数が不可欠です。評価関数は、モデルの予測結果がどれだけ実際のデータに近いかを定量的に評価するもので、その選択は作成したいモデルの目的やタスクによります。
今回のタスクでは、大きな予測誤差を出さないモデルの作成を目指しています。そのため、評価関数としてRMSE(Root Mean Squared Error)を採用します。RMSEは、実測値とモデルの予測値の差を2乗したものの平均の平方根を計算することで得られます。数式で表すと以下のようになります。
$$\text{RMSE} = \sqrt{\frac{1}{n}\sum_{k=1}^{n}(y_{\text{actual},k} – y_{\text{pred},k})^2}$$
ここで、yactual,kはk番目のデータの実測値、y_pred,kはk番目のデータの予測値を表し、nはデータの数を意味します。
RMSEが小さいほどモデルの予測精度が高いことを示します。また、RMSEは予測誤差の二乗を用いているため、大きな誤差を出すモデルに対して厳しい評価を行います。したがって、大きな予測誤差が許されないタスクにおいては、RMSEを評価関数として採用するのが適しています。
RMSEの計算方法
PythonでRMSEを計算するには、scikit-learnライブラリのMSE(Mean Squared Error)を利用します。MSEは予測誤差の二乗の平均を計算する関数で、これの平方根を取ることでRMSEを求めることができます。
まず、scikit-learnからMSEをインポートします。
from sklearn.metrics import mean_squared_error as MSE
引数に実測値と予測値を与えることで、MSEを計算することができます。
tmp = MSE(y_actual, y_pred)
このMSEの平方根を取ることで、RMSEを得ることができます。平方根はnumpyのsqrt関数を利用することで計算ができます。以下のように記述します:
rmse = np.sqrt(tmp)
予測精度の評価(評価データ)
モデルの汎化性能を評価するためには、評価データだけでなく学習データに対する予測精度も評価することが重要です。特に、過学習(モデルが学習データに過度に適合し、新しい未知のデータに対する予測精度が低下する現象)を防ぐためには、学習データと評価データそれぞれに対する予測精度のギャップを確認することが一つの手法となります。
過学習の場合、学習データへの予測精度は高い一方で、評価データへの予測精度が顕著に低下します。したがって、学習データと評価データの両方に対する予測精度を比較することで、モデルが過学習している可能性を推測することができます。
そのため、学習データに対する予測精度の評価と同様に、評価データに対する予測精度も評価する必要があります。具体的には、評価データに対するRMSE(Root Mean Square Error)を計算し、モデルの予測精度を評価します。
予測精度の可視化
予測モデルの評価を深化するためには、予測精度を数値的に評価するだけでなく、予測結果の傾向を理解することが重要です。例えば、予測値が大きい時や小さい時に予測が外れやすいかどうかというような傾向を把握することで、モデルの改良戦略を立てるための手がかりを得ることができます。
具体的には、予測値(縦軸)と実測値(横軸)を散布図としてプロットすることが一つの方法です。散布図を見ることで、予測が実測値を上回る傾向(予測過大)や下回る傾向(予測過小)があるか、または予測が大きく外れる点がないか確認することができます。
以下のコードで散布図を作成することができます:
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 8)) # グラフのサイズを指定
plt.scatter(y_actual, y_pred) # 実測値と予測値の散布図を描く
plt.xlim([min(y_actual), max(y_actual)]) # x軸の範囲を指定
plt.ylim([min(y_pred), max(y_pred)]) # y軸の範囲を指定
plt.plot([min(y_actual), max(y_actual)], [min(y_pred), max(y_pred)], color='red') # 対角線を描く
plt.show()
散布図により予測結果を可視化することができた後は、その結果から予測の傾向を読み取ることができます。理想的には、予測値が全て実測値に一致している場合、散布図上の全ての点は対角線上に表示されます。
よって予測が実測値を上回る(上振れ)または下回る(下振れ)傾向があるか、また極端に外れた予測が存在するかどうかを確認することができます。これにより、予測モデルの性能を更に詳しく理解し、必要ならば改良の方向性を探ることができます。
残差分析
モデルの評価が終わったら、モデルの改善に移ります。ここではその手段の1つである残差分析について解説します。
残差分析の実施
予測モデルの性能をより深く理解するために、どのデータで予測が当たり、どのデータで予測が外れているのかを詳細に把握するために残差分析を行います。
残差とは、予測値と実測値との差のことを指します。ここでは、元のデータに予測値と残差のカラムを追加し、残差の大きさ順にデータをソートして表示します。これにより、どの特徴を持つデータが大きく予測を外しているかを特定することができます。
残差分析の手順
残差分析では以下の手順を踏みます:
- 予測値と残差のカラムを元のデータに追加します。
- 残差の大きさに基づいてデータをソートします。
具体的には以下のようなコードで実装することができます:
# 予測値と残差のカラムを追加
df['prediction'] = model.predict(X)
df['residual'] = df['actual'] - df['prediction']
# 残差の絶対値でソート
df = df.sort_values(by='residual', ascending=False)
このようにして、予測が大きく外れているデータを特定し、それらがどのような特性を持つのかを理解することができ、モデルの改良点を見つけることができます。
以上、回帰モデルの作成について一連のステップを紹介しました。なお、ここではイメージがしやすい重回帰モデルを取り上げましたが、決定木モデル、特に勾配ブースティングモデルは良い結果を収めることが多いので、別のモデルを試す、あるいは組み合わせるなどの方法でさらに改善が図れる可能性が高まると思います。