【问题标题】:Finding right keras model - football prediction寻找正确的 keras 模型 - 足球预测
【发布时间】:2022-01-21 11:43:03
【问题描述】:

我试图生成一个能够预测足球比赛结果(赢、输、平)的神经网络 (LSTM)。特别是,我试图在this 论文中扩展该算法,使其能够预测平局,而不仅仅是输赢。 训练数据集完全具有第 3 页中描述的列。这些列都已缩放,以便在 0 到 1 的范围内。第 9 列和第 10 列是赢/输/平局编码为 1 2 和 3,列从 11 到18 是二进制值。 我修改了在同一个 github 存储库中创建的网络,结果如下:

import numpy as np
from sklearn.model_selection import train_test_split
from tensorflow import keras
import pandas as pd


# Build the RNN model
def build_model(allow_cudnn_kernel=True):
    input_dim = 27
    units = 64
    output_size = 3  # labels are from Win or Loss
    # CuDNN is only available at the layer level, and not at the cell level.
    # This means `LSTM(units)` will use the CuDNN kernel,
    # while RNN(LSTMCell(units)) will run on non-CuDNN kernel.
    if allow_cudnn_kernel:
        # The LSTM layer with default options uses CuDNN.
        lstm_layer = keras.layers.LSTM(units, input_shape=(input_dim, 1))
    else:
        # Wrapping a LSTMCell in a RNN layer will not use CuDNN.
        lstm_layer = keras.layers.RNN(
            keras.layers.LSTMCell(units), input_shape=(input_dim, 1)
        )
    model = keras.models.Sequential(
        [
            lstm_layer,
            keras.layers.BatchNormalization(),
            keras.layers.Dense(output_size),
        ]
    )
    return model


def final_model():
    batch_size = 64
    data = pd.read_csv("onehotencoder/allAtt_onehot_large_train.csv")
    dataTrain, dataTest = train_test_split(data, test_size=0.2)
    row_count = dataTrain.shape[0]
    x_train, y_train = dataTrain.iloc[:, 2:29].values, dataTrain.iloc[:, 29:].values
    x_train = np.reshape(x_train, (row_count, 27, 1))
    row_count = dataTest.shape[0]
    x_test, y_test = dataTest.iloc[:, 2:29].values, dataTest.iloc[:, 29:].values
    x_test = np.reshape(x_test, (row_count, 27, 1))
    model = build_model(allow_cudnn_kernel=True)
    model.compile(
        loss=keras.losses.CategoricalCrossentropy(from_logits=True),
        optimizer="Adam",
        metrics=["categorical_accuracy"],
    )
    model.fit(
        x_train, y_train, validation_data=(x_test, y_test), batch_size=batch_size, epochs=10
    )
    return model


model = final_model()

然后,我预测了一些结果:

data = pd.read_csv("onehotencoder/allAtt_onehot_large_train.csv")
dataTrain, dataTest = train_test_split(data, test_size=0.2)
x_test, y_test = dataTest.iloc[:, 2:29].values, dataTest.iloc[:, 29:].values
pred = model.predict(x_test)

j = 0
truth = []
correct_win = 0
correct_lose = 0
correct_draw = 0
for i in pred:
    if i[0] > i[1] and i[0] > i[2]:
        w = 1
    elif(i[1] > i[0] and i[1] > i[2]):
        w = 0
    else:
        w = 2 #draw
    if y_test[j][0] == 1:
        truth.append(1)
    elif y_test[j][1] == 1:
        truth.append(2)
    else:
        truth.append(0)
    if truth[j] == w:
        if w == 1:
            correct_win+=1
        elif w == -1:
            correct_lose+=1
        else:
            correct_draw+=1
    j+=1

print(str(correct_win)+"/"+str(truth.count(1)))
print(str(correct_lose)+"/"+str(truth.count(0)))
print(str(correct_draw)+"/"+str(truth.count(2)))

