這是機器學習系列的第一篇文章。機器學習
本文將使用Python
及scikit-learn
的線性迴歸預測Google的股票走勢。請千萬別指望這個示例可以讓你成爲股票高手。下面按逐步介紹如何進行實踐。函數
本文使用的數據來自www.quandl.com
網站。使用Python
相應的quandl
庫就能夠經過簡單的幾行代碼獲取到咱們想要的數據。本文使用的是其中的免費數據。利用下面代碼就能夠拿到數據:學習
import quandl df = quandl.get('WIKI/GOOGL')
其中WIKI/GOOGL
是數據集的ID,能夠在網站查詢到。不過我發現新版本的Quandl
要求用戶在其網站註冊獲取身份信息,而後利用身份信息才能讀取數據。這裏用到的WIKI/GOOGL
數據集屬於舊版本接口提供的數據,不須要提供身份信息。測試
經過上面代碼,咱們把數據獲取到,並存放在df
變量中。默認地,Quandl
獲取到的數據以Pandas
的DataFrame
存儲。所以你能夠經過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/完整代碼。
本文來自同步博客