我尝试创建一个预测足球比分的模型。
我使用了这个数据集: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,但预测完全错误。
为什么它不起作用(我的猜测是它进入了局部最小值并且无法退出,但我可能完全错了,因为我对整个事情非常陌生)以及我应该如何更改模型这样它就能工作吗?
尝试更改批量大小、层数、纪元...
还是不行...
首先,当我尝试编译您的代码时,我在
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)。然后神经网络必须首先知道这种关系没有任何意义,这使得它的工作变得更加困难。
在
nn.ReLU()
函数之间添加非线性函数(例如 nn.Sigmoid()
或 fc
)。目前,您的整个网络相当于一个带有 fc
的线性 sigmoid
层。
您将分数除以
10
,以确保它们符合网络输出[-1,1]
的范围。将最终的非线性(目前sigmoid
)更改为范围是目标数据范围的值会更明智,即[0,infinity)
,例如ReLU
功能。