2025/04/30

スゲー!のかな? Visual StudioのIntellisense!!

これ、少し前ってかVisual Studio 2022の目玉だった? 正確な記憶が残ってませんが、ここの所も別にサボってた訳じゃなくひたすらコード書いてたのでこちらにはあまり書き込む余裕が無かったんです。でも、登場当初よりも更に磨きかけて助けてくれる様になってきた気がします。

その昔はキーボードマクロなんかで少しでも楽して大量のコードの記述してたんですが、ストラクチャーやクラスのメンバーなんかのあまり覚えてない部分でも候補だしてくれるので、そこから選択すれば可能なのは本当に助かってますが、Copilotなんかのサポートも入れ込んだものになってきたのか入力が格段に効率アップしてます。

PythonのTensorFlowで訓練したモデルのC#での利用って事で進めてますが、また無駄な時間の浪費になるのも覚悟で...いや、結局外部プロセスでの実装を選択したんですが、この際なので...まあ、そもそも順位予測には走破タイムの予測を入れてます。テスト的に行った訓練にはモデルビルダーの学習モデルが吐き出した走破タイム予測を利用してますが、どうせやるなら、その走破タイムの予測もTensorFlowにした方が筋が通るかなって事でね。まずは新馬戦学習用CSV出力のMシリーズでの書き直し。AutoMLにしてもモデルビルダーにしても、走破タイムの予測は個々の馬で予測させて来ましたが、どうなるかは未知ですが、レース毎に出走馬全てを一括で走破タイムの予測を行う事がTensorFlowでは可能なので試してみようと必死にコーディング中。出来ればある程度の形にGW中に仕上げられれば、最悪微調整なんかはその後でもと思って進めてます。

まあ、ズッコケたら日の目を見ずにお蔵入りですけどね😓

2025/04/26

C#でTensorFlowのモデル利用

モデル訓練も2つ程終わらせてるので実際に利用可能か試し始めました。簡単に利用するにはML.NETでロードして利用がと思い調べて試してます。

  • Microsoft.ML
  • Microsoft.ML.TensorFlow
  • SciSharp.TensorFlow.Redist

これらがまず必要なのはわかりインストール。

  1. using Microsoft.ML;
  2. using Microsoft.ML.Data;
  3.  
  4. namespace TFCheck;
  5.  
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. var mlContext = new MLContext();
  11. // Load the model
  12. var modelPath = @"TFMJuniFullCK";
  13. var tensorFlowModel = mlContext.Model.LoadTensorFlowModel(modelPath);
  14. // 入力と出力のスキーマを確認
  15. var schema = tensorFlowModel.GetInputSchema();
  16. Console.WriteLine("Input Schema:");
  17. foreach (var column in schema)
  18. {
  19. Console.WriteLine($"Name: {column.Name}, Type: {column.Type}");
  20. }
  21. }
  22. }

こんな単純なのが最初動かない。少し調べると何のことはないです。この所では珍しくない事でx86がサポートされてない。自力でx86用にビルドすれば可能のようですがそこまでするのは面倒が多過ぎる。が、ちょっと悩むなぁ。苦労してビルドしてうまく行くならアプリにも組み込めます。逆にx64で行くならまた外部プロセスにする事になる。

2025/04/24

TensorFlowモデル訓練で痛恨のミス

モデル訓練が順調に走ってる事は事前に色々Copilotにも相談しながら進めてたので問題無かったんですが、コード自体は更に続いて予測、結果表示、保存と進んでいくんですが、訓練までしかテストしないまま訓練スタートさせて、今回はなんと5.5日の予定だったのが、まあそれよりちょっと早く(?)昨夜終わったんです。が!その後の予測でエラー!となり、保存まで行かなかったのでここまでの苦労は全て無駄にorz いや、全くの無駄かといえば、ここまでやるとかなり訓練されるのは分かったし、ここまでやってもEarlyStoppingにならないのでもっと長くやれば更にって事なのは分かりました。

現在保存まで行ける筈の修正込みでEpochs=50で訓練中。ああ、訓練済みのモデルロードして更に訓練も出来る筈なのでその辺りも試そうとは思います。

しかし、今回の訓練でのPC連続稼働で電気代はザックリな計算で2,700円を無駄にした。750Wの電源つけてるPCだからって本当に750W使ってるかは別として24時間で540円程度。別に訓練とかしてなくても週末なんかだと朝起きて寝るまで18時間程度PCは動かしてるので、それだけで400円程電気代掛かってると再認識すると...いや、でもPCは必要だから😓

