为什么我在 PyTorch 中的足球预测神经网络不起作用?

问题描述 投票:0回答:1

我尝试创建一个预测足球比分的模型。

我使用了这个数据集:https://www.kaggle.com/datasets/martj42/international-football-results-from-1872-to-2017

然后,我给每个团队名称一个唯一的整数。

这是 NN 的代码:

import csv
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import pandas as pd
import pandas as pd

data = []
with open('/Volumes/Drive 2/Football nn/output.csv', 'r') as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        data.append(row)

# team names
home_team = [str(row[1]) for row in data]
away_team = [str(row[2]) for row in data]
#team scores
old_home_score = [str(row[3]) for row in data]
old_away_score = [str(row[4]) for row in data]

home_score = []
away_score = []
print(home_team[44762])
print(away_team[44762])
home_team.pop(0)
away_team.pop(0)

old_home_score.pop(0)
old_away_score.pop(0)

for item in (old_home_score):
    iteam = int(item)
    iteam /=10
    home_score.append(iteam)

for item in (old_away_score):
    iteam = int(item)
    iteam /=10
    away_score.append(iteam)

print(away_score[44761])
print(home_score[44761])
home_team = [eval(i) for i in home_team]
away_team = [eval(i) for i in away_team]
class SoccerNN(nn.Module):
    def __init__(self):
        super(SoccerNN, self).__init__()
        self.fc1 = nn.Linear(2, 15)  
        self.fc2 = nn.Linear(15, 20)
        self.fc3 = nn.Linear(20, 10)
        self.fc4 = nn.Linear(10, 2) 

    def forward(self, x):
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        x = self.fc4(x)
        x = torch.sigmoid(x)
        return x


# Convert the columns to PyTorch tensors
input_data = torch.tensor(np.column_stack((home_team, away_team)), dtype=torch.int16)
output_data = torch.tensor(np.column_stack((home_score, away_score)), dtype=torch.int16)


model = SoccerNN()
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Training loop
epochs = 50  # Adjust the number of epochs as needed
batch_size = 10  # Adjust the batch size as needed
for epoch in range(epochs):
    for batch_start in range(0, len(input_data), batch_size):
        batch_end = batch_start + batch_size
        batch_input = input_data[batch_start:batch_end]
        batch_output = output_data[batch_start:batch_end]
        # Convert batch_input and batch_output to the same dtype as the model's parameters
        batch_input = batch_input.to(model.fc1.weight.dtype)
        batch_output = batch_output.to(model.fc2.weight.dtype)

        # Zero the gradients
        optimizer.zero_grad()

        # Forward pass
        predictions = model(batch_input)

        # Calculate loss
        loss = criterion(predictions, batch_output)

        # Backpropagation
        loss.backward()

        # Update weights
        optimizer.step()

    
        print(f"Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}")

# After training, you can use the model for predictions
home_team = [16]
away_team = [37]
new_data = torch.tensor(np.column_stack((home_team, away_team)), dtype=torch.int16)
new_data = torch.tensor(new_data, dtype=torch.float32)  # Use the appropriate data type

# Put the model in evaluation mode
model.eval()

# Make predictions
with torch.no_grad():
    predictions = model(new_data)

# Convert predictions to numpy array
predictions_np = predictions.numpy()

# Print or use the predictions as needed
print(predictions_np)

我给网络两个整数作为输入(每个整数代表一个团队),网络应该输出比赛的预测得分......

当我训练模型时,它说损失为 0,但预测完全错误。

为什么它不起作用(我的猜测是它进入了局部最小值并且无法退出,但我可能完全错了,因为我对整个事情非常陌生)以及我应该如何更改模型这样它就能工作吗?

尝试更改批量大小、层数、纪元...

还是不行...

python deep-learning pytorch neural-network
1个回答
1
投票

首先,当我尝试编译您的代码时,我在

home_team = [eval(i) for i in home_team]
行收到错误,我怀疑您想将团队映射到整数,即:

NameError: name 'Scotland' is not defined

我将首先解释如何正确地进行此映射,即使这不是将类(团队)输入神经网络的正确方法,稍后我将对此进行解释。

将团队映射到整数

您可以使用以下代码:

string_to_int = {}
next_int = 0  # Initialize the integer counter
# Iterate through the list of strings
for string in home_team + away_team:
    # Check if the string is already in the dictionary
    if string not in string_to_int:
        string_to_int[string] = next_int
        next_int += 1  # Increment the integer counter

home_team = [string_to_int[s] for s in home_team]
away_team = [string_to_int[s] for s in away_team]

有了这个,我就能够运行你的代码,并损失了大约

0.014

如何提高模型性能

  • 仅当类具有某种关系时,将类映射到整数才有意义,例如一个订单。在这种情况下,他们不会这样做,但通过将它们作为

    int
    提供给 NN,您明确地告诉 NN,例如
    Uruguay
    (5) 靠近
    Austria
    (6) 而远离
    Surrey
    (314)。然后神经网络必须首先知道这种关系没有任何意义,这使得它的工作变得更加困难。

    • 更好的选择是使用 One Hot Encoding 或 Learned Encoding(请参阅此教程
    • 您现在将拥有更广泛的网络,因为输入将具有唯一类数量的维度(此处〜300)
  • nn.ReLU()
    函数之间添加非线性函数(例如
    nn.Sigmoid()
    fc
    )。目前,您的整个网络相当于一个带有
    fc
    的线性
    sigmoid
    层。

  • 您将分数除以

    10
    ,以确保它们符合网络输出
    [-1,1]
    的范围。将最终的非线性(目前
    sigmoid
    )更改为范围是目标数据范围的值会更明智,即
    [0,infinity)
    ,例如
    ReLU
    功能。

© www.soinside.com 2019 - 2024. All rights reserved.