機械学習でボートレース予想してみた④ モデル作成 編

機械学習

ついに予測か。

まだです。次は予測に必要なモデルを作るよ。

なにそれ。

うーん。予測するために必要なものかな?

機械学習でボートレース予想実現までの工程

今回は「5.機械学習でモデル作成」を中心にまとめてます。

 1.機械学習について調査

 2.技術選定
 3.環境構築

 4.機械学習用のデータ取得


 5.機械学習でモデル作成(今回はここ!)
 6.作成したモデルで予測

この後に、舟券投票や機械学習モデルを改善する工程もありますが、このシリーズでは予測までをまとめてます。

機械学習モデルとは?

今回使用するML.NETでは、モデルとは以下のように定義されています。

ML.NET モデルは、予測される出力に到達するために入力データに対して実行される変換を含むオブジェクトです。

ML.NET の概要とそのしくみ – ML.NET | Microsoft Learn

私も完全に理解できているわけではないので、説明がちょっと難しいのですが、今回のボートレースを例に挙げて説明します。レース開始前のデータが入力データだとしたら、そのレース結果を予測(出力)するのに使用するものが機械学習モデルです。

モデル作成までの流れ

機械学習にはいくつかの方法がありますが、今回のボートレースの予測で選択した教師あり学習では、答えがある過去のデータを使用し学習させることでモデルを作ります。

教師あり学習とは、答えが含まれるデータを使用して学習することで、答えなしのデータから答えを予測する手法になります。機械学習や教師あり学習については、前の記事にもう少し詳しく書いているので見てみてください。

今回はボートレースの着順を予想したいので「着順」を答えとし、その他の選手の能力を表す数値やモーター勝率などを学習に使用するトレーニングデータとして使用します。

流れとしては下記のとおりです。詳しくは下で説明していきます。
1.データ準備(前処理)
2.データとトレーニングデータとテストデータに分割
3.目的変数と説明変数の選択
4.学習アルゴリズムの設定
5.トレーニングデータを使用してモデル作成
6.テストデータを使用してモデルの性能評価

今回、ML.NETで機械学習をするにあたって、下記のIris Flowers Classificationがとても参考になりました。作成したコード全体の公開は考えていませんが、具体的なサンプルとしてこちらを見ると分かりやすそうです。

モデル作成

1.データ準備(前処理)

データ準備といっても前の記事で説明したデータ取得とは異なり、こちらでは取得した生データをコンピュータが整理しやすいように変換や整理を行います。

以下のような数値となっていないデータは数値化する必要があります。
 ・階級(A1,A2,B1,B2)など分類
 ・レースタイムなどの時間
 ・選手名などの文字
 ・真偽値のようなフラグ

生データのままではコンピュータは理解できず処理できないためです。

他にも欠損値(Nullデータや空データ)の補完・削除や、外れ値(極端に大きな値、極端に小さな値)の削除など行う場合もあります。実施しない場合、作成されたモデルの精度が下がってしまうためです。

2.データとトレーニングデータとテストデータに分割

前処理が終わったら、データをトレーニングデータとテストデータに分割します。
テストデータはモデル評価に使用しますが、学習時に使用したデータを評価時にも使用した場合、正しい評価ができないので、データのうちの一部を事前に分割しておきます。

私は10%をテストデータにしてますが、データ量に合わせて選択する必要があるため決まった値があるわけではないようです。

トレーニングデータモデルの学習をするのに使用
テストデータモデルを評価するのに使用

ML.NETではTrainTestSplitを使用してトレーニングデータとテストデータを分割できます。
レースごとに一意になるキーをsamplingKeyColumnNameに指定することで、分割する際の同じレースが分割されてしまうことを避けることもできます。

var dataView = mlContext.Data.LoadFromEnumerable<RaceModel>(data);
var split = mlContext.Data
    .TrainTestSplit(dataView, testFraction: 0.1, samplingKeyColumnName: "GroupId");

// トレーニングデータ
var trainSet = mlContext.Data
    .CreateEnumerable<RaceModel>(split.TrainSet, reuseRowObject: false);
CommonFunctions.DataProcessing(ref trainSet);
var trainingDataView = mlContext.Data.LoadFromEnumerable<RaceModel>(trainSet);

// テストデータ
var testSet = mlContext.Data
    .CreateEnumerable<RaceModel>(split.TestSet, reuseRowObject: false);
CommonFunctions.DataProcessing(ref testSet);
var testDataView = mlContext.Data.LoadFromEnumerable<RaceModel>(testSet);

もちろん、↑の方法でなくてもデータが分割出来たらOKです。