2025/04/18

iOS 18.4.1

以前ここにApple Intelligenceの事を昨年暮れに書いてますが、実はその後に何度となく言語設定変更してImage Playgroundで遊んでたんですが、確かハングする感じがあり、まっ、対処方法はアンインストールして入れなおせば直るかなぁって単純に考えてアンインストールしました。で、App Storeで検索すれば出てきて出来る筈が出てくるのは似たアプリばかりで本物が出てこない。

まあ、ちょっとインチキではないが、本来まだ日本語では利用出来ないものを利用してたのでiOS 18.4で日本語対応して直るだろう思ってたんですが...App Storeで見つけられない。確かにSiriなんかは画面の周りが光る新しいものに変わってるのに。で、AppleのFAQなんかも見たり、CopilotやSiriに質問ぶつけたりしたけど解決出来ないのでAppleのサポートに直接問い合わせしました。しかし、サポートでもなぜApp Storeで検索出来ないか原因が分からずでした。そのうちに修正されると思いますって言われてました。

で、数日前にiOS 18.4.1がリリースれたのでアップデート。特に何が修正されたとか確認はしてませんでしたが、ダメ元でApp Storeで検索すると出てくれました😍

TensorFlowのモデルの訓練

先日書いたPythonでTensorFlow使ってモデルの訓練したってやつは、まあ、さらだでもやった順位予測の一番シンプルなファクター(特徴量)数の31個だったので、まあ、Epochsを50程度で本当にさらっと学習させられるものでした。

