畢業(yè)設計 大數(shù)據(jù)股票預測分析系統(tǒng)
0 前言
?? 這兩年開始畢業(yè)設計和畢業(yè)答辯的要求和難度不斷提升,傳統(tǒng)的畢設題目缺少創(chuàng)新和亮點,往往達不到畢業(yè)答辯的要求,這兩年不斷有學弟學妹告訴學長自己做的項目系統(tǒng)達不到老師的要求。
為了大家能夠順利以及最少的精力通過畢設,學長分享優(yōu)質(zhì)畢業(yè)設計項目,今天要分享的是
?? ?深度學習 大數(shù)據(jù) 股票預測系統(tǒng)
??學長這里給一個題目綜合評分(每項滿分5分)
工作量:3分
創(chuàng)新點:4分
畢設幫助,選題指導,技術(shù)解答,歡迎打擾,見B站個人主頁
https://space.bilibili.com/33886978
1 課題意義
利用神經(jīng)網(wǎng)絡模型如果能夠提高對股票價格的預測精度,更好地掌握股票價格發(fā)展趨勢,這對于投資者來說可以及時制定相應的發(fā)展策略,更好地應對未來發(fā)生的不確定性事件,對于個人來說可以降低投資風險,減少財產(chǎn)損失,實現(xiàn)高效投資,具有一定的實踐價值。
1.1 股票預測主流方法
股票市場復雜、非線性的特點使我們難以捉摸其變化規(guī)律,目前有很多預測股票走勢的論文和算法。
定量分析從精確的數(shù)據(jù)資料中獲得股票發(fā)展的價值規(guī)律,通過建立模型利用數(shù)學語言對股市的發(fā)展情況做出解釋與預測。
目前常用的定量分析方法有:
傳統(tǒng)時間序列預測模型
馬爾可夫鏈預測
灰色系統(tǒng)理論預測
遺傳算法
機器學習預測等方法
2 什么是LSTM
LSTM是長短期記憶網(wǎng)絡(LSTM,Long Short-Term Memory),想要理解什么是LSTM,首先要了解什么是循環(huán)神經(jīng)網(wǎng)絡。
2.1 循環(huán)神經(jīng)網(wǎng)絡
?對于傳統(tǒng)的BP神經(jīng)網(wǎng)絡如深度前饋網(wǎng)絡、卷積神經(jīng)網(wǎng)絡來說,同層及跨層之間的神經(jīng)元是獨立的,但實際應用中對于一些有上下聯(lián)系的序列來說,如果能夠?qū)W習到它們之間的相互關系,使網(wǎng)絡能夠?qū)Σ煌瑫r刻的輸入序列產(chǎn)生一定的聯(lián)系,像生物的大腦一樣有“記憶功能”,這樣的話我們的模型也就會有更低的訓練出錯頻率及更好的泛化能力。
?JordanMI提出序列理論,描述了一種體現(xiàn)“并行分布式處理”的網(wǎng)絡動態(tài)系統(tǒng),適用于語音生成中的協(xié)同發(fā)音問題,并進行了相關仿真實驗,ElmanJL認為連接主義模型中對時間如何表示是至關重要的,1990年他提出使用循環(huán)連接為網(wǎng)絡提供動態(tài)內(nèi)存,從相對簡單的異或問題到探尋單詞的語義特征,網(wǎng)絡均學習到了有趣的內(nèi)部表示,網(wǎng)絡還將任務需求和內(nèi)存需求結(jié)合在一起,由此形成了簡單循環(huán)網(wǎng)絡的基礎框架。
?循環(huán)神經(jīng)網(wǎng)絡(RNN)之間的神經(jīng)元是相互連接的,不僅在層與層之間的神經(jīng)元建立連接,而且每一層之間的神經(jīng)元也建立了連接,隱藏層神經(jīng)元的輸入由當前輸入和上一時刻隱藏層神經(jīng)元的輸出共同決定,每一時刻的隱藏層神經(jīng)元記住了上一時刻隱藏層神經(jīng)元的輸出,相當于對網(wǎng)絡增添了“記憶”功能。我們都知道在輸入序列中不可避免會出現(xiàn)重復或相似的某些序列信息,我們希望RNN能夠保留這些記憶信息便于再次調(diào)用,且RNN結(jié)構(gòu)中不同時刻參數(shù)是共享的,這一優(yōu)點便于網(wǎng)絡在不同位置依舊能將該重復信息識別出來,這樣一來模型的泛化能力自然有所上升。
RNN結(jié)構(gòu)如下:

