Bladeren bron

added docu to net.jl, changed default architecture of net.jl to best performing
added ReportMotionLogger.pdf, fixed histogram bug in MATLAB/generate.m

Sebastian Vendt 5 jaren geleden
bovenliggende
commit
7c60914a2d

BIN
MATLAB/TrainingData/2019_09_09_1658_TEST.mat


BIN
MATLAB/TrainingData/2019_09_09_1658_TRAIN.mat


BIN
MATLAB/TrainingData/2019_09_09_1658_VAL.mat


BIN
MATLAB/TrainingData/Hist_MinMax.fig


BIN
MATLAB/TrainingData/Hist_Pause.fig


BIN
MATLAB/TrainingData/Hist_duration.fig


+ 3 - 3
MATLAB/generate.m

@@ -50,8 +50,8 @@ TimeBetweenTouchEvents = csvData(indicesTBT(2:end), TIMEBETWEENTOUCHEVENTS);
 TimeBetweenTouchEvents = sort(TimeBetweenTouchEvents);
 TimeBetweenTouchEvents = TimeBetweenTouchEvents(1:end-8);
 
-maxGYRO = [max(dataset(:,:,1)')', max(dataset(:,:,2)')', max(dataset(:,:,3)')'];
-maxACC = [max(dataset(:,:,4)')', max(dataset(:,:,5)')', max(dataset(:,:,6)')'];
+maxGYRO = [max(squeeze(abs(dataset(:,1,:))))', max(squeeze(abs(dataset(:,2,:))))', max(squeeze(abs(dataset(:,3,:))))'];
+maxACC = [max(squeeze(abs(dataset(:,4,:))))', max(squeeze(abs(dataset(:,5,:))))', max(squeeze(abs(dataset(:,6,:))))'];
 
 fig1 = figure;
 histogram(pointerDownTimes ./ 1000000) % Divide from ns to ms 
@@ -61,7 +61,7 @@ histogram(TimeBetweenTouchEvents ./ 1000000) % Divide from ns to ms
 title('Histogram of the time between sequential touch events in ms')
 fig3 = figure;
 subplot(2,3,1)
-nbins = 10;
+nbins = 40;
 histogram(maxGYRO(:, 1), nbins)
 title('Hist Max Gyro X')
 subplot(2,3,2)

+ 1 - 0
MATLAB/generateTrainingDataFromCSV.m

@@ -38,6 +38,7 @@ function [data, labels] = generateTrainingDataFromCSV(file, offset, len, framesi
       labels = cat(2, labels, file(indices, X_COORD:Y_COORD)');
   end
   fprintf("created %d frames out of %d touch events\n", size(data, 3), length(indices));
+  labels = bsxfun(@minus, labels, [0; 699])
 end
 
 function samples = getSamplesFromData(file, indices, framesize, frameoffset)

BIN
ReportMotionLogger.pdf


+ 3 - 2
julia/dataManager.jl

@@ -8,7 +8,7 @@ using Flux:onehotbatch
 
 # dimension of coordinates (labels): (x, y)
 lbls_dims = (1080, 980)
-lbls_offset = (0, 699)
+# lbls_offset = (0, 699)
 
 """
 	make_minibatch(X, Y, idxset)
@@ -66,7 +66,8 @@ function make_batch(filepath, filenames...; batch_size=100, normalize_data=true,
 	data = cat(dims=4, data)
 	
 	# normalize the labels 
-	labels = (labels .- lbls_offset) ./ lbls_dims
+	# labels = (labels .- lbls_offset) ./ lbls_dims
+	labels = labels ./ lbls_dims;
 
     # rearrange the data array 
 	# size(data) = (50, 6, 1, N)

+ 12 - 22
julia/net.jl

@@ -1,9 +1,8 @@
 
 """
 Author: Sebastian Vendt, University of Ulm
-
-
-
+This script implements the convolutional neural network for infering tap locations from motion data frames. 
+For detailed documentation please read through ReportMotionLogger.pdf in the github repo.
 """
 
 using ArgParse
@@ -18,7 +17,7 @@ s = ArgParseSettings()
     "--epochs" 
 		help = "Number of epochs"
 		arg_type = Int64
-		default = 40
+		default = 100
 	"--logmsg"
 		help = "additional message describing the training log"
 		arg_type = String
@@ -52,14 +51,14 @@ norm(x::TrackedArray{T}) where T = sqrt(sum(abs2.(x)) + eps(T))
 # PARAMETERS
 ######################
 const batch_size = 100
-momentum = 0.9f0
+momentum = 0.99f0
 const lambda = 0.0005f0
-const delta = 0.00001
-learning_rate = 0.1f0
+const delta = 0.00006
+learning_rate = 0.03f0
 validate = parsed_args["eval"]
 const epochs = parsed_args["epochs"]
 const decay_rate = 0.1f0
-const decay_step = 40
+const decay_step = 60
 const usegpu = parsed_args["gpu"]
 const printout_interval = 2
 const time_format = "HH:MM:SS"
@@ -69,11 +68,11 @@ data_size = (60, 6) # resulting in a 300ms frame
 # DEFAULT ARCHITECTURE
 channels = 1
 features = [32, 64, 128] # needs to find the relation between the axis which represents the screen position 
-kernel = [(3,1), (3,1), (3,6)]  # convolute only horizontally, last should convolute all 6 rows together to map relations between the channels  
-pooldims = [(2,1), (2,1)]# (30,6) -> (15,6)
+kernel = [(5,1), (5,1), (2,6)]  # convolute only horizontally, last should convolute all 6 rows together to map relations between the channels  
+pooldims = [(3,1), (3,1)]# (30,6) -> (15,6)
 # formula for calculating output dimensions of convolution: 
 # dim1 = ((dim1 - Filtersize + 2 * padding) / stride) + 1
-inputDense = [1664, 600, 300] # prod((data_size .÷ pooldims[1] .÷ pooldims[2]) .- kernel[3] .+ 1) * features[3]
+inputDense = [0, 600, 300] # the first dense layer is automatically calculated
 dropout_rate = 0.3f0
 
 # random search values
@@ -112,8 +111,6 @@ function adapt_learnrate(epoch_idx)
 end
 
 # TODO different idea for the accuracy: draw circle around ground truth and if prediction lays within the circle count this as a hit 
-# TODO calculate the mean distance in pixel without normalizantion
-
 function accuracy(model, x, y)
 	y_hat = Tracker.data(model(x))
 	return mean(mapslices(button_number, y_hat, dims=1) .== mapslices(button_number, y, dims=1))
@@ -132,7 +129,7 @@ function button_number(X)
 end
 
 function loss(model, x, y) 
-	# quadratic euclidean distance + parameternorm
+	# quadratic euclidean distance + norm 
 	return Flux.mse(model(x), y) + lambda * sum(norm, params(model))
 end
 
@@ -215,14 +212,6 @@ function train_model()
         opt.eta = adapt_learnrate(i)
 		log_csv(model, i)
 		log(model, i, !validate)
-		
-		# early stopping
-		curr_loss = loss(model, train_set)
-		if(abs(last_loss - curr_loss) < delta)
-			@printf(io, "Early stopping with Loss(train) %f at epoch %d (Accuracy: %f)\n", curr_loss, i, accuracy(model, validation_set))
-			return eval_model(model)
-		end
-		last_loss = curr_loss
     end
     return eval_model(model)
 end
@@ -230,6 +219,7 @@ end
 function random_search()
 	rng = MersenneTwister()
 	results = []
+	global epochs = 40
 	for search in 1:800
 		# create random set
 		global momentum = rand(rng, rs_momentum)