でまあ、TensorFlowの基本的な流れは出来たのでCSVデータもRaceJuniFullCKと同等なものを出力させてファクター数も230個と格段に増やしました。

  1. # 入力データ(特徴量)
  2. X = data[[
  3. "JouCD", "KaisaiTuki", "KaisaiKai", "KaisaiNichi",
  4. "TrackCD", "Course", "Kyori", "Tousu", "Tenko", "Baba",
  5. "KyosouShubetu", "KyosouJouken", "JuuryoShubetu", "StandardDeviation",
  6. "Uma1Barei", "Uma1Sex", "Uma1Blinkers", "Uma1Kinryo",
  7. "Uma1Kyakusitu1", "Uma1Kyakusitu2", "Uma1Kyakusitu3", "Uma1Kyakusitu4",
  8. "Uma1Kishu", "Uma1Chokyosi", "Uma1Souha", "Uma1DeviationValues",
  9. "Uma2Barei", "Uma2Sex", "Uma2Blinkers", "Uma2Kinryo",
  10. "Uma2Kyakusitu1", "Uma2Kyakusitu2", "Uma2Kyakusitu3", "Uma2Kyakusitu4",
  11. "Uma2Kishu", "Uma2Chokyosi", "Uma2Souha", "Uma2DeviationValues",
  12. "Uma3Barei", "Uma3Sex", "Uma3Blinkers", "Uma3Kinryo",
  13. "Uma3Kyakusitu1", "Uma3Kyakusitu2", "Uma3Kyakusitu3", "Uma3Kyakusitu4",
  14. "Uma3Kishu", "Uma3Chokyosi", "Uma3Souha", "Uma3DeviationValues",
  15. "Uma4Barei", "Uma4Sex", "Uma4Blinkers", "Uma4Kinryo",
  16. "Uma4Kyakusitu1", "Uma4Kyakusitu2", "Uma4Kyakusitu3", "Uma4Kyakusitu4",
  17. "Uma4Kishu", "Uma4Chokyosi", "Uma4Souha", "Uma4DeviationValues",
  18. "Uma5Barei", "Uma5Sex", "Uma5Blinkers", "Uma5Kinryo",
  19. "Uma5Kyakusitu1", "Uma5Kyakusitu2", "Uma5Kyakusitu3", "Uma5Kyakusitu4",
  20. "Uma5Kishu", "Uma5Chokyosi", "Uma5Souha", "Uma5DeviationValues",
  21. "Uma6Barei", "Uma6Sex", "Uma6Blinkers", "Uma6Kinryo",
  22. "Uma6Kyakusitu1", "Uma6Kyakusitu2", "Uma6Kyakusitu3", "Uma6Kyakusitu4",
  23. "Uma6Kishu", "Uma6Chokyosi", "Uma6Souha", "Uma6DeviationValues",
  24. "Uma7Barei", "Uma7Sex", "Uma7Blinkers", "Uma7Kinryo",
  25. "Uma7Kyakusitu1", "Uma7Kyakusitu2", "Uma7Kyakusitu3", "Uma7Kyakusitu4",
  26. "Uma7Kishu", "Uma7Chokyosi", "Uma7Souha", "Uma7DeviationValues",
  27. "Uma8Barei", "Uma8Sex", "Uma8Blinkers", "Uma8Kinryo",
  28. "Uma8Kyakusitu1", "Uma8Kyakusitu2", "Uma8Kyakusitu3", "Uma8Kyakusitu4",
  29. "Uma8Kishu", "Uma8Chokyosi", "Uma8Souha", "Uma8DeviationValues",
  30. "Uma9Barei", "Uma9Sex", "Uma9Blinkers", "Uma9Kinryo",
  31. "Uma9Kyakusitu1", "Uma9Kyakusitu2", "Uma9Kyakusitu3", "Uma9Kyakusitu4",
  32. "Uma9Kishu", "Uma9Chokyosi", "Uma9Souha", "Uma9DeviationValues",
  33. "Uma10Barei", "Uma10Sex", "Uma10Blinkers", "Uma10Kinryo",
  34. "Uma10Kyakusitu1", "Uma10Kyakusitu2", "Uma10Kyakusitu3", "Uma10Kyakusitu4",
  35. "Uma10Kishu", "Uma10Chokyosi", "Uma10Souha", "Uma10DeviationValues",
  36. "Uma11Barei", "Uma11Sex", "Uma11Blinkers", "Uma11Kinryo",
  37. "Uma11Kyakusitu1", "Uma11Kyakusitu2", "Uma11Kyakusitu3", "Uma11Kyakusitu4",
  38. "Uma11Kishu", "Uma11Chokyosi", "Uma11Souha", "Uma11DeviationValues",
  39. "Uma12Barei", "Uma12Sex", "Uma12Blinkers", "Uma12Kinryo",
  40. "Uma12Kyakusitu1", "Uma12Kyakusitu2", "Uma12Kyakusitu3", "Uma12Kyakusitu4",
  41. "Uma12Kishu", "Uma12Chokyosi", "Uma12Souha", "Uma12DeviationValues",
  42. "Uma13Barei", "Uma13Sex", "Uma13Blinkers", "Uma13Kinryo",
  43. "Uma13Kyakusitu1", "Uma13Kyakusitu2", "Uma13Kyakusitu3", "Uma13Kyakusitu4",
  44. "Uma13Kishu", "Uma13Chokyosi", "Uma13Souha", "Uma13DeviationValues",
  45. "Uma14Barei", "Uma14Sex", "Uma14Blinkers", "Uma14Kinryo",
  46. "Uma14Kyakusitu1", "Uma14Kyakusitu2", "Uma14Kyakusitu3", "Uma14Kyakusitu4",
  47. "Uma14Kishu", "Uma14Chokyosi", "Uma14Souha", "Uma14DeviationValues",
  48. "Uma15Barei", "Uma15Sex", "Uma15Blinkers", "Uma15Kinryo",
  49. "Uma15Kyakusitu1", "Uma15Kyakusitu2", "Uma15Kyakusitu3", "Uma15Kyakusitu4",
  50. "Uma15Kishu", "Uma15Chokyosi", "Uma15Souha", "Uma15DeviationValues",
  51. "Uma16Barei", "Uma16Sex", "Uma16Blinkers", "Uma16Kinryo",
  52. "Uma16Kyakusitu1", "Uma16Kyakusitu2", "Uma16Kyakusitu3", "Uma16Kyakusitu4",
  53. "Uma16Kishu", "Uma16Chokyosi", "Uma16Souha", "Uma16DeviationValues",
  54. "Uma17Barei", "Uma17Sex", "Uma17Blinkers", "Uma17Kinryo",
  55. "Uma17Kyakusitu1", "Uma17Kyakusitu2", "Uma17Kyakusitu3", "Uma17Kyakusitu4",
  56. "Uma17Kishu", "Uma17Chokyosi", "Uma17Souha", "Uma17DeviationValues",
  57. "Uma18Barei", "Uma18Sex", "Uma18Blinkers", "Uma18Kinryo",
  58. "Uma18Kyakusitu1", "Uma18Kyakusitu2", "Uma18Kyakusitu3", "Uma18Kyakusitu4",
  59. "Uma18Kishu", "Uma18Chokyosi", "Uma18Souha", "Uma18DeviationValues"
  60. ]]

