機器學習:使用scikit-learn的線性迴歸預測Google股票

這是機器學習系列的第一篇文章。機器學習

本文將使用Pythonscikit-learn的線性迴歸預測Google的股票走勢。請千萬別指望這個示例可以讓你成爲股票高手。下面按逐步介紹如何進行實踐。函數

準備數據

本文使用的數據來自www.quandl.com網站。使用Python相應的quandl庫就能夠經過簡單的幾行代碼獲取到咱們想要的數據。本文使用的是其中的免費數據。利用下面代碼就能夠拿到數據:學習

import quandl
df = quandl.get('WIKI/GOOGL')

其中WIKI/GOOGL是數據集的ID,能夠在網站查詢到。不過我發現新版本的Quandl要求用戶在其網站註冊獲取身份信息,而後利用身份信息才能讀取數據。這裏用到的WIKI/GOOGL數據集屬於舊版本接口提供的數據,不須要提供身份信息。測試

經過上面代碼,咱們把數據獲取到,並存放在df變量中。默認地,Quandl獲取到的數據以PandasDataFrame存儲。所以你能夠經過DataFrame的相關函數查看數據內容。以下圖,使用print(df.head())能夠打印表格數據的頭幾行內容。網站

 

預處理數據

從上面圖片咱們看到數據集提供了不少列字段,例如Open記錄了股票開盤價、Close記錄了收盤價、Volumn記錄了當天的成交量。帶Adj.前綴的數據應該是除權後的數據。spa

咱們並不須要用到全部的字段,由於咱們的目標是預測股票的走勢,所以須要研究的對象是某一時刻的股票價格,這樣的有比較性。因此咱們以除權後的收盤價Adj. Close爲研究對象來描述股票價格,也就是咱們選擇它做爲將要被預測的變量。unix

接下來須要考慮關於什麼變量跟股票價格有關。下面代碼選取了幾個可能影響Adj. Close變化的字段做爲迴歸預測的特徵,並對這些特徵進行處理。詳細步驟請閱讀註釋。code

import math
import numpy as np

# 定義預測列變量,它存放研究對象的標籤名
forecast_col = 'Adj. Close'
# 定義預測天數,這裏設置爲全部數據量長度的1%
forecast_out = int(math.ceil(0.01*len(df)))

# 只用到df中下面的幾個字段
df = df[['Adj. Open', 'Adj. High', 'Adj. Low', 'Adj. Close', 'Adj. Volume']]

# 構造兩個新的列
# HL_PCT爲股票最高價與最低價的變化百分比
df['HL_PCT'] = (df['Adj. High'] - df['Adj. Close']) / df['Adj. Close'] * 100.0
# HL_PCT爲股票收盤價與開盤價的變化百分比
df['PCT_change'] = (df['Adj. Close'] - df['Adj. Open']) / df['Adj. Open'] * 100.0

# 下面爲真正用到的特徵字段
df = df[['Adj. Close', 'HL_PCT', 'PCT_change', 'Adj. Volume']]
# 由於scikit-learn並不會處理空數據,須要把爲空的數據都設置爲一個比較難出現的值,這裏取-9999,
df.fillna(-99999, inplace=True)
# 用label表明該字段,是預測結果
# 經過讓與Adj. Close列的數據往前移動1%行來表示
df['label'] = df[forecast_col].shift(-forecast_out)

# 最後生成真正在模型中使用的數據X和y和預測時用到的數據數據X_lately
X = np.array(df.drop(['label'], 1))
# TODO 此處尚有疑問
X = preprocessing.scale(X)
# 上面生成label列時留下的最後1%行的數據,這些行並無label數據,所以咱們能夠拿他們做爲預測時用到的輸入數據
X_lately = X[-forecast_out:]
X = X[:-forecast_out]
# 拋棄label列中爲空的那些行
df.dropna(inplace=True)
y = np.array(df['label'])

上面代碼難點在理解label列的是如何生成的以及有什麼用。實際上這一列的第i個元素都是Adj. Close列的第i + forecast_out個元素。我想嘗試用簡單文字描述:這列的每一個數據是真實統計中的將來forecast_out天的收盤價。利用這一列的數據做爲線性迴歸模型的監督標準,讓模型學習出規律,而後咱們才能用之預測結果。orm

另外X = preprocessing.scale(X)這行代碼對X的數據進行規範化處理,讓X的數據服從正態分佈。(PS. 可是,我發現這種處理讓X的數據都發生了變化,所以沒法理解這樣作的緣由,以及爲何不會影響模型學習的結果。有知道答案的麻煩留言告告知。)對象

線性迴歸

上面咱們已經準備好了數據。能夠開始構建線性迴歸模型,並讓用數據訓練它。

# scikit-learn從0.2版本開始廢棄cross_validation,改用model_selection
from sklearn import preprocessing, model_selection, svm
from sklearn.linear_model import LinearRegression

# 開始前,先X和y把數據分紅兩部分,一部分用來訓練,一部分用來測試
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.2)

# 生成scikit-learn的線性迴歸對象
clf = LinearRegression(n_jobs=-1)
# 開始訓練
clf.fit(X_train, y_train)
# 用測試數據評估準確性
accuracy = clf.score(X_test, y_test) 
# 進行預測
forecast_set = clf.predict(X_lately)

print(forecast_set, accuracy)

上述幾行代碼就是使用scikit-learn進行線性迴歸的訓練和預測過程。咱們能夠經過測試數據計算模型的準確性accuracy,而且經過向模型提供X_lately計算預測結果forecast_set

我運行獲得的結果以下:

 
 

須要注意到的這個準確性accuracy並不表示模型預測100天的數據有97天是正確的。它表示的是線性模型可以描述統計數據的信息的一個統計概念。在後續的文章我可能會對這個變量進行一些討論。

繪製走勢

最後咱們使用matplotlib讓數據可視化話。詳細步驟看代碼註釋。

import matplotlib.pyplot as plt
from matplotlib import style
import datetime

# 修改matplotlib樣式
style.use('ggplot')

one_day = 86400
# 在df中新建Forecast列,用於存放預測結果的數據
df['Forecast'] = np.nan
# 取df最後一行的時間索引
last_date = df.iloc[-1].name
last_unix = last_date.timestamp()
next_unix = last_unix + one_day

# 遍歷預測結果,用它往df追加行
# 這些行除了Forecast字段,其餘都設爲np.nan
for i in forecast_set:
    next_date = datetime.datetime.fromtimestamp(next_unix)
    next_unix += one_day
    # [np.nan for _ in range(len(df.columns) - 1)]生成不包含Forecast字段的列表
    # 而[i]是隻包含Forecast值的列表
    # 上述兩個列表拼接在一塊兒就組成了新行,按日期追加到df的下面
    df.loc[next_date] = [np.nan for _ in range(len(df.columns) - 1)] + [i]

# 開始繪圖
df['Adj. Close'].plot()
df['Forecast'].plot()
plt.legend(loc=4)
plt.xlabel('Date')
plt.ylabel('Price')
plt.show()

運行代碼能夠獲得下圖。

 

上圖紅色部分爲採集到的已有數據,藍色部分爲預測數據。

點擊這裏查看http://www.javashuo.com/tag/完整代碼

本文來自同步博客

相關文章
相關標籤/搜索