实时对战游戏是人工智能研究领域的一个热点。由于游戏复杂性、部分可观察和动态实时变化战局等游戏特点使得研究变得比较困难。我们可以在选择英雄阶段预测胜负概率,也可以在比赛期间根据比赛实时数据进行建模。那么我们英雄联盟对局进行期间,能知道自己的胜率吗?
比赛数据使用了英雄联盟玩家的实时游戏数据,记录下用户在游戏中对局数据(如击杀数、住物理伤害)。希望参赛选手能从数据集中挖掘出数据的规律,并预测玩家在本局游戏中的输赢情况。
赛题训练集案例如下:
- 训练集18万数据;
- 测试集2万条数据;
import pandas as pd
import numpy as np
train = pd.read_csv('train.csv.zip')
对于数据集中每一行为一个玩家的游戏数据,数据字段如下所示:
- id:玩家记录id
- win:是否胜利,标签变量
- kills:击杀次数
- deaths:死亡次数
- assists:助攻次数
- largestkillingspree:最大 killing spree(游戏术语,意味大杀特杀。当你连续杀死三个对方英雄而中途没有死亡时)
- largestmultikill:最大mult ikill(游戏术语,短时间内多重击杀)
- longesttimespentliving:最长存活时间
- doublekills:doublekills次数
- triplekills:doublekills次数
- quadrakills:quadrakills次数
- pentakills:pentakills次数
- totdmgdealt:总伤害
- magicdmgdealt:魔法伤害
- physicaldmgdealt:物理伤害
- truedmgdealt:真实伤害
- largestcrit:最大暴击伤害
- totdmgtochamp:对对方玩家的伤害
- magicdmgtochamp:对对方玩家的魔法伤害
- physdmgtochamp:对对方玩家的物理伤害
- truedmgtochamp:对对方玩家的真实伤害
- totheal:治疗量
- totunitshealed:痊愈的总单位
- dmgtoturrets:对炮塔的伤害
- timecc:法控时间
- totdmgtaken:承受的伤害
- magicdmgtaken:承受的魔法伤害
- physdmgtaken:承受的物理伤害
- truedmgtaken:承受的真实伤害
- wardsplaced:侦查守卫放置次数
- wardskilled:侦查守卫摧毁次数
- firstblood:是否为firstblood 测试集中label字段win为空,需要选手预测。
- 数据说明
选手需要提交测试集队伍排名预测,具体的提交格式如下:
win
0
1
1
0
- 评估指标
本次竞赛的使用准确率进行评分,数值越高精度越高,评估代码参考:
from sklearn.metrics import accuracy_score
y_pred = [0, 2, 1, 3]
y_true = [0, 1, 2, 3]
accuracy_score(y_true, y_pred)
import pandas as pd
import paddle
import numpy as np
%pylab inline
import seaborn as sns
train_df = pd.read_csv('data/data137276/train.csv.zip')
test_df = pd.read_csv('data/data137276/test.csv.zip')
train_df = train_df.drop(['id', 'timecc'], axis=1)
test_df = test_df.drop(['id', 'timecc'], axis=1)
# 2.Z-Score Normalization(Z分数归一化)
for col in train_df.columns[1:]:
train_df[col] = (train_df[col]-train_df[col].mean()) / train_df[col].std()
test_df[col] = (test_df[col]-test_df[col].mean()) / test_df[col].std()
class Classifier(paddle.nn.Layer):
# self代表类的实例自身
def __init__(self):
# 初始化父类中的一些参数
super(Classifier, self).__init__()
self.fc1 = paddle.nn.Linear(in_features=29, out_features=40)
self.fc2 = paddle.nn.Linear(in_features=40, out_features=1)
self.relu = paddle.nn.ReLU()
# 网络的前向计算
def forward(self, inputs):
x = self.relu(self.fc1(inputs))
x = self.fc2(x)
return x
model = Classifier()
model.train()
opt = paddle.optimizer.SGD(learning_rate=0.01, parameters=model.parameters())
loss_fn = paddle.nn.BCEWithLogitsLoss()
EPOCH_NUM = 1000 # 设置外层循环次数
BATCH_SIZE = 100 # 设置batch大小
training_data = train_df.iloc[:-1000,].values.astype(np.float32)
val_data = train_df.iloc[-1000:, ].values.astype(np.float32)
# 定义外层循环
for epoch_id in range(EPOCH_NUM):
# 在每轮迭代开始之前,将训练数据的顺序随机的打乱
np.random.shuffle(training_data)
# 训练集测试,将训练数据进行拆分,每个batch包含10条数据
train_loss = []
train_acc = []
mini_batches = [training_data[k:k+BATCH_SIZE] for k in range(0, len(training_data), BATCH_SIZE)]
for iter_id, mini_batch in enumerate(mini_batches):
x = np.array(mini_batch[:, 1:]) # 获得当前批次训练数据
y = np.array(mini_batch[:, :1]) # 获得当前批次训练标签
# 将numpy数据转为飞桨动态图tensor的格式
features = paddle.to_tensor(x)
y = paddle.to_tensor(y)
# 前向计算
predicts = model(features)
# 计算损失
loss = loss_fn(predicts, y, )
avg_loss = paddle.mean(loss)
train_loss.append(avg_loss.numpy())
# 计算准确率
acc = (predicts > 0).astype(int).flatten() == y.flatten().astype(int)
acc = acc.astype(float).mean()
train_acc.append(acc.numpy())
# 反向传播,计算每层参数的梯度值
avg_loss.backward()
# 更新参数,根据设置好的学习率迭代一步
opt.step()
# 清空梯度变量,以备下一轮计算
opt.clear_grad()
# 验证集测试
mini_batches = [val_data[k:k+BATCH_SIZE] for k in range(0, len(val_data), BATCH_SIZE)]
val_loss = []
val_acc = []
for iter_id, mini_batch in enumerate(mini_batches):
x = np.array(mini_batch[:, :-1]) # 获得当前批次训练数据
y = np.array(mini_batch[:, -1:]) # 获得当前批次训练标签
# 将numpy数据转为飞桨动态图tensor的格式
features = paddle.to_tensor(x)
y = paddle.to_tensor(y)
# 前向计算
predicts = model(features)
# 计算损失
loss = loss_fn(predicts, y, )
avg_loss = paddle.mean(loss)
val_loss.append(avg_loss.numpy())
# 计算准确率
acc = (predicts > 0).astype(int).flatten() == y.flatten().astype(int)
acc = acc.astype(float).mean()
val_acc.append(acc.numpy())
print(f'Epoch {epoch_id}, train BCE {np.mean(train_loss)}, train Acc {np.mean(train_acc)}, val BCE {np.mean(val_loss)}, val Acc {np.mean(val_acc)}')
model.eval()
test_data = paddle.to_tensor(test_df.values.astype(np.float32))
test_predict = model(test_data)
test_predict = (test_predict > 0).astype(int).flatten()
pd.DataFrame({'win':
test_predict.numpy()
}).to_csv('submission.csv', index=None)
!zip submission.zip submission.csv
updating: submission.csv (deflated 90%)
- 原始赛题字段存在关联,可以进一步提取交叉特征。
- 模型训练过程中可以加入验证集验证过程。