利用深度学习预测股票 - CSDN
  • 利用深度学习预测股票价格变动

    千次阅读 2019-09-10 20:52:48
    在这篇文章中,我将创建一个预测股票价格变动的完整过程。我们将使用生成对抗网络(GAN)与LSTM(一种循环神经网络)作为生成器,使用卷积神经网络CNN作为鉴别器。我们使用LSTM的原因很明显,我们正在尝试预测时间...

    博客原文:http://www.360doc.com/content/19/0112/18/410279_808412489.shtml

    完整架构概述

    在这篇文章中,我将创建一个预测股票价格变动的完整过程。我们将使用生成对抗网络(GAN)与LSTM(一种循环神经网络)作为生成器,使用卷积神经网络CNN作为鉴别器。我们使用LSTM的原因很明显,我们正在尝试预测时间序列数据。为什么我们使用GAN,特别是卷积神经网络(CNN)作为鉴别器呢?这是一个很好的问题:稍后会有特别的部分。

    当然,我们将详细介绍每个步骤,但最困难的部分是GAN:成功训练GAN的非常棘手的部分是获得正确的超参数集。出于这个原因,我们将使用贝叶斯优化(还有高斯过程)和深度强化学习(DRL)来决定何时以及如何改变GAN的超参数。在创建强化学习时,我将使用该领域的最新进展,例如Rainbow和PPO。

    我们将使用许多不同类型的输入数据。除了股票的历史交易数据和技术指标,我们将使用NLP的最新进展(使用“BERT,对NLP进行迁移学习)来创建情感分析(作为基本面分析的来源) ),用于提取整体趋势方向的傅里叶变换,用于识别其他高级特征的栈式自动编码器,用于查找相关资产的特征投资组合,差分整合移动平均自回归模型(ARIMA))对于股票函数近似,以便捕获尽可能多的关于股票的信息,模式,依赖关系等。我们都知道,数据越多越好。预测股价走势是一项极其复杂的任务,所以我们对股票(从不同的角度)了解得越多,我们的系统就会越好。

    为了创建所有神经网络,我们将使用MXNet和它的高级API - Gluon,并在多个GPU上训练它们。

    注:尽管我试图深入探讨数学和几乎所有算法和技术背后的机制,但本文并没有明确地解释机器/深度学习或股票市场是如何运作的。其目的是展示我们如何使用不同的技术和算法来准确预测股票价格的变动,并给出每一步使用每种技术的原因和有用性背后的理论基础。

    1.简介

    准确预测股票市场是一项复杂的任务,因为有数百万种情况会影响它。因此,我们需要能够尽可能多地捕获这些前置条件。我们还需要做出几个重要的假设:1)市场不是100%随机,2)历史重复,3)市场遵循人们的理性行为,4)市场是“ 完美的 ”。

    我们将尝试预测高盛(NYSE: GS)的价格走势。为此,我们将使用2010年1月1日至2018年12月31日的每日收盘价(七年数据用于训练,两年数据用于验证)。我们将交替使用“高盛”和“GS”这两个术语。

    2.数据

    我们需要尽可能多地合并信息(从不同方面和角度描绘股票)。我们将使用每日数据,1585天来训练各种算法(我们有70%的数据)并预测接下来的680天(测试数据),然后我们将把预测结果与测试数据进行比较。每种类型的数据(我们将其称为特征)将在后面的章节中进行更详细的解释,但是,作为一个高层次的概述,我们将使用的特征是:

    1. 相关资产 - 这些是其他资产(任何类型,不一定是股票,如商品,外汇,指数,甚至固定收益证券)。像高盛这样的大公司显然不会“生活”在一个孤立的世界中 - 它依赖于许多外部因素,并与之相互作用,包括竞争对手,客户,全球经济,地缘政治形势,财政和货币政策,获得资金等。详情将在后面列出。
    2. 技术指标 - 很多投资者都遵循技术指标。我们将最受欢迎的指标作为独立特征。如 - 7和21天移动平均线,指数移动平均线,momentum,布林线,MACD。
    3. 一个非常重要的特征,表明股票可能上涨或下跌。基本面分析有两个特征:1)使用10-K和10-Q报告分析公司业绩,分析ROE和P/E等(我们不会使用这个);我们将为高盛(Goldman Sachs)和阅读每日新闻提取总情绪是否对高盛(Goldman Sachs)在那一天是正面的,还是负面的(如得分从0到1)。由于许多投资者会仔细阅读新闻,并根据新闻(当然是部分依据新闻)做出投资决策,因此,如果高盛(Goldman Sachs)今天的消息非常正面,那么该股明天将大幅上涨的可能性在一定程度上是很高的。关键的一点是,我们将在以后对每个特征(包括这个特征)执行特征重要性(意思是它对GS波动的指示性),并决定是否使用它。我们将使用BERT - 谷歌最近公布的NLP方法,用于情感分类股票新闻情绪提取的迁移学习。
    4. 傅里叶变换 - 除了每日收盘价,我们还将创建傅里叶变换,以概括多个长期和短期趋势。使用这些变换,我们将消除大量噪声(随机游走)并创建真实股票移动的近似值。趋势近似可以帮助LSTM网络更准确地选择其预测趋势。
    5. 自回归整合移动平均线(ARIMA) - 这是预测时间序列数据未来值的最流行的技术之一(在pre-neural网络时代)。让我们添加它,看看它是否是一个重要的预测特征。
    6. 栈式自动编码器 - 上述大部分特征(基础分析、技术分析等)都是人们经过几十年的研究发现的。也许有一些隐藏的相关性,人们无法理解,因为有大量的数据点、事件、资产、图表等。通过栈式自动编码器(神经网络的类型),我们可以利用计算机的力量,可能会发现影响股票走势的新类型的特征。即使我们无法理解人类语言中的这些特征,我们也将在GAN中使用它们。
    7. 期权定价中异常检测的深度无监督学习。我们将再使用一项功能 - 每天我们都会为高盛股票增加90天看涨期权的价格。期权定价本身结合了大量数据。期权合约的价格取决于股票的未来值(分析师也试图预测价格,以便为看涨期权提供最准确的价格)。使用深度无监督机器学习(Self-organized Maps),我们将尝试发现每天定价中的异常情况。异常(例如价格的剧烈变化)可能表明一个事件可能对LSTM了解整个股票模式有用。

    接下来,有这么多特征,我们需要执行几个重要步骤:

    1. 对数据的“质量”进行统计检查。如果我们创建的数据有缺陷,那么无论我们的算法多么复杂,结果都不会是正确的。检查包括确保数据不受异方差、多重共线性或序列相关性的影响。
    2. 创建特征的重要性。如果一个特征(如另一只股票或一个技术指标)对我们想预测的股票没有解释力,那么我们就没有必要在神经网络的训练中使用它。我们将使用XGBoost(eXtreme Gradient boost),一种boosted 树回归算法。

    作为数据准备的最后一步,我们还将使用主成分分析(PCA)创建Eigen投资组合,以减少自动编码器创建的特征的维数。

    from utils import *
    import time
    import numpy as np
    from mxnet import nd, autograd, gluon
    from mxnet.gluon import nn, rnn
    import mxnet as mx
    import datetime
    import seaborn as sns
    import matplotlib.pyplot as plt
    %matplotlib inline
    from sklearn.decomposition import PCA
    import math
    from sklearn.preprocessing import MinMaxScaler
    from sklearn.metrics import mean_squared_error
    from sklearn.preprocessing import StandardScaler
    import xgboost as xgb
    from sklearn.metrics import accuracy_score
    import warnings
    warnings.filterwarnings("ignore")
    context = mx.cpu(); model_ctx=mx.cpu()
    mx.random.seed(1719)
    def parser(x):
     return datetime.datetime.strptime(x,'%Y-%m-%d')
    dataset_ex_df = pd.read_csv('data/panel_data_close.csv', header=0, parse_dates=[0], date_parser=parser)
    dataset_ex_df[['Date', 'GS']].head(3)
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    print('There are {} number of days in the dataset.'.format(dataset_ex_df.shape[0]))
    

    output >>> There are 2265 number of days in the dataset.

    让我们想象一下过去九年的股票。垂直虚线表示训练和测试数据之间的分离。

    plt.figure(figsize=(14, 5), dpi=100)
    plt.plot(dataset_ex_df['Date'], dataset_ex_df['GS'], label='Goldman Sachs stock')
    plt.vlines(datetime.date(2016,4, 20), 0, 270, linestyles='--', colors='gray', label='Train/Test data cut-off')
    plt.xlabel('Date')
    plt.ylabel('USD')
    plt.title('Figure 2: Goldman Sachs stock price')
    plt.legend()
    plt.show()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    num_training_days = int(dataset_ex_df.shape[0]*.7)
    print('Number of training days: {}. Number of test days: {}.'.format(num_training_days, 
     dataset_ex_df.shape[0]-num_training_days))
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    Number of training days: 1585. Number of test days: 680.

    2.1、相关资产

    如前所述,我们将使用其他资产作为特征,而不仅仅是GS。

    那么,还有哪些资产会影响高盛的股价走势呢?对公司、业务线、竞争环境、依赖关系、供应商和客户类型等的良好理解对于选择正确的相关资产集非常重要:

    • 首先是类似于GS的公司。我们将把摩根大通(JPMorgan Chase)和摩根士丹利(Morgan Stanley)等公司加入数据集。
    • 作为一家投资银行,高盛(Goldman Sachs)依赖于全球经济。经济不景气或不稳定意味着没有并购或IPO,也可能是有限的自营交易收益。这就是为什么我们将包括全球经济指数。此外,我们将包括LIBOR(美元和英镑计价)利率,因为分析师可能会考虑经济的冲击来设定这些利率以及其他FI证券。
    • 每日波动率指数(VIX) - 由于前一点所述的原因。
    • 综合指数 - 例如纳斯达克和纽约证券交易所(美国)、FTSE100指数(英国)、Nikkei225指数(日本)、恒生指数和BSE Sensex指数(亚太)。
    • 货币 - 全球贸易多次反映货币如何变动,因此我们将使用一篮子货币(如美元兑日元,英镑兑美元等)作为特征。

    总的来说,我们在数据集中有72个其他资产 - 每个资产的每日价格。

    2.2、技术指标

    我们已经讨论了什么是技术指标以及为什么使用它们,现在让我们直接跳到Python代码。我们将只为GS创建技术指标。

    def get_technical_indicators(dataset):
     # Create 7 and 21 days Moving Average
     dataset['ma7'] = dataset['price'].rolling(window=7).mean()
     dataset['ma21'] = dataset['price'].rolling(window=21).mean()
     
     # Create MACD
     dataset['26ema'] = pd.ewma(dataset['price'], span=26)
     dataset['12ema'] = pd.ewma(dataset['price'], span=12)
     dataset['MACD'] = (dataset['12ema']-dataset['26ema'])
     # Create Bollinger Bands
     dataset['20sd'] = pd.stats.moments.rolling_std(dataset['price'],20)
     dataset['upper_band'] = dataset['ma21'] + (dataset['20sd']*2)
     dataset['lower_band'] = dataset['ma21'] - (dataset['20sd']*2)
     
     # Create Exponential moving average
     dataset['ema'] = dataset['price'].ewm(com=0.5).mean()
     
     # Create Momentum
     dataset['momentum'] = dataset['price']-1
     
     return dataset
    dataset_TI_df = get_technical_indicators(dataset_ex_df[['GS']])
    dataset_TI_df.head()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    所以我们有每个交易日的技术指标(包括MACD、Bollinger bands等)。我们总共有12项技术指标。

    让我们想象一下这些指标的最后400天。

    def plot_technical_indicators(dataset, last_days):
     plt.figure(figsize=(16, 10), dpi=100)
     shape_0 = dataset.shape[0]
     xmacd_ = shape_0-last_days
     
     dataset = dataset.iloc[-last_days:, :]
     x_ = range(3, dataset.shape[0])
     x_ =list(dataset.index)
     
     # Plot first subplot
     plt.subplot(2, 1, 1)
     plt.plot(dataset['ma7'],label='MA 7', color='g',linestyle='--')
     plt.plot(dataset['price'],label='Closing Price', color='b')
     plt.plot(dataset['ma21'],label='MA 21', color='r',linestyle='--')
     plt.plot(dataset['upper_band'],label='Upper Band', color='c')
     plt.plot(dataset['lower_band'],label='Lower Band', color='c')
     plt.fill_between(x_, dataset['lower_band'], dataset['upper_band'], alpha=0.35)
     plt.title('Technical indicators for Goldman Sachs - last {} days.'.format(last_days))
     plt.ylabel('USD')
     plt.legend()
     # Plot second subplot
     plt.subplot(2, 1, 2)
     plt.title('MACD')
     plt.plot(dataset['MACD'],label='MACD', linestyle='-.')
     plt.hlines(15, xmacd_, shape_0, colors='g', linestyles='--')
     plt.hlines(-15, xmacd_, shape_0, colors='g', linestyles='--')
     plt.plot(dataset['log_momentum'],label='Momentum', color='b',linestyle='-')
     plt.legend()
     plt.show()
    plot_technical_indicators(dataset_TI_df, 400)
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    2.3、基本面分析

    对于基本面分析,我们将对所有关于GS的每日新闻进行情感分析。最后使用sigmoid,结果将在0和1之间。分数越接近0 - 新闻越负面(接近1表示正面情感)。对于每一天,我们将创建平均每日得分(作为0到1之间的数字)并将其添加为特征。

    2.3.1、 BERT

    为了将新闻分类为正面或负面(或中性),我们将使用BERT,这是一种预训练的语言表示。

    已经在MXNet / Gluon中提供预训练的BERT模型。我们只需要实例化它们并添加两个(任意数量)Dense层,softmax - 得分从0到1。

    # just import bert
    import bert
    

    2.4、傅立叶变换用于趋势分析

    傅立叶变换采用函数并创建一系列正弦波(具有不同的幅度和帧)。组合时,这些正弦波接近原始函数。从数学上讲,变换看起来像这样:

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    我们将使用傅里叶变换来提取GS股票的整体和局部趋势,并对其进行降噪。我们来看看它是如何工作的。

    data_FT = dataset_ex_df[['Date', 'GS']]
    close_fft = np.fft.fft(np.asarray(data_FT['GS'].tolist()))
    fft_df = pd.DataFrame({'fft':close_fft})
    fft_df['absolute'] = fft_df['fft'].apply(lambda x: np.abs(x))
    fft_df['angle'] = fft_df['fft'].apply(lambda x: np.angle(x))
    plt.figure(figsize=(14, 7), dpi=100)
    fft_list = np.asarray(fft_df['fft'].tolist())
    for num_ in [3, 6, 9, 100]:
     fft_list_m10= np.copy(fft_list); fft_list_m10[num_:-num_]=0
     plt.plot(np.fft.ifft(fft_list_m10), label='Fourier transform with {} components'.format(num_))
    plt.plot(data_FT['GS'], label='Real')
    plt.xlabel('Days')
    plt.ylabel('USD')
    plt.title('Figure 3: Goldman Sachs (close) stock prices & Fourier transforms')
    plt.legend()
    plt.show()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    正如您在图3中看到的,我们使用傅里叶变换的成分越多,逼近函数越接近实际股票价格(100个成分变换几乎与原始函数相同 - 红色和紫色线几乎重叠)。我们使用傅立叶变换来提取长期和短期趋势,因此我们将使用具有3,6和9个成分的变换。您可以推断出具有3个成分的转换是长期趋势。

    用于去噪数据的另一种技术是调用小波。小波和傅里叶变换给出了类似的结果,因此我们只使用傅里叶变换。

    from collections import deque
    items = deque(np.asarray(fft_df['absolute'].tolist()))
    items.rotate(int(np.floor(len(fft_df)/2)))
    plt.figure(figsize=(10, 7), dpi=80)
    plt.stem(items)
    plt.title('Figure 4: Components of Fourier transforms')
    plt.show()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    2.5、ARIMA作为一项特征值

    ARIMA是一种预测时间序列数据的技术。我们将展示如何使用它,虽然ARIMA不能作为我们的最终预测,但我们将使用它作为一种技术来稍微降低噪声,并(可能)提取一些新的模式或特征。

    from statsmodels.tsa.arima_model import ARIMA
    from pandas import DataFrame
    from pandas import datetime
    series = data_FT['GS']
    model = ARIMA(series, order=(5, 1, 0))
    model_fit = model.fit(disp=0)
    print(model_fit.summary())
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    from pandas.tools.plotting import autocorrelation_plot
    autocorrelation_plot(series)
    plt.figure(figsize=(10, 7), dpi=80)
    plt.show() 
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    from pandas import read_csv
    from pandas import datetime
    from statsmodels.tsa.arima_model import ARIMA
    from sklearn.metrics import mean_squared_error
    X = series.values
    size = int(len(X) * 0.66)
    train, test = X[0:size], X[size:len(X)]
    history = [x for x in train]
    predictions = list()
    for t in range(len(test)):
     model = ARIMA(history, order=(5,1,0))
     model_fit = model.fit(disp=0)
     output = model_fit.forecast()
     yhat = output[0]
     predictions.append(yhat)
     obs = test[t]
     history.append(obs)
    error = mean_squared_error(test, predictions)
    print('Test MSE: %.3f' % error)
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    Test MSE: 10.151

    # Plot the predicted (from ARIMA) and real prices
    plt.figure(figsize=(12, 6), dpi=100)
    plt.plot(test, label='Real')
    plt.plot(predictions, color='red', label='Predicted')
    plt.xlabel('Days')
    plt.ylabel('USD')
    plt.title('Figure 5: ARIMA model on GS stock')
    plt.legend()
    plt.show()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    从图5中可以看出,ARIMA给出了一个非常接近实际股价的结果。我们将通过ARIMA使用预测价格作为LSTM的输入特征,因为正如我们前面提到的,我们希望尽可能多地捕获关于高盛的特征和模式。我们测试MSE(均方误差)为10.151,这本身并不是一个坏结果(考虑到我们有很多测试数据),但是我们仍然只将其作为LSTM中的一个特征。

    2.6、统计检查

    确保数据具有良好的质量对于机器学习模型非常重要。为了确保我们的数据拟合,我们将执行几个简单的检查,以确保我们实现和观察到的结果是真实的,而不是因为底层数据分布存在基本错误而受到损害。

    2.6.1、异方差性,多重共线性,序列相关性

    • 条件异方差发生在误差项(通过回归得到的预测值与实际值之间的差)依赖于数据时——例如,误差项随着数据点(沿x轴)的增长而增长。
    • 多重共线性是指误差项(也称为残差)相互依赖的时间。
    • 序列相关性是指一个数据(特征)是另一个特征的公式(或完全不相关)。

    我们不会在这里进入代码,因为它很简单,我们的重点更多地放在深度学习部分,但数据是定性的。

    2.7、特征工程

    print('Total dataset has {} samples, and {} features.'.format(dataset_total_df.shape[0], 
     dataset_total_df.shape[1]))
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    Total dataset has 2265 samples, and 112 features.

    因此,在添加了所有类型的数据(相关资产、技术指标、基础分析、傅立叶和Arima)之后,我们在这2,265天中总共有112个特征(如前所述,训练数据只有1,585天)。

    我们还将从自动编码器生成更多特征。

    2.7.1、XGBoost的重要性

    有这么多的特征,我们必须要考虑它们是否真的代表了走势。例如,我们在机器学习数据集中包含了以美元计价的LIBOR利率,因为我们认为LIBOR的变化可能表明经济的变化,而经济的变化又可能表明GS的股票行为的变化。但我们需要测试。测试特征重要性的方法有很多,但是我们将使用XGBoost,因为它在分类和回归问题中都给出了最好的结果之一。

    由于特征数据集非常大,出于演示目的,我们将仅使用技术指标。在真实特征重要性测试期间,所有选定的特征都证明有些重要,因此我们在训练GAN时不会排除任何内容。

    def get_feature_importance_data(data_income):
     data = data_income.copy()
     y = data['price']
     X = data.iloc[:, 1:]
     
     train_samples = int(X.shape[0] * 0.65)
     
     X_train = X.iloc[:train_samples]
     X_test = X.iloc[train_samples:]
     y_train = y.iloc[:train_samples]
     y_test = y.iloc[train_samples:]
     
     return (X_train, y_train), (X_test, y_test)
    # Get training and test data
    (X_train_FI, y_train_FI), (X_test_FI, y_test_FI) = get_feature_importance_data(dataset_TI_df)
    regressor = xgb.XGBRegressor(gamma=0.0,n_estimators=150,base_score=0.7,colsample_bytree=1,learning_rate=0.05)
    xgbModel = regressor.fit(X_train_FI,y_train_FI, 
     eval_set = [(X_train_FI, y_train_FI), (X_test_FI, y_test_FI)], 
     verbose=False)
    eval_result = regressor.evals_result()
    training_rounds = range(len(eval_result['validation_0']['rmse']))
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    让我们绘制训练和验证误差的曲线图,以便观察训练和检查过拟合(欠拟合)。

    plt.scatter(x=training_rounds,y=eval_result['validation_0']['rmse'],label='Training Error')
    plt.scatter(x=training_rounds,y=eval_result['validation_1']['rmse'],label='Validation Error')
    plt.xlabel('Iterations')
    plt.ylabel('RMSE')
    plt.title('Training Vs Validation Error')
    plt.legend()
    plt.show()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    fig = plt.figure(figsize=(8,8))
    plt.xticks(rotation='vertical')
    plt.bar([i for i in range(len(xgbModel.feature_importances_))], xgbModel.feature_importances_.tolist(), tick_label=X_test_FI.columns)
    plt.title('Figure 6: Feature importance of the technical indicators.')
    plt.show()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    毫不奇怪,MA7,MACD和BB是其中的重要特征。

    我遵循相同的逻辑来对整个数据集执行特征重要性 - 与仅少数几个特征相比,训练花费的时间更长,结果更难以阅读。

    2.8、使用Stacked Autoencoders提取高级特征

    在我们进入自动编码器之前,我们将探索激活函数。

    2.8.1、激活功函数- GELU(高斯误差)

    最近提出了GELU - Gaussian Error Linear Unites - link。在论文中,作者展示了使用ReLU作为激活的使用GELU的神经网络优于网络的几个实例。gelu也用于BERT,我们用于新闻情绪分析的NLP方法。

    我们将使用GELU作为自动编码器。

    注:下面的单元格展示了GELU数学背后的逻辑。它不是作为激活函数的实际实现。我必须在MXNet中实现GELU。如果您按照代码将act_type='relu'更改为act_type='gelu',那么它将不起作用,除非您更改MXNet的实现。对整个项目发出pull请求,以访问GELU的MXNet实现。

    def gelu(x):
     return 0.5 * x * (1 + math.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * math.pow(x, 3))))
    def relu(x):
     return max(x, 0)
    def lrelu(x):
     return max(0.01*x, x)
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    让我们来看看GELU、ReLU和LeakyReLU(最后一个主要用于GAN)。

    plt.figure(figsize=(15, 5))
    plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=.5, hspace=None)
    ranges_ = (-10, 3, .25)
    plt.subplot(1, 2, 1)
    plt.plot([i for i in np.arange(*ranges_)], [relu(i) for i in np.arange(*ranges_)], label='ReLU', marker='.')
    plt.plot([i for i in np.arange(*ranges_)], [gelu(i) for i in np.arange(*ranges_)], label='GELU')
    plt.hlines(0, -10, 3, colors='gray', linestyles='--', label='0')
    plt.title('Figure 7: GELU as an activation function for autoencoders')
    plt.ylabel('f(x) for GELU and ReLU')
    plt.xlabel('x')
    plt.legend()
    plt.subplot(1, 2, 2)
    plt.plot([i for i in np.arange(*ranges_)], [lrelu(i) for i in np.arange(*ranges_)], label='Leaky ReLU')
    plt.hlines(0, -10, 3, colors='gray', linestyles='--', label='0')
    plt.ylabel('f(x) for Leaky ReLU')
    plt.xlabel('x')
    plt.title('Figure 8: LeakyReLU')
    plt.legend()
    plt.show()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    好的,回到自动编码器,如下所示(图像只是原理图,它不代表实际的层数,units等)

    注意:通常,在自动编码器中编码器的数量==解码器的数量。但是,我们希望提取更高级别的特征(而不是创建相同的输入),因此我们可以跳过解码器中的最后一层。我们实现了这一点,在训练期间创建了具有相同层数的编码器和解码器。

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    batch_size = 64
    n_batches = VAE_data.shape[0]/batch_size
    VAE_data = VAE_data.values
    train_iter = mx.io.NDArrayIter(data={'data': VAE_data[:num_training_days,:-1]}, 
     label={'label': VAE_data[:num_training_days, -1]}, batch_size = batch_size)
    test_iter = mx.io.NDArrayIter(data={'data': VAE_data[num_training_days:,:-1]}, 
     label={'label': VAE_data[num_training_days:,-1]}, batch_size = batch_size)
    model_ctx = mx.cpu()
    class VAE(gluon.HybridBlock):
     def __init__(self, n_hidden=400, n_latent=2, n_layers=1, n_output=784, 
     batch_size=100, act_type='relu', **kwargs):
     self.soft_zero = 1e-10
     self.n_latent = n_latent
     self.batch_size = batch_size
     self.output = None
     self.mu = None
     super(VAE, self).__init__(**kwargs)
     
     with self.name_scope():
     self.encoder = nn.HybridSequential(prefix='encoder')
     
     for i in range(n_layers):
     self.encoder.add(nn.Dense(n_hidden, activation=act_type))
     self.encoder.add(nn.Dense(n_latent*2, activation=None))
     self.decoder = nn.HybridSequential(prefix='decoder')
     for i in range(n_layers):
     self.decoder.add(nn.Dense(n_hidden, activation=act_type))
     self.decoder.add(nn.Dense(n_output, activation='sigmoid'))
     def hybrid_forward(self, F, x):
     h = self.encoder(x)
     #print(h)
     mu_lv = F.split(h, axis=1, num_outputs=2)
     mu = mu_lv[0]
     lv = mu_lv[1]
     self.mu = mu
     eps = F.random_normal(loc=0, scale=1, shape=(self.batch_size, self.n_latent), ctx=model_ctx)
     z = mu + F.exp(0.5*lv)*eps
     y = self.decoder(z)
     self.output = y
     KL = 0.5*F.sum(1+lv-mu*mu-F.exp(lv),axis=1)
     logloss = F.sum(x*F.log(y+self.soft_zero)+ (1-x)*F.log(1-y+self.soft_zero), axis=1)
     loss = -logloss-KL
     return loss
    n_hidden=400 # neurons in each layer
    n_latent=2 
    n_layers=3 # num of dense layers in encoder and decoder respectively
    n_output=VAE_data.shape[1]-1 
    net = VAE(n_hidden=n_hidden, n_latent=n_latent, n_layers=n_layers, n_output=n_output, batch_size=batch_size, act_type='gelu')
    net.collect_params().initialize(mx.init.Xavier(), ctx=mx.cpu())
    net.hybridize()
    trainer = gluon.Trainer(net.collect_params(), 'adam', {'learning_rate': .01})
    print(net)
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    所以我们在编码器和解码器中都有3层(每个层有400个神经元)。

    n_epoch = 150
    print_period = n_epoch // 10
    start = time.time()
    training_loss = []
    validation_loss = []
    for epoch in range(n_epoch):
     epoch_loss = 0
     epoch_val_loss = 0
     train_iter.reset()
     test_iter.reset()
     n_batch_train = 0
     for batch in train_iter:
     n_batch_train +=1
     data = batch.data[0].as_in_context(mx.cpu())
     with autograd.record():
     loss = net(data)
     loss.backward()
     trainer.step(data.shape[0])
     epoch_loss += nd.mean(loss).asscalar()
     n_batch_val = 0
     for batch in test_iter:
     n_batch_val +=1
     data = batch.data[0].as_in_context(mx.cpu())
     loss = net(data)
     epoch_val_loss += nd.mean(loss).asscalar()
     epoch_loss /= n_batch_train
     epoch_val_loss /= n_batch_val
     training_loss.append(epoch_loss)
     validation_loss.append(epoch_val_loss)
     """if epoch % max(print_period, 1) == 0:
     print('Epoch {}, Training loss {:.2f}, Validation loss {:.2f}'.
     format(epoch, epoch_loss, epoch_val_loss))"""
    end = time.time()
    print('Training completed in {} seconds.'.format(int(end-start)))
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    Training completed in 62 seconds.

    dataset_total_df['Date'] = dataset_ex_df['Date']
    vae_added_df = mx.nd.array(dataset_total_df.iloc[:, :-1].values)
    print('The shape of the newly created (from the autoencoder) features is {}.'.format(vae_added_df.shape))
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    The shape of the newly created (from the autoencoder) features is (2265, 112).

    我们从自动编码器中创建了112个更多特征。由于我们只想拥有高级特征(整体模式),我们将使用主成分分析(PCA)在新创建的112个特征上创建特征投资组合。这将减少数据的维度(列数)。Eigen组合的描述能力将与原始的112个特征相同。

    注意再一次,这纯粹是实验性的。我并非100%确定描述的逻辑将成立。作为人工智能和深度学习的其他一切,这是艺术和需要实验。

    2.8.2、主成分分析的特征组合

    # We want the PCA to create the new components to explain 80% of the variance
    pca = PCA(n_components=.8)
    x_pca = StandardScaler().fit_transform(vae_added_df)
    principalComponents = pca.fit_transform(x_pca)
    principalComponents.n_components_
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    84

    所以,为了解释80%的方差我们需要84个(112个)特征。这仍然是一个很大的问题。因此,目前我们不包括自动编码器创建的特征。我将致力于创建autoencoder架构,在该架构中,我们从中间层(而不是最后一层)获得输出,并使用30个神经元将其连接到另一个Dense 层。因此,我们将1)只提取更高级别的特征,2)提供更少的列数。

    3.生成性对抗网络(GAN)

    利用深度学习来预测股票价格变动(长文,建议收藏)

    GAN的体系结构

    GAN如何运作?

    如前所述,本文的目的不是详细解释深度学习背后的数学,而是展示其应用。当然,在我看来,彻底和非常坚实的理解从基础到最小的细节,是极其必要的。因此,我们将尝试平衡并给出一个关于GAN如何工作的高级概述,以便读者充分理解使用GAN预测股价走势背后的原理。

    GAN网络由两个模型组成 - Generator(G)和Discriminator (D)。训练GAN的步骤如下:

    1. 使用随机数据(噪声表示为z),Generator试图“生成”与真实数据无法区分或非常接近的数据。它的目的是学习真实数据的分布。
    2. 将随机、真实或生成的数据拟合到Discriminator 中,Discriminator 作为分类器,试图了解数据是来自Generator还是真实数据。
    3. 然后,G和D的损失被组合并通过Generator传播回来。因此,Generator的损失取决于GeneratorDiscriminator 。这是帮助Generator了解真实数据分布的步骤。如果Generator在生成真实数据(具有相同分布)方面做得不好,则Discriminator 的工作将很容易区分生成与实际数据集。因此,Discriminator 的损失将非常小。小的Discriminator 损失将导致更大的Generator损耗(参见下面的等式 L(D,G))。这使得创建Discriminator 有点棘手,因为Discriminator 太好会导致巨大的Generator损失,使得Generator无法学习。
    4. 该过程一直持续到Discriminator无法再将生成数据与实际数据区分开来。

    当组合在一起时,D和G作为一种playing minmax游戏(Generator试图欺骗Discriminator ,使其增加假例子的概率,即最小化z〜pz(z)[log(1-D(G) z)))]。Discriminator 想要通过最大化x~pr(x)[logD(x)]来分离来自发生器D(G(z))的数据。但是,具有分离的损失函数,它是不清楚两者如何汇合在一起(这就是为什么我们使用普通GAN的一些进步,例如Wasserstein GAN)。总的来说,组合损失函数看起来像:

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    3.1、为什么GAN用于股市预测

    生成对抗网络(GAN)最近主要用于创建逼真的图像,绘画和视频剪辑。在我们的案例中,没有多少GAN用于预测时间序列数据。然而,主要想法应该是相同的 - 我们希望预测未来的股票变动。在未来,GS股票的模式和行为应该或多或少相同(除非它开始以完全不同的方式运作,或者经济急剧变化)。因此,我们希望“生成”未来的数据,这些数据将具有与我们已有的相似(当然不完全相同)的分布 - 历史交易数据。所以,从理论上讲,它应该有效。

    在我们的例子中,我们将使用LSTM作为时间序列生成器,并使用CNN作为Discriminator

    3.2、Metropolis-Hastings GAN和Wasserstein GAN

    I. Metropolis-Hastings GAN

    Uber的工程团队最近对传统GAN进行了改进,称为Metropolis-Hastings GAN(MHGAN)。优步的方法背后的想法(正如他们所述)与谷歌和加州大学伯克利分校创建的另一种方法有点类似,称为DRS。基本上,当我们训练GAN时,我们使用Discriminator(D)的唯一目的是更好地训练Generator(G)。通常,在训练GAN之后我们不再使用D. 然而,MHGAN和DRS尝试使用D来选择由G生成的接近实际数据分布的样本(MHGAN之间的微小差异是使用马尔可夫链蒙特卡罗(MCMC)进行采样)。

    MHGAN采用从G生成的K个样本(从独立的噪声输入到下图中的G-z0到zK)。然后它依次运行K个输出(x'0到x'K)并遵循接受规则(从Discriminator创建)决定是接受当前样本还是保留最后接受的样本。最后保留的输出是被认为是G的实际输出的输出。

    注意:MHGAN最初由优步在pytorch中实现。我只把它转移到MXNet / Gluon。

    利用深度学习来预测股票价格变动(长文,建议收藏)

    图10:MHGAN的视觉表示

    II。Wasserstein GAN

    训练GAN非常困难。模型可能永远不会收敛,模式崩溃很容易发生。我们将使用名为Wasserstein GAN - WGAN的GAN修改。

    最值得注意的要点是:

    • 我们知道GAN背后的主要目标是让Generator开始将随机噪声转换为我们想要模仿的某些给定数据。因此,在GAN中,比较两个分布之间的相似性的想法是非常必要的。这两个最广泛使用的指标是:
    • KL散度(Kullback-Leibler) - DKL(p‖q)=∫xp(x)logp(x)q(x)dx。当p(x)等于q(x)时,DKL为零,
    • JS Divergence(Jensen-Shannon)。JS散度以0和1为界,与KL散度不同,它是对称的,更平滑。当损失从KL转移到JS散度时,GAN训练取得了显著的成功。
    • WGAN使用 Wasserstein距离,W(PR,PG)=1Ksup‖f‖L≤Kx~pr[F(X)] - x~pg[F(X)](其中supsup代表supremum),作为损失函数。与KL和JS的差异相比,Wasserstein度量提供了一个平滑的度量(没有突然的跳跃)。这使得它更适合在梯度下降期间创建稳定的学习过程。
    • 此外,与KL和JS相比,Wasserstein距离几乎无处不在。众所周知,在反向传播过程中,我们会区分损失函数以创建梯度,从而更新权重。因此,具有可微分的损失函数是非常重要的。

    3.4、Generator - One layer RNN

    3.4.1、LSTM或GRU

    如前所述,Generator是LSTM网络的一种循环神经网络(RNN)。RNN用于时间序列数据,因为它们跟踪所有先前的数据点,并且可以捕获随时间发展的模式。由于它们的性质,RNN很多时候都会受到梯度消失的影响 - 也就是说,在训练期间权重变化的变化变得如此之小,以至于它们不会改变,使得网络无法收敛到最小的损失(相反的问题也可以有时会观察到 - 当梯度变得太大时。这称为梯度爆炸,但解决方法很简单。两个方法解决了这个问题 - 门控循环单元(GRU)和长短期记忆(LSTM)。两者之间最大的区别是:1)GRU有2个门(update 和reset),LSTM有4个(update, input, forget, 和output),2)LSTM保持内部存储器状态,而GRU没有, 3)LSTM在输出门之前应用非线性(sigmoid),GRU不应用。

    在大多数情况下,LSTM和GRU在准确性方面给出了类似的结果,但GRU的计算密集程度要低得多,因为GRU的可训练参数更少。然而,LSTM使用得更多。

    严格地说,LSTM cell (gates)背后的数学是:

    利用深度学习来预测股票价格变动(长文,建议收藏)

    LSTM cell背后的数学

    其中⊙是一个逐元素的乘法运算符,并且,对于所有x = [x1,x2,...,xk]⊤∈R^ k,激活函数:

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    3.4.2LSTM架构

    LSTM架构非常简单 - LSTM一层有112个输入单元(因为我们在数据集中有112个特征)和500个隐藏单元,Dense层有1个输出 - 每天的价格。初始化器是Xavier,我们将使用L1损失(这是L1正则化的平均绝对误差损失)。

    注意 - 在Python代码中,您可以看到我们使用Adam(使用learning rate.01)作为优化器。

    gan_num_features = dataset_total_df.shape[1]
    sequence_length = 17
    class RNNModel(gluon.Block):
     def __init__(self, num_embed, num_hidden, num_layers, bidirectional=False, 
     sequence_length=sequence_length, **kwargs):
     super(RNNModel, self).__init__(**kwargs)
     self.num_hidden = num_hidden
     with self.name_scope():
     self.rnn = rnn.LSTM(num_hidden, num_layers, input_size=num_embed, 
     bidirectional=bidirectional, layout='TNC')
     
     self.decoder = nn.Dense(1, in_units=num_hidden)
     
     def forward(self, inputs, hidden):
     output, hidden = self.rnn(inputs, hidden)
     decoded = self.decoder(output.reshape((-1, self.num_hidden)))
     return decoded, hidden
     
     def begin_state(self, *args, **kwargs):
     return self.rnn.begin_state(*args, **kwargs)
     
    lstm_model = RNNModel(num_embed=gan_num_features, num_hidden=500, num_layers=1)
    lstm_model.collect_params().initialize(mx.init.Xavier(), ctx=mx.cpu())
    trainer = gluon.Trainer(lstm_model.collect_params(), 'adam', {'learning_rate': .01})
    loss = gluon.loss.L1Loss()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    我们将在LSTM层中使用500个神经元并使用Xavier初始化。为了正则化,我们将使用L1。让我们来看看LSTMMXNet打印的内容。

    print(lstm_model)
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    正如我们所看到的,LSTM的输入是112个特征(dataset_total_df.shape[1])然后进入LSTM层中的500个神经元,然后转换为单个输出 - 股票价格值。

    LSTM背后的逻辑是:我们取17天(sequence_length)的数据(同样,这些数据是GS股票每天的股价+当天的所有其他特性——相关资产、情绪等),并尝试预测第18天。

    3.4.3、学习率调度程序

    最重要的超参数之一是学习率。在训练神经网络时,为几乎所有优化器(例如SGD,Adam或RMSProp)设置学习速率至关重要,因为它既能控制收敛速度,又能控制网络的最终性能。最简单的学习率策略之一是在整个训练过程中具有固定的学习率。选择较小的学习速率可以使优化器找到好的解决方案,但这是以限制初始收敛速度为代价的。随着时间的推移改变学习率可以克服这种权衡。

    让我们绘制我们将在每个epoch使用的学习率。

    class TriangularSchedule():
     def __init__(self, min_lr, max_lr, cycle_length, inc_fraction=0.5): 
     self.min_lr = min_lr
     self.max_lr = max_lr
     self.cycle_length = cycle_length
     self.inc_fraction = inc_fraction
     
     def __call__(self, iteration):
     if iteration <= self.cycle_length*self.inc_fraction:
     unit_cycle = iteration * 1 / (self.cycle_length * self.inc_fraction)
     elif iteration <= self.cycle_length:
     unit_cycle = (self.cycle_length - iteration) * 1 / (self.cycle_length * (1 - self.inc_fraction))
     else:
     unit_cycle = 0
     adjusted_cycle = (unit_cycle * (self.max_lr - self.min_lr)) + self.min_lr
     return adjusted_cycle
    class CyclicalSchedule():
     def __init__(self, schedule_class, cycle_length, cycle_length_decay=1, cycle_magnitude_decay=1, **kwargs):
     self.schedule_class = schedule_class
     self.length = cycle_length
     self.length_decay = cycle_length_decay
     self.magnitude_decay = cycle_magnitude_decay
     self.kwargs = kwargs
     
     def __call__(self, iteration):
     cycle_idx = 0
     cycle_length = self.length
     idx = self.length
     while idx <= iteration:
     cycle_length = math.ceil(cycle_length * self.length_decay)
     cycle_idx += 1
     idx += cycle_length
     cycle_offset = iteration - idx + cycle_length
     
     schedule = self.schedule_class(cycle_length=cycle_length, **self.kwargs)
     return schedule(cycle_offset) * self.magnitude_decay**cycle_idx
    schedule = CyclicalSchedule(TriangularSchedule, min_lr=0.5, max_lr=2, cycle_length=500)
    iterations=1500
    plt.plot([i+1 for i in range(iterations)],[schedule(i) for i in range(iterations)])
    plt.title('Learning rate for each epoch')
    plt.xlabel("Epoch")
    plt.ylabel("Learning Rate")
    plt.show()
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    3.4.4、如何防止过度拟合和偏差 - 方差权衡

    有很多特征和神经网络,我们需要确保我们避免过拟合,并注意总损失。

    我们使用几种技术来防止过度拟合(不仅在LSTM中,并且在CNN和自动编码器中):

    • 确保数据质量。我们已经进行了统计检查,确保数据不受多重共线性或序列自相关的影响。进一步,我们对每个特征执行了特征重要性检查。最后,利用一些有关股票市场运作机制的领域知识进行了初始特征选择(例如,选择相关资产、技术指标等)。
    • 正规化(或权重惩罚)。两种最广泛使用的正则化技术是LASSO(L1)和Ridge(L2)。L1增加了平均绝对误差,L2增加了平均误差。在没有涉及太多数学细节的情况下,基本区别是:LASSO回归(L1)同时进行变量选择和参数收缩,而Ridge归仅进行参数收缩并最终包括模型中的所有系数。在存在相关变量的情况下,岭回归可能是首选。此外,岭回归在最小二乘估计具有较高方差的情况下效果最佳。因此,这取决于我们的模型目标。两种类型的正则化的影响是完全不同的。虽然它们都会对大权重进行惩罚,但L1正则化会导致零不可微函数。L2正则化有利于较小的权重,但L1正则化有利于权重变为零。所以,使用L1正则化,您可以得到一个稀疏模型 - 一个参数较少的模型。在这两种情况下,L1和L2正则化模型的参数“收缩”,但在L1正则化的情况下,收缩直接影响模型的复杂性(参数的数量)。
    • Dropout。Dropout层随机删除隐藏图层中的节点。
    • ense-sparse-dense training
    • Early stopping.

    构建复杂神经网络时的另一个重要考虑因素是偏差 - 方差权衡。基本上,我们在训练网络时得到的误差是偏差,方差和不可减少误差的函数 - σ(由噪声和随机性引起的误差)。权衡的最简单公式是:Error=bias^2+variance+σ.

    • 偏见。偏差衡量训练的(训练数据集)算法在看不见的数据上的表现。高偏差(欠拟合)意味着模型不能很好地处理看不见的数据。
    • 方差。方差衡量模型对数据集变化的敏感性。高度差异是过度拟合。

    3.5、Discriminator

    为什么CNN作为Discriminator ?

    我们通常将CNN用于与图像相关的工作(分类,上下文提取等)。例如,在狗的图像中,第一个卷积层将检测边缘,第二个将开始检测圆圈,第三个将检测到鼻子。在我们的例子中,数据点形成小趋势,小趋势形成更大,趋势形成模式。CNN检测特征的能力可用于提取有关GS股票价格变动模式的信息。

    使用CNN的另一个原因是CNN在空间数据上运行良好 - 这意味着彼此更接近的数据点彼此之间的相关性更高,而不是数据点。对于时间序列数据,这应该适用。在我们的例子中,每个数据点(对于每个特征)是连续的每一天。很自然地假设彼此距离越近,彼此之间的相关性就越大。需要考虑的一件事(虽然没有涉及这项工作)是季节性以及它如何改变(如果有的话)CNN的工作。

    3.5.1。CNN架构

    利用深度学习来预测股票价格变动(长文,建议收藏)

    建议的CNN模型的架构

    GAN中CNN的Python代码是这样的:

    num_fc = 512
    # ... other parts of the GAN
    cnn_net = gluon.nn.Sequential()
    with net.name_scope():
     
     # Add the 1D Convolutional layers
     cnn_net.add(gluon.nn.Conv1D(32, kernel_size=5, strides=2))
     cnn_net.add(nn.LeakyReLU(0.01))
     cnn_net.add(gluon.nn.Conv1D(64, kernel_size=5, strides=2))
     cnn_net.add(nn.LeakyReLU(0.01))
     cnn_net.add(nn.BatchNorm())
     cnn_net.add(gluon.nn.Conv1D(128, kernel_size=5, strides=2))
     cnn_net.add(nn.LeakyReLU(0.01))
     cnn_net.add(nn.BatchNorm())
     
     # Add the two Fully Connected layers
     cnn_net.add(nn.Dense(220, use_bias=False), nn.BatchNorm(), nn.LeakyReLU(0.01))
     cnn_net.add(nn.Dense(220, use_bias=False), nn.Activation(activation='relu'))
     cnn_net.add(nn.Dense(1))
     
    # ... other parts of the GAN
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    让我们打印CNN。

    print(cnn_net)
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    3.6、超参数

    我们将跟踪和优化的超参数是:

    • batch_size :LSTM和CNN的批量大小
    • cnn_lr:CNN的学习率
    • strides:CNN中的strides
    • lrelu_alpha:GAN中LeakyReLU的alpha
    • batchnorm_momentum:momentum for the batch normalisation in the CNN
    • padding:CNN中的padding
    • kernel_size':1:CNN中的核大小
    • dropout:LSTM中的dropout
    • filters:初始filters数量

    我们将训练超过200个epochs。

    4.超参数优化

    在200个epochs的GAN训练之后,它将记录MAE(这是LSTM中的误差函数,GG)并将其作为奖励值传递给强化学习,该学习决定是否改变继续训练的超参数。

    如果RL决定它将更新超参数,它将调用贝叶斯优化(下面讨论)库,它将提供下一个最佳预期的超级参数集

    4.1、超参数优化的强化学习

    为什么我们在超参数优化中使用强化学习?股市一直在变化。即使我们设法训练我们的GAN和LSTM以创建非常准确的结果,结果可能仅在一段时间内有效。意思是,我们需要不断优化整个过程。为了优化流程,我们可以:

    • 添加或删除特征(例如添加可能相关的新股票或货币)
    • 改善我们的深度学习模式。改进机器学习模型的最重要方法之一是通过超参数。一旦找到了一组超参数,我们就需要决定何时更改它们以及何时使用已知的集合(探索与利用)。此外,股市代表一个连续的空间,取决于数百万参数。

    4.1.1、强化学习理论

    在不解释RL的基础知识的情况下,我们将详细介绍我们在此实现的具体方法。我们将使用model-free RL算法,原因很明显我们不了解整个环境,因此没有明确的环境工作模型 - 如果我们不需要预测股票价格变动 - 它们只会按照该模型。我们将使用model-free RL的两个细分 - 策略优化和Q学习。

    • Q-learning - 在Q-learning中我们学习从一个给定的状态采取动作的价值。Q值是采取动作后的预期回报。我们将使用Rainbow,它是七种Q学习算法的组合。
    • 策略优化 - 在策略优化中,我们学习从给定状态采取的动作。(如果我们使用像Actor / Critic这样的方法),我们也会学习处于给定状态的值。我们将使用近端策略优化。

    构建RL算法的一个关键方面是准确设置奖励。它必须捕获环境的所有方面以及代理与环境的交互。我们将奖励R定义为:

    Reward=2∗lossG+lossD+accuracyG,

    其中lossG,accuracyG和lossD分别是Generator的损失和准确性,以及Discriminator的损失。环境是GAN和LSTM训练的结果。不同代理可以采取的动作是如何更改GAN的D和G网络的超参数。

    4.1.1.1、Rainbow

    Rainbow(link)是一种基于Q学习的非策略深度强化学习算法,它将七种算法结合在一起:

    • DQN。DQN是Q学习算法的扩展,其使用神经网络来表示Q值。与监督(深度)学习类似,在DQN中,我们训练神经网络并尝试最小化损失函数。我们通过随机抽样转换(状态、动作、奖励)来训练网络。例如,这些层不仅可以是全连接层,而且可以是卷积层。
    • Double Q学习。Double QL处理Q学习中的一个大问题,即高估偏差。
    • Prioritized replay。在vanilla DQN中,所有转换都存储在replay 缓冲区中,并均匀地对此缓冲区进行采样。然而,并非所有transitions在学习阶段都同样有益(这也使得学习效率低,因为需要更多的episodes )。Prioritized experience replay 不是均匀采样,而是使用分布,该分布为先前迭代中具有较高Q损失的样本提供更高的概率。
    • Dueling networksDueling networks通过使用两个单独的流(即具有两个不同的微型神经网络)来稍微改变Q学习架构。一个流用于值,一个用于优势。它们都共享一个卷积编码器。棘手的部分是流的合并 - 它使用了一个特殊的聚合器(Wang et al.2016)。
    • Multi-step learningMulti-step learning背后的巨大差异在于它使用N步返回计算Q值(不仅是下一步的返回),这自然应该更准确。
    • 分布式RL。Q学习使用平均估计的Q值作为目标值。但是,在许多情况下,Q值在不同情况下可能不同。分布式RL可以直接学习(或近似)Q值的分布,而不是对它们求平均值。再次,数学比这复杂得多,但对我们来说,好处是Q值的更准确的采样。
    • Noisy Nets。基本DQN实现了一个简单的ε-贪婪机制来进行探索。这种探索方法有时效率低下。Noisy Nets解决这个问题的方法是添加一个有噪声的线性层。随着时间的推移,网络将学习如何忽略噪声(添加为嘈杂的流)。但是这种学习在空间的不同部分以不同的速度进行,允许进行状态探索。

    4.1.1.2、PPO

    近端策略优化(PPO)是一种无策略优化模型的强化学习。实现其他算法要简单得多,效果非常好。

    我们为什么要使用PPO?PPO的一个优点是它直接学习策略,而不是间接地通过值(Q学习使用Q值来学习策略的方式)。它可以在连续动作空间中很好地工作,这在我们的使用案例中是合适的,并且可以(通过平均值和标准偏差)学习分布概率(如果将softmax作为输出添加)。

    政策梯度方法的问题在于它们对步长选择极其敏感 - 如果它很小,则进度需要太长时间(很可能主要是由于需要二阶导数矩阵); 如果它很大,会有很多噪音会显著降低性能。由于政策的变化(以及奖励和观察变化的分布),输入数据是非平稳的。与监督学习相比,选择不当的步骤可能会更具破坏性,因为它会影响下次访问的整个分布。PPO可以解决这些问题。更重要的是,与其他一些方法相比,PPO:

    • 例如,与ACER(它需要额外的代码来保持策略外相关性和replay 缓冲区)或TRPO(它对代理目标函数施加了约束,即新旧策略之间的KL差异)相比,前者要简单得多。这个约束用于控制过多更改的策略——这可能会造成不稳定。PPO减少了计算(由约束)利用 clipped 之间([1 -1 +])替代目标函数和修改目标函数用惩罚有太大的更新。
    • 与TRPO相比,它与在值和策略函数或辅助损失之间共享参数的算法兼容(尽管PPO也具有信任区域PO的增益)。

    注意:出于练习的目的,我们不会过多地研究和优化RL方法,PPO和其他方法。相反,我们将采用可用的方法,并尝试适应我们的GAN,LSTM和CNN模型的超参数优化过程。我们将重用和自定义的Python代码由OpenAI创建,可在此处获得(https://github.com/openai/baselines)。

    4.1.2、进一步加强学习的工作

    进一步探索强化学习的一些想法:

    • 我接下来要介绍的第一件事是使用增强随机搜索(https://arxiv.org/pdf/1803.07055.pdf)作为替代算法。该算法的作者(在UC,Berkeley之外)已经设法获得与其他最先进的方法(如PPO)类似的奖励结果,但平均快15倍。
    • 选择奖励函数非常重要。
    • 使用好奇心作为探索政策。
    • 根据伯克利的AI研究团队(BAIR)提出的建立多代理体系结构 - 链接(https://bair.berkeley.edu/blog/2018/12/12/rllib/)。

    4.2、贝叶斯优化

    我们将使用贝叶斯优化来代替网格搜索,这可能需要花费大量时间来找到超参数的最佳组合。我们将使用的库已经实现 - 链接(https://github.com/fmfn/BayesianOptimization)。

    4.2.1、高斯过程

    # Initialize the optimizer
    from bayes_opt import BayesianOptimization
    from bayes_opt import UtilityFunction
    utility = UtilityFunction(kind="ucb", kappa=2.5, xi=0.0)
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    4.2.2、高斯过程结果

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    5.结果

    最后,当在过程的不同阶段之后将看不见的(测试)数据用作输入时,我们将比较LSTM的输出。

    1. 在第一个epoch之后绘制图像。
    from utils import plot_prediction
    plot_prediction('Predicted and Real price - after first epoch.')
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    2.绘制50个epochs后的图像。

    plot_prediction('Predicted and Real price - after first 50 epochs.')
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    plot_prediction('Predicted and Real price - after first 200 epochs.')
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

     

    RL运行en episodes(我们将eposide定义为200个epochs上的一个完整GAN训练)。

    plot_prediction('Final result.')
    

    利用深度学习来预测股票价格变动(长文,建议收藏)

    展开全文
  • 博主路一瓢的博文:Tensorflow实例:利用LSTM预测股票每日最高价(一)Tensorflow实例:利用LSTM预测股票每日最高价(二)在以上两篇博文中,博主介绍了RNN和LSTM,并使用LSTM实现了股票预测的例子,让人受益匪浅。...

    博主路一瓢的博文:

    Tensorflow实例:利用LSTM预测股票每日最高价(一)

    Tensorflow实例:利用LSTM预测股票每日最高价(二)

    在以上两篇博文中,博主介绍了RNN和LSTM,并使用LSTM实现了股票预测的例子,让人受益匪浅。

    但博主提供的代码有一些bug,无法直接运行,经过本人的多番调试,已能完整运行,希望能在深度学习的路上给大家带来一些帮助。


    以上为原博文

    之前的代码结构有些混乱,深度学习框架也有了长足的进步,遂重写了相关代码,使其具备如下特性:

    • 更简洁更模块化
    • 支持pytorch,keras和tensorflow三个主流深度学习框架
    • 参数、模型、框架可高度定制化修改
    • 支持增量式训练
    • 支持同时预测多个指标,预测未来任意天数
    • 支持训练过程的loss可视化和日志记录
    • 更多特性,详解GitHub代码:stock_predict_with_LSTM

    代码在更新之后,很多之前评论区的问题可以得到快速的解决

    如果还有问题,可以联系vx:hichenway,会在非工作时间解答,谢谢理解

    下图是基于pytorch框架,同时预测未来一天的最高价和最低价的结果:
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 来源:AISHWARYA SINGH, 2018年10月25日;翻译:赵雪尧;校对:车前子本文约8000字,建议阅读15+分钟。本文介绍了如何运用深度学习预测股票市场。...
        

    来源:AISHWARYA SINGH, 2018年10月25日;翻译:赵雪尧;校对:车前子

    本文约8000字,建议阅读15+分钟。

    本文介绍了如何运用深度学习法预测股票市场。

    简介

    预测股市将如何变化历来是最困难的事情之一。这个预测行为中包含着如此之多的因素—包括物理或心理因素、理性或者不理性行为因素等等。所有这些因素结合在一起,使得股价波动剧烈,很难准确预测。

     

    使用机器学习可能改变游戏规则吗?机器学习技术使用最新的组织公告、季度收益等作为特征,有潜力挖掘出我们以前没有见过的模式和见解,并可用于准确无误的预测。


    640?wx_fmt=png

    在本文中,我们将研究上市公司股价的历史数据。我们将结合机器学习算法来预测这家公司的未来股价,从平均和线性回归这样的简单算法开始,然后转向像Auto ARIMA和LSTM这样的高级模型。

     

    本文背后的核心思想是展示这些算法是如何实现的,因此我只会简单描述该技术并提供相关参考链接,以便在必要时对这些概念进行复习。如果您是时间序列领域的新手,我建议您先阅读以下文章:

    • 创建时间序列预测的初学者综合指南

    • 时间序列建模的完整教程


    目录

    1、 问题理解

    2、 移动平均

    3、 线性回归

    4、 K-近邻

    5、 自动ARIMA

    6、 先知(Prophet)

    7、 长短时记忆网络(LSTM)

     

    1、问题理解

    我们将很快深入本文的实现部分,但首先重要的是确定我们要解决的问题。一般来说,股票市场分析分为两个部分——基本面分析和技术分析。

    • 基本面分析是根据公司目前的经营环境和财务状况,对公司未来的盈利能力进行分析。

    • 技术分析包括阅读图表和使用统计数字来确定股票市场的趋势。

    您可能已经猜到,我们的重点将放在技术分析部分。我们将使用来自Quandl的数据集(您可以在这里找到各种股票的历史数据),这个项目中,我使用了“塔塔全球饮料”的数据。是时候开始了!

    首先让我们加载数据集,定义问题的目标变量:


    #import packages

    import pandas as pd

    import numpy as np

     

    #to plot within notebook

    import matplotlib.pyplot as plt

    %matplotlib inline

     

    #setting figure size

    from matplotlib.pylab import rcParams

    rcParams['figure.figsize'] = 20,10

     

    #for normalizing data

    from sklearn.preprocessing import MinMaxScaler

    scaler = MinMaxScaler(feature_range=(0, 1))

     

    #read the file

    df = pd.read_csv('NSE-TATAGLOBAL(1).csv')

     

    #print the head

    df.head()


    640?wx_fmt=png

    数据集中有多个变量——日期(date)、开盘价(open)、最高价(high)、最低价(low)、最后交易价(last)、收盘价(close)、总交易额(total_trade_quantity)和营业额(turnover)。

     

    • 开盘价和收盘价代表股票在某一天交易的起始价和最终价。

    • 最高价、最低价和最后交易价表示当天股票的最高价、最低价和最后交易价格。

    • 交易总量是指当天买卖的股票数量,而营业额(Lacs)是指某一特定公司在某一特定日期的营业额。

    要注意的另一点是,市场在周末和公共假期休市。注意上表缺失了一些日期值——2/10/2018、6/10/2018、7/10/2018。其中2号是国庆节,6号和7号是周末。

     

    损益的计算通常由股票当日的收盘价决定,因此我们将收盘价作为目标变量。让我们画出目标变量来理解它在我们的数据集中的分布:


    #setting index as date

    df['Date'] = pd.to_datetime(df.Date,format='%Y-%m-%d')

    df.index = df['Date']

     

    #plot

    plt.figure(figsize=(16,8))

    plt.plot(df['Close'], label='Close Price history')


    640?wx_fmt=png


    在接下来的部分中,我们将探索这些变量,并使用不同的技术来预测股票的每日收盘价。

     

    2、移动平均

    简介

    “平均数”是我们日常生活中最常用的统计量之一。例如,计算平均分数来确定整体表现,或者根据过去几天的平均温度来了解今天的温度——这些都是我们经常做的日常工作。因此,使用这个方法开始用数据集进行预测是个不错的选择。

     

    我们利用一组先前观测值的平均值作为每天的预期收盘价。我们将使用移动平均法,而不是使用简单的平均值,移动平均法使用最近的一组数据计算预测值。换句话说,对于后续的每个新的时间,在考虑预测值时,将从集合中删除最早的观测值,并加入上一个观测值。下面是一个简单的图,它将帮助您更清楚地理解这一点。

    640?wx_fmt=png


    我们将在数据集上使用这种技术。第一步是创建一个只包含日期和收盘价列的数据框,然后将其拆分为训练集和验证集来验证我们的预测。

    实现

    #creating dataframe with date and the target variable

    data = df.sort_index(ascending=True, axis=0)

    new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close'])

     

    for i in range(0,len(data)):

         new_data['Date'][i] = data['Date'][i]

         new_data['Close'][i] = data['Close'][i]


    在将数据分割为训练和验证时,我们不能使用随机分割,因为这会破坏时间顺序。所以这里我将去年的数据作为验证集,将之前4年的数据作为训练集。


    #splitting into train and validation

    train = new_data[:987]

    valid = new_data[987:]

     

    new_data.shape, train.shape, valid.shape

    ((1235, 2), (987, 2), (248, 2))

     

    train['Date'].min(), train['Date'].max(), valid['Date'].min(), valid['Date'].max()

     

    (Timestamp('2013-10-08 00:00:00'),

    Timestamp('2017-10-06 00:00:00'),

    Timestamp('2017-10-09 00:00:00'),

    Timestamp('2018-10-08 00:00:00'))


    下一步是为验证集创建预测值,并使用真实值来检查RMSE误差。


    #make predictions

    preds = []

    for i in range(0,248):

        a = train['Close'][len(train)-248+i:].sum() + sum(preds)

        b = a/248

        preds.append(b)


    结果

    #calculate rmse

    rms=np.sqrt(np.mean(np.power((np.array(valid['Close'])-preds),2)))

    rms

     

    104.51415465984348


    仅仅检查RMSE并不能帮助我们评估模型预测效果的。让我们通过做图得到更直观的理解。下面是预测值和实际值的曲线图。


    #plot

    valid['Predictions'] = 0

    valid['Predictions'] = preds

    plt.plot(train['Close'])

    plt.plot(valid[['Close', 'Predictions']])


    640?wx_fmt=png


    推论

    RMSE值接近105,但是结果不是很理想(从图中可以看出)。预测值与训练集的观测值的范围相同(开始有上升趋势,然后缓慢下降)。

     

    在下一节中,我们将使用两种常用的机器学习技术——线性回归和kNN,看看它们在我们的股票市场数据上表现如何。

     

    3、线性回归

    简介

    在这些数据上可以实现的最基本的机器学习算法是线性回归。线性回归模型生成一个确定自变量和因变量之间关系的方程。

     

    线性回归方程可以写成:


    640?wx_fmt=png

    在这里x1, x2, ....xn代表自变量,系数θ1,θ2,....θn代表权重。你可以参考下面的文章来更详细地学习线性回归:

    • 对于线性回归和Lasso回归的一个综合的初学者指南.


    我们的问题中,没有太多的自变量,只有日期。让我们使用时间(date)列提取特征,如- day, month, year, mon/fri等,然后拟合线性回归模型。


    实现

    我们将首先按升序对数据集进行排序,然后创建一个单独的数据集,这样创建的任何新特性都不会影响原始数据。


    #setting index as date values

    df['Date'] = pd.to_datetime(df.Date,format='%Y-%m-%d')

    df.index = df['Date']

     

    #sorting

    data = df.sort_index(ascending=True, axis=0)

     

    #creating a separate dataset

    new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close'])

     

    for i in range(0,len(data)):

        new_data['Date'][i] = data['Date'][i]

        new_data['Close'][i] = data['Close'][i]


    #create features

    from fastai.structured import  add_datepart

    add_datepart(new_data, 'Date')

    new_data.drop('Elapsed', axis=1, inplace=True)  #elapsed will be the time stamp


    这将创建以下特征:

    ‘Year’, ‘Month’, ‘Week’, ‘Day’, ‘Dayofweek’, ‘Dayofyear’, ‘Is_month_end’, ‘Is_month_start’, ‘Is_quarter_end’, ‘Is_quarter_start’,  ‘Is_year_end’, and  ‘Is_year_start’.


    注意:我使用了来自fastai库的add_datepart。如果您没有安装它,您可以简单地使用命令pip install fastai。您也可以使用python中的简单for循环来创建这些特性。我在下面展示了一个例子。

     

    除此之外,我们还可以添加自己的一组特性,我们认为这些特性与预测相关。例如,我的假设是,本周的头几天和最后几天对股票收盘价的影响可能远远超过其他日子。因此,我创建了一个特性来识别给定的一天是星期一/星期五还是星期二/星期三/星期四。这可以用以下几行代码来完成:


    new_data['mon_fri'] = 0

    for i in range(0,len(new_data)):

        if (new_data['Dayofweek'][i] == 0 or new_data['Dayofweek'][i] == 4):

            new_data['mon_fri'][i] = 1

        else:

            new_data['mon_fri'][i] = 0


    如果是星期日或星期五,列值将为1,否则为0。类似地,您可以创建多个特性。如果你对有助于预测股价的特征有一些想法,请在留言里分享。

     

    现在我们将把数据分成训练集和验证集来检查模型的性能。


    #split into train and validation

    train = new_data[:987]

    valid = new_data[987:]

     

    x_train = train.drop('Close', axis=1)

    y_train = train['Close']

    x_valid = valid.drop('Close', axis=1)

    y_valid = valid['Close']

     

    #implement linear regression

    from sklearn.linear_model import LinearRegression

    model = LinearRegression()

    model.fit(x_train,y_train)


    结果

    #make predictions and find the rmse

    preds = model.predict(x_valid)

    rms=np.sqrt(np.mean(np.power((np.array(y_valid)-np.array(preds)),2)))

    rms

     

    121.16291596523156

     

    RMSE值高于之前的方法,这清楚地表明线性回归的表现很差。让我们看看这个图,并理解为什么线性回归预测效果不是很好:


    #plot

    valid['Predictions'] = 0

    valid['Predictions'] = preds


    valid.index = new_data[987:].index

    train.index = new_data[:987].index

     

    plt.plot(train['Close'])

    plt.plot(valid[['Close', 'Predictions']])


    640?wx_fmt=png


    推论


    线性回归是一种简单的技术,很容易解释,但也有一些明显的缺点。使用回归算法的一个问题是,模型过度拟合了日期和月份。模型将考虑一个月前相同日期或一年前相同日期/月的值,而不是从预测的角度考虑以前的值。

     

    从上图可以看出,2016年1月和2017年1月,股价出现下跌。该模型预测2018年1月也将如此。线性回归技术可以很好地解决像大卖场销售这样的问题,在这些问题中,独立的特征对于确定目标值是有用的。


    4、k-近邻

    简介

    另一个有趣的ML算法是kNN (k近邻)。基于自变量,kNN可以发现新数据点与旧数据点之间的相似性。让我用一个简单的例子来解释这个问题。

     

    考虑11个人的身高和年龄。根据给定的特征(“年龄”和“身高”),下表可以用图形形式表示,如下图所示:

    640?wx_fmt=png


    为了确定ID #11的权重,kNN考虑该ID的最近邻居的权重。ID #11的权重被预测为其邻居的平均值。如果我们现在考虑三个邻居(k=3), ID#11的重量将是= (77+72+60)/3 = 69.66 kg。


    640?wx_fmt=png

    对于kNN的详细了解,可以参考以下文章:

    • k近邻介绍:简介

    • 对k近邻回归算法的实际介绍


    实现

    #importing libraries

    from sklearn import neighbors

    from sklearn.model_selection import GridSearchCV

    from sklearn.preprocessing import MinMaxScaler

    scaler = MinMaxScaler(feature_range=(0, 1))

    使用上一节中相同的训练和验证集:

     

    #scaling data

    x_train_scaled = scaler.fit_transform(x_train)

    x_train = pd.DataFrame(x_train_scaled)

    x_valid_scaled = scaler.fit_transform(x_valid)

    x_valid = pd.DataFrame(x_valid_scaled)

     

    #using gridsearch to find the best parameter

    params = {'n_neighbors':[2,3,4,5,6,7,8,9]}

    knn = neighbors.KNeighborsRegressor()


    model = GridSearchCV(knn, params, cv=5)

     

    #fit the model and make predictions

    model.fit(x_train,y_train)

    preds = model.predict(x_valid)


    结果

    #rmse

    rms=np.sqrt(np.mean(np.power((np.array(y_valid)-np.array(preds)),2)))

    rms

     

    115.17086550026721


    RMSE值并没有太大的差异,但是一个预测值和实际值的曲线图应该提供一个更清晰的理解。

     

    #plot

    valid['Predictions'] = 0

    valid['Predictions'] = preds

    plt.plot(valid[['Close', 'Predictions']])

    plt.plot(train['Close'])


    640?wx_fmt=png


    推论

    RMSE值与线性回归模型近似,图中呈现出相同的模式。与线性回归一样,kNN也发现了2018年1月的下降,因为这是过去几年的模式。我们可以有把握地说,回归算法在这个数据集上表现得并不好。

    让我们来看一些时间序列预测技术,看看它们在面对股价预测挑战时的表现。


    5、自动ARIMA

    简介

    ARIMA是一种非常流行的时间序列预测统计方法。ARIMA模型使用过去的值来预测未来的值。ARIMA中有三个重要参数:

    • p(用来预测下一个值的过去值)

    • q(用来预测未来值的过去预测误差)

    • d(差分的顺序)

    ARIMA的参数优化需要大量时间。因此我们将使用自动 ARIMA,自动选择误差最小的(p,q,d)最佳组合。要了解更多关于自动ARIMA的工作原理,请参阅本文:


    • 利用自动ARIMA建立高性能时间序列模型


    实现

    from pyramid.arima import auto_arima

     

    data = df.sort_index(ascending=True, axis=0)

     

    train = data[:987]

    valid = data[987:]

     

    training = train['Close']

    validation = valid['Close']

     

    model = auto_arima(training, start_p=1, start_q=1,max_p=3, max_q=3, m=12,start_P=0, seasonal=True,d=1, D=1, trace=True,error_action='ignore',suppress_warnings=True)

    model.fit(training)

     

    forecast = model.predict(n_periods=248)

    forecast = pd.DataFrame(forecast,index = valid.index,columns=['Prediction'])


    结果

    rms=np.sqrt(np.mean(np.power((np.array(valid['Close'])-np.array(forecast['Prediction'])),2)))

    rms

     

    44.954584993246954

     

     

    #plot

    plt.plot(train['Close'])

    plt.plot(valid['Close'])

    plt.plot(forecast['Prediction'])


    640?wx_fmt=png


    推论

    正如我们前面看到的,自动ARIMA模型使用过去的数据来理解时间序列中的模式。利用这些值,该模型捕捉到该系列中的增长趋势。虽然使用这种技术的预测比以前实现的机器学习模型的预测要好得多,但是这些预测仍然与实际值相距甚远。

     

    从图中可以明显看出,该模型在序列中捕捉到了一种趋势,但忽略了季节的影响。在下一节中,我们将使用一个同时考虑了序列的趋势和季节性的时间序列模型。该模型。

    6、先知(Prophet)

    简介

    有许多时间序列技术可以用在股票预测数据集上,但是大多数技术在拟合模型之前需要大量的数据预处理。Prophet(先知)由Facebook设计和开发,是一个时间序列预测库,不需要数据预处理,并且非常容易实现。先知的输入是一个带有两列的数据框:日期和目标(ds和y)。

     

    先知试图在过去的数据中捕捉季节性,并且在数据集很大的时候依然表现良好。这里有一篇有趣的文章,用一个简单和直观的方式解释了先知算法:

    • 使用Facebook的Prophet生成快速准确的时间序列预测

    实现

    #importing prophet

    from fbprophet import Prophet

     

    #creating dataframe

    new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close'])

     

    for i in range(0,len(data)):

        new_data['Date'][i] = data['Date'][i]

        new_data['Close'][i] = data['Close'][i]

     

    new_data['Date'] = pd.to_datetime(new_data.Date,format='%Y-%m-%d')

    new_data.index = new_data['Date']

     

    #preparing data

    new_data.rename(columns={'Close': 'y', 'Date': 'ds'}, inplace=True)

     

    #train and validation

    train = new_data[:987]

    valid = new_data[987:]

     

    #fit the model

    model = Prophet()

    model.fit(train)

     

    #predictions

    close_prices = model.make_future_dataframe(periods=len(valid))

    forecast = model.predict(close_prices)


    结果

    #rmse

    forecast_valid = forecast['yhat'][987:]

    rms=np.sqrt(np.mean(np.power((np.array(valid['y'])-np.array(forecast_valid)),2)))

    rms

     

    57.494461930575149

     

     

    #plot

    valid['Predictions'] = 0

    valid['Predictions'] = forecast_valid.values

     

    plt.plot(train['y'])

    plt.plot(valid[['y', 'Predictions']])


    640?wx_fmt=png


    推论

    先知(像大多数时间序列预测技术一样)试图从过去的数据中捕捉趋势和季节性。该模型通常在时间序列数据集上表现良好,但在本例中没有达到预期效果。

     

    事实证明,股票价格没有特定的趋势或季节性。价格的涨跌很大程度上取决于目前市场上的情况。因此,像ARIMA、SARIMA和Prophet这样的预测技术并不能很好地解决这个特殊的问题。

     

    让我们继续尝试另一种高级技术——长短时记忆网络(LSTM)。

    7、长短期记忆网络(LSTM)

    简介

    LSTM 算法广泛应用于序列预测问题中,并被证明是一种非常有效的方法。它们之所表现如此出色,是因为LSTM能够存储重要的既往信息,并忽略不重要的信息。

    LSTM有三个门:

    • 输入门:输入门将信息添加到细胞状态

    • 遗忘门:它移除模型不再需要的信息

    • 输出门:LSTM的输出门选择作为输出的信息

    要更详细地了解LSTM及其体系结构,可以阅读下面的文章:

    • 长短期记忆网络简介

    现在,让我们将LSTM实现为一个黑盒,并检查它在特定数据上的性能。


    实现

    #importing required libraries

    from sklearn.preprocessing import MinMaxScaler

    from keras.models import Sequential

    from keras.layers import Dense, Dropout, LSTM

     

    #creating dataframe

    data = df.sort_index(ascending=True, axis=0)

    new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close'])

    for i in range(0,len(data)):

        new_data['Date'][i] = data['Date'][i]

        new_data['Close'][i] = data['Close'][i]

     

    #setting index

    new_data.index = new_data.Date

    new_data.drop('Date', axis=1, inplace=True)

     

    #creating train and test sets

    dataset = new_data.values

     

    train = dataset[0:987,:]

    valid = dataset[987:,:]

     

    #converting dataset into x_train and y_train

    scaler = MinMaxScaler(feature_range=(0, 1))

    scaled_data = scaler.fit_transform(dataset)

     

    x_train, y_train = [], []

    for i in range(60,len(train)):

        x_train.append(scaled_data[i-60:i,0])

        y_train.append(scaled_data[i,0])

    x_train, y_train = np.array(x_train), np.array(y_train)

     

    x_train = np.reshape(x_train, (x_train.shape[0],x_train.shape[1],1))

     

    # create and fit the LSTM network

    model = Sequential()

    model.add(LSTM(units=50, return_sequences=True, input_shape=(x_train.shape[1],1)))

    model.add(LSTM(units=50))

    model.add(Dense(1))

     

    model.compile(loss='mean_squared_error', optimizer='adam')

    model.fit(x_train, y_train, epochs=1, batch_size=1, verbose=2)

     

    #predicting 246 values, using past 60 from the train data

    inputs = new_data[len(new_data) - len(valid) - 60:].values

    inputs = inputs.reshape(-1,1)

    inputs  = scaler.transform(inputs)

     

    X_test = []

    for i in range(60,inputs.shape[0]):

        X_test.append(inputs[i-60:i,0])

    X_test = np.array(X_test)

     

    X_test = np.reshape(X_test, (X_test.shape[0],X_test.shape[1],1))

    closing_price = model.predict(X_test)

    closing_price = scaler.inverse_transform(closing_price)

    结果

    rms=np.sqrt(np.mean(np.power((valid-closing_price),2)))

    rms

     

    11.772259608962642


    #for plotting

    train = new_data[:987]

    valid = new_data[987:]

    valid['Predictions'] = closing_price

    plt.plot(train['Close'])

    plt.plot(valid[['Close','Predictions']])


    640?wx_fmt=png


    推论

    哇!LSTM轻松地超越了我们目前看到的任何算法。LSTM模型可以对各种参数进行调优,如改变LSTM层数、增加dropout值或增加训练迭代轮数(epoch)数。但LSTM的预测是否足以确定股票价格将上涨还是下跌?当然不行!

     

    正如我在文章开头提到的,股价受到公司新闻和其他因素的影响,如公司的非货币化或合并/分拆。还有一些无形的因素往往是无法事先预测的。

    写在最后

    我在写这些文章时意识到时间序列预测是一个非常有趣的领域。在社区中有观点认为这是一个复杂的领域,虽然有一定道理,我还是想说一旦你掌握了基本的技巧,就不难理解它了。

     

    我对LSTM如何处理其他时间序列的问题很感兴趣,并鼓励您自己也尝试一下。如果你有任何问题,请在下面的留言部分与我联系。


    原文链接:https://www.analyticsvidhya.com/blog/2018/10/predicting-stock-price-machine-learningnd-deep-learning-techniques-python/


    译者简介:赵雪尧,北邮研三在读,京东见习算法工程师,目前研究强化学习广告竞价模型。相信数据和算法将为企业发展赋能,希望跟志同道合的小伙伴一起追寻前沿消息,深入探索算法的极限。在玄学调参的道路上,一路狂奔。

    「完」


    本次转自:THU数据派 微信公众号;

    版权声明:本号内容部分来自互联网,转载请注明原文链接和作者,如有侵权或出处有误请和我们联系。

    关联阅读

    原创系列文章:

    1:从0开始搭建自己的数据运营指标体系(概括篇)

    2 :从0开始搭建自己的数据运营指标体系(定位篇)

    3 :从0开始搭建自己的数据运营体系(业务理解篇)

    4 :数据指标的构建流程与逻辑

    5 :系列 :从数据指标到数据运营指标体系

    6:   实战 :为自己的公号搭建一个数据运营指标体系

    7:  从0开始搭建自己的数据运营指标体系(运营活动分析)

    数据运营 关联文章阅读:  

    运营入门,从0到1搭建数据分析知识体系    

    推荐 :数据分析师与运营协作的9个好习惯

    干货 :手把手教你搭建数据化用户运营体系

    推荐 :最用心的运营数据指标解读

    干货 : 如何构建数据运营指标体系

    从零开始,构建数据化运营体系

    干货 :解读产品、运营和数据三个基友关系

    干货 :从0到1搭建数据运营体系

    数据分析、数据产品 关联文章阅读:

    干货 :数据分析团队的搭建和思考

    关于用户画像那些事,看这一文章就够了

    数据分析师必需具备的10种分析思维。

    如何构建大数据层级体系,看这一文章就够了

    干货 : 聚焦于用户行为分析的数据产品

    80%的运营注定了打杂?因为你没有搭建出一套有效的用户运营体系

    从底层到应用,那些数据人的必备技能

    读懂用户运营体系:用户分层和分群

    做运营必须掌握的数据分析思维,你还敢说不会做数据分析

    合作请加qq:365242293  


    更多相关知识请回复:“ 月光宝盒 ”;

    数据分析(ID : ecshujufenxi )互联网科技与数据圈自己的微信,也是WeMedia自媒体联盟成员之一,WeMedia联盟覆盖5000万人群。

    640?wx_fmt=png

    展开全文
  • 来源:AISHWARYA SINGH, 2018年10月25日翻译:赵雪尧校对:车前子本文约8000字,建议阅读15+分钟。本文介绍了如何运用深度学习预测股票市场。简介...
        

    640?wx_fmt=png

    来源:AISHWARYA SINGH, 2018年10月25日

    翻译:赵雪尧

    校对:车前子

    本文约8000字,建议阅读15+分钟。

    本文介绍了如何运用深度学习法预测股票市场。


    简介


    预测股市将如何变化历来是最困难的事情之一。这个预测行为中包含着如此之多的因素—包括物理或心理因素、理性或者不理性行为因素等等。所有这些因素结合在一起,使得股价波动剧烈,很难准确预测。

     

    使用机器学习可能改变游戏规则吗?机器学习技术使用最新的组织公告、季度收益等作为特征,有潜力挖掘出我们以前没有见过的模式和见解,并可用于准确无误的预测。


    640?wx_fmt=png


    在本文中,我们将研究上市公司股价的历史数据。我们将结合机器学习算法来预测这家公司的未来股价,从平均和线性回归这样的简单算法开始,然后转向像Auto ARIMA和LSTM这样的高级模型。

     

    本文背后的核心思想是展示这些算法是如何实现的,因此我只会简单描述该技术并提供相关参考链接,以便在必要时对这些概念进行复习。如果您是时间序列领域的新手,我建议您先阅读以下文章:


    • 创建时间序列预测的初学者综合指南

    • 时间序列建模的完整教程


    目录


    1、 问题理解

    2、 移动平均

    3、 线性回归

    4、 K-近邻

    5、 自动ARIMA

    6、 先知(Prophet)

    7、 长短时记忆网络(LSTM)

     

    1、问题理解


    我们将很快深入本文的实现部分,但首先重要的是确定我们要解决的问题。一般来说,股票市场分析分为两个部分——基本面分析和技术分析。


    • 基本面分析是根据公司目前的经营环境和财务状况,对公司未来的盈利能力进行分析。

    • 技术分析包括阅读图表和使用统计数字来确定股票市场的趋势。


    您可能已经猜到,我们的重点将放在技术分析部分。我们将使用来自Quandl的数据集(您可以在这里找到各种股票的历史数据),这个项目中,我使用了“塔塔全球饮料”的数据。是时候开始了!


    首先让我们加载数据集,定义问题的目标变量:


    #import packages

    import pandas as pd

    import numpy as np

     

    #to plot within notebook

    import matplotlib.pyplot as plt

    %matplotlib inline

     

    #setting figure size

    from matplotlib.pylab import rcParams

    rcParams['figure.figsize'] = 20,10

     

    #for normalizing data

    from sklearn.preprocessing import MinMaxScaler

    scaler = MinMaxScaler(feature_range=(0, 1))

     

    #read the file

    df = pd.read_csv('NSE-TATAGLOBAL(1).csv')

     

    #print the head

    df.head()


    640?wx_fmt=png


    数据集中有多个变量——日期(date)、开盘价(open)、最高价(high)、最低价(low)、最后交易价(last)、收盘价(close)、总交易额(total_trade_quantity)和营业额(turnover)。

     

    • 开盘价和收盘价代表股票在某一天交易的起始价和最终价。

    • 最高价、最低价和最后交易价表示当天股票的最高价、最低价和最后交易价格。

    • 交易总量是指当天买卖的股票数量,而营业额(Lacs)是指某一特定公司在某一特定日期的营业额。


    要注意的另一点是,市场在周末和公共假期休市。注意上表缺失了一些日期值——2/10/2018、6/10/2018、7/10/2018。其中2号是国庆节,6号和7号是周末。

     

    损益的计算通常由股票当日的收盘价决定,因此我们将收盘价作为目标变量。让我们画出目标变量来理解它在我们的数据集中的分布:


    #setting index as date

    df['Date'] = pd.to_datetime(df.Date,format='%Y-%m-%d')

    df.index = df['Date']

     

    #plot

    plt.figure(figsize=(16,8))

    plt.plot(df['Close'], label='Close Price history')


    640?wx_fmt=png


    在接下来的部分中,我们将探索这些变量,并使用不同的技术来预测股票的每日收盘价。

     

    2、移动平均


    简介


    “平均数”是我们日常生活中最常用的统计量之一。例如,计算平均分数来确定整体表现,或者根据过去几天的平均温度来了解今天的温度——这些都是我们经常做的日常工作。因此,使用这个方法开始用数据集进行预测是个不错的选择。

     

    我们利用一组先前观测值的平均值作为每天的预期收盘价。我们将使用移动平均法,而不是使用简单的平均值,移动平均法使用最近的一组数据计算预测值。换句话说,对于后续的每个新的时间,在考虑预测值时,将从集合中删除最早的观测值,并加入上一个观测值。下面是一个简单的图,它将帮助您更清楚地理解这一点。


    640?wx_fmt=png


    我们将在数据集上使用这种技术。第一步是创建一个只包含日期和收盘价列的数据框,然后将其拆分为训练集和验证集来验证我们的预测。


    实现


    #creating dataframe with date and the target variable

    data = df.sort_index(ascending=True, axis=0)

    new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close'])

     

    for i in range(0,len(data)):

         new_data['Date'][i] = data['Date'][i]

         new_data['Close'][i] = data['Close'][i]


    在将数据分割为训练和验证时,我们不能使用随机分割,因为这会破坏时间顺序。所以这里我将去年的数据作为验证集,将之前4年的数据作为训练集。


    #splitting into train and validation

    train = new_data[:987]

    valid = new_data[987:]

     

    new_data.shape, train.shape, valid.shape

    ((1235, 2), (987, 2), (248, 2))

     

    train['Date'].min(), train['Date'].max(), valid['Date'].min(), valid['Date'].max()

     

    (Timestamp('2013-10-08 00:00:00'),

    Timestamp('2017-10-06 00:00:00'),

    Timestamp('2017-10-09 00:00:00'),

    Timestamp('2018-10-08 00:00:00'))


    下一步是为验证集创建预测值,并使用真实值来检查RMSE误差。


    #make predictions

    preds = []

    for i in range(0,248):

        a = train['Close'][len(train)-248+i:].sum() + sum(preds)

        b = a/248

        preds.append(b)


    结果


    #calculate rmse

    rms=np.sqrt(np.mean(np.power((np.array(valid['Close'])-preds),2)))

    rms

     

    104.51415465984348


    仅仅检查RMSE并不能帮助我们评估模型预测效果的。让我们通过做图得到更直观的理解。下面是预测值和实际值的曲线图。


    #plot

    valid['Predictions'] = 0

    valid['Predictions'] = preds

    plt.plot(train['Close'])

    plt.plot(valid[['Close', 'Predictions']])


    640?wx_fmt=png


    推论


    RMSE值接近105,但是结果不是很理想(从图中可以看出)。预测值与训练集的观测值的范围相同(开始有上升趋势,然后缓慢下降)。

     

    在下一节中,我们将使用两种常用的机器学习技术——线性回归和kNN,看看它们在我们的股票市场数据上表现如何。

     

    3、线性回归


    简介


    在这些数据上可以实现的最基本的机器学习算法是线性回归。线性回归模型生成一个确定自变量和因变量之间关系的方程。

     

    线性回归方程可以写成:


    640?wx_fmt=png


    在这里x1, x2, ....xn代表自变量,系数θ1,θ2,....θn代表权重。你可以参考下面的文章来更详细地学习线性回归:


    • 对于线性回归和Lasso回归的一个综合的初学者指南.


    我们的问题中,没有太多的自变量,只有日期。让我们使用时间(date)列提取特征,如- day, month, year, mon/fri等,然后拟合线性回归模型。


    实现


    我们将首先按升序对数据集进行排序,然后创建一个单独的数据集,这样创建的任何新特性都不会影响原始数据。


    #setting index as date values

    df['Date'] = pd.to_datetime(df.Date,format='%Y-%m-%d')

    df.index = df['Date']

     

    #sorting

    data = df.sort_index(ascending=True, axis=0)

     

    #creating a separate dataset

    new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close'])

     

    for i in range(0,len(data)):

        new_data['Date'][i] = data['Date'][i]

        new_data['Close'][i] = data['Close'][i]


    #create features

    from fastai.structured import  add_datepart

    add_datepart(new_data, 'Date')

    new_data.drop('Elapsed', axis=1, inplace=True)  #elapsed will be the time stamp


    这将创建以下特征:


    ‘Year’, ‘Month’, ‘Week’, ‘Day’, ‘Dayofweek’, ‘Dayofyear’, ‘Is_month_end’, ‘Is_month_start’, ‘Is_quarter_end’, ‘Is_quarter_start’,  ‘Is_year_end’, and  ‘Is_year_start’.


    注意:我使用了来自fastai库的add_datepart。如果您没有安装它,您可以简单地使用命令pip install fastai。您也可以使用python中的简单for循环来创建这些特性。我在下面展示了一个例子。

     

    除此之外,我们还可以添加自己的一组特性,我们认为这些特性与预测相关。例如,我的假设是,本周的头几天和最后几天对股票收盘价的影响可能远远超过其他日子。因此,我创建了一个特性来识别给定的一天是星期一/星期五还是星期二/星期三/星期四。这可以用以下几行代码来完成:


    new_data['mon_fri'] = 0

    for i in range(0,len(new_data)):

        if (new_data['Dayofweek'][i] == 0 or new_data['Dayofweek'][i] == 4):

            new_data['mon_fri'][i] = 1

        else:

            new_data['mon_fri'][i] = 0


    如果是星期日或星期五,列值将为1,否则为0。类似地,您可以创建多个特性。如果你对有助于预测股价的特征有一些想法,请在留言里分享。

     

    现在我们将把数据分成训练集和验证集来检查模型的性能。


    #split into train and validation

    train = new_data[:987]

    valid = new_data[987:]

     

    x_train = train.drop('Close', axis=1)

    y_train = train['Close']

    x_valid = valid.drop('Close', axis=1)

    y_valid = valid['Close']

     

    #implement linear regression

    from sklearn.linear_model import LinearRegression

    model = LinearRegression()

    model.fit(x_train,y_train)


    结果


    #make predictions and find the rmse

    preds = model.predict(x_valid)

    rms=np.sqrt(np.mean(np.power((np.array(y_valid)-np.array(preds)),2)))

    rms

     

    121.16291596523156

     

    RMSE值高于之前的方法,这清楚地表明线性回归的表现很差。让我们看看这个图,并理解为什么线性回归预测效果不是很好:


    #plot

    valid['Predictions'] = 0

    valid['Predictions'] = preds


    valid.index = new_data[987:].index

    train.index = new_data[:987].index

     

    plt.plot(train['Close'])

    plt.plot(valid[['Close', 'Predictions']])


    640?wx_fmt=png


    推论


    线性回归是一种简单的技术,很容易解释,但也有一些明显的缺点。使用回归算法的一个问题是,模型过度拟合了日期和月份。模型将考虑一个月前相同日期或一年前相同日期/月的值,而不是从预测的角度考虑以前的值。

     

    从上图可以看出,2016年1月和2017年1月,股价出现下跌。该模型预测2018年1月也将如此。线性回归技术可以很好地解决像大卖场销售这样的问题,在这些问题中,独立的特征对于确定目标值是有用的。


    4、k-近邻


    简介


    另一个有趣的ML算法是kNN (k近邻)。基于自变量,kNN可以发现新数据点与旧数据点之间的相似性。让我用一个简单的例子来解释这个问题。

     

    考虑11个人的身高和年龄。根据给定的特征(“年龄”和“身高”),下表可以用图形形式表示,如下图所示:


    640?wx_fmt=png


    为了确定ID #11的权重,kNN考虑该ID的最近邻居的权重。ID #11的权重被预测为其邻居的平均值。如果我们现在考虑三个邻居(k=3), ID#11的重量将是= (77+72+60)/3 = 69.66 kg。


    640?wx_fmt=png


    对于kNN的详细了解,可以参考以下文章:


    • k近邻介绍:简介

    • 对k近邻回归算法的实际介绍


    实现


    #importing libraries

    from sklearn import neighbors

    from sklearn.model_selection import GridSearchCV

    from sklearn.preprocessing import MinMaxScaler

    scaler = MinMaxScaler(feature_range=(0, 1))


    使用上一节中相同的训练和验证集:

     

    #scaling data

    x_train_scaled = scaler.fit_transform(x_train)

    x_train = pd.DataFrame(x_train_scaled)

    x_valid_scaled = scaler.fit_transform(x_valid)

    x_valid = pd.DataFrame(x_valid_scaled)

     

    #using gridsearch to find the best parameter

    params = {'n_neighbors':[2,3,4,5,6,7,8,9]}

    knn = neighbors.KNeighborsRegressor()


    model = GridSearchCV(knn, params, cv=5)

     

    #fit the model and make predictions

    model.fit(x_train,y_train)

    preds = model.predict(x_valid)


    结果


    #rmse

    rms=np.sqrt(np.mean(np.power((np.array(y_valid)-np.array(preds)),2)))

    rms

     

    115.17086550026721


    RMSE值并没有太大的差异,但是一个预测值和实际值的曲线图应该提供一个更清晰的理解。

     

    #plot

    valid['Predictions'] = 0

    valid['Predictions'] = preds

    plt.plot(valid[['Close', 'Predictions']])

    plt.plot(train['Close'])


    640?wx_fmt=png


    推论


    RMSE值与线性回归模型近似,图中呈现出相同的模式。与线性回归一样,kNN也发现了2018年1月的下降,因为这是过去几年的模式。我们可以有把握地说,回归算法在这个数据集上表现得并不好。


    让我们来看一些时间序列预测技术,看看它们在面对股价预测挑战时的表现。


    5、自动ARIMA


    简介


    ARIMA是一种非常流行的时间序列预测统计方法。ARIMA模型使用过去的值来预测未来的值。ARIMA中有三个重要参数:


    • p(用来预测下一个值的过去值)

    • q(用来预测未来值的过去预测误差)

    • d(差分的顺序)


    ARIMA的参数优化需要大量时间。因此我们将使用自动 ARIMA,自动选择误差最小的(p,q,d)最佳组合。要了解更多关于自动ARIMA的工作原理,请参阅本文:


    • 利用自动ARIMA建立高性能时间序列模型


    实现


    from pyramid.arima import auto_arima

     

    data = df.sort_index(ascending=True, axis=0)

     

    train = data[:987]

    valid = data[987:]

     

    training = train['Close']

    validation = valid['Close']

     

    model = auto_arima(training, start_p=1, start_q=1,max_p=3, max_q=3, m=12,start_P=0, seasonal=True,d=1, D=1, trace=True,error_action='ignore',suppress_warnings=True)

    model.fit(training)

     

    forecast = model.predict(n_periods=248)

    forecast = pd.DataFrame(forecast,index = valid.index,columns=['Prediction'])


    结果


    rms=np.sqrt(np.mean(np.power((np.array(valid['Close'])-np.array(forecast['Prediction'])),2)))

    rms

     

    44.954584993246954

     

     

    #plot

    plt.plot(train['Close'])

    plt.plot(valid['Close'])

    plt.plot(forecast['Prediction'])


    640?wx_fmt=png


    推论


    正如我们前面看到的,自动ARIMA模型使用过去的数据来理解时间序列中的模式。利用这些值,该模型捕捉到该系列中的增长趋势。虽然使用这种技术的预测比以前实现的机器学习模型的预测要好得多,但是这些预测仍然与实际值相距甚远。

     

    从图中可以明显看出,该模型在序列中捕捉到了一种趋势,但忽略了季节的影响。在下一节中,我们将使用一个同时考虑了序列的趋势和季节性的时间序列模型。该模型。


    6、先知(Prophet)


    简介


    有许多时间序列技术可以用在股票预测数据集上,但是大多数技术在拟合模型之前需要大量的数据预处理。Prophet(先知)由Facebook设计和开发,是一个时间序列预测库,不需要数据预处理,并且非常容易实现。先知的输入是一个带有两列的数据框:日期和目标(ds和y)。

     

    先知试图在过去的数据中捕捉季节性,并且在数据集很大的时候依然表现良好。这里有一篇有趣的文章,用一个简单和直观的方式解释了先知算法:


    • 使用Facebook的Prophet生成快速准确的时间序列预测


    实现


    #importing prophet

    from fbprophet import Prophet

     

    #creating dataframe

    new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close'])

     

    for i in range(0,len(data)):

        new_data['Date'][i] = data['Date'][i]

        new_data['Close'][i] = data['Close'][i]

     

    new_data['Date'] = pd.to_datetime(new_data.Date,format='%Y-%m-%d')

    new_data.index = new_data['Date']

     

    #preparing data

    new_data.rename(columns={'Close': 'y', 'Date': 'ds'}, inplace=True)

     

    #train and validation

    train = new_data[:987]

    valid = new_data[987:]

     

    #fit the model

    model = Prophet()

    model.fit(train)

     

    #predictions

    close_prices = model.make_future_dataframe(periods=len(valid))

    forecast = model.predict(close_prices)


    结果


    #rmse

    forecast_valid = forecast['yhat'][987:]

    rms=np.sqrt(np.mean(np.power((np.array(valid['y'])-np.array(forecast_valid)),2)))

    rms

     

    57.494461930575149

     

     

    #plot

    valid['Predictions'] = 0

    valid['Predictions'] = forecast_valid.values

     

    plt.plot(train['y'])

    plt.plot(valid[['y', 'Predictions']])


    640?wx_fmt=png


    推论


    先知(像大多数时间序列预测技术一样)试图从过去的数据中捕捉趋势和季节性。该模型通常在时间序列数据集上表现良好,但在本例中没有达到预期效果。

     

    事实证明,股票价格没有特定的趋势或季节性。价格的涨跌很大程度上取决于目前市场上的情况。因此,像ARIMA、SARIMA和Prophet这样的预测技术并不能很好地解决这个特殊的问题。

     

    让我们继续尝试另一种高级技术——长短时记忆网络(LSTM)。


    7、长短期记忆网络(LSTM)


    简介


    LSTM 算法广泛应用于序列预测问题中,并被证明是一种非常有效的方法。它们之所表现如此出色,是因为LSTM能够存储重要的既往信息,并忽略不重要的信息。


    LSTM有三个门:


    • 输入门:输入门将信息添加到细胞状态

    • 遗忘门:它移除模型不再需要的信息

    • 输出门:LSTM的输出门选择作为输出的信息


    要更详细地了解LSTM及其体系结构,可以阅读下面的文章:


    • 长短期记忆网络简介


    现在,让我们将LSTM实现为一个黑盒,并检查它在特定数据上的性能。


    实现


    #importing required libraries

    from sklearn.preprocessing import MinMaxScaler

    from keras.models import Sequential

    from keras.layers import Dense, Dropout, LSTM

     

    #creating dataframe

    data = df.sort_index(ascending=True, axis=0)

    new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close'])

    for i in range(0,len(data)):

        new_data['Date'][i] = data['Date'][i]

        new_data['Close'][i] = data['Close'][i]

     

    #setting index

    new_data.index = new_data.Date

    new_data.drop('Date', axis=1, inplace=True)

     

    #creating train and test sets

    dataset = new_data.values

     

    train = dataset[0:987,:]

    valid = dataset[987:,:]

     

    #converting dataset into x_train and y_train

    scaler = MinMaxScaler(feature_range=(0, 1))

    scaled_data = scaler.fit_transform(dataset)

     

    x_train, y_train = [], []

    for i in range(60,len(train)):

        x_train.append(scaled_data[i-60:i,0])

        y_train.append(scaled_data[i,0])

    x_train, y_train = np.array(x_train), np.array(y_train)

     

    x_train = np.reshape(x_train, (x_train.shape[0],x_train.shape[1],1))

     

    # create and fit the LSTM network

    model = Sequential()

    model.add(LSTM(units=50, return_sequences=True, input_shape=(x_train.shape[1],1)))

    model.add(LSTM(units=50))

    model.add(Dense(1))

     

    model.compile(loss='mean_squared_error', optimizer='adam')

    model.fit(x_train, y_train, epochs=1, batch_size=1, verbose=2)

     

    #predicting 246 values, using past 60 from the train data

    inputs = new_data[len(new_data) - len(valid) - 60:].values

    inputs = inputs.reshape(-1,1)

    inputs  = scaler.transform(inputs)

     

    X_test = []

    for i in range(60,inputs.shape[0]):

        X_test.append(inputs[i-60:i,0])

    X_test = np.array(X_test)

     

    X_test = np.reshape(X_test, (X_test.shape[0],X_test.shape[1],1))

    closing_price = model.predict(X_test)

    closing_price = scaler.inverse_transform(closing_price)


    结果


    rms=np.sqrt(np.mean(np.power((valid-closing_price),2)))

    rms

     

    11.772259608962642


    #for plotting

    train = new_data[:987]

    valid = new_data[987:]

    valid['Predictions'] = closing_price

    plt.plot(train['Close'])

    plt.plot(valid[['Close','Predictions']])


    640?wx_fmt=png


    推论


    哇!LSTM轻松地超越了我们目前看到的任何算法。LSTM模型可以对各种参数进行调优,如改变LSTM层数、增加dropout值或增加训练迭代轮数(epoch)数。但LSTM的预测是否足以确定股票价格将上涨还是下跌?当然不行!

     

    正如我在文章开头提到的,股价受到公司新闻和其他因素的影响,如公司的非货币化或合并/分拆。还有一些无形的因素往往是无法事先预测的。


    写在最后


    我在写这些文章时意识到时间序列预测是一个非常有趣的领域。在社区中有观点认为这是一个复杂的领域,虽然有一定道理,我还是想说一旦你掌握了基本的技巧,就不难理解它了。

     

    我对LSTM如何处理其他时间序列的问题很感兴趣,并鼓励您自己也尝试一下。如果你有任何问题,请在下面的留言部分与我联系。


    原文链接:https://www.analyticsvidhya.com/blog/2018/10/predicting-stock-price-machine-learningnd-deep-learning-techniques-python/


    译者简介

    640?wx_fmt=png

    赵雪尧,北邮研三在读,京东见习算法工程师,目前研究强化学习广告竞价模型。相信数据和算法将为企业发展赋能,希望跟志同道合的小伙伴一起追寻前沿消息,深入探索算法的极限。在玄学调参的道路上,一路狂奔。

    翻译组招募信息

    工作内容:需要一颗细致的心,将选取好的外文文章翻译成流畅的中文。如果你是数据科学/统计学/计算机类的留学生,或在海外从事相关工作,或对自己外语水平有信心的朋友欢迎加入翻译小组。

    你能得到:定期的翻译培训提高志愿者的翻译水平,提高对于数据科学前沿的认知,海外的朋友可以和国内技术应用发展保持联系,THU数据派产学研的背景为志愿者带来好的发展机遇。

    其他福利:来自于名企的数据科学工作者,北大清华以及海外等名校学生他们都将成为你在翻译小组的伙伴。


    点击文末“阅读原文”加入数据派团队~

    转载须知

    如需转载,请在开篇显著位置注明作者和出处(转自:数据派ID:datapi),并在文章结尾放置数据派醒目二维码。有原创标识文章,请发送【文章名称-待授权公众号名称及ID】至联系邮箱,申请白名单授权并按要求编辑。

    发布后请将链接反馈至联系邮箱(见下方)。未经许可的转载以及改编者,我们将依法追究其法律责任。

    640?wx_fmt=jpeg

    640?wx_fmt=jpeg

    640?wx_fmt=jpeg

    点击“阅读原文”拥抱组织

    展开全文
  • 深度学习算法预测未来股票走势

    千次阅读 2020-08-21 16:23:50
    最近研究了一下用深度学习算法来预测股票未来的走势,看了网上不少别人分享的案例,也实际进行了测试,感觉用 LSTM 算法比较适用。长短期记忆网络(LSTM,Long Short-Term Memory)是一种时间循环神经网络,是为了...
  • 从这篇开始,我们的专栏将正式开始涉及人工智能领域。 人工智能常常用来解决分类和回归的问题...这篇文章我们将使用深度学习的方法,针对1991年至今的上证指数进行时间序列的预测,来看一看未来大盘的走势如何。 ...
  • 该论文旨在结合短期、中期和长期新闻事件来共同预测股票价格波动。 文章要点 利用OpenIE(open information extraction)从新闻文本中抓取事件结构表征(执行器、动作、对象、时间),然后利用神经张量网络或...
  • 介绍 ...利用一些特性,比如关于一个组织的最新公告,他们的季度收入结果等功能,机器学习技术有可能发掘出我们以前没有看到的模式和见解,并且可以用来做出准确无误的预测。 在本文中,我们将使...
  • Introduction 预测股市将如何表现是最... 利用有关组织的最新公告,季度收入结果等功能,机器学习技术有可能发掘出我们以前没有看到的模式和见解,并且可以用来做出准确无误的预测。 在本文中,我们将使用有关上...
  • 利用LSTM原理预测股市

    2020-07-27 23:33:56
    利用深度学习的长短记忆原理(LSTM)对美国纳斯达克股市进行预测
  • 我去一家量化交易公司实习,一次meeting中,我和老总还有一个资深大佬谈机器学习股票和期货里面的应用。 我:LSTM在时间序列上应用的效果比较好,我们可以尝试把LSTM应用在股票预测上。 此时,大佬在阴笑,老总...
  • ![图片说明](https://img-ask.csdn.net/upload/201906/12/1560330493_143606.png)麻烦问下小哥哥小姐姐们,这里的代码是用来做什么的,tf.variable和tf.constant,tf.random_normal都代表什么意思,,,,
  • 举个例子,假设我们试着去预测“I grew up in France… 中间隔了好多好多字……I speak fluent __”下划线的词。我们拍脑瓜子想这个词应该是French。对于循环神经网络来说,当前的信息建议下一个词可能是一种语言的...
  • 利用深度强化学习预测股价

    千次阅读 2019-09-17 14:26:10
    作者介绍:王茂霖,北京航空航天大学飞行器设计专业博士在读,python、C++入门小白。个人公众号:(vvrn1_field) 0.总体思路本文灵感来源于Si...
  • 卷积神经网络项目是我在华泰实习的过程中做的一个项目,主要是用卷积神经网络来预测股票的走势,现在对项目做一个总结。 报告详情: 【华泰金工林晓明团队】人工智能选股之卷积神经网络——华泰人工智能系列之十五 ...
  • 全文共5549字,预计学习时长11分钟 正如人们所想象的一样,在华尔街工作充满机遇与挑战。大家都西装革履、脸色阴沉、手持香烟吞云吐雾。在世界金融中心的喧嚣里,每个人的实际目标都很简单。不过是冒着将事物过于...
  • 最近再看一些量化交易相关的材料,偶然在网上看到了一个关于用RNN实现股票预测的文章,出于好奇心把文章中介绍的代码在本地跑了一遍,发现可以work。于是就花了两个晚上的时间学习了下代码,顺便把核心的内容翻译成...
  • Tensorflow实例:利用LSTM预测股票每日最高价(二)

    万次阅读 多人点赞 2017-09-02 11:39:11
    根据股票历史数据中的最低价、最高价、开盘价、收盘价、交易量、交易额、跌涨幅等...单因素输入特征及RNN、LSTM的介绍请戳上一篇 Tensorflow实例:利用LSTM预测股票每日最高价(一)导入包及声明常量import pandas a
1 2 3 4 5 ... 20
收藏数 3,878
精华内容 1,551
热门标签
关键字:

利用深度学习预测股票