added classification, results are bad...

This commit is contained in:
Toni
2016-01-09 23:30:44 +01:00
parent 1af38ba3b5
commit 901291932e
14 changed files with 42297 additions and 47754 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,10 @@
display("functions") display("functions")
source("settings.m");
function files = getDataFiles(clsName, trainsetPerClass) function files = getDataFiles(clsName, trainsetPerClass)
setDataDir = "/home/toni/Documents/handygames/HandyGames/daten/"; global setDataDir;
dir = strcat(setDataDir, clsName, "/"); dir = strcat(setDataDir, clsName, "/");
lst = readdir(dir); lst = readdir(dir);
@@ -36,13 +38,16 @@ function samples = getSamplesForClass(clsName, trainsetPerClass, start, percent)
display(strcat("training data for '", clsName, "': ", num2str(length(samples)), " samples")); display(strcat("training data for '", clsName, "': ", num2str(length(samples)), " samples"));
end end
function data = getRawTrainData(trainsetPerClass) function data = getRawTrainData()
#global trainsetPerClass;
data = {}; data = {};
data{1}.samples = getSamplesForClass("forwardbend", trainsetPerClass, 10, 0.9); data{1}.samples = getSamplesForClass("forwardbend", 9, 10, 0.95);
data{2}.samples = getSamplesForClass("kneebend", trainsetPerClass, 10, 0.9); data{2}.samples = getSamplesForClass("kneebend", 11, 10, 0.95);
data{3}.samples = getSamplesForClass("pushups", trainsetPerClass, 10, 0.9); data{3}.samples = getSamplesForClass("pushups", 11, 10, 0.95);
data{4}.samples = getSamplesForClass("situps", trainsetPerClass, 10, 0.9); data{4}.samples = getSamplesForClass("situps", 8, 10, 0.95);
data{5}.samples = getSamplesForClass("jumpingjack", trainsetPerClass, 10, 0.9); data{5}.samples = getSamplesForClass("jumpingjack", 13, 10, 0.95);
end end
function plotData(data,outPath) function plotData(data,outPath)
@@ -75,17 +80,15 @@ function filteredData = filterData(data)
end end
function win = window(rawVec, posMS) function win = window(rawVec, posMS)
global setWindowSize;
pos = posMS / 10; pos = posMS / 10;
#check if out of bounce, if yes- fill with zeros
#the last windows are sometimes filled with a lot of zeros... this could cause problems #only full windows are accepted.
if length(rawVec) <= pos+100-1 if length(rawVec) <= pos+(setWindowSize/2)-1
#win = rawVec(pos-100:length(rawVec),:);
#fillOut = zeros((pos+100-1) - length(rawVec), 3);
#length(fillOut)
#win = [win; fillOut];
win = []; win = [];
else else
win = rawVec(pos-100:pos+100-1,:); #100*10 ms is half the window size. that is 2s for each window. win = rawVec(pos-(setWindowSize/2):pos+(setWindowSize/2)-1,:); #100*10 ms is half the window size.
endif endif
end end
@@ -100,14 +103,24 @@ function out = getMagnitude(data)
end end
function windowedData = windowData(data) function windowedData = windowData(data)
windowedData = {};
global setWindowSize;
global setWindowSliding;
windowedData = {};
for k = 1:numel(data) for k = 1:numel(data)
for j = 1:numel(data{k}.samples) for j = 1:numel(data{k}.samples)
winsAccel = {}; #init
winsGyro = {}; winsAccelX = {};
winsMagnet = {}; winsAccelY = {};
winsAccelZ = {};
winsGyroX = {};
winsGyroY = {};
winsGyroZ = {};
winsMagnetX = {};
winsMagnetY = {};
winsMagnetZ = {};
winsAccelPCA = {}; winsAccelPCA = {};
winsGyroPCA = {}; winsGyroPCA = {};
@@ -118,12 +131,15 @@ windowedData = {};
winsMagnetMG = {}; winsMagnetMG = {};
winEnd = length(data{k}.samples{j}.raw{1}) * 10; # *10ms winEnd = length(data{k}.samples{j}.raw{1}) * 10; # *10ms
winBuffer = ((setWindowSize/2)+1) * 10;
for i = 1010:200:winEnd-1010 #200ms steps for sliding/overlapping windows for i = winBuffer:setWindowSliding:winEnd-winBuffer #steps for sliding/overlapping windows
#accel #accel
winAccel = window(data{k}.samples{j}.raw{1}, i); winAccel = window(data{k}.samples{j}.raw{1}, i);
winsAccel = [winsAccel winAccel]; winsAccelX = [winsAccelX winAccel(:,1)];
winsAccelY = [winsAccelY winAccel(:,2)];
winsAccelZ = [winsAccelZ winAccel(:,3)];
[coeff1, score1] = princomp(winAccel); [coeff1, score1] = princomp(winAccel);
winsAccelPCA = [winsAccelPCA score1(:,1)]; #choose the first axis (eigvec with the biggest eigvalue) winsAccelPCA = [winsAccelPCA score1(:,1)]; #choose the first axis (eigvec with the biggest eigvalue)
@@ -133,7 +149,9 @@ windowedData = {};
#gyro #gyro
winGyro = window(data{k}.samples{j}.raw{2}, i); winGyro = window(data{k}.samples{j}.raw{2}, i);
winsGyro = [winsGyro winGyro]; winsGyroX = [winsGyroX winGyro(:,1)];
winsGyroY = [winsGyroY winGyro(:,2)];
winsGyroZ = [winsGyroZ winGyro(:,3)];
[coeff2, score2] = princomp(winGyro); [coeff2, score2] = princomp(winGyro);
winsGyroPCA = [winsGyroPCA score2(:,1)]; winsGyroPCA = [winsGyroPCA score2(:,1)];
@@ -143,7 +161,9 @@ windowedData = {};
#magnet #magnet
winMagnet = window(data{k}.samples{j}.raw{3}, i); winMagnet = window(data{k}.samples{j}.raw{3}, i);
winsMagnet = [winsMagnet winMagnet]; winsMagnetX = [winsMagnetX winMagnet(:,1)];
winsMagnetY = [winsMagnetY winMagnet(:,2)];
winsMagnetZ = [winsMagnetZ winMagnet(:,3)];
[coeff3, score3] = princomp(winMagnet); [coeff3, score3] = princomp(winMagnet);
winsMagnetPCA = [winsMagnetPCA score3(:,1)]; winsMagnetPCA = [winsMagnetPCA score3(:,1)];
@@ -154,53 +174,68 @@ windowedData = {};
end end
#write back data #write back data
windowedData{k}.samples{j}.raw{1}.wins = winsAccel; windowedData{k}.samples{j}.raw{1}.wins = winsAccelX; #X
windowedData{k}.samples{j}.raw{2}.wins = winsGyro; windowedData{k}.samples{j}.raw{2}.wins = winsAccelY; #Y
windowedData{k}.samples{j}.raw{3}.wins = winsMagnet; windowedData{k}.samples{j}.raw{3}.wins = winsAccelZ; #Z
windowedData{k}.samples{j}.raw{4}.wins = winsAccelPCA; windowedData{k}.samples{j}.raw{4}.wins = winsGyroX;
windowedData{k}.samples{j}.raw{5}.wins = winsGyroPCA; windowedData{k}.samples{j}.raw{5}.wins = winsGyroY;
windowedData{k}.samples{j}.raw{6}.wins = winsMagnetPCA; windowedData{k}.samples{j}.raw{6}.wins = winsGyroZ;
windowedData{k}.samples{j}.raw{7}.wins = winsAccelMG; windowedData{k}.samples{j}.raw{7}.wins = winsMagnetX;
windowedData{k}.samples{j}.raw{8}.wins = winsGyroMG; windowedData{k}.samples{j}.raw{8}.wins = winsMagnetY;
windowedData{k}.samples{j}.raw{9}.wins = winsMagnetMG; windowedData{k}.samples{j}.raw{9}.wins = winsMagnetZ;
windowedData{k}.samples{j}.raw{10}.wins = winsAccelPCA;
windowedData{k}.samples{j}.raw{11}.wins = winsGyroPCA;
windowedData{k}.samples{j}.raw{12}.wins = winsMagnetPCA;
windowedData{k}.samples{j}.raw{13}.wins = winsAccelMG;
windowedData{k}.samples{j}.raw{14}.wins = winsGyroMG;
windowedData{k}.samples{j}.raw{15}.wins = winsMagnetMG;
end end
end end
end end
function features = featureCalculation(data) function features = featureCalculation(data)
features = []; global setAutocorrelationBinSize;
global setPSDBinSize;
features = [];
for k = 1:numel(data) for k = 1:numel(data)
for j = 1:numel(data{k}.samples) for j = 1:numel(data{k}.samples)
for i = 1:numel(data{k}.samples{j}.raw) for i = 1:numel(data{k}.samples{j}.raw)
for m = 1:numel(data{k}.samples{j}.raw{i}.wins) for m = 1:numel(data{k}.samples{j}.raw{i}.wins)
currentWindow = data{k}.samples{j}.raw{i}.wins{m}; currentWindow = data{k}.samples{j}.raw{i}.wins{m};
currentWindow = currentWindow(:,1);
#autocorrelation on window. split into 5 evenly spaced bins (frequencies are evenly spaced, not number of values ;) ) and calculate mean of bin. #autocorrelation on window. split into 5 evenly spaced bins (frequencies are evenly spaced, not number of values ;) ) and calculate mean of bin.
[autoCorr] = xcorr(currentWindow); [autoCorr] = xcorr(currentWindow);
[binNum, binCenter] = hist(autoCorr, 5); #define 5 bins for the data. [binNum, binCenter] = hist(autoCorr, setAutocorrelationBinSize); #define bins for the data.
binSize = abs(binCenter(end-1) - binCenter(end)); binSize = abs(binCenter(end-1) - binCenter(end));
binEdges = linspace(binCenter(1)-(binSize/2), binCenter(end)+(binSize/2), 6); binEdges = linspace(binCenter(1)-(binSize/2), binCenter(end)+(binSize/2), setAutocorrelationBinSize+1);
[binNumc, binIdx] = histc(autoCorr, binEdges); [binNumc, binIdx] = histc(autoCorr, binEdges);
binMeans = getBinMean(autoCorr, binIdx, 5); binMeans = getBinMean(autoCorr, binIdx, setAutocorrelationBinSize);
#calculate the root-mean-square (RMS) of the signal #calculate the root-mean-square (RMS) of the signal
rms = sqrt(mean(currentWindow.^2)); rms = sqrt(mean(currentWindow.^2));
#power bands 0.5 to 25hz (useful if the windows are greater then 4s and window sizes to 256, 512..) #power bands 0.5 to 25hz (useful if the windows are greater then 4s and window sizes to 256, 512..)
[powerBand, w] = periodogram(currentWindow); #fills up fft with zeros [powerBand, w] = periodogram(currentWindow); #fills up fft with zeros
powerEdges = logspace(log10(0.5), log10(25), 10 + 2); #logarithmic bin spaces for 10 bins powerEdges = logspace(log10(0.5), log10(25), setPSDBinSize + 2); #logarithmic bin spaces for 10 bins
triFilter = getTriangularFunction(powerEdges, length(powerBand)*2 - 2); triFilter = getTriangularFunction(powerEdges, length(powerBand)*2 - 2);
for l = 1:numel(triFilter) for l = 1:numel(triFilter)
filteredBand = triFilter{l} .* powerBand; filteredBand = triFilter{l} .* powerBand;
psd(l) = sum(filteredBand); #sum freq (no log and no dct) psd(l) = sum(filteredBand); #sum freq (no log and no dct)
end end
#statistical features
windowMean = mean(currentWindow);
windowSTD = std(currentWindow); #standard deviation
windowVariance = var(currentWindow);
windowKurtosis = kurtosis(currentWindow); #(ger. Wölbung)
windowIQR = iqr(currentWindow); #interquartile range
#put everything together #put everything together
classLabel = k; #what class? classLabel = k; #what class?
features = [features; classLabel, binMeans, rms, psd]; sampleLabel = j; #what sample?
features = [features; sampleLabel, classLabel, binMeans, rms, psd, windowMean, windowSTD, windowVariance, windowKurtosis, windowIQR];
end end
end end
end end
@@ -209,29 +244,34 @@ end
function value = getBinMean(data, idx, numBins) function value = getBinMean(data, idx, numBins)
#search for an idx == numBins+1. this index occurs if a value == lastEdge, thanks histc...
isSix = find(idx == numBins+1);
if isSix != 0
idx(isSix) = numBins;
endif
value = []; value = [];
for i = 1:numBins for i = 1:numBins
flagBinMembers = (idx == i); flagBinMembers = (idx == i);
binMembers = data(flagBinMembers); binMembers = data(flagBinMembers);
# if length(binMembers) == 0 if length(binMembers) == 0
# idx value(i) = 0;
#data else
# input = 'balala' value(i) = mean(binMembers);
#endif endif
value(i) = mean(binMembers);
end end
end end
#triangular functions. (edges of the triangles; num fft values -> nfft.) #triangular functions. (edges of the triangles; num fft values -> nfft.)
function triFilter = getTriangularFunction(edges, nfft) function triFilter = getTriangularFunction(edges, nfft)
global samplerateHZ;
#get idx of the edges within the samples. thanks to fft each sample represents a frequency. #get idx of the edges within the samples. thanks to fft each sample represents a frequency.
# idx * samplerate / nfft = hertz of that idx # idx * samplerate / nfft = hertz of that idx
for i = 1:length(edges) for i = 1:length(edges)
edgesByIdx(i) = floor((nfft + 1) * edges(i)/100); #100hz is the samplerate edgesByIdx(i) = floor((nfft + 1) * edges(i)/samplerateHZ);
end end
#generate the triangle filters #generate the triangle filters

