From 3bf2bd3251b66f6e20a4b881c88a278bad217125 Mon Sep 17 00:00:00 2001 From: longemen3000 Date: Thu, 29 Oct 2020 15:20:42 -0300 Subject: [PATCH 1/6] moved some ops --- src/AdaBoost.jl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/AdaBoost.jl b/src/AdaBoost.jl index b438c5533..b07f14daf 100755 --- a/src/AdaBoost.jl +++ b/src/AdaBoost.jl @@ -159,13 +159,15 @@ function learn( # set feature weight best_feature = features[best_feature_idx] - feature_weight = 0.5 * log((1 - best_error) / best_error) # β + feature_weight = β(best_error) # β best_feature.weight = feature_weight classifiers = push!(classifiers, best_feature) + sqrt_best_error = @fastmath(sqrt(best_error / (one(best_error) - best_error))) + # update image weights $w_{t+1,i}=w_{t,i}\beta_{t}^{1-e_i}$ - weights = map(i -> labels[i] ≠ votes[best_feature_idx, i] ? weights[i] * sqrt((1 - best_error) / best_error) : weights[i] * sqrt(best_error / (1 - best_error)), 1:num_imgs) + weights = map(i -> labels[i] ≠ votes[best_feature_idx, i] ? weights[i] * sqrt_best_error : weights[i] * sqrt_best_error, 1:num_imgs) # remove feature (a feature can't be selected twice) filter!(e -> e ∉ best_feature_idx, feature_indices) # note: without unicode operators, `e ∉ [a, b]` is `!(e in [a, b])` @@ -179,6 +181,12 @@ function learn( end +function β(err::T)::T where T + _1=one(err) + _half = T(0.5) + @fastmath(_half*log((_1 - err) / err)) +end + function learn( positive_path::AbstractString, negative_path::AbstractString, From 53a5627fb9536f5ce4005283fd12dfa1222de7b3 Mon Sep 17 00:00:00 2001 From: longemen3000 Date: Thu, 29 Oct 2020 15:40:42 -0300 Subject: [PATCH 2/6] optimized rounds --- src/HaarLikeFeature.jl | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/HaarLikeFeature.jl b/src/HaarLikeFeature.jl index 9135d316e..f4e13b87c 100755 --- a/src/HaarLikeFeature.jl +++ b/src/HaarLikeFeature.jl @@ -77,38 +77,41 @@ Get score for given integral image array. function get_score(feature::HaarLikeObject{I,F}, int_img::Array) where {I,F} score = zero(I) faceness = zero(I) - + _2f = F(2) + _half = F(0.5) + _third = F(1.0/3.0) + _3f = F(3) if feature.feature_type == feature_types.two_vertical - first = sum_region(int_img, feature.top_left, (feature.top_left[1] + feature.width, I(round(feature.top_left[2] + feature.height / 2)))) - second = sum_region(int_img, (feature.top_left[1], I(round(feature.top_left[2] + feature.height / 2))), feature.bottom_right) + first = sum_region(int_img, feature.top_left, (feature.top_left[1] + feature.width, I(round(feature.top_left[2] + feature.height * _half)))) + second = sum_region(int_img, (feature.top_left[1], I(round(feature.top_left[2] + feature.height * _half))), feature.bottom_right) score = first - second faceness = I(1) elseif feature.feature_type == feature_types.two_horizontal - first = sum_region(int_img, feature.top_left, (I(round(feature.top_left[1] + feature.width / 2)), feature.top_left[2] + feature.height)) - second = sum_region(int_img, (I(round(feature.top_left[1] + feature.width / 2)), feature.top_left[2]), feature.bottom_right) + first = sum_region(int_img, feature.top_left, (I(round(feature.top_left[1] + feature.width * _half)), feature.top_left[2] + feature.height)) + second = sum_region(int_img, (I(round(feature.top_left[1] + feature.width * _half)), feature.top_left[2]), feature.bottom_right) score = first - second faceness = I(2) elseif feature.feature_type == feature_types.three_horizontal - first = sum_region(int_img, feature.top_left, (I(round(feature.top_left[1] + feature.width / 3)), feature.top_left[2] + feature.height)) - second = sum_region(int_img, (I(round(feature.top_left[1] + feature.width / 3)), feature.top_left[2]), (I(round(feature.top_left[1] + 2 * feature.width / 3)), feature.top_left[2] + feature.height)) - third = sum_region(int_img, (I(round(feature.top_left[1] + 2 * feature.width / 3)), feature.top_left[2]), feature.bottom_right) + first = sum_region(int_img, feature.top_left, (I(round(feature.top_left[1] + feature.width * _third)), feature.top_left[2] + feature.height)) + second = sum_region(int_img, (I(round(feature.top_left[1] + feature.width * _third)), feature.top_left[2]), (I(round(feature.top_left[1] + _2f *feature.width * _third)), feature.top_left[2] + feature.height)) + third = sum_region(int_img, (I(round(feature.top_left[1] + _2f *feature.width * _third)), feature.top_left[2]), feature.bottom_right) score = first - second + third faceness = I(3) elseif feature.feature_type == feature_types.three_vertical - first = sum_region(int_img, feature.top_left, (feature.bottom_right[1], I(round(feature.top_left[2] + feature.height / 3)))) - second = sum_region(int_img, (feature.top_left[1], I(round(feature.top_left[2] + feature.height / 3))), (feature.bottom_right[1], I(round(feature.top_left[2] + 2 * feature.height / 3)))) - third = sum_region(int_img, (feature.top_left[1], I(round(feature.top_left[2] + 2 * feature.height / 3))), feature.bottom_right) + first = sum_region(int_img, feature.top_left, (feature.bottom_right[1], I(round(feature.top_left[2] + feature.height * _third)))) + second = sum_region(int_img, (feature.top_left[1], I(round(feature.top_left[2] + feature.height * _third))), (feature.bottom_right[1], I(round(feature.top_left[2] + _2f *feature.height * _third)))) + third = sum_region(int_img, (feature.top_left[1], I(round(feature.top_left[2] + _2f *feature.height * _third))), feature.bottom_right) score = first - second + third faceness = I(4) elseif feature.feature_type == feature_types.four # top left area - first = sum_region(int_img, feature.top_left, (I(round(feature.top_left[1] + feature.width / 2)), I(round(feature.top_left[2] + feature.height / 2)))) + first = sum_region(int_img, feature.top_left, (I(round(feature.top_left[1] + feature.width * _half)), I(round(feature.top_left[2] + feature.height * _half)))) # top right area - second = sum_region(int_img, (I(round(feature.top_left[1] + feature.width / 2)), feature.top_left[2]), (feature.bottom_right[1], I(round(feature.top_left[2] + feature.height / 2)))) + second = sum_region(int_img, (I(round(feature.top_left[1] + feature.width * _half)), feature.top_left[2]), (feature.bottom_right[1], I(round(feature.top_left[2] + feature.height * _half)))) # bottom left area - third = sum_region(int_img, (feature.top_left[1], I(round(feature.top_left[2] + feature.height / 2))), (I(round(feature.top_left[1] + feature.width / 2)), feature.bottom_right[2])) + third = sum_region(int_img, (feature.top_left[1], I(round(feature.top_left[2] + feature.height * _half))), (I(round(feature.top_left[1] + feature.width * _half)), feature.bottom_right[2])) # bottom right area - fourth = sum_region(int_img, (I(round(feature.top_left[1] + feature.width / 2)), I(round(feature.top_left[2] + feature.height / 2))), feature.bottom_right) + fourth = sum_region(int_img, (I(round(feature.top_left[1] + feature.width * _half)), I(round(feature.top_left[2] + feature.height * _half))), feature.bottom_right) score = first - second - third + fourth faceness = I(5) end From 9af77823070d88543db8e7aab658093577d8cafe Mon Sep 17 00:00:00 2001 From: longemen3000 Date: Thu, 29 Oct 2020 15:40:54 -0300 Subject: [PATCH 3/6] changed precision in test --- test/runtests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 1b0a23754..d66875a3a 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -61,8 +61,8 @@ const main_data_path = joinpath(@__DIR__, "images") p = sum(ensemble_vote_all(pos_testing_path, classifiers)) / num_faces n = (num_non_faces - sum(ensemble_vote_all(neg_testing_path, classifiers))) / num_non_faces end - @test isapprox(p, 0.63, atol=1e-1) - @test isapprox(n, 0.372, atol=1e-1) + @test isapprox(p, 0.63, atol=2e-1) + @test isapprox(n, 0.372, atol=2e-1) random_img = rand(vcat(filtered_ls.([pos_training_path, neg_training_path, pos_testing_path, neg_testing_path])...)) @test get_faceness(classifiers[rand(1:length(classifiers))], load_image(random_img)) isa Integer @test determine_feature_size(pos_training_path, neg_training_path) == (10, 10, 8, 8, (19, 19)) From da1ed2ebf96102b9c7c13b15096550dabad7596f Mon Sep 17 00:00:00 2001 From: longemen3000 Date: Thu, 29 Oct 2020 16:03:45 -0300 Subject: [PATCH 4/6] more implace ops --- src/AdaBoost.jl | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/AdaBoost.jl b/src/AdaBoost.jl index b07f14daf..e2fa6bf1f 100755 --- a/src/AdaBoost.jl +++ b/src/AdaBoost.jl @@ -117,8 +117,8 @@ function learn( features::AbstractArray, votes::AbstractArray, num_classifiers::Integer=-1 + ) - # get number of positive and negative images (and create a global variable of the total number of images——global for the @everywhere scope) num_pos = length(filtered_ls(positive_path)) num_neg = length(filtered_ls(negative_path)) @@ -141,18 +141,23 @@ function learn( # select classifiers classifiers = [] p = Progress(num_classifiers, 1) # minimum update interval: 1 second + classification_errors = Vector{Float64}(undef, length(feature_indices)) + for t in 1:num_classifiers # classification_errors = zeros(length(feature_indices)) - classification_errors = Matrix{Float64}(undef, length(feature_indices), 1) + #classification_errors = Matrix{Float64}(undef, length(feature_indices), 1) + # normalize the weights $w_{t,i}\gets \frac{w_{t,i}}{\sum_{j=1}^n w_{t,j}}$ - weights = float(weights) / sum(weights) + inv_sumweights = 1.0/sum(weights) + weights .*= inv_sumweights # For each feature j, train a classifier $h_j$ which is restricted to using a single feature. The error is evaluated with respect to $w_j,\varepsilon_j = \sum_i w_i\left|h_j\left(x_i\right)-y_i\right|$ - map!(view(classification_errors, :), 1:length(feature_indices)) do j + + map!(classification_errors, 1:length(feature_indices)) do j sum(1:num_imgs) do img_idx - labels[img_idx] ≠ votes[feature_indices[j], img_idx] ? weights[img_idx] : zero(Float64) + labels[img_idx] ≠ votes[feature_indices[j], img_idx] ? weights[img_idx] : zero(eltype(classification_errors)) end end - + # choose the classifier $h_t$ with the lowest error $\varepsilon_t$ best_error, min_error_idx = findmin(classification_errors) best_feature_idx = feature_indices[min_error_idx] @@ -165,13 +170,20 @@ function learn( classifiers = push!(classifiers, best_feature) sqrt_best_error = @fastmath(sqrt(best_error / (one(best_error) - best_error))) - + inv_sqrt_best_error = @fastmath(sqrt((one(best_error) - best_error)/best_error)) # update image weights $w_{t+1,i}=w_{t,i}\beta_{t}^{1-e_i}$ - weights = map(i -> labels[i] ≠ votes[best_feature_idx, i] ? weights[i] * sqrt_best_error : weights[i] * sqrt_best_error, 1:num_imgs) + + @inbounds for i in 1:num_imgs + if labels[i] !== votes[best_feature_idx, i] + weights[i] *= inv_sqrt_best_error + else + weights[i] *= sqrt_best_error + end + end # remove feature (a feature can't be selected twice) filter!(e -> e ∉ best_feature_idx, feature_indices) # note: without unicode operators, `e ∉ [a, b]` is `!(e in [a, b])` - + resize!(classification_errors,length(feature_indices)) next!(p) # increment progress bar end From 9e1952c15b11aa34e1f0e2be42e3f581eb82f153 Mon Sep 17 00:00:00 2001 From: longemen3000 Date: Thu, 29 Oct 2020 16:06:32 -0300 Subject: [PATCH 5/6] runtest runs correctly again --- test/runtests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index d66875a3a..1b0a23754 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -61,8 +61,8 @@ const main_data_path = joinpath(@__DIR__, "images") p = sum(ensemble_vote_all(pos_testing_path, classifiers)) / num_faces n = (num_non_faces - sum(ensemble_vote_all(neg_testing_path, classifiers))) / num_non_faces end - @test isapprox(p, 0.63, atol=2e-1) - @test isapprox(n, 0.372, atol=2e-1) + @test isapprox(p, 0.63, atol=1e-1) + @test isapprox(n, 0.372, atol=1e-1) random_img = rand(vcat(filtered_ls.([pos_training_path, neg_training_path, pos_testing_path, neg_testing_path])...)) @test get_faceness(classifiers[rand(1:length(classifiers))], load_image(random_img)) isa Integer @test determine_feature_size(pos_training_path, neg_training_path) == (10, 10, 8, 8, (19, 19)) From b3aec6b880ab7efae3f265e9581219efc33f171c Mon Sep 17 00:00:00 2001 From: longemen3000 Date: Thu, 29 Oct 2020 16:49:03 -0300 Subject: [PATCH 6/6] changed one map! to a loop --- src/AdaBoost.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/AdaBoost.jl b/src/AdaBoost.jl index b6f685505..667cb75b5 100755 --- a/src/AdaBoost.jl +++ b/src/AdaBoost.jl @@ -124,14 +124,16 @@ function learn( #classification_errors = Matrix{Float64}(undef, length(feature_indices), 1) # normalize the weights $w_{t,i}\gets \frac{w_{t,i}}{\sum_{j=1}^n w_{t,j}}$ - inv_sumweights = 1.0/sum(weights) + inv_sumweights = inv(sum(weights)) weights .*= inv_sumweights # For each feature j, train a classifier $h_j$ which is restricted to using a single feature. The error is evaluated with respect to $w_j,\varepsilon_j = \sum_i w_i\left|h_j\left(x_i\right)-y_i\right|$ - map!(classification_errors, 1:length(feature_indices)) do j - sum(1:num_imgs) do img_idx - labels[img_idx] ≠ votes[feature_indices[j], img_idx] ? weights[img_idx] : zero(eltype(classification_errors)) + for j in 1:length(feature_indices) + _sum = sum(1:num_imgs) do img_idx + _bool = (labels[img_idx] !== votes[feature_indices[j], img_idx]) + _bool*weights[img_idx] end + classification_errors[j] = _sum end # choose the classifier $h_t$ with the lowest error $\varepsilon_t$