前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用深度强化学习预测股票:DQN 、Double DQN和Dueling Double DQN对比和代码示例

使用深度强化学习预测股票:DQN 、Double DQN和Dueling Double DQN对比和代码示例

作者头像
deephub
发布于 2024-07-01 06:41:36
发布于 2024-07-01 06:41:36
30900
代码可运行
举报
文章被收录于专栏:DeepHub IMBADeepHub IMBA
运行总次数:0
代码可运行

深度强化学习可以将深度学习强化学习相结合:深度学习擅长从原始数据中学习复杂的表示,强化学习则使代理能够通过反复试验在给定环境中学习最佳动作。通过DRL,研究人员和投资者可以开发能够分析历史数据的模型,理解复杂的市场动态,并对股票购买、销售或持有做出明智的决策。

下面我们一边写代码一边介绍这些相关的知识

数据集

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 import numpy as np
 import pandas as pd
 import copyimport numpy as npimport chainer
 import chainer.functions as F
 import chainer.links as Lfrom plotly import tools
 from plotly.graph_objs import *
 from plotly.offline import init_notebook_mode, iplot, iplot_mpl
 from tqdm import tqdm_notebook as tqdminit_notebook_mode()

这里主要使用使用Jupyter notebook和plotly进行可视化,所以需要一些额外的设置,下面开始读取数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 try:
     data = pd.read_csv('../input/Data/Stocks/goog.us.txt')
     data['Date'] = pd.to_datetime(data['Date'])
     data = data.set_index('Date')except (FileNotFoundError):    import datetime
     import pandas_datareader as pdr
     from pandas import Series, DataFrame    start = datetime.datetime(2010, 1, 1)
     end = datetime.datetime(2017, 1, 11)    data = pdr.get_data_yahoo("AAPL", start, end)print(data.index.min(), data.index.max())split_index = int(len(data)/2)
 date_split = data.index[split_index]
 train = data[:split_index]
 test = data[split_index:]#date_split = '2016-01-01'
 date_split = '2016-01-01'
 train = data[:date_split]
 test = data[date_split:]
 print(len(data), len(train), len(test))
 display(data)

代码从数据集中读取数据。进行测试和验证集的拆分,然后使用' display '函数,代码在Jupyter笔记本中显示导入的数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def plot_train_test(train, test, date_split):
     
     data = [
         Candlestick(x=train.index, open=train['Open'], high=train['High'], low=train['Low'], close=train['Close'], name='train'),
         Candlestick(x=test.index, open=test['Open'], high=test['High'], low=test['Low'], close=test['Close'], name='test')
     ]
     layout = {
          'shapes': [
              {'x0': date_split, 'x1': date_split, 'y0': 0, 'y1': 1, 'xref': 'x', 'yref': 'paper', 'line': {'color': 'rgb(0,0,0)', 'width': 1}}
          ],
         'annotations': [
             {'x': date_split, 'y': 1.0, 'xref': 'x', 'yref': 'paper', 'showarrow': False, 'xanchor': 'left', 'text': ' test data'},
             {'x': date_split, 'y': 1.0, 'xref': 'x', 'yref': 'paper', 'showarrow': False, 'xanchor': 'right', 'text': 'train data '}
         ]
     }
     figure = Figure(data=data, layout=layout)
     iplot(figure)

这段代码定义了一个名为plot_train_test的函数,该函数使用Python绘图库Plotly创建可视化图。基于指定的日期,图表将股票数据分为训练集和测试集。输入参数包括train、test和date_split。

可视化结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 plot_train_test(train, test, date_split)

环境

下面我们开始编写强化学习相关的内容

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 class Environment:
     
     def __init__(self, data, history_t=90):
         self.data = data
         self.history_t = history_t
         self.reset()
         
     def reset(self):
         self.t = 0
         self.done = False
         self.profits = 0
         self.positions = []
         self.position_value = 0
         self.history = [0 for _ in range(self.history_t)]
         return [self.position_value] + self.history # obs
     
     def step(self, act):
         reward = 0
         
         # act = 0: stay, 1: buy, 2: sell
         if act == 1:
             self.positions.append(self.data.iloc[self.t, :]['Close'])
         elif act == 2: # sell
             if len(self.positions) == 0:
                 reward = -1
             else:
                 profits = 0
                 for p in self.positions:
                     profits += (self.data.iloc[self.t, :]['Close'] - p)
                 reward += profits
                 self.profits += profits
                 self.positions = []
         
         # set next time
         self.t += 1
         self.position_value = 0
         for p in self.positions:
             self.position_value += (self.data.iloc[self.t, :]['Close'] - p)
         self.history.pop(0)
         self.history.append(self.data.iloc[self.t, :]['Close'] - self.data.iloc[(self.t-1), :]['Close'])
         
         # clipping reward
         if reward > 0:
             reward = 1
         elif reward < 0:
             reward = -1
         
         return [self.position_value] + self.history, reward, self.done, self.profits # obs, reward, done, profits

首先定义强化学习的环境,这里的Environment的类模拟了一个简单的交易环境。使用历史股票价格数据,代理可以根据这些数据决定是否购买、出售或持有股票。

init()接受两个参数:data,表示股票价格数据;history_t,定义环境应该维持多少时间步长。通过设置data和history_t值并调用reset(),构造函数初始化了环境。

Reset()初始化或重置环境的内部状态变量,包括当前时间步长(self.t)、完成标志、总利润、未平仓头寸、头寸值和历史价格。该方法返回由头寸价值和价格历史组成的观测值。

step()方法,可以基于一个动作更新环境的状态。动作用整数表示:0表示持有,1表示购买,2表示出售。如果代理人决定买入,股票的当前收盘价将被添加到头寸列表中。一旦经纪人决定卖出,该方法计算每个未平仓头寸的利润或损失,并相应地更新利润变量。然后,所有未平仓头寸被平仓。根据卖出行为中产生的利润或损失,奖励被削减到- 1,0或1。

代理可以使用Environment类学习并根据历史股票价格数据做出决策,Environment类模拟股票交易环境。在受控环境中,可以训练强化学习代理来制定交易策略。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 env = Environment(train)
 print(env.reset())
 for _ in range(3):
     pact = np.random.randint(3)
     print(env.step(pact))