View File

@@ -1,4 +1,4 @@
display("rawPlot") display("Generating Features")
#load and plot raw data #load and plot raw data
#{ #{
@@ -14,9 +14,8 @@ access the cells using classes{u}.samples{v}.raw{w}
#} #}
source("functions.m"); source("functions.m");
trainsetPerClass = 6; #number of used trainsets for one class
classes = {}; classes = {};
classes = getRawTrainData(trainsetPerClass); classes = getRawTrainData();
#outPath = "/home/toni/Documents/handygames/HandyGames/toni/img/raw" #outPath = "/home/toni/Documents/handygames/HandyGames/toni/img/raw"
#plotData(classes, outPath); #plotData(classes, outPath);
@@ -32,12 +31,12 @@ filteredClasses = filterData(classes);
data structure of windowedClasses: data structure of windowedClasses:
classes[1 to 5] classes[1 to 5]
samples[1 to trainsetPerClass] samples[1 to trainsetPerClass]
raw[1 to 9] <--- 9 different signals raw[1 to 15] <--- 15 different signals
WindowsAccel[2.5s at 200ms] 3x WindowsAccel (X, Y, Z)
Win, Win, Win, Win ... <--- single matrices Win, Win, Win, Win ... <--- single matrices
WindowsGyro[2.5s at 200ms] 3x WindowsGyro (X, Y, Z)
Win, Win, Win, Win ... <--- single matrices Win, Win, Win, Win ... <--- single matrices
WindowsMagnet[2.5s at 200ms] 3x WindowsMagnet (X, Y, Z)
Win, Win, Win, Win ... <--- single matrices Win, Win, Win, Win ... <--- single matrices
---> add 6 additional sensors: pca and magnitude ---> add 6 additional sensors: pca and magnitude
@@ -56,11 +55,13 @@ windowedClasses = windowData(filteredClasses);
#calculated features for the 5 signales (x, y, z, MG, PCA) of a sensor #calculated features for the 5 signales (x, y, z, MG, PCA) of a sensor
#{ #{
data structure of features data structure of features
label | feature #1 | 2 | 3 ... [classLabel, binMeans, rms, psd, windowMean, windowSTD, windowVariance, windowKurtosis, windowIQR]
#} #}
features = featureCalculation(windowedClasses); features = featureCalculation(windowedClasses);
#train svm #save features
save features.txt features;
display("saved features into features.txt");
#run svm

