Sleep Stage Classification with MNE and Scikit-learn Python

Wisanu Simalai
10 min readOct 29, 2023

--

การนอนหลับ คือสิ่งสำคัญที่ช่วยให้ร่างกายฟื้นตัวจากความเหนื่อยล้าและความวิตกกังวล ซึ่งมีบทบาทสำคัญในการสนับสนุนระบบภูมิคุ้มกันตลอดจนช่วยให้ร่างกายซ่อมแซมตัวเองได้

อย่างไรก็ตาม การที่เราจะรับรู้ได้ว่าการนอนหลับของเราเป็นอย่างไร จำเป็นต้องได้รับการตรวจวัดคลื่นไฟฟ้าสมอง หรือ Electroencephalogram (EEG) เพื่อจำแนกระยะการนอนหลับของเรา (Sleep Stage)

ดังนั้นการทำความเข้าใจพฤติกรรมของมนุษย์ระหว่างการนอนหลับเป็นกระบวนการที่สำคัญ เนื่องจากมักใช้ในการวินิจฉัยความผิดปกติของการนอนหลับ และเพื่อศึกษาการจำแนก Class ของ Sleep Stage เราจะใช้ Python ในการสร้าง Machine Learning Model ขึ้นมาสำหรับการทำนายผล

Sleep Cycle and Sleep Stage 💤

Figure 1: Sleep Cycle

การนอนหลับมีหลาย Stage ประกอบด้วย 1, 2, 3, 4 และ Rapid Eye Movement (REM) คนส่วนใหญ่คิดว่าวงจรการนอนหลับโดยทั่วไปจะมีเพียงแค่วงจรเดียวเท่านั้น แต่ความจริงแล้วระยะของการนอนหลับจะวนไปตลอดทั้งคืน 4–5 cycles ขึ้นอยู่กับระยะเวลาการนอนหลับ โดยในช่วงที่ใกล้จะตื่นจะเกิดช่วง REM ถี่ขึ้น คิดเป็นอัตราส่วนของระยะ Awake 2–5 %, stage 1–2 (Light Sleep) 45–55 %, stage 3–4 (Deep Sleep) 13–23 % และ REM 20–25 %

Figure 2: EEG Pattern of sleep stages

Stage 1 (N1)

ระยะที่ 1 เป็นระยะแรกของการนอนหลับแบบ non-REM (N1) โดยทั่วไปขั้นตอนนี้จะใช้เวลาน้อยกว่า 10 นาที และสังเกตได้จากการเต้นของหัวใจ การหายใจ และการเคลื่อนไหวของดวงตาช้าลง เช่นเดียวกับการผ่อนคลายกล้ามเนื้อ ในช่วงเริ่มต้นของระยะที่ 1 สมองจะผลิตคลื่นอัลฟ่าที่มีแอมพลิจูดสูง และเริ่มสร้างคลื่นทีต้าเมื่อระยะดำเนินไป

Stage 2 (N2)

ระยะที่ 2 ยังคงเป็นช่วงการนอนหลับตื้น โดยมีลักษณะคล้ายคลึงกับ N1 เช่น การเต้นของหัวใจและการหายใจช้าลงอย่างต่อเนื่อง และกล้ามเนื้อผ่อนคลายไกลกว่าใน N1 ในระยะนี้ อุณหภูมิร่างกายของคุณจะลดลง และการเคลื่อนไหวของดวงตาของคุณจะหยุดลงโดยสิ้นเชิง

ระยะที่ 2 มีลักษณะเฉพาะด้วยคลื่นทีต้า แต่สมองก็เริ่มสร้างคลื่นสมองเป็นจังหวะอย่างรวดเร็วที่เรียกว่า sleep spindles และยังมี k-complexes ซึ่งเป็นรูปแบบแอมพลิจูดสูง โดยรวมแล้ว N2 ใช้เวลาประมาณ 20 นาที

Stage 3+4 หรือ Deep Sleep (N3)

