loto6-mlp
ロト6予想
MLPのお題としてロト6の番号予想を行ないます。ただし、限りなくランダムに近いものであり、有意な法則はないはずですので、有用なものは作れないです。
データの用意
過去の当選番号をまとめているサイトが幾つかあります、 csv形式で公開しているものが使いやすいので、下記のサイトからダウンロードしました。 再配布は禁止されているので、直接ダウンロードしてください。
学習コード
上記のcsvファイルを、loto6.csvとして配置し、実行します。
import torch import random from torch.utils.data import DataLoader import numpy as np import pandas as pd # Loto6.csvを読み込む loto6_file_path = 'loto6.csv' df = pd.read_csv(loto6_file_path) # 独自のデータセットクラス class MyDataset(torch.utils.data.Dataset): def __init__(self, df): self._df = df def __len__(self): # 入力データと正解データはDataFrameの直近のペアで組み合わせるので、 # データ数はDataFrameの総行数-1となる return len(self._df) - 1 def __getitem__(self, idx): input_data = df.iloc[idx, 2:9].values.astype(int) # 1origin to 0origin input_data = input_data - 1 target_size = 43 input_data_onehot = np.eye(target_size)[input_data] # axisはより外側の軸が小さい値になる input_data_onehot = input_data_onehot.sum(axis = 0) # 正解データにはボーナス数字は含まない output_data = df.iloc[idx+1, 2:8].values.astype(int) # 1origin to 0origin output_data = output_data - 1 target_size = 43 output_data_onehot = np.eye(target_size)[output_data] # axisはより外側の軸が小さい値になる output_data_onehot = output_data_onehot.sum(axis = 0) input_tensor = torch.FloatTensor(input_data_onehot) output_tensor = torch.FloatTensor(output_data_onehot) return input_tensor, output_tensor # DNNモデル(多層パーセプトロン) class MLPR(torch.nn.Module): def __init__(self, n_input, n_hidden, n_output): super(MLPR, self).__init__() self.l1 = torch.nn.Linear(n_input, n_hidden) self.l2 = torch.nn.Linear(n_hidden, n_hidden) self.l3 = torch.nn.Linear(n_hidden, n_hidden) self.l4 = torch.nn.Linear(n_hidden, n_output) def forward(self, x): h1 = self.l1(x) h2 = torch.relu(h1) h3 = self.l2(h2) h4 = torch.relu(h3) h5 = self.l3(h4) h6 = torch.relu(h5) h7 = self.l4(h6) h8 = torch.sigmoid(h7) return h8 device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') print('using device:', device) myds = MyDataset(df) train_loader = DataLoader(myds, batch_size=200, shuffle=False) model = MLPR(43, 500, 43) # 二値分類なので交差エントロピーを損失関数に使う criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.1) model.to(device) criterion.to(device) # 学習プロセス # 学習が進みに応じた損失関数の変化を見る。検証プロセスは無し。 from torch.autograd import Variable loss_history = [] for epoch in range(1000): total_loss = 0 for x_train, y_train in train_loader: # Variableは微分機能内包 x_train = Variable(x_train) y_train = Variable(y_train) optimizer.zero_grad() x_train = x_train.to(device) y_train = y_train.to(device) y_pred = model(x_train) loss = criterion(y_pred, y_train) loss.backward() optimizer.step() total_loss += loss.item() loss_history.append(total_loss) if (epoch +1) % 100 == 0: print(epoch + 1, total_loss) torch.save(model.state_dict(), 'loto6_model_weights.pth')
学習結果
直前の回の当選番号を元に今回の当選番号を導くための学習をさせます。 各番号をone-hot-vector形式で指定し、0~1の範囲で出力します。 データ総数は2007で、バッチサイズは200なので、 最大の損失は43*2007/200=430くらいになります。
using device: cpu 100 243.7310848236084 200 241.97664260864258 300 237.96832656860352 400 232.6889190673828 500 228.08361434936523 600 223.40085792541504 700 219.68487739562988 800 217.33679389953613 900 213.1663055419922 1000 212.26333236694336
大体240くらいから始まって、210くらいに収束します。 エポックを重ねればさらに収束していきますが、210あたりでだいぶ速度が遅くなります。 過学習のフェーズに入っていると思われます。
推論
上記で作成したモデルのパラメータは、“loto6_model_weights.pth”というファイルで保存しています。 これを用いて推論させます。 毎回学習させても良いのですが、それなりに時間が掛かるので、 学習済モデルを使う方が速いです。
model = MLPR(43, 500, 43) model.load_state_dict(torch.load('loto6_model_weights.pth')) model.to(device) # 直前の当選番号を入力値として用意する input_data = np.array([2, 4, 5, 6, 19, 39, 42]) # 0-originに変換する input_data_0origin = input_data - 1 # one-hot-vectorに変換する target_size = 43 input_data_onehot = np.eye(target_size)[input_data_0origin].sum(axis=0) # Pytorch tensor型に変換する input_tensor = torch.FloatTensor(input_data_onehot) # バッチ処理用の次元を追加する input_tensor = input_tensor.unsqueeze(0) # デバイスに転送する(GPU) input_tensor = input_tensor.to(device) # 推論する(学習プロセスではないので勾配は計算しない) with torch.no_grad(): prediction = model(input_tensor) # バッチ処理用の次元を取り除く prediction_np = prediction.squeeze(0).cpu().numpy() # 確率の高い上位6つの値を取り出す predicted_indices = np.argsort(prediction_np)[-6:][::-1] # 0 originから 1 originに戻す predicted_numbers = predicted_indices + 1 print("Predicted numbers:", predicted_numbers)
loto6-mlp.txt · 最終更新: 2025/06/21 07:00 by bokupi