初始HMM及hmmlearn實現 - 知乎

一、初始HMM

隱馬爾科夫模型(Hidden Markov Model,簡稱HMM)是用來描述隱含未知參數的統計模型,HMM已經被成功於語音識別、文本分類、生物信息科學、故障診斷和壽命預測等領域。python

HMM能夠由三個要素組成: \lambda =(A,B,II),其中A爲狀態轉移機率矩陣,B爲觀測狀態機率矩陣,II爲隱藏狀態初始機率分佈。算法

HMM有兩個基本假設,一是齊次馬爾可夫性假設,隱馬爾可夫鏈t的狀態只和t-1狀態有關;二是觀測獨立性假設,觀測只和當前時刻狀態有關。網絡

HMM解決的三個問題:app

  • 一是機率計算問題,已知模型和觀測序列,計算觀測序列出現的機率,該問題求解的方法爲向前向後法;
  • 二是學習問題,已知觀測序列,估計模型的參數,該問題求解的方法爲鮑姆-韋爾奇算法
  • 三是預測問題(解碼問題),已知模型和觀測序列,求解狀態序列,該問題求解的方法爲動態規劃的維特比算法。【實例分析】

HMM的實現:python的hmmlearn類,按照觀測狀態是連續狀態仍是離散狀態,能夠分爲兩類。GaussianHMM和GMMHMM是連續觀測狀態的HMM模型;MultinomialHMM是離散觀測狀態的模型。學習

二、實例分析

(1)問題描述:股票預測問題,觀測值爲股票的漲幅值(當天收盤價-前一天收盤價)和成交量2種,隱藏狀態假定爲平、跌和漲3種,根據股票的歷史數據構建HMM,並進一步預測股票的收盤價。測試

(2)數據預處理:從原始數據中提取有用的列,並作異常值處理操做,獲得模型的數據數據,原始數據爲某支股票2013-2019的記錄數據,以下圖所示。flex

import datetime
import numpy as np
import pandas as pd
from matplotlib import cm, pyplot as plt
from hmmlearn.hmm import GaussianHMM
#數據處理
df = pd.read_excel("601668.SH.xlsx", header=0)
print("原始數據的大小:", df.shape)
print("原始數據的列名", df.columns)
df['日期'] = pd.to_datetime(df['日期'])
df.reset_index(inplace=True, drop=False)
df.drop(['index','交易日期','開盤價','最高價','最低價' ,'市值', '換手率', 'pe', 'pb'], axis=1, inplace=True)
df['日期'] = df['日期'].apply(datetime.datetime.toordinal)
print(df.head())
dates = df['日期'][1:]
close_v = df['收盤價']
volume = df['成交量'][1:]
diff = np.diff(close_v)
#得到輸入數據
X = np.column_stack([diff, volume])
print("輸入數據的大小:", X.shape)   #(1504, 2)

(3)異常值的處理:spa

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]

(4)模型的構建:3d

#數據集的劃分
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=3, covariance_type='diag', n_iter=1000) 
model.fit(X_Test)
print("隱藏狀態的個數", model.n_components)  #
print("均值矩陣")
print(model.means_)
print("協方差矩陣")
print(model.covars_)
print("狀態轉移矩陣--A")
print(model.transmat_)

均值矩陣:共三行,每一行表明一種隱藏層狀態(狀態0、一、2),每一行的兩個元素分別表明漲幅值的均值和成交量的均值。因爲該股票的變化不是特別大,所以結果不是特別明顯,但能夠觀察到狀態0均值爲負值,能夠解釋爲「跌」;狀態1均值最小,接近0,能夠解釋爲「平」,狀態2均值爲正,能夠解釋爲「漲」。excel

協方差矩陣:共三個協方差矩陣,分別對應三種隱藏層狀態。對角線的值爲該狀態下的方差,方差越大,表明該狀態的預測不可信。狀態0的方差約爲0.00255,方差最小,預測很是可信;狀態1的方差約爲0.0157,可信度居中;狀態2的方差爲0.1232,方差最大,最不可信。

狀態轉移矩陣:表明三個隱藏層狀態的轉移機率。能夠看出對角線的數值較大,即狀態0、一、2都傾向保持當前的狀態,意味該股票較穩。

(5)隱藏狀態劃分結果:

#訓練數據的隱藏狀態劃分
X_pic = np.column_stack([dates[:-30], hidden_states, X_Test])
for i in range(len(X_pic)):
    if X_pic[i, 1] == 0:
        plt.plot_date(x=X_pic[i, 0],y=X_pic[i,2],color='r')
    elif X_pic[i, 1] == 1:
        plt.plot_date(x=X_pic[i, 0],y=X_pic[i,2],color='purple')
    else:plt.plot_date(x=X_pic[i, 0],y=X_pic[i,2],color ='y')
plt.show()

(6)預測值計算:

將預測數據的第一組做爲初始數據,預測下一時段的股票漲幅值,以此類推預測該股票後三十組的價格。

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]

(7)預測結果展現:

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()

三、小結

  • 能夠看出,該預測結果的趨勢與真實值一致,但預測結果不佳。能夠經過增長訓練的數據量,並進行模型參數調優來提升預測的精度。
  • HMM應用場景:研究問題是基於序列的,好比時間序列或狀態序列;存在兩種狀態的意義,一種是觀測序列,一種是隱藏狀態序列。
  • 相比於RNN、LSTM等神經網絡序列模型,HMM進行預測的效果可能較劣,總之【股市有風險】

參考資料:hmmlearn官方文檔

https://hmmlearn.readthedocs.io/en/latest/hmmlearn.readthedocs.io
相關文章
相關標籤/搜索