2.1 LSTM誕生
RNN在解決長序列問題時未能有良好的建模效果,存在長期依賴的弊端,對此HochreiterS等人對神經(jīng)單元做出了改進,引入自循環(huán)使梯度信息得以長時間持續(xù)流動,即模型可以擁有長期記憶信息,且自循環(huán)權(quán)重可以根據(jù)前后信息進行調(diào)整并不是固定的。作為RNN的一種特殊結(jié)構(gòu),它可以根據(jù)前后輸入情況決定歷史信息的去留,增進的門控機制可以動態(tài)改變累積的時間尺度進而控制神經(jīng)單元的信息流,這樣神經(jīng)網(wǎng)絡便能夠自己根據(jù)情況決定清除或保留舊的信息,不至于狀態(tài)信息過長造成網(wǎng)絡崩潰,這便是長短期記憶(LSTM)網(wǎng)絡。隨著信息不斷流入,該模型每個神經(jīng)元內(nèi)部的遺忘門、輸入門、輸出門三個門控機制會對每一時刻的信息做出判斷并及時進行調(diào)整更新,LSTM模型現(xiàn)已廣泛應用于無約束手寫識別、語音識別、機器翻譯等領域。

2 如何用LSTM做股票預測
2.1 算法構(gòu)建流程

2.2 部分代碼
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import pandas as pd
import math
def LSTMtest(data):
? ?n1 = len(data[0]) - 1 #因為最后一位為label
? ?n2 = len(data)
? ?print(n1, n2)
? ?# 設置常量
? ?input_size = n1 ?# 輸入神經(jīng)元個數(shù)
? ?rnn_unit = 10 ? ?# LSTM單元(一層神經(jīng)網(wǎng)絡)中的中神經(jīng)元的個數(shù)
? ?lstm_layers = 7 ?# LSTM單元個數(shù)
? ?output_size = 1 ?# 輸出神經(jīng)元個數(shù)(預測值)
? ?lr = 0.0006 ? ? ?# 學習率
? ?train_end_index = math.floor(n2*0.9) ?# 向下取整
? ?print('train_end_index', train_end_index)
? ?# 前90%數(shù)據(jù)作為訓練集,后10%作為測試集
? ?# 獲取訓練集
? ?# time_step 時間步,batch_size 每一批次訓練多少個樣例
? ?def get_train_data(batch_size=60, time_step=20, train_begin=0, train_end=train_end_index):
? ? ? ?batch_index = []
? ? ? ?data_train = data[train_begin:train_end]
? ? ? ?normalized_train_data = (data_train - np.mean(data_train, axis=0)) / np.std(data_train, axis=0) ?# 標準化
? ? ? ?train_x, train_y = [], [] ?# 訓練集
? ? ? ?for i in range(len(normalized_train_data) - time_step):
? ? ? ? ? ?if i % batch_size == 0:
? ? ? ? ? ? ? ?# 開始位置
? ? ? ? ? ? ? ?batch_index.append(i)
? ? ? ? ? ? ? ?# 一次取time_step行數(shù)據(jù)
? ? ? ? ? ?# x存儲輸入維度(不包括label) :X(最后一個不?。?br> ? ? ? ? ? ?# 標準化(歸一化)
? ? ? ? ? ?x = normalized_train_data[i:i + time_step, :n1]
? ? ? ? ? ?# y存儲label
? ? ? ? ? ?y = normalized_train_data[i:i + time_step, n1, np.newaxis]
? ? ? ? ? ?# np.newaxis分別是在行或列上增加維度
? ? ? ? ? ?train_x.append(x.tolist())
? ? ? ? ? ?train_y.append(y.tolist())
? ? ? ?# 結(jié)束位置
? ? ? ?batch_index.append((len(normalized_train_data) - time_step))
? ? ? ?print('batch_index', batch_index)
? ? ? ?# print('train_x', train_x)
? ? ? ?# print('train_y', train_y)
? ? ? ?return batch_index, train_x, train_y
? ?# 獲取測試集
? ?def get_test_data(time_step=20, test_begin=train_end_index+1):
? ? ? ?data_test = data[test_begin:]
? ? ? ?mean = np.mean(data_test, axis=0)
? ? ? ?std = np.std(data_test, axis=0) ?# 矩陣標準差
? ? ? ?# 標準化(歸一化)
? ? ? ?normalized_test_data = (data_test - np.mean(data_test, axis=0)) / np.std(data_test, axis=0)
? ? ? ?# " // "表示整數(shù)除法。有size個sample
? ? ? ?test_size = (len(normalized_test_data) + time_step - 1) // time_step
? ? ? ?print('test_size$$$$$$$$$$$$$$', test_size)
? ? ? ?test_x, test_y = [], []
? ? ? ?for i in range(test_size - 1):
? ? ? ? ? ?x = normalized_test_data[i * time_step:(i + 1) * time_step, :n1]
? ? ? ? ? ?y = normalized_test_data[i * time_step:(i + 1) * time_step, n1]
? ? ? ? ? ?test_x.append(x.tolist())
? ? ? ? ? ?test_y.extend(y)
? ? ? ?test_x.append((normalized_test_data[(i + 1) * time_step:, :n1]).tolist())
? ? ? ?test_y.extend((normalized_test_data[(i + 1) * time_step:, n1]).tolist())
? ? ? ?return mean, std, test_x, test_y
? ?# ——————————————————定義神經(jīng)網(wǎng)絡變量——————————————————
? ?# 輸入層、輸出層權(quán)重、偏置、dropout參數(shù)
? ?# 隨機產(chǎn)生 w,b
? ?weights = {
? ? ? ?'in': tf.Variable(tf.random_normal([input_size, rnn_unit])),
? ? ? ?'out': tf.Variable(tf.random_normal([rnn_unit, 1]))
? ?}
? ?biases = {
? ? ? ?'in': tf.Variable(tf.constant(0.1, shape=[rnn_unit, ])),
? ? ? ?'out': tf.Variable(tf.constant(0.1, shape=[1, ]))
? ?}
? ?keep_prob = tf.placeholder(tf.float32, name='keep_prob') ?# dropout 防止過擬合
? ?# ——————————————————定義神經(jīng)網(wǎng)絡——————————————————
? ?def lstmCell():
? ? ? ?# basicLstm單元
? ? ? ?# tf.nn.rnn_cell.BasicLSTMCell(self, num_units, forget_bias=1.0,
? ? ? ?# tate_is_tuple=True, activation=None, reuse=None, name=None)
? ? ? ?# num_units:int類型,LSTM單元(一層神經(jīng)網(wǎng)絡)中的中神經(jīng)元的個數(shù),和前饋神經(jīng)網(wǎng)絡中隱含層神經(jīng)元個數(shù)意思相同
? ? ? ?# forget_bias:float類型,偏置增加了忘記門。從CudnnLSTM訓練的檢查點(checkpoin)恢復時,必須手動設置為0.0。
? ? ? ?# state_is_tuple:如果為True,則接受和返回的狀態(tài)是c_state和m_state的2-tuple;如果為False,則他們沿著列軸連接。后一種即將被棄用。
? ? ? ?# (LSTM會保留兩個state,也就是主線的state(c_state),和分線的state(m_state),會包含在元組(tuple)里邊
? ? ? ?# state_is_tuple=True就是判定生成的是否為一個元組)
? ? ? ?# ? 初始化的 c 和 a 都是zero_state 也就是都為list[]的zero,這是參數(shù)state_is_tuple的情況下
? ? ? ?# ? 初始state,全部為0,慢慢的累加記憶
? ? ? ?# activation:內(nèi)部狀態(tài)的激活函數(shù)。默認為tanh
? ? ? ?# reuse:布爾類型,描述是否在現(xiàn)有范圍中重用變量。如果不為True,并且現(xiàn)有范圍已經(jīng)具有給定變量,則會引發(fā)錯誤。
? ? ? ?# name:String類型,層的名稱。具有相同名稱的層將共享權(quán)重,但為了避免錯誤,在這種情況下需要reuse=True.
? ? ? ?#
? ? ? ?basicLstm = tf.nn.rnn_cell.BasicLSTMCell(rnn_unit, forget_bias=1.0, state_is_tuple=True)
? ? ? ?# dropout 未使用
? ? ? ?drop = tf.nn.rnn_cell.DropoutWrapper(basicLstm, output_keep_prob=keep_prob)
? ? ? ?return basicLstm
?
? ?def lstm(X): ?# 參數(shù):輸入網(wǎng)絡批次數(shù)目
? ? ? ?batch_size = tf.shape(X)[0]
? ? ? ?time_step = tf.shape(X)[1]
? ? ? ?w_in = weights['in']
? ? ? ?b_in = biases['in']
? ? ? ?# 忘記門(輸入門)
? ? ? ?# 因為要進行矩陣乘法,所以reshape
? ? ? ?# 需要將tensor轉(zhuǎn)成2維進行計算
? ? ? ?input = tf.reshape(X, [-1, input_size])
? ? ? ?input_rnn = tf.matmul(input, w_in) + b_in
? ? ? ?# 將tensor轉(zhuǎn)成3維,計算后的結(jié)果作為忘記門的輸入
? ? ? ?input_rnn = tf.reshape(input_rnn, [-1, time_step, rnn_unit])
? ? ? ?print('input_rnn', input_rnn)
? ? ? ?# 更新門
? ? ? ?# 構(gòu)建多層的lstm
? ? ? ?cell = tf.nn.rnn_cell.MultiRNNCell([lstmCell() for i in range(lstm_layers)])
? ? ? ?init_state = cell.zero_state(batch_size, dtype=tf.float32)
? ? ? ?# 輸出門
? ? ? ?w_out = weights['out']
? ? ? ?b_out = biases['out']
? ? ? ?# output_rnn是最后一層每個step的輸出,final_states是每一層的最后那個step的輸出
? ? ? ?output_rnn, final_states = tf.nn.dynamic_rnn(cell, input_rnn, initial_state=init_state, dtype=tf.float32)
? ? ? ?output = tf.reshape(output_rnn, [-1, rnn_unit])
? ? ? ?# 輸出值,同時作為下一層輸入門的輸入
? ? ? ?pred = tf.matmul(output, w_out) + b_out
? ? ? ?return pred, final_states
? ?# ————————————————訓練模型————————————————————
? ?def train_lstm(batch_size=60, time_step=20, train_begin=0, train_end=train_end_index):
? ? ? ?# 于是就有了tf.placeholder,
? ? ? ?# 我們每次可以將 一個minibatch傳入到x = tf.placeholder(tf.float32,[None,32])上,
? ? ? ?# 下一次傳入的x都替換掉上一次傳入的x,
? ? ? ?# 這樣就對于所有傳入的minibatch x就只會產(chǎn)生一個op,
? ? ? ?# 不會產(chǎn)生其他多余的op,進而減少了graph的開銷。
? ? ? ?X = tf.placeholder(tf.float32, shape=[None, time_step, input_size])
? ? ? ?Y = tf.placeholder(tf.float32, shape=[None, time_step, output_size])
? ? ? ?batch_index, train_x, train_y = get_train_data(batch_size, time_step, train_begin, train_end)
? ? ? ?# 用tf.variable_scope來定義重復利用,LSTM會經(jīng)常用到
? ? ? ?with tf.variable_scope("sec_lstm"):
? ? ? ? ? ?pred, state_ = lstm(X) # pred輸出值,state_是每一層的最后那個step的輸出
? ? ? ?print('pred,state_', pred, state_)
? ? ? ?# 損失函數(shù)
? ? ? ?# [-1]——列表從后往前數(shù)第一列,即pred為預測值,Y為真實值(Label)
? ? ? ?#tf.reduce_mean 函數(shù)用于計算張量tensor沿著指定的數(shù)軸(tensor的某一維度)上的的平均值
? ? ? ?loss = tf.reduce_mean(tf.square(tf.reshape(pred, [-1]) - tf.reshape(Y, [-1])))
? ? ? ?# 誤差loss反向傳播——均方誤差損失
? ? ? ?# 本質(zhì)上是帶有動量項的RMSprop,它利用梯度的一階矩估計和二階矩估計動態(tài)調(diào)整每個參數(shù)的學習率。
? ? ? ?# Adam的優(yōu)點主要在于經(jīng)過偏置校正后,每一次迭代學習率都有個確定范圍,使得參數(shù)比較平穩(wěn).
? ? ? ?train_op = tf.train.AdamOptimizer(lr).minimize(loss)
? ? ? ?saver = tf.train.Saver(tf.global_variables(), max_to_keep=15)
? ? ? ?with tf.Session() as sess:
? ? ? ? ? ?# 初始化
? ? ? ? ? ?sess.run(tf.global_variables_initializer())
? ? ? ? ? ?theloss = []
? ? ? ? ? ?# 迭代次數(shù)
? ? ? ? ? ?for i in range(200):
? ? ? ? ? ? ? ?for step in range(len(batch_index) - 1):
? ? ? ? ? ? ? ? ? ?# sess.run(b, feed_dict = replace_dict)
? ? ? ? ? ? ? ? ? ?state_, loss_ = sess.run([train_op, loss],
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?feed_dict={X: train_x[batch_index[step]:batch_index[step + 1]],
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Y: train_y[batch_index[step]:batch_index[step + 1]],
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? keep_prob: 0.5})
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# ?使用feed_dict完成矩陣乘法 處理多輸入
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# ?feed_dict的作用是給使用placeholder創(chuàng)建出來的tensor賦值
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# ?[batch_index[step]: batch_index[step + 1]]這個區(qū)間的X與Y
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# ?keep_prob的意思是:留下的神經(jīng)元的概率,如果keep_prob為0的話, 就是讓所有的神經(jīng)元都失活。
? ? ? ? ? ? ? ?print("Number of iterations:", i, " loss:", loss_)
? ? ? ? ? ? ? ?theloss.append(loss_)
? ? ? ? ? ?print("model_save: ", saver.save(sess, 'model_save2\\modle.ckpt'))
? ? ? ? ? ?print("The train has finished")
? ? ? ?return theloss
? ?theloss = train_lstm()
? ?
? ? ? ? ? ?# 相對誤差=(測量值-計算值)/計算值×100%
? ? ? ? ? ?test_y = np.array(test_y) * std[n1] + mean[n1]
? ? ? ? ? ?test_predict = np.array(test_predict) * std[n1] + mean[n1]
? ? ? ? ? ?acc = np.average(np.abs(test_predict - test_y[:len(test_predict)]) / test_y[:len(test_predict)])
? ? ? ? ? ?print("預測的相對誤差:", acc)
? ? ? ? ? ?print(theloss)
? ? ? ? ? ?plt.figure()
? ? ? ? ? ?plt.plot(list(range(len(theloss))), theloss, color='b', )
? ? ? ? ? ?plt.xlabel('times', fontsize=14)
? ? ? ? ? ?plt.ylabel('loss valuet', fontsize=14)
? ? ? ? ? ?plt.title('loss-----blue', fontsize=10)
? ? ? ? ? ?plt.show()
? ? ? ? ? ?# 以折線圖表示預測結(jié)果
? ? ? ? ? ?plt.figure()
? ? ? ? ? ?plt.plot(list(range(len(test_predict))), test_predict, color='b', )
? ? ? ? ? ?plt.plot(list(range(len(test_y))), test_y, color='r')
? ? ? ? ? ?plt.xlabel('time value/day', fontsize=14)
? ? ? ? ? ?plt.ylabel('close value/point', fontsize=14)
? ? ? ? ? ?plt.title('predict-----blue,real-----red', fontsize=10)
? ? ? ? ? ?plt.show()
? ?prediction()
需要完整代碼工程的同學,請聯(lián)系學長獲取
3 實現(xiàn)效果
3.1 數(shù)據(jù)
采集股票數(shù)據(jù)

