Working with 1 channel EEG data from Neurosky Mindwave Mobile 2

Harsh Kataria
8 min readJul 30, 2020

--

This article will take you through my time spent with the Neurosky Mindwave Mobile 2 and discuss the data obtained from it, compare its results when put in a couple of classifiers, namely, Naive bayes, Decision Tree, Logistic and Random Forest classifier.

This is not a tutorial for using the device or learning AI/ML. This is a story about Neurosky Mindwave Mobile 2, the data obtained from it and a couple operations on them.

EEG stands short for Electroencephalogram or Electroencephalography. EEG data is data collected from electroencephalography. It is a physical record of brain activity.

We are trying to capture this data using the device. The device, Neurosky mindwave mobile 2 is a single channel EEG device which is made to easily rest the node on the forehead with its headband design.

You got to place the contact node on your forehead above the left eyebrow and clip the reference contacts on the left earlobe.

Neurosky Mindwave Mobile 2

The Neurosky Mindwave Mobile 2 is a single channel EEG headset with a EEG forehead contact node and a reference ear clip.

The MindWave Mobile 2 safely measures and outputs the EEG power spectrums (alpha waves, beta waves, etc), NeuroSky eSense meters (attention and meditation) and eye blinks. The device consists of a headset, an ear-clip, and a sensor arm. The headset’s reference and ground electrodes are on the ear clip and the EEG electrode is on the sensor arm, resting on the forehead above the eye (FP1 position). It uses a single AAA battery with 8 hours of battery life.

How it works

> Sensor detects a faint brainwave signal safely and passively

> System interprets meaning of brain signals

> Brainwave signals cause various effects in the application

From the NeuroSky website

Applications of EEG

EEG is a developing field with low research and has a wide variety of applications.

One major application would be thought to text classification enabling and empowering so many ill people all around the world and giving birth to endless opportunities.

Interfacing the device and obtaining the data from the Neurosky Mindwave Mobile 2

The device is equiped with Bluetooth. It uses bluetooth technology to send the processed data points captured by the forehead node to send to a paired device. By processed data i mean it process the raw node values into meaningful brain signals like EEG power values, and meditation and attention values and eye blink strengths by performing mathematical functions on the raaw node values such as FFT and fourier transforms, it basically analyses the raw waves.

I have a simple C# script that uses Sockets to intercept these data points and send it to my main program to be put in the algorithms or save as a csv for training and data capture purposes.

A sample of my C# console application and the values it is receiving

However you will need an application called ThinkGear Connector to address the incoming Neurosky connections and give them a port o your device.

ThinkGear Connector app

Obtaining the data was fairly easy. I would start my device and connect it with the C# program with the ThinkGear connector running and collect data or stream it to another program.

I would sit in multiple batches of one minutes and think about whatever class i wanted the data to be for the whole minute. Uninterrupted. Then save these values into a csv. The console app was programmed to shut down and save the csv automatically after 1 minute. 60 Seconds. It gets tough after a while to be thinking about something for a long time.

The Dataset

The dataset is a personal data collected by myself…of myself…for myself. I say ‘for myself’ because this a very user specific thing. What i mean is, my thought of say moving forward maybe different from yours, that is, i might think of walking forward but you may think of it as driving or simply moving forward whereas someone else might think that their surrounding is moving behind them.

The values being collected

So thats the source and the issue behind the dataset.

The Data

The data in this dataset is catagorized by 11 columns.

One of them is the events column, it is the class that the corresponding values refer to. Its values are U (Up), D (Down), L (Left), R (Right).

The other ten columns are:

attention, meditation, delta, theta, lowAlpha, highAlpha, lowBeta, highBeta,lowGamma, highGamma

The waves

These are the EEG power and eSense signal values collected as a single datapoint from the device. These values are either integers or floating points.

The whole data has 545 rows(datapoints).

So the dataset is a 545 x 11 shaped. With unequal number of datapoints for each class, but not by much.

Preprocessing

Photo of RaNdoM nUmBeRs by Mika Baumeister on Unsplash

Since we get our datapoints processed already there is not much need of data pre processing as such.

But, i still went ahead and tried a couple things (which i reverted as they were unnecessary)

Getting started as…

import pandas as pd
import numpy as np
import matplotlib.pyplot as pltdf = pd.read_csv('/content/HK_UDLR-EEGData.csv')

Down below are couple of things anyone could try.

sample data
# df = df.replace(['?'], 'NaN')
# df.head()

There were no ? values.

# from sklearn.preprocessing import Imputer
# #imputing missing values
# imputer = Imputer(missing_values="NaN", strategy = 'mean', axis = 0)
# imputer = imputer.fit(x.iloc[:,:3])
# x.iloc[:,:3] = imputer.transform(x.iloc[:,:3])
# imputer = Imputer(missing_values="NaN", strategy = 'mean', axis = 0)
# imputer = imputer.fit(x.iloc[:,4:])
# x.iloc[:,4:] = imputer.transform(x.iloc[:,4:])
# x

There were no missing values.

