2017年6月20日 星期二

[深度學習練習] [Deep Learning Practice] 神經網路入門(十二)- 遞歸神經網路 X TFLearn X 台指分K

上一篇我們已經把 lstm 訓練好的 model 儲存起來,

這一篇,是深度學習的最後一篇,我們要寫一個回測的方法,

看看我們的模型到底學到什麼。

------------------------------------------------------------------------------------------------------------

這邊是廢話,

基本上,最近就是買了 Alexa 之後迷上智慧管家,

買的那一週,立刻寫了用 Alexa 控制家電的程式,

但因為要在樹莓派上開小伺服器接收資料,

而且操作很不直覺,舉例來說,要叫他拍照,

要說 Alexa ask Raspberry Pi to take a picture,

真的很麻煩,發展性又不強,所以就決定自己寫一個在樹莓派上,




就是這樣,所以就一直懶得寫最後一集。

------------------------------------------------------------------------------------------------------------

六、參數及模型定義

我們這邊要先定義一些基本參數讓我們的 lstm model 可以被實體化

實體化之後,ㄗ用 TFLearn 的 load 將 model 內的 weight 儲存進來。

除此之外,我們也要去爬台股分 K 資料,這邊為了方便,

我直接把整理好的分 K 分享給大家。 --> google drive share link



儲存好正確答案後,

我們也要定義要回測的時間,

記得兩篇前我們是用 2014 ~ 2016 資料來訓練模型,

我們這次就要回測就要避開當初訓練的資料

import numpy as np
import tflearn
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.estimator import regression
from tflearn.layers.recurrent import lstm
from datetime import date, timedelta
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd

LR = 1e-3

# 最近才發現 pandas 有 read_pickle 功能!讚讚!

df = pd.read_pickle('../tkinter/data/TWfuture_min_data_2014_adjusted.pickle')

start_day = date(2017,1,3)
end_day = date(2017,3,27)
interval = timedelta(days=1)

span_day = end_day-start_day
span = int(span_day.days)
last_day = start_day

all_deposit = 0

定義完之後,我們還要初始化一個 model 讓等等 load model 時,

有地方放東西。

def lstm_model(input_size,time_steps,output_size):

    network = input_data(shape=[None,time_steps,input_size], name='input')
    network = lstm(network,128, dropout=0.8,forget_bias=0.5)

    network = fully_connected(network, 32, activation='relu')
    network = dropout(network, 0.8)

    network = fully_connected(network, output_size, activation='softmax')
    network = regression(network, optimizer='adam', learning_rate=LR,

                         loss='categorical_crossentropy', name='targets')
    model = tflearn.DNN(network, tensorboard_dir='log', tensorboard_verbose=1)

    return model

model = lstm_model(8,15,3)
model.load('lstm_15to15.tflearn')

到這邊就定義完了。

可以開始跑回測了!期待吧 lol

------------------------------------------------------------------------------------------------------------

七、回測及視覺化


for _ in range(span):

    deposit = 0 # 初始化金錢


    put = [0 for _ in range(15)] # 前 15 分鐘不做預測
    non = [0 for _ in range(15)]
    call = [0 for _ in range(15)]


    start_day += interval
    df_today = df[df["date"]==start_day] # 取出當天的資料
    app = [0 for _ in range(len(df_today)-135)] # 這邊我真的忘記我當初在做什麼


    if len(df_today) > 0:

        
        # 取出技術指標

        y_price = df[df["date"]==last_day]["close"][-1]
        df_today.loc[:,'open_adjusted'] = (df_today["open"] - y_price)*100/y_price
        df_today.loc[:,"high_adjusted"] = (df_today["high"] - y_price)*100/y_price
        df_today.loc[:,"low_adjusted"] = (df_today["low"] - y_price)*100/y_price
        df_today.loc[:,"close_adjusted"] = (df_today["close"] - y_price)*100/y_price
        df_today.loc[:,"close_mvag20_adjusted"] = (df_today["close_mvag20"] - y_price)*100/y_price
        df_today.loc[df_today.index,"close_EMA5_adjusted"] = (df_today["EMA5"] - y_price)*100/y_price

        last_day = start_day
        print (start_day)

        for i in range(120):
            # 列出當初用來 train 的 columns,等等要當 input

            df_today_min = df_today[i:i+15][["open_adjusted","high_adjusted",

                         "low_adjusted","close_adjusted","close_mvag20_adjusted",
                         "close_EMA5_adjusted","K9","D9"]]

            X = np.array(df_today_min).reshape(-1,15,8)
            y = model.predict(X)
            put.append(y[0][0])
            non.append(y[0][1])
            call.append(y[0][2])


        put += app
        non += app
        call += app


        # 視覺化

        ax1 = plt.subplot2grid((2,1),(0,0))
        ax2 = plt.subplot2grid((2,1),(1,0), sharex= ax1)
        df_today['put'] = pd.Series(put, index= df_today.index)
        df_today['none'] = pd.Series(non, index= df_today.index)
        df_today['call'] = pd.Series(call, index= df_today.index)
        df_today[['call', 'put', 'none']][:135].plot(ax= ax2, linewidth=2, color=['r','g','b'])
        df_today['close'][:135].plot(ax= ax1, linewidth=2, color='k')



        # 定義 買與賣的時機以及會獲得的金錢
        for i in range(1,135):
            if put[i]>non[i] and put[i-1]<non[i-1]:

                #put
                earn = df_today["close"][i] - df_today["open"][i+15]
                deposit += earn
            elif call[i]>non[i] and call[i-1]<non[i-1]:

                #call
                earn = df_today["open"][i+15] - df_today["close"][i]
                deposit += earn
        print (deposit)
        all_deposit += deposit

        plt.show()

