If you have machine learning skill why not apply that skill to predict cryptocurrency prices because everybody talking about cryptocurrency these days. In this tutorial, I’m going to show you how to predict the Bitcoin price, but this can apply to any cryptocurrency. We’re gonna use a very simple model built with Keras in TensorFlow.

Keras is the easiest way to get started with Deep learning. It’s a great library. You can learn all about deep learning just from reading the Keras documentation.

In this tutorial, we’re gonna use bi-directional LSTM recurrent network. It’s basically a more advanced version of an RNN. That takes into account future values in sequence instead of just the past.

The dataset we are using is available at Bitcoin Historical Data. The first thing we do is importing all the necessary Python libraries.

from tensorflow.python.keras.layers import Bidirectional, Dropout, Activation, Dense, LSTM

from tensorflow.keras.models import Sequential
from tensorflow.python.keras.callbacks import EarlyStopping

from sklearn.preprocessing import MinMaxScaler

from datetime import date

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

For these first three lines is importing the relevant parts of Keras that we’re going to need for this model.

Data Processing


First, We are going to transform the data to get the average price grouped by the day and to see the usual DateTime format instead of timestamp.

data = pd.read_csv(path)

data['date'] = pd.to_datetime(data['Timestamp'], unit='s').dt.date

group = data.groupby('date')

day_price = group['Weighted_Price'].mean()

Normalization

The reason we want to normalize data is that our model will be able to converge faster. The data normalization is a step that we always perform in data pre-processing.It‘s a very important thing to do.

date1 = date(2016, 1, 1)
date2 = date(2018, 6, 25)

delta = date2 - date1
days_look = delta.days + 1


data = day_price[len(day_price) - days_look:len(day_price)]

scl = MinMaxScaler()

data = data.values.reshape(data.shape[0], 1)
scale_data = scl.fit_transform(data)

For time-series transform, it’s going to be from a [number of days X the number of features] that were the original array. We are going to convert that to the number of days per sample times by the number of features so we’re turning it from 2D array to a 3D array and this is just a preprocessing step so we can then feed it into our network.

SEQ_LEN = 50
WINDOW_SIZE = SEQ_LEN - 1

BATCH_SIZE=64

DROPOUT = 0.2


def load_data(data_raw, seq_len):
    data = []

    for index in range(len(data_raw) - seq_len):
        data.append(data_raw[index: index + seq_len])

    data = np.array(data)
    train_split = 0.8

    num_data = data.shape[0]

    num_train = int(train_split * num_data)

    data = np.array(data);

    x_train = data[:num_train, :-1, :]

    y_train = data[:num_train, -1, :]

    x_test = data[num_train:, :-1, :]
    y_test = data[num_train:, -1, :]

    return [x_train, y_train, x_test, y_test]


x_train, y_train, x_test, y_test = load_data(scale_data, SEQ_LEN)

Buile Model


We are building a three-layer recurrent network with 20% dropout at each layer to reduce overfitting in the training. The type of RNN we’re going to build is called a bidirectional LSTM network.

model = Sequential()

# First Layer
model.add(Bidirectional(LSTM(WINDOW_SIZE, return_sequences=True),
                        input_shape=(WINDOW_SIZE, x_train.shape[-1])))
model.add(Dropout(DROPOUT))

# Second Layer
model.add(Bidirectional(LSTM((WINDOW_SIZE * 2), return_sequences=True)))
model.add(Dropout(DROPOUT))

# Third Layer
model.add(Bidirectional(LSTM(WINDOW_SIZE, return_sequences=False)))

model.add(Dense(units=1))

Bi-directional LSTM RNN is a relatively complex model to make in TensorFlow but with Keras we can do this in just about 1 lines. The Dense fully connected layer comes at the end then our activation function and then our loss function at the very end which is going to be Adam.

# Set activation function
model.add(Activation('linear'))

# compile and fit the model
model.compile(loss='mean_squared_error', optimizer='adam')

The loss function is going to be mean squared error. The linear activation function in this model is going to determine the output of each neuron in the model.

Training the Model

We’re gonna train it with a batch size of 64 for 100 epochs. we are going to minimize the loss of its training data using the mean squared error. For fitting the model use model.fit and we give it all of those variables that we computed at the very beginning the training data.

history = model.fit(x_train, y_train, epochs=100, batch_size=BATCH_SIZE, shuffle=False,
                    validation_data=(x_test, y_test),
                    callbacks=[EarlyStopping(monitor='val_loss', min_delta=5e-5, patience=20, verbose=1)])

Predict Price

Finally, we came to predicting the price and plot it to compare with the real results.

predict_prices = model.predict(x_test)

plt.plot(scl.inverse_transform(y_test), label="Actual Values", color='green')
plt.plot(scl.inverse_transform(predict_prices), label="Predicted Values", color='red')

plt.title('BitCoin price Prediction')
plt.xlabel('time [days]')
plt.ylabel('Price')
plt.legend(loc='best')

plt.show()

Rescale the predicted data to match its real values.
Predict bitcoin prices