HMM隐马尔科夫模型及股票预测
文章目錄
- 0 前言
- 1 馬爾科夫鏈
- 2 隱馬爾科夫模型
- 3 HMM預測股票
- 4 最后
0 前言
不少同學讓我出一起HMM的教學文章,學長為了滿足各位同學的要求,寫下此文
1 馬爾科夫鏈
隱馬爾科夫模型是自然語言處理中很重要的一種算法。在此之前,我們首先給大家介紹馬爾科夫鏈。馬爾科夫鏈,因安德烈·馬爾科夫得名,是指數學中具有馬爾科夫性質的離散事件的隨機過程。在給定當前知識或信息的情況下,過去對于預測未來是無關的。每個狀態的轉移只依賴于之前的N個狀態,這個過程被稱為1個n階的模型。其中n是影響轉移狀態的數目。最簡單的馬爾科夫過程就是一階過程,每一個狀態的轉移只依賴于其之前的哪一個狀態。用數學的表達式表示就是如下所示:
假設天氣服從馬爾科夫鏈:
轉移矩陣
那么,從今天開始,在遙遠的未來的某天,晴陰的概率分布是什么?
其實,不管是今天是晴天,還是陰天,其實很多天之后的晴陰分布收斂到一個固定分布。這個固定分布就是我們熟悉的穩態分布。因此,我們就為上面的一階馬爾科夫過程定義一以下三個部分:
- 1、狀態:晴天、陰天
- 2、初始向量:定義系統在時間為0的時候的狀態概率
- 3、狀態轉移矩陣:每種天氣轉換的概率。所有的能被這樣描述的系統就是一個馬爾科夫過程。
但是
以上出現一個明顯的缺陷,也就是前后關系的缺失,帶來了信息的缺失:例如我們經常玩的股市,如果只是觀測市場,我們只能知道當天的價格,成交量等信息,但是并不知道當前的股市是處于什么狀態。
在這種情況下我們有兩個狀態集合,一個是可以觀察到的狀態集合;另一個是一個隱藏的狀態集合。我們希望能夠找到一個算法可以根據股市價格的成交量狀況和馬爾科夫假設來預測股市的狀況。基于上面我們提到的情況下,我們可以觀察到狀態序列和隱藏的狀態序列是概率相關的。因此,我們可以將這種類型的過程建模為一個有隱藏的馬爾科夫過程和一個與這個隱馬爾科夫過程概率相關的并且可以觀察到的狀態集合,這就是我們今天要介紹的隱馬爾科夫模型(HMM)。
接下學長來為大家詳細介紹隱馬爾科夫模型。
2 隱馬爾科夫模型
隱馬爾科夫模型是一種統計模型,用來描述一個含有隱含層未知參數的馬爾科夫過程。但是其中最大的難點就是從可觀察的參數中確定該過程的隱含參數,然后利用這些參數來作進一步分析。我們以日常的投骰子為例來解釋隱馬爾科夫模型:假設有三個不同的骰子(6面、4面、8面),每次先從三個骰子里面選擇一個,每個骰子選中的概率為1/3,如下圖所示,重復上述過程,得到一串數值[1,6,3,5,2,7]。這些可觀測變量組成可觀測狀態鏈。同時,在隱馬爾可夫模型中還有一條由隱變量組成的隱含狀態鏈,在本例中即骰子的序列。比如得到這串數字骰子的序列可能為[D6, D8, D8, D6, D4, D8]。
具體如下:
隱含狀態轉換示意圖
3 HMM預測股票
這次使用HMM算法來進行股票預測,使用昨天的股票數據來預測今天是否漲跌。
import tushare as tstoken = '' # 設置tocken pro = ts.pro_api(token) # 初始化pro接口 # 獲取數據 df_gldq = pro.daily(ts_code='000651.sz', start_date='20201210', end_date='20210513')df_gldq.sort_values(by='trade_date', inplace=True) # 打印數據 df_gldq.to_excel('data/stock.xls')首先使用tushare模塊來獲取數據。token是自己獲取的,ts_code決定哪支股票,還有時間區間以及排序,最后寫入stock.xls文件中。
#數據處理 df = pd.read_excel("data/stock.xls") print("原始數據的大小:", df.shape) print("原始數據的列名", df.columns)df['trade_date'] = pd.to_datetime(df['trade_date']) df.reset_index(inplace=True, drop=False) df.drop(['index', 'ts_code', 'open', 'high', 'low' , 'pre_close', 'change', 'pct_chg', 'amount'], axis=1, inplace=True) #df['trade_date'] = df['trade_date'].apply(datetime.datetime.toordinal) print(df.head()) dates = df['trade_date'][1:] close_v = df['close'] volume = df['vol'][1:] diff = np.diff(close_v) #獲得輸入數據 X = np.column_stack([diff, volume]) print("輸入數據的大小:", X.shape) #(1504, 2)min = X.mean(axis=0)[0] - 8*X.std(axis=0)[0] #最小值 max = X.mean(axis=0)[0] + 8*X.std(axis=0)[0] #最大值 X = pd.DataFrame(X) #異常值設為均值 for i in range(len(X)): #dataframe的遍歷if (X.loc[i, 0]< min) | (X.loc[i, 0] > max):X.loc[i, 0] = X.mean(axis=0)[0]#數據集的劃分 X_Test = X.iloc[:-30] X_Pre = X.iloc[-30:] print("訓練集的大小:", X_Test.shape) #(1474, 2) print("測試集的大小:", X_Pre.shape) #(30, 2)接下來是數據的預處理。獲取特征因子與標簽,歸一化、異常值處理、數據集劃分等等。
model = GaussianHMM(n_components=8, covariance_type='diag', n_iter=1000, min_covar=0.1) model.fit(X_Test)expected_returns_volumes = np.dot(model.transmat_, model.means_) expected_returns = expected_returns_volumes[:,0] predicted_price = [] #預測值 current_price = close_v.iloc[-30] for i in range(len(X_Pre)):hidden_states = model.predict(X_Pre.iloc[i].values.reshape(1,2)) #將預測的第一組作為初始值predicted_price.append(current_price+expected_returns[hidden_states])current_price = predicted_price[i]然后是利用HMM做股票預測
x = dates[-29: ] y_act = close_v[-29:] y_pre = pd.Series(predicted_price[:-1]) plt.figure(figsize=(8,6)) plt.plot_date(x, y_act,linestyle="-",marker="None",color='g') plt.plot_date(x, y_pre,linestyle="-",marker="None",color='r') plt.legend(['Actual', 'Predicted']) plt.show()將預測股票走勢折線圖與股票真實折線圖做對比
可以看出預測的股票曲線雖然無法完全擬合真實股票走勢,但是大體的趨勢是一致的。另外值得一提的是,很多股票預測實驗預測值與真實值貼的很緊密,這一般都是用今天的信息預測今天漲跌了,這種預測是無意義的。
4 最后
總結
以上是生活随笔為你收集整理的HMM隐马尔科夫模型及股票预测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创建线程的第二种方法(实现Runnabl
- 下一篇: 在mysql表中如何变换列和行_在SQL