BIN
toni/octave/libsvmread.mex Executable file

Binary file not shown.

BIN
toni/octave/libsvmwrite.mex Executable file

Binary file not shown.

8
toni/octave/settings.m Normal file
View File

@@ -0,0 +1,8 @@
#global trainsetPerClass = 6; #number of used trainsets for one class
global setDataDir = "/home/toni/Documents/handygames/HandyGames/daten/";
global setWindowSize = 256; #in samples per window. even integer!
global setWindowSliding = 320; #in ms - (sampling rate is 10 ms.. so numSamples*10)
global setAutocorrelationBinSize = 5;
global setPSDBinSize = 10;
global samplerateHZ = 100;

BIN
toni/octave/svmpredict.mex Executable file

Binary file not shown.

BIN
toni/octave/svmtrain.mex Executable file

Binary file not shown.

View File

@@ -3,6 +3,7 @@ daten mal plotten
vorverarbeitung: vorverarbeitung:
low-pass-filter (-60dB at 20hZ) low-pass-filter (-60dB at 20hZ)
windowing (5s sliding at 200ms) windowing (5s sliding at 200ms)
Hinweis: die ersten 4 - 5 samples sind schon ziemlich mistig. kommen ganz gruselige werte.
segmentation (erstmal weglassen, da daten dafür nicht trainiert. bräuchten trainingsdaten von non-exercise die dann gelabeled sind) segmentation (erstmal weglassen, da daten dafür nicht trainiert. bräuchten trainingsdaten von non-exercise die dann gelabeled sind)
laufen ist z.b. keine übung! (man läuft ja zwischen übungen durch die gegend) laufen ist z.b. keine übung! (man läuft ja zwischen übungen durch die gegend)