print (all_deposit) # 這個值等個幾天的圖之後,把上面 plt.show() comment out 在看


好!!!!

到這邊,算是寫完了。

可以來看一下,我們訓練出來的機器,到底在亂投資什麼。


2017 1 4 



















2017 1 5





















列了兩天,剩下大家可以自己看。

上面的子圖是期貨指數,下面子圖則是 call or put 的機率。

可以發現,我們的機器大概就是學到順勢交易的樣子,

都是在趨勢出來才會反應。

有趣的是,如果在紅色線一有起色(上揚)的時候,就進場的回測效果,

會非常好。

至於三個月下來的累積收益,就讓大家自己去看了。

------------------------------------------------------------------------------------------------------------

七、結果討論與未來規劃

okok ! 恭喜恭喜,十二堂亂學的練習都已經走完

還經歷了 tensorflow 的重大改版,哈哈。

希望大家做完之後,會對機器學習以及 tensorflow 的使用方法

有粗淺的了解。

更重要的是,理解想要分析一件事情的時候,會經過的每一個步驟。

決定目標、學習基礎知識、收集資料資料前處理資料處理設計演算法回測。



那接下來我們可以做些什麼呢?

不知道大家在跑兩篇前的分 K 資料前處理時,有沒有發現,

整理資料要很久,算一算 三年資料 每天五小時大概有十萬筆資料,

光是這樣的處理,我們筆電就很痛苦,

更何況實務上,幾千萬個 row 是很常會發生的事 QQ

所以如果要更上一層樓,

我們要把基礎再用強一點,如


1. 使用 Virtual Machine 跑資料 => 不會佔用筆電記憶體,需要就租,不要就刪除

2. 利用 IPython 快速處理資料 => 視覺化很快很直覺,資料可輸出成 notebook

3. Pyenv 版本管理 => 為不同的目標使用不同 Library 時,會需要使用不同版本 Python

4. 資料結構 => 幾千萬個 row 的時候,自定義 column data type 這個很重要

5. 甚至是 PEP 寫作規範 => 寫 code 更加整潔與漂亮


這些都是我們可以繼續去學的,

雖然與機器學習沒有關係,

但這些練習與機器學習並沒有衝突,

反而可以讓我們機器學習更佳厲害!

如果不想下這種功夫,也可以直接去 Kaggle 找題目來練習!



接下來呢,還在想要專注寫什麼東西,

基本上應該也就是拿一些之前做的亂寫,

可能是 LSTM 做編曲學習,

也可以是使用 Jieba 和貝葉斯做文章分類,

或者是分享最近最愛的樹莓派,

也可能是重新認真學韓文 QQ,哈哈哈哈!



廢話就到這,祝大家在機器學習的路上,一切順心。

導流一下製作交易系統的文章


------------------------------------------------------------------------------------------------------------

Reference

[1] Practical Machine Learning Problem

[2] 圖解機器學習

[3] Coursera - Machine Leanring 

[4] A tour of machine learning algorithms

12 則留言:

  1. 嗨你好,
    我看你在這個blog一系列關於deep learning 的文章,有些問題想要請教你
    我在上學期有上了一門deep learning的課,老師上課主要是在講數學跟演算法,另外有project讓我們實作,而我選擇了MNIST data進行實作。我想請問你,你是怎麼選擇應用的主題(e.g. 台指,水位)?又是怎麼把deep learning應用在這些主題上(以在MNIST應用為基礎去延伸)?我會deep learning這個工具,但是想不太到怎麼去應用....

    回覆刪除
    回覆
    1. 應該是任何事情都可以運用,我是找自己有興趣的領域去融合,
      像我水位是因為替代役單位需要用,台指是因為對金融市場有興趣。
      建議你可以想想自己有興趣的事物,再想想這件事情有沒有辦法被最佳化或是被預測,
      舉例像: NBA 比賽預測簽運彩、給機器學巴哈作曲、甚至是讓機器辨識誰回家了。

      刪除
  2. 這篇的model是以上一篇文章train出來的?
    以結果來說,即使loss未下降,準確率也沒有明顯上升
    但是以模型提供的結果下去做交易,理論上還是能有一定收穫的?
    還是說這篇的model有改變training的方式?

    回覆刪除
  3. 嗯,是上一篇的演算法 train 出來的。
    loss 和投資結果的差異是來自於,
    定義 loss function 和使用結果的方法不同,
    意思是,就算 loss 沒下降,只能說模型一直沒進步,
    但不能說他什麼都不會。

    回覆刪除
  4. 偶然發現你的文章
    非常感謝你的分享,這邊留言給你鼓勵
    剩下的我再來慢慢研讀0.0

    回覆刪除
  5. 偶然發現你的文章
    非常感謝你的分享,這邊留言給你鼓勵
    也是軟體工程師很喜歡你的文章

    回覆刪除
  6. 想問一下
    在PC上跑你的程式碼
    時常出現pandas.indexes 的import error
    要怎麼解決呢?(ex deeplearning_LSTM_for_TX 裡面的lstm_learning.py)
    (已經有用pip show pandas測過有安裝pandas了)

    回覆刪除
  7. 這個問題好像是 pandas 和 pickle 版本問題,抱歉QQ
    所以我現在都不喜歡用 pickle 了。
    有時候用pickle 就會搭配 virtualenv 確定共同開發的人都在同一個版本底下。
    import error 的話,你可以留個 email 給我,
    我可以 dump 我 DB 的 table 給你,應該可以讓你順利跑完 script

    回覆刪除