ระยะที่ 3 (N3) เดิมชื่อระยะที่ 3 และ 4 เป็นระยะสุดท้ายของการนอนหลับแบบไม่ REM ในช่วง N3 หัวใจเต้นและหายใจช้าลงจนถึงระดับต่ำสุด และกล้ามเนื้อจะผ่อนคลายมากจนอาจปลุกได้ยาก ระยะนี้เรียกว่า “Slow wave sleep” เนื่องจากมีคลื่นเดลต้า

ในระยะนี้ฮอร์โมนการเจริญเติบโตของมนุษย์ (HGH) จะถูกปล่อยออกมา HGH ทำงานเพื่อฟื้นฟูและสร้างร่างกายและกล้ามเนื้อของคุณขึ้นมาใหม่ซึ่ง N3 ใช้เวลาประมาณ 20 ถึง 40 นาที

REM Sleep

การนอนหลับ REM เป็นการนอนหลับที่ลึกที่สุด โดยการเคลื่อนไหวของดวงตาอย่างรวดเร็วและร่างกายเป็นอัมพาตเกือบสมบูรณ์ หรือที่เรียกว่า REM atonia ซึ่งเซลล์ประสาทสั่งการถูกยับยั้งโดยสิ้นเชิง ในระยะนี้ คลื่นสมองจะเร็วและมีแอมพลิจูดต่ำ คล้ายกับรูปแบบที่เห็นระหว่างตื่นตัว โดยเปอร์เซ็นต์การนอนหลับ REM ของผู้ใหญ่จะอยู่ที่ประมาณ 20–25% ของเวลานอนหลับทั้งหมด

Data Exploration 🔎

Data Source: Sleep-EDF Database Expanded

ฐานข้อมูล sleep-edf ประกอบด้วยการบันทึกการนอนหลับ PolySomnoGraphic ตลอดทั้งคืน 197 รายการ ประกอบด้วย Electroencephalogram (EEG), Electroocoulogram (EOG), Chin Electromyography (EMG) และ event markers บันทึกบางรายการยังมีการหายใจและอุณหภูมิร่างกายด้วย โดยแบ่งไฟล์เป็นสองประเภทคือ Raw File กับ Annotation File

  • ไฟล์ *PSG.edf เป็นการบันทึกการนอนหลับที่มี EEG (จากตำแหน่งอิเล็กโทรด Fpz-Cz และ Pz-Oz), EOG , EMG ใต้คาง และ Event Markers
  • ไฟล์ *Hypnogram.edf มีคำอธิบายประกอบของรูปแบบการนอนหลับที่สอดคล้องกับ PSG ประกอบด้วยระยะการนอนหลับ W, R, 1, 2, 3, 4, M (Movement) และ ? (ไม่ได้ระบุ) ฮิปโนแกรมทั้งหมดได้รับการให้คะแนนด้วยตนเองโดยช่างเทคนิคที่ผ่านการฝึกอบรมมาอย่างดี
Figure 3: The eight-electrodes configuration. The standard positions (i.e., Fz, Cz, Pz, Oz, P7, P3, P4, and P8)

สร้างกราฟเพื่อวิเคราะห์สัญญาณ EEG

  1. ติดตั้ง Library MNE และโหลด Library อื่นๆที่จำเป็น
!pip install mne

import mne
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from google.colab import drive

2. ทำการโหลดข้อมูลเพื่อสร้างเป็นกราฟ

#setting file path
drive.mount('/content/drive/')
data_root = '/content/drive/MyDrive/Brain Code 101/Dataset/'

#read edf file and set annotation
raw_train = mne.io.read_raw_edf(f"{data_root}sleep-cassette/SC4001E0-PSG.edf", preload=True, infer_types = True, stim_channel="Event marker")
annot_train = mne.read_annotations(f"{data_root}sleep-cassette/SC4001EC-Hypnogram.edf")
raw_train.set_annotations(annot_train, emit_warning=False)

