赞
踩
当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。
让我们来看看美赛的C题!
完整内容可以在文章末尾领取!
问题重述:
在2023年温布尔登男子单打决赛中,20岁的西班牙新星卡洛斯·阿尔卡拉斯击败了36岁的诺瓦克·德约科维奇。这场比赛是德约科维奇自2013年以来在温网的首次败北,结束了这位历史上一位伟大选手在大满贯比赛中的非凡表现。
比赛本身是一场激动人心的战斗。德约科维奇在第一盘中占据绝对优势,以6-1(赢得7局中的6局)取胜。然而,第二盘紧张而最终由阿尔卡拉斯在抢七局中以7-6获胜。第三盘与第一盘相反,阿尔卡拉斯轻松以6-1获胜。年轻的西班牙人在第四盘开始时似乎完全掌控比赛,但比赛再次改变方向,德约科维奇完全掌控比赛以6-3获胜。第五盘开始时,德约科维奇带着第四盘的优势,但比赛再次改变方向,阿尔卡拉斯掌控比赛并以6-4获胜。本问题提供了这场比赛的数据集“match_id”为“2023-wimbledon-1701”。
在这场比赛中,经常发生明显的变化,有时是在某个选手占据优势的情况下,甚至会影响多个积分或局数,这经常被归因于“动力”现象。动量的一个词典定义是“通过运动或一系列事件获得的力量或力量”。在体育中,一支团队或球员可能会感到他们在比赛/局中有动力,但要测量这种现象是困难的。此外,很难立即看出比赛中的各种事件如何影响或改变动力(如果存在的话)。
提供了温网2023男子比赛后两轮的所有积分数据。你可以选择包含额外的球员信息或其他数据,但必须完全记录来源。使用数据来:
积分计算:
局和积分规则: 在网球比赛中,每场比赛包含多个局(sets),每个局包含多个游戏(games),每个游戏包含多个积分(points)。玩家必须以2分的优势赢得游戏和局。积分的计数方式是0、15、30、40,胜出的情况称为“Deuce”,之后再赢一个积分即可获胜。在抢七局中,需要先达到7分,必须以至少2分的优势获胜。
球员得分记录: 根据提供的数据集,可以追踪每个球员在比赛中的得分情况,包括每个局、每个游戏和每个积分的得分。
动量模型:
滑动窗口计算动量: 为了计算动量的变化,引入一个滑动窗口,窗口内包含一定数量的连续积分。可以选择合适的窗口大小,比如每个局结束时或每个游戏结束时。在每个窗口内,计算球员得分的变化,并根据变化来计算动量。
动量公式: 动量(Momentum)可以使用得分变化与时间变化的比率来表示,即 M = Δ S Δ t M = \frac{\Delta S}{\Delta t} M=ΔtΔS,其中 Δ S \Delta S ΔS为得分变化, Δ t \Delta t Δt为时间变化。
发球优势的影响:
引入发球优势因子: 考虑到网球中发球方有更高的概率赢得积分,引入一个发球优势因子 F F F。根据发球方和非发球方的得分变化来调整动量模型中的得分变化。
公式调整: 对于发球方得分变化 Δ S 1 \Delta S1 ΔS1,可以使用 Δ S 1 = Δ S 1 + F ⋅ 发球方得分变化 \Delta S1 = \Delta S1 + F \cdot \text{发球方得分变化} ΔS1=ΔS1+F⋅发球方得分变化,对于非发球方得分变化 Δ S 2 \Delta S2 ΔS2,可以使用 Δ S 2 = Δ S 2 + F ⋅ 非发球方得分变化 \Delta S2 = \Delta S2 + F \cdot \text{非发球方得分变化} ΔS2=ΔS2+F⋅非发球方得分变化。
可视化:
动量图和得分变化曲线: 利用得到的动量数据和得分变化数据,可以生成动量图和得分变化曲线。这些图表可以帮助教练和球员更直观地了解比赛中的动态变化。
其他可视化工具: 根据需要,还可以考虑使用其他可视化工具,比如热力图来表示不同时间段的动量强度。
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据集
data = pd.read_csv("Wimbledon_featured_matches.csv")
# 初始化变量
momentum_data = [] # 存储动量数据
window_size = 5 # 滑动窗口大小
# 遍历每个比赛点
for i in range(len(data)):
# 获取当前比赛点的信息
match_id = data.loc[i, 'match_id']
elapsed_time = data.loc[i, 'elapsed_time']
player1_score = data.loc[i, 'p1_points_won']
player2_score = data.loc[i, 'p2_points_won']
server = data.loc[i, 'server']
# 计算得分差和动量
score_diff = player1_score - player2_score
momentum = score_diff / window_size
# 考虑发球优势
if server == 1: # 如果是发球方
momentum += 0.1 * (data.loc[i, 'p1_points_won'] - data.loc[i, 'p1_points_won_prev'])
else: # 如果是非发球方
momentum += 0.1 * (data.loc[i, 'p2_points_won'] - data.loc[i, 'p2_points_won_prev'])
# 将动量数据添加到列表中
momentum_data.append({'match_id': match_id, 'elapsed_time': elapsed_time, 'momentum': momentum})
# 更新前一点的得分,用于下一个数据点的发球优势计算
data.at[i, 'p1_points_won_prev'] = player1_score
data.at[i, 'p2_points_won_prev'] = player2_score
# 将动量数据转换为DataFrame
momentum_df = pd.DataFrame(momentum_data)
# 可视化动量变化
plt.figure(figsize=(12, 6))
plt.plot(momentum_df['elapsed_time'], momentum_df['momentum'], label='Momentum', color='blue')
plt.title('Momentum in Tennis Match')
plt.xlabel('Elapsed Time (minutes)')#见完整版
逻辑回归模型公式:
P
(
Player1 Wins
)
=
1
1
+
e
−
(
β
0
+
β
1
⋅
Momentum
+
β
2
⋅
Other Features
)
P(\text{{Player1 Wins}}) = \frac{1}{1 + e^{-(\beta_0 + \beta_1 \cdot \text{{Momentum}} + \beta_2 \cdot \text{{Other Features}})}}
P(Player1 Wins)=1+e−(β0+β1⋅Momentum+β2⋅Other Features)1
其中,
Momentum
\text{{Momentum}}
Momentum 表示在该点之前的动量,
Other Features
\text{{Other Features}}
Other Features 是其他可能影响球员表现的特征。模型的参数
β
0
,
β
1
,
β
2
\beta_0, \beta_1, \beta_2
β0,β1,β2 需要从训练数据中学习得到。
通过以上详细步骤,我们可以系统地建立和验证动量模型,并提供深入的分析和建议,以帮助教练更好地理解比赛中的动量效应。
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, confusion_matrix
# 读取数据
data = pd.read_csv("2023-wimbledon-1701.csv")
# 数据预处理
def preprocess_data(data):
# ...(根据具体情况进行缺失值处理、特征提取等操作)
return processed_data
# 特征选择
def select_features(data):
features = ["Momentum", "Other Features"]
X = data[features]
y = data["PointVictor"]
return X, y
# 划分训练集和测试集
def split_train_test(X, y):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
return X_train, X_test, y_train, y_test
# 建立和训练逻辑回归模型
def build_and_train_model(X_train, y_train):
model = LogisticRegression()
model.fit(X_train, y_train)
return model
# 模型预测
def make_predictions(model, X_test):
y_pred = model.predict(X_test)
return y_pred
# 模型性能评估
def evaluate_model(y_test, y_pred):
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
conf_matrix = confusion_matrix(y_test, y_pred)
return accuracy, precision, recall, conf_matrix
# 可视化混淆矩阵
def plot_confusion_matrix(conf_matrix):
sns.heatmap(conf_matrix, annot=True, fmt="d", cmap="Blues")
plt.xlabel("Predicted Label")
plt.ylabel("True Label")
plt.show()
# 主流程
def main():
# 数据预处理
processed_data = preprocess_data(data)
# 特征选择
X, y = select_features(processed_data)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = split_train_test(X, y)
# 建立和训练模型
model = build_and_train_model(X_train, y_train)
# 模型预测
y_pred = make_predictions(model, X_test)#见完整版
问题三涉及开发一个模型,该模型可以预测比赛中的“momentum”变化,同时需要确定哪些因素与这种变化相关。以下是一个详细的建模思路,包括一些概念和公式:
1.定义“Momentum”:
在网球比赛中,“momentum”可以理解为某一方在比赛中的表现势头。我们可以用某种方式量化势头,例如,在每个时间点,计算某一方在过去一段时间内赢得的点的数量。
M o m e n t u m t = ∑ i = t − k t ( 1 p 1 _ w i n s _ p o i n t i − 1 p 2 _ w i n s _ p o i n t i ) Momentum_t=\sum_{i=t-k}^{t}(1_{p1\_wins\_point_i}-1_{p2\_wins\_point_i}) Momentumt=∑i=t−kt(1p1_wins_pointi−1p2_wins_pointi)
其中, M o m e n t u m t Momentum_t Momentumt是在时间点 t t t的势头, k k k是我们选择的时间窗口大小, 1 p 1 _ w i n s _ p o i n t i 1_{p1\_wins\_point_i} 1p1_wins_pointi和 1 p 2 _ w i n s _ p o i n t i 1_{p2\_wins\_point_i} 1p2_wins_pointi是指示在时间点 i i i球员1和球员2是否赢得了该点的指示函数。
2.建立预测模型:
我们可以使用机器学习模型,如线性回归、决策树或神经网络,来预测“momentum”变化。我们选择一组特征(可能包括当前比分、球员排名、比赛阶段等),并使用过去的数据进行训练。
M o m e n t u m _ C h a n g e t = f ( Features t ) Momentum\_Change_t=f(\text{Features}_t) Momentum_Changet=f(Featurest)
这里, M o m e n t u m _ C h a n g e t Momentum\_Change_t Momentum_Changet是在时间点 t t t的势头变化, Features t \text{Features}_t Featurest是我们选择的一组特征。
3.确定相关因素:
利用模型的系数或特征的重要性,可以确定哪些因素对“momentum”变化有较大影响。
Important_Features = arg max Features ∣ Coefficient/Importance ∣ \text{Important\_Features}=\arg\max_{\text{Features}}|\text{Coefficient/Importance}| Important_Features=argmaxFeatures∣Coefficient/Importance∣
4.模型评估:
使用历史比赛数据进行模型的交叉验证,并考虑评估指标,如均方误差(MeanSquaredError)或分类准确率,来评估模型的性能。
M S E = 1 n ∑ i = 1 n ( M o m e n t u m _ C h a n g e t i − M o m e n t u m _ C h a n g e ^ t i ) 2 MSE=\frac{1}{n}\sum_{i=1}^{n}(Momentum\_Change_{t_i}-\hat{Momentum\_Change}_{t_i})^2 MSE=n1∑i=1n(Momentum_Changeti−Momentum_Change^ti)2
其中, M o m e n t u m _ C h a n g e ^ t i \hat{Momentum\_Change}_{t_i} Momentum_Change^ti是模型在时间点 t i t_i ti的预测势头变化。
5.模型应用和建议:
将训练好的模型应用于新的比赛数据,以预测势头变化。如果有势头变化的迹象,可以给出建议,例如提醒球员调整策略、休息或调整心态。
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
# 读取数据
data = pd.read_csv("2023-wimbledon-1701.csv")
# 数据预处理
def preprocess_data(data):
# ...(根据具体情况进行缺失值处理、特征提取等操作)
return processed_data
# 计算势头变化
def calculate_momentum_change(data, window_size=5):
data["MomentumChange"] = data["PointVictor"].rolling(window=window_size).sum()
return data
# 特征选择
def select_features(data):
features = ["Feature1", "Feature2", ...] # 根据实际数据选择特征
X = data[features]
y = data["MomentumChange"]
return X, y
# 划分训练集和测试集
def split_train_test(X, y, test_size=0.2):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=42)
return X_train, X_test, y_train, y_test
# 建立和训练线性回归模型
def build_and_train_model(X_train, y_train):
model = LinearRegression()
model.fit(X_train, y_train)
return model
# 模型预测
def make_predictions(model, X_test):
y_pred = model.predict(X_test)
return y_pred
# 模型评估
def evaluate_model(y_test, y_pred):
mse = mean_squared_error(y_test, y_pred)
return mse
# 可视化势头变化和预测
def visualize_momentum(data, y_test, y_pred):
plt.plot(data["Timestamp"], data["MomentumChange"], label="Actual Momentum Change")
plt.plot(data["Timestamp"], y_pred, label="Predicted Momentum Change")
plt.legend()
plt.xlabel("Timestamp")
plt.ylabel("Momentum Change")
plt.show()
# 主流程
def main():
# 数据预处理
processed_data = preprocess_data(data)
# 计算势头变化
processed_data = calculate_momentum_change(processed_data)
# 特征选择
X, y = select_features(processed_data)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = split_train_test(X, y)#见完整版
为了将我们之前构建的模型应用于新的比赛数据集,我们需要确保该数据集的特征与之前使用的数据相似。首先,加载新的比赛数据集。
new_data = pd.read_csv("new_competition_data.csv")
分析:
确保新数据集的特征与之前训练的模型兼容,可以通过比较列名、数据类型等来进行初步检查。
使用问题三中训练的模型对新比赛的数据进行预测。
Momentum_Change_new = model.predict(Features_new)
分析:
观察模型对新数据集的预测效果,通过可视化或统计指标(如均方误差)来评估模型的适用性。
计算模型在新比赛中的均方误差(MSE)等评估指标。
MSE_new = mean_squared_error(Momentum_Change_new, Momentum_Change_true)
分析:
MSE提供了模型预测误差的度量,通过与之前的训练集进行比较,评估模型在新数据上的泛化性能。
对比赛数据的特征进行分析,了解模型在新比赛中的预测是否受到特定因素的影响。
feature_importance = pd.Series(model.coef_, index=X.columns)
分析:
通过特征重要性分析,确定哪些特征对于模型在新比赛中的预测起着关键作用,从而深入了解势头变化的影响因素。
根据因素分析的结果,考虑改进模型。
new_feature = extract_new_feature(new_data)
new_processed_data["NewFeature"] = new_feature
X_new_updated = new_processed_data[updated_features]
model_updated = build_and_train_model(X_train_updated, y_train)
分析:
通过新特征的提取和模型的重新训练,尝试提高模型在新比赛数据上的准确性,注意监测模型性能的改善。
测试模型在不同比赛、不同赛事和场地的表现。
other_competition_data = pd.read_csv("other_competition_data.csv")
分析:
通过在不同比赛数据上的表现,评估模型的泛化性能,注意观察是否存在过拟合或欠拟合的情况。
在不同比赛、不同赛事和场地的数据上测试模型的泛化性能。
other_competition_data = pd.read_csv("other_competition_data.csv")
Features_other = other_competition_data[relevant_features]
Momentum_Change_other = model.predict(Features_other)
分析:
评估模型在其他比赛数据上的表现,关注模型是否能够泛化到不同比赛和场地。使用均方误差等指标来衡量性能。
通过在不同时间段的比赛数据上测试模型的稳定性。
time_split_data = pd.read_csv("time_split_data.csv")
Features_time = time_split_data[relevant_features]
Momentum_Change_time = model.predict(Features_time)
分析:
考察模型对于比赛数据的时间变化是否具有稳定性。模型应该能够适应比赛风格和趋势的变化。
基于模型的势头变化预测,为球员提供应对不同事件的建议。
event_impact = model.get_event_impact()
分析:
通过分析模型的特征重要性,了解哪些比赛事件对势头变化影响较大。为球员提供在关键时刻的应对建议,例如调整战术或情绪管理。
使用模型预测整场比赛的走势,并与实际比赛结果进行比较。
match_trend_prediction = model.predict_match_trend(Features_match)
actual_match_result = match_data["Actual_Result"]
分析:
通过比较模型预测的比赛走势和实际比赛结果,评估模型对整场比赛的预测能力。
尝试更复杂的特征工程,例如引入动态特征或基于事件的特征。
advanced_features = generate_advanced_features(match_data)
分析:
考虑引入更多的比赛动态信息或特殊事件的特征,以提高模型对势头变化的准确预测。
根据对模型在各方面分析的结果,尝试优化模型,可能包括超参数调整、特征选择等。
optimized_model = optimize_model(X_train, y_train)
分析:
通过反复测试和调整模型,迭代优化模型的性能,确保其在各种情况下都能表现良好。
更多内容具体可以看看我的下方名片!里面包含有美赛一手资料与分析!
另外在赛中,我们也会陪大家一起解析美赛的一些方向
关注 CS数模 团队,数模不迷路~
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。