Detecting emotions using the EEG brainwave¶
Credit: AITS Cainvas Community
The notebook uses EEG brainwave data to predict the emotions of humans.
What is EEG?¶
Brain cells communicate with each other through electrical signals.
Electroencephalography (EEG) is an electrophysiological monitoring method to record electrical activity of the brain. It is used for diagnosing or treating various disorders like brain tumors, stroke, sleep disorders etc.
Source - Wikipedia - Electroencephalography
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import layers
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import random
import matplotlib.pyplot as plt
The dataset¶
The data was collected from two people (1 male, 1 female) for 3 minutes per state - positive, neutral, negative. A Muse EEG headband recorded the TP9, AF7, AF8 and TP10 EEG placements via dry electrodes. Six minutes of resting neutral data was also recorded.
The stimuli used to evoke the emotions are below
1. Marley and Me - Negative (Twentieth Century Fox) Death Scene
2. Up - Negative (Walt Disney Pictures) Opening Death Scene
3. My Girl - Negative (Imagine Entertainment) Funeral Scene
4. La La Land - Positive (Summit Entertainment) Opening musical number
5. Slow Life - Positive (BioQuest Studios) Nature timelapse
6. Funny Dogs - Positive (MashupZone) Funny dog clips
Dataset citation:
J. J. Bird, L. J. Manso, E. P. Ribiero, A. Ekart, and D. R. Faria, “A study on mental state classification using eeg-based brain-machine interface,”in 9th International Conference on Intelligent Systems, IEEE, 2018.
J. J. Bird, A. Ekart, C. D. Buckingham, and D. R. Faria, “Mental emotional sentiment classification with an eeg-based brain-machine interface,” in The International Conference on Digital Image and Signal Processing (DISP’19), Springer, 2019.
eeg = pd.read_csv('https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/emotions.csv')
eeg
# Number of samlpes in each class
eeg['label'].value_counts()
This is a balanced dataset.
# Checking the datatypes of the columns
eeg.dtypes
# defining the input and output columns to separate the dataset in the later cells.
input_columns = list(eeg.columns[:-1])
output_columns = ['NEGATIVE', 'NEUTRAL', 'POSITIVE'] # column names to be used after one-hot encoding
print("Number of input columns: ", len(input_columns))
#print("Input columns: ", ', '.join(input_columns))
print("Number of output columns: ", len(output_columns))
#print("Output columns: ", ', '.join(output_columns))
# One hot encoding the labels
y = pd.get_dummies(eeg.label)
print(y)
# Adding the one hot encodings to the dataset
for x in output_columns:
eeg[x] = y[x]
# Viewing the dataset again
eeg
# Splitting into train, val and test set -- 80-10-10 split
# First, an 80-20 split
train_df, val_test_df = train_test_split(eeg, test_size = 0.2)
# Then split the 20% into half
val_df, test_df = train_test_split(val_test_df, test_size = 0.5)
print("Number of samples in...")
print("Training set: ", len(train_df))
print("Validation set: ", len(val_df))
print("Testing set: ", len(test_df))
# Splitting into X (input) and y (output)
Xtrain, ytrain = np.array(train_df[input_columns]), np.array(train_df[output_columns])
Xval, yval = np.array(val_df[input_columns]), np.array(val_df[output_columns])
Xtest, ytest = np.array(test_df[input_columns]), np.array(test_df[output_columns])
print("Range of values in X")
min(Xtrain[0]), max(Xtrain[0])
# Each feature has a different range.
# Using min_max_scaler to scale them to values in the range [0,1].
min_max_scaler = MinMaxScaler()
# Fit on training set alone
Xtrain = min_max_scaler.fit_transform(Xtrain)
# Use it to transform val and test input
Xval = min_max_scaler.transform(Xval)
Xtest = min_max_scaler.transform(Xtest)
print("Range of values in X")
min(Xtrain[0]), max(Xtrain[0])
Model¶
model = tf.keras.Sequential([
layers.Dense(512, activation = 'relu', input_shape = Xtrain[0].shape),
layers.Dense(256, activation = 'relu'),
layers.Dense(128, activation = 'relu'),
layers.Dense(3, activation = 'softmax')
])
model.compile(optimizer='adam', loss=tf.losses.CategoricalCrossentropy(), metrics=['accuracy'])
model.summary()
history = model.fit(Xtrain, ytrain, validation_data = (Xval, yval), epochs=128)
model.evaluate(Xtest, ytest)
def plot(history, variable):
plt.plot(range(len(history[variable])), history[variable])
plt.title(variable)
plot(history.history, "accuracy")
plot(history.history, "loss")
deepC¶
model.save('eeg_emotion.h5')
!deepCC eeg_emotion.h5
# Pick random test sample
i = random.randint(0, len(test_df)-1)
np.savetxt('sample.data', Xtest[i])
# run exe with input
!eeg_emotion_deepC/eeg_emotion.exe sample.data
# show predicted output
nn_out = np.loadtxt('dense_3.out')
print ("\nModel predicted the emotion: ", output_columns[np.argmax(nn_out)])
# actual output
print("Actual emotion: ", output_columns[np.argmax(ytest[i])])