Files
V20pyPro/ML_research.py
2018-05-19 02:18:43 -07:00

304 lines
11 KiB
Python

import os
import numpy as np
import pandas as pd
from pandas.plotting import autocorrelation_plot
from statsmodels.tsa.arima_model import ARIMA
from keras.models import Sequential
from keras.layers import LSTM, Dense
from sklearn.preprocessing import MinMaxScaler, normalize
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_squared_error
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import (AdaBoostRegressor, BaggingRegressor,
ExtraTreesRegressor, GradientBoostingRegressor,
RandomForestRegressor)
import tensorflow as tf
from tensorflow.contrib import rnn
import matplotlib.pyplot as plt
file = 'history/AUD_JPY_D.csv'
folder = 'history/'
def walk_folder(folder):
all_files = list()
for files in os.walk(folder):
for f in files[2]:
f = os.path.join(folder, f)
all_files.append(f)
return all_files
# TODO: test this some more, it works with Keras and sklearn; but had trouble with TF.
def split_data(X, y, n, split, o):
m = int(n * split)
X_train, X_test = X[0:m], X[m:n-o]
y_train, y_test = y[o:m+o], y[m+o:n]
return X_train, X_test, y_train, y_test
def tf_nn_research(file, epochs=10, split=0.6, o=1):
# import data and clean it for processing
df = pd.read_csv(file)
df = df[['Close', 'Open','High', 'Low']]
n = df.shape[0]
p = df.shape[1]
data = df.values
# Training and test data; split_data doesn't work too well with TF atm
train_start = 0
train_end = int(0.6*n)
test_start = train_end + 1
test_end = n
data_train = data[np.arange(train_start, train_end), :]
data_test = data[np.arange(test_start, test_end), :]
# Scale data
scaler = MinMaxScaler(feature_range=(-1, 1))
scaler.fit(data_train)
data_train = scaler.transform(data_train)
data_test = scaler.transform(data_test)
# Build X and y
X_train = data_train[:, 1:]
y_train = data_train[:, 0]
X_test = data_test[:, 1:]
y_test = data_test[:, 0]
# length of training data
m = X_train.shape[1]
# neurons in each layer
neurons_1 = 1024
neurons_2 = 512
neurons_3 = 256
neurons_4 = 128
# session
sess = tf.InteractiveSession()
# Placeholders
X = tf.placeholder(dtype=tf.float32, shape=[None, m])
Y = tf.placeholder(dtype=tf.float32, shape=[None])
# initializers
sigma = 1
W = tf.variance_scaling_initializer(mode="fan_avg", distribution="uniform", scale=sigma)
b = tf.zeros_initializer()
# hidden weights
W_hidden_1 = tf.Variable(W([m, neurons_1]))
b_hidden_1 = tf.Variable(b([neurons_1]))
W_hidden_2 = tf.Variable(W([neurons_1, neurons_2]))
b_hidden_2 = tf.Variable(b([neurons_2]))
W_hidden_3 = tf.Variable(W([neurons_2, neurons_3]))
b_hidden_3 = tf.Variable(b([neurons_3]))
W_hidden_4 = tf.Variable(W([neurons_3, neurons_4]))
b_hidden_4 = tf.Variable(b([neurons_4]))
# output weights
W_out = tf.Variable(W([neurons_4, 1]))
b_out = tf.Variable(b([1]))
# hidden layers
hidden_1 = tf.nn.relu(tf.add(tf.matmul(X, W_hidden_1), b_hidden_1))
hidden_2 = tf.nn.relu(tf.add(tf.matmul(hidden_1, W_hidden_2), b_hidden_2))
hidden_3 = tf.nn.relu(tf.add(tf.matmul(hidden_2, W_hidden_3), b_hidden_3))
hidden_4 = tf.nn.relu(tf.add(tf.matmul(hidden_3, W_hidden_4), b_hidden_4))
# transpose the output layer
out = tf.transpose(tf.add(tf.matmul(hidden_4, W_out), b_out))
# cost function
mse = tf.reduce_mean(tf.squared_difference(out, Y))
# optimizer
opt = tf.train.AdamOptimizer().minimize(mse)
# init
sess.run(tf.global_variables_initializer())
# start plot
plt.ion()
fig = plt.figure()
ax1 = fig.add_subplot(111)
line1, = ax1.plot(y_test)
line2, = ax1.plot(y_test * 0.5)
plt.show()
# fit neural net
batch_size = 1
mse_train = []
mse_test = []
# run the network
for e in range(epochs):
# shuffle training data
shuffle_indices = np.random.permutation(np.arange(len(y_train)))
X_train = X_train[shuffle_indices]
y_train = y_train[shuffle_indices]
# Minibatch training
for i in range(0, len(y_train) // batch_size):
start = i * batch_size
batch_x = X_train[start:start + batch_size]
batch_y = y_train[start:start + batch_size]
# run optimizer with batch
sess.run(opt, feed_dict={X: batch_x, Y: batch_y})
# show progress
if np.mod(i, 50) == 0:
# MSE train and test
mse_train.append(sess.run(mse, feed_dict={X: X_train, Y: y_train}))
mse_test.append(sess.run(mse, feed_dict={X: X_test, Y: y_test}))
print('MSE Train: ', mse_train[-1])
print('MSE Test: ', mse_test[-1])
# prediction
pred = sess.run(out, feed_dict={X: X_test})
line2.set_ydata(pred)
plt.title('Epoch ' + str(e) + ', Batch ' + str(i))
plt.pause(0.10)
plt.savefig('graphs/%s_%s.png' %(str(e), str(i)))
# Xcols=20 returns better results than Xcols=1, with o=5
# Xcols=20 and o=1 returns 90-95% accuracy for every model
def ensemble_research(file, split=0.6, o=5, Xcols=1):
"""Xcols == 1 or 20; 1 for 'Open' or 20 for all input values"""
# import, split, and prepare data
df = pd.read_csv(file)
n = len(df)
if Xcols == 1:
y = df['Close'].values.reshape(n, 1)
X = df['Open'].values.reshape(n, 1)
X_train, X_test, y_train, y_test = split_data(X, y, n, split, o)
elif Xcols == 20:
y = df['Close'].values
a = df['Close'].mean()
df.fillna(a, inplace=True)
for col in df.columns:
if 'Unnamed' in col:
df.drop(col, axis=1, inplace=True)
df.drop('Close', axis=1, inplace=True)
X = df[df.columns.tolist()].values
X_train, X_test, y_train, y_test = split_data(X, y, n, split, o)
# instantiate the models to be explored
models = [AdaBoostRegressor(),
BaggingRegressor(),
DecisionTreeRegressor(),
ExtraTreesRegressor(),
GradientBoostingRegressor(),
RandomForestRegressor()]
# set and run models
scores = list()
for model in models:
model.fit(X_train, y_train)
yhat = model.predict(X_test)
score = model.score(X_test, y_test)
scores.append(score)
plt.plot(yhat, label='predictions')
plt.plot(y_test, label='real data')
plt.title(str(score))
plt.legend()
plt.show()
# multivariate LSTM in Keras (OHL, plus technical indicators; 20 columns in total)
def LSTMulti_research(file, o=5, split=0.6, show_loss=False):
# import and clean the dataframe as needed, filling in any missing data
df = pd.read_csv(file)
n = len(df)
y = df['Close'].values
a = df['Close'].mean()
df.fillna(a, inplace=True)
for col in df.columns:
if "Unnamed" in col:
df.drop(col, axis=1, inplace=True)
df.drop('Close', axis=1, inplace=True)
X = df[df.columns.tolist()].values
# split data and reshape input values
X_train, X_test, y_train, y_test = split_data(X,y,n,split,o)
X_train = np.reshape(X_train, (X_train.shape[0], 1, X_train.shape[1]))
X_test = np.reshape(X_test, (X_test.shape[0], 1, X_test.shape[1]))
model = Sequential()
model.add(LSTM(20, input_shape=(1,20,), activation='linear'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
history = model.fit(X_train, y_train, epochs=50, batch_size=1,
validation_data=(X_test, y_test), verbose=2, shuffle=False)
score = model.evaluate(X_test, y_test)#history['']
if show_loss == True:
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='test')
plt.title('LSTMulti Score' + str(score))
plt.legend()
plt.show()
else:
plt.plot(y_test, label='prices')
plt.plot(model.predict(X_test), label='predictions')
plt.title('LSTMulti Score ' + str(score))
plt.legend()
plt.show()
def plot_Ridge(file, o=5, split=0.6):
df = pd.read_csv(file)
n = len(df)
X = df['Open'].values.reshape(n,1)
y = df['Close'].values.reshape(n,1)
X_train, X_test, y_train, y_test = split_data(X, y, n, split, o)
model = Ridge()
model.fit(X_train, y_train)
predictions = model.predict(X_test)
score = model.score(X_test, y_test)
print("Model score: %.2f" % score)
plt.plot([x for x in range(len(X_test))], predictions, label='predictions')
plt.plot([x for x in range(len(X_test))], y_test, label='actual data')
plt.legend()
plt.show()
def plot_LinearRegression(file, o=5, split=0.6):
# o == offset, how far away is the prediction we want to make?
# changing o from 5 to 1 improves prediction accuract from 81% to 94%
df = pd.read_csv(file)
n = len(df)
# convert pd.Series to np.ndarrays now for manipulation
X = df['Open'].values.reshape(n,1)
y = df['Close'].values.reshape(n,1)
# slight offset, X[t] is used to 'predict' y[t+o]
X_train, X_test, y_train, y_test = split_data(X,y,n,split,o)
# check to make sure the two sets of arrays match in length
print("Training sizes: X: %.2f, y: %.2f" % (X_train.shape[0], y_train.shape[0]))
print("Test sizes: X: %.2f, y: %.2f" % (X_test.shape[0], y_test.shape[0]))
model = LinearRegression()
model.fit(X_train, y_train)
predictions = model.predict(X_test)
score = model.score(X_test, y_test)
print("Model score: ", score)
plt.plot([x for x in range(len(X_test))], predictions, label='predictions')
plt.plot([y for y in range(len(y_test))], y_test, label='real data')
plt.legend()
plt.show()
#arima_research(file, 'Close', 5, 1, 1) # best fit
def arima_research(file, series, p, d, q):
# prepare data
df = pd.read_csv(file)
X = df[series].values
size = int(len(X) * 0.6)
train, test = X[:size], X[size:]
history = [x for x in train]
predictions = list()
# fit the model and make predictions
for t in range(len(test)):
model = ARIMA(history, order=(p,d,q))
model_fit = model.fit(disp=0)
#print(model_fit.summary())
output = model_fit.forecast()
yhat = output[0]
predictions.append(yhat)
obs = test[t]
history.append(obs)
err = abs(yhat - obs)
print("Predicted: %.3f, Expected: %.3f, Error: %.3f" % (yhat, obs, err))
# print summary and graph results
error = mean_squared_error(test, predictions)
print("Test MSE: %.3f" % (error))
plt.plot(test, label='actual prices')
plt.plot(predictions, label='predicted prices')
plt.legend()
plt.show()