DQN

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def train_dqn(env, epoch_num=50):
     class Q_Network(chainer.Chain):
         def __init__(self, input_size, hidden_size, output_size):
             super(Q_Network, self).__init__(
                 fc1 = L.Linear(input_size, hidden_size),
                 fc2 = L.Linear(hidden_size, hidden_size),
                 fc3 = L.Linear(hidden_size, output_size)
             )        def __call__(self, x):
             h = F.relu(self.fc1(x))
             h = F.relu(self.fc2(h))
             y = self.fc3(h)
             return y
         def reset(self):
             self.zerograds()
     Q = Q_Network(input_size=env.history_t+1, hidden_size=100, output_size=3)
     Q_ast = copy.deepcopy(Q)
     optimizer = chainer.optimizers.Adam()
     optimizer.setup(Q)
     step_max = len(env.data)-1
     memory_size = 200
     batch_size = 20
     epsilon = 1.0
     epsilon_decrease = 1e-3
     epsilon_min = 0.1
     start_reduce_epsilon = 200
     train_freq = 10
     update_q_freq = 20
     gamma = 0.97
     show_log_freq = 5    memory = []
     total_step = 0
     total_rewards = []
     total_losses = []    start = time.time()
     for epoch in range(epoch_num):        pobs = env.reset()
         step = 0
         done = False
         total_reward = 0
         total_loss = 0
         while not done and step < step_max:            # select act
             pact = np.random.randint(3)
             if np.random.rand() > epsilon:
                 pact = Q(np.array(pobs, dtype=np.float32).reshape(1, -1))
                 pact = np.argmax(pact.data)            # act
             obs, reward, done, profit = env.step(pact)            # add memory
             memory.append((pobs, pact, reward, obs, done))
             if len(memory) > memory_size:
                 memory.pop(0)            # train or update q
             if len(memory) == memory_size:
                 if total_step % train_freq == 0:
                     shuffled_memory = np.random.permutation(memory)
                     memory_idx = range(len(shuffled_memory))
                     for i in memory_idx[::batch_size]:
                         batch = np.array(shuffled_memory[i:i+batch_size])
                         b_pobs = np.array(batch[:, 0].tolist(), dtype=np.float32).reshape(batch_size, -1)
                         b_pact = np.array(batch[:, 1].tolist(), dtype=np.int32)
                         b_reward = np.array(batch[:, 2].tolist(), dtype=np.int32)
                         b_obs = np.array(batch[:, 3].tolist(), dtype=np.float32).reshape(batch_size, -1)
                         b_done = np.array(batch[:, 4].tolist(), dtype=np.bool)
                         q = Q(b_pobs)
                         maxq = np.max(Q_ast(b_obs).data, axis=1)
                         target = copy.deepcopy(q.data)
                         for j in range(batch_size):
                             target[j, b_pact[j]] = b_reward[j]+gamma*maxq[j]*(not b_done[j])
                         Q.reset()
                         deephub_loss = F.mean_squared_error(q, target)
                         total_loss += loss.data
                         loss.backward()
                         optimizer.update()
                 if total_step % update_q_freq == 0:
                         Q_ast = copy.deepcopy(Q)            # epsilon
             if epsilon > epsilon_min and total_step > start_reduce_epsilon:
                 epsilon -= epsilon_decrease            # next step
             total_reward += reward
             pobs = obs
             step += 1
             total_step += 1        
             total_rewards.append(total_reward)
         total_losses.append(total_loss)
         if (epoch+1) % show_log_freq == 0:
             log_reward = sum(total_rewards[((epoch+1)-show_log_freq):])/show_log_freq
             log_loss = sum(total_losses[((epoch+1)-show_log_freq):])/show_log_freq
             elapsed_time = time.time()-start
             print('\t'.join(map(str, [epoch+1, epsilon, total_step, log_reward, log_loss, elapsed_time])))
             start = time.time()
             
     return Q, total_losses, total_rewards

这段代码定义了一个函数train_dqn(),它为一个简单的股票交易环境训练一个Deep Q-Network (DQN)。该函数接受两个参数:一个是env参数,表示交易环境;另一个是epoch_num参数,指定要训练多少epoch。

代码定义了一个Q_Network类,它是Chainer的Chain类的一个子类。在Q-Network中,有三个完全连接的层,前两层具有ReLU激活函数。模型梯度通过reset()方法归零。

创建Q- network的两个实例Q和Q_ast,以及用于更新模型参数的Adam优化器。对于DQN训练,定义了几个超参数,包括缓冲区内存大小、批处理大小、epsilon、gamma和更新频率。

为了跟踪模型在训练期间的表现,在内存列表中创建total_rewards和total_losses列表。在每个epoch的开始,环境被重置,一些变量被初始化。

代理根据当前状态和epsilon-greedy探索策略选择一个动作(持有、买入或卖出)。然后,代理在环境中执行动作,获得奖励,并观察新的状态。在缓冲区中,存储了经验元组(前一个状态、动作、奖励、新状态和完成标志)。

为了训练DQN,当缓冲区满时,从内存中采样一批经验。利用Q_ast网络和Bellman方程,计算了目标q值。损失计算为预测q值与目标q值之间的均方误差。计算梯度,优化器更新模型参数。

目标网络Q_ast使用主网络q的权值定期更新,随着智能体的学习,epsilon值线性减小,促进更多的利用。每个时期,总奖励和损失都会累积起来,结果也会被记录下来。

训练结束时,train_dqn()返回训练后的Q-Network、总损失和总奖励。DQN模型可用于根据输入的股票价格数据和模拟的交易环境制定交易策略。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 dqn, total_losses, total_rewards = train_dqn(Environment(train), epoch_num=25)

这段代码使用来自指定环境的训练数据(使用train_dqn函数)训练DQN模型,并返回训练后的模型以及每个训练历元的总损失和奖励。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def plot_loss_reward(total_losses, total_rewards):
    figure = tools.make_subplots(rows=1, cols=2, subplot_titles=('loss', 'reward'), print_grid=False)
    figure.append_trace(Scatter(y=total_losses, mode='lines', line=dict(color='skyblue')), 1, 1)
    figure.append_trace(Scatter(y=total_rewards, mode='lines', line=dict(color='orange')), 1, 2)
    figure['layout']['xaxis1'].update(title='epoch')
    figure['layout']['xaxis2'].update(title='epoch')
    figure['layout'].update(height=400, width=900, showlegend=False)
    iplot(figure)

