├── .gitignore ├── EEG-Inception ├── EEG_Inception.py ├── Net_train.py ├── Readme.md └── cross_val_net.py ├── EEGNet ├── EEGNet_paper.pth ├── EEGNet_version_01.py ├── Readme.md ├── Test_model.py └── Test_net.py ├── ML-MI ├── BCICIV_calib_ds1b.mat ├── EEG_MI_ML.ipynb ├── Readme.md └── refresh_classification.ipynb ├── New train folder ├── EEGNet.py ├── Readme.md ├── confusion_matrix1.png ├── metrics.py ├── read_data.ipynb ├── train.py └── training_metrics_subject_1.png ├── README.md ├── mne包教程.pdf └── 脑机接口导论笔记.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /EEG-Inception/EEG_Inception.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | from torchsummary import summary 5 | 6 | 7 | class DepthwiseSeparableConv2d(nn.Module): 8 | def __init__(self, in_channels, out_channels, kernel_size, padding=0): 9 | super(DepthwiseSeparableConv2d, self).__init__() 10 | self.depthwise = nn.Conv2d(in_channels, in_channels, kernel_size=kernel_size, padding='valid', groups=in_channels) 11 | self.pointwise = nn.Conv2d(in_channels, out_channels, kernel_size=1) 12 | 13 | def forward(self, x): 14 | x = self.depthwise(x) 15 | x = self.pointwise(x) 16 | # 进行通道压缩 17 | 18 | 19 | return x 20 | 21 | class EEGInception(nn.Module): 22 | def __init__(self, input_time=1000, fs=128, ncha=8, filters_per_branch=8, 23 | scales_time=(500, 250, 125), dropout_rate=0.25, 24 | activation='relu', n_classes=2): 25 | super(EEGInception, self).__init__() 26 | 27 | # ============================= CALCULATIONS ============================= # 28 | input_samples = int(input_time * fs / 1000) 29 | scales_samples = [int(s * fs / 1000) for s in scales_time] 30 | 31 | # ================================ INPUT ================================= # 32 | self.input_layer = nn.Conv2d(1, ncha, kernel_size=(1, 1)) 33 | 34 | # ========================== BLOCK 1: INCEPTION ========================== # 35 | b1_units = [] 36 | for i in range(len(scales_samples)): 37 | unit = nn.Sequential( 38 | nn.Conv2d(ncha, ncha, kernel_size=(1, scales_samples[i]), padding='same'), 39 | nn.BatchNorm2d(ncha), 40 | nn.ELU(inplace=True), 41 | DepthwiseSeparableConv2d(ncha, ncha*2, kernel_size=(ncha, 1)), 42 | nn.BatchNorm2d(ncha*2), 43 | nn.ELU(inplace=True), 44 | nn.Dropout(dropout_rate) 45 | ) 46 | b1_units.append(unit) 47 | 48 | self.b1_units = nn.ModuleList(b1_units) 49 | 50 | # ========================== BLOCK 2: INCEPTION ========================== # 51 | b2_units = [] 52 | for i in range(len(scales_samples)): 53 | unit = nn.Sequential( 54 | nn.Conv2d(filters_per_branch*6, filters_per_branch, kernel_size=(int(scales_samples[i]/4), 1), padding='same', padding_mode='zeros'), 55 | nn.BatchNorm2d(filters_per_branch), 56 | nn.ELU(inplace=True), 57 | nn.Dropout(dropout_rate) 58 | ) 59 | b2_units.append(unit) 60 | 61 | self.b2_units = nn.ModuleList(b2_units) 62 | 63 | # ============================ BLOCK 3: OUTPUT =========================== # 64 | self.b3_u1 = nn.Sequential( 65 | nn.Conv2d(filters_per_branch * len(scales_samples), int(filters_per_branch*len(scales_samples)/2), kernel_size=(8, 1),padding='same'), 66 | nn.BatchNorm2d(int(filters_per_branch*len(scales_samples)/2)), 67 | nn.ELU(inplace=True), 68 | nn.AvgPool2d((2, 1)), 69 | nn.Dropout(dropout_rate) 70 | ) 71 | 72 | self.b3_u2 = nn.Sequential( 73 | nn.Conv2d(int(filters_per_branch*len(scales_samples)/2), int(filters_per_branch*len(scales_samples)/4), kernel_size=(4, 1),padding='same'), 74 | nn.BatchNorm2d(int(filters_per_branch*len(scales_samples)/4)), 75 | nn.ELU(inplace=True), 76 | nn.AvgPool2d((2, 1)), 77 | nn.Dropout(dropout_rate) 78 | ) 79 | 80 | self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) 81 | self.fc = nn.Linear(int(filters_per_branch*len(scales_samples)/4), n_classes) 82 | 83 | def forward(self, x): 84 | # ================================ INPUT ================================= # 85 | 86 | 87 | x = self.input_layer(x) 88 | 89 | 90 | 91 | # ========================== BLOCK 1: INCEPTION ========================== # 92 | b1_outputs = [unit(x) for unit in self.b1_units] 93 | 94 | 95 | b1_out = torch.cat(b1_outputs, dim=1) 96 | 97 | b1_out = b1_out.permute((0, 1, 3, 2)) 98 | 99 | b1_out = F.avg_pool2d(b1_out, (4, 1)) 100 | # b1_out = b1_out.permute((0, 2, 1, 3)) 101 | 102 | 103 | 104 | 105 | # ========================== BLOCK 2: INCEPTION ========================== # 106 | b2_outputs = [unit(b1_out) for unit in self.b2_units] 107 | 108 | b2_out = torch.cat(b2_outputs, dim=1) 109 | 110 | b2_out = F.avg_pool2d(b2_out, (2, 1)) 111 | 112 | 113 | # ============================ BLOCK 3: OUTPUT =========================== # 114 | b3_u1_out = F.avg_pool2d(F.elu(self.b3_u1(b2_out)), (2, 1)) 115 | 116 | b3_u2_out = F.avg_pool2d(F.elu(self.b3_u2(b3_u1_out)), (2, 1)) 117 | 118 | b3_out = self.avgpool(b3_u2_out) 119 | 120 | b3_out = b3_out.view(b3_out.size(0), -1) 121 | output = self.fc(b3_out) 122 | return output 123 | 124 | 125 | 126 | 127 | 128 | if __name__ == '__main__': 129 | data = torch.randn(1, 1, 8, 128).to('cuda') 130 | model = EEGInception().to('cuda') 131 | output = model(data) 132 | sum_parameter = 0 133 | for param in model.parameters(): 134 | sum_parameter += param.numel() 135 | print(sum_parameter) 136 | summary(model, (1, 8, 128), device='cuda', batch_size=48) 137 | -------------------------------------------------------------------------------- /EEG-Inception/Net_train.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | from torch.utils.data import DataLoader 4 | from EEGNet_pytorch_version import * 5 | from torch import optim 6 | from EEG_Inception import * 7 | 8 | from sklearn.model_selection import cross_val_score, StratifiedKFold 9 | 10 | 11 | 12 | 13 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 14 | torch.backends.cudnn.enabled = True 15 | # 加载EEGNetdata 16 | 17 | EEGNetdata = EEGNetDataset(file_path='C:\\Users\\24242\\PycharmProjects\\paper_rebuild\\EEG-dataprocessing\\EEG-Conformerprocessing\\combine_data_and_label\\A01_combine\\train_data_A01.pt', target_path='C:\\Users\\24242\\PycharmProjects\\paper_rebuild\\EEG-dataprocessing\\EEG-Conformerprocessing\\combine_data_and_label\\A01_combine\\train_label_A01.pt', transform=False, target_transform=False) 18 | 19 | train_dataloader = DataLoader(EEGNetdata, batch_size=48, shuffle=False) 20 | 21 | # 构建EEGNet 22 | print(device) 23 | 24 | net = EEGInception(input_time=1000, fs=250, ncha=22, filters_per_branch=22, n_classes=4).to(device) 25 | 26 | 27 | 28 | # 损失函数 29 | criterion = nn.CrossEntropyLoss() 30 | 31 | optimizer = optim.Adam(net.parameters(), lr=0.001) 32 | counter = [] 33 | # 画图要用 34 | loss_history = [] 35 | 36 | iteration_number = 0 37 | train_correct = 0 38 | total = 0 39 | 40 | classNum = 4 41 | # 画图要用 42 | acc_history = [] 43 | # 开启训练模式 44 | net.train() 45 | 46 | for epoch in range(0, 250): 47 | for i,data in enumerate(train_dataloader, 0): 48 | item, target = data 49 | item, target = item.to(device), target.to(device) 50 | item = item.type(torch.cuda.FloatTensor) 51 | target = target.type(torch.cuda.LongTensor) 52 | 53 | optimizer.zero_grad() 54 | 55 | output = net(item) 56 | 57 | loss = criterion(output, target) 58 | loss.backward() 59 | optimizer.step() 60 | 61 | pred = torch.max(output.data, 1)[1] 62 | train_correct += (pred == target).sum().item() 63 | total += target.size(0) 64 | train_acc = train_correct / total 65 | train_acc = np.array(train_acc) 66 | if i % 50 == 0: 67 | print('Epoch number {}\n acc {}\n loss {}'.format(epoch, train_acc, loss)) 68 | 69 | iteration_number += 1 70 | counter.append(iteration_number) 71 | acc_history.append(train_acc.item()) 72 | loss_history.append(loss.item()) 73 | 74 | 75 | show_plot(counter, acc_history, loss_history) 76 | torch.save(net, 'EEGNet_paper.pth') 77 | 78 | 79 | -------------------------------------------------------------------------------- /EEG-Inception/Readme.md: -------------------------------------------------------------------------------- 1 | This directory contain EEG-Inception implements and myself EEG_data_processing file 2 | It come from my blog,See my blog for more details https://blog.csdn.net/frankprok?type=blog 3 | -------------------------------------------------------------------------------- /EEG-Inception/cross_val_net.py: -------------------------------------------------------------------------------- 1 | from sklearn.model_selection import cross_val_score,StratifiedKFold 2 | from sklearn.metrics import accuracy_score 3 | import torch 4 | import torch.nn as nn 5 | from torch import optim 6 | from torch.utils.data import DataLoader, TensorDataset 7 | from EEGNet_pytorch_version import * 8 | from EEG_Inception import * 9 | import numpy as np 10 | 11 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 12 | 13 | data = torch.load('C:\\Users\\24242\\PycharmProjects\\paper_rebuild\\EEG-dataprocessing\\EEG-Conformerprocessing\\combine_data_and_label\\A03_combine\\A03_combine_data.pt') 14 | label = torch.load('C:\\Users\\24242\\PycharmProjects\\paper_rebuild\\EEG-dataprocessing\\EEG-Conformerprocessing\\combine_data_and_label\\A03_combine\\A03_combine_label.pt') 15 | data = data.detach().to('cpu') 16 | label = label.detach().to('cpu') 17 | cv = StratifiedKFold(n_splits=8) 18 | 19 | acc = [] 20 | count = 0 21 | for train_index, test_index in cv.split(data, label): 22 | count += 1 23 | X_train, X_test = data[train_index], data[test_index] 24 | y_train, y_test = label[train_index], label[test_index] 25 | train_dataset = TensorDataset(X_train, y_train) 26 | batch_size = 48 27 | test_dataset = TensorDataset(X_test, y_test) 28 | train_loader = DataLoader(train_dataset, batch_size=batch_size) 29 | test_loader = DataLoader(test_dataset, batch_size=batch_size) 30 | 31 | model = EEGInception(input_time=1000, fs=250, ncha=22, filters_per_branch=22, n_classes=4).to(device) 32 | criterion = nn.CrossEntropyLoss() 33 | optimizer = optim.Adam(model.parameters(), lr=0.001) 34 | model.train() 35 | 36 | 37 | print(f'-------------The {count} number run the model------------------') 38 | 39 | for epoch in range(500): 40 | 41 | for batch_data, batch_labels in train_loader: 42 | batch_data = batch_data.to(device).type(torch.cuda.FloatTensor) 43 | batch_labels = batch_labels.to(device).type(torch.cuda.LongTensor) 44 | optimizer.zero_grad() 45 | output = model(batch_data) 46 | loss = criterion(output, batch_labels) 47 | loss.backward() 48 | optimizer.step() 49 | if epoch % 10 == 0: 50 | print("Epoch: {}/{}.. ".format(epoch + 1, 500)) 51 | print("Loss: {:.12f}".format(loss.item())) 52 | 53 | 54 | model.eval() 55 | all_pre = [] 56 | all_label = [] 57 | with torch.no_grad(): 58 | for batch_data, batch_labels in test_loader: 59 | batch_data = batch_data.to(device).type(torch.cuda.FloatTensor) 60 | batch_labels = batch_labels.to(device).type(torch.cuda.LongTensor) 61 | output = model(batch_data) 62 | pre = torch.max(output.data, 1)[1] 63 | pre = pre.cpu().numpy() 64 | all_pre.extend(pre) 65 | all_label.extend(batch_labels.cpu().numpy()) 66 | 67 | acc_num = accuracy_score(y_true=np.array(all_label), y_pred=np.array(all_pre)) 68 | acc.append(acc_num) 69 | print(f'-------------Finish {count} acc recognize-------------------') 70 | print(f'-------------Test Accuracy: {acc_num}-----------------------') 71 | 72 | 73 | print('-------------Finish process-------------') 74 | print(f'cross_val_scores is{np.mean(acc)}') 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /EEGNet/EEGNet_paper.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XCZchaos/python-implementation-of-motion-imagination-classification/238c22858402277b51a80c7d9f6d03c17a9f5aa0/EEGNet/EEGNet_paper.pth -------------------------------------------------------------------------------- /EEGNet/EEGNet_version_01.py: -------------------------------------------------------------------------------- 1 | # 导入工具包 2 | import numpy as np 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | 7 | 8 | class EEGNet(nn.Module): 9 | def __init__(self, classes_num): 10 | super(EEGNet, self).__init__() 11 | self.drop_out = 0.25 12 | 13 | self.block_1 = nn.Sequential( 14 | # Pads the input tensor boundaries with zero 15 | # left, right, up, bottom 16 | nn.ZeroPad2d((31, 32, 0, 0)), 17 | nn.Conv2d( 18 | in_channels=1, # input shape (1, C, T) 19 | out_channels=8, # num_filters 20 | kernel_size=(1, 64), # filter size 21 | bias=False 22 | ), # output shape (8, C, T) 23 | nn.BatchNorm2d(8) # output shape (8, C, T) 24 | ) 25 | 26 | # block 2 and 3 are implementations of Depthwise Convolution and Separable Convolution 27 | self.block_2 = nn.Sequential( 28 | nn.Conv2d( 29 | in_channels=8, # input shape (8, C, T) 30 | out_channels=16, # num_filters 31 | kernel_size=(22, 1), # filter size 32 | # group8意味着八组滤波器 33 | groups=8, 34 | bias=False 35 | ), # output shape (16, 1, T) 36 | nn.BatchNorm2d(16), # output shape (16, 1, T) 37 | nn.ELU(), 38 | nn.AvgPool2d((1, 4)), # output shape (16, 1, T//4) 39 | nn.Dropout(self.drop_out) # output shape (16, 1, T//4) 40 | ) 41 | 42 | self.block_3 = nn.Sequential( 43 | nn.ZeroPad2d((8, 8, 0, 0)), 44 | nn.Conv2d( 45 | in_channels=16, # input shape (16, 1, T//4) 46 | out_channels=16, # num_filters 47 | kernel_size=(1, 16), # filter size 48 | # 十六组滤波器 49 | groups=16, 50 | bias=False 51 | ), # output shape (16, 1, T//4) 52 | nn.Conv2d( 53 | in_channels=16, # input shape (16, 1, T//4) 54 | out_channels=16, # num_filters 55 | kernel_size=(1, 1), # filter size 56 | bias=False 57 | ), # output shape (16, 1, T//4) 58 | nn.BatchNorm2d(16), # output shape (16, 1, T//4) 59 | nn.ELU(), 60 | nn.AvgPool2d((1, 8)), # output shape (16, 1, T//32) 61 | nn.Dropout(self.drop_out) 62 | ) 63 | 64 | self.out = nn.Linear((16 * 31), classes_num) 65 | 66 | def forward(self, x): 67 | x = self.block_1(x) 68 | # print("block1", x.shape) 69 | x = self.block_2(x) 70 | # print("block2", x.shape) 71 | x = self.block_3(x) 72 | # print("block3", x.shape) 73 | 74 | x = x.view(x.size(0), -1) 75 | x = self.out(x) 76 | # return F.softmax(x, dim=1), x # return x for visualization 77 | return x 78 | # if __name__ == '__main__': 79 | # input = torch.randn(32,1,22,1125) 80 | # 81 | # model = EEGNet(4) 82 | # 83 | # out = model(input) 84 | # 85 | # print(model) 86 | -------------------------------------------------------------------------------- /EEGNet/Readme.md: -------------------------------------------------------------------------------- 1 | This directory contain EEGNet-pytorch version implements,and EEGNet paper code 2 | -------------------------------------------------------------------------------- /EEGNet/Test_model.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | from sklearn.metrics import accuracy_score 5 | from torch.utils.data import Dataset 6 | from torch.utils.data import DataLoader 7 | from torchsummary import summary 8 | 9 | 10 | def accuracy(output, target): 11 | pred = torch.argmax(output, dim=1) 12 | pred = pred.float() 13 | correct = torch.sum(pred == target) 14 | return 100 * correct / len(target) 15 | 16 | 17 | 18 | def plot_loss(epoch_number, loss): 19 | plt.plot(epoch_number, loss, color='red') 20 | plt.xlabel('Epoch') 21 | plt.ylabel('Loss') 22 | plt.title('Loss during test') 23 | plt.savefig("loss.jpg") 24 | plt.show() 25 | 26 | 27 | 28 | def plot_accuracy(epoch_number, accuracy): 29 | plt.plot(epoch_number, accuracy, color='orange') 30 | plt.xlabel('Epoch') 31 | plt.ylabel('Accuracy') 32 | plt.title('Accuracy during test') 33 | plt.savefig("accuracy.jpg") 34 | plt.show() 35 | 36 | 37 | 38 | def plot_recall(epoch_number, recall): 39 | plt.plot(epoch_number, recall, color='purple', label='Recall') 40 | plt.xlabel('Epoch') 41 | plt.ylabel('Rate') 42 | plt.title('Recall during test') 43 | plt.savefig("recall.jpg") 44 | plt.show() 45 | 46 | 47 | 48 | def plot_precision(epoch_number, precision): 49 | plt.plot(epoch_number, precision, color='black', label='Precision') 50 | plt.xlabel('Epoch') 51 | plt.ylabel('Rate') 52 | plt.title('Precision during test') 53 | plt.savefig("precision.jpg") 54 | plt.show() 55 | 56 | 57 | 58 | def plot_f1(epoch_number, f1): 59 | plt.plot(epoch_number, f1, color='yellow', label='f1') 60 | plt.xlabel('Epoch') 61 | plt.ylabel('Rate') 62 | plt.title('f1 during test') 63 | plt.savefig("f1.jpg") 64 | plt.show() 65 | 66 | 67 | 68 | def calc_recall_precision(output, target): 69 | pred = torch.argmax(output, dim=1) 70 | pred = pred.float() 71 | tp = ((pred == target) & (target == 1)).sum().item() # 正确预测为“相同”的样本数 72 | tn = ((pred == target) & (target == 0)).sum().item() # 正确预测为“不相同”的样本数 73 | fp = ((pred != target) & (target == 0)).sum().item() # 错误预测为“相同”的样本数 74 | fn = ((pred != target) & (target == 1)).sum().item() # 错误预测为“不相同”的样本数 75 | recall = tp / (tp + fn) if (tp + fn) != 0 else 0 # 计算召回率 76 | precision = tp / (tp + fp) if (tp + fp) != 0 else 0 # 计算精确度 77 | return recall, precision 78 | 79 | 80 | 81 | # ## 用于配置的帮助类 82 | class Config(): 83 | training_dir = "./data/faces/training/" 84 | testing_dir = "./data/faces/testing/" 85 | # batch_size也会影响模型的精度 86 | train_batch_size = 48 # 64 87 | test_batch_size = 48 88 | train_number_epochs = 100 # 100 89 | test_number_epochs = 20 90 | 91 | 92 | 93 | class EEGNetDataset(Dataset): 94 | # Dataset模块提供了一些接口可供实现 属于是抽象基类 95 | def __init__(self,file_path,transform=None): 96 | self.file_path = file_path 97 | 98 | # 读取文件 EEGdata与label 99 | self.data = self.parse_data_file(file_path) 100 | 101 | 102 | self.transform = transform 103 | 104 | 105 | def parse_data_file(self,file_path): 106 | 107 | data = torch.load(file_path) 108 | return np.array(data,dtype=np.float32) 109 | 110 | 111 | # dataset的抽象方法 需要自己实现,下同 112 | # 返回data的长度 size为样本量总和 22*20*50 即channels*sample -> channels * h * w 113 | def __len__(self): 114 | 115 | return len(self.data) 116 | # dataset的抽象方法 117 | # 加载数据特征的index进行截取 index参数是由getitem自动生成的 118 | def __getitem__(self,index): 119 | # 只要创建了对象就会迭代 迭代48次也就是一个batch_size 120 | # data 已变成 287*22*1000的数据 121 | # 选择第一个维度index个样本 每个样本的shape为(22,20,50) 每一个index即为一个trail 122 | item = self.data[index,:] 123 | 124 | 125 | # 目前不会执行 126 | if self.transform: 127 | item = self.transform(item) 128 | 129 | 130 | return item 131 | 132 | if __name__ == '__main__': 133 | device = 'cuda' if torch.cuda.is_available() else 'cpu' 134 | print(device) 135 | model_EEG_net = torch.load('EEGNet_paper.pth', map_location=torch.device(device)) 136 | data_test = torch.load('A01T_new.pt') 137 | print(data_test.shape) 138 | labels = torch.load('A01T_new_label.pt').to(device) 139 | 140 | 141 | 142 | model_EEG_net.eval() 143 | test_label = [] 144 | 145 | with torch.no_grad(): 146 | # EEGnetdata = EEGNetDataset(file_path ='C:\\Users\\24242\\DataspellProjects\\EEG_Project\\EEGNet\\A01T.pt',transform=False) 147 | # test_dataloader = DataLoader(EEGnetdata,shuffle=False,num_workers=0,batch_size=Config.train_batch_size,drop_last=True) 148 | 149 | 150 | 151 | 152 | output = model_EEG_net(data_test.to(device)) #输出 153 | # output = torch.max(output, 1)[1] 154 | 155 | # labels = labels[:-1] 156 | # print(label_test) 157 | # print(labels) 158 | 159 | # result = accuracy(output,labels) 160 | # result1 = accuracy(output=output, target=labels.to(device)) 161 | # 162 | # print(result1) 163 | # summary(model_EEG_net,input_size=(1, 22, 1000), batch_size=20) 164 | # print(result1) 165 | # 模型打印 166 | summary(model_EEG_net, batch_size=48, input_size=(1, 22, 1000)) 167 | 168 | # 0.89 0.85 0.71 0.86 0.87 169 | print(accuracy(output, labels)) 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /EEGNet/Test_net.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from EEGNet_version_01 import * 4 | 5 | 6 | num = torch.rand((32, 1, 22, 1000)) 7 | 8 | net = EEGNet(4) 9 | 10 | out = net(num) 11 | 12 | print(net) 13 | 14 | -------------------------------------------------------------------------------- /ML-MI/BCICIV_calib_ds1b.mat: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ML-MI/Readme.md: -------------------------------------------------------------------------------- 1 | This repository corresponds to the code for my blog 2 | 3 | 4 | In this experiment, CSP and LDA were used for simple classification of EEG data. It is worth noting that at this time, EEG data were not preprocessed and denoised, nor were the subsequent models optimized and adjusted. It was only a simple experiment 5 | 6 | 7 | This experiment adopts the MNE and sklearn modules in python 8 | 9 | 10 | 11 | 12 | One of the files named EEG_MI_ML is a simple experiment of motion imaging left-handed and right-handed binary classification. The experiment involves filtering processing, CSP and LDA, and the mat files related to the experiment are also uploaded 13 | 14 | -------------------------------------------------------------------------------- /ML-MI/refresh_classification.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 225, 6 | "id": "initial_id", 7 | "metadata": { 8 | "collapsed": true, 9 | "ExecuteTime": { 10 | "end_time": "2024-01-26T08:57:44.162933600Z", 11 | "start_time": "2024-01-26T08:57:44.115319400Z" 12 | } 13 | }, 14 | "outputs": [], 15 | "source": [ 16 | "import numpy as np\n", 17 | "import matplotlib.pyplot as plt\n", 18 | "import mne\n", 19 | "from sklearn.discriminant_analysis import LinearDiscriminantAnalysis\n", 20 | "from sklearn.metrics import accuracy_score,roc_curve,auc \n", 21 | "from make_mymodel.csp import CSP\n", 22 | "import os\n", 23 | "from sklearn.svm import SVC" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 226, 29 | "outputs": [ 30 | { 31 | "name": "stdout", 32 | "output_type": "stream", 33 | "text": [ 34 | "['S100R01.edf', 'S100R02.edf', 'S100R03.edf', 'S100R04.edf', 'S100R05.edf', 'S100R06.edf', 'S100R07.edf', 'S100R08.edf', 'S100R09.edf', 'S100R10.edf', 'S100R11.edf', 'S100R12.edf', 'S100R13.edf', 'S100R14.edf']\n", 35 | "['S101R01.edf', 'S101R02.edf', 'S101R03.edf', 'S101R04.edf', 'S101R05.edf', 'S101R06.edf', 'S101R07.edf', 'S101R08.edf', 'S101R09.edf', 'S101R10.edf', 'S101R11.edf', 'S101R12.edf', 'S101R13.edf', 'S101R14.edf']\n", 36 | "['S102R01.edf', 'S102R02.edf', 'S102R03.edf', 'S102R04.edf', 'S102R05.edf', 'S102R06.edf', 'S102R07.edf', 'S102R08.edf', 'S102R09.edf', 'S102R10.edf', 'S102R11.edf', 'S102R12.edf', 'S102R13.edf', 'S102R14.edf']\n", 37 | "['S103R01.edf', 'S103R02.edf', 'S103R03.edf', 'S103R04.edf', 'S103R05.edf', 'S103R06.edf', 'S103R07.edf', 'S103R08.edf', 'S103R09.edf', 'S103R10.edf', 'S103R11.edf', 'S103R12.edf', 'S103R13.edf', 'S103R14.edf']\n", 38 | "['S104R01.edf', 'S104R02.edf', 'S104R03.edf', 'S104R04.edf', 'S104R05.edf', 'S104R06.edf', 'S104R07.edf', 'S104R08.edf', 'S104R09.edf', 'S104R10.edf', 'S104R11.edf', 'S104R12.edf', 'S104R13.edf', 'S104R14.edf']\n", 39 | "['S105R01.edf', 'S105R02.edf', 'S105R03.edf', 'S105R04.edf', 'S105R05.edf', 'S105R06.edf', 'S105R07.edf', 'S105R08.edf', 'S105R09.edf', 'S105R10.edf', 'S105R11.edf', 'S105R12.edf', 'S105R13.edf', 'S105R14.edf']\n", 40 | "['S106R01.edf', 'S106R02.edf', 'S106R03.edf', 'S106R04.edf', 'S106R05.edf', 'S106R06.edf', 'S106R07.edf', 'S106R08.edf', 'S106R09.edf', 'S106R10.edf', 'S106R11.edf', 'S106R12.edf', 'S106R13.edf', 'S106R14.edf']\n", 41 | "['S107R01.edf', 'S107R02.edf', 'S107R03.edf', 'S107R04.edf', 'S107R05.edf', 'S107R06.edf', 'S107R07.edf', 'S107R08.edf', 'S107R09.edf', 'S107R10.edf', 'S107R11.edf', 'S107R12.edf', 'S107R13.edf', 'S107R14.edf']\n", 42 | "['S108R01.edf', 'S108R02.edf', 'S108R03.edf', 'S108R04.edf', 'S108R05.edf', 'S108R06.edf', 'S108R07.edf', 'S108R08.edf', 'S108R09.edf', 'S108R10.edf', 'S108R11.edf', 'S108R12.edf', 'S108R13.edf', 'S108R14.edf']\n" 43 | ] 44 | } 45 | ], 46 | "source": [ 47 | "for i in range(100,109):\n", 48 | " dir_str = r'C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S'+ str(i)\n", 49 | " file_name = os.listdir(dir_str)\n", 50 | " filter_files = [file for file in file_name if file.endswith('.edf')]\n", 51 | " print(filter_files)" 52 | ], 53 | "metadata": { 54 | "collapsed": false, 55 | "ExecuteTime": { 56 | "end_time": "2024-01-26T08:57:44.225901900Z", 57 | "start_time": "2024-01-26T08:57:44.134556700Z" 58 | } 59 | }, 60 | "id": "bbafb7fa04094e48" 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 227, 65 | "outputs": [ 66 | { 67 | "name": "stdout", 68 | "output_type": "stream", 69 | "text": [ 70 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R03.edf...\n", 71 | "EDF file detected\n", 72 | "Setting channel info structure...\n", 73 | "Creating raw.info structure...\n", 74 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 75 | "Filtering raw data in 1 contiguous segment\n", 76 | "Setting up band-pass filter from 8 - 15 Hz\n", 77 | "\n", 78 | "FIR filter parameters\n", 79 | "---------------------\n", 80 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 81 | "- Windowed time-domain design (firwin) method\n", 82 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 83 | "- Lower passband edge: 8.00\n", 84 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 85 | "- Upper passband edge: 15.00 Hz\n", 86 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 87 | "- Filter length: 265 samples (1.656 s)\n", 88 | "\n", 89 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R04.edf...\n", 90 | "EDF file detected\n", 91 | "Setting channel info structure...\n", 92 | "Creating raw.info structure...\n", 93 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 94 | "Filtering raw data in 1 contiguous segment\n", 95 | "Setting up band-pass filter from 8 - 15 Hz\n", 96 | "\n", 97 | "FIR filter parameters\n", 98 | "---------------------\n", 99 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 100 | "- Windowed time-domain design (firwin) method\n", 101 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 102 | "- Lower passband edge: 8.00\n", 103 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 104 | "- Upper passband edge: 15.00 Hz\n", 105 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 106 | "- Filter length: 265 samples (1.656 s)\n", 107 | "\n", 108 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R05.edf...\n", 109 | "EDF file detected\n", 110 | "Setting channel info structure...\n", 111 | "Creating raw.info structure...\n", 112 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 113 | "Filtering raw data in 1 contiguous segment\n", 114 | "Setting up band-pass filter from 8 - 15 Hz\n", 115 | "\n", 116 | "FIR filter parameters\n", 117 | "---------------------\n", 118 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 119 | "- Windowed time-domain design (firwin) method\n", 120 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 121 | "- Lower passband edge: 8.00\n", 122 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 123 | "- Upper passband edge: 15.00 Hz\n", 124 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 125 | "- Filter length: 265 samples (1.656 s)\n", 126 | "\n", 127 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R06.edf...\n", 128 | "EDF file detected\n", 129 | "Setting channel info structure...\n", 130 | "Creating raw.info structure...\n", 131 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 132 | "Filtering raw data in 1 contiguous segment\n", 133 | "Setting up band-pass filter from 8 - 15 Hz\n", 134 | "\n", 135 | "FIR filter parameters\n", 136 | "---------------------\n", 137 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 138 | "- Windowed time-domain design (firwin) method\n", 139 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 140 | "- Lower passband edge: 8.00\n", 141 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 142 | "- Upper passband edge: 15.00 Hz\n", 143 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 144 | "- Filter length: 265 samples (1.656 s)\n" 145 | ] 146 | }, 147 | { 148 | "name": "stderr", 149 | "output_type": "stream", 150 | "text": [ 151 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 152 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 153 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 154 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n" 155 | ] 156 | }, 157 | { 158 | "name": "stdout", 159 | "output_type": "stream", 160 | "text": [ 161 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R07.edf...\n", 162 | "EDF file detected\n", 163 | "Setting channel info structure...\n", 164 | "Creating raw.info structure...\n", 165 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 166 | "Filtering raw data in 1 contiguous segment\n", 167 | "Setting up band-pass filter from 8 - 15 Hz\n", 168 | "\n", 169 | "FIR filter parameters\n", 170 | "---------------------\n", 171 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 172 | "- Windowed time-domain design (firwin) method\n", 173 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 174 | "- Lower passband edge: 8.00\n", 175 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 176 | "- Upper passband edge: 15.00 Hz\n", 177 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 178 | "- Filter length: 265 samples (1.656 s)\n", 179 | "\n", 180 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R08.edf...\n", 181 | "EDF file detected\n", 182 | "Setting channel info structure...\n", 183 | "Creating raw.info structure...\n", 184 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 185 | "Filtering raw data in 1 contiguous segment\n", 186 | "Setting up band-pass filter from 8 - 15 Hz\n", 187 | "\n", 188 | "FIR filter parameters\n", 189 | "---------------------\n", 190 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 191 | "- Windowed time-domain design (firwin) method\n", 192 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 193 | "- Lower passband edge: 8.00\n", 194 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 195 | "- Upper passband edge: 15.00 Hz\n", 196 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 197 | "- Filter length: 265 samples (1.656 s)\n", 198 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R09.edf...\n", 199 | "EDF file detected\n", 200 | "Setting channel info structure...\n", 201 | "Creating raw.info structure...\n", 202 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 203 | "Filtering raw data in 1 contiguous segment\n", 204 | "Setting up band-pass filter from 8 - 15 Hz\n", 205 | "\n", 206 | "FIR filter parameters\n", 207 | "---------------------\n", 208 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 209 | "- Windowed time-domain design (firwin) method\n", 210 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 211 | "- Lower passband edge: 8.00\n", 212 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 213 | "- Upper passband edge: 15.00 Hz\n", 214 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 215 | "- Filter length: 265 samples (1.656 s)\n", 216 | "\n", 217 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R10.edf...\n", 218 | "EDF file detected\n", 219 | "Setting channel info structure...\n", 220 | "Creating raw.info structure...\n", 221 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 222 | "Filtering raw data in 1 contiguous segment\n", 223 | "Setting up band-pass filter from 8 - 15 Hz\n", 224 | "\n", 225 | "FIR filter parameters\n", 226 | "---------------------\n", 227 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 228 | "- Windowed time-domain design (firwin) method\n", 229 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 230 | "- Lower passband edge: 8.00\n", 231 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 232 | "- Upper passband edge: 15.00 Hz\n", 233 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 234 | "- Filter length: 265 samples (1.656 s)\n" 235 | ] 236 | }, 237 | { 238 | "name": "stderr", 239 | "output_type": "stream", 240 | "text": [ 241 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 242 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 243 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 244 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n" 245 | ] 246 | }, 247 | { 248 | "name": "stdout", 249 | "output_type": "stream", 250 | "text": [ 251 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R11.edf...\n", 252 | "EDF file detected\n", 253 | "Setting channel info structure...\n", 254 | "Creating raw.info structure...\n", 255 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 256 | "Filtering raw data in 1 contiguous segment\n", 257 | "Setting up band-pass filter from 8 - 15 Hz\n", 258 | "\n", 259 | "FIR filter parameters\n", 260 | "---------------------\n", 261 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 262 | "- Windowed time-domain design (firwin) method\n", 263 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 264 | "- Lower passband edge: 8.00\n", 265 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 266 | "- Upper passband edge: 15.00 Hz\n", 267 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 268 | "- Filter length: 265 samples (1.656 s)\n", 269 | "\n", 270 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R12.edf...\n", 271 | "EDF file detected\n", 272 | "Setting channel info structure...\n", 273 | "Creating raw.info structure...\n", 274 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 275 | "Filtering raw data in 1 contiguous segment\n", 276 | "Setting up band-pass filter from 8 - 15 Hz\n", 277 | "\n", 278 | "FIR filter parameters\n", 279 | "---------------------\n", 280 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 281 | "- Windowed time-domain design (firwin) method\n", 282 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 283 | "- Lower passband edge: 8.00\n", 284 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 285 | "- Upper passband edge: 15.00 Hz\n", 286 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 287 | "- Filter length: 265 samples (1.656 s)\n", 288 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R13.edf...\n", 289 | "EDF file detected\n", 290 | "Setting channel info structure...\n", 291 | "Creating raw.info structure...\n", 292 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 293 | "Filtering raw data in 1 contiguous segment\n", 294 | "Setting up band-pass filter from 8 - 15 Hz\n", 295 | "\n", 296 | "FIR filter parameters\n", 297 | "---------------------\n", 298 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 299 | "- Windowed time-domain design (firwin) method\n", 300 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 301 | "- Lower passband edge: 8.00\n", 302 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 303 | "- Upper passband edge: 15.00 Hz\n", 304 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n", 305 | "- Filter length: 265 samples (1.656 s)\n", 306 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\EEG-files\\S001\\S001R11.edf...\n", 307 | "EDF file detected\n", 308 | "Setting channel info structure...\n", 309 | "Creating raw.info structure...\n", 310 | "Reading 0 ... 19999 = 0.000 ... 124.994 secs...\n", 311 | "Filtering raw data in 1 contiguous segment\n", 312 | "Setting up band-pass filter from 8 - 15 Hz\n", 313 | "\n", 314 | "FIR filter parameters\n", 315 | "---------------------\n", 316 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 317 | "- Windowed time-domain design (firwin) method\n", 318 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 319 | "- Lower passband edge: 8.00\n", 320 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 321 | "- Upper passband edge: 15.00 Hz\n", 322 | "- Upper transition bandwidth: 3.75 Hz (-6 dB cutoff frequency: 16.88 Hz)\n" 323 | ] 324 | }, 325 | { 326 | "name": "stderr", 327 | "output_type": "stream", 328 | "text": [ 329 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 330 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 331 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n" 332 | ] 333 | }, 334 | { 335 | "name": "stdout", 336 | "output_type": "stream", 337 | "text": [ 338 | "- Filter length: 265 samples (1.656 s)\n" 339 | ] 340 | }, 341 | { 342 | "name": "stderr", 343 | "output_type": "stream", 344 | "text": [ 345 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n" 346 | ] 347 | }, 348 | { 349 | "data": { 350 | "text/plain": "", 351 | "text/html": "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Measurement dateAugust 12, 2009 16:15:00 GMT
ExperimenterUnknown
ParticipantX
Digitized pointsNot available
Good channels64 EEG
Bad channelsNone
EOG channelsNot available
ECG channelsNot available
Sampling frequency160.00 Hz
Highpass8.00 Hz
Lowpass15.00 Hz
FilenamesS001R11.edf
Duration00:02:05 (HH:MM:SS)
" 352 | }, 353 | "execution_count": 227, 354 | "metadata": {}, 355 | "output_type": "execute_result" 356 | } 357 | ], 358 | "source": [ 359 | "raw = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R03.edf',preload=True)\n", 360 | "raw.filter(8,15)\n", 361 | "raw1 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R04.edf',preload=True)\n", 362 | "raw1.filter(8,15)\n", 363 | "raw2 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R05.edf',preload=True)\n", 364 | "raw2.filter(8,15)\n", 365 | "raw3 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R06.edf',preload=True)\n", 366 | "raw3.filter(8,15)\n", 367 | "raw4 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R07.edf',preload=True)\n", 368 | "raw4.filter(8,15)\n", 369 | "raw5 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R08.edf',preload=True)\n", 370 | "raw5.filter(8,15)\n", 371 | "raw6 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R09.edf',preload=True)\n", 372 | "raw6.filter(8,15)\n", 373 | "raw7 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R10.edf',preload=True)\n", 374 | "raw7.filter(8,15)\n", 375 | "raw8 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R11.edf',preload=True)\n", 376 | "raw8.filter(8,15)\n", 377 | "raw9 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R12.edf',preload=True)\n", 378 | "raw9.filter(8,15)\n", 379 | "raw10 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R13.edf',preload=True)\n", 380 | "raw10.filter(8,15)\n", 381 | "raw11 = mne.io.read_raw_edf('C:\\\\Users\\\\24242\\\\Desktop\\\\AI_Reference\\\\data_bag\\\\EEG-files\\\\S001\\\\S001R11.edf',preload=True)\n", 382 | "raw11.filter(8,15)" 383 | ], 384 | "metadata": { 385 | "collapsed": false, 386 | "ExecuteTime": { 387 | "end_time": "2024-01-26T08:57:45.001638300Z", 388 | "start_time": "2024-01-26T08:57:44.178689800Z" 389 | } 390 | }, 391 | "id": "1aa20ec1436414a4" 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": 228, 396 | "outputs": [], 397 | "source": [ 398 | "def choose_event_Epochs_data(raw):\n", 399 | " event,event_id = mne.events_from_annotations(raw)\n", 400 | " event_pick_id = [2,3]\n", 401 | " pick_event = mne.pick_events(event,include=event_pick_id)\n", 402 | " event_new_id = {'T1':2,'T2':3}\n", 403 | " epochs = mne.Epochs(raw,pick_event,event_new_id,tmin=-1,tmax=5,preload=True)\n", 404 | " label = epochs.events[:,-1]\n", 405 | " epochs.load_data().filter(l_freq=8,h_freq=12)\n", 406 | " data = epochs.get_data()\n", 407 | " print(data.shape,label.shape)\n", 408 | " return data,label" 409 | ], 410 | "metadata": { 411 | "collapsed": false, 412 | "ExecuteTime": { 413 | "end_time": "2024-01-26T08:57:45.017373900Z", 414 | "start_time": "2024-01-26T08:57:44.937289900Z" 415 | } 416 | }, 417 | "id": "4f352135ec155406" 418 | }, 419 | { 420 | "cell_type": "code", 421 | "execution_count": 229, 422 | "outputs": [ 423 | { 424 | "name": "stdout", 425 | "output_type": "stream", 426 | "text": [ 427 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 428 | "Not setting metadata\n", 429 | "15 matching events found\n", 430 | "Setting baseline interval to [-1.0, 0.0] s\n", 431 | "Applying baseline correction (mode: mean)\n", 432 | "0 projection items activated\n", 433 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 434 | "1 bad epochs dropped\n", 435 | "Setting up band-pass filter from 8 - 12 Hz\n", 436 | "\n", 437 | "FIR filter parameters\n", 438 | "---------------------\n", 439 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 440 | "- Windowed time-domain design (firwin) method\n", 441 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 442 | "- Lower passband edge: 8.00\n", 443 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 444 | "- Upper passband edge: 12.00 Hz\n", 445 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 446 | "- Filter length: 265 samples (1.656 s)\n", 447 | "(14, 64, 961) (14,)\n" 448 | ] 449 | }, 450 | { 451 | "name": "stderr", 452 | "output_type": "stream", 453 | "text": [ 454 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 455 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 456 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 457 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 458 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n", 459 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n", 460 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 461 | ] 462 | } 463 | ], 464 | "source": [ 465 | "data,label = choose_event_Epochs_data(raw)" 466 | ], 467 | "metadata": { 468 | "collapsed": false, 469 | "ExecuteTime": { 470 | "end_time": "2024-01-26T08:57:45.142484700Z", 471 | "start_time": "2024-01-26T08:57:44.952979700Z" 472 | } 473 | }, 474 | "id": "81c3965c45e75e0a" 475 | }, 476 | { 477 | "cell_type": "code", 478 | "execution_count": 230, 479 | "outputs": [ 480 | { 481 | "name": "stdout", 482 | "output_type": "stream", 483 | "text": [ 484 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 485 | "Not setting metadata\n", 486 | "15 matching events found\n", 487 | "Setting baseline interval to [-1.0, 0.0] s\n", 488 | "Applying baseline correction (mode: mean)\n", 489 | "0 projection items activated\n", 490 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 491 | "1 bad epochs dropped\n", 492 | "Setting up band-pass filter from 8 - 12 Hz\n", 493 | "\n", 494 | "FIR filter parameters\n", 495 | "---------------------\n", 496 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 497 | "- Windowed time-domain design (firwin) method\n", 498 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 499 | "- Lower passband edge: 8.00\n", 500 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 501 | "- Upper passband edge: 12.00 Hz\n", 502 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 503 | "- Filter length: 265 samples (1.656 s)\n" 504 | ] 505 | }, 506 | { 507 | "name": "stderr", 508 | "output_type": "stream", 509 | "text": [ 510 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 511 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 512 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 513 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n" 514 | ] 515 | }, 516 | { 517 | "name": "stdout", 518 | "output_type": "stream", 519 | "text": [ 520 | "(14, 64, 961) (14,)\n" 521 | ] 522 | }, 523 | { 524 | "name": "stderr", 525 | "output_type": "stream", 526 | "text": [ 527 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n", 528 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n", 529 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 530 | ] 531 | } 532 | ], 533 | "source": [ 534 | "data1,label1 = choose_event_Epochs_data(raw1)" 535 | ], 536 | "metadata": { 537 | "collapsed": false, 538 | "ExecuteTime": { 539 | "end_time": "2024-01-26T08:57:45.335822300Z", 540 | "start_time": "2024-01-26T08:57:45.093949700Z" 541 | } 542 | }, 543 | "id": "e551d1f286d8aa54" 544 | }, 545 | { 546 | "cell_type": "code", 547 | "execution_count": 231, 548 | "outputs": [ 549 | { 550 | "name": "stdout", 551 | "output_type": "stream", 552 | "text": [ 553 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 554 | "Not setting metadata\n", 555 | "15 matching events found\n", 556 | "Setting baseline interval to [-1.0, 0.0] s\n", 557 | "Applying baseline correction (mode: mean)\n", 558 | "0 projection items activated\n", 559 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 560 | "1 bad epochs dropped\n", 561 | "Setting up band-pass filter from 8 - 12 Hz\n", 562 | "\n", 563 | "FIR filter parameters\n", 564 | "---------------------\n", 565 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 566 | "- Windowed time-domain design (firwin) method\n", 567 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 568 | "- Lower passband edge: 8.00\n", 569 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 570 | "- Upper passband edge: 12.00 Hz\n", 571 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 572 | "- Filter length: 265 samples (1.656 s)\n" 573 | ] 574 | }, 575 | { 576 | "name": "stderr", 577 | "output_type": "stream", 578 | "text": [ 579 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 580 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 581 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 582 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 583 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n" 584 | ] 585 | }, 586 | { 587 | "name": "stdout", 588 | "output_type": "stream", 589 | "text": [ 590 | "(14, 64, 961) (14,)\n" 591 | ] 592 | }, 593 | { 594 | "name": "stderr", 595 | "output_type": "stream", 596 | "text": [ 597 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n", 598 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 599 | ] 600 | } 601 | ], 602 | "source": [ 603 | "data2,label2 = choose_event_Epochs_data(raw2)" 604 | ], 605 | "metadata": { 606 | "collapsed": false, 607 | "ExecuteTime": { 608 | "end_time": "2024-01-26T08:57:45.351464700Z", 609 | "start_time": "2024-01-26T08:57:45.221222100Z" 610 | } 611 | }, 612 | "id": "4f32bbf225ef9e12" 613 | }, 614 | { 615 | "cell_type": "code", 616 | "execution_count": 232, 617 | "outputs": [ 618 | { 619 | "name": "stdout", 620 | "output_type": "stream", 621 | "text": [ 622 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 623 | "Not setting metadata\n", 624 | "15 matching events found\n", 625 | "Setting baseline interval to [-1.0, 0.0] s\n", 626 | "Applying baseline correction (mode: mean)\n", 627 | "0 projection items activated\n", 628 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 629 | "1 bad epochs dropped\n", 630 | "Setting up band-pass filter from 8 - 12 Hz\n", 631 | "\n", 632 | "FIR filter parameters\n", 633 | "---------------------\n", 634 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 635 | "- Windowed time-domain design (firwin) method\n", 636 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 637 | "- Lower passband edge: 8.00\n", 638 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 639 | "- Upper passband edge: 12.00 Hz\n", 640 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 641 | "- Filter length: 265 samples (1.656 s)\n" 642 | ] 643 | }, 644 | { 645 | "name": "stderr", 646 | "output_type": "stream", 647 | "text": [ 648 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 649 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 650 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 651 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 652 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n" 653 | ] 654 | }, 655 | { 656 | "name": "stdout", 657 | "output_type": "stream", 658 | "text": [ 659 | "(14, 64, 961) (14,)\n" 660 | ] 661 | }, 662 | { 663 | "name": "stderr", 664 | "output_type": "stream", 665 | "text": [ 666 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n", 667 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 668 | ] 669 | } 670 | ], 671 | "source": [ 672 | "data3,label3 = choose_event_Epochs_data(raw3)" 673 | ], 674 | "metadata": { 675 | "collapsed": false, 676 | "ExecuteTime": { 677 | "end_time": "2024-01-26T08:57:45.493627200Z", 678 | "start_time": "2024-01-26T08:57:45.351464700Z" 679 | } 680 | }, 681 | "id": "e309ac74c728cbc4" 682 | }, 683 | { 684 | "cell_type": "code", 685 | "execution_count": 233, 686 | "outputs": [ 687 | { 688 | "name": "stdout", 689 | "output_type": "stream", 690 | "text": [ 691 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 692 | "Not setting metadata\n", 693 | "15 matching events found\n", 694 | "Setting baseline interval to [-1.0, 0.0] s\n", 695 | "Applying baseline correction (mode: mean)\n", 696 | "0 projection items activated\n", 697 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 698 | "1 bad epochs dropped\n", 699 | "Setting up band-pass filter from 8 - 12 Hz\n", 700 | "\n", 701 | "FIR filter parameters\n", 702 | "---------------------\n", 703 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 704 | "- Windowed time-domain design (firwin) method\n", 705 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 706 | "- Lower passband edge: 8.00\n", 707 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 708 | "- Upper passband edge: 12.00 Hz\n", 709 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 710 | "- Filter length: 265 samples (1.656 s)\n" 711 | ] 712 | }, 713 | { 714 | "name": "stderr", 715 | "output_type": "stream", 716 | "text": [ 717 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 718 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 719 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 720 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 721 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n", 722 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n" 723 | ] 724 | }, 725 | { 726 | "name": "stdout", 727 | "output_type": "stream", 728 | "text": [ 729 | "(14, 64, 961) (14,)\n" 730 | ] 731 | }, 732 | { 733 | "name": "stderr", 734 | "output_type": "stream", 735 | "text": [ 736 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 737 | ] 738 | } 739 | ], 740 | "source": [ 741 | "data4,label4 = choose_event_Epochs_data(raw4)" 742 | ], 743 | "metadata": { 744 | "collapsed": false, 745 | "ExecuteTime": { 746 | "end_time": "2024-01-26T08:57:45.603932Z", 747 | "start_time": "2024-01-26T08:57:45.477907Z" 748 | } 749 | }, 750 | "id": "e0b4bbd9dd75139e" 751 | }, 752 | { 753 | "cell_type": "code", 754 | "execution_count": 234, 755 | "outputs": [ 756 | { 757 | "name": "stdout", 758 | "output_type": "stream", 759 | "text": [ 760 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 761 | "Not setting metadata\n", 762 | "15 matching events found\n", 763 | "Setting baseline interval to [-1.0, 0.0] s\n", 764 | "Applying baseline correction (mode: mean)\n", 765 | "0 projection items activated\n", 766 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 767 | "1 bad epochs dropped\n", 768 | "Setting up band-pass filter from 8 - 12 Hz\n", 769 | "\n", 770 | "FIR filter parameters\n", 771 | "---------------------\n", 772 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 773 | "- Windowed time-domain design (firwin) method\n", 774 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 775 | "- Lower passband edge: 8.00\n", 776 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 777 | "- Upper passband edge: 12.00 Hz\n", 778 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 779 | "- Filter length: 265 samples (1.656 s)\n" 780 | ] 781 | }, 782 | { 783 | "name": "stderr", 784 | "output_type": "stream", 785 | "text": [ 786 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 787 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 788 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 789 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 790 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n" 791 | ] 792 | }, 793 | { 794 | "name": "stdout", 795 | "output_type": "stream", 796 | "text": [ 797 | "(14, 64, 961) (14,)\n" 798 | ] 799 | }, 800 | { 801 | "name": "stderr", 802 | "output_type": "stream", 803 | "text": [ 804 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n", 805 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 806 | ] 807 | } 808 | ], 809 | "source": [ 810 | "data5,label5 = choose_event_Epochs_data(raw5)" 811 | ], 812 | "metadata": { 813 | "collapsed": false, 814 | "ExecuteTime": { 815 | "end_time": "2024-01-26T08:57:45.735943600Z", 816 | "start_time": "2024-01-26T08:57:45.603932Z" 817 | } 818 | }, 819 | "id": "67d0b341927b8e08" 820 | }, 821 | { 822 | "cell_type": "code", 823 | "execution_count": 235, 824 | "outputs": [ 825 | { 826 | "name": "stdout", 827 | "output_type": "stream", 828 | "text": [ 829 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 830 | "Not setting metadata\n", 831 | "15 matching events found\n", 832 | "Setting baseline interval to [-1.0, 0.0] s\n", 833 | "Applying baseline correction (mode: mean)\n", 834 | "0 projection items activated\n", 835 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 836 | "1 bad epochs dropped\n", 837 | "Setting up band-pass filter from 8 - 12 Hz\n", 838 | "\n", 839 | "FIR filter parameters\n", 840 | "---------------------\n", 841 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 842 | "- Windowed time-domain design (firwin) method\n", 843 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 844 | "- Lower passband edge: 8.00\n", 845 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 846 | "- Upper passband edge: 12.00 Hz\n", 847 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 848 | "- Filter length: 265 samples (1.656 s)\n" 849 | ] 850 | }, 851 | { 852 | "name": "stderr", 853 | "output_type": "stream", 854 | "text": [ 855 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 856 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 857 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 858 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 859 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n", 860 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n" 861 | ] 862 | }, 863 | { 864 | "name": "stdout", 865 | "output_type": "stream", 866 | "text": [ 867 | "(14, 64, 961) (14,)\n" 868 | ] 869 | }, 870 | { 871 | "name": "stderr", 872 | "output_type": "stream", 873 | "text": [ 874 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 875 | ] 876 | } 877 | ], 878 | "source": [ 879 | "data6,label6 = choose_event_Epochs_data(raw6)" 880 | ], 881 | "metadata": { 882 | "collapsed": false, 883 | "ExecuteTime": { 884 | "end_time": "2024-01-26T08:57:45.857502Z", 885 | "start_time": "2024-01-26T08:57:45.730934200Z" 886 | } 887 | }, 888 | "id": "7a670ba615b4140c" 889 | }, 890 | { 891 | "cell_type": "code", 892 | "execution_count": 236, 893 | "outputs": [ 894 | { 895 | "name": "stdout", 896 | "output_type": "stream", 897 | "text": [ 898 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 899 | "Not setting metadata\n", 900 | "15 matching events found\n", 901 | "Setting baseline interval to [-1.0, 0.0] s\n", 902 | "Applying baseline correction (mode: mean)\n", 903 | "0 projection items activated\n", 904 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 905 | "1 bad epochs dropped\n", 906 | "Setting up band-pass filter from 8 - 12 Hz\n", 907 | "\n", 908 | "FIR filter parameters\n", 909 | "---------------------\n", 910 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 911 | "- Windowed time-domain design (firwin) method\n", 912 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 913 | "- Lower passband edge: 8.00\n", 914 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 915 | "- Upper passband edge: 12.00 Hz\n", 916 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 917 | "- Filter length: 265 samples (1.656 s)\n" 918 | ] 919 | }, 920 | { 921 | "name": "stderr", 922 | "output_type": "stream", 923 | "text": [ 924 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 925 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 926 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 927 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 928 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n" 929 | ] 930 | }, 931 | { 932 | "name": "stdout", 933 | "output_type": "stream", 934 | "text": [ 935 | "(14, 64, 961) (14,)\n" 936 | ] 937 | }, 938 | { 939 | "name": "stderr", 940 | "output_type": "stream", 941 | "text": [ 942 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n", 943 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 944 | ] 945 | } 946 | ], 947 | "source": [ 948 | "data7,label7 = choose_event_Epochs_data(raw7)" 949 | ], 950 | "metadata": { 951 | "collapsed": false, 952 | "ExecuteTime": { 953 | "end_time": "2024-01-26T08:57:46.031457300Z", 954 | "start_time": "2024-01-26T08:57:45.857502Z" 955 | } 956 | }, 957 | "id": "bd7730d2c855cc29" 958 | }, 959 | { 960 | "cell_type": "code", 961 | "execution_count": 237, 962 | "outputs": [ 963 | { 964 | "name": "stdout", 965 | "output_type": "stream", 966 | "text": [ 967 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 968 | "Not setting metadata\n", 969 | "15 matching events found\n", 970 | "Setting baseline interval to [-1.0, 0.0] s\n", 971 | "Applying baseline correction (mode: mean)\n", 972 | "0 projection items activated\n", 973 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 974 | "1 bad epochs dropped\n", 975 | "Setting up band-pass filter from 8 - 12 Hz\n", 976 | "\n", 977 | "FIR filter parameters\n", 978 | "---------------------\n", 979 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 980 | "- Windowed time-domain design (firwin) method\n", 981 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 982 | "- Lower passband edge: 8.00\n", 983 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 984 | "- Upper passband edge: 12.00 Hz\n", 985 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 986 | "- Filter length: 265 samples (1.656 s)\n" 987 | ] 988 | }, 989 | { 990 | "name": "stderr", 991 | "output_type": "stream", 992 | "text": [ 993 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 994 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 995 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 996 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 997 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n", 998 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n", 999 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 1000 | ] 1001 | }, 1002 | { 1003 | "name": "stdout", 1004 | "output_type": "stream", 1005 | "text": [ 1006 | "(14, 64, 961) (14,)\n" 1007 | ] 1008 | } 1009 | ], 1010 | "source": [ 1011 | "data8,label8 = choose_event_Epochs_data(raw8)" 1012 | ], 1013 | "metadata": { 1014 | "collapsed": false, 1015 | "ExecuteTime": { 1016 | "end_time": "2024-01-26T08:57:46.110297200Z", 1017 | "start_time": "2024-01-26T08:57:45.983428200Z" 1018 | } 1019 | }, 1020 | "id": "d96506677fae1ea2" 1021 | }, 1022 | { 1023 | "cell_type": "code", 1024 | "execution_count": 238, 1025 | "outputs": [ 1026 | { 1027 | "name": "stdout", 1028 | "output_type": "stream", 1029 | "text": [ 1030 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 1031 | "Not setting metadata\n", 1032 | "15 matching events found\n", 1033 | "Setting baseline interval to [-1.0, 0.0] s\n", 1034 | "Applying baseline correction (mode: mean)\n", 1035 | "0 projection items activated\n", 1036 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 1037 | "1 bad epochs dropped\n", 1038 | "Setting up band-pass filter from 8 - 12 Hz\n", 1039 | "\n", 1040 | "FIR filter parameters\n", 1041 | "---------------------\n", 1042 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 1043 | "- Windowed time-domain design (firwin) method\n", 1044 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 1045 | "- Lower passband edge: 8.00\n", 1046 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 1047 | "- Upper passband edge: 12.00 Hz\n", 1048 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 1049 | "- Filter length: 265 samples (1.656 s)\n" 1050 | ] 1051 | }, 1052 | { 1053 | "name": "stderr", 1054 | "output_type": "stream", 1055 | "text": [ 1056 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 1057 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 1058 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 1059 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 1060 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n", 1061 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n" 1062 | ] 1063 | }, 1064 | { 1065 | "name": "stdout", 1066 | "output_type": "stream", 1067 | "text": [ 1068 | "(14, 64, 961) (14,)\n" 1069 | ] 1070 | }, 1071 | { 1072 | "name": "stderr", 1073 | "output_type": "stream", 1074 | "text": [ 1075 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 1076 | ] 1077 | } 1078 | ], 1079 | "source": [ 1080 | "data9,label9 = choose_event_Epochs_data(raw9)" 1081 | ], 1082 | "metadata": { 1083 | "collapsed": false, 1084 | "ExecuteTime": { 1085 | "end_time": "2024-01-26T08:57:46.268207500Z", 1086 | "start_time": "2024-01-26T08:57:46.110297200Z" 1087 | } 1088 | }, 1089 | "id": "a5c338594250d135" 1090 | }, 1091 | { 1092 | "cell_type": "code", 1093 | "execution_count": 239, 1094 | "outputs": [ 1095 | { 1096 | "name": "stdout", 1097 | "output_type": "stream", 1098 | "text": [ 1099 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 1100 | "Not setting metadata\n", 1101 | "15 matching events found\n", 1102 | "Setting baseline interval to [-1.0, 0.0] s\n", 1103 | "Applying baseline correction (mode: mean)\n", 1104 | "0 projection items activated\n", 1105 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 1106 | "1 bad epochs dropped\n", 1107 | "Setting up band-pass filter from 8 - 12 Hz\n", 1108 | "\n", 1109 | "FIR filter parameters\n", 1110 | "---------------------\n", 1111 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 1112 | "- Windowed time-domain design (firwin) method\n", 1113 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 1114 | "- Lower passband edge: 8.00\n", 1115 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 1116 | "- Upper passband edge: 12.00 Hz\n", 1117 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 1118 | "- Filter length: 265 samples (1.656 s)\n" 1119 | ] 1120 | }, 1121 | { 1122 | "name": "stderr", 1123 | "output_type": "stream", 1124 | "text": [ 1125 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 1126 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 1127 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 1128 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 1129 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n", 1130 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n" 1131 | ] 1132 | }, 1133 | { 1134 | "name": "stdout", 1135 | "output_type": "stream", 1136 | "text": [ 1137 | "(14, 64, 961) (14,)\n", 1138 | "Used Annotations descriptions: ['T0', 'T1', 'T2']\n", 1139 | "Not setting metadata\n", 1140 | "15 matching events found\n", 1141 | "Setting baseline interval to [-1.0, 0.0] s\n", 1142 | "Applying baseline correction (mode: mean)\n", 1143 | "0 projection items activated\n", 1144 | "Using data from preloaded Raw for 15 events and 961 original time points ...\n", 1145 | "1 bad epochs dropped\n", 1146 | "Setting up band-pass filter from 8 - 12 Hz\n", 1147 | "\n", 1148 | "FIR filter parameters\n", 1149 | "---------------------\n", 1150 | "Designing a one-pass, zero-phase, non-causal bandpass filter:\n", 1151 | "- Windowed time-domain design (firwin) method\n", 1152 | "- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n", 1153 | "- Lower passband edge: 8.00\n", 1154 | "- Lower transition bandwidth: 2.00 Hz (-6 dB cutoff frequency: 7.00 Hz)\n", 1155 | "- Upper passband edge: 12.00 Hz\n", 1156 | "- Upper transition bandwidth: 3.00 Hz (-6 dB cutoff frequency: 13.50 Hz)\n", 1157 | "- Filter length: 265 samples (1.656 s)\n" 1158 | ] 1159 | }, 1160 | { 1161 | "name": "stderr", 1162 | "output_type": "stream", 1163 | "text": [ 1164 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n", 1165 | "[Parallel(n_jobs=1)]: Done 17 tasks | elapsed: 0.0s\n", 1166 | "[Parallel(n_jobs=1)]: Done 71 tasks | elapsed: 0.0s\n", 1167 | "[Parallel(n_jobs=1)]: Done 161 tasks | elapsed: 0.0s\n", 1168 | "[Parallel(n_jobs=1)]: Done 287 tasks | elapsed: 0.0s\n", 1169 | "[Parallel(n_jobs=1)]: Done 449 tasks | elapsed: 0.0s\n", 1170 | "[Parallel(n_jobs=1)]: Done 647 tasks | elapsed: 0.0s\n" 1171 | ] 1172 | }, 1173 | { 1174 | "name": "stdout", 1175 | "output_type": "stream", 1176 | "text": [ 1177 | "(14, 64, 961) (14,)\n" 1178 | ] 1179 | }, 1180 | { 1181 | "name": "stderr", 1182 | "output_type": "stream", 1183 | "text": [ 1184 | "[Parallel(n_jobs=1)]: Done 881 tasks | elapsed: 0.0s\n" 1185 | ] 1186 | } 1187 | ], 1188 | "source": [ 1189 | "data10,label10 = choose_event_Epochs_data(raw10)\n", 1190 | "data11,label11 = choose_event_Epochs_data(raw11)" 1191 | ], 1192 | "metadata": { 1193 | "collapsed": false, 1194 | "ExecuteTime": { 1195 | "end_time": "2024-01-26T08:57:46.505247700Z", 1196 | "start_time": "2024-01-26T08:57:46.236753Z" 1197 | } 1198 | }, 1199 | "id": "a89eb50d8a898de1" 1200 | }, 1201 | { 1202 | "cell_type": "code", 1203 | "execution_count": 240, 1204 | "outputs": [], 1205 | "source": [ 1206 | "def gather_data(data,data1,label,label1):\n", 1207 | " data2 = np.concatenate((data,data1),axis=0)\n", 1208 | " label2 = np.append(label,label1)\n", 1209 | " return data2,label2\n", 1210 | " " 1211 | ], 1212 | "metadata": { 1213 | "collapsed": false, 1214 | "ExecuteTime": { 1215 | "end_time": "2024-01-26T08:57:46.505247700Z", 1216 | "start_time": "2024-01-26T08:57:46.473775500Z" 1217 | } 1218 | }, 1219 | "id": "e61ab4a26426ef41" 1220 | }, 1221 | { 1222 | "cell_type": "code", 1223 | "execution_count": 241, 1224 | "outputs": [], 1225 | "source": [ 1226 | "data_2,label_2 = gather_data(data,data1,label,label1)\n", 1227 | "data_3,label_3 = gather_data(data_2,data2,label_2,label2)\n", 1228 | "data_4,label_4 = gather_data(data_3,data3,label_3,label3)\n", 1229 | "data_5,label_5 = gather_data(data_4,data4,label_4,label4)\n", 1230 | "data_6,label_6 = gather_data(data_5,data5,label_5,label5)\n", 1231 | "data_all,label_all = gather_data(data_6,data6,label_6,label6)\n", 1232 | "data_all,label_all = gather_data(data_all,data7,label_all,label7)\n", 1233 | "Test_data,Test_label = gather_data(data8,data9,label8,label9)\n", 1234 | "Test_data,Test_label = gather_data(Test_data,data10,Test_label,label10)\n", 1235 | "Test_data,Test_label = gather_data(Test_data,data11,Test_label,label11)" 1236 | ], 1237 | "metadata": { 1238 | "collapsed": false, 1239 | "ExecuteTime": { 1240 | "end_time": "2024-01-26T08:57:46.583596200Z", 1241 | "start_time": "2024-01-26T08:57:46.489554300Z" 1242 | } 1243 | }, 1244 | "id": "c82ba8e5bdd55537" 1245 | }, 1246 | { 1247 | "cell_type": "code", 1248 | "execution_count": 242, 1249 | "outputs": [ 1250 | { 1251 | "data": { 1252 | "text/plain": "(112, 64, 961)" 1253 | }, 1254 | "execution_count": 242, 1255 | "metadata": {}, 1256 | "output_type": "execute_result" 1257 | } 1258 | ], 1259 | "source": [ 1260 | "data_all.shape" 1261 | ], 1262 | "metadata": { 1263 | "collapsed": false, 1264 | "ExecuteTime": { 1265 | "end_time": "2024-01-26T08:57:46.583596200Z", 1266 | "start_time": "2024-01-26T08:57:46.552232100Z" 1267 | } 1268 | }, 1269 | "id": "5f4f13520c78ff58" 1270 | }, 1271 | { 1272 | "cell_type": "code", 1273 | "execution_count": 243, 1274 | "outputs": [ 1275 | { 1276 | "data": { 1277 | "text/plain": "(112,)" 1278 | }, 1279 | "execution_count": 243, 1280 | "metadata": {}, 1281 | "output_type": "execute_result" 1282 | } 1283 | ], 1284 | "source": [ 1285 | "label_all.shape" 1286 | ], 1287 | "metadata": { 1288 | "collapsed": false, 1289 | "ExecuteTime": { 1290 | "end_time": "2024-01-26T08:57:46.583596200Z", 1291 | "start_time": "2024-01-26T08:57:46.567858800Z" 1292 | } 1293 | }, 1294 | "id": "ef4d80c8e71501e2" 1295 | }, 1296 | { 1297 | "cell_type": "code", 1298 | "execution_count": 244, 1299 | "outputs": [ 1300 | { 1301 | "data": { 1302 | "text/plain": "((56, 64, 961), (56,))" 1303 | }, 1304 | "execution_count": 244, 1305 | "metadata": {}, 1306 | "output_type": "execute_result" 1307 | } 1308 | ], 1309 | "source": [ 1310 | "Test_data.shape,Test_label.shape" 1311 | ], 1312 | "metadata": { 1313 | "collapsed": false, 1314 | "ExecuteTime": { 1315 | "end_time": "2024-01-26T08:57:46.599326800Z", 1316 | "start_time": "2024-01-26T08:57:46.583596200Z" 1317 | } 1318 | }, 1319 | "id": "88f48d1769e1e1f3" 1320 | }, 1321 | { 1322 | "cell_type": "code", 1323 | "execution_count": 245, 1324 | "outputs": [ 1325 | { 1326 | "data": { 1327 | "text/plain": "((112, 10), (56, 10))" 1328 | }, 1329 | "execution_count": 245, 1330 | "metadata": {}, 1331 | "output_type": "execute_result" 1332 | } 1333 | ], 1334 | "source": [ 1335 | "csp = CSP(n_components=10)\n", 1336 | "X_csp_all = csp.fit_transform(data_all,label_all)\n", 1337 | "Test_data_csp = csp.transform(Test_data)\n", 1338 | "X_csp_all.shape,Test_data_csp.shape" 1339 | ], 1340 | "metadata": { 1341 | "collapsed": false, 1342 | "ExecuteTime": { 1343 | "end_time": "2024-01-26T08:57:46.757773200Z", 1344 | "start_time": "2024-01-26T08:57:46.599326800Z" 1345 | } 1346 | }, 1347 | "id": "f6c3dc755cc4471e" 1348 | }, 1349 | { 1350 | "cell_type": "code", 1351 | "execution_count": 246, 1352 | "outputs": [], 1353 | "source": [ 1354 | "svc = SVC(kernel='linear')\n", 1355 | "svc.fit(X_csp_all,label_all)\n", 1356 | "y_pred = svc.predict(Test_data_csp)\n", 1357 | "acc = accuracy_score(Test_label,y_pred)" 1358 | ], 1359 | "metadata": { 1360 | "collapsed": false, 1361 | "ExecuteTime": { 1362 | "end_time": "2024-01-26T08:57:46.773527900Z", 1363 | "start_time": "2024-01-26T08:57:46.757773200Z" 1364 | } 1365 | }, 1366 | "id": "b9a2b439a7c72a2a" 1367 | }, 1368 | { 1369 | "cell_type": "code", 1370 | "execution_count": 247, 1371 | "outputs": [ 1372 | { 1373 | "data": { 1374 | "text/plain": "0.625" 1375 | }, 1376 | "execution_count": 247, 1377 | "metadata": {}, 1378 | "output_type": "execute_result" 1379 | } 1380 | ], 1381 | "source": [ 1382 | "acc" 1383 | ], 1384 | "metadata": { 1385 | "collapsed": false, 1386 | "ExecuteTime": { 1387 | "end_time": "2024-01-26T08:57:46.836602Z", 1388 | "start_time": "2024-01-26T08:57:46.773527900Z" 1389 | } 1390 | }, 1391 | "id": "24914a975aa48686" 1392 | }, 1393 | { 1394 | "cell_type": "code", 1395 | "execution_count": 248, 1396 | "outputs": [ 1397 | { 1398 | "name": "stdout", 1399 | "output_type": "stream", 1400 | "text": [ 1401 | "0.6785714285714286\n", 1402 | "[0.15153537 0.29535886 0.33919194 0.03493327 0.79198978 0.06977115\n", 1403 | " 0.00823536 0.32510551 0.71568288 0.05275308 0.14087436 0.88222796\n", 1404 | " 0.4045542 0.51859964 0.1742485 0.26558711 0.04140591 0.4023113\n", 1405 | " 0.04647999 0.48569648 0.69364207 0.02200009 0.16639753 0.59960677\n", 1406 | " 0.1656594 0.47406661 0.36024742 0.3653722 0.11608622 0.90631418\n", 1407 | " 0.08251557 0.97969391 0.8347348 0.57485275 0.83467668 0.03731981\n", 1408 | " 0.66060446 0.17135124 0.0134101 0.79913199 0.87322459 0.39165128\n", 1409 | " 0.15153537 0.29535886 0.33919194 0.03493327 0.79198978 0.06977115\n", 1410 | " 0.00823536 0.32510551 0.71568288 0.05275308 0.14087436 0.88222796\n", 1411 | " 0.4045542 0.51859964]\n", 1412 | "[2 2 2 2 3 2 2 2 3 2 2 3 2 3 2 2 2 2 2 2 3 2 2 3 2 2 2 2 2 3 2 3 3 3 3 2 3\n", 1413 | " 2 2 3 3 2 2 2 2 2 3 2 2 2 3 2 2 3 2 3]\n", 1414 | "[-1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1]\n" 1415 | ] 1416 | } 1417 | ], 1418 | "source": [ 1419 | "lda = LinearDiscriminantAnalysis()\n", 1420 | "lda.fit(X_csp_all,label_all)\n", 1421 | "pred_lda = lda.predict(Test_data_csp)\n", 1422 | "print(accuracy_score(y_pred=pred_lda,y_true=Test_label))\n", 1423 | "y_score = lda.predict_proba(Test_data_csp)[:,1]\n", 1424 | "print(y_score)\n", 1425 | "print(lda.predict(Test_data_csp))\n", 1426 | "new_Test_label = []\n", 1427 | "for i in Test_label:\n", 1428 | " if i == 2:\n", 1429 | " new_Test_label.append(-1)\n", 1430 | " else:\n", 1431 | " new_Test_label.append(1)\n", 1432 | "print(new_Test_label)" 1433 | ], 1434 | "metadata": { 1435 | "collapsed": false, 1436 | "ExecuteTime": { 1437 | "end_time": "2024-01-26T08:57:46.837107500Z", 1438 | "start_time": "2024-01-26T08:57:46.789239200Z" 1439 | } 1440 | }, 1441 | "id": "9955628275c33567" 1442 | }, 1443 | { 1444 | "cell_type": "code", 1445 | "execution_count": 249, 1446 | "outputs": [], 1447 | "source": [ 1448 | "fpr,tpr,thresholds = roc_curve(y_true=new_Test_label,y_score=y_score)\n", 1449 | "roc_acu = auc(fpr,tpr)" 1450 | ], 1451 | "metadata": { 1452 | "collapsed": false, 1453 | "ExecuteTime": { 1454 | "end_time": "2024-01-26T08:57:46.837107500Z", 1455 | "start_time": "2024-01-26T08:57:46.805125900Z" 1456 | } 1457 | }, 1458 | "id": "9bb1451afef6273c" 1459 | }, 1460 | { 1461 | "cell_type": "code", 1462 | "execution_count": 250, 1463 | "outputs": [ 1464 | { 1465 | "data": { 1466 | "text/plain": "
", 1467 | "image/png": "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" 1468 | }, 1469 | "metadata": {}, 1470 | "output_type": "display_data" 1471 | } 1472 | ], 1473 | "source": [ 1474 | "plt.figure(figsize=(8,8))\n", 1475 | "plt.plot(fpr,tpr,color='darkorange',lw=2,label='ROC curve(ACU={:.2f})'.format(roc_acu))\n", 1476 | "plt.plot([0, 1], [0, 1],color='navy',lw=2,linestyle='--',label='Random Guess')\n", 1477 | "\n", 1478 | "plt.xlabel('Flase Positive Rate')\n", 1479 | "plt.ylabel('True Positive Rate')\n", 1480 | "plt.title('Receiver Operating Characteristic (ROC) Curve')\n", 1481 | "plt.legend(loc='lower right')\n", 1482 | "plt.show()" 1483 | ], 1484 | "metadata": { 1485 | "collapsed": false, 1486 | "ExecuteTime": { 1487 | "end_time": "2024-01-26T08:57:46.962842200Z", 1488 | "start_time": "2024-01-26T08:57:46.820816600Z" 1489 | } 1490 | }, 1491 | "id": "955e75e3389d1fb" 1492 | }, 1493 | { 1494 | "cell_type": "code", 1495 | "execution_count": 251, 1496 | "outputs": [ 1497 | { 1498 | "name": "stdout", 1499 | "output_type": "stream", 1500 | "text": [ 1501 | "[0.8035714285714286, 0.7678571428571429, 0.7678571428571429, 0.6964285714285714, 0.6785714285714286, 0.6607142857142857, 0.6428571428571429, 0.7142857142857143, 0.7321428571428571, 0.6964285714285714]\n" 1502 | ] 1503 | } 1504 | ], 1505 | "source": [ 1506 | "# 计算精度与CSP共空间模式中n_component的数量对LDA分类器的影响\n", 1507 | "component_num = [2,4,6,8,10,12,14,16,18,20]\n", 1508 | "acc_list = []\n", 1509 | "for i in component_num:\n", 1510 | " csp = CSP(n_components=i)\n", 1511 | " X_csp_all = csp.fit_transform(data_all,label_all)\n", 1512 | " Test_data_csp = csp.transform(Test_data)\n", 1513 | " lda = LinearDiscriminantAnalysis()\n", 1514 | " lda.fit(X_csp_all,label_all)\n", 1515 | " pred_lda = lda.predict(Test_data_csp)\n", 1516 | " acc_lda = accuracy_score(y_true=Test_label,y_pred=pred_lda)\n", 1517 | " acc_list.append(acc_lda)\n", 1518 | "print(acc_list)" 1519 | ], 1520 | "metadata": { 1521 | "collapsed": false, 1522 | "ExecuteTime": { 1523 | "end_time": "2024-01-26T08:57:48.560734100Z", 1524 | "start_time": "2024-01-26T08:57:46.962842200Z" 1525 | } 1526 | }, 1527 | "id": "2f3911827c688610" 1528 | }, 1529 | { 1530 | "cell_type": "code", 1531 | "execution_count": 252, 1532 | "outputs": [], 1533 | "source": [ 1534 | "def plot_acc(X,Y):\n", 1535 | " plt.figure(figsize=(8,8))\n", 1536 | " plt.plot(X,Y)\n", 1537 | " plt.xlabel('different model')\n", 1538 | " plt.ylabel('Acc')\n", 1539 | " " 1540 | ], 1541 | "metadata": { 1542 | "collapsed": false, 1543 | "ExecuteTime": { 1544 | "end_time": "2024-01-26T08:57:48.576443200Z", 1545 | "start_time": "2024-01-26T08:57:48.560734100Z" 1546 | } 1547 | }, 1548 | "id": "81f535613cc08110" 1549 | }, 1550 | { 1551 | "cell_type": "code", 1552 | "execution_count": 253, 1553 | "outputs": [ 1554 | { 1555 | "data": { 1556 | "text/plain": "
", 1557 | "image/png": "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N954o+Li4mSxWPTxxx9X+75hGJo+fbpiY2MVGBiolJQUbd++/bznnT17thISEhQQEKCkpCSlp6c30hWY41zvW3l5uR5//HH17NlTwcHBiouL0+jRo3XgwIFznrM+P+/u6Hz33N13333G+3D99def97zefM9JqvH3ncVi0TPPPHPWc3rDPVeb/FFSUqJJkyYpIiJCzZo106233qrc3Nxznre+vxsvFIHXxa1YsUKTJk3SqlWrtGzZMpWXl+u6665TcXHxOY8LCQlRdna287V3794mqth1dO/evdp7sHLlyrPu+/333+v222/XuHHjtH79eg0bNkzDhg3T5s2bm7Bi17BmzZpq79uyZcskScOHDz/rMd54vxUXF6t3796aPXt2jd//+9//rhdffFFz5szR6tWrFRwcrMGDB6ukpOSs51y8eLGmTJmiGTNmaN26derdu7cGDx6svLy8xrqMJneu9+348eNat26dpk2bpnXr1mnJkiXaunWrbrrppvOety4/7+7qfPecJF1//fXV3od33333nOf09ntOUrX3Kzs7WwsWLJDFYtGtt956zvN6+j1Xm/zxyCOP6D//+Y/ef/99rVixQgcOHNAtt9xyzvPW53djgzDgVvLy8gxJxooVK866z+uvv26EhoY2XVEuaMaMGUbv3r1rvf9tt91mDBkypNq2pKQk47777mvgytzP5MmTjQ4dOhh2u73G73O/GYYk46OPPnJ+bbfbjZiYGOOZZ55xbsvPzzf8/f2Nd99996znGTBggDFp0iTn1xUVFUZcXJwxc+bMRqnbbL9832qSnp5uSDL27t171n3q+vPuCWp678aMGWMMHTq0TufhnjvT0KFDjauvvvqc+3jjPffL/JGfn2/4+voa77//vnOfLVu2GJKMtLS0Gs9R39+NDYEOr5spKCiQJIWHh59zv2PHjqlt27aKj4/X0KFD9eOPPzZFeS5l+/btiouLU/v27TVq1ChlZmaedd+0tDSlpKRU2zZ48GClpaU1dpkuraysTP/61790zz33yGKxnHU/7rfqdu/erZycnGr3VGhoqJKSks56T5WVlSkjI6PaMVarVSkpKV59HxYUFMhisSgsLOyc+9Xl592TLV++XFFRUercubMmTpyow4cPn3Vf7rkz5ebm6tNPP9W4cePOu6+33XO/zB8ZGRkqLy+vdv906dJFbdq0Oev9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" 1558 | }, 1559 | "metadata": {}, 1560 | "output_type": "display_data" 1561 | } 1562 | ], 1563 | "source": [ 1564 | "plot_acc(component_num,acc_list)" 1565 | ], 1566 | "metadata": { 1567 | "collapsed": false, 1568 | "ExecuteTime": { 1569 | "end_time": "2024-01-26T08:57:48.707894900Z", 1570 | "start_time": "2024-01-26T08:57:48.576443200Z" 1571 | } 1572 | }, 1573 | "id": "5d04d8d3f7653904" 1574 | } 1575 | ], 1576 | "metadata": { 1577 | "kernelspec": { 1578 | "display_name": "Python 3", 1579 | "language": "python", 1580 | "name": "python3" 1581 | }, 1582 | "language_info": { 1583 | "codemirror_mode": { 1584 | "name": "ipython", 1585 | "version": 2 1586 | }, 1587 | "file_extension": ".py", 1588 | "mimetype": "text/x-python", 1589 | "name": "python", 1590 | "nbconvert_exporter": "python", 1591 | "pygments_lexer": "ipython2", 1592 | "version": "2.7.6" 1593 | } 1594 | }, 1595 | "nbformat": 4, 1596 | "nbformat_minor": 5 1597 | } 1598 | -------------------------------------------------------------------------------- /New train folder/EEGNet.py: -------------------------------------------------------------------------------- 1 | # 导入工具包 2 | import numpy as np 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | 7 | 8 | class EEGNet(nn.Module): 9 | def __init__(self, classes_num): 10 | super(EEGNet, self).__init__() 11 | self.drop_out = 0.25 12 | 13 | self.block_1 = nn.Sequential( 14 | # Pads the input tensor boundaries with zero 15 | # left, right, up, bottom 16 | nn.ZeroPad2d((31, 32, 0, 0)), 17 | nn.Conv2d( 18 | in_channels=1, # input shape (1, C, T) 19 | out_channels=8, # num_filters 20 | kernel_size=(1, 64), # filter size 21 | bias=False 22 | ), # output shape (8, C, T) 23 | nn.BatchNorm2d(8) # output shape (8, C, T) 24 | ) 25 | 26 | # block 2 and 3 are implementations of Depthwise Convolution and Separable Convolution 27 | self.block_2 = nn.Sequential( 28 | nn.Conv2d( 29 | in_channels=8, # input shape (8, C, T) 30 | out_channels=16, # num_filters 31 | kernel_size=(22, 1), # filter size 32 | # group8意味着八组滤波器 33 | groups=8, 34 | bias=False 35 | ), # output shape (16, 1, T) 36 | nn.BatchNorm2d(16), # output shape (16, 1, T) 37 | nn.ELU(), 38 | nn.AvgPool2d((1, 4)), # output shape (16, 1, T//4) 39 | nn.Dropout(self.drop_out) # output shape (16, 1, T//4) 40 | ) 41 | 42 | self.block_3 = nn.Sequential( 43 | nn.ZeroPad2d((8, 8, 0, 0)), 44 | nn.Conv2d( 45 | in_channels=16, # input shape (16, 1, T//4) 46 | out_channels=16, # num_filters 47 | kernel_size=(1, 16), # filter size 48 | # 十六组滤波器 49 | groups=16, 50 | bias=False 51 | ), # output shape (16, 1, T//4) 52 | nn.Conv2d( 53 | in_channels=16, # input shape (16, 1, T//4) 54 | out_channels=16, # num_filters 55 | kernel_size=(1, 1), # filter size 56 | bias=False 57 | ), # output shape (16, 1, T//4) 58 | nn.BatchNorm2d(16), # output shape (16, 1, T//4) 59 | nn.ELU(), 60 | nn.AvgPool2d((1, 8)), # output shape (16, 1, T//32) 61 | nn.Dropout(self.drop_out) 62 | ) 63 | 64 | self.out = nn.Linear((16 * 31), classes_num) 65 | 66 | def forward(self, x): 67 | x = self.block_1(x) 68 | # print("block1", x.shape) 69 | x = self.block_2(x) 70 | # print("block2", x.shape) 71 | x = self.block_3(x) 72 | # print("block3", x.shape) 73 | 74 | x = x.view(x.size(0), -1) 75 | x = self.out(x) 76 | 77 | # return F.softmax(x, dim=1), x # return x for visualization 78 | return x -------------------------------------------------------------------------------- /New train folder/Readme.md: -------------------------------------------------------------------------------- 1 | The new training method has been updated.This file folder contain some metrics and whole train and test processing. 2 | 3 | 4 | 5 | 6 | Modify the contents of the function in get_source_data to read your own data files.The preprocessing code is not publicly available, but thanks for understanding. 7 | 8 | 9 | 10 | 11 | If you have some questions, Please contact me. 12 | 13 | 14 | 15 | 16 | E-mail:asherxiong552@gmail.com 17 | -------------------------------------------------------------------------------- /New train folder/confusion_matrix1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XCZchaos/python-implementation-of-motion-imagination-classification/238c22858402277b51a80c7d9f6d03c17a9f5aa0/New train folder/confusion_matrix1.png -------------------------------------------------------------------------------- /New train folder/metrics.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | from sklearn.metrics import confusion_matrix 5 | import itertools 6 | from scipy import stats 7 | from sklearn import manifold 8 | from einops import reduce 9 | from scipy.linalg import eigh 10 | 11 | def plot_confusion_matrix(y_true, y_pred, sub, title = "Confusion matrix - 2a", 12 | cmap=plt.cm.Blues, save_flg=True): 13 | 14 | y_pred = y_pred.cpu().detach().numpy() 15 | y_true = y_true.cpu().detach().numpy() 16 | classes = [str(i) for i in range(4)] 17 | labels = range(4) 18 | 19 | cm = confusion_matrix(y_true, y_pred, labels=labels, normalize='true') 20 | plt.figure(figsize=(14, 12)) 21 | plt.imshow(cm, interpolation='nearest', cmap=cmap) 22 | plt.title(title, fontsize=40) 23 | plt.colorbar() 24 | tick_marks = np.arange(len(classes)) 25 | plt.xticks(tick_marks, classes, fontsize=20) 26 | plt.yticks(tick_marks, classes, fontsize=20) 27 | 28 | # print('Confusion matrix, without normalization') 29 | 30 | thresh = cm.max() / 2. 31 | for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): 32 | plt.text(j, i, format(cm[i, j], '.2f'), 33 | horizontalalignment="center", 34 | color="white" if cm[i, j] > thresh else "black", 35 | fontsize=30) 36 | 37 | plt.ylabel('True label', fontsize=30) 38 | plt.xlabel('Predicted label', fontsize=30) 39 | # save your path,you can choose your path and change it 40 | if save_flg: 41 | plt.savefig("confusion_matrix" + str(sub) + ".png") 42 | 43 | 44 | 45 | def plt_tsne(data, label, per, nsub): 46 | 47 | data = data.cpu().detach().numpy() 48 | data = reduce(data, 'b n e -> b e', reduction='mean') 49 | label = label.cpu().detach().numpy() 50 | 51 | tsne = manifold.TSNE(n_components=2, perplexity=per, init='pca', random_state=166, learning_rate=200, n_iter=1000) 52 | X_tsne = tsne.fit_transform(data) 53 | 54 | x_min, x_max = X_tsne.min(0), X_tsne.max(0) 55 | X_norm = (X_tsne - x_min) / (x_max - x_min) 56 | plt.figure(figsize=(10, 8)) 57 | 58 | color_list = ['blue', 'red', 'green', 'orange'] 59 | 60 | unique_labels = np.unique(label) 61 | num_classes = len(unique_labels) 62 | 63 | label_to_color = {unique_labels[i]: color_list[i % len(color_list)] for i in range(num_classes)} 64 | 65 | for i in range(X_norm.shape[0]): 66 | plt.scatter(X_norm[i, 0], X_norm[i, 1], color=label_to_color[label[i]], s=50, alpha=0.8) # 增加点的大小和透明度 67 | 68 | plt.xticks([]) 69 | plt.yticks([]) 70 | plt.title('t-SNE visualization') 71 | 72 | plt.savefig('EEGNet_%d.png' % (nsub), dpi=600) 73 | 74 | 75 | 76 | def plot_metrics(train_losses, train_accuracies, nSub): 77 | epochs = range(1, len(train_losses) + 1) 78 | fig, ax1 = plt.subplots(figsize=(10, 5)) 79 | 80 | ax2 = ax1.twinx() 81 | ax1.plot(epochs, train_losses, 'g-', label='Training loss') 82 | ax2.plot(epochs, train_accuracies, 'r-', label='Training accuracy') 83 | 84 | ax1.set_xlabel('Epochs') 85 | ax1.set_ylabel('Loss', color='g') 86 | ax2.set_ylabel('Accuracy', color='r') 87 | 88 | 89 | lines1, labels1 = ax1.get_legend_handles_labels() 90 | lines2, labels2 = ax2.get_legend_handles_labels() 91 | 92 | 93 | combined_legend = ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper right', bbox_to_anchor=(0.5, 0.5)) 94 | 95 | ax1.add_artist(combined_legend) # 添加合并的图例 96 | 97 | plt.title('Training Loss and Accuracy') 98 | plt.savefig('training_metrics_subject_%d.png' % (nSub)) 99 | plt.show() 100 | 101 | -------------------------------------------------------------------------------- /New train folder/read_data.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import mne\n", 10 | "import scipy\n", 11 | "import torch\n", 12 | "from torchsummary import summary\n", 13 | "from EEGNet import EEGNet" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# 读取数据" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 3, 26 | "metadata": {}, 27 | "outputs": [ 28 | { 29 | "name": "stdout", 30 | "output_type": "stream", 31 | "text": [ 32 | "(1000, 22, 288)\n", 33 | "(288, 1)\n" 34 | ] 35 | } 36 | ], 37 | "source": [ 38 | "raw = scipy.io.loadmat(r'C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\BCICIV_2a_gdf\\A01T.mat')\n", 39 | "# 4x250, 22, 288 250为sample_rate 4为4秒的取值\n", 40 | "data = raw['data']\n", 41 | "label = raw['label']\n", 42 | "print(data.shape)\n", 43 | "print(label.shape)" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "# 进行维度的转换" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 4, 56 | "metadata": {}, 57 | "outputs": [ 58 | { 59 | "name": "stdout", 60 | "output_type": "stream", 61 | "text": [ 62 | "(288, 22, 1000)\n" 63 | ] 64 | } 65 | ], 66 | "source": [ 67 | "data = data.transpose(2, 1, 0)\n", 68 | "print(data.shape)" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": {}, 74 | "source": [ 75 | "# 标准的EEGNet及其神经网络的输入" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 5, 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "data": { 85 | "text/plain": [ 86 | "(288, 1, 22, 1000)" 87 | ] 88 | }, 89 | "execution_count": 5, 90 | "metadata": {}, 91 | "output_type": "execute_result" 92 | } 93 | ], 94 | "source": [ 95 | "data = data.reshape(data.shape[0], 1, data.shape[1], data.shape[2])\n", 96 | "data.shape" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "# 查看EEGNet的模型架构" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 6, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "----------------------------------------------------------------\n", 116 | " Layer (type) Output Shape Param #\n", 117 | "================================================================\n", 118 | " ZeroPad2d-1 [48, 1, 22, 1063] 0\n", 119 | " Conv2d-2 [48, 8, 22, 1000] 512\n", 120 | " BatchNorm2d-3 [48, 8, 22, 1000] 16\n", 121 | " Conv2d-4 [48, 16, 1, 1000] 352\n", 122 | " BatchNorm2d-5 [48, 16, 1, 1000] 32\n", 123 | " ELU-6 [48, 16, 1, 1000] 0\n", 124 | " AvgPool2d-7 [48, 16, 1, 250] 0\n", 125 | " Dropout-8 [48, 16, 1, 250] 0\n", 126 | " ZeroPad2d-9 [48, 16, 1, 266] 0\n", 127 | " Conv2d-10 [48, 16, 1, 251] 256\n", 128 | " Conv2d-11 [48, 16, 1, 251] 256\n", 129 | " BatchNorm2d-12 [48, 16, 1, 251] 32\n", 130 | " ELU-13 [48, 16, 1, 251] 0\n", 131 | " AvgPool2d-14 [48, 16, 1, 31] 0\n", 132 | " Dropout-15 [48, 16, 1, 31] 0\n", 133 | " Linear-16 [48, 4] 1,988\n", 134 | "================================================================\n", 135 | "Total params: 3,444\n", 136 | "Trainable params: 3,444\n", 137 | "Non-trainable params: 0\n", 138 | "----------------------------------------------------------------\n", 139 | "Input size (MB): 4.03\n", 140 | "Forward/backward pass size (MB): 165.78\n", 141 | "Params size (MB): 0.01\n", 142 | "Estimated Total Size (MB): 169.83\n", 143 | "----------------------------------------------------------------\n" 144 | ] 145 | } 146 | ], 147 | "source": [ 148 | "model = EEGNet(4).to('cuda')\n", 149 | "summary(input_size=(1, 22, 1000), batch_size=48, device='cuda', model=model)" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 7, 155 | "metadata": {}, 156 | "outputs": [ 157 | { 158 | "name": "stdout", 159 | "output_type": "stream", 160 | "text": [ 161 | "Extracting EDF parameters from C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\BCICIV_2a_gdf\\A01T.gdf...\n", 162 | "GDF file detected\n", 163 | "Setting channel info structure...\n", 164 | "Could not determine channel type of the following channels, they will be set as EEG:\n", 165 | "EEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG, EOG-left, EOG-central, EOG-right\n", 166 | "Creating raw.info structure...\n" 167 | ] 168 | }, 169 | { 170 | "name": "stderr", 171 | "output_type": "stream", 172 | "text": [ 173 | "E:\\Anaconda3\\lib\\contextlib.py:126: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n", 174 | " next(self.gen)\n" 175 | ] 176 | }, 177 | { 178 | "name": "stdout", 179 | "output_type": "stream", 180 | "text": [ 181 | "Reading 0 ... 672527 = 0.000 ... 2690.108 secs...\n" 182 | ] 183 | }, 184 | { 185 | "data": { 186 | "text/html": [ 187 | "
\n", 188 | " General\n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | "
Measurement dateJanuary 17, 2005 12:00:00 GMT
ExperimenterUnknown
ParticipantA01
\n", 211 | "
\n", 212 | "
\n", 213 | " Channels\n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | "
Digitized pointsNot available
Good channels25 EEG
Bad channelsNone
EOG channelsNot available
ECG channelsNot available
\n", 238 | "
\n", 239 | "
\n", 240 | " Data\n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | "
Sampling frequency250.00 Hz
Highpass0.50 Hz
Lowpass100.00 Hz
\n", 264 | "
" 265 | ], 266 | "text/plain": [ 267 | "" 280 | ] 281 | }, 282 | "execution_count": 7, 283 | "metadata": {}, 284 | "output_type": "execute_result" 285 | } 286 | ], 287 | "source": [ 288 | "raw = mne.io.read_raw_gdf(r'C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\BCICIV_2a_gdf\\A01T.gdf', preload=True)\n", 289 | "raw.info" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": 10, 295 | "metadata": {}, 296 | "outputs": [ 297 | { 298 | "data": { 299 | "text/html": [ 300 | "
\n", 301 | " General\n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | "
Measurement dateJanuary 17, 2005 12:00:00 GMT
ExperimenterUnknown
ParticipantA01
\n", 324 | "
\n", 325 | "
\n", 326 | " Channels\n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | "
Digitized pointsNot available
Good channels25 EEG
Bad channelsNone
EOG channelsNot available
ECG channelsNot available
\n", 351 | "
\n", 352 | "
\n", 353 | " Data\n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 362 | " \n", 363 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 370 | " \n", 371 | " \n", 372 | " \n", 373 | " \n", 374 | " \n", 375 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | "
Sampling frequency250.00 Hz
Highpass0.50 Hz
Lowpass100.00 Hz
FilenamesA01T.gdf
Duration00:44:51 (HH:MM:SS)
\n", 387 | "
" 388 | ], 389 | "text/plain": [ 390 | "" 391 | ] 392 | }, 393 | "execution_count": 10, 394 | "metadata": {}, 395 | "output_type": "execute_result" 396 | }, 397 | { 398 | "ename": "", 399 | "evalue": "", 400 | "output_type": "error", 401 | "traceback": [ 402 | "\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n", 403 | "\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n", 404 | "\u001b[1;31m单击此处了解详细信息。\n", 405 | "\u001b[1;31m有关更多详细信息,请查看 Jupyter log。" 406 | ] 407 | } 408 | ], 409 | "source": [ 410 | "raw" 411 | ] 412 | } 413 | ], 414 | "metadata": { 415 | "kernelspec": { 416 | "display_name": ".venv", 417 | "language": "python", 418 | "name": "python3" 419 | }, 420 | "language_info": { 421 | "codemirror_mode": { 422 | "name": "ipython", 423 | "version": 3 424 | }, 425 | "file_extension": ".py", 426 | "mimetype": "text/x-python", 427 | "name": "python", 428 | "nbconvert_exporter": "python", 429 | "pygments_lexer": "ipython3", 430 | "version": "3.9.7" 431 | } 432 | }, 433 | "nbformat": 4, 434 | "nbformat_minor": 2 435 | } 436 | -------------------------------------------------------------------------------- /New train folder/train.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import numpy as np 4 | from EEGNet import EEGNet 5 | import scipy 6 | from torch.autograd import Variable 7 | from sklearn.metrics import cohen_kappa_score 8 | from metrics import plot_confusion_matrix, plot_metrics 9 | import random 10 | 11 | gpus = [0] 12 | 13 | # 输入的shape 14 | # (288, 1, 22, 1000) (trial, cov_number, channel, timepiont) (batch_size, channel, width, height) 15 | # (batch_size, RGB, height, width) 16 | class Trans(): 17 | def __init__(self, nsub): 18 | super(Trans, self).__init__() 19 | self.batch_size = 50 20 | self.n_epochs = 1000 21 | self.lr = 0.0002 22 | self.b1 = 0.5 23 | self.b2 = 0.9 24 | self.nSub = nsub 25 | self.start_epoch = 0 26 | self.root = 'C:\\Users\\24242\\Desktop\\AI_Reference\\data_bag\\BCICIV_2a_gdf\\' # the path of data 27 | self.pretrain = False 28 | self.Tensor = torch.cuda.FloatTensor 29 | self.LongTensor = torch.cuda.LongTensor 30 | self.model = EEGNet(4).cuda() 31 | self.model = nn.DataParallel(self.model, device_ids=[i for i in range(len(gpus))]) 32 | self.model = self.model.cuda() 33 | self.centers = {} 34 | self.criterion = nn.CrossEntropyLoss() 35 | 36 | def get_source_data(self): 37 | self.total_data = scipy.io.loadmat(self.root + 'A0%dT.mat' % self.nSub) 38 | self.train_data = self.total_data['data'] 39 | self.train_label = self.total_data['label'] 40 | self.train_data = np.transpose(self.train_data, (2, 1, 0)) 41 | self.train_data = np.expand_dims(self.train_data, axis=1) # (288, 1, 22, 1000) 42 | self.train_label = np.transpose(self.train_label) 43 | self.allData = self.train_data 44 | self.allLabel = self.train_label[0] 45 | self.test_tmp = scipy.io.loadmat(self.root + 'A0%dE.mat' % self.nSub) 46 | self.test_data = self.test_tmp['data'] 47 | self.test_label = self.test_tmp['label'] 48 | self.test_data = np.transpose(self.test_data, (2, 1, 0)) 49 | self.test_data = np.expand_dims(self.test_data, axis=1) 50 | self.test_label = np.transpose(self.test_label) 51 | self.testData = self.test_data 52 | self.testLabel = self.test_label[0] 53 | # 归一化 54 | target_mean = np.mean(self.allData) 55 | target_std = np.std(self.allData) 56 | self.allData = (self.allData - target_mean) / target_std 57 | self.testData = (self.testData - target_mean) / target_std 58 | return self.allData, self.allLabel, self.testData, self.testLabel 59 | 60 | def update_lr(self, optimizer, lr): 61 | for param_group in optimizer.param_groups: 62 | param_group['lr'] = lr 63 | 64 | def calculate_kappa(self, y_true, y_pred): 65 | kappa = cohen_kappa_score(y_true.cpu().numpy(), y_pred.cpu().numpy()) 66 | return kappa 67 | 68 | def interaug(self, timg, label): 69 | aug_data = [] 70 | aug_label = [] 71 | for cls4aug in range(4): 72 | cls_idx = np.where(label == cls4aug + 1) 73 | tmp_data = timg[cls_idx] 74 | tmp_label = label[cls_idx] 75 | tmp_aug_data = np.zeros((int(self.batch_size / 4), 1, 22, 1000)) 76 | for ri in range(int(self.batch_size / 4)): 77 | for rj in range(8): 78 | rand_idx = np.random.randint(0, tmp_data.shape[0], 8) 79 | tmp_aug_data[ri, :, :, rj * 125:(rj + 1) * 125] = tmp_data[rand_idx[rj], :, :, rj * 125:(rj + 1) * 125] 80 | aug_data.append(tmp_aug_data) 81 | aug_label.append(tmp_label[:int(self.batch_size / 4)]) 82 | aug_data = np.concatenate(aug_data) 83 | aug_label = np.concatenate(aug_label) 84 | aug_shuffle = np.random.permutation(len(aug_data)) 85 | aug_data = aug_data[aug_shuffle, :, :] 86 | aug_label = aug_label[aug_shuffle] 87 | aug_data = torch.from_numpy(aug_data).cuda() 88 | aug_data = aug_data.float() 89 | aug_label = torch.from_numpy(aug_label - 1).cuda() 90 | aug_label = aug_label.long() 91 | return aug_data, aug_label 92 | 93 | def train(self): 94 | img, label, test_data, test_label = self.get_source_data() 95 | img = torch.from_numpy(img) 96 | label = torch.from_numpy(label - 1) 97 | dataset = torch.utils.data.TensorDataset(img, label) 98 | self.dataloader = torch.utils.data.DataLoader(dataset=dataset, batch_size=self.batch_size, shuffle=True) 99 | test_data = torch.from_numpy(test_data) 100 | test_label = torch.from_numpy(test_label - 1) 101 | test_dataset = torch.utils.data.TensorDataset(test_data, test_label) 102 | self.test_dataloader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=self.batch_size, shuffle=True) 103 | test_data = Variable(test_data.type(self.Tensor)) 104 | test_label = Variable(test_label.type(self.LongTensor)) 105 | bestAcc = 0 106 | averAcc = 0 107 | num = 0 108 | Y_true = 0 109 | Y_pred = 0 110 | 111 | train_losses = [] 112 | train_accuracies = [] 113 | 114 | for e in range(self.n_epochs): 115 | self.model.train() 116 | for i, (img, label) in enumerate(self.dataloader): 117 | img = Variable(img.cuda().type(self.Tensor)) 118 | label = Variable(label.cuda().type(self.LongTensor)) 119 | aug_data, aug_label = self.interaug(self.allData, self.allLabel) 120 | img = torch.cat((img, aug_data)) 121 | label = torch.cat((label, aug_label)) 122 | outputs = self.model(img) 123 | print(label.shape) 124 | loss = self.criterion(outputs, label) 125 | self.optimizer = torch.optim.Adam(self.model.parameters(), lr=self.lr, betas=(self.b1, self.b2)) 126 | self.optimizer.zero_grad() 127 | loss.backward() 128 | self.optimizer.step() 129 | 130 | 131 | 132 | 133 | if (e + 1) % 1 == 0: 134 | self.model.eval() 135 | outputs_test= self.model(test_data) 136 | loss_test = self.criterion(outputs_test, test_label) 137 | y_pred = torch.max(outputs_test, 1)[1] 138 | acc = float((y_pred == test_label).cpu().numpy().astype(int).sum()) / float(test_label.size(0)) 139 | train_pred = torch.max(outputs, 1)[1] 140 | train_acc = float((train_pred == label).cpu().numpy().astype(int).sum()) / float(label.size(0)) 141 | print('Epoch:', e, 142 | ' Train loss:', loss.detach().cpu().numpy(), 143 | ' Test loss:', loss_test.detach().cpu().numpy(), 144 | ' Train accuracy:', train_acc, 145 | ' Test accuracy is:', acc) 146 | train_losses.append(loss.detach().cpu().numpy()) 147 | train_accuracies.append(train_acc) 148 | num = num + 1 149 | averAcc = averAcc + acc 150 | if acc > bestAcc: 151 | bestAcc = acc 152 | Y_true = test_label 153 | Y_pred = y_pred 154 | 155 | 156 | 157 | # if e == self.n_epochs - 1: 158 | 159 | # plt_tsne(outputs_test, test_label, per=30, nsub=self.nSub) 160 | # plt_tsne(test_label, per=30, nsub=self.nSub) 161 | 162 | # you can save the model state_dict in your path 163 | # torch.save(self.model.module.state_dict(), '/root/autodl-tmp/model_picture/TFCformer_model_Subject_%d.pth' % (self.nSub)) 164 | averAcc = averAcc / num 165 | print('The average accuracy is:', averAcc) 166 | print('The best accuracy is:', bestAcc) 167 | kappa = self.calculate_kappa(Y_true, Y_pred) 168 | print('The kappa score is:', kappa) 169 | plot_metrics(train_losses, train_accuracies, self.nSub) 170 | return bestAcc, averAcc, Y_true, Y_pred, kappa 171 | 172 | 173 | 174 | def main(): 175 | best = 0 176 | aver = 0 177 | for i in range(9): 178 | seed_n = np.random.randint(500) 179 | print('seed is ' + str(seed_n)) 180 | random.seed(seed_n) 181 | np.random.seed(seed_n) 182 | torch.manual_seed(seed_n) 183 | torch.cuda.manual_seed(seed_n) 184 | torch.cuda.manual_seed_all(seed_n) 185 | print('Subject %d' % (i+1)) 186 | trans = Trans(i + 1) 187 | bestAcc, averAcc, Y_true, Y_pred, kappa = trans.train() 188 | print('THE BEST ACCURACY IS ' + str(bestAcc)) 189 | plot_confusion_matrix(Y_true, Y_pred, i+1) 190 | best = best + bestAcc 191 | aver = aver + averAcc 192 | if i == 0: 193 | yt = Y_true 194 | yp = Y_pred 195 | else: 196 | yt = torch.cat((yt, Y_true)) 197 | yp = torch.cat((yp, Y_pred)) 198 | plot_confusion_matrix(yt, yp, 666) 199 | 200 | 201 | if __name__ == '__main__': 202 | 203 | main() -------------------------------------------------------------------------------- /New train folder/training_metrics_subject_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XCZchaos/python-implementation-of-motion-imagination-classification/238c22858402277b51a80c7d9f6d03c17a9f5aa0/New train folder/training_metrics_subject_1.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python-implementation-of-motion-imagination-classification 2 | This repository corresponds to the code for my blog 3 | 4 | 5 | 6 | 7 | And some of my notes from BCI learning are uploaded here, but the notes are in Chinese 8 | 9 | Thank you for your interest in this repository 10 | 11 | 12 | 13 | If you have some questions, Please contact me. 14 | 15 | 16 | E-mail:asherxiong552@gmail.com 17 | 18 | 19 | 20 | 21 | updata log: 22 | Updated the New folder 'New train fold',If you want to learn more,please read the file 'Readme.md' in 'New train folder' 23 | --------Edited on 2024/8/14 24 | -------------------------------------------------------------------------------- /mne包教程.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XCZchaos/python-implementation-of-motion-imagination-classification/238c22858402277b51a80c7d9f6d03c17a9f5aa0/mne包教程.pdf -------------------------------------------------------------------------------- /脑机接口导论笔记.md: -------------------------------------------------------------------------------- 1 | ### 论文知识 2 | 3 | 我们在进行运动想象事件当中,我们一般都使用C3 C4两个通道,Cz通道其实对运动想象的结果并没有那么大,C3和C4、Cz三者组成的是大脑的感觉运动皮层,而β节律是主要运动想象所需的节律 4 | 5 | ![img](https://pic2.zhimg.com/80/v2-9956a285c0e96767ba12912178af99d1_720w.webp) 6 | 7 | 8 | 9 | 10 | 11 | 想象肢体运动时,对应皮层投射区域出现脑电节律调制现象。当想象左手运动时,大脑右半球C4区域神经电活动增强,该区域的信息加工导致EEG功率谱出现减弱现象;当想象右手运动时,大脑左半球C3区域神经电活动增强,其EEG功率谱出现减弱现象;而对应脚和舌头的ERD/ERS现象分别出现在大脑顶叶和颞叶,大致为Cz和CP6区域。不同运动想象任务时所激活的脑区如下图1所示,其空间分布符合周围神经纤维与大脑皮层投射关系,与脑功能分区图相一致,因此,运动想象脑电信号具有空间特性。 12 | 13 | ERD/ERS现象主要出现在频率范围在8-12Hz的mu节律和频率范围在18-26Hz的beta节律,特别是mu节律变化最为显著。但是不同任务的运动想象脑电在特征频段上也有差别,对应手的ERD经常出现在10-12Hz和20-24Hz,对应脚的ERD经常出现在7-8Hz和20-24Hz,对应舌头的ERS经常出现在10-11Hz,并且运动想象脑电频段是与特定人相关的,因此,运动想象脑电信号还具有频段特性,合理选择最佳的滤波器及滤波频段是后续处理提高分类效果的关键。 14 | 15 | ### 第三章、记录大脑信号和刺激大脑 16 | 17 | EEG信号反应的是上千个神经元产生的突出后点位的总和。EEG信号通常会被其他行为干扰,比如眼动等与实验无关行为产生的点位,还有一些设备因素,比如工频干扰(国内50HZ),我们一般使用凹陷滤波进行去除工频干扰。 18 | 19 | 记住几个比较特殊的电极位置,比如挂在耳垂的乳突(A1,A2)以及中间的电极CZ和CZ两侧的电极C3和C4,这对运动想象实验来说比较重要 20 | 21 | 在测量EEG信号时,可以测量一对电极之间的电位差。测量各个电极的电位和一个中性电极或者所有电极的平均值(共同平均参考或者CAR) 22 | 23 | 当我们进行运动想象时,alpha节律(mu节律,范围为8~13HZ)会减少,而beta节律(范围为13~30HZ)会增强。 24 | 25 | ### 第四章、信号处理 26 | 27 | #### 1.锋电位分类 28 | 29 | 我们看脑电图像时,会看到很多条周期函数混合在一起,因为电极记录的是局部神经元进行的放电,并把其局部所有神经元的峰值电位混合在了一起。 30 | 31 | 锋电位分类在信号处理时,能够可靠地分离和提取每个记录电极采集的由单个神经元发出的锋电位 32 | 33 | #### 2.频域分析 34 | 35 | 傅里叶变换将一个区间[-T/2,T/2]中的事件信号t(s)分解为无限多个正弦和余弦函数加权和 36 | 37 | 正弦和余弦波可以视为基本函数,将这些函数以不同的加权,从而可以得到不同的信号,这一过程即为信号合成,其权值可以由输入的信号计算出来 38 | 39 | 傅里叶变换运用于滤波当中,如利用凹陷滤波去除工频干扰,将输入信号进行重构,使得重构后的信号不包含该特征。权值的求解是对时域函数*特征频率的正弦或者余弦函数在[-T/2,T/2]上进行积分 40 | 41 | #### 3.频谱特征 42 | 43 | 从一段时间间隔内大脑信号的功率谱中提取特征,在进行运动想象时,beta节律会增强,alpha节律会减少。具体的频谱怎么用,参照mne包中的笔记 44 | 45 | #### 4.小波分析 46 | 47 | 由于EEG等大脑信号是非平稳信号,所以在短时窗内进行傅里叶分析,这种方法被称为短时傅里叶变换。小波变换的基函数不再是正弦和余弦函数,小波函数是由一个有限长的母小波通过伸缩和平移得到,小波函数有限的长度使其可以用来表示非周期信号或是有陡变不连续的信号。 48 | 49 | 小波变换也是用基函数的线性组合来表示原信号 50 | 51 | #### 5.时域分析 52 | 53 | ##### 分形维数 54 | 55 | 如果一个信号表现出自相似性,则认为它分形的,信号的一部分与整个信号都具有相似性。分形维数是对这种相似性的定量测量。EEG的大脑信号的分形维数一般在1.4和1.7之间,值越大表明发生了高锋电位的活动,例如癫痫。 56 | 57 | ##### 自回归模型 58 | 59 | 自然信号在时间或者空间等其他维度上有着相关的趋势,因此常常能用之前的一些测量值来预测下一个测量值。贝叶斯滤波和卡尔曼滤波也是该递归原理,利用上一项计算下一项 60 | 61 | #### 6.空间滤波 62 | 63 | 空间滤波将不同位置记录大脑信号通过几种方式进行信号转换,目的是增强局部活动、减弱各通道中的共有噪声、降低噪声维数,识别隐含的源,找到能最大程度区分不同类别的投影 64 | 65 | 双极信号通过计算两极之间的电位差来进行处理 66 | 67 | 拉普拉斯滤波是将电极减去四个正交的最邻近电极信号的平均值,共同平均参考则是减去所有电极的平均值 68 | 69 | ##### 主成分分析 70 | 71 | 如果有64位通道、一次实验中可获取N个64维向量组成的数据集,所以在一次实验中会获得N*64个数据 72 | 73 | PCA会选找到L位数据中方差最大的方向,将原坐标旋转变换到最大方差的方向上,如果原数据是冗余的,并且保留一些方差大的方向,那么就可以丢弃方差小的方向上的坐标,使得数据维度降低 74 | 75 | 大多数自然自然信号,从多个位置记录到大脑信号都可能是冗余的,因此可以进行降维操作,PCA可以利用这些冗余,试图去寻找数据差异性的主方向。如果找到了这些低位子空间的主方向,那么就可以将原数据进行主方向上投影,从而达到降维效果,得到M维向量就可以用做分类任务的特征向量 76 | 77 | 复习以下协方差矩阵的概念以及拉格朗日乘子法来计算特征值 78 | 79 | ##### 独立分量分析 80 | 81 | PCA能确保协方差为零,但是无法确保两个随机变量具有高阶独立性,在高阶时,两个变量的协方差不一定为零,比如在平方时可能不为零导致变量不独立 82 | 83 | 地形图判断严重的原理是,对前额和眼睛附近的主成分进行正值和负值的加权从而得到区分度 84 | 85 | ICA与PCA的不同在W矩阵中的行向量不再需要满足正交的条件,而且PCA中向量a的维度小于且最多等于输入x的维数,而ICA特征向量的维数可以小于、等于或者大于输入的维数 86 | 87 | ##### 共空间模式 88 | 89 | PCA和ICA都是无监督学习,而CSP是一种监督方法,每个训练数据都是被标记过的,每个数据向量类型都是已知 90 | 91 | CSP寻找空间滤波器,使滤波处理后的数据与其中一类的方差达到最大,而与另一类的方差达到最小,因而,得到的特征向量增强了两类之间的差别 92 | 93 | CSP是实质上使得BCI所使用特征的可区分程度最大化 94 | 95 | --------------------------------------------------------------------------------