出力データは以前のものと同じです。で、今回は当たり前ですが本格的に取り組みました。Copilotとまあ平日で夜勤なのでちょっと眠い感じではありますが、可能な限り作業を続け3日目となる昨日出勤2時間前程度にどうにか訓練してくれる所までこぎつけました。

  1. # コースは小数点第1位までの実数ですが、整数に変換する必要があります。
  2. X["Course"] = (X["Course"] * 10).astype(int) # コースデータを10倍して整数化

このコース区分はAutoMLやLightGBM用のCSVデータでもそうだったんですがコース区分を数値にしてて、"A"~"E"だけど、中には"A1"とかもあるって事で"A"は1.0、"A1"は1.1的にしてました。ML.NET系は基本実数なので特に問題なく使えてましたが、TensorFlowでファクター(特徴量)をカテゴリ変数とする場合にはint64である必要があるのでこんな感じでデータを前処理加工。

  1. # レースのカテゴリ変数
  2. X_train_inputs = [
  3. X_train["JouCD"], X_train["KaisaiTuki"], X_train["TrackCD"], X_train["Course"], X_train["Tenko"], X_train["Baba"],
  4. X_train["KyosouShubetu"], X_train["KyosouJouken"], X_train["JuuryoShubetu"]
  5. ]
  6. # レースの数値データを追加
  7. X_train_inputs.extend([
  8. X_train["KaisaiKai"], X_train["KaisaiNichi"], X_train["Kyori"], X_train["Tousu"], X_train["StandardDeviation"]
  9. ])

こんな感じで指定しました。馬毎のファクターも同様にカテゴリ変数と数値データを指定。

  1. # ウマごとのカテゴリ変数を追加
  2. for i in range(18):
  3. X_train_inputs.extend([
  4. X_train[f"Uma{i+1}Sex"], X_train[f"Uma{i+1}Blinkers"], X_train[f"Uma{i+1}Kishu"], X_train[f"Uma{i+1}Chokyosi"]
  5. ])
  6.  
  7. # ウマごとの数値データを追加
  8. X_train_inputs.extend([
  9. X_train[f"Uma{i+1}{feature}"]
  10. for i in range(18)
  11. for feature in ["Barei", "Kinryo", "Kyakusitu1", "Kyakusitu2", "Kyakusitu3", "Kyakusitu4", "Souha", "DeviationValues"]
  12. ])

で、TensorFlowではお決まりの層を定義していく為に

  1. # レースのカテゴリ変数を定義
  2. input_joucd = Input(shape=(1,), name="JouCD") # 場コード
  3. embedding_joucd = Embedding(input_dim=11, output_dim=4)(input_joucd) # 場コードの埋め込み
  4. flatten_joucd = Flatten()(embedding_joucd)
  5. input_kaisaituki = Input(shape=(1,), name="KaisaiTuki") # 開催月
  6. embedding_kaisaituki = Embedding(input_dim=13, output_dim=4)(input_kaisaituki) # 開催月の埋め込み
  7. flatten_kaisaituki = Flatten()(embedding_kaisaituki)
  8. input_trackcd = Input(shape=(1,), name="TrackCD") # トラックコード
  9. embedding_trackcd = Embedding(input_dim=60, output_dim=4)(input_trackcd) # トラックコードの埋め込み
  10. flatten_trackcd = Flatten()(embedding_trackcd)
  11. input_course = Input(shape=(1,), name="Course") # コース
  12. embedding_course = Embedding(input_dim=100, output_dim=4)(input_course) # コースの埋め込み
  13. flatten_course = Flatten()(embedding_course)
  14. input_tenko = Input(shape=(1,), name="Tenko") # 天候
  15. embedding_tenko = Embedding(input_dim=7, output_dim=2)(input_tenko) # 天候の埋め込み
  16. flatten_tenko = Flatten()(embedding_tenko)
  17. input_baba = Input(shape=(1,), name="Baba") # 馬場状態
  18. embedding_baba = Embedding(input_dim=5, output_dim=2)(input_baba) # 馬場状態の埋め込み
  19. flatten_baba = Flatten()(embedding_baba)
  20. input_kyosoushubetu = Input(shape=(1,), name="KyosouShubetu") # 競走種別
  21. embedding_kyosoushubetu = Embedding(input_dim=25, output_dim=2)(input_kyosoushubetu) # 競走種別の埋め込み
  22. flatten_kyosoushubetu = Flatten()(embedding_kyosoushubetu)
  23. input_kyosoujouken = Input(shape=(1,), name="KyosouJouken") # 競走条件
  24. embedding_kyosoujouken = Embedding(input_dim=1000, output_dim=8)(input_kyosoujouken) # 競走条件の埋め込み
  25. flatten_kyosoujouken = Flatten()(embedding_kyosoujouken)
  26. input_juuryoushubetu = Input(shape=(1,), name="JuuryoShubetu") # 斤量種別
  27. embedding_juuryoushubetu = Embedding(input_dim=5, output_dim=2)(input_juuryoushubetu) # 斤量種別の埋め込み
  28. flatten_juuryoushubetu = Flatten()(embedding_juuryoushubetu)
  29.  
  30. # レースの数値変数を定義
  31. input_kaisai_kai = Input(shape=(1,), name="KaisaiKai") # 開催回
  32. input_kaisai_nichi = Input(shape=(1,), name="KaisaiNichi") # 開催日
  33. input_kyori = Input(shape=(1,), name="Kyori") # 距離
  34. input_tousu = Input(shape=(1,), name="Tousu") # 頭数
  35. input_standard_deviation = Input(shape=(1,), name="StandardDeviation") # 標準偏差