#plot EEG graph
raw_train.plot(
start=60,
duration=60,
scalings=dict(eeg=1e-4, resp=1e3, eog=1e-4, emg=1e-7, misc=1e-1)
)

โดยมีรายละเอียดของสัญญาณที่ประกอบไปด้วย 7 channels และไม่มีสัญญาณเสียแสดงดังรูปด้านล่าง

3. ทำการตัดแบ่งสัญญาณ EEG เป็นทุกช่วง 30 วินาทีที่เรียกว่า Epoch สำหรับใช้ในการแบ่ง Sleep Stage ออกเป็น 5 คลาส คือ Wake (W), ระยะ 1, ระยะ 2, ระยะ 3/4 และ REM (R) นอกจากนี้ เราจะตัด 30 นาทีแรกตั้งแต่เริ่มนอนและ 30 นาทีสุดท้ายก่อนตื่นออก

annotation_desc_2_event_id = {
"Sleep stage W": 1,
"Sleep stage 1": 2,
"Sleep stage 2": 3,
"Sleep stage 3": 4,
"Sleep stage 4": 4,
"Sleep stage R": 5,
}

# keep last 30-min wake events before sleep and first 30-min wake events after
# sleep and redefine annotations on raw data
annot_train.crop(annot_train[1]["onset"] - 30 * 60, annot_train[-2]["onset"] + 30 * 60)
raw_train.set_annotations(annot_train, emit_warning=False)

events_train, _ = mne.events_from_annotations(
raw_train, event_id=annotation_desc_2_event_id, chunk_duration=30.0
)

# create a new event_id that unifies stages 3 and 4
event_id = {
"Sleep stage W": 1,
"Sleep stage 1": 2,
"Sleep stage 2": 3,
"Sleep stage 3/4": 4,
"Sleep stage R": 5,
}

# plot events
fig = mne.viz.plot_events(
events_train,
event_id=event_id,
sfreq=raw_train.info["sfreq"],
first_samp=events_train[0, 0],
)

# keep the color-code for further plotting
stage_colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]

จากกราฟก็จะเห็นได้ว่ามีช่วง Sleep Stage เป็น cycles โดยตลอดระยะเวลาการนอน ช่วง Rem มี 125 ครั้ง, Deep Sleep (3/4) มี 220 ครั้ง, N2 มี 250 ครั้ง, N1 มี 58 ครั้ง และ Wake มี 188 ครั้ง

Data Processing to ML Model Evalution⚙️

Figure 4: Processing Block diagram of the sleep stages classification.

1. Load EEG files and stack data to a data frame

1.1 กำหนด Path และชื่อไฟล์ที่ต้องการจะอ่าน

import pandas as pd
# Define your file paths
data_root = '/content/drive/MyDrive/...' #กรณีเก็บไฟล์ไว้ใน Google Drive
raw_file_paths = ['Your Raw File Name.edf',...] #ชื่อไฟล์ Raw EEG
annot_file_paths = ['Your Hypnogram.edf',...] #ชื่อไฟล์ Annotation EEG

1.2 สร้าง Function สำหรับกรองความถี่ที่ต้องการนำไปสร้างเป็น Feature

def eeg_power_band(epochs):

# specific frequency bands
FREQ_BANDS = {
"delta": [0.5, 4.5],
"theta": [4.5, 8.5],
"alpha": [8.5, 11.5],
"sigma": [11.5, 15.5],
"beta": [15.5, 30],
}

spectrum = epochs.compute_psd(picks="eeg", fmin=0.5, fmax=30.0)
psds, freqs = spectrum.get_data(return_freqs=True)
# Normalize the PSDs
psds /= np.sum(psds, axis=-1, keepdims=True)

X = []
for fmin, fmax in FREQ_BANDS.values():
psds_band = psds[:, :, (freqs >= fmin) & (freqs < fmax)].mean(axis=-1)
X.append(psds_band.reshape(len(psds), -1))

return np.concatenate(X, axis=1)