plot_loss_reward”使用Plotly库的“make_subplots”函数创建一个带有两个子图的图形。在训练周期内,该图显示了损失值和奖励值的趋势,提供了对DQN模型性能的洞察。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot_loss_reward(total_losses, total_rewards)

显示了在训练时期损失和奖励值的趋势。在DQN模型(可能用于股票市场预测)的训练过程中,代码使用该函数绘制损失和回报值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def plot_train_test_by_q(train_env, test_env, Q, algorithm_name):
    
    # train
    pobs = train_env.reset()
    train_acts = []
    train_rewards = []
    train_ongoing_profits = []
    for _ in range(len(train_env.data)-1):
        
        pact = Q(np.array(pobs, dtype=np.float32).reshape(1, -1))
        pact = np.argmax(pact.data)
        train_acts.append(pact)
            
        obs, reward, done, profit = train_env.step(pact)
        train_rewards.append(reward)
        train_ongoing_profits.append(profit)        pobs = obs
        
    train_profits = train_env.profits
    
    # test
    pobs = test_env.reset()
    test_acts = []
    test_rewards = []
    test_ongoing_profits = []    for _ in range(len(test_env.data)-1):
    
        pact = Q(np.array(pobs, dtype=np.float32).reshape(1, -1))
        pact = np.argmax(pact.data)
        test_acts.append(pact)
            
        deep_hub_obs, reward, done, profit = test_env.step(pact)
        test_rewards.append(reward)
        test_ongoing_profits.append(profit)        pobs = obs
        
    test_profits = test_env.profits
    
    # plot
    train_copy = train_env.data.copy()
    test_copy = test_env.data.copy()
    train_copy['act'] = train_acts + [np.nan]
    train_copy['reward'] = train_rewards + [np.nan]
    test_copy['act'] = test_acts + [np.nan]
    test_copy['reward'] = test_rewards + [np.nan]
    train0 = train_copy[train_copy['act'] == 0]
    train1 = train_copy[train_copy['act'] == 1]
    train2 = train_copy[train_copy['act'] == 2]
    test0 = test_copy[test_copy['act'] == 0]
    test1 = test_copy[test_copy['act'] == 1]
    test2 = test_copy[test_copy['act'] == 2]
    act_color0, act_color1, act_color2 = 'gray', 'cyan', 'magenta'    data = [
        Candlestick(x=train0.index, open=train0['Open'], high=train0['High'], low=train0['Low'], close=train0['Close'], increasing=dict(line=dict(color=act_color0)), decreasing=dict(line=dict(color=act_color0))),
        Candlestick(x=train1.index, open=train1['Open'], high=train1['High'], low=train1['Low'], close=train1['Close'], increasing=dict(line=dict(color=act_color1)), decreasing=dict(line=dict(color=act_color1))),
        Candlestick(x=train2.index, open=train2['Open'], high=train2['High'], low=train2['Low'], close=train2['Close'], increasing=dict(line=dict(color=act_color2)), decreasing=dict(line=dict(color=act_color2))),
        Candlestick(x=test0.index, open=test0['Open'], high=test0['High'], low=test0['Low'], close=test0['Close'], increasing=dict(line=dict(color=act_color0)), decreasing=dict(line=dict(color=act_color0))),
        Candlestick(x=test1.index, open=test1['Open'], high=test1['High'], low=test1['Low'], close=test1['Close'], increasing=dict(line=dict(color=act_color1)), decreasing=dict(line=dict(color=act_color1))),
        Candlestick(x=test2.index, open=test2['Open'], high=test2['High'], low=test2['Low'], close=test2['Close'], increasing=dict(line=dict(color=act_color2)), decreasing=dict(line=dict(color=act_color2)))
    ]
    title = '{}: train s-reward {}, profits {}, test s-reward {}, profits {}'.format(
       deephub_algorithm_name,
        int(sum(train_rewards)),
        int(train_profits),
        int(sum(test_rewards)),
        int(test_profits)
    )
    layout = {
        'title': title,
        'showlegend': False,
         'shapes': [
             {'x0': date_split, 'x1': date_split, 'y0': 0, 'y1': 1, 'xref': 'x', 'yref': 'paper', 'line': {'color': 'rgb(0,0,0)', 'width': 1}}
         ],
        'annotations': [
            {'x': date_split, 'y': 1.0, 'xref': 'x', 'yref': 'paper', 'showarrow': False, 'xanchor': 'left', 'text': ' test data'},
            {'x': date_split, 'y': 1.0, 'xref': 'x', 'yref': 'paper', 'showarrow': False, 'xanchor': 'right', 'text': 'train data '}
        ]
    }
    figure = Figure(data=data, layout=layout)
    iplot(figure)
    
    return train_ongoing_profits, test_ongoing_profits

Plot_train_test_by_q()将训练好的DQN模型在训练和测试数据集上的交易行为和性能可视化。

使用训练好的Q-Network,该函数初始化环境并迭代训练和测试数据。对于这两个数据集,它都会累积行动、奖励和持续利润。

为了分析或比较算法的性能,该函数返回训练和测试数据集的持续利润。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
train_profits, test_profits = plot_train_test_by_q(Environment(train), Environment(test), dqn, 'DQN')

基于DQN模型的预测,' train_profits '变量接收从训练数据中获得的利润。' test_profits '接收测试数据作为DQN模型预测的结果而获得的利润。

代码在训练和测试数据上评估训练好的DQN模型,并计算每个数据集上获得的利润。这种评价可能有助于确定DQN模型的准确性和有效性。

我们还可以将,将DQN模型的性能与用于股市预测的“买入并持有”策略进行比较。Matplotlib的' plt '模块用于生成绘图。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plt.figure(figsize=(23,8))
plt.plot(data.index,((data['Close']-data['Close'][0])/data['Close'][-1]), label='buy and hold')
plt.plot(train.index, ([0] + train_profits)/data['Close'][-1], label='rl (train)')
plt.plot(test.index, (([0] + test_profits) + train_profits[-1])/data['Close'][-1], label='rl (test)')
plt.ylabel('relative gain')
plt.legend()
plt.show()