てな感じでして

  1. # レースの特徴量を結合
  2. race_features = Concatenate()([
  3. flatten_joucd, flatten_kaisaituki, flatten_trackcd, flatten_course, flatten_tenko, flatten_baba,
  4. flatten_kyosoushubetu, flatten_kyosoujouken, flatten_juuryoushubetu,
  5. input_kaisai_kai, input_kaisai_nichi, input_kyori, input_tousu, input_standard_deviation
  6. ])
  7. race_dense = Dense(64, activation='relu')(race_features) # 隠れ層の学習
  8. race_dense = Dense(32, activation='relu')(race_dense) # 更に学習層を追加

この後、当然馬毎の入力層も定義し

  1. # 馬ごとのネットワーク
  2. merged_horses = Concatenate()(uma_networks)
  3.  
  4. # レース特徴量と馬特徴量を結合
  5. final_features = Concatenate()([race_dense, merged_horses])
  6.  
  7. # 結合後のネットワーク全体
  8. x = Dense(128, activation='relu')(final_features) # 隠れ層
  9. output = Dense(18, activation='linear', name="Output")(x) # 出力層

これで、層は出来たので

  1. # モデルを構築
  2. model_inputs = [input_joucd, input_kaisaituki, input_trackcd, input_course, input_tenko, input_baba,
  3. input_kyosoushubetu, input_kyosoujouken, input_juuryoushubetu,
  4. input_kaisai_kai, input_kaisai_nichi, input_kyori, input_tousu, input_standard_deviation] + uma_inputs
  5. model = Model(inputs=model_inputs, outputs=output)

後は入力データを↑の様に整えるのに

  1. X_train_inputs = [
  2. X_train["JouCD"], # JouCD
  3. X_train["KaisaiTuki"], # KaisaiTuki
  4. X_train["TrackCD"], # TrackCD
  5. X_train["Course"], # Course
  6. X_train["Tenko"], # Tenko
  7. X_train["Baba"], # Baba
  8. X_train["KyosouShubetu"], # KyosouShubetu
  9. X_train["KyosouJouken"], # KyosouJouken
  10. X_train["JuuryoShubetu"], # JuuryoShubetu
  11. X_train["KaisaiKai"], # KaisaiKai
  12. X_train["KaisaiNichi"], # KaisaiNichi
  13. X_train["Kyori"], # Kyori
  14. X_train["Tousu"], # Tousu
  15. X_train["StandardDeviation"], # StandardDeviation
  16. ]
  17. for i in range(18):
  18. X_train_inputs.extend([
  19. X_train[f"Uma{i+1}Sex"], # Uma{i+1}Sex
  20. X_train[f"Uma{i+1}Blinkers"], # Uma{i+1}Blinkers
  21. X_train[f"Uma{i+1}Kishu"], # Uma{i+1}Kishu
  22. X_train[f"Uma{i+1}Chokyosi"], # Uma{i+1}Chokyosi
  23. X_train[f"Uma{i+1}Barei"], # Uma{i+1}Barei
  24. X_train[f"Uma{i+1}Kinryo"], # Uma{i+1}Kinryo
  25. X_train[f"Uma{i+1}Kyakusitu1"], # Uma{i+1}Kyakusitu1
  26. X_train[f"Uma{i+1}Kyakusitu2"], # Uma{i+1}Kyakusitu2
  27. X_train[f"Uma{i+1}Kyakusitu3"], # Uma{i+1}Kyakusitu3
  28. X_train[f"Uma{i+1}Kyakusitu4"], # Uma{i+1}Kyakusitu4
  29. X_train[f"Uma{i+1}Souha"], # Uma{i+1}Souha
  30. X_train[f"Uma{i+1}DeviationValues"], # Uma{i+1}DeviationValues
  31. ])

