赞
踩
当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。
让我们来看看认证杯的A题!
完整内容可以在文章末尾领取!
趋势(Trend): 表示数据长期上升或下降的方向。趋势可以通过拟合多项式或其他非线性函数来建模。在太阳活动中,趋势可能表示太阳黑子数量随时间的总体增加或减少趋势。
季节性(Seasonality): 表示数据在特定时间范围内的周期性变化。太阳活动通常以约11年的周期性变化为主。
残差(Residuals): 指的是模型不能解释的数据部分,可能包含随机噪声或其他未考虑的因素。
ARIMA(差分整合移动平均自回归)是一种常用于时间序列预测的模型。ARIMA模型包括三个主要组件:
自回归(AR): 表示当前值与过去值的关系,即当前值的预测取决于前一时刻的值。
差分整合(I): 表示对时间序列进行差分以消除趋势或季节性。
移动平均(MA): 表示当前值与过去的误差项的关系,即当前值的预测取决于过去的误差。
ARIMA 模型的一般形式为 ARIMA(p, d, q),其中 p、d、q 分别为自回归、差分整合和移动平均的阶数。
ARIMA 模型的基本预测公式可以表示为:
Y t = c + ϕ 1 Y t − 1 + ϕ 2 Y t − 2 + … + ϕ p Y t − p + ϵ t − θ 1 ϵ t − 1 − θ 2 ϵ t − 2 − … − θ q ϵ t − q Y_t = c + \phi_1 Y_{t-1} + \phi_2 Y_{t-2} + \ldots + \phi_p Y_{t-p} + \epsilon_t - \theta_1 \epsilon_{t-1} - \theta_2 \epsilon_{t-2} - \ldots - \theta_q \epsilon_{t-q} Yt=c+ϕ1Yt−1+ϕ2Yt−2+…+ϕpYt−p+ϵt−θ1ϵt−1−θ2ϵt−2−…−θqϵt−q
其中:
自回归(AR)部分:
Y t = c + ϕ 1 Y t − 1 + ϕ 2 Y t − 2 + … + ϕ p Y t − p + ϵ t Y_t = c + \phi_1 Y_{t-1} + \phi_2 Y_{t-2} + \ldots + \phi_p Y_{t-p} + \epsilon_t Yt=c+ϕ1Yt−1+ϕ2Yt−2+…+ϕpYt−p+ϵt
这一部分表示当前值 Y t Y_t Yt 与过去 p p p 个时间步的值 Y t − 1 , Y t − 2 , … , Y t − p Y_{t-1}, Y_{t-2}, \ldots, Y_{t-p} Yt−1,Yt−2,…,Yt−p 之间的关系。系数 ϕ 1 , ϕ 2 , … , ϕ p \phi_1, \phi_2, \ldots, \phi_p ϕ1,ϕ2,…,ϕp 表示对应时间步的权重。
差分整合(I)部分:
差分整合部分表示对时间序列进行 d d d 阶差分,以消除趋势或季节性。差分整合的目标是使时间序列平稳。
Y t ′ = Y t − Y t − 1 Y_t' = Y_t - Y_{t-1} Yt′=Yt−Yt−1
重复差分 d d d 次,直到达到平稳性。
移动平均(MA)部分:
Y t = c + ϵ t − θ 1 ϵ t − 1 − θ 2 ϵ t − 2 − … − θ q ϵ t − q Y_t = c + \epsilon_t - \theta_1 \epsilon_{t-1} - \theta_2 \epsilon_{t-2} - \ldots - \theta_q \epsilon_{t-q} Yt=c+ϵt−θ1ϵt−1−θ2ϵt−2−…−θqϵt−q
这一部分表示当前值 Y t Y_t Yt 与过去 q q q 个时间步的误差项 ϵ t − 1 , ϵ t − 2 , … , ϵ t − q \epsilon_{t-1}, \epsilon_{t-2}, \ldots, \epsilon_{t-q} ϵt−1,ϵt−2,…,ϵt−q 之间的关系。
使用时间序列分析中的趋势分析方法。其中利用移动平均和趋势分析来估计太阳黑子的趋势。
移动平均法是一种平滑时间序列的方法,可以消除一些噪声,突出趋势。有两种常见的移动平均:简单移动平均(SMA)和指数加权移动平均(EWMA)。
简单移动平均(SMA):
M A t = 1 n ∑ i = 1 n Y t − i MA_t = \frac{1}{n} \sum_{i=1}^{n} Y_{t-i} MAt=n1i=1∑nYt−i
其中 M A t MA_t MAt 是时间 t t t 的移动平均值, n n n 是选定的时间窗口大小。
指数加权移动平均(EWMA):
E M A t = α ⋅ Y t + ( 1 − α ) ⋅ E M A t − 1 EMA_t = \alpha \cdot Y_t + (1-\alpha) \cdot EMA_{t-1} EMAt=α⋅Yt+(1−α)⋅EMAt−1
其中 E M A t EMA_t EMAt 是时间 t t t 的指数加权移动平均值, α \alpha α 是平滑因子 ( 0 < α < 1 ) (0 < \alpha < 1) (0<α<1)。
趋势分析旨在捕捉数据中的长期趋势。可以通过拟合多项式或其他函数来实现。假设我们采用线性趋势:
Y t = β 0 + β 1 ⋅ t + ϵ t Y_t = \beta_0 + \beta_1 \cdot t + \epsilon_t Yt=β0+β1⋅t+ϵt
其中 Y t Y_t Yt 是时间 t t t 的观测值, β 0 \beta_0 β0 是截距, β 1 \beta_1 β1 是斜率, ϵ t \epsilon_t ϵt 是误差项。
可以通过以下步骤来整合趋势和移动平均来预测太阳黑子的趋势:
计算移动平均: 使用简单移动平均或指数加权移动平均平滑太阳黑子的时间序列数据。
趋势分析: 利用线性趋势分析,拟合趋势方程。
整合: 将移动平均和趋势相加,得到整合后的趋势估计。
import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression # 生成模拟太阳黑子数据 np.random.seed(42) t = np.arange(1, 101) sunspots = 10 * np.sin(0.2 * t) + np.random.normal(scale=2, size=len(t)) # 创建DataFrame data = pd.DataFrame({'Time': t, 'Sunspots': sunspots}) # 计算简单移动平均 window_size = 5 data['SMA'] = data['Sunspots'].rolling(window=window_size).mean() # 趋势分析 X = data['Time'].values.reshape(-1, 1) y = data['Sunspots'].values model = LinearRegression() model.fit(X, y) data['Trend'] = model.predict(X) # 整合趋势和移动平均 data['Integrated_Trend'] = data['SMA'] + data['Trend'] # 绘制结果 plt.figure(figsize=(10, 6)) plt.plot(data['Time'], data['Sunspots'], label='Original Data') plt.plot(data['Time'], data['SMA'], label=f'SMA ({window_size} periods)') plt.plot(data['Time'], data['Trend'], label='Trend') plt.plot(data['Time'], data['Integrated_Trend'], label='Integrated Trend') plt.xlabel('Time') plt.ylabel('Sunspots') plt.legend() plt.show()
理论基础:
太阳活动周期: 太阳活动表现为周期性的变化,主要是由于太阳磁场的活动导致的。太阳活动的周期性变化约为11年,被称为太阳活动周期或太阳周期。这个周期性变化主要是由太阳黑子的数量和太阳黑子区域的活动引起的。
太阳黑子与太阳活动关系: 太阳黑子是太阳表面的一种现象,它们标志着强烈的磁活动。太阳黑子的数量和活动水平通常与整个太阳活动周期相关联,即在太阳周期内,太阳黑子的数量经历峰值和谷值的变化。
峰值时期: 太阳周期中的峰值时期被称为太阳最大值。在太阳最大值时,太阳黑子的数量和太阳黑子区域的活动都达到峰值。这通常是太阳活动的高峰期,伴随着较强的太阳射击和其他太阳活动。
太阳最大值的预测: 预测太阳最大值的发生时间和持续时间是一个复杂的问题,因为它涉及到理解太阳活动的驱动机制以及对太阳周期的整体变化的建模。传统上,科学家们使用太阳黑子的观测数据,结合数学模型,例如傅里叶分析、差分方程、时间序列分析等,来尝试预测太阳最大值。
5.峰值的持续时间: 太阳最大值的持续时间通常取决于太阳黑子的活动水平和持续时间。在太阳最大值期间,太阳黑子活动较为频繁和强烈。持续时间的估计可能涉及到对太阳黑子数据的统计分析和模型拟合。
预测太阳活动的确切时刻和强度是一个非常复杂的问题,因为太阳活动受多种影响,包括太阳磁场的变化和其他不确定性因素。目前,没有单一的理论公式可以准确描述太阳活动周期的最大值时刻和持续时间。然而,一些传统的方法和模型被用来尝试进行这样的预测。
Wolf数(Wolf Number):
Wolf数是一种用于衡量太阳黑子活动水平的指标,可以用来估计太阳活动周期的强度。它通常由以下公式定义:
W = 10 ⋅ G + N W = 10 \cdot G + N W=10⋅G+N
其中 $ G $ 是给定时期内的太阳黑子群的数量,$ N $ 是给定时期内的太阳黑子的总数。
斯皮格勒公式(Spörer’s Law):
斯皮格勒公式描述了太阳活动周期的变化,其基本形式为:
D = A + B ⋅ C M D = A + B \cdot C^M D=A+B⋅CM
其中 $ D $ 是太阳活动周期的持续时间,$ A 、 、 、 B 、 、 、 C $ 和 $ M $ 是与具体时期相关的参数。
正弦函数是一种简单而常用的周期性函数,可以用来描述太阳活动的周期性变化。在这里,我们将使用正弦函数来进行太阳活动周期的分析:
Y ( t ) = A sin ( 2 π f t + ϕ ) + C Y(t) = A \sin(2\pi ft + \phi) + C Y(t)=Asin(2πft+ϕ)+C
其中:
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit # 模拟太阳活动周期数据 np.random.seed(42) t = np.arange(1, 301) sunspots = 10 * np.sin(0.1 * t) + np.random.normal(scale=2, size=len(t)) # 定义正弦函数模型 def sine_function(t, A, f, phi, C): return A * np.sin(2 * np.pi * f * t + phi) + C # 使用 curve_fit 拟合正弦函数模型 params, covariance = curve_fit(sine_function, t, sunspots) # 提取拟合后的参数 A_fit, f_fit, phi_fit, C_fit = params # 生成拟合后的曲线 fit_curve = sine_function(t, A_fit, f_fit, phi_fit, C_fit) # 绘制原始数据和拟合后的曲线 plt.figure(figsize=(10, 6)) plt.plot(t, sunspots, label='Original Data') plt.plot(t, fit_curve, label='Fit Curve') plt.xlabel('Time') plt.ylabel('Sunspots') plt.legend() plt.show() # 输出拟合后的参数 print(f"振幅 (A): {A_fit}") print(f"频率 (f): {f_fit}") print(f"相位 (phi): {phi_fit}") print(f"偏移项 (C): {C_fit}")
针对太阳周期的最大值,可以使用峰值检测方法,找到太阳活动周期中的峰值时刻。并观察活动水平的持续时间。
import numpy as np import pandas as pd from scipy.signal import find_peaks # 生成模拟太阳黑子数据 np.random.seed(42) t = np.arange(1, 301) sunspots = 10 * np.sin(0.1 * t) + np.random.normal(scale=2, size=len(t)) # 创建DataFrame data = pd.DataFrame({'Time': t, 'Sunspots': sunspots}) # 寻找峰值 peaks, _ = find_peaks(data['Sunspots'], height=0) # 提取峰值对应的时间点 peak_times = data['Time'].iloc[peaks] # 计算持续时间 if len(peak_times) >= 2: max_intensity_start = peak_times.iloc[0] max_intensity_end = peak_times.iloc[-1] max_intensity_duration = max_intensity_end - max_intensity_start else: max_intensity_start = max_intensity_end = max_intensity_duration = np.nan print(f"预测太阳周期太阳最大值的发生时间:从 {max_intensity_start} 到 {max_intensity_end}") print(f"预测太阳周期太阳最大值的持续时间:{max_intensity_duration} 单位时间")
太阳周期信息: 使用历史数据分析,确定太阳周期的长度和变化。
历史太阳黑子数量: 考虑前几个周期的太阳黑子数量作为特征。
我们使用长短时记忆网络(LSTM)进行时间序列预测时,模型的基本公式可以描述为以下过程:
输入层:
输入层接受时间序列数据,其形状为 ( b a t c h _ s i z e , t i m e _ s t e p s , f e a t u r e s ) (batch\_size, time\_steps, features) (batch_size,time_steps,features)。
LSTM 层:
LSTM 层是模型的核心部分,其内部包含许多门(gates),用于控制信息的流动。LSTM 的更新过程如下:
输入门(Input Gate):
i
t
=
σ
(
W
i
i
x
t
+
b
i
i
+
W
h
i
h
t
−
1
+
b
h
i
)
i_t = \sigma(W_{ii} x_t + b_{ii} + W_{hi} h_{t-1} + b_{hi})
it=σ(Wiixt+bii+Whiht−1+bhi)
遗忘门(Forget Gate):
f
t
=
σ
(
W
i
f
x
t
+
b
i
f
+
W
h
f
h
t
−
1
+
b
h
f
)
f_t = \sigma(W_{if} x_t + b_{if} + W_{hf} h_{t-1} + b_{hf})
ft=σ(Wifxt+bif+Whfht−1+bhf)
细胞状态(Cell State)更新:
g
t
=
tanh
(
W
i
g
x
t
+
b
i
g
+
W
h
g
h
t
−
1
+
b
h
g
)
g_t = \tanh(W_{ig} x_t + b_{ig} + W_{hg} h_{t-1} + b_{hg})
gt=tanh(Wigxt+big+Whght−1+bhg)
c
t
=
f
t
⋅
c
t
−
1
+
i
t
⋅
g
t
c_t = f_t \cdot c_{t-1} + i_t \cdot g_t
ct=ft⋅ct−1+it⋅gt
输出门(Output Gate):
o
t
=
σ
(
W
i
o
x
t
+
b
i
o
+
W
h
o
h
t
−
1
+
b
h
o
)
o_t = \sigma(W_{io} x_t + b_{io} + W_{ho} h_{t-1} + b_{ho})
ot=σ(Wioxt+bio+Whoht−1+bho)
隐藏状态更新:
h
t
=
o
t
⋅
tanh
(
c
t
)
h_t = o_t \cdot \tanh(c_t)
ht=ot⋅tanh(ct)
其中, σ \sigma σ 表示 sigmoid 激活函数, tanh \tanh tanh 表示双曲正切激活函数, W W W 和 b b b 分别是权重和偏置。
输出层:
输出层产生模型的最终预测结果。在时间序列预测中,可以是单个值或多个值,具体取决于任务的性质。
损失函数:
损失函数用于度量模型预测值与实际值之间的差异。在回归任务中,常用均方误差(Mean Squared Error,MSE)作为损失函数。
整个 LSTM 模型的训练过程涉及通过反向传播算法调整权重和偏置,使损失函数最小化。
import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.preprocessing import MinMaxScaler from sklearn.metrics import mean_squared_error from keras.models import Sequential from keras.layers import LSTM, Dense # 生成模拟太阳黑子数据 np.random.seed(42) t = np.arange(1, 501) sunspots = 10 * np.sin(0.1 * t) + np.random.normal(scale=2, size=len(t)) # 归一化数据 scaler = MinMaxScaler(feature_range=(0, 1)) sunspots_normalized = scaler.fit_transform(sunspots.reshape(-1, 1)) # 创建时间窗口数据集 def create_dataset(dataset, time_steps=1): dataX, dataY = [], [] for i in range(len(dataset) - time_steps): a = dataset[i:(i + time_steps), 0] dataX.append(a) dataY.append(dataset[i + time_steps, 0]) return np.array(dataX), np.array(dataY) # 设置时间窗口大小 time_steps = 10 # 创建时间窗口数据集 X, y = create_dataset(sunspots_normalized, time_steps) # 将数据整形为 LSTM 期望的格式 [样本数, 时间步数, 特征数] X = np.reshape(X, (X.shape[0], X.shape[1], 1)) # 构建 LSTM 模型 model = Sequential() model.add(LSTM(units=50, return_sequences=True, input_shape=(X.shape[1], 1))) model.add(LSTM(units=50)) model.add(Dense(units=1)) model.compile(optimizer='adam', loss='mean_squared_error') # 训练模型 model.fit(X, y, epochs=100, batch_size=1, verbose=2) # 使用训练好的模型进行预测 train_predict = model.predict(X) train_predict = scaler.inverse_transform(train_predict) y_actual = scaler.inverse_transform(y.reshape(-1, 1)) # 计算均方根误差 rmse = np.sqrt(mean_squared_error(y_actual, train_predict)) print(f"均方根误差 (RMSE): {rmse}") # 可视化预测结果 plt.figure(figsize=(15, 6)) plt.plot(t[time_steps:], sunspots[time_steps:], label='实际值') plt.plot(t[time_steps:], train_predict, label='预测值') plt.xlabel('时间步数') plt.ylabel('太阳黑子数量') plt.legend() plt.show()
在数据预处理阶段,我们对太阳黑子数量和面积的历史数据进行了可行性分析,并采取了一系列合理的处理方法。可行性结果的重新组织:
缺失值和异常值处理:
时间序列平滑:
# 缺失值处理 - 线性插值
def interpolate_missing_values(data):
interpolated_data = data.interpolate(method='linear')
return interpolated_data
# 异常值处理 - 修正为阈值
def handle_outliers(data, threshold):
data[data > threshold] = threshold
return data
# 时间序列平滑 - 移动平均
def smooth_time_series(data, window_size):
smoothed_data = data.rolling(window=window_size).mean()
return smoothed_data
通过对比处理前后数据的统计特征、可视化结果以及在一小部分数据上的模型预测效果,我们对处理后数据的质量和对模型的影响进行了评估。这一系列处理方法在维护数据质量的同时,为后续的预测模型提供了更为可靠的输入。
这样的数据预处理工作为进一步建立和训练预测模型奠定了基础,确保模型在真实世界的应用中能够取得更好的性能。
更多内容具体可以看看我的下方名片!里面包含有认证杯一手资料与分析!
另外在赛中,我们也会陪大家一起解析认证杯的一些方向
关注 CS数模 团队,数模不迷路~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。