1.3 ทำการอ่านทีละไฟล์และแปลงข้อมูลให้อยู่ในรูปแบบของ Data Frame

# Initialize a list to hold DataFrames for each file
df_list = []

# Loop through the files
for raw_path, annot_path in zip(raw_file_paths, annot_file_paths):
raw_train = mne.io.read_raw_edf(
data_root + raw_path, stim_channel="Event marker", infer_types=True, preload=True
)
annot_train = mne.read_annotations(data_root + annot_path)
annot_train.crop(annot_train[1]["onset"] - 30 * 60, annot_train[-2]["onset"] + 30 * 60)
raw_train.set_annotations(annot_train, emit_warning=False)
events_train, _ = mne.events_from_annotations(raw_train, event_id=annotation_desc_2_event_id, chunk_duration=30.0)
epochs_train = mne.Epochs(
raw=raw_train,
events=events_train,
event_id=event_id,
tmin=0.0,
tmax=tmax,
baseline=None,
)
del raw_train

X = eeg_power_band(epochs_train)
Y = epochs_train.events[:, 2]

# Combine X and Y into a DataFrame
df = pd.DataFrame(X)
df['Stage'] = Y
df_list.append(df)

# Concatenate all DataFrames in the list into a single DataFrame
combined_df = pd.concat(df_list, axis=0)

เราก็จะได้ข้อมูลที่อยู่ในรูปแบบ Data Frame สำหรับใช้ในการทำ Model ต่อไป

2. Split Data

2.1 Rebalancing Data ด้วยการทำ Random Oversampling

Figure 5: Imbalancing Data

จากกราฟจะเห็นได้ว่า Sleep Class ของแต่ละช่วงมีจำนวนที่ไม่เท่ากันซึ่งอาจจะทำประสิทธิภาพการทำนายผลของโมเดลเราลดลง จึงต้องทำการ Random Oversampling ก่อนเพื่อให้ทุกคลาสมีจำนวนเท่ากัน

from imblearn.over_sampling import RandomOverSampler

x = combined_df.iloc[:, :-1].copy()
y = combined_df.iloc[:, -1].copy()

ros = RandomOverSampler(random_state=42)
X_resampled, y_resampled = ros.fit_resample(x, y)

2.2 ทำการแบ่งข้อมูลเป็นส่วน Train set 80% และ Test set 20%

from sklearn.model_selection import train_test_split

# สร้าง training data และ test data โดยแบ่งจากชุดข้อมูล x,y
x_train, x_test, y_train, y_test = train_test_split(X_resampled, y_resampled, test_size=0.2,
stratify=y_resampled,
shuffle=True,
random_state=42)

print('Train set: จำนวนข้อมูล แบ่งกลุ่มตาม class label')
unique, counts = np.unique(y_train, return_counts=True)
print(np.asarray((unique, counts)).T)

print('Test set: จำนวนข้อมูล แบ่งกลุ่มตาม class label')
unique, counts = np.unique(y_test, return_counts=True)
print(np.asarray((unique, counts)).T)

3. Standardization

ทำการ standardization โดยใช้ mean และ SD จาก training set ในการ standardize test set เพื่อป้องกัน information leak

x_scaler = StandardScaler().fit(x_train)

x_scale_train = x_scaler.transform(x_train)
x_scale_test = x_scaler.transform(x_test)
Figure 6: Comparison of normal features and standardized features

4. ML Model Evaluation

เริ่มจากการ Import Library ที่จำเป็นสำหรับการสร้าง ML Model ก่อน

from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier as KNC
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.ensemble import GradientBoostingClassifier as GBC
from sklearn.neural_network import MLPClassifier as MLP
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.model_selection import StratifiedKFold, KFold
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, ConfusionMatrixDisplay
import time

# ตั้งค่า random seed สำหรับการทำซ้ำ (reproducibility)
RANDOM_SEED = 42