として、モデルの訓練は以前のものほぼ変わらずですが、

  1. # モデルの訓練
  2. from tensorflow.keras.callbacks import EarlyStopping
  3. early_stopping = EarlyStopping(monitor='val_rmse', patience=5, mode='min')
  4. history = model.fit(
  5. X_train_inputs, # 入力データをリスト形式で渡す
  6. Y_train, # 出力データ(ターゲット)
  7. epochs=2000,
  8. batch_size=32,
  9. validation_split=0.2,
  10. callbacks=[early_stopping]
  11. )

流石に複雑なのでってのと、何度もやるのは辛いと想像して最初からepochsを2,000にしてます。ただ、これ、ちょっとザックリと指定してしまいましたが、昨日スタートすると明らかに各epochがこれまでと違い時間が掛かります。特にプログラム的に時間表示させたりしてないので目測的に測ると4分とかです。たった今205回目が終わってました。4×205=820÷60=13.6時間です。もし、過学習でEarlyStoppingにならないと4×2,000=8,000÷60=133.3÷24=5.5日です😰

今晩も夜勤で出勤しますが、訓練が終わらない事には予測させるコーディングも進められないので今週末には間に合わない。まっ、GW中には形に出来れば...

追記 2025.4.19 18:30
少し前に675個目のepochが終わりました。TensorFlowってテキストベースでログが出て各epochの終わりに

って感じで出るんですが、地味に進んでるのでEarlyStoppingにはならないのかな? 勝手にそろそろ終わるんじゃね?っと思ったんですが地味に続くのが良いのか悪いのか😓 MicrosoftをGoogleが超えるのをマジ期待してたりもします😉
いや、AutoMLやML.NET、LightGBMはMicrosoftで、TensorFlowはGoogleって話なら...

いやね、そろそろ、いつEarlyStoppingになってもって思ってますが地味に進んでるのがepochs=2000って指定が良かったのかが...ここまで36時間以上なのでやり直しは簡単ではないので期待してる😉

追記 2025.4.19
↑の追記は間違いが多いかな。多分675/2000って出てるEpochですが、これ次に始まった奴だったと思うので、厳密には674個目の終わりだった。更にそろそろ36時間以上ではなく48時間以上だな。いや、一昨日の出勤2時間前にコーディング終えてスタートしたんでね😉 先程750個目がスタートした。

追記 2025.4.20
何が失敗っていきなり2,000epochsで行った事ですね😭 いや、実際問題としてはその位必要な感じで進んではいます。だからこそ中断という選択は無いんです。ただ、今回ってbatch_size=32で行ったんですが、こちらのPCには64GB積んでるんでbatch_size=64でも行けたかも? これ指定してれば半分で済んだかも? その辺りも後から分かったけど今更中断出来ないのが辛いです。開始してからこれに要する時間が5.5日程度と分かった時点で一旦止める判断しなかったのが悔やまれますが、これも自分の知識不足が原因として。先程929回目がスタートしました。まだ半分に届いてない。でもloss: 6.1598と確実に進んでるのは分かります。進まなければEarlyStoppingが効くはずなのでね。まいったなぁ、終わるのはこのまま行くと3.4日後って木曜日になるのかなぁorz

2025/04/15

PythonのTensorFlow

確かにこれまでの苦労がうその様に楽に動きます。C#に固執しなければ良さげですが、そうもいかないのはこれまでの蓄積したアプリの形。ここにどうにかTensorFlowのモデルを読み込んで利用出来るまでもって行きたい。