我保留了 github 存储库中的 cmets,但并不真正了解此模型的工作原理。 用作 y_train 的三列分别代表胜利、失败和平局,只有当事件发生时才应为一列。我认为这是传递输入的好方法。输出是一个列表中的许多数组,每个数组都有一堆数字,我认为这些数字是某种概率,所以我选择了结果预测的最高值。 我也知道,我计算模型性能的方式可能不是最好的,而且我知道我应该使用在训练的任何时候都没有包含的测试数据。但是,我认为它的表现应该比这更好:

160/190 correct wins
0/131 correct lost
16/95 correct draws

模型创建过程中一定有逻辑错误,但我不知道如何解决这个问题。我没有要求任何人为我创建这个模型,但我很想了解哪里出了问题以及是否可以解决这个问题。我知道足球预测的预测非常复杂,但我想有可能比这表现得更好。

【问题讨论】:

  • 1.为什么lstm在这里?尝试一个只有几个密集层的 nn 来解决这个分类问题。 2. 你的训练指标是什么意思?你的损失怎么了? 3. 带有 if else if 的 for 循环有点太时髦了 :)
  • 我知道循环很糟糕,但是如果还不明显的话,我对 ml 库和 keras 非常缺乏经验。我在网上看到那个人并不是唯一一个使用 lstm 的人,所以我认为这是一个不错的选择。感谢您的帮助@B.Kocis!
  • 确保您基本上可以在任何地方使用lstm,这更多是手头问题的问题。尽管如此,查看训练指标总是有帮助的。
  • 你能和我分享文件onehotencoder/allAtt_onehot_large_train.csv,我可以运行它,看看我的输出是什么。另外,我注意到您将数据拆分了两次(一次在模型中,然后再次用于测试/预测)。你不应该那样做(除非你设置一个种子,这样你就得到了完全相同的分裂)。否则,当您做出这些预测时,您可能会将模型训练时使用的一些数据泄露到测试数据集中。
  • 然后是的,你的逻辑有缺陷。您将 w 的值返回为 1、0 或 2。但是当计算正确的值时,您会让它寻找 w 为 1 或 -1,(然后是其他)。

标签: python machine-learning keras neural-network prediction


【解决方案1】:

你的逻辑似乎在这里:

if truth[j] == w:
    if w == 1:
        correct_win+=1
    elif w == -1:
        correct_lose+=1
    else:
        correct_draw+=1

当你返回上一行代码时:

if i[0] > i[1] and i[0] > i[2]:
    w = 1
elif(i[1] > i[0] and i[1] > i[2]):
    w = 0
else:
    w = 2 #draw

所以你永远不会添加到correct loss,因为w = -1 没有价值......你只有w 等于1, 0, or 2。如果正确分配了值,我相信您应该更改其中一种逻辑。

两者都有:

for i in pred:
    if i[0] > i[1] and i[0] > i[2]:
        w = 1
    elif(i[1] > i[0] and i[1] > i[2]):
        w = -1  # <-- CHANGE from 0
    else:
        w = 2 #draw
    if y_test[j][0] == 1:
        truth.append(1)
    elif y_test[j][1] == 1:
        truth.append(2)
    else:
        truth.append(0)
    if truth[j] == w:
        if w == 1:
            correct_win+=1
        elif w == -1:     # <-- To match here
            correct_lose+=1
        else:
            correct_draw+=1
    j+=1

for i in pred:
    if i[0] > i[1] and i[0] > i[2]:
        w = 1
    elif(i[1] > i[0] and i[1] > i[2]):
        w = 0  # <-- to match here
    else:
        w = 2 #draw
    if y_test[j][0] == 1:
        truth.append(1)
    elif y_test[j][1] == 1:
        truth.append(2)
    else:
        truth.append(0)
    if truth[j] == w:
        if w == 1:
            correct_win+=1
        elif w == 0:  # <-- CHANGE to 0
            correct_lose+=1
        else:
            correct_draw+=1
    j+=1

但仍有一些问题,因为您的数字总和没有达到应有的 416。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-28
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多