私はGroupIdとしてレース日付・レース場番号・レース番号を文字にしてつなげたものとしてます。

public uint GroupId
{
    get
    {
        return uint.Parse($"{RaceDate.ToString("yyMMdd")}{StadiumId:00}{RaceNo:00}");
    }
}

3.目的変数と説明変数の選択

目的変数とは予測したい項目になります。今回は「着順」です。
それに対して説明変数とは、準備したデータの中で、着順を予測に使用する項目の事です。
例えば以下のようなものがあります。

目的変数着順
説明変数階級、枠番、体重、平均ST、能力指数、全国勝率、
当地勝率、モーター勝率、ボート勝率 など

ここで何を選択するかによって、予測精度に影響があります。また、説明変数の項目数とデータ量の関係によって正しい分析ができない場合があります。

「着順」を説明変数に含めないように注意してください。目的となる答えを予測に使用することになります。

また、「順位確定後」に分かる内容を特徴量として使用する場合は注意してください。例えば天気や風速などの水面気象情報です。水面気象情報は公式サイトで公開されていますが、ひとつ前のレースのものです。

説明変数は、取込データだけでなく、持っているデータを組み合わせて作ることも可能です。
コース別の勝率や事故率など

// inputColumnNameは目的変数[順位]の項目名、featureColsは説明変数の配列
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "KeyColumn", inputColumnName: nameof(RaceModel.Label))
    .Append(mlContext.Transforms.Concatenate("Features", featureCols));

4.学習アルゴリズムの設定

次は分析方法に応じた学習アルゴリズムを設定します。ML.NETでは教師あり学習の分析方法は、二項分類・多クラス分類・回帰などいくつかの方法が選択可能です。今回は分類方法として多クラス分類を選択しました。

多クラス分類を選択した理由としては
 ・理解しやすかった
 ・ボートレースは6艇固定

だからです。着順を目的として、多クラス分類した場合、1位~6位の予測割合が分類結果が出力されます。

また、多クラス分類で使用できるアルゴリズムについてです。
下記の多クラス分類トレーナーに記載がありますが、今回はLightGbmMulticlassTrainerを選択しました。

LightGbmを選択した理由としては、高速ということと調べた当時人気があったからです。。具体的な理由があるわけではありません。そのため、他のアルゴリズムを選択したら精度が上がる可能性もあるので、今後検証していきたいです。

var trainer = mlContext.MulticlassClassification.Trainers
    .LightGbm(labelColumnName: "KeyColumn", featureColumnName: "Features")
    .Append(mlContext.Transforms.Conversion.MapKeyToValue(outputColumnName: nameof(RaceModel.Label), inputColumnName: "KeyColumn"));

var trainingPipeline = dataProcessPipeline.Append(trainer);

5.トレーニングデータを使用してモデル作成

ここまで済んだら、モデルをトレーニングします。
トレーニングした機械学習モデルは保存しておくことで予測時に使用可能です。

// モデルをトレーニングします。
var trainedModel = trainingPipeline.Fit(trainingDataView);

// モデル保存します。保存したモデルは予測時に使用できます。
mlContext.Model.Save(trainedModel, trainingDataView.Schema, modelPath);

6.テストデータを使用してモデルの性能評価

最後にテストデータを使用してモデルの性能評価をします。ML.NETでは下記のようにモデルを評価したり、選択した説明変数の重要度を図るものが用意されていますのでそれを使用して確認することが可能です。

MulticlassClassificationMetrics多クラス分類トレーナーの評価結果
PermutationFeatureImportance多クラス分類の順列特徴の重要度

説明変数の重要度の絶対値が低い項目の場合は、今回の順位を予測するのに影響を与えていない可能性があるので、モデルから取り除くことを検討することになります。評価結果の各項目の意味については説明も難しいので、気になる人は調べてみてください。

私は上記に加えて実際に作成したモデルを使用して予測し、どのぐらい予測と順位が一致しているかを確認するようにしていますが、予測の方法については次回にしますので、ここでは割愛します。

まとめ

今回はモデル作成についてまとめてみました。
ML.NETは公式サイト以外にあまり日本語のドキュメントが無かったの、細かい部分を調べる時に大変でしたが、サンプルがしっかりとあったので最低限動かすところまでは分かりやすかった印象です。
(MacだとM2に対応してないのか動かないところがあったので、悩みましたがいったんWindowsで動いているので良しとしてます。。)

次回、最後のモデル予測編に続きます。

※当ブログに掲載されている情報は、可能な限り正確性を重視していますが、正確性について保証するものではありません。読者の方々は、自己責任において情報を活用してください。

コメント

タイトルとURLをコピーしました