#encoding
# from sklearn.preprocessing import LabelEncoder# labelencoder = LabelEncoder()
# y[:] = labelencoder.fit_transform(y[:])
# y=to_categorical(y)
# print(y)

There was a column that needed encoding. The events column, which is present in string format.

But, i thought of moving forward with it as it is and check the results. So, this is also unused.

We could have also used onehotencoder like

#one hot encoding
# from sklearn.preprocessing import OneHotEncoder
# onehotenc = pd.get_dummies(y['event'])
# y = y.drop('event',axis = 1)
# y = y.join(onehotenc)
# y.head()

Then

#mean normalization# df = x
# df['y'] = y# df = (df - df.mean())/df.std()

No need of Normalising either. All data is in a similar range.

We also didnt need feature selection as all the values were important.

Processing

Coming to the real deal.

Splitting the data now…

x = df.iloc[:,:-1].values
y = df.iloc[:,-1].values# split the dataset into test set and train set
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.30, random_state=0)
print('x_train shape:',x_train.shape)
print('x_test shape:', x_test.shape)
print('y_train shape:', y_train.shape)
print('y_test shape:', y_test.shape)

We did a 70/30 split of the data. and the shapes are up there.

Naive Bayes Model

Naive Bayes classifiers are a collection of classification algorithms based on Bayes’ Theorem. It is not a single algorithm but a family of algorithms where all of them share a common principle, i.e. every pair of features being classified is independent of each other

# import the Naive Bayes model from scikit learn
from sklearn.naive_bayes import GaussianNB# initialize the Naive Bayes Model
classifier = GaussianNB()#fit the Naive Bayes Model
classifier.fit(x_train,y_train)# Predicted the result
y_pred=classifier.predict(x_test)
y_pred# Making a Confusion Matrix
from sklearn.metrics import confusion_matrix
cm=confusion_matrix(y_test, y_pred)
cm
# check the accuracy score
from sklearn.metrics import accuracy_score
ac=accuracy_score(y_test, y_pred)
ac

Logistic Regression Model

Logistic regression is basically a supervised classification algorithm. In a classification problem, the target variable(or output), y, can take only discrete values for given set of features(or inputs), X. Contrary to popular belief, logistic regression IS a regression model.

# import the Logistic regression model from scikit learnfrom sklearn.linear_model import LogisticRegression# init the modelLG = LogisticRegression(random_state=0)# fit the training data into our modelLG.fit(x_train,y_train)# predicted the resulty_pred = LG.predict(x_test)y_pred# Confusion metricfrom sklearn.metrics import confusion_matrixcm=confusion_matrix(y_test,y_pred)cm# Accuracy score
from sklearn.metrics import accuracy_score
ac=accuracy_score(y_test, y_pred)
ac

Decsion Tree Classifier

A decision tree is a flowchart-like tree structure where an internal node represents feature(or attribute), the branch represents a decision rule, and each leaf node represents the outcome. The topmost node in a decision tree is known as the root node.

# import the Decision tree classider from scikit learnfrom sklearn.tree import DecisionTreeClassifier#initialize the Decision tree modelclassifier=DecisionTreeClassifier(criterion ='entropy', random_state= 0)# fit the modelclassifier.fit(x_train,y_train)# predicted the resulty_pred = classifier.predict(x_test)y_pred# making a confusion matrixfrom sklearn.metrics import confusion_matrixcm=confusion_matrix(y_test, y_pred)cm# accuracy scorefrom sklearn.metrics import accuracy_scoreac=accuracy_score(y_test,y_pred)ac

Random Forest Classifier

The Random Forest Classifier. Random forest, like its name implies, consists of a large number of individual decision trees that operate as an ensemble. Each individual tree in the random forest spits out a class prediction and the class with the most votes becomes our model’s prediction

# import random forest classifier model from scikit learnfrom sklearn.ensemble import RandomForestClassifier# initialize the modelclassifier = RandomForestClassifier(n_estimators = 10, criterion = 'entropy', random_state = 0)# fit the train data into our modelclassifier.fit(x_train,y_train)# Making a predictiony_pred = classifier.predict(x_test)y_pred# Making a confusion matrixfrom sklearn.metrics import confusion_matrixcm= confusion_matrix(y_test, y_pred)cm# Accuracy resultfrom sklearn.metrics import accuracy_scoreac= accuracy_score(y_test, y_pred)ac

Summary

There is a lot of room for improvement. We can increase the data by a lot firstly, and explore more extensive feature engineering and neural networks implementation for the same. We could pinpoint hyperparameters and tune them.

If you read it through you must have seen that no such preprocessing was done and it should have. Well there are certain more complex sorts of preprocessing that i am not yet aware of which are left but would prove to be beneficial. The basic preprocessing was tried and and classed redundant.

Feel free to reach out regarding any queries or data or code.

Github: www.github.com/rockangator

End.

References:
http://neurosky.com/2018/06/mindwave-mobile-2-available-now-improved-comfort/
http://developer.neurosky.com/

--

--