49
toni/octave/training.m Normal file
View File

@@ -0,0 +1,49 @@
#train features using svm
display("Train Features")
#load all features
# features = [sampleLabel, classLabel, binMeans, rms, psd, windowMean, windowSTD, windowVariance, windowKurtosis, windowIQR];
load "features.txt"; #matrix is also called features
# split features into training and test features using leave-one-out method
# class idx:
# idx 1 -> forwardbend
# idx 2 -> kneebend
# idx 3 -> pushups
# idx 4 -> situps
# idx 5 -> jumpingjack
# define which sampleSet is used as testset and not for training.
leaveOut = find(features(:,1) == 3 & features(:,2) == 2); #sampleset 3 class 2
testFeatures = features(leaveOut, :); #set testSignal
features(leaveOut,:) = []; #remove the testFeatures
features(:,1) = []; #remove the sampleLabel
# bring the feature matrix into libsvm format.
# 1. the label vector:
trainLabel = features(:,1);
# 2. sparse matrix with every feature in one column:
features(:,1) = []; #remove the classLabel
trainFeatures = sparse(features);
# before training we need to scale the feature values
minimums = min(trainFeatures);
ranges = max(trainFeatures) - minimums;
trainFeatures = (trainFeatures - repmat(minimums, size(trainFeatures, 1), 1)) ./ repmat(ranges, size(trainFeatures, 1), 1);
# training: svm with default settings
model = svmtrain(trainLabel, trainFeatures);
display("Classify Features")
# for testing we need to scale again
testLabel = testFeatures(:,2);
testFeatures(:,1:2) = []; #remove the labels
testFeatures = (testFeatures - repmat(minimums, size(testFeatures, 1), 1)) ./ repmat(ranges, size(testFeatures, 1), 1);
# classification
[predict_label, accuracy, dec_values] = svmpredict(testLabel, testFeatures, model);