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")
source("settings.m");
function files = getDataFiles(clsName, trainsetPerClass)
setDataDir = "/home/toni/Documents/handygames/HandyGames/daten/";
global setDataDir;
dir = strcat(setDataDir, clsName, "/");
lst = readdir(dir);
@@ -36,13 +38,16 @@ function samples = getSamplesForClass(clsName, trainsetPerClass, start, percent)
display(strcat("training data for '", clsName, "': ", num2str(length(samples)), " samples"));
end
function data = getRawTrainData(trainsetPerClass)
function data = getRawTrainData()
#global trainsetPerClass;
data = {};
data{1}.samples = getSamplesForClass("forwardbend", trainsetPerClass, 10, 0.9);
data{2}.samples = getSamplesForClass("kneebend", trainsetPerClass, 10, 0.9);
data{3}.samples = getSamplesForClass("pushups", trainsetPerClass, 10, 0.9);
data{4}.samples = getSamplesForClass("situps", trainsetPerClass, 10, 0.9);
data{5}.samples = getSamplesForClass("jumpingjack", trainsetPerClass, 10, 0.9);
data{1}.samples = getSamplesForClass("forwardbend", 9, 10, 0.95);
data{2}.samples = getSamplesForClass("kneebend", 11, 10, 0.95);
data{3}.samples = getSamplesForClass("pushups", 11, 10, 0.95);
data{4}.samples = getSamplesForClass("situps", 8, 10, 0.95);
data{5}.samples = getSamplesForClass("jumpingjack", 13, 10, 0.95);
end
function plotData(data,outPath)
@@ -75,17 +80,15 @@ function filteredData = filterData(data)
end
function win = window(rawVec, posMS)
global setWindowSize;
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
if length(rawVec) <= pos+100-1
#win = rawVec(pos-100:length(rawVec),:);
#fillOut = zeros((pos+100-1) - length(rawVec), 3);
#length(fillOut)
#win = [win; fillOut];
#only full windows are accepted.
if length(rawVec) <= pos+(setWindowSize/2)-1
win = [];
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
end
@@ -100,14 +103,24 @@ function out = getMagnitude(data)
end
function windowedData = windowData(data)
windowedData = {};
global setWindowSize;
global setWindowSliding;
windowedData = {};
for k = 1:numel(data)
for j = 1:numel(data{k}.samples)
winsAccel = {};
winsGyro = {};
winsMagnet = {};
#init
winsAccelX = {};
winsAccelY = {};
winsAccelZ = {};
winsGyroX = {};
winsGyroY = {};
winsGyroZ = {};
winsMagnetX = {};
winsMagnetY = {};
winsMagnetZ = {};
winsAccelPCA = {};
winsGyroPCA = {};
@@ -118,12 +131,15 @@ windowedData = {};
winsMagnetMG = {};
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
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);
winsAccelPCA = [winsAccelPCA score1(:,1)]; #choose the first axis (eigvec with the biggest eigvalue)
@@ -133,7 +149,9 @@ windowedData = {};
#gyro
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);
winsGyroPCA = [winsGyroPCA score2(:,1)];
@@ -143,7 +161,9 @@ windowedData = {};
#magnet
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);
winsMagnetPCA = [winsMagnetPCA score3(:,1)];
@@ -154,53 +174,68 @@ windowedData = {};
end
#write back data
windowedData{k}.samples{j}.raw{1}.wins = winsAccel;
windowedData{k}.samples{j}.raw{2}.wins = winsGyro;
windowedData{k}.samples{j}.raw{3}.wins = winsMagnet;
windowedData{k}.samples{j}.raw{4}.wins = winsAccelPCA;
windowedData{k}.samples{j}.raw{5}.wins = winsGyroPCA;
windowedData{k}.samples{j}.raw{6}.wins = winsMagnetPCA;
windowedData{k}.samples{j}.raw{7}.wins = winsAccelMG;
windowedData{k}.samples{j}.raw{8}.wins = winsGyroMG;
windowedData{k}.samples{j}.raw{9}.wins = winsMagnetMG;
windowedData{k}.samples{j}.raw{1}.wins = winsAccelX; #X
windowedData{k}.samples{j}.raw{2}.wins = winsAccelY; #Y
windowedData{k}.samples{j}.raw{3}.wins = winsAccelZ; #Z
windowedData{k}.samples{j}.raw{4}.wins = winsGyroX;
windowedData{k}.samples{j}.raw{5}.wins = winsGyroY;
windowedData{k}.samples{j}.raw{6}.wins = winsGyroZ;
windowedData{k}.samples{j}.raw{7}.wins = winsMagnetX;
windowedData{k}.samples{j}.raw{8}.wins = winsMagnetY;
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
function features = featureCalculation(data)
features = [];
global setAutocorrelationBinSize;
global setPSDBinSize;
features = [];
for k = 1:numel(data)
for j = 1:numel(data{k}.samples)
for i = 1:numel(data{k}.samples{j}.raw)
for m = 1:numel(data{k}.samples{j}.raw{i}.wins)
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.
[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));
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);
binMeans = getBinMean(autoCorr, binIdx, 5);
binMeans = getBinMean(autoCorr, binIdx, setAutocorrelationBinSize);
#calculate the root-mean-square (RMS) of the signal
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..)
[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);
for l = 1:numel(triFilter)
filteredBand = triFilter{l} .* powerBand;
psd(l) = sum(filteredBand); #sum freq (no log and no dct)
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
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
@@ -209,29 +244,34 @@ end
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
flagBinMembers = (idx == i);
binMembers = data(flagBinMembers);
# if length(binMembers) == 0
# idx
#data
# input = 'balala'
#endif
value(i) = mean(binMembers);
if length(binMembers) == 0
value(i) = 0;
else
value(i) = mean(binMembers);
endif
end
end
#triangular functions. (edges of the triangles; num fft values -> nfft.)
function triFilter = getTriangularFunction(edges, nfft)
global samplerateHZ;
#get idx of the edges within the samples. thanks to fft each sample represents a frequency.
# idx * samplerate / nfft = hertz of that idx
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
#generate the triangle filters

View File

@@ -1,4 +1,4 @@
display("rawPlot")
display("Generating Features")
#load and plot raw data
#{
@@ -14,9 +14,8 @@ access the cells using classes{u}.samples{v}.raw{w}
#}
source("functions.m");
trainsetPerClass = 6; #number of used trainsets for one class
classes = {};
classes = getRawTrainData(trainsetPerClass);
classes = getRawTrainData();
#outPath = "/home/toni/Documents/handygames/HandyGames/toni/img/raw"
#plotData(classes, outPath);
@@ -32,12 +31,12 @@ filteredClasses = filterData(classes);
data structure of windowedClasses:
classes[1 to 5]
samples[1 to trainsetPerClass]
raw[1 to 9] <--- 9 different signals
WindowsAccel[2.5s at 200ms]
raw[1 to 15] <--- 15 different signals
3x WindowsAccel (X, Y, Z)
Win, Win, Win, Win ... <--- single matrices
WindowsGyro[2.5s at 200ms]
3x WindowsGyro (X, Y, Z)
Win, Win, Win, Win ... <--- single matrices
WindowsMagnet[2.5s at 200ms]
3x WindowsMagnet (X, Y, Z)
Win, Win, Win, Win ... <--- single matrices
---> 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
#{
data structure of features
label | feature #1 | 2 | 3 ...
[classLabel, binMeans, rms, psd, windowMean, windowSTD, windowVariance, windowKurtosis, windowIQR]
#}
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:
low-pass-filter (-60dB at 20hZ)
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)
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);