|
a |
|
b/Models/main-GRU.py |
|
|
1 |
#!/usr/bin/env python |
|
|
2 |
# -*- coding: utf-8 -*- |
|
|
3 |
|
|
|
4 |
# Import useful packages |
|
|
5 |
from __future__ import absolute_import |
|
|
6 |
from __future__ import print_function |
|
|
7 |
from __future__ import division |
|
|
8 |
|
|
|
9 |
# Hide the Configuration and Warnings |
|
|
10 |
import os |
|
|
11 |
os.environ["TF_CPP_MIN_LOG_LEVEL"] = '3' |
|
|
12 |
|
|
|
13 |
import random |
|
|
14 |
import numpy as np |
|
|
15 |
import tensorflow as tf |
|
|
16 |
from Models.DatasetAPI.DataLoader import DatasetLoader |
|
|
17 |
from Models.Network.GRU import GRU |
|
|
18 |
from Models.Loss_Function.Loss import loss |
|
|
19 |
from Models.Evaluation_Metrics.Metrics import evaluation |
|
|
20 |
|
|
|
21 |
# Model Name |
|
|
22 |
Model = 'Gated_Recurrent_Unit' |
|
|
23 |
|
|
|
24 |
# Clear all the stack and use GPU resources as much as possible |
|
|
25 |
tf.reset_default_graph() |
|
|
26 |
config = tf.ConfigProto() |
|
|
27 |
config.gpu_options.allow_growth = True |
|
|
28 |
sess = tf.Session(config=config) |
|
|
29 |
|
|
|
30 |
# Your Dataset Location, for example EEG-Motor-Movement-Imagery-Dataset |
|
|
31 |
# The CSV file should be named as training_set.csv, training_label.csv, test_set.csv, and test_label.csv |
|
|
32 |
DIR = 'DatasetAPI/EEG-Motor-Movement-Imagery-Dataset/' |
|
|
33 |
SAVE = 'Saved_Files/' + Model + '/' |
|
|
34 |
if not os.path.exists(SAVE): # If the SAVE folder doesn't exist, create one |
|
|
35 |
os.mkdir(SAVE) |
|
|
36 |
|
|
|
37 |
# Load the dataset, here it uses one-hot representation for labels |
|
|
38 |
train_data, train_labels, test_data, test_labels = DatasetLoader(DIR=DIR) |
|
|
39 |
train_labels = tf.one_hot(indices=train_labels, depth=4) |
|
|
40 |
train_labels = tf.squeeze(train_labels).eval(session=sess) |
|
|
41 |
test_labels = tf.one_hot(indices=test_labels, depth=4) |
|
|
42 |
test_labels = tf.squeeze(test_labels).eval(session=sess) |
|
|
43 |
|
|
|
44 |
# Model Hyper-parameters |
|
|
45 |
n_input = 64 # The input size of signals at each time |
|
|
46 |
max_time = 64 # The unfolded time slices of the GRU Model |
|
|
47 |
gru_size = 256 # The number of GRUs inside the GRU Model |
|
|
48 |
|
|
|
49 |
n_class = 4 # The number of classification classes |
|
|
50 |
n_hidden = 64 # The number of hidden units in the first fully-connected layer |
|
|
51 |
num_epoch = 300 # The number of Epochs that the Model run |
|
|
52 |
keep_rate = 0.75 # Keep rate of the Dropout |
|
|
53 |
|
|
|
54 |
lr = tf.constant(1e-4, dtype=tf.float32) # Learning rate |
|
|
55 |
lr_decay_epoch = 50 # Every (50) epochs, the learning rate decays |
|
|
56 |
lr_decay = 0.50 # Learning rate Decay by (50%) |
|
|
57 |
|
|
|
58 |
batch_size = 1024 |
|
|
59 |
n_batch = train_data.shape[0] // batch_size |
|
|
60 |
|
|
|
61 |
# Initialize Model Parameters (Network Weights and Biases) |
|
|
62 |
# This Model only uses Two fully-connected layers, and u sure can add extra layers DIY |
|
|
63 |
weights_1 = tf.Variable(tf.truncated_normal([gru_size, n_hidden], stddev=0.01)) |
|
|
64 |
biases_1 = tf.Variable(tf.constant(0.01, shape=[n_hidden])) |
|
|
65 |
weights_2 = tf.Variable(tf.truncated_normal([n_hidden, n_class], stddev=0.01)) |
|
|
66 |
biases_2 = tf.Variable(tf.constant(0.01, shape=[n_class])) |
|
|
67 |
|
|
|
68 |
# Define Placeholders |
|
|
69 |
x = tf.placeholder(tf.float32, [None, 64 * 64]) |
|
|
70 |
y = tf.placeholder(tf.float32, [None, 4]) |
|
|
71 |
keep_prob = tf.placeholder(tf.float32) |
|
|
72 |
|
|
|
73 |
# Load Model Network |
|
|
74 |
prediction, features = GRU(Input=x, |
|
|
75 |
max_time=max_time, |
|
|
76 |
n_input=n_input, |
|
|
77 |
gru_size=gru_size, |
|
|
78 |
keep_prob=keep_prob, |
|
|
79 |
weights_1=weights_1, |
|
|
80 |
biases_1=biases_1, |
|
|
81 |
weights_2=weights_2, |
|
|
82 |
biases_2=biases_2) |
|
|
83 |
|
|
|
84 |
# Load Loss Function |
|
|
85 |
loss = loss(y=y, prediction=prediction, l2_norm=True) |
|
|
86 |
|
|
|
87 |
# Load Optimizer |
|
|
88 |
train_step = tf.train.AdamOptimizer(lr).minimize(loss) |
|
|
89 |
|
|
|
90 |
# Load Evaluation Metrics |
|
|
91 |
Global_Average_Accuracy = evaluation(y=y, prediction=prediction) |
|
|
92 |
|
|
|
93 |
# Merge all the summaries |
|
|
94 |
merged = tf.summary.merge_all() |
|
|
95 |
train_writer = tf.summary.FileWriter(SAVE + '/train_Writer', sess.graph) |
|
|
96 |
test_writer = tf.summary.FileWriter(SAVE + '/test_Writer') |
|
|
97 |
|
|
|
98 |
# Initialize all the variables |
|
|
99 |
sess.run(tf.global_variables_initializer()) |
|
|
100 |
for epoch in range(num_epoch + 1): |
|
|
101 |
# U can use learning rate decay or not |
|
|
102 |
# Here, we set a minimum learning rate |
|
|
103 |
# If u don't want this, u definitely can modify the following lines |
|
|
104 |
learning_rate = sess.run(lr) |
|
|
105 |
if epoch % lr_decay_epoch == 0 and epoch != 0: |
|
|
106 |
if learning_rate <= 1e-6: |
|
|
107 |
lr = lr * 1.0 |
|
|
108 |
sess.run(lr) |
|
|
109 |
else: |
|
|
110 |
lr = lr * lr_decay |
|
|
111 |
sess.run(lr) |
|
|
112 |
|
|
|
113 |
# Randomly shuffle the training dataset and train the Model |
|
|
114 |
for batch_index in range(n_batch): |
|
|
115 |
random_batch = random.sample(range(train_data.shape[0]), batch_size) |
|
|
116 |
batch_xs = train_data[random_batch] |
|
|
117 |
batch_ys = train_labels[random_batch] |
|
|
118 |
sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys, keep_prob: keep_rate}) |
|
|
119 |
|
|
|
120 |
# Show Accuracy and Loss on Training and Test Set |
|
|
121 |
# Here, for training set, we only show the result of first 100 samples |
|
|
122 |
# If u want to show the result on the entire training set, please modify it. |
|
|
123 |
train_accuracy, train_loss = sess.run([Global_Average_Accuracy, loss], feed_dict={x: train_data[0:100], y: train_labels[0:100], keep_prob: 1.0}) |
|
|
124 |
Test_summary, test_accuracy, test_loss = sess.run([merged, Global_Average_Accuracy, loss], feed_dict={x: test_data, y: test_labels, keep_prob: 1.0}) |
|
|
125 |
test_writer.add_summary(Test_summary, epoch) |
|
|
126 |
|
|
|
127 |
# Show the Model Capability |
|
|
128 |
print("Iter " + str(epoch) + ", Testing Accuracy: " + str(test_accuracy) + ", Training Accuracy: " + str(train_accuracy)) |
|
|
129 |
print("Iter " + str(epoch) + ", Testing Loss: " + str(test_loss) + ", Training Loss: " + str(train_loss)) |
|
|
130 |
print("Learning rate is ", learning_rate) |
|
|
131 |
print('\n') |
|
|
132 |
|
|
|
133 |
# Save the prediction and labels for testing set |
|
|
134 |
# The "labels_for_test.csv" is the same as the "test_label.csv" |
|
|
135 |
# We will use the files to draw ROC CCurve and AUC |
|
|
136 |
if epoch == num_epoch: |
|
|
137 |
output_prediction = sess.run(prediction, feed_dict={x: test_data, y: test_labels, keep_prob: 1.0}) |
|
|
138 |
np.savetxt(SAVE + "prediction_for_test.csv", output_prediction, delimiter=",") |
|
|
139 |
np.savetxt(SAVE + "labels_for_test.csv", test_labels, delimiter=",") |
|
|
140 |
|
|
|
141 |
# if you want to extract and save the features from fully-connected layer, use all the dataset and uncomment this. |
|
|
142 |
# All data is the total data = training data + testing data |
|
|
143 |
# We use the features from the overall dataset |
|
|
144 |
# ML models might be used to classify the features further |
|
|
145 |
# if epoch == num_epoch: |
|
|
146 |
# Features = sess.run(features, feed_dict={x: all_data, y: all_labels, keep_prob: 1.0}) |
|
|
147 |
# np.savetxt(SAVE + "Features.csv", features, delimiter=",") |
|
|
148 |
|
|
|
149 |
train_writer.close() |
|
|
150 |
test_writer.close() |
|
|
151 |
sess.close() |