主に順位予測に対してなんですが、ここまでModel BuilderでRMSE 3.0880とか、LightGBMではRMSE 3.6735程度。これがまあ検証は出来ていませんが、RMSE 2.77とか2.78辺りが出てます。Epochsがやり始めは50だったけど、Copilotに相談しながらLightGBMでも採用している過学習させない工夫入れたり、特徴量のグループ化等取り入れて何度か500まで試してるんですが、それでもEarly Stoppingされないって事は回数足りてないので明日もう少し増やしてどこまでになるか確認します。

しかし、ここまで苦労しててもC#でモデル読み込んで予測可能にならなかったら...

2025/04/13

ディープラーニングを諦めた訳ではない

ここにも何度となく色々な事にチャレンジしている事は書いてます。まあ、その主軸はディープラーニングであるTensorFlowなんですが、これ自体は本来ってかPythonで使うものなので自分自身がPythonをあまり好きになれず、ってかねぇ、60歳過ぎて手を出した訳だし自分の脳が馴染めないだけなんだけど...いや、そもそもテキストベースなのがねぇって言い訳してた。

先日何だったかやってた時にOSが開発者モード(?)じゃないとか言われて

設定にあるこれをオンにしたんですが、以前Visual StudioでPython環境整備している時にシェルスクリプトだったか許可されないからって感じで使えなかった理由がこれなんじゃと思い確認してみるとVisual Studioで無事(実際には無事にとは行かないが、毎回指定すれば)にAnacondaの仮想Python環境で行ける様になり単純なTensorFlowでの多変量多出力回帰をしてみた。CopilotとGeminiに相談しながらなんとか行けました。

CSVファイルはpandas使って

  1. import pandas as pd
  2.  
  3. # CSVファイルの読み込み
  4. data = pd.read_csv("MRaceJuni.csv") # ファイル名を適宜変更

入出力の指定して

  1. # 入力データ(特徴量)
  2. X = data[[
  3. "JouCD", "KaisaiTuki", "KaisaiKai", "KaisaiNichi",
  4. "TrackCD", "Course", "Kyori", "Tousu", "Tenko", "Baba",
  5. "KyosouShubetu", "KyosouJouken", "JuuryoShubetu",
  6. "Uma1Souha", "Uma2Souha", "Uma3Souha", "Uma4Souha",
  7. "Uma5Souha", "Uma6Souha", "Uma7Souha", "Uma8Souha",
  8. "Uma9Souha", "Uma10Souha", "Uma11Souha", "Uma12Souha",
  9. "Uma13Souha", "Uma14Souha", "Uma15Souha", "Uma16Souha",
  10. "Uma17Souha", "Uma18Souha"
  11. ]]
  12.  
  13. # 出力データ(ターゲット)
  14. Y = data[[
  15. "Umaban1", "Umaban2", "Umaban3", "Umaban4", "Umaban5",
  16. "Umaban6", "Umaban7", "Umaban8", "Umaban9", "Umaban10",
  17. "Umaban11", "Umaban12", "Umaban13", "Umaban14", "Umaban15",
  18. "Umaban16", "Umaban17", "Umaban18"
  19. ]]

後は今までと同じ感じでデータ準備とTensorFlow特有の層を指定して学習が

  1. from sklearn.model_selection import train_test_split
  2. from sklearn.preprocessing import StandardScaler
  3.  
  4. # データ分割
  5. X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42)
  6.  
  7. # 標準化
  8. scaler = StandardScaler()
  9. X_train = scaler.fit_transform(X_train)
  10. X_test = scaler.transform(X_test)
  11.  
  12. import tensorflow as tf
  13. from tensorflow.keras import Model, Input
  14. from tensorflow.keras.layers import Dense
  15.  
  16. # 入力層を定義
  17. input_layer = Input(shape=(X_train.shape[1],))
  18.  
  19. # 隠れ層と出力層
  20. x = Dense(64, activation='relu')(input_layer)
  21. x = Dense(32, activation='relu')(x)
  22. output_layer = Dense(Y_train.shape[1])(x)
  23.  
  24. # モデルを構築
  25. model = Model(inputs=input_layer, outputs=output_layer)
  26.  
  27. # モデルのコンパイル
  28. model.compile(optimizer='adam', loss='mse')
  29.  
  30. # モデルの訓練
  31. history = model.fit(X_train, Y_train, epochs=50, batch_size=32, validation_split=0.2)

