iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 6
1
Google Developers Machine Learning

AI可以分析股票嗎?系列 第 6

股票預測初探 :: 只有過程沒有結果~嗚嗚

  • 分享至 

  • twitterImage
  •  

零、引言

上一篇我們提到了NN模型的三個分類 :: FCCNN以及RNN
那我們到底要挑哪一個來當我們的模型呢?

答案是,沒有一定

什麼鬼答案? 這我也會!! 別急,我的意思是說,你可以都用看看,或是...

  • CNN+FC
  • CNN+RNN
  • RNN+FC
  • CNN+RNN+FC
  • 甚至...平行的LSTM混合輸出到一個大的LSTM中再預測...等,像是拼積木一般隨機組合

哇! 這也太多了吧? 到底怎麼挑啊? 很簡單,學習從模仿開始
上網爬了一下文,可以知道現今最強的RNN模型無非就是LSTM
它的特殊架構我就不提了。所以鑑於此,今天的實作會先從這個
最單純的RNN延伸模型 -- LSTM下手,讓我們敬請期待吧!

一、Kaggle API下載 Dataset

還記得幾篇之前提過ML三寶嗎? Dataset、Model和Computer ~
現在我們的Computer有了(GCP上的VM),Model決定了(LSTM),剩下的就是Dataset
而Kaggle正符合我們目前所需

Kaggle 是一個比賽的平台,內容通常以數據建模、分析為主,想當然上面有海量的資料集囉~
所以非常推薦每個人都去了解一下Kaggle的生態。這邊提供一個Kaggle API是為了方便下載數據用,對於較大的Dataset也是建議使用API下載,那麼話不多說,上SOP :

0. 安裝API

  • 安裝API
    • $sudo pip3 install kaggle

1. 申請金鑰

現在都喜歡搞金鑰嗎? 很麻煩耶! 為什麼要申請金鑰? 就只是因為你想下載kaggle的Dataset就必須登入而已

  • a. 到網址 : https://www.kaggle.com/<username>/account
  • b. 找到Create API Token下載並把它放到~/.kaggle/裡面
  • c. 將該檔案更改權限
    • chmod 600 ~/.kaggle/kaggle.json
  • d. 測試
    • $kaggle

2. 下載Dataset

  • 我先來看看跟股票有關的Dataset有哪些吧!
    • $kaggle datasets list -s stock
  • 可以選一個下載囉! (我先選daily-historical-stock-prices-1970-2018這個)
    • $kaggle datasets download ehallmar/daily-historical-stock-prices-1970-2018
    • $unzip daily-historical-stock-prices-1970-2018.zip

二、拿到Dataset,開始訓練...?

不,還早。

我知道我下的標題很不好,但確實很多人以為蒐集完三寶就可以開始把Dataset丟到Model裡面訓練。
但事情往往沒這麼容易。 的確,光是蒐集Dataset這點就是一個很大的難關,儘管你能夠拿到別人幫你蒐集的資料,但他所蒐集的資料格式、資料內容、甚至資料來源都不一定是你想要的。

  • 補充::在Google Study Jam的課程中有提到...
    • 我們要蒐集怎麼樣的資料、model pre-train
      • How Google does Machine LearningIt's all about data和下面幾個
    • 維持資料正規的重要性
      • Launching into Machine LearningGeneralization and Sampling的章節

->所以通常我們還要多做一步 :: 資料預處理

預處理有哪些步驟?

    1. 資料提取,刪掉不需要的資訊(如股票名稱、K線的高低峰)
    1. 資料正規化,目的是防止訓練過程中的梯度爆炸或是梯度消失問題
    • 最常見的正規化就是將所有的資料正規到0-1之間

我們先來看一看daily-historical-stock-prices-1970-2018 dataset長什麼樣子吧!

  • historical_stocks.csv
    • 單純地描述有哪些股票資訊在這裡面
    • 其維度是 6460 rows × 5 columns 代表有6460家公司的5個公司資訊
  • historical_stock_prices.csv
    • 記錄這6460家公司從2013年開始的日K資料至2018
    • 維度超級大! 有 20973889 rows × 8 columns 記錄每日開始價格、結束價格、...等資訊

現在知道了這個Dataset的長相之後,我們只要取我們關心的資料即可。
在此先嘗試我們所要的資料是adj_close價格,就是「adjusted closing price」的資訊即可。
這邊我所做的處理是將自己前30天的資料當作input,第30天的資料當作答案。

因為資料說實在超大,我希望切開來用TFRecord去存,以下程式碼片段所做的事情就是將資料讀進來、正規到0-1,最後分段存入TFRecord資料(然後也超~級~久~

# Create TFRecord
import os
import tensorflow as tf

def _bytes_feature(value):
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=value))