จากนั้นจึงสร้าง Function Training Pipeline โดยกำหนดให้มีการรับค่า 6 อย่างคือ Model name, Hyperparameter, x_train, y_train, x_test, y_test หลังจากนั้นจึงทำการ Train Model และแสดงผลลัพธ์ในรูปแบบของ Classifacation Report, Confusion Metrix และระยะเวลาที่ใช้ในการ Training Model

def tune_train_test_pipeline(base_clf, clf_params, x_train, y_train, x_test, y_test):

# Record the start time
start_time = time.time()

# แบ่งข้อมูล training data ด้วย 5-fold cross-validation เพื่อ tune hyperparameter
cv_splitter = StratifiedKFold(n_splits=5, shuffle=True, random_state=RANDOM_SEED)

# ใช้ GridSearchCV เพื่อสอนโมเดลจากชุดค่า hyperparameters จาก clf_params
# และคำนวณค่า accuracy ของแต่ละโมเดล เพื่อเลือกชุด hyperparameters ที่ดีที่สุด
# โดยใช้เทคนิค cross-validation ในการแบ่งกลุ่ม validation data จาก training data
tuned_clf = GridSearchCV(estimator=base_clf, param_grid=clf_params,
scoring=['accuracy'], refit='accuracy', cv=cv_splitter)

# fit โมเดลด้วย training data
tuned_clf.fit(x_train, y_train)

# แสดงผล hyperparameters ที่ดีที่สุด และ cross-validation score
print('Best hyperparameters: {}'.format(tuned_clf.best_params_))
print("Best cross-validation score: {:.2f}".format(tuned_clf.best_score_))

# ให้โมเดลทำนายค่า y จาก train data และคำนวณ accuracy score
prediction_train = tuned_clf.predict(x_train)
accuracy_train = accuracy_score(y_train, prediction_train)

# ให้โมเดลทำนายค่า y จาก test data และคำนวณ accuracy score
prediction_test = tuned_clf.predict(x_test)
accuracy_test = accuracy_score(y_test, prediction_test)

# แสดงผล classification ของโมเดลจาก training data และ test data
print('Training Set: Classification report')
print(classification_report(y_train, prediction_train))
print('\nTest Set: Classification report')
print(classification_report(y_test, prediction_test))

# Define the class labels if you have them (optional)
class_labels = ["W", "1", "2", "3/4", "R"]

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
# Choose a blue tone colormap, such as 'Blues'
cmap = plt.get_cmap('Blues')

# คำนวณและแสดง confusion matrix ของโมเดลจาก training data
cm_train = confusion_matrix(y_train, prediction_train)
display = ConfusionMatrixDisplay(confusion_matrix=cm_train, display_labels=class_labels)
display.plot(ax=ax1, cmap=cmap)
ax1.set_title('[Training Data] \nConfusion Matrix: tuned model')
# คำนวณและแสดง confusion matrix จาก test data
cm_test = confusion_matrix(y_test, prediction_test)
display = ConfusionMatrixDisplay(confusion_matrix=cm_test, display_labels=class_labels)
display.plot(ax=ax2, cmap=cmap)
ax2.set_title('[Test Set] \nConfusion Matrix: tuned model')

plt.tight_layout()
plt.show()

end_time = time.time() # Record the end time
training_time = end_time - start_time # Calculate the training time
training_time = training_time / 60 # Convert training time to minutes
print("Processing time: {:.2f} minutes".format(training_time))

return tuned_clf, [accuracy_train,accuracy_test], cm_train, cm_test, training_time

4.1 Logistic Regression

# สร้างโมเดล และ กำหนดช่วงค่า hyperparameters ในรูปแบบ dictionary
base_clf = LogisticRegression()
clf_params = {'solver': ['liblinear'],
'C': [0.01, 0.1, 1],
'penalty': ['l2']
}
tuned_logit, accuracy_logit, cm_train_logit, cm_test_logit, processing_logit_time = tune_train_test_pipeline(base_clf, clf_params, x_train, y_train, x_test, y_test)

โดยใช้เวลาในการ Training ไป 5.4 วินาที