出来たモデルの結果を

  1. # 予測
  2. predictions = model.predict(X_test)
  3.  
  4. # 結果表示
  5. print(predictions)

まあ、これまでのRMSEに馴染みがあるので

  1. from sklearn.metrics import mean_squared_error
  2. import numpy as np
  3.  
  4. # 平均二乗誤差(MSE)を計算
  5. mse = mean_squared_error(Y_test, predictions)
  6.  
  7. # 平方根を取ってRMSEを計算
  8. rmse = np.sqrt(mse)
  9. print(f"Root Mean Squared Error: {rmse}")

って感じにすれば感覚つかみ易いですね。で、出来上がったモデルをどうやって利用するかが問題なんです。H5とかで保存やonnxもあり、まあ、この辺りも以前から苦労してた記憶がありますが

  1. # SavedModel形式で保存
  2. model.export('my_saved_model')

としてTensorFlowのSavedModel形式で保存してTensorFlow.NETでVisual Studioのc#で利用しようかと思ってますが、また躓くかもです😓

第85回桜花賞

馬券は相変わらずパッとしないですね。まあ、そろそろって期待しながら今回は独自に予想してみました。

無傷な2頭とか気になりましたが、最内から俊君が逃げるのがちょっと怖い気もするけど阪神なら消えてくれると信じてノーマーク。
頭絞り切れなくて2点で行ってみました。

2025/04/07

新たな焼酎探し

楽天の買い回りで8本試してみた。

全て初トライと思ったら1本だけ既に1度飲んでた😓 まっ、それだけ影が薄かった奴なのかと思う。取敢えずこの並びは無視でなんとなく鬼嫁から行ってみてます。これ、特に普通に普通。悪くないけど態々リピするってのは微妙。1,580円ってのがまあまあな感じ。でも、今回の8本では4本が1,580円なんです。真ん中あたりの伝説ってのが唯一麦です。でも濱田酒造なのでちょっと期待。

2025/04/06

第69回大阪杯

昨日は2つ程当てましたが微負け。本日はここまで酷い結果で唯一複勝1.8倍とか拾った程度で惨敗中。

ちょっと素直に順位予測に乗ってみました。でも、現時点ってか、乗った時点は朝9時ちょっと過ぎなんですが、そこから何が影響したのか不明ですが、予測が変わってますね😓 まあ、既に投票済なので今更ですけど。
だったんですが、気が付いてしまったので
3点追加投票しておきました。




2025/04/05

ナビダイアル使う企業

以前から非常に不快に思うのは、企業の窓口としてナビダイアルを表示する会社。これ、単に客に電話代払わせて余分な通話を減らす目的としか思えません。昨今通話を無料にするプランを利用する方が多いかと思います。自分はそうではないけど、通話無料になるアプリを利用してます。固定電話は解約済み。通信費削減は当然なんですが、そこに確実に通話料が発生するナビダイアルを自社の窓口として設定する企業は最悪のイメージしかわきません。

って事で、今後通販で日本郵政使うショップは排除していきます。なぜ?ヤマトや佐川と違い、日本郵政のシステムが酷いのにその窓口がナビダイアルなんで、そこを使うショップも問答無用で使いたくない。当たり前に当たり障りのない回答したつもりだとは思うけど、誰もそんな回答求めてメールしてない事に気が付かない担当者は不快。

更にこれ伝えたショップも特に問題ないって対応で不快。まあね、別にひとりが何言った所で変わるものではないのは分かるので、だからってこちらも泣き寝入りはしません。それに対して不快な気分にされない方法は避けるしかないのでね。

いや、実際、日本郵政がとか日本郵便がとか以前に他にも沢山の企業が当たり前にナビダイアルを表示してるんだけど、今のご時世にあうものと思って使っているのか、単に有料に強制的にする事で、それを嫌う客を遠ざける為の施策なんだろうかと思ってしまう。

固定電話を持たない家庭が増える中、固定電話はフリーダイヤルで携帯電話はナビダイアルにする意図を、その案内している場所で明確に表示して欲しいですよね。

こんなのに運(?)を使うから?

昨日郵送されてきたんですが

これ、頂きました。昨年はJRAから沢山のQuoカード頂いてますが、馬券成績は良くないのでこんなのに運を使わずにリアル馬券で大きいのが欲しいですね😉