def _int64_feature(value):
    return tf.train.Feature(int64_list=tf.train.Int64List(value=value))

def _float32_feature(value):
    return tf.train.Feature(float_list=tf.train.FloatList(value=value))

def create_tfrecords(days, stock_sc, save_name):
    stock_sc = np.asarray(stock_sc, np.float32)
    max_days = len(stock_sc)
    with tf.python_io.TFRecordWriter(save_name) as writer:
        for i in range(days, max_days):
            x = stock_sc[i-days:i, 0]
            y = stock_sc[i, 0]
            feature = {
                'x': _bytes_feature([x.tostring()]),
                'y': _float32_feature([y])}
            example = tf.train.Example(features=tf.train.Features(feature=feature))
            writer.write(example.SerializeToString())
            
# Data Normalization
from sklearn.preprocessing import MinMaxScaler

companies = names.ticker.unique()

scaler = MinMaxScaler()
days_before = 30
for company in companies:
    stock = prices.loc[prices['ticker'] == company]
    training_data = stock[['adj_close']].values
    # print(training_data.shape)
    try:
        ### scaler
        get_sc = scaler.fit_transform(training_data)
        # print(get_sc)
        create_tfrecords(days=days_before, stock_sc=get_sc, save_name='./generate_stock/'+company)
    except:
        print(company, training_data.shape)

三、開始訓練

我其實不確定自己訓練得對不對,明天再來看看怎麼樣驗證吧! 哈哈哈

Read TFRecord

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import os
reshape_size = 30
batch_size = 200
epochs = 20

def extract_features(example, reshape_size):
    features = tf.parse_single_example(
        example,
        features={
            'x': tf.FixedLenFeature([], tf.string),
            'y': tf.FixedLenFeature([], tf.float32),
        }
    )
    stock = tf.decode_raw(features['x'], tf.float32)
    stock = tf.reshape(stock, [reshape_size])
    stock = tf.cast(stock, tf.float32)
    stock = tf.expand_dims(stock, -1)
    label = features['y']
    return stock, label

tfrecords_path = './generate_stock/AEP'
dataset = tf.data.TFRecordDataset(tfrecords_path)
dataset = dataset.map(lambda x: extract_features(x, reshape_size))
dataset = dataset.shuffle(buffer_size=1000)
dataset = dataset.batch(batch_size, drop_remainder=True)
dataset = dataset.repeat()
train_gen = dataset.make_initializable_iterator()

Create Model

# LSTM Training
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout

model = Sequential()

model.add(LSTM(units = 50, return_sequences = True, input_shape = (reshape_size, 1)))

# model.add(LSTM(units = 92, return_sequences = True))
# model.add(Dropout(0.2))

# model.add(LSTM(units = 92, return_sequences = True))
# model.add(Dropout(0.2))

model.add(LSTM(units = 30, return_sequences = False))

model.add(Dense(units = 1))
model.compile(optimizer = 'adam', loss = 'mean_squared_error')

Training

with tf.Session() as sess:
    sess.run(train_gen.initializer)
    train = model.fit(train_gen, epochs = epochs, batch_size = batch_size, steps_per_epoch=100)

在Testing的時候,我有點後悔我將Data存成TFRecord,因為我對它其實並不熟悉,結果現在無法很順利地進行下去。

  • 就直接查看loss而言,根本無法判定

或許我試一試先不用TFRecord的方式來一遍好了Orz
今天先這樣~ 撤!

參考

Stock Price Prediction Using Attention-based Multi-Input LSTM


上一篇
股票預測需要什麼樣的NN模型?
下一篇
股票預測二訪 :: 簡單測試及修正小問題
系列文
AI可以分析股票嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
彭偉鎧
iT邦研究生 3 級 ‧ 2019-09-08 00:06:16

你的股票資料依據是K線圖,K線圖是四個數值(當日收、開盤、最高、最低價)價組成,所以你需要抓每天四個數字來組成K線,單純抓K線只是個圖而已,你的那三個要素的其中兩個FC、CNN兩個抓取資料庫時,會不知道該抓哪個數值,到後面做RNN迴歸分析的時候,你的函數會無法建立的。

以上是我個人看了之後的一些看法,給您參考!

感謝您的回覆以及意見,我上方的網路結構沒有仔細說明,其實它並沒有使用到CNN和FC,只有單純的LSTM。

我上面只有取用每日的「調整後收盤價格」來做預測,只是單純想要看看它的效果。

之後如果要加入CNN,會在思考其他方式,,感謝您~!

我要留言

立即登入留言