任選幾支股票作為研究對象。
3.2 預測結(jié)果




項目運行展示
廢話不多說, 先展示項目運行結(jié)果, 后面才進行技術(shù)講解
對某公司的股票進行分析和預測 :

開發(fā)環(huán)境
如果只運行web項目,則只需安裝如下包:
python 3.6.x
django >= 2.1.4 (或者使用conda安裝最新版)
pandas >= 0.23.4 (或者使用conda安裝最新版)
numpy >= 1.15.2 (或者使用conda安裝最新版) *apscheduler = 2.1.2 (請用pip install apscheduler==2.1.2 安裝,conda裝的版本不兼容) 如果需要訓練模型或者使用模型來預測(注:需要保證本機擁有 NVIDIA GPU以及顯卡驅(qū)動),則還需要安裝:
tensorflow-gpu >= 1.10.0 (可以使用conda安裝最新版。如用conda安裝,cudatoolkit和cudnn會被自動安裝)
cudatoolkit >= 9.0 (根據(jù)自己本機的顯卡型號決定,請去NVIDIA官網(wǎng)查看)
cudnn >= 7.1.4 (版本與cudatoolkit9.0對應的,其他版本請去NVIDIA官網(wǎng)查看對應的cudatoolkit版本)
keras >= 2.2.2 (可以使用conda安裝最新版)
matplotlib >= 2.2.2 (可以使用conda安裝最新版)
數(shù)據(jù)獲取
訓練模型的數(shù)據(jù),即10個公司的歷史股票數(shù)據(jù)。獲取國內(nèi)上市公司歷史股票數(shù)據(jù), 并以csv格式保存下來。csv格式方便用pandas讀取,輸入到LSTM神經(jīng)網(wǎng)絡模型, 用于訓練模型以及預測股票數(shù)據(jù)。
最后
畢設幫助,選題指導,技術(shù)解答,歡迎打擾,見B站個人主頁
https://space.bilibili.com/33886978