機械学習用のデータの準備
機械学習モデルを作成する前に、トレーニングと評価に使用するデータを準備する必要があります。 データは、多くの場合、データ ファイルとして、ソースから Azure Databricks に取り込まれます。 必要に応じて、データ ファイルに基づいてデルタ テーブルを作成し、データの探索と分析を簡略化できます。 データを取り込んだ後、データ科学者はそれを機械学習用に準備します。
通常、データの準備には、2 つの重要なタスクが含まれます。
- データのクレンジング: 機械学習の有用性に影響を与えるデータの問題の特定と軽減。
- 特徴エンジニアリングと前処理: モデルのトレーニングに適した特徴の選択と変換。
データ クレンジング
データのクリーンアップに必要な具体的な手順はプロジェクトによって異なりますが、次のような一般的な問題に対処する必要があります。
- 不完全なデータ: データには、多くの場合、個々のフィールドが欠落しているレコードが含まれます (多くの場合、null 値の存在で示されます)。 欠落している値を特定し、次の方法で軽減する必要があります。
- 適切な代替値による置き換え - 系列での値の補間、平均値 (または中央値) の使用、または他の適切な値の作成。
- 不完全な行の完全な削除 (モデリングのための適切な代表的データが十分に残る場合)
- エラー: データ入力の間違いや上流でのデータ処理の失敗が原因で、データにエラーが含まれることは珍しくありません。 エラーの検出は困難な場合があり、通常は、クエリと視覚化を使用してデータを要約し、特定のフィールドで他のほとんどの値と一致しない値を探すことで、データを精査する必要があります。
- 外れ値: 外れ値とは、データの統計的分布から著しく外側 (上または下) にある値です。 外れ値は、エラーを示す場合や (余分なゼロが含まれる値や、小数点の省略など)、ほとんどの観測値と比較して異常に高い、または低い正規の値である場合があります。 いずれの場合も、極端な外れ値は機械学習モデルのトレーニングに悪影響を与える可能性があります。そのため、通常は、上限または下限のしきい値に設定しなおすか、外れ値を含むレコードをデータセットから削除することで対処するのが最善です。
- 不正なデータ型: 機械学習アルゴリズムは、特徴値に割り当てられたデータ型によって影響を受ける場合があります。 エラーまたは null 値を含むテキスト ファイルに基づくデータセットにより、数値フィールドが文字列データ型に誤ってキャストされることがよくあり、多くの場合、不連続な整数値を表す値が 10 進数 (またはその逆) に誤ってキャストされることがあります。 データのスキーマを調べて、データ値を最も効果的に反映する適切なデータ型を割り当てる必要があります。
- 不均衡なデータ: 機械学習のトレーニングは、発生する可能性のあるさまざまな特徴とラベルの組み合わせがトレーニング データで適切に表現されている場合に、最適に行われます。 不均衡なデータセットでは、特定のカテゴリ値またはフィールドの組み合わせを含むレコードが過剰に表わされており、トレーニング アルゴリズムに影響を与え、モデルにバイアスが発生する可能性があります。 この問題を軽減する一般的な手法は、重複する行を含めることによって表現の少ない値を "オーバーサンプリング" するか、表現の多い行を (データセットから削除することによって) "アンダーサンプリング" することです。
Azure Databricks でこのような問題を検出して処理する最も一般的な方法は、データを探索して操作するコードをノートブックで記述することです。 この種のデータ操作に主に使われるクラスは、Spark のデータフレームです。
たとえば、次のコードは、テキスト ファイルからデータフレームにデータを読み込みます。
df = spark.read.format("csv").option("header", "true").load("/myfolder/mydata.csv")
または、データが Azure Databricks ワークスペースのデルタ テーブルに読み込まれている場合は、SQL クエリを使ってデータフレームにデータを読み込むことができます。
df = spark.sql("SELECT * FROM mytable")
データがデータフレームに読み込まれた後は、Spark SQL ライブラリのそのメソッドや他の関数を使って、データを探索して変換できます。 たとえば、次のコードでは、dropna メソッドを使って、null 値を含む行を削除し、データフレームの列に特定のデータ型を割り当てています。
clean_data = df.dropna().select(col("column1").astype("string"),
col("column2").astype("float"))
ヒント
Spark データフレーム機能について詳しくは、Spark データフレームのドキュメントをご覧ください。
特徴エンジニアリングと前処理
データセットが完全でクリーンであることを確認したら、機械学習用に特徴の準備を始めることができます。 特徴エンジニアリングは反復的なアプローチであり、多くの場合、試行錯誤により、予測値を持つ特徴列と、特徴を表現するのに最適な方法を決定する必要があります。 一般的な特徴エンジニアリングと前処理のタスクは次のとおりです。
新しい特徴の導出: 多くの場合、既存の特徴から新しい、より予測性の高い特徴を導出できます。 たとえば、データセットには "日付" 列が含まれていますが、完全な日付はラベルを識別する際の重要な予測要因ではなく、曜日がそうではないかと思われるものとします。 このような場合、日付から導出される新しい day_of_week 特徴を作成し、その理論をテストできます。
数値特徴の離散化: 場合によっては、特定の値の範囲を表すカテゴリに "離散化" すると、数値の予測性が高くなる可能性があります。 たとえば、"価格" 特徴の値を取得し、適切なしきい値に基づいて "低"、"中"、"高" のカテゴリに割り当てることができます。
カテゴリ特徴のエンコード: 多くのデータセットには、文字列値で表されるカテゴリ データが含まれます。 ただし、ほとんどの機械学習アルゴリズムは数値データで最適に動作します。 そのため、カテゴリを表すために文字列ではなく数値コードを割り当てるのが一般的です。 たとえば、ある製品の詳細のデータセットには、"Green"、"Red"、または "Blue" の値を持つ "色" の特徴が含まれるとします。 これらの値を、簡単な整数コードを使ってエンコードできます ("Green" を 0、"Red" を 1、"Blue" を 2 など)。 または、次のように、"One-hot エンコード" 手法を使って、あり得るカテゴリごとに新しい列を作成し、各行に適切な値として 1 または 0 を各列に割り当てることができます。
"元の色の列" [緑] [赤] 青 緑 1 0 0 青 0 0 1 赤 0 1 0 数値のスケーリング (正規化): 数値データ値は、互いに異なるスケールまたは測定単位になっていることがよくあります。 機械学習アルゴリズムではそれらのすべてが絶対数値として処理され、多くの場合、より大きな値を持つ特徴がモデルのトレーニングを支配する可能性があります。 この問題を解決するには、1 つの列については個々の値が互いに同じ比例関係を維持する一方、すべての数値列が同様のスケールになるように、すべての数値列をスケーリングするのが一般的です。 たとえば、データセットにメートルとキログラムで測定された "長さ" と "重さ" の値が含まれているとします。 次のように、これらの両方の特徴を 0 から 1 の間にスケーリングされた値に変換できます。
length weight scaled_length scaled_weight 250.0 2.1 0.250 0.210 176.0 0.9 0.176 0.09
多くの機械学習ライブラリには、一般的な特徴エンジニアリング タスクを実行するために使用できるクラスが含まれています。 たとえば、Spark MLlib ライブラリに含まれる StringIndexer クラスを使うと、文字列値に対して簡単な整数ベースのエンコードを実行できます。
from pyspark.ml.feature import StringIndexer
encoder = StringIndexer(inputCol="catCol", outputCol="catColCode")
encoded_data = encoder.fit(data).transform(data)
Note
StringIndexer のコード サンプルについては、もう少し詳しく説明する価値があります。 Spark MLlib クラスには、特定の変換操作のアルゴリズムを一部のサンプル データに適合させる "エバリュエーター" が含まれることがあります。 この場合、StringIndexer は、エンコード アルゴリズムを data データフレームの catCol 列の個別の文字列値に適合させて、エンコードされた値を含む新しい catColCode 列を生成するために必要な特定の計算を決定します。 エバリュエーターの出力は、エバリュエーターによって定義された関数をカプセル化する "トランスフォーマー" であり、その関数をデータに適用して新しいデータフレームを生成できます。 この例では、エンコード関数を "決定" するために使われたのと同じデータを結果のトランスフォーマーに渡して、実際にエンコードを "適用" しています。
Spark MLLib では、データの準備に必要なすべての特徴エンジニアリングと前処理の手順を実行する "パイプライン" に、一連のエバリュエーターとトランスフォーマーをまとめて連結できます。 パイプラインは、準備された特徴からラベルを予測するために必要な操作を決定するエバリュエーターとして機能する機械学習アルゴリズムで終了できます。 パイプラインの出力は機械学習モデルであり、これは実際には、モデル関数をデータフレームの特徴に適用して、対応するラベル値を予測するために使用できるトランスフォーマーです。