时间序列的深度学习与强化学习实践
1. 深度学习模型在时间序列中的应用
在时间序列预测中,我们尝试了多种深度学习模型,以提高预测的准确性。
1.1 全连接前馈网络
首先,我们注意到在特定配置下,训练过程会持续更长时间。新的全连接前馈网络在拟合效果上比之前的网络有了显著提升。该网络结合了嵌入、缩放和基线等技术,对飞机乘客数量的预测与实际值的对比图表显示出较好的拟合效果。不过,我们将进一步优化该网络的任务留给读者自行尝试。
1.2 循环神经网络(RNN)
循环神经网络在建模时间序列中各点之间的长期关系方面表现出色。我们使用与之前相同的数据集,即航空公司乘客的单变量值。为了训练RNN,我们需要为每个训练样本准备一系列的点。在每个训练步骤中,RNN将基于前序乘客数量来预测下一个乘客数量。
以下是具体的操作步骤:
1.
数据重采样
:
def wrap_data(df, lookback: int):
dataset = []
for index in range(lookback, len(df)+1):
features = {
f"col_{i}": float(val) for i, val in enumerate(
df.iloc[index-lookback:index].values
)
}
row = pd.DataFrame.from_dict([features])
row.index = [df.index[index-1]]
dataset.append(row)
return pd.concat(dataset, axis=0)
LOOKBACK = 10
dataset = wrap_data(passengers, lookback=LOOKBACK)
dataset = dataset.join(passengers.shift(-1))
这里我们使用了
lookback
参数为10,但这并非最优值,读者可以尝试选择更合适的值。
- 导入必要的库 :
import tensorflow.keras as keras
from tensorflow.keras.layers import Input, Bidirectional, LSTM, Dense
import tensorflow as tf
- 定义RNN模型 :
def create_model(passengers):
input_layer = Input(shape=(LOOKBACK, 1))
recurrent = Bidirectional(LSTM(20, activation="tanh"))(input_layer)
output_layer = Dense(1)(recurrent)
model = keras.models.Model(inputs=input_layer, outputs=output_layer)
model.compile(loss='mse', optimizer=keras.optimizers.Adagrad(),
metrics=[keras.metrics.RootMeanSquaredError(), keras.metrics.MeanAbsoluteError()])
return model
这是一个双向LSTM网络,将LSTM的激活函数设置为
tanh
,以便在GPU运行时受益于NVIDIA的GPU加速库cuDNN。
- 数据划分与训练 :
from sklearn.model_selection import train_test_split
callback = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=3)
model = create_model(passengers)
X_train, X_test, y_train, y_test = train_test_split(
dataset.drop(columns="passengers"),
dataset["passengers"],
shuffle=False
)
model.fit(X_train, y_train, epochs=1000, callbacks=[callback])
训练结果已经相当不错,尽管我们做了一些次优的选择。
以下是整个RNN模型训练的流程图:
graph LR
A[数据准备] --> B[数据重采样]
B --> C[导入库]
C --> D[定义模型]
D --> E[数据划分]
E --> F[模型训练]
1.3 扩张因果卷积神经网络(Dilated Causal Convolutional Neural Network)
该模型基于Krist Papadopoulos对Anastasia Borovykh等人论文的实现。TensorFlow中进行因果卷积非常容易,
Conv1D
层的
padding
参数可以设置为
'causal'
,这会根据因果性质在层的输入前填充零,使得时间
t
的输出仅依赖于之前的时间步。
以下是具体的操作步骤:
1.
导入必要的库
:
import numpy as np
import pandas as pd
from keras.layers import Conv1D, Input, Add, Activation, Dropout
from keras.models import Sequential, Model
from keras.layers.advanced_activations import LeakyReLU, ELU
from keras import optimizers
import tensorflow as tf
- 定义DC_CNN块 :
def DC_CNN_Block(nb_filter, filter_length, dilation):
def f(input_):
residual = input_
layer_out = Conv1D(
filters=nb_filter, kernel_size=filter_length,
dilation_rate=dilation,
activation='linear', padding='causal', use_bias=False
)(input_)
layer_out = Activation('selu')(layer_out)
skip_out = Conv1D(1, 1, activation='linear', use_bias=False)(layer_out)
network_in = Conv1D(1, 1, activation='linear', use_bias=False)(layer_out)
network_out = Add()([residual, network_in])
return network_out, skip_out
return f
- 定义DC_CNN模型 :
def DC_CNN_Model(length):
input = Input(shape=(length,1))
l1a, l1b = DC_CNN_Block(32, 2, 1)(input)
l2a, l2b = DC_CNN_Block(32, 2, 2)(l1a)
l3a, l3b = DC_CNN_Block(32, 2, 4)(l2a)
l4a, l4b = DC_CNN_Block(32, 2, 8)(l3a)
l5a, l5b = DC_CNN_Block(32, 2, 16)(l4a)
l6a, l6b = DC_CNN_Block(32, 2, 32)(l5a)
l6b = Dropout(0.8)(l6b)
l7a, l7b = DC_CNN_Block(32, 2, 64)(l6a)
l7b = Dropout(0.8)(l7b)
l8 = Add()([l1b, l2b, l3b, l4b, l5b, l6b, l7b])
l9 = Activation('relu')(l8)
l21 = Conv1D(1, 1, activation='linear', use_bias=False)(l9)
model = Model(inputs=input, outputs=l21)
model.compile(loss='mae', optimizer=optimizers.Adam(),
metrics=['mse'])
return model
- 数据加载与划分 :
passengers = pd.read_csv(
"passengers.csv", parse_dates=["date "]
).set_index("date")
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
passengers.passengers, passengers.passengers.shift(-1),
shuffle=False
)
- 模型训练与预测 :
def fit_model(timeseries):
length = len(timeseries)-1
model = DC_CNN_Model(length)
model.summary()
X = timeseries[:-1].reshape(1,length, 1)
y = timeseries[1:].reshape(1,length, 1)
model.fit(X, y, epochs=3000, callbacks=[callback])
return model
def forecast(model, timeseries, horizon: int):
length = len(timeseries)-1
pred_array = np.zeros(horizon).reshape(1, horizon, 1)
X_test_initial = timeseries[1:].reshape(1,length,1)
pred_array[: ,0, :] = model.predict(X_test_initial)[:, -1:, :]
for i in range(horizon-1):
pred_array[:, i+1:, :] = model.predict(
np.append(
X_test_initial[:, i+1:, :],
pred_array[:, :i+1, :]
).reshape(1, length, 1))[:, -1:, :]
return pred_array.flatten()
def evaluate_timeseries(series, horizon: int):
model = fit_model(series)
pred_array = forecast(model, series, horizon)
return pred_array, model
HORIZON = len(y_test)
predictions, model = evaluate_timeseries(
X_train.values.reshape(-1, 1), horizon= HORIZON
)
该模型虽然很深,但由于卷积的存在,参数数量并不是很多。然而,模型的拟合效果并不是非常理想,无论是均方误差(MSE)还是预测图表都不太令人满意。这表明每个模型都有其优缺点,在没有对模型进行针对性调整和对数据进行仔细预处理的情况下,很难获得良好的性能。读者可以尝试调整该模型以提高性能。
2. 强化学习在时间序列中的应用
强化学习是一种广泛应用于控制问题和函数优化的范式,无需标记数据。它是一种基于经验的自主学习框架,智能体通过采取行动与环境直接交互,并通过试错来提高效率。
2.1 强化学习简介
强化学习是机器学习中的主要范式之一,与监督学习和无监督学习方法并列。与监督学习和无监督学习的被动响应不同,强化学习主动改变环境并寻找新的数据。从机器学习的角度来看,强化学习算法可以看作是在寻找优质数据和对这些数据进行监督学习之间交替进行。
强化学习在人工智能领域取得了重大突破,例如DeepMind的AlphaGo在2016年3月击败了职业围棋选手李世石,这一事件被视为人工智能发展的一个里程碑。有观点认为,强化学习正在推动我们向通用人工智能(AGI)迈进。
在强化学习中,智能体通过行动与环境交互,并以奖励的形式获得反馈。与监督学习不同,这里没有标记数据,智能体基于对累积奖励的期望来探索和利用环境。强化学习的核心目标是最大化累积奖励,通过与环境的交互,智能体学习采取更好的行动,从而形成目标导向的行为。
强化学习问题由三个主要组件定义:环境(ε)、智能体(A)和累积目标。智能体是一个决策实体,能够观察环境的当前状态并采取行动。执行行动会使智能体从一个状态转移到另一个状态,并获得一个数值奖励,该奖励是向目标前进的即时度量。环境的状态取决于当前状态、所采取的行动以及可能的随机因素。
强化学习主要分为两类:
-
基于价值的学习
:通过价值函数(模型)近似行动的结果或环境状态的价值,行动选择归结为采取具有最佳预期结果的行动。
-
基于策略的学习
:通过从环境状态预测行动来直接选择行动。
此外,强化学习还存在探索与利用的困境。智能体可以选择继续执行已知效果最佳的行动(利用),或者尝试新的途径(探索)。尝试新事物可能在短期内导致较差的结果,但可能在未来带来重要的经验教训。一种简单的平衡方法是ε - 贪心策略,通过随机选择探索或利用来平衡两者。ε是执行模型未识别为最佳行动的概率,ε值越高,模型的行动越随机。
深度学习强化学习(DRL)是强化学习方法的一个子集,其中模型是深度神经网络或多层感知机。
2.2 强化学习在时间序列中的应用
强化学习可以应用于时间序列问题,但需要以特定的方式构建问题。为了将强化学习应用于时间序列预测,预测结果必须能够触发行动,因此状态的演变取决于当前状态、智能体的行动以及随机因素。假设奖励可以是预测准确性的性能指标,但好或坏的预测结果本身并不会影响原始环境,这种情况本质上类似于监督学习问题。
更有意义的是,当我们将问题构建为强化学习问题时,系统的状态应该受到智能体决策的影响。例如,在与股票市场交互时,我们可以根据对股票走势的预测进行买卖操作,并将投资组合和资金等因素纳入状态中。
综上所述,强化学习非常适合处理随时间变化的过程,特别是那些可以被控制或影响的过程。在工业过程和控制中,强化学习已经得到了广泛的应用。
以下是强化学习在时间序列应用中的关键要点总结:
| 要点 | 详情 |
| ---- | ---- |
| 应用条件 | 预测需触发行动,状态演变受当前状态、行动和随机因素影响 |
| 实际案例 | 股票市场,根据预测买卖,考虑投资组合和资金 |
| 核心应用领域 | 工业过程和控制 |
时间序列的深度学习与强化学习实践(续)
3. 强化学习算法在时间序列中的应用实例
3.1 多臂老虎机算法(Bandit algorithms)
在强化学习中,多臂老虎机问题是一个经典的例子,它很好地体现了探索与利用的困境。想象有多个老虎机,每个老虎机有不同的奖励分布。智能体的目标是在有限的尝试次数内,通过不断尝试不同的老虎机(探索),找到奖励最高的老虎机,并尽可能多地使用它(利用)。
以下是几种常见的多臂老虎机算法:
-
ε - 贪心算法
:在前面我们已经提到过,这是一种简单的平衡探索和利用的方法。以一定的概率 ε 随机选择一个老虎机进行尝试(探索),以 1 - ε 的概率选择当前已知奖励最高的老虎机(利用)。代码示例如下:
import numpy as np
# 假设有 5 个老虎机
num_bandits = 5
# 每个老虎机的真实奖励分布
true_rewards = np.random.normal(0, 1, num_bandits)
# 每个老虎机的估计奖励
estimated_rewards = np.zeros(num_bandits)
# 每个老虎机的尝试次数
num_pulls = np.zeros(num_bandits)
# ε 值
epsilon = 0.1
# 总尝试次数
num_trials = 1000
for i in range(num_trials):
if np.random.uniform(0, 1) < epsilon:
# 探索:随机选择一个老虎机
bandit = np.random.choice(num_bandits)
else:
# 利用:选择估计奖励最高的老虎机
bandit = np.argmax(estimated_rewards)
# 获得奖励
reward = np.random.normal(true_rewards[bandit], 1)
# 更新估计奖励和尝试次数
num_pulls[bandit] += 1
estimated_rewards[bandit] += (reward - estimated_rewards[bandit]) / num_pulls[bandit]
- 上置信界(Upper Confidence Bound, UCB)算法 :UCB 算法通过为每个老虎机的估计奖励添加一个置信上界,来平衡探索和利用。置信上界表示了我们对每个老虎机奖励的不确定性,不确定性越大,我们越有动力去尝试该老虎机。代码示例如下:
import numpy as np
# 假设有 5 个老虎机
num_bandits = 5
# 每个老虎机的真实奖励分布
true_rewards = np.random.normal(0, 1, num_bandits)
# 每个老虎机的估计奖励
estimated_rewards = np.zeros(num_bandits)
# 每个老虎机的尝试次数
num_pulls = np.zeros(num_bandits)
# 总尝试次数
num_trials = 1000
for i in range(1, num_trials + 1):
# 计算每个老虎机的 UCB 值
ucb_values = estimated_rewards + np.sqrt(2 * np.log(i) / (num_pulls + 1e-6))
# 选择 UCB 值最大的老虎机
bandit = np.argmax(ucb_values)
# 获得奖励
reward = np.random.normal(true_rewards[bandit], 1)
# 更新估计奖励和尝试次数
num_pulls[bandit] += 1
estimated_rewards[bandit] += (reward - estimated_rewards[bandit]) / num_pulls[bandit]
3.2 深度 Q - 学习(Deep Q - Learning)
深度 Q - 学习是一种基于价值的强化学习算法,它结合了深度学习和 Q - 学习的思想。Q - 学习的核心是学习一个 Q 函数,该函数用于估计在某个状态下采取某个行动的预期累积奖励。在深度 Q - 学习中,我们使用深度神经网络来近似这个 Q 函数。
以下是深度 Q - 学习的基本步骤:
1.
定义状态和动作空间
:确定智能体可以观察到的状态和可以采取的动作。
2.
初始化 Q 网络
:使用深度神经网络初始化 Q 函数。
3.
与环境交互
:智能体根据当前的 Q 网络选择动作,与环境交互并获得奖励和下一个状态。
4.
更新 Q 网络
:使用经验回放和目标网络等技术来更新 Q 网络的参数,以最小化 Q 值的估计误差。
以下是一个简单的深度 Q - 学习代码示例:
import numpy as np
import tensorflow as tf
from collections import deque
import random
# 定义 Q 网络
class QNetwork(tf.keras.Model):
def __init__(self, state_size, action_size):
super(QNetwork, self).__init__()
self.dense1 = tf.keras.layers.Dense(24, activation='relu')
self.dense2 = tf.keras.layers.Dense(24, activation='relu')
self.output_layer = tf.keras.layers.Dense(action_size)
def call(self, x):
x = self.dense1(x)
x = self.dense2(x)
return self.output_layer(x)
# 定义经验回放缓冲区
class ReplayBuffer:
def __init__(self, buffer_size):
self.buffer = deque(maxlen=buffer_size)
def add(self, state, action, reward, next_state, done):
self.buffer.append((state, action, reward, next_state, done))
def sample(self, batch_size):
batch = random.sample(self.buffer, batch_size)
states, actions, rewards, next_states, dones = zip(*batch)
return np.array(states), np.array(actions), np.array(rewards), np.array(next_states), np.array(dones)
def __len__(self):
return len(self.buffer)
# 深度 Q - 学习算法
class DQNAgent:
def __init__(self, state_size, action_size):
self.state_size = state_size
self.action_size = action_size
self.q_network = QNetwork(state_size, action_size)
self.target_network = QNetwork(state_size, action_size)
self.optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
self.replay_buffer = ReplayBuffer(buffer_size=10000)
self.gamma = 0.95
self.epsilon = 1.0
self.epsilon_min = 0.01
self.epsilon_decay = 0.995
def act(self, state):
if np.random.rand() <= self.epsilon:
return np.random.choice(self.action_size)
state = np.reshape(state, [1, self.state_size])
q_values = self.q_network(state)
action = np.argmax(q_values.numpy())
return action
def replay(self, batch_size):
if len(self.replay_buffer) < batch_size:
return
states, actions, rewards, next_states, dones = self.replay_buffer.sample(batch_size)
next_q_values = self.target_network(next_states)
max_next_q_values = np.max(next_q_values.numpy(), axis=1)
target_q_values = rewards + (1 - dones) * self.gamma * max_next_q_values
with tf.GradientTape() as tape:
q_values = self.q_network(states)
one_hot_actions = tf.keras.utils.to_categorical(actions, self.action_size)
q_values = tf.reduce_sum(tf.multiply(q_values, one_hot_actions), axis=1)
loss = tf.keras.losses.mean_squared_error(target_q_values, q_values)
gradients = tape.gradient(loss, self.q_network.trainable_variables)
self.optimizer.apply_gradients(zip(gradients, self.q_network.trainable_variables))
if self.epsilon > self.epsilon_min:
self.epsilon *= self.epsilon_decay
def update_target_network(self):
self.target_network.set_weights(self.q_network.get_weights())
4. 总结
在时间序列的预测和处理中,深度学习和强化学习都展现出了强大的能力。深度学习模型如全连接前馈网络、循环神经网络和扩张因果卷积神经网络,通过对历史数据的学习和分析,能够捕捉时间序列中的复杂模式和长期关系,从而实现较为准确的预测。然而,每个模型都有其优缺点,需要根据具体的问题和数据特点进行选择和调整。
强化学习则为处理时间序列中的决策问题提供了一种有效的方法。它通过智能体与环境的交互,以最大化累积奖励为目标,学习最优的行动策略。在时间序列的应用中,强化学习尤其适用于那些可以被控制或影响的过程,如工业过程控制和金融投资决策等。
在实际应用中,我们可以根据具体的问题需求,灵活选择合适的模型和算法,并结合数据预处理、模型调优等技术,以提高预测和决策的准确性和效率。同时,不断探索和尝试新的方法和技术,也是推动时间序列分析和强化学习发展的重要途径。
以下是深度学习和强化学习在时间序列应用中的对比总结:
| 方法 | 优点 | 缺点 | 适用场景 |
| ---- | ---- | ---- | ---- |
| 深度学习 | 能够处理复杂的非线性关系,自动提取特征 | 需要大量的数据和计算资源,模型解释性较差 | 时间序列预测 |
| 强化学习 | 适用于决策问题,能够根据环境反馈动态调整策略 | 训练过程复杂,收敛速度慢 | 工业过程控制、金融投资决策 |
未来,随着技术的不断发展和创新,深度学习和强化学习在时间序列领域的应用将会更加广泛和深入,为解决各种实际问题提供更强大的支持。
以下是整个时间序列深度学习与强化学习应用的流程图:
graph LR
A[时间序列数据] --> B[深度学习模型]
B --> C[预测结果]
A --> D[强化学习环境]
D --> E[智能体]
E --> F[行动选择]
F --> D
D --> G[奖励反馈]
G --> E
C --> H[决策依据]
F --> H
超级会员免费看
2852

被折叠的 条评论
为什么被折叠?