4.2 Support Vector Machine (SVM)

# สร้างโมเดล และ กำหนดช่วงค่า hyperparameters ในรูปแบบ dictionary
base_clf = SVC(random_state=RANDOM_SEED)
clf_params = {'kernel': ['rbf','linear'],
'C': [0.1, 1]
}
tuned_svm, accuracy_svm, cm_train_svm, cm_test_svm, processing_svm_time = tune_train_test_pipeline(base_clf, clf_params, x_train, y_train, x_test, y_test)

โดยใช้เวลาในการ Training ไป 3 นาที 12.6 วินาที

4.3 Random Forest (RF)

# สร้างโมเดล และ กำหนดช่วงค่า hyperparameters ในรูปแบบ dictionary
base_clf = RFC(random_state=RANDOM_SEED)
clf_params = {'n_estimators': [10,50,100],
'max_depth': [3,5]
}
tuned_rf, accuracy_rf, cm_train_rf, cm_test_rf, processing_rf_time = tune_train_test_pipeline(base_clf, clf_params, x_train, y_train, x_test, y_test)

โดยใช้เวลาในการ Training ไป 38.4 วินาที

4.4 k-Nearest Neighbor (k-NN)

# สร้างโมเดล และ กำหนดช่วงค่า hyperparameters ในรูปแบบ dictionary
base_clf = KNC()
clf_params = {'weights': ['uniform','distance'],
'n_neighbors': [3, 5, 7]
}
tuned_knn, accuracy_knn, cm_train_knn, cm_test_knn, processing_knn_time = tune_train_test_pipeline(base_clf, clf_params, x_train, y_train, x_test, y_test)

โดยใช้เวลาในการ Training ไป 8.4 วินาที

4.5 Gradient Boosting Classifier (GBC)

# สร้างโมเดล และ กำหนดช่วงค่า hyperparameters ในรูปแบบ dictionary
base_clf = GBC()
clf_params = {
'n_estimators': [200], # The number of boosting stages (trees)
'learning_rate': [0.2, 0.5], # The step size shrinkage used to prevent overfitting
'max_depth': [2, 5] # Maximum depth of the individual trees
}
tuned_gb, accuracy_gb, cm_train_gb, cm_test_gb, processing_gb_time = tune_train_test_pipeline(base_clf, clf_params, x_train, y_train, x_test, y_test)

โดยใช้เวลาในการ Training ไป 27 นาที 28 วินาที

4.6 Neural network models : Multi-layer Perceptron (MLP)

# Define the base classifier and the hyperparameters to search over
base_clf = MLP(max_iter=1000)
clf_params = {
'hidden_layer_sizes': [(50, 50, 50)], # Size of hidden layers
'activation': ['relu', 'tanh'], # Activation function
'alpha': [0.0001, 0.001, 0.01], # L2 regularization term
'learning_rate': ['constant', 'invscaling', 'adaptive'], # Learning rate schedule
}

# Use this base_clf and clf_params with your tune_train_test_pipeline function
tuned_mlp, accuracy_mlp, cm_train_mlp, cm_test_mlp, processing_mlp_time = tune_train_test_pipeline(base_clf, clf_params, x_train, y_train, x_test, y_test)

โดยใช้เวลาในการ Training ไป 3 ชม. 53 นาที

Model Comparison

Table 1: Summary Model Results

เมื่อเปรียบเทียบทั้ง 6 โมเดลจะเห็นได้ว่า Gradient Boosting Classifier (GBC) มีผล Accuracy สูงสุด อย่างไรก็ตามหากพิจารณาเรื่องระยะเวลาที่ใช้ในการ Training จะพบว่าใช้เวลาที่ค่อนข้างนานเช่นกัน

