データ前処理②
機械学習前のデータ処理メモ。
教材の説明だけでは理解しにくい部分をBardに「もう少しわかり易く教えて」等聞きながら作りました。
標準化
データの標準化(Standardization)とは、平均を0に、標準偏差を1にするスケーリングを意味します。機械学習の中でもNN(ニューラルネットワーク)の分野では、データの標準化をしないとモデル精度が落ちてしまうことがあります。
例えば、検診データからある病気にかかっているかを分類する機械学習モデルを作成する際に、身長と体重を示す説明変数が存在し、身長の単位が【cm】、体重を【kg】で表していたとします。人間の場合は数値の情報と単位の情報を考慮できるため、身長と体重のデータ値の比較を行うことができます。しかし、機械学習などのアルゴリズムでは、単位となる情報がなく数値情報のみから病気であるかを判断するため、うまく身長と体重との比較ができずアルゴリズムが機能しないことがあります。
そのためデータの標準化を行い、アルゴリズムに対しても情報の比較が可能となるような物差しを渡してあげます。線形回帰やNN(ニューラルネットワーク)などのアルゴリズムを用いる際に、データの標準化を行います。
# 標準化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaled_data = scaler.fit_transform(data)
正規化
データの正規化(Normalization)とは、特徴量の値の範囲を一定の範囲におさめるスケーリングを意味します。機械学習の分野では主に[0, 1]か、[-1, 1]の範囲内に収めることが多く、最大値と最小値が予め決まっている場合や、データの分布が一様分布である場合に有効です。
また、データ内に外れ値が存在する場合は正規化することでデータに偏りが生まれてしまうので注意しましょう。
# 正規化
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))#最小値0,最大値1
scaled_data = scaler.fit_transform(data)
【標準化と正規化の違い】
※標準化は、データの平均値を0、標準偏差を1に変更する方法。これにより、各データの値が同じスケールになる。
※正規化は、データの値を最大値と最小値の間に収める方法。これにより、各データの値の比率が同じになる。
ラベルエンコード
ラベルエンコーディングは、カテゴリ変数の値を数値に変換する手法です。機械学習のアルゴリズムの多くは、数値データしか処理できないため、カテゴリ変数をラベルエンコーディングすることで、機械学習のアルゴリズムに対応させることができます。
Pythonでラベルエンコーディングを行うには、sklearn.preprocessingモジュールのLabelEncoderクラスを使用します。LabelEncoderクラスのfit_transformメソッドを使用すると、カテゴリ変数の値を数値に変換することができます。
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
# カテゴリ変数のエンコーディング
le.fit(カテゴリ変数)
# エンコードされたカテゴリ変数
エンコードされたカテゴリ変数 = le.transform(カテゴリ変数)
#カテゴリ変数が「赤」「青」「緑」の場合
le.classes_
Out[108]: array(['赤', '青', '緑'], dtype=object)
le.transform(['赤', '青', '緑'])
Out[109]: array([0, 1, 2], dtype=int64)
ダミー変数化
ラベルエンコードとダミー変数化の違いが今一つ分かっていないのでBard回答をひとまずメモ。↓
ダミー変数化は、カテゴリ変数の各レベルに、1つのダミー変数を作成します。例えば、カテゴリ変数が「赤」「青」「緑」の場合、ダミー変数化では、「赤」に1、 「青」に2、 「緑」に3のダミー変数を作成します。
ラベルエンコーディングは、カテゴリ変数の各レベルに、1つの数値を割り当てます。例えば、カテゴリ変数が「赤」「青」「緑」の場合、ラベルエンコーディングでは、「赤」に0、 「青」に1、 「緑」に2の値を割り当てます。
ダミー変数化は、カテゴリ変数間の順序を保持することができます。一方、ラベルエンコーディングは、カテゴリ変数間の順序を保持することができません。
例えば、カテゴリ変数が「赤」「青」「緑」の場合、ダミー変数化では、「赤」は「青」より大きい値になります。しかし、ラベルエンコーディングでは、「赤」は「青」より大きい値になるわけではありません。
どちらのアルゴリズムを使用するかは、データの特性や機械学習モデルによって異なります。一般的に、カテゴリ変数間の順序を保持する必要がある場合は、ダミー変数化が適しています。一方、カテゴリ変数間の順序を保持する必要がない場合は、ラベルエンコーディングが適しています。
#ダミー変数化
x = pd.get_dummies(x)
ワンホットエンコード
ワンホットエンコーディングは、機械学習モデルにカテゴリ変数を入力するために使用されます。機械学習モデルは、数値データのみを入力として受け入れることができるため、カテゴリ変数を数値に変換する必要があります。ワンホットエンコーディングは、ラベルエンコーディングよりも多くの特徴量を作成しますが、カテゴリ変数間の順序を保持することができます。
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()
# カテゴリ変数のエンコーディング
ohe.fit(カテゴリ変数)
# エンコードされたカテゴリ変数
エンコードされたカテゴリ変数 = ohe.transform(カテゴリ変数).toarray()
#カテゴリ変数が「赤」「青」「緑」の場合
ohe.categories_
Out[108]: array([['赤'],
['青'],
['緑']], dtype=object)
ohe.transform(['赤', '青', '緑']).toarray()
Out[109]:
array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
対数化
対数化とは、ある数値をその数の底にあるべき数で割った値を返す関数です。例えば、10の対数は、log10(10) = 1です。
対数化は、数学的な計算を行うだけでなく、データの分析や機械学習にも使用されます。例えば、データの分布を対数化することで、データの偏りを正したり、データの傾向をよりわかりやすくしたりすることができます。また、機械学習では、対数化を使用して、データの特徴量を正規化したり、データの次元を削減したりすることができます。
import numpy as np
# 対数関数を適用
log_data = np.log(data)
ホールドアウト法
train_test_split()でpandasのデータフレーム、NumPy配列、リストなどの配列データを分割することが可能。
【train_test_split()の引数】
◆位置引数
第一引数(可変長): 分割の対象となる配列。
◆キーワード引数
・test_size:テストデータの割合または個数を指定(0.0 ~ 1.0の割合か、個数を指定)
・train_size: 学習データの割合または個数を指定(0.0 ~ 1.0の割合か、個数を指定)
・shuffle: Trueの場合はデータのシャッフルを行う
・random_state: 乱数シードを指定
from sklearn.model_selection import train_test_split
# データの分割
x = df
y = df['target']
X_train,X_test,y_train,y_test = train_test_split(x,y,train_size = 0.7 ,random_state=0)
K-分割交差検証【KFold】
データセットをK個のグループに分割し、そのうちの1つのグループをテストデータとして使い、残りのK-1個のグループをトレーニングデータとして機械学習モデルを学習させる方法です。この操作をK回繰り返し、各回で得られた評価指標の平均値を最終的な評価指標として使用します。
【KFold()の引数】
・n_split: データの分割数、デフォルトは5
・shuffle: 連続する数字のグループ分けとするか(True もしくはFalse)
・random_state: 乱数の設定
from sklearn.model_selection import KFold
# データセットをロードする
X = np.loadtxt("data.csv", delimiter=",")
y = np.loadtxt("labels.csv", delimiter=",")
#df['カラム名']をXyに指定する場合は.value必要
# K-分割交差検証を行う
kf = KFold(n_splits=10,shuffle=True,random_state=0)#10回分繰り返し
for train_index, test_index in kf.split(X):
# トレーニングデータとテストデータを分割する
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
# 機械学習モデルを学習させる
model = LogisticRegression()#重回帰分析
model.fit(X_train, y_train)
# テストデータでモデルを評価する
score = model.score(X_test, y_test)
print(score)
層化K-分割交差検証【StratifiedKFold】
K-分割交差検証の一種で、目的変数の偏りがある場合や目的変数のクラス数が多い場合に有効な検証方法となり、目的変数のクラス割合を担保しながらデータの分割を行います。
K-分割交差検証では、データセットをランダムに分割するため、クラス分布が偏ってしまうことがあります。層化K-分割交差検証では、データセットのクラス分布を保ったまま分割するため、クラス分布が偏らず、より正確な評価を行うことができます。
クラス要素を元にFold数だけ分割を行い、各クラスの割合が等しくなるようにデータを分割します。(各クラスの割合が8:2などアンバランスな時に効果的)
※目的変数が二値または多クラスである場合にのみ使用できる。目的変数が連続の場合は、StratifiedKFold()を使用できません。
【StratifiedKFold()の引数】
・n_split: データの分割数、デフォルトは5
・shuffle: 連続する数字のグループ分けとするか(True もしくはFalse)
・random_state: 乱数の設定
import pandas as pd
from sklearn.datasets import load_wine
# データのロード
wine = load_wine()
df_wine = pd.DataFrame(data=wine.data,columns=wine.feature_names)
df_wine['target'] = wine.target
# 目的変数のクラス割合
print(df_wine['target'].value_counts(normalize = True))
from sklearn.model_selection import StratifiedKFold
kf = StratifiedKFold(n_splits=3,shuffle=True,random_state=0)
for fold,(train_index, test_index) in enumerate(kf.split(wine.data, df_wine['target'])):
print('FOLD{}'.format(fold))
print(df_wine.iloc[train_index]['target'].value_counts(True))
グループ付き交差検証
学習データとテストデータに同じグループが現れないように分ける場合に有効な検証方法となり、データセットの汎化性能を確保するためをグループ化を行いながらデータの分割を行います。
ユーザIDが付与されている購買履歴データや、患者IDがついた疾患者データなどの検証の時にIDを元にグループ付き交差検証を行うことがあります。
K-分割交叉検証と層化K-分割交叉検証よりも計算量が多いため、データセットのサイズが大きい場合は、実行時間が長くなる可能性があります。
【GroupKFold()の引数】
・n_split: データの分割数、デフォルトは5
from sklearn.model_selection import GroupKFold
X = pd.read_csv('data.csv')
y = pd.read_csv('labels.csv')
# グループの作成
groups = X['group_id']
# グループ付き交差検証の実行
cv = GroupKFold(n_splits=5)
for train_index, test_index in cv.split(X, y, groups):
X_train, X_test = X.iloc[train_index], X.iloc[test_index]
y_train, y_test = y.iloc[train_index], y.iloc[test_index]
# モデルの学習と評価
model = train_model(X_train, y_train)
score = evaluate_model(model, X_test, y_test)
print(score)
cross_val_score 関数
クロスバリデーション手法の一種です。指定された回数、データセットを分割して、モデルの精度を評価します。
【cross_val_score()】の引数】
estimator: 評価するモデル。
X: データ。
y: ラベル。
cv: クロスバリデーションの回数。
scoring: 評価に使用するスコアリング関数。詳細は公式↓
from sklearn.model_selection import cross_val_score
#10回クロスバリデーションを実行し、平均精度を計算する
clf = DecisionTreeClassifier()
X = iris.data
y = iris.target
scores = cross_val_score(clf, X, y, cv=10, scoring='accuracy')
print(scores.mean())
時系列データ分割【TimeSeriesSplit】
日付データなどのカラムを持つ、時系列データの交差検証に使うためのKFold実装。時系列データを対象に予測モデルを構築する場合、過去のデータを使って学習し、未来のデータを使って評価するという順序の時系列になっていなければなりません。
(1FOLD目などの序盤のFOLDのデータは全データに比べてデータ数が減る)
【TimeSeriesSplit()の引数】
・n_split: データの分割数、デフォルトは5
from sklearn.model_selection import TimeSeriesSplit
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([1, 2, 3, 4, 5, 6])
tscv = TimeSeriesSplit(n_splits=5)
for train_index, test_index in tscv.split(X):
print("TRAIN:", train_index, "TEST:", test_index)