脑电EEG代码开源分享 【1.前置准备-静息态篇】
往期文章
希望了解更多的道友點這里
0. 分享【腦機接口 + 人工智能】的學習之路
1.1 . 腦電EEG代碼開源分享 【1.前置準備-靜息態篇】
1.2 . 腦電EEG代碼開源分享 【1.前置準備-任務態篇】
2.1 . 腦電EEG代碼開源分享 【2.預處理-靜息態篇】
2.2 . 腦電EEG代碼開源分享 【2.預處理-任務態篇】
3.1 . 腦電EEG代碼開源分享 【3.可視化分析-靜息態篇】
3.2 . 腦電EEG代碼開源分享 【3.可視化分析-任務態篇】
4.1 . 腦電EEG代碼開源分享 【4.特征提取-時域篇】
4.2 . 腦電EEG代碼開源分享 【4.特征提取-頻域篇】
4.3 . 腦電EEG代碼開源分享 【4.特征提取-時頻域篇】
4.4 . 腦電EEG代碼開源分享 【4.特征提取-空域篇】
5 . 腦電EEG代碼開源分享 【5.特征選擇】
6.1 . 腦電EEG代碼開源分享 【6.分類模型-機器學習篇】
6.2 . 腦電EEG代碼開源分享 【6.分類模型-深度學習篇】
匯總. 專欄:腦電EEG代碼開源分享【文檔+代碼+經驗】
0 . 【深度學習】常用網絡總結
腦電EEG代碼開源分享 【1.前置準備-靜息態篇】
- 往期文章
- 一、前言
- 二、前置準備 框架介紹
- 三、代碼格式說明
- 三、腦電處理 代碼
- 3.0 參數設置
- 3.1 數據導入
- 3.2 前置準備-主函數
- 3.3 前置準備-功能函數
- 3.4 前置準備-結果保存
- 四、前置準備 整體代碼
- 總結
- To:新想法、鬼點子的道友:
一、前言
本文檔旨在歸納BCI-EEG-matlab的數據處理代碼,作為EEG數據處理的總結,方便快速搭建處理框架的Baseline,實現自動化、模塊插拔化、快速化。本文非鎖時任務(無鎖時刺激,如靜息態、運動想象)為例,分享腦電EEG的分析處理方法。
腦電數據分析系列。分為以下6個模塊:
1. 前置準備
2. 數據預處理
3. 數據可視化
4. 特征提取(特征候選集)
5. 特征選擇(量化特征擇優)
6. 分類模型
本文內容:【1.前置準備】
提示:以下為各功能代碼詳細介紹,若節約閱讀時間,請下滑至文末的整合代碼
二、前置準備 框架介紹
前置準備
前置準備的主要功能,分為以下4部分:
1. 降采樣
2. 數據分段
3. 去暫態
4. 選擇導聯
前期準備的代碼框圖、流程如下所示:
注:前置準備 理論上可以歸類到 預處理階段,本代碼將兩者分開基于以下考慮:
三、代碼格式說明
本文非鎖時任務態(下文以靜息態代替)范例為:ADHD患者、正常人群在靜息狀態下的腦模式分類
- 分段代碼名稱:代碼命名為Standard_cut_rest
- 輸入格式:靜息態為Data的結構體,內部為data命名的原始數據(通道*總采樣點數)。
- 參數設置:**采樣率\單試次時長\試次標簽\試次位置\頻域去除暫態時長\降采樣(防止數據過大導致運行和內存消耗)
- 處理形式:**EEG數據匯總為cell(試次被試數),每個cell內為(通道數采樣點數)。按照不同分類的類別放入不同cell,cell自身名稱如下保存格式名稱。例如任務態數據為{100,1}[16*512],其意為16通道數據采集,100試次,單試次為512點數據點。
- **保存格式:**單獨保存個人的名稱為Standard_input_target_xx(被試序號),總保存文件名稱為Standard_input_target\ nontarget _xx代表被試個數。
三、腦電處理 代碼
提示:代碼環境為 matlab 2018
3.0 參數設置
原采樣率 fs_raw=500Hz,降低到 fs_down = 250Hz
一次進行10人次的批處理,subject_num = [1;10]
每段數據分段長度為2秒,epoch_length = 2
處理全部導聯編號為1-128的電極,perocess_channel = [1 ; 128];
經驗建議:
- 采樣率降到300Hz以下,目前主流研究認為,靜息態腦電有效頻率<100Hz,根據腦奎斯特定理,采樣率到200Hz以上即可。采樣率是最影響計算時間的參數之一,尤其影響后期的非線性計算,繪圖、特征分析等。
- 建議每批處理人數<10人,如有大量被試應分為多組。一是由于多被試處理時間長,中間運算和調試周期較長;二是多被試計算結果存儲量大,MATLAB對于2GB以上的數據存儲較慢,并且下一階段讀取也緩慢。
- 去暫態20s,temp_abandon = 20,是由于一般腦電設備開機后需要穩定波形,這個數值要根據設備、現場環境修改。
3.1 數據導入
導入原始數據,并輸出顯示基本數據信息:
%% 1.Standard_input % 0.1 rest_data 輸入數據格式為:通道數*采樣點數 standard_time = floor(size(raw_temp_data,2)/fs_raw- temp_abandon); remain_raw_time = standard_time - temp_abandon; remain_trial = floor(remain_raw_time/epoch_length); remain_confrim_time = remain_trial * epoch_length;disp(['數據總時長: ' , num2str(standard_time) , '||暫態時長: ' , num2str(temp_abandon), '||修正剩余時長: ' , num2str(remain_confrim_time)]); disp(['采樣率: ' , num2str(fs_raw), '||每段時長: ' , num2str(epoch_length), '||試次數量: ' , num2str(remain_trial)]);3.2 前置準備-主函數
主要功能依靠調用 Standard_cut_rest 函數實現:
%% 1.切分數據 disp(['數據分段中...']); Standard_input_target = []; Standard_input_nontarget = [];Standard_input_target.fs = fs_down; Standard_input_nontarget.fs = fs_down;Standard_input_target.subject_num = subject_num; Standard_input_nontarget.subject_num = subject_num;[Standard_input_target.data,Standard_input_nontarget.data] = Standard_cut_rest(data_path,stuct_name,file_name_target,file_name_nontarget,fs_raw,fs_down,subject_num,remain_trial,epoch_length,temp_abandon,perocess_channel); Standard_input_target.file = file_name_target; Standard_input_nontarget.file = file_name_nontarget; disp(['||已完成標準分段||']);3.3 前置準備-功能函數
主功能函數 Standard_cut_rest :
function[Standard_input_target,Standard_input_nontarget] = Standard_cut_rest(data_path,stuct_name,file_name_target,file_name_nontarget,fs_raw,fs_down,subject_num,remain_trial,epoch_length,temp_abandon,perocess_channel) %% 0.參數說明 % data_path 數據路徑 % file_name_target 目標數據統一名 % file_name_nontarget 非目標數據統一名 % fs_raw 原始數據采樣率 % subject_num 被試起止編號 % remain_trial 剩余試次數 % epoch_length 單試次時長 % temp_abandon 暫態去除時長 % perocess_channel 有效數據通道的首末 Standard_input_target = cell(remain_trial,subject_num(2,1)-subject_num(1,1)+1); Standard_input_nontarget = cell(remain_trial,subject_num(2,1)-subject_num(1,1)+1);%% 1.切分數據 print_count=0; sub_count = 1; for sub_loop = subject_num(1,1):subject_num(2,1) raw_data_target = load ([data_path ,file_name_target , num2str(sub_loop)]); raw_data_target = raw_data_target.(stuct_name).data; raw_data_target = downsample(raw_data_target',fs_raw/fs_down)';raw_data_nontarget = load ([data_path ,file_name_nontarget , num2str(sub_loop)]); raw_data_nontarget = raw_data_nontarget.(stuct_name).data; raw_data_nontarget = downsample(raw_data_nontarget',fs_raw/fs_down)';temp_abandon_point = temp_abandon * fs_down; for trial_loop = 1:remain_trialcut_temp = [];cut_temp = raw_data_target(perocess_channel(1,1):perocess_channel(2,1), temp_abandon_point+ (trial_loop-1)*fs_down*epoch_length+1 : temp_abandon_point + trial_loop*fs_down*epoch_length);Standard_input_target{trial_loop,sub_count} = cut_temp;cut_temp = [];cut_temp = raw_data_nontarget(:, temp_abandon_point+ (trial_loop-1)*fs_down*epoch_length+1 : temp_abandon_point + trial_loop*fs_down*epoch_length);Standard_input_nontarget{trial_loop,sub_count} = cut_temp; end % disp(['輸入標準化分段: ' , num2str(sub_loop/subject_num)]);fprintf(repmat('\b',1,print_count)); print_count=fprintf('計算標準化分段進度 : %f',sub_count/(subject_num(2,1) - subject_num(1,1)+1)); sub_count = sub_count+1; end fprintf('\n'); end3.4 前置準備-結果保存
最終,結果保存:
%% 2.保存標準輸入文件 disp(['標準分段保存中...']); save([ svae_path , 'Standard_input_target_',num2str(subject_num(1,1)),'_',num2str(subject_num(2,1))],'Standard_input_target'); save([ svae_path , 'Standard_input_nontarget_',num2str(subject_num(1,1)),'_',num2str(subject_num(2,1))],'Standard_input_nontarget'); disp(['||已完成標準分段保存||']); t_Standard_input_cost = toc; disp(['標準輸入格式調整完畢,耗時: ',num2str(t_Standard_input_cost)]);四、前置準備 整體代碼
靜息態信號整體代碼:
disp(['||0.靜息態類數據處理-標準輸入格式||']); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 0.!!!需手動調整參數 data_path = 'C:\Users\Amax\Desktop\basetest_flod\raw_data_flod\'; svae_path = 'C:\Users\Amax\Desktop\basetest_flod\save_fold\'; file_name_target = 'ADHD'; file_name_nontarget = 'Normal'; stuct_name = 'Data';raw_temp_data = load ([data_path ,file_name_target,'1']); raw_temp_data = raw_temp_data.Data.data; fs_raw = 500; fs_down = 250; %降采樣后采樣率 subject_num = [1;10]; temp_abandon = 20; %去掉的暫態,以秒為單位 epoch_length = 2; perocess_channel = [1 ; 128]; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% tic; %% 1.Standard_input % 0.1 rest_data 輸入數據格式為:通道數*采樣點數 standard_time = floor(size(raw_temp_data,2)/fs_raw- temp_abandon); remain_raw_time = standard_time - temp_abandon; remain_trial = floor(remain_raw_time/epoch_length); remain_confrim_time = remain_trial * epoch_length;disp(['數據總時長: ' , num2str(standard_time) , '||暫態時長: ' , num2str(temp_abandon), '||修正剩余時長: ' , num2str(remain_confrim_time)]); disp(['采樣率: ' , num2str(fs_raw), '||每段時長: ' , num2str(epoch_length), '||試次數量: ' , num2str(remain_trial)]);%% 1.切分數據 disp(['數據分段中...']); Standard_input_target = []; Standard_input_nontarget = [];Standard_input_target.fs = fs_down; Standard_input_nontarget.fs = fs_down;Standard_input_target.subject_num = subject_num; Standard_input_nontarget.subject_num = subject_num;[Standard_input_target.data,Standard_input_nontarget.data] = Standard_cut_rest(data_path,stuct_name,file_name_target,file_name_nontarget,fs_raw,fs_down,subject_num,remain_trial,epoch_length,temp_abandon,perocess_channel); Standard_input_target.file = file_name_target; Standard_input_nontarget.file = file_name_nontarget; disp(['||已完成標準分段||']);%% 2.保存標準輸入文件 disp(['標準分段保存中...']); save([ svae_path , 'Standard_input_target_',num2str(subject_num(1,1)),'_',num2str(subject_num(2,1))],'Standard_input_target'); save([ svae_path , 'Standard_input_nontarget_',num2str(subject_num(1,1)),'_',num2str(subject_num(2,1))],'Standard_input_nontarget'); disp(['||已完成標準分段保存||']); t_Standard_input_cost = toc; disp(['標準輸入格式調整完畢,耗時: ',num2str(t_Standard_input_cost)]);總結
前置準備是數據處理的敲門磚,本文僅進行了基礎的處理。
本文中靜息態的前置準備,通過主功能函數 Standard_cut_rest 實現
靜息態數據無時間錨點(triger,marker),數據分段較為簡單,一般分為等間距的數據段即可
當然
實際應用時會面臨很多潛在的工程問題,例如儀器數據格式、軟件運行內存、硬件運行時間等等…
代碼工程嘛,就是面對現實…
掛一漏萬,如有筆誤請大家指正~
感謝您耐心的觀看,本系列更新了約30000字,約3000行開源代碼,體量相當于一篇碩士工作。
往期內容放在了文章開頭,麻煩幫忙點點贊,分享給有需要的朋友~
堅定初心,本博客永遠:
免費拿走,全部開源,全部無償分享~
To:新想法、鬼點子的道友:
自己:腦機接口+人工智領域,主攻大腦模式解碼、身份認證、仿腦模型…
在讀博士第3年,在最后1年,希望將代碼、文檔、經驗、掉坑的經歷分享給大家~
做的不好請大佬們多批評、多指導~ 虛心向大伙請教!
想一起做些事情 or 奇奇怪怪點子 or 單純批評我的,請至Rongkaizhang_bci@163.com
總結
以上是生活随笔為你收集整理的脑电EEG代码开源分享 【1.前置准备-静息态篇】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux vim替换指定字符串
- 下一篇: 51单片机延时与按钮响应时间答复:模拟发