ในทางตรงกันข้าม Model อย่าง MLP ที่เป็นลักษณะของ Neural Network น่าจะเป็นโมเดลที่ดีสุดเนื่องจากใช้เวลาในการ Training นานที่สุด แต่กลับให้ผลลัพธ์ที่น้อย GBC ซะอีก ดังนั้นหากผู้เขียนต้องการจะเลือก Model ที่มีความสมดุลที่สุด คงเลือก KNN เพราะใช้ระยะเวลาที่น้อยกว่า GBC มากแต่ยังคงให้ Accuracy ที่สูงอยู่

Conclusion

การศึกษานี้เป็นเพียงตัวอย่างเบื้องต้นของการสร้าง Machine Learning Model ขึ้นมาด้วย Sklearn Python เพื่อใช้สำหรับการทำนายผลของ Sleep Stage โดยการสร้างแต่ละ Model ขึ้นมาเพื่อเปรียบเทียบกันว่า Algorithm ไหนดีที่สุด

Project นี้สามารถนำไปต่อยอดได้หลายแนวทางอีกในอนาคต ซึ่งอาจนำไปสร้างเป็น Deep Learning Model ของเครื่อง EEG เพื่อลดภาระงานของเจ้าหน้าที่ในการทำ Event Marker ระบุแต่ละช่วงว่าช่วงใดบ้างอยู่ใน Sleep Stage Class ใด

นอกจากนี้จะเห็นได้ว่าผู้เขียนได้นำ Feature ทั้งหมดมาใช้ในการสร้างโมเดลเลย ซึ่งเราสามารถลดเวลาในการ Training ลงได้ในการตัด Feature ที่ไม่จำเป็นออก

Acknowledgments

ขอขอบคุณเหล่าคณะอาจารย์, TA และเพื่อนๆในโครงการ Brain Code Camp ที่คอยช่วยเหลือและให้คำปรึกษาจนงานนี้สำเร็จไปได้ด้วยดี แม้ว่าจะมีระยะเวลาที่จำกัดก็ถือเป็นโอกาสอันดีในการเปิดโลกใบใหม่สู่ด้าน Computational-Neuroscience ผู้เขียนหวังว่างานนี้จะมีประโยชน์แก่ทุกท่าน ขอบคุณติดตามอ่านมาถึงตรงนี้ ขอบคุณครับ

Source Code

Credit

https://mne.tools/stable/auto_tutorials/clinical/60_sleep.html

https://course-braincodecamp.web.app/Fundamentals/MachineLearning/eeg_supervised_learning.html

Reference 📖

Al-Salman, W., Li, Y., & Almaged, S. (2023). Sleep stage classification in EEG signals using the clustering approach based probability distribution features coupled with classification algorithms. Neuroscience Research, 188, 51–67. https://doi.org/10.1016/j.neures.2022.09.009

Bisram, C. (2023, April 17). Comparative Analysis of Machine learning Algorithms for sleep stage Classification. Medium. https://medium.com/@codyysb/automated-sleep-stage-classification-evaluating-and-comparing-machine-learning-algorithms-for-d1a34c65241d

Kavish. (2022, May 30). Handling Imbalanced Data with Imbalance-Learn in Python. Analytics Vidhya. https://www.analyticsvidhya.com/blog/2022/05/handling-imbalanced-data-with-imbalance-learn-in-python/

Sleep-EDF Database Expanded V1.0.0. (2013, October 24). https://www.physionet.org/content/sleep-edfx/1.0.0/#ref1

Supervised learning. (n.d.). Scikit-learn. https://scikit-learn.org/stable/supervised_learning.html

Figure Source

Fig 1: Travis Cooper (2014), Understanding Sleep for Optimal Recovery & Productivity,https://www.catalystathletics.com/article/1845/Understanding-Sleep-for-Optimal-Recovery-Productivity/

Fig 2: Ayumi Matsuzaki (2022), What Happens During Sleep, https://www.seisen.com/student-life/seisen-post/features/~board/seisen-post/post/what-happens-during-sleep

Fig 3: Arjon Turnip et al. (2011), Real-time feature extraction of EEG-based P300 using adaptive nonlinear principal component analysis, http://dx.doi.org/10.1186/1475-925X-10-83

--

--