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.

The 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.

1 2 3 4 5 6 7 8 9 10 11 12 |
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.

1 2 3 4 5 6 7 |
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.

1 2 3 4 5 6 7 8 9 10 11 12 13 |
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.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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.

1 2 3 4 5 |
# 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.

1 2 3 |
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.

1 2 3 4 5 6 7 8 9 10 11 |
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.