代码绘制了在训练数据上获得的利润。在该图中,x轴表示训练数据的指数,y轴表示DQN模型预测的相对收益。相对收益是通过将利润除以输入数据中的最后收盘价来计算的。

使用DQN模型,代码绘制了在测试数据上获得的利润。x轴表示测试数据的指数,y轴表示DQN模型预测的相对利润增益。通过将训练利润相加并除以导入数据中的最后收盘价来计算相对收益。该图的标签为“rl (test)”。

使用Matplotlib库的“show”函数显示该图。在训练和测试数据上,该图显示了“买入并持有”策略和DQN模型预测的相对利润增益。将DQN模型与“买入并持有”等简单策略进行比较,可以深入了解其有效性。

Double DQN

Double Deep Q-Network (DDQN) 是一种用于强化学习中的深度学习算法,特别是在处理离散动作空间的 Q-Learning 问题时非常有效。DDQN 是对传统 Deep Q-Network (DQN) 的一种改进,旨在解决 DQN 在估计 Q 值时可能存在的过高估计(overestimation)问题。

DDQN 使用一个额外的神经网络来评估选取最大 Q 值的动作。它不再直接使用目标 Q 网络预测的最大 Q 值来更新当前 Q 网络的 Q 值,而是使用当前 Q 网络选择的动作在目标 Q 网络中预测的 Q 值来更新。这种方法通过减少动作选择与目标 Q 值计算之间的相关性,有助于减轻 Q 值的过高估计问题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def train_ddqn(env, epoch_num=50):
    class Q_Network(chainer.Chain): 
        def __init__(self, input_size, hidden_size, output_size):
            super(Q_Network, self).__init__(
                fc1 = L.Linear(input_size, hidden_size),
                fc2 = L.Linear(hidden_size, hidden_size),
                fc3 = L.Linear(hidden_size, output_size)
            )        def __call__(self, x):
            h = F.relu(self.fc1(x))
            h = F.relu(self.fc2(h))
            y = self.fc3(h)
            return y
        def reset(self):
            self.zerograds()
            Q = Q_Network(input_size=env.history_t+1, hidden_size=100, output_size=3)
    Q_ast = copy.deepcopy(Q)
    optimizer = chainer.optimizers.Adam()
    optimizer.setup(Q)
    step_max = len(env.data)-1
    memory_size = 200
    batch_size = 50
    epsilon = 1.0
    epsilon_decrease = 1e-3
    epsilon_min = 0.1
    start_reduce_epsilon = 200
    train_freq = 10
    update_q_freq = 20
    gamma = 0.97
    show_log_freq = 5    memory = []
    total_step = 0
    total_rewards = []
    total_losses = []    start = time.time()
    for epoch in range(epoch_num): 
        pobs = env.reset()
        step = 0
        done = False
        total_reward = 0
        total_loss = 0
        while not done and step < step_max:            # select act
            pact = np.random.randint(3)
            if np.random.rand() > epsilon:
                pact = Q(np.array(pobs, dtype=np.float32).reshape(1, -1))
                pact = np.argmax(pact.data)            # act
            obs, reward, done, profit = env.step(pact)            # add memory
            memory.append((pobs, pact, reward, obs, done))
            if len(memory) > memory_size:
                memory.pop(0)            # train or update q
            if len(memory) == memory_size:
                if total_step % train_freq == 0:
                    deep_hub_shuffled_memory = np.random.permutation(memory)
                    memory_idx = range(len(shuffled_memory))
                    for i in memory_idx[::batch_size]:
                        batch = np.array(shuffled_memory[i:i+batch_size])
                        b_pobs = np.array(batch[:, 0].tolist(), dtype=np.float32).reshape(batch_size, -1)
                        b_pact_deephub = np.array(batch[:, 1].tolist(), dtype=np.int32)
                        b_reward = np.array(batch[:, 2].tolist(), dtype=np.int32)
                        b_obs = np.array(batch[:, 3].tolist(), dtype=np.float32).reshape(batch_size, -1)
                        b_done = np.array(batch[:, 4].tolist(), dtype=np.bool) 
                        q = Q(b_pobs)
                        """ <<< DQN -> Double DQN
                        maxq = np.max(Q_ast(b_obs).data, axis=1)
                        === """
                        indices = np.argmax(q.data, axis=1)
                        maxqs = Q_ast(b_obs).data
                        """ >>> """
                        target = copy.deepcopy(q.data)
                        for j in range(batch_size):
                            """ <<< DQN -> Double DQN
                            target[j, b_pact[j]] = b_reward[j]+gamma*maxq[j]*(not b_done[j])
                            === """
                            target[j, b_pact[j]] = b_reward[j]+gamma*maxqs[j, indices[j]]*(not b_done[j])
                            """ >>> """
                        Q.reset()
                        loss = F.mean_squared_error(q, target)
                        total_loss += loss.data
                        loss.backward()
                        optimizer.update()
                        if total_step % update_q_freq == 0:
                    	Q_ast = copy.deepcopy(Q)            # epsilon
            if epsilon > epsilon_min and total_step > start_reduce_epsilon:
                epsilon -= epsilon_decrease            # next step
            total_reward += reward
            pobs = obs
            step += 1
            total_step += 1
            total_rewards.append(total_reward)
        total_losses.append(total_loss)
        if (epoch+1) % show_log_freq == 0:
            log_reward = sum(total_rewards[((epoch+1)-show_log_freq):])/show_log_freq
            log_loss = sum(total_losses[((epoch+1)-show_log_freq):])/show_log_freq
            elapsed_time = time.time()-start
            print('\t'.join(map(str, [epoch+1, epsilon, total_step, log_reward, log_loss, elapsed_time])))
            start = time.time()
            
    return Q, total_losses, total_rewards

上面代码定义了一个函数train_ddqn(),该函数训练Double Deep Q-Network (DDQN)来解决交易环境。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ddqn, total_losses, total_rewards = train_ddqn(Environment(train), epoch_num=50)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot_loss_reward(total_losses, total_rewards)

可视化了在训练时期的损失和奖励值的趋势。在DDQN模型(可能用于预测股票市场价格)的训练过程中,该函数绘制损失和回报值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
train_profits, test_profits = plot_train_test_by_q(Environment(train), Environment(test), ddqn, 'Double DQN')

