diff --git a/balanceClasses.m b/balanceClasses.m index 3ccbd98..c5574e4 100644 --- a/balanceClasses.m +++ b/balanceClasses.m @@ -5,7 +5,7 @@ r=floor(size(mostFrequent,2)*rand(1)+1); delIndex=mostFrequent(r); trainClasses=trainClasses([1:delIndex-1,delIndex+1:end]); - trainData=trainData([1:delIndex-1,delIndex+1:end]); + trainData=trainData([1:delIndex-1,delIndex+1:end],:); end assert(size(trainClasses,2)>0) end \ No newline at end of file diff --git a/classifyAccordingToEMG.m b/classifyAccordingToEMG.m new file mode 100644 index 0000000..79cdd2e --- /dev/null +++ b/classifyAccordingToEMG.m @@ -0,0 +1,15 @@ +function [classification]=classifyAccordingToEMG(trainingDataEEG, trainingDataEMG, classes,shift,frequency,threshold) + classification=zeros([size(trainingDataEEG,1),1]); + oldclass=0; + for i=1:size(trainingDataEEG,1) + if mean(trainingDataEMG(i,:)) > threshold % is movement + class=mode(classes(max(round(shift*frequency*i-frequency),1):min(round(i*shift*frequency-1),end))); + if class <= 5 % task is to move + classification(i)=class; + oldclass=class; + else % task is to rest but movement not finished + classification(i)=oldclass; + end + end + end +end \ No newline at end of file diff --git a/generateTrainingData.m b/generateTrainingData.m index 33ea013..bf0e6e2 100644 --- a/generateTrainingData.m +++ b/generateTrainingData.m @@ -1,27 +1,21 @@ -function [trainingDataEEG,trainingDataEMG] = generateTrainingData(splitSignals,NFFT,window,shift,params,secs) +function [trainingDataEEG,trainingDataEMG] = generateTrainingData(signal,NFFT,window,shift,params) frequency=params.SamplingRate.NumericValue; - tempEEG2=zeros([32,size(splitSignals,3),NFFT/2+1]); - tempEMG2=zeros(fix([size(splitSignals,2)-3-32,size(splitSignals,3),fix(floor(size(splitSignals,1)/(frequency*window))-1)*window/shift+1])); + signalWindow=frequency*window; + shiftProp=window/shift; + tempEEG=zeros([32,fix(floor(size(signal,1)/signalWindow)-1)*shiftProp+1,NFFT/2+1]); + tempEMG=zeros(fix([size(signal,2)-3-32,fix(floor(size(signal,1)/signalWindow)-1)*shiftProp+1])); %Filter around 50Hz and below 2 Hz [A,B]= butter(2,[48 52]/(frequency/2),'stop'); [C,D]= butter(2,2/(frequency/2),'high'); parfor i=1:32 %filter single channel, w/o HEOG, Synchro and 0s - tempEEG=zeros(size(splitSignals,3),NFFT/2+1); - for j=1:size(splitSignals,3) %filter single trial - tempEEG(j,:)=pwelch(filter(C,D,filter(A,B,splitSignals(1:secs*frequency,i,j))),[],[],NFFT,frequency); - end - tempEEG2(i,:,:)=tempEEG; + tempEEG(i,:,:)=shiftingPwelch(filter(C,D,filter(A,B,signal(:,i))),frequency,window,shift,NFFT); end - trainingDataEEG=permute(tempEEG2,[2 1 3]); + trainingDataEEG=permute(tempEEG,[2 1 3]); - parfor i=33:size(splitSignals,2)-3 - tempEMG=zeros(fix([size(splitSignals,3),(floor(size(splitSignals,1)/(frequency*window))-1)*window/shift+1])); - for j=1:size(splitSignals,3) %filter single trial - tempEMG(j,:)=waveformLength(filter(C,D,filter(A,B,splitSignals(:,i,j))),frequency,window,shift); - end - tempEMG2(i,:,:)=tempEMG; + parfor i=33:size(signal,2)-3 + tempEMG(i-32,:,:)=waveformLength(filter(C,D,filter(A,B,signal(:,i))),frequency,window,shift); end - trainingDataEMG=permute(tempEMG2,[2 1 3]); + trainingDataEMG=permute(tempEMG,[2 1 3]); end \ No newline at end of file diff --git a/kfoldCV.m b/kfoldCV.m index f49d0e6..8a4587a 100644 --- a/kfoldCV.m +++ b/kfoldCV.m @@ -1,5 +1,5 @@ function [model] = kfoldCV(classification,trainingData,k,cExpMax) - noClasses=size(unique(classification),2); + noClasses=size(unique(classification),1); cvAccurancy=zeros(2*cExpMax+1,1); parfor cExp=1:2*cExpMax+1 c=2^(cExp-cExpMax-1); @@ -21,7 +21,7 @@ end [~,maxC]=max(cvAccurancy); bestC=2^(maxC-cExpMax-1); - [balanceLeftClasses, balanceLeftOut]=balanceClasses(classification,trainingData,noClasses,0.00001); - model=svmtrain(balanceLeftClasses, balanceLeftOut(:,:),sprintf('-t 0 -c %f -q',bestC)); + [balancedClasses, balanceData]=balanceClasses(classification,trainingData,noClasses,0.00001); + model=svmtrain(balancedClasses, balanceData(:,:),sprintf('-t 0 -c %f -q',bestC)); end \ No newline at end of file diff --git a/plotStairs.m b/plotStairs.m new file mode 100644 index 0000000..ee7577a --- /dev/null +++ b/plotStairs.m @@ -0,0 +1,10 @@ +function [ ] = plotStairs( inVec ) +%plotStairs plots Stairs for Vector +% plots sum up to Index i as value for i + stair=zeros(size(inVec)); + for i=1:size(classification,1) + stair(i)=sum(inVec(1:i)); + end + plot(stairs) +end + diff --git a/read.m b/read.m index d13a0ff..4f291bc 100644 --- a/read.m +++ b/read.m @@ -1,7 +1,30 @@ -signal=[]; -stimulusCodes=[]; -for i=1:5 +%params +NFFT=2048; +window=0.2; +shift=0.2; +k=10; +maxExpC=7; +maxFile=5; +threshold=7500; + +trainingDataEEGcell=cell(maxFile,1); +trainingDataEMGcell=cell(maxFile,1); +classesCell=cell(maxFile,1); + +for i=1:maxFile [sig, stat, params] = load_bcidat(sprintf('/home/jph/Uni/masterarbeit/Block1_ReachingMovements/AO/AO_B1001/AO_B1S001R0%i.dat',i)); - signal=cat(1,signal,sig); - stimulusCodes=cat(1,stat.StimulusCode,stimulusCodes); + [trainingDataEEGcell{i},trainingDataEMGcell{i}]=generateTrainingData(sig,NFFT,window,shift,params); + classesCell{i}=stat.StimulusCode; + fprintf('%ith file processed\n',i) end + +trainingDataEEG=cell2mat(trainingDataEEGcell); +trainingDataEMG=cell2mat(trainingDataEMGcell); +classes=cell2mat(classesCell); + +classification=classifyAccordingToEMG(trainingDataEEG, trainingDataEMG,classes,shift,params.SamplingRate.NumericValue,threshold); + +smoothClassification=zeros(size(classification)); +for i=1:size(classification,1) + smoothClassification(i)=round(mean(classification(max(i-round(1/window),1):min(i+round(1/window),end)))); +end \ No newline at end of file diff --git a/readme.m b/readme.m index 28b94dd..9bb3767 100644 --- a/readme.m +++ b/readme.m @@ -53,12 +53,26 @@ % Aufteilung EMG xor EEG (done) % danach dann Bewegungen aufteilenC +% EMG ganze Bewegung % von einer Person und einem Tag zusammen (done) % nur die ersten zwei Sekunden der Bewegung (done [generateTrainingData]) % für WL keine Fenster sondern ganze Bewegung (done s.o.) -% äußere Crossvalidation -% Confusion +% äußere Crossvalidation (done) +% Confusion (done) % Ruhe / Bewegung aufteilen EEG EMG % -> testen ob mit EMG besser +% Bewegungen mit EEG: 30.59% +% Bewegungen mit EMG: 26.4112% +% Move/Rest EMG: 53.7683% +% Move/Rest EEG: 53.2012% + + +% libsvm vorne in den path (done) +% besser erst fft bzw. WL, dann aneinanderhängen (done, MEMORY!)) +% schneiden anhand von EMG (mean oder max) +% zum Trainieren Pause vor Bewegung(= EMG-Aktivität) +% threshold anhand von historgam/plot (bimodal?) + +% für confusion: caxis, normierung für predicted diff --git a/shiftingPwelch.m b/shiftingPwelch.m new file mode 100644 index 0000000..c0dc716 --- /dev/null +++ b/shiftingPwelch.m @@ -0,0 +1,9 @@ +function [EEG] = shiftingPwelch(signal,frequency,window,windowShift,NFFT) + signalShift=frequency*windowShift; + signalWindow=frequency*window; + shiftProp=window/windowShift; + EEG=zeros([fix(floor(size(signal,1)/signalWindow)-1)*shiftProp+1,NFFT/2+1]); + for j=1:fix(floor(size(signal,1)/signalWindow-1)*shiftProp+1) + EEG(j,:)=pwelch(signal((j-1)*signalShift+1:(j-1)*signalShift+signalWindow),[],[],NFFT,2500); + end +end \ No newline at end of file diff --git a/svm.m b/svm.m index 62cc6cf..f298ba0 100644 --- a/svm.m +++ b/svm.m @@ -1,53 +1,41 @@ +close all +clear all +clc + %params NFFT=2048; cutWindowEEG=2; window=0.2; shift=0.05; -k=10; -rounds=1; -maxExpC=7; -%svm load('/home/jph/Uni/masterarbeit/data/AO1.mat'); -[ splitSignals, code ] = cutMovements( stimulusCodes, signal ); -%[ splitSignals, code ] = cutWindows( stimulusCodes, signal, params, cutWindow ); - -%trainingData has format trial x ch x powerSpectrum -[trainingDataEEG,trainingDataEMG]=generateTrainingData(splitSignals,NFFT,window,shift,params,cutWindowEEG); - -%classify for different movements and rest -classification=zeros(size(code)); -for i=1:size(code) - if code(i)<=5 - classification(i)=code(i); - else - classification(i)=0; - end -end - - -%classify for move/rest -% cann't use cutMovements then -%classification=double(code<=5); +%k=2; +maxExpC=5; % c\in {2^i|i=-maxExpC:1:maxExpC} %choose to estimate based on EEG or EMG -trainingData=trainingDataEEG; +trainingData=trainingDataEMG; +clear trainingDataEEG; +clear trainingDataEMG; - -accurancy=zeros(rounds,3); -means=zeros(rounds,1); +accurancy=zeros(k,3); +noClasses=size(unique(classification),1); +cm=zeros(noClasses); +randMap=randperm(size(trainingData,1)); +disp('startCV') for i=1:k - randMap=randperm(size(trainingData,1)); - leaveOut=trainingData(mod(randMap,k+1)==i,:,:); - leaveClasses=classification(mod(randMap,k+1)==i); - remaining=trainingData(mod(randMap,k+1)~=i,:,:); - remainingClasses=classification(mod(randMap,k+1)~=i); - + leaveOut=trainingData(mod(randMap,k)==i-1,:,:); + leaveClasses=classification(mod(randMap,k)==i-1); + remaining=trainingData(mod(randMap,k)~=i-1,:,:); + remainingClasses=classification(mod(randMap,k)~=i-1); + disp(datestr(datetime('now'))) + fprintf('create %ith model\n',i) model=kfoldCV(remainingClasses,remaining,k,maxExpC); + disp(datestr(datetime('now'))) [predictions,accurancy(i,:),pvalues]=svmpredict(leaveClasses,leaveOut(:,:),model); - means(i)=mean(leaveClasses-predictions); %confusion matrix + cm=cm+confusionmat(leaveClasses,predictions); %confusion matrix %cf: for each cue what was the prediction (maybe colourCoded) + %fprintf('%ith step done\n',i) end meanAccurancy=mean(accurancy(:,1)) \ No newline at end of file diff --git a/text/collection.txt b/text/collection.txt new file mode 100644 index 0000000..7025eb6 --- /dev/null +++ b/text/collection.txt @@ -0,0 +1,14 @@ +Results +======= +given Classification +-------------------- +Bewegungen mit EEG: 30.59% +Bewegungen mit EMG: 26.4112% +Move/Rest EMG: 53.7683% +Move/Rest EEG: 53.2012% + +new Classification +------------------ +Move/Rest EMG : 99.9535% +Bewegungen EMG: 74.4832% *k=2, c=1* + diff --git a/waveformLength.m b/waveformLength.m index 8239c05..3b927f3 100644 --- a/waveformLength.m +++ b/waveformLength.m @@ -5,8 +5,8 @@ signalWindow=frequency*window; shiftProp=window/windowShift; WL=zeros((floor(size(signal,1)/signalWindow)-1)*shiftProp+1,1); - for j=1:(size(signal,1)/signalWindow-1)*shiftProp+1 - WL(j)=sum(diff(signal((j-1)*signalShift+1:(j-1)*signalShift+signalWindow))); + for j=1:fix(floor(size(signal,1)/signalWindow-1)*shiftProp+1) + WL(j)=sum(abs(diff(signal((j-1)*signalShift+1:(j-1)*signalShift+signalWindow)))); end end