在训练和测试数据上评估训练后的DDQN模型的性能,为每个数据集获得利润。对于股票市场预测或其他需要强化学习的决策任务,此评估的结果可能有用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plt.figure(figsize=(23,8))
plt.plot(data.index,((data['Close']-data['Close'][0])/data['Close'][-1]), label='buy and hold')
plt.plot(train.index, ([0] + train_profits)/data['Close'][-1], label='rl (train)')
plt.plot(test.index, (([0] + test_profits) + train_profits[-1])/data['Close'][-1], label='rl (test)')
plt.ylabel('relative gain')
plt.legend()
plt.show()

可以看到Double DQN要更高一些。这和Double Deep Q-Network的介绍: (DDQN)通过使用两个神经网络来分别估计当前策略选择的动作和目标 Q 值的最大动作,有效解决了传统 DQN 中的 Q 值过高估计问题,提高了在离散动作空间下的强化学习性能和稳定性。是相吻合的

Dueling Double DQN

Dueling Double Deep Q-Network (Dueling DDQN) 是一种结合了两种技术的强化学习算法:Dueling网络结构和Double DQN。它旨在进一步提高 Q-Learning 的效率和稳定性,特别是在处理离散动作空间的问题时非常有效。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def train_dddqn(env, epoch_num=50):    """ <<< Double DQN -> Dueling Double DQN
    class Q_Network(chainer.Chain):        def __init__(self, input_size, hidden_size, output_size):
            super(Q_Network, self).__init__(
                fc1 = L.Linear(input_size, hidden_size),
                fc2 = L.Linear(hidden_size, hidden_size),
                fc3 = L.Linear(hidden_size, output_size)
            )        def __call__(self, x):
            h = F.relu(self.fc1(x))
            h = F.relu(self.fc2(h))
            y = self.fc3(h)
            return y        def reset(self):
            self.zerograds()
    === """
    class Q_Network(chainer.Chain): 
        def __init__(self, input_size, hidden_size, output_size):
            super(Q_Network, self).__init__(
                fc1 = L.Linear(input_size, hidden_size),
                fc2 = L.Linear(hidden_size, hidden_size),
                fc3 = L.Linear(hidden_size, hidden_size//2),
                fc4 = L.Linear(hidden_size, hidden_size//2),
                state_value = L.Linear(hidden_size//2, 1),
                advantage_value = L.Linear(hidden_size//2, output_size)
            )
            self.input_size = input_size
            self.hidden_size = hidden_size
            self.output_size = output_size        def __call__(self, x):
            h = F.relu(self.fc1(x))
            h = F.relu(self.fc2(h))
            hs = F.relu(self.fc3(h))
            ha = F.relu(self.fc4(h))
            state_value = self.state_value(hs)
            advantage_value = self.advantage_value(ha)
            advantage_mean = (F.sum(advantage_value, axis=1)/float(self.output_size)).reshape(-1, 1)
            q_value = F.concat([state_value for _ in range(self.output_size)], axis=1) + (advantage_value - F.concat([advantage_mean for _ in range(self.output_size)], axis=1))
            return q_value
        def reset(self):
            self.zerograds()
    """ >>> """
    Q = Q_Network(input_size=env.history_t+1, hidden_size=100, output_size=3)
    Q_ast = copy.deepcopy(Q)
    optimizer = chainer.optimizers.Adam()
    optimizer.setup(Q)    step_max = len(env.data)-1
    memory_size = 200
    batch_size = 50
    epsilon = 1.0
    epsilon_decrease = 1e-3
    epsilon_min = 0.1
    start_reduce_epsilon = 200
    train_freq = 10
    update_q_freq = 20
    gamma = 0.97
    show_log_freq = 5    memory = []
    total_step = 0
    total_rewards = []
    total_losses = []
    start = time.time()
    for epoch in range(epoch_num):
        pobs = env.reset()
        step = 0
        done = False
        total_reward = 0
        total_loss = 0
        while not done and step < step_max:            # select act
            pact = np.random.randint(3)
            if np.random.rand() > epsilon:
                pact = Q(np.array(pobs, dtype=np.float32).reshape(1, -1))
                pact = np.argmax(pact.data)            # act
            obs, reward, done, profit = env.step(pact)            # add memory
            memory.append((pobs, pact, reward, obs, done))
            if len(memory) > memory_size:
                memory.pop(0)            # train or update q
            if len(memory) == memory_size:
                if total_step % train_freq == 0:
                    shuffled_memory = np.random.permutation(memory)
                    memory_idx = range(len(shuffled_memory))
                    for i in memory_idx[::batch_size]:
                        deephub_batch = np.array(shuffled_memory[i:i+batch_size])
                        b_pobs = np.array(batch[:, 0].tolist(), dtype=np.float32).reshape(batch_size, -1)
                        b_pact = np.array(batch[:, 1].tolist(), dtype=np.int32)
                        b_reward = np.array(batch[:, 2].tolist(), dtype=np.int32)
                        b_obs = np.array(batch[:, 3].tolist(), dtype=np.float32).reshape(batch_size, -1)
                        b_done = np.array(batch[:, 4].tolist(), dtype=np.bool)                        q = Q(b_pobs)
                        """ <<< DQN -> Double DQN
                        maxq = np.max(Q_ast(b_obs).data, axis=1)
                        === """
                        indices = np.argmax(q.data, axis=1)
                        maxqs = Q_ast(b_obs).data
                        """ >>> """
                        target = copy.deepcopy(q.data)
                        for j in range(batch_size):
                            """ <<< DQN -> Double DQN
                            target[j, b_pact[j]] = b_reward[j]+gamma*maxq[j]*(not b_done[j])
                            === """
                            target[j, b_pact[j]] = b_reward[j]+gamma*maxqs[j, indices[j]]*(not b_done[j])
                            """ >>> """
                        Q.reset()
                        loss = F.mean_squared_error(q, target)
                        total_loss += loss.data
                        loss.backward()
                        optimizer.update()
                        if total_step % update_q_freq == 0:
                    	Q_ast = copy.deepcopy(Q)            # epsilon
            if epsilon > epsilon_min and total_step > start_reduce_epsilon:
                epsilon -= epsilon_decrease            # next step
            total_reward += reward
            pobs = obs
            step += 1
            total_step += 1
            total_rewards.append(total_reward)
        total_losses.append(total_loss)
        if (epoch+1) % show_log_freq == 0:
            log_reward = sum(total_rewards[((epoch+1)-show_log_freq):])/show_log_freq
            log_loss = sum(total_losses[((epoch+1)-show_log_freq):])/show_log_freq
            elapsed_time = time.time()-start
            print('\t'.join(map(str, [epoch+1, epsilon, total_step, log_reward, log_loss, elapsed_time])))
            start = time.time()
            
    return Q, total_losses, total_rewards

call方法中,前两层在两个流之间共享,然后分成两个独立的流。状态价值流有一个输出单个值的额外线性层(state_value),而优势价值流有一个为每个动作输出值的额外线性层(advantage_value)。最终的q值由状态值和优势值结合计算,并减去平均优势值以保持稳定性。代码的其余部分与Double DQN实现非常相似。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dddqn, total_losses, total_rewards = train_dddqn(Environment(train), epoch_num=25)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plot_loss_reward(total_losses, total_rewards)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
train_profits, test_profits = plot_train_test_by_q(Environment(train), Environment(test), dddqn, 'Dueling Double DQN')
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
plt.figure(figsize=(23,8))
plt.plot(data.index,((data['Close']-data['Close'][0])/data['Close'][-1]), label='buy and hold')
plt.plot(train.index, ([0] + train_profits)/data['Close'][-1], label='rl (train)')
plt.plot(test.index, (([0] + test_profits) + train_profits[-1])/data['Close'][-1], label='rl (test)')
plt.plot(test.index, (([0] + test_profits) - data['Close'][0] + data['Close'][len(train_profits)])/data['Close'][-1], label='rl (test)')
plt.ylabel('relative gain')
plt.legend()
plt.show()

Dueling Double Deep Q-Network (Dueling DDQN) 是一种结合了 Dueling 网络结构和 Double DQN 的强化学习算法。它通过将 Q 函数分解为状态值函数和优势函数来提高效率,同时利用 Double DQN 的思想来减少 Q 值的过高估计,从而在处理离散动作空间下的强化学习问题中表现出色。

总结

让我们对传统的 Deep Q-Network (DQN), Double DQN, Dueling DQN 和 Dueling Double DQN 进行对比总结,看看它们各自的特点和优劣势。

1、Deep Q-Network (DQN)

  • 特点
    • 使用深度神经网络来估计 Q 函数,从而学习到每个状态下每个动作的价值。
    • 使用经验回放和固定 Q 目标网络来提高稳定性和收敛性。
  • 优点
    • 引入深度学习提高了 Q 函数的表示能力,能够处理复杂的状态和动作空间。
    • 经验回放和固定 Q 目标网络有助于稳定训练过程,减少样本间的相关性。
  • 缺点
    • 存在 Q 值的过高估计问题,尤其是在动作空间较大时更为明显,这可能导致训练不稳定和性能下降。

2、Double Deep Q-Network (Double DQN)

  • 特点
    • 解决了 DQN 中 Q 值过高估计的问题。
    • 引入一个额外的目标 Q 网络来计算目标 Q 值,减少更新时的相关性。
  • 优点
    • 减少了 Q 值的过高估计,提高了训练的稳定性和收敛性。
  • 缺点
    • 算法结构相对简单,对于某些复杂问题可能需要更高的表示能力。

3、Dueling Double Deep Q-Network (Dueling DDQN)

  • 特点
    • 结合了 Dueling 网络结构和 Double DQN 的优势。
    • 使用 Dueling 网络结构来分解 Q 函数,提高了效率和学习表示能力。
    • 使用 Double DQN 的思想来减少 Q 值的过高估计问题。
  • 优点
    • 综合了两种技术的优势,能够在更广泛的问题空间中表现出色。
    • 提高了训练的稳定性和效率,有助于更快地收敛到较好的策略。
  • 缺点
    • 算法实现和调优可能比单一 DQN 及其改进版更复杂。

总结比较

  • 效果和稳定性:Dueling DDQN 在处理动作空间较大的问题时表现出更高的效率和稳定性,因为它们能够更有效地分离状态值和动作优势。
  • 过高估计问题:Dueling DDQN 解决了传统 DQN 中 Q 值过高估计的问题,其中 Double DQN 通过目标网络降低相关性,而 Dueling 结构则通过优势函数减少过高估计。
  • 复杂性:Dueling DDQN 相对于传统 DQN 和 Double DQN 更复杂,需要更多的实现和理解成本,但也带来了更好的性能。

传统 DQN 适用于简单的强化学习任务,而 Double DQN、Dueling DDQN 则适用于更复杂和具有挑战性的问题,根据问题的特性选择合适的算法可以有效提升训练效率和性能。

最后我们也看到,深度强化学习预测股票是可行的,因为他不再预测具体的股票价格,而是针对收益预测买进,卖出和持有,我们这里只是使用了股票本身的数据,如果有更多的外生数据那么强化学习应该可以模拟更准确的人工操作。

数据集地址:

https://www.kaggle.com/datasets/borismarjanovic/price-volume-data-for-all-us-stocks-etfs

作者:Connor Roberts

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DeepHub IMBA 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
OpenDaylight铍版本初体验——坑还多吗
OpenDaylight项目发布铍版本(ODL Be),这也是其发布的第四个版本,距离上次发布锂版本(SR3)仅仅只相隔了两个半月,相比较以前版本发布,时间较短,但是据官方宣称,这个发布与先前版本有着
SDNLAB
2018/04/02
1.8K0
OpenDaylight铍版本初体验——坑还多吗
OpenDaylight即将迈入“七年之痒”?
前段时间看到一篇文章,叫《OpenStack已死?》,讲述了OpenStack自2010年提出之后的9年间各方利益牵扯导致的一系列问题,尽管最终作者的结论是OpenStack现在只是进入了成熟期,但实际上早在16年就已经有人开始对OpenStack的发展提出质疑。看到这里有人要说了,你要谈OpenDaylight(ODL)扯我们OpenStack干什么,饭圈第一守则不要“踩一捧一”好吗?别着急,下面我们就来说说ODL。
SDNLAB
2019/05/17
1K0
OpenDaylight即将迈入“七年之痒”?
开源MANO软件盘点
本文描述了ETSI NFV MANO的概况,以及在该领域的概况。 MANO致力于“管理和编排”,是ETSI NFV定义的架构框架的功能模块的一部分。OSM即开源MANO。 Fig 1 – ETSI N
SDNLAB
2018/04/02
2.9K0
开源MANO软件盘点
NFV基本概念_nf缩写是什么意思
NFV(网络功能虚拟化) SDN(软件定义网络) NFV即网络功能虚拟化(Network Functions Virtualization),将许多类型的网络设备(如servers,switches和storage等)构建为一个Data Center Network,通过借用IT的虚拟化技术虚拟化形成VM(虚拟机,Virtual Machine),然后将传统的CT业务部署到VM上。 在NFV出现之前设备的专业化很突出,具体设备都有其专门的功能实现,而之后设备的控制平面与具体设备进行分离,不同设备的控制平面基于虚拟机,虚拟机基于云操作系统,这样当企业需要部署新业务时只需要在开放的虚拟机平台上创建相应的虚机,然后在虚拟机上安装相应功能的软件包即可。这种方式我们就叫做网络功能虚拟化。
全栈程序员站长
2022/09/30
1.6K0
NFV基本概念_nf缩写是什么意思
SDN实战团分享(十九):OpenDaylight在电信网络中的应用
大家好!首先自我介绍一下:我来自中国电信广州研究院,我和我的SDN小组是一支来自电信运营商的研发团队,主要从事一些预研性的研究和开发工作。大家可能是从最近的一本关于ODL的新书《OpenDaylight应用指南》中了解到我们在ODL方面做过一些工作,我这里想说的是,我们的工作在整个运营商的SDN/NFV研究拼图中只是很小的一部分,因为这里涉及到宽带IP网、移动网、传输网、接入网、终端、BOSS等各类专业领域的向SDN的演进问题,今天我们没法在这里展开讲,只用一张图来表明一下相关的工作基础和广域网SDN控制器
SDNLAB
2018/04/02
1.3K0
SDN实战团分享(十九):OpenDaylight在电信网络中的应用
OPNFV SFC简介
今天主要让大家了解下下ODL 中SFC的实现,以下如有描述不准确的地方请指正。 1 基本概念 本架构参考ODL SFC项目,其已经合并到OPNFV的Brahmaputra平台 1.1 Service Functions SF提供特定的网络服务,例如Firewall,NAT,QoS,DPI等。在OPNFV中,SF指提供虚拟网络功能的设备。 1.2 Service Function Forwarders SFF是Service Chaining的核心组件,在OPNFV中,他是一个OVS bridge,在每个co
SDNLAB
2018/03/30
2.1K0
OPNFV SFC简介
开源MANO
MANO(管理和网络编排)在ETSI ISG NFV架构中定义为由多个功能实体所组合而成的一个层,这些功能实体负责管理和编排云基础设施、资源以及服务等。 NFVOrchestrator(编排器)负责管
SDNLAB
2018/03/30
2.3K0
开源MANO
SDxCentral 2015年NFV报告
1 报告概述 《2015年网络功能虚拟化(NFV)报告》将为读者提供关于NFV市场的发展趋势,以及目前取得进展等方面的观点。我们已经开始看到,在运营商,甚至在企业网上,越来越多的概念验证(POC)已经进行了尝试。因此目前非常重要的一件事情,就是认识到NFV对于整个网络产业所带来的巨大变化。 NFV以软件的方式实现网络的功能,因此能够部署在虚拟环境,以及通用的标准硬件上。这能够满足运营商及企业中多样化的网络要求,这也是应用、服务器和储存这些基础设施所依赖的。这篇报告主要分析NFV市场中主要的架构/设计、用
SDNLAB
2018/04/04
9240
SDxCentral 2015年NFV报告
OpenDaylight可视化和控制用例
概述 尽管控制平面在SDN领域吸引了大部分关注,但是网络管理平面的转变也同样重要。SDN提供了在广泛的案例中提高敏捷性同时降低成本的可能。然而,虚拟、物理和混合网络,各式各样的应用,和来自多个供应商的硬件全部一起管理起来是非常有挑战的。 通过自动化,前所未有的智能化,和域范围的可视化。SDN有可能为网络管理带来变革,其变革的程度不亚于服务交付。这些特性也强化了网络的安全管理,后者已经受益于SDN架构。与以往不大相同的是,网络和安全管理可以在中立厂商和多厂商环境中有效实现。 挑战 传统FCAPS(故障、配置、
SDNLAB
2018/04/02
8350
未来已来:网络功能虚拟化(NFV)势必引领下一代通信技术革命!
网络功能虚拟化(Network Function Virtualization, NFV)是当前网络领域的一项颠覆性技术,它将传统网络架构推向新的高度。在过去的几十年里,网络一直是固定功能的,运行在专用硬件上,这种架构在灵活性、可扩展性和成本方面存在挑战,随着云计算、物联网和5G等新兴技术的崛起,现有的网络架构不再能够满足快速变化的需求。NFV出现在这一背景下,它革新了网络功能的交付方式,将其虚拟化成软件实体,运行在通用硬件上。这一技术的影响不仅仅局限于电信和网络服务提供商,还延伸到了云计算、企业网络和边缘计算等领域。
网络技术联盟站
2023/11/13
4.2K0
未来已来:网络功能虚拟化(NFV)势必引领下一代通信技术革命!
VPP系列砖题七:SDN 控制器OpenDaylight在电信网络中的应用
OpenDaylight 是一套以社区为主导的开源框架,旨在推动创新实施以及软件定义网络(简称 SDN)透明化。面对 SDN 型网络,大家需要合适的工具帮助自己管理基础设施,这正是 OpenDaylight 的专长。作为项目核心,OpenDaylight 拥有一套模块化、可插拔且极为灵活的控制器,这使其能够被部署在任何支持 Java 的平台之上。这款控制器中还包含一套模块合集,能够执行需要快速完成的网络任务。
通信行业搬砖工
2023/07/09
1.3K1
VPP系列砖题七:SDN 控制器OpenDaylight在电信网络中的应用
OpenDaylight你不得不知道的十大问题——Opendaylight是什么?
一 ODL的诞生背景 随着互联网的普及,用户数量不断攀升,网络不堪重负。移动终端发展势如破竹,智能手机不断更新换代,各种手机软件层出不穷,手机控随时随地上网,导致流量需求与日俱增,负荷过度的网络无法满足用户需求。网络体系庞大,架构臃肿,不够灵活,不能适应不断涌现出的新业务需求,服务质量得不到保证。网络体系复杂,网络操作需要与其他IT操作的集成与协作,导致网络部署困难。网络更新麻烦,动手操作过多,网络管理员分身乏术。改良已经无法解决现有的网络问题,网络改革势在必行,于是SDN应运而生。 SDN是美国斯坦
SDNLAB
2018/04/02
2K0
OpenDaylight你不得不知道的十大问题——Opendaylight是什么?
[新手指南]OPNFV,SDN for OpenStack
读过之前OpenStack基金会的NFV白皮书的粉丝,想必对OPNFV也不会陌生,本篇文章为大家介绍OPNFV的最新版本-Brahmaptura,帮您快速了解这个新版本的新功能及其他重要信息。 Open Platform for Network Function Virtualiziation(OPNFV)是一个历时2年的Linux基金会项目,提供了一个集成、可安装的开源NFV方案。OPNFV包含了OpenStack和超过30个其他可选组件, 并为它们增加了电信级功能。终端用户可以下载自己需要的安装包、操作
SDNLAB
2018/04/02
2.1K0
[新手指南]OPNFV,SDN for OpenStack
NFV帮助电信运营商节省WAN基础设施成本
虚拟化网络功能以及软件定义网络(SDN)是更广泛的电信广域网(WAN)基础设施向虚拟化和商品化过渡趋势的一部分。 网络功能虚拟化(NFV)的重点在于优化由WAN基础设施提供商这里成为(电信运营商,telcos)运营的网络服务,而SDN谋求的是将控制和转发平面分离,以实现网络的集中控制。 电信运营商采用NFV的主要驱动因素是基础设施的成本不断上升,以及云计算的大规模采用推动网络的变化。诸如Google和Skype等互联网内容提供商正在向用户提供新的视频和音频服务及内容,推出服务的速度比传统电
SDNLAB
2018/03/30
1.2K0
NFV帮助电信运营商节省WAN基础设施成本
菜鸟驿站:学习SDN/NFV路上遇到的术语(一)
SDN:软件定义网络(Software Defined Network,SDN),是一种新型的网络创新架构,是网络虚拟化的一种实现方式,其核心技术OpenFlow通过将网络设备的控制面和数据面分离开来,从而实现了网络流量的灵活控制,使网络作为管道变得更加智能。 NFV:网络功能虚拟化(Network Function Virtualization),通过X86等通用硬件以及虚拟化技术,来承载很多功能的软件处理。从而降低网络昂贵的设备成本,可通过软硬件解耦及功能抽象,使网络设备不在依赖于专用硬件,资源可以充分
SDNLAB
2018/04/02
1.3K0
菜鸟驿站:学习SDN/NFV路上遇到的术语(一)
白话网络编排(MANO),给你感兴趣的项目
网络功能虚拟化(NFV)提供了一种设计、部署和管理网络服务的全新方式,NFV将网络功能如网络地址转换(NAT)、防火墙、入侵检测、域名服务和缓存等功能从专有硬件中分离出来,并通过软件加以实现。NFV能够整合和交付完全虚拟化基础设施所需的网络组建,包括虚拟服务器、存储等。 NFV具备以下优势: ☘降低CAPEX:减少企业对专有硬件的需求,并且提供了按需付费的模式 ☘降低OPEX:简化网络服务的推出和管理 ☘加快服务投入市场的时间:减少部署新服务的时间,能够有效应对不断变化的业务需求,抓住市场机遇提高投资回报
SDNLAB
2018/03/29
2K0
白话网络编排(MANO),给你感兴趣的项目
ECOMP——增强型MANO,两大框架、两级编排、八大软件系统
一、AT&T为什么需要ECOMP? 自2006年开始到2013年期间,AT&T业务收入基本上原地踏步。八年业务收入总共增长8%,年均复合增长率接近1%。业务收入算术平均值为1255亿美金,八年最大的上下波动幅度仅仅为-5.7%--+5.5%。尽管这八年之间业务本身经历了宽带高速增长、triple play业务大发展、移动用户爆发式增长、智能手机拉动数据业务等巨大变化,但基本上算是此消彼长,总体业务收入稳如泰山。这才是AT&T在资本市场面临的大挑战。 业务收入持续高增长无望,而持续稳定股利分红的压力就变得山大
SDNLAB
2018/03/29
1.2K0
ECOMP——增强型MANO,两大框架、两级编排、八大软件系统
通过Tacker将NFV引入OpenStack
2014年的这个时候,我们还在OpenStack社区中为NFV是否属于OpenStack而争论不休。如今这一争议已经被解决了。OpenStack已经成为NFV讨论中的重要部分,正如下面的ETSI MA
SDNLAB
2018/04/03
1.3K0
通过Tacker将NFV引入OpenStack
SDN实战团分享(二十):From Lithium to Beryllium,ODL最新动态变化
家好, 感谢宇峰的邀请, 和大家分享OpenDaylight最新发布的一些进展,胶片主要来自Neela Jacques, Phil Robbs和Colin Dixon。 ODL 社区在铍版本的开发的两
SDNLAB
2018/04/02
7870
SDN实战团分享(二十):From Lithium to Beryllium,ODL最新动态变化
ODL应用案例之云和网络功能虚拟化应用案例
概述 近年来,大公司和中小企业已经认识到云计算技术是提高自己的竞争力的核心技术。混合云和公共云虽然具备了提高业务灵活性并降低总成本的潜力,但它们对于传统网络的需求依旧非常显著。云计算需要极其高水平的动态计算和自动化技术来解决快速变化的需求,当云计算在自动化计算和存储方向已经取得了重大进展的同时,网络自动化仍然因为更复杂而难以实现,从而阻碍了大多数云服务的部署。 通信服务提供商(CSP)也正利用云技术来增强其庞大的网络基础设施的可管理性和成本效益,同时提高了服务灵活性。许多世界领先的电信和有线电视运营商在网
SDNLAB
2018/04/02
1.1K0
ODL应用案例之云和网络功能虚拟化应用案例
推荐阅读
相关推荐
OpenDaylight铍版本初体验——坑还多吗
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档