From 1299a6f00868c650274ce43b0b03dd3e908a7880 Mon Sep 17 00:00:00 2001 From: Alex Robson Date: Fri, 3 Dec 2021 12:14:00 +0000 Subject: [PATCH 1/8] Add LogTransform --- src/FeatureTransforms.jl | 4 +++- test/runtests.jl | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/FeatureTransforms.jl b/src/FeatureTransforms.jl index ddb741c..71b9368 100644 --- a/src/FeatureTransforms.jl +++ b/src/FeatureTransforms.jl @@ -7,7 +7,8 @@ using Tables export Transform, transform, transform! export HoD, LinearCombination, OneHotEncoding, Periodic, Power -export AbstractScaling, IdentityScaling, MeanStdScaling +export AbstractScaling, IdentityScaling +export MeanStdScaling, LogTransform include("utils.jl") include("traits.jl") @@ -16,6 +17,7 @@ include("apply.jl") # Transform implementations include("linear_combination.jl") +include("log.jl") include("one_hot_encoding.jl") include("periodic.jl") include("power.jl") diff --git a/test/runtests.jl b/test/runtests.jl index 7fedca2..eaa447c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,6 +17,7 @@ using TimeZones Sys.WORD_SIZE == 64 && v"1.6" <= VERSION < v"1.7" && doctest(FeatureTransforms) include("linear_combination.jl") + include("log.jl") include("one_hot_encoding.jl") include("periodic.jl") include("power.jl") From da13f64f8bfa47bccd6e3c6e14ba07ebea2796c6 Mon Sep 17 00:00:00 2001 From: Alex Robson Date: Fri, 3 Dec 2021 12:23:13 +0000 Subject: [PATCH 2/8] Add untracked files. Add HyperbolicSine transform --- src/FeatureTransforms.jl | 2 +- src/log.jl | 22 +++++++++++++++++++ test/log.jl | 46 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/log.jl create mode 100644 test/log.jl diff --git a/src/FeatureTransforms.jl b/src/FeatureTransforms.jl index 71b9368..9b70268 100644 --- a/src/FeatureTransforms.jl +++ b/src/FeatureTransforms.jl @@ -8,7 +8,7 @@ using Tables export Transform, transform, transform! export HoD, LinearCombination, OneHotEncoding, Periodic, Power export AbstractScaling, IdentityScaling -export MeanStdScaling, LogTransform +export MeanStdScaling, LogTransform, InverseHyperbolicSine include("utils.jl") include("traits.jl") diff --git a/src/log.jl b/src/log.jl new file mode 100644 index 0000000..badf7d7 --- /dev/null +++ b/src/log.jl @@ -0,0 +1,22 @@ + +struct LogTransform <: Transform end +cardinality(::LogTransform) = OneToOne() + +_logtransform(x) = sign(x) * log(abs(x) + 1) +_invlogtransform(x) = sign(x) * (exp(sign(x) * x) - 1) + +function _apply(A::AbstractArray, transform::LogTransform; inverse=false, kwargs...) + inverse && return _invlogtransform.(A) + return _logtransform.(A) +end + +# Hyperbolic +struct InverseHyperbolicSine <: Transform end +cardinality(::InverseHyperbolicSine) = OneToOne() + +function _apply(A::AbstractArray, transform::InverseHyperbolicSine; inverse=false, kwargs...) + inverse && return sinh.(A) + return asinh.(A) +end + + diff --git a/test/log.jl b/test/log.jl new file mode 100644 index 0000000..1c2df73 --- /dev/null +++ b/test/log.jl @@ -0,0 +1,46 @@ +@testset "log" begin + + V1 = [1; 2; 3; 4; 5; 6] + V2 = [1; 2; -3; 4; 5; 6] + M = [1 1 0.5; 0.0 1.0 2.0] + + @testset "LogTransform" begin + + logV1 = [0.693147; 1.098612; 1.386294; 1.609437; 1.791759; 1.945910] + logV2 = [0.693147; 1.098612; -1.386294; 1.609437; 1.791759; 1.945910] + logM = [0.693147 0.693147 0.405465; 0.0 0.693147 1.09861] + + @testset "simple" for x in (V1, V2, M) + transform = LogTransform() + @test cardinality(transform) == OneToOne() + @test transform isa Transform + end + + @testset "Apply" for (x, y) in ((V1, logV1), (V2, logV2), (M, logM)) + f = LogTransform() + transformed = FeatureTransforms.apply(x, f) + @test transformed ≈ y atol=1e-5 + @test FeatureTransforms.apply(transformed, f; inverse=true) ≈ x atol=1e-5 + end + end + + @testset "InverseHyperbolicSine" begin + + logV1 = asinh.(V1) + logV2 = asinh.(V2) + logM = asinh.(M) + + @testset "simple" for x in (V1, V2, M) + transform = InverseHyperbolicSine() + @test cardinality(transform) == OneToOne() + @test transform isa Transform + end + + @testset "Apply" for (x, y) in ((V1, logV1), (V2, logV2), (M, logM)) + f = InverseHyperbolicSine() + transformed = FeatureTransforms.apply(x, f) + @test transformed ≈ y atol=1e-5 + @test FeatureTransforms.apply(transformed, f; inverse=true) ≈ x atol=1e-5 + end + end +end \ No newline at end of file From 18f65927b4e190d14f77390661e8e3264e52cbcb Mon Sep 17 00:00:00 2001 From: Alex Robson Date: Fri, 3 Dec 2021 12:28:42 +0000 Subject: [PATCH 3/8] Add docstring --- src/log.jl | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/log.jl b/src/log.jl index badf7d7..8800c71 100644 --- a/src/log.jl +++ b/src/log.jl @@ -1,4 +1,10 @@ +""" + LogTransform <: Transform +Logarithmically transform the data through: sign(x) * log(|x| + 1). + +This allows positive domains elements to be transformed. +""" struct LogTransform <: Transform end cardinality(::LogTransform) = OneToOne() @@ -10,13 +16,18 @@ function _apply(A::AbstractArray, transform::LogTransform; inverse=false, kwargs return _logtransform.(A) end -# Hyperbolic + +""" + InverseHyperbolicSine <: Transform + +Logarithmically transform the data through: log(x + √(x² + 1)). + +This is the inverse hyperbolic sine. +""" struct InverseHyperbolicSine <: Transform end cardinality(::InverseHyperbolicSine) = OneToOne() function _apply(A::AbstractArray, transform::InverseHyperbolicSine; inverse=false, kwargs...) inverse && return sinh.(A) return asinh.(A) -end - - +end \ No newline at end of file From e2500924c880c9baa1c814c30ab3a7c19d682c9c Mon Sep 17 00:00:00 2001 From: Alex Robson Date: Fri, 3 Dec 2021 12:36:05 +0000 Subject: [PATCH 4/8] Bump version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 075c199..c1fe007 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "FeatureTransforms" uuid = "8fd68953-04b8-4117-ac19-158bf6de9782" authors = ["Invenia Technical Computing Corporation"] -version = "0.3.10" +version = "0.3.11" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" From 35915a1d11b7be9665bae2e7045fff8e2daf077f Mon Sep 17 00:00:00 2001 From: Alex Robson Date: Fri, 3 Dec 2021 14:15:53 +0000 Subject: [PATCH 5/8] Apply suggestions from code review Co-authored-by: Miha Zgubic --- src/FeatureTransforms.jl | 4 ++-- src/log.jl | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/FeatureTransforms.jl b/src/FeatureTransforms.jl index 9b70268..f278731 100644 --- a/src/FeatureTransforms.jl +++ b/src/FeatureTransforms.jl @@ -7,8 +7,8 @@ using Tables export Transform, transform, transform! export HoD, LinearCombination, OneHotEncoding, Periodic, Power -export AbstractScaling, IdentityScaling -export MeanStdScaling, LogTransform, InverseHyperbolicSine +export AbstractScaling, IdentityScaling, MeanStdScaling +export LogTransform, InverseHyperbolicSine include("utils.jl") include("traits.jl") diff --git a/src/log.jl b/src/log.jl index 8800c71..323b24e 100644 --- a/src/log.jl +++ b/src/log.jl @@ -3,13 +3,13 @@ Logarithmically transform the data through: sign(x) * log(|x| + 1). -This allows positive domains elements to be transformed. +This allows transformations of all real numbers, not just positive ones. """ struct LogTransform <: Transform end cardinality(::LogTransform) = OneToOne() -_logtransform(x) = sign(x) * log(abs(x) + 1) -_invlogtransform(x) = sign(x) * (exp(sign(x) * x) - 1) +_logtransform(x) = sign(x) * log(abs(x) + one(x)) +_invlogtransform(x) = sign(x) * (exp(sign(x) * x) - one(x)) function _apply(A::AbstractArray, transform::LogTransform; inverse=false, kwargs...) inverse && return _invlogtransform.(A) From 8389232396edbe2f3c8f05be847affa37148bd8a Mon Sep 17 00:00:00 2001 From: Alex Robson Date: Fri, 3 Dec 2021 14:37:45 +0000 Subject: [PATCH 6/8] Clearer test value --- test/log.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/log.jl b/test/log.jl index 1c2df73..d5a3256 100644 --- a/test/log.jl +++ b/test/log.jl @@ -1,14 +1,14 @@ @testset "log" begin - V1 = [1; 2; 3; 4; 5; 6] - V2 = [1; 2; -3; 4; 5; 6] + V1 = [1; 2; 3; 4; 0; 6] + V2 = [1; 2; -3; 4; 0; 6] M = [1 1 0.5; 0.0 1.0 2.0] @testset "LogTransform" begin - logV1 = [0.693147; 1.098612; 1.386294; 1.609437; 1.791759; 1.945910] - logV2 = [0.693147; 1.098612; -1.386294; 1.609437; 1.791759; 1.945910] - logM = [0.693147 0.693147 0.405465; 0.0 0.693147 1.09861] + logV1 = [log(2); log(3); log(4); log(5); log(1); log(7)] + logV2 = [log(2); log(3); -log(4); log(5); log(1); log(7)] + logM = [log(2) log(2) log(1.5); log(1) log(2) log(3)] @testset "simple" for x in (V1, V2, M) transform = LogTransform() From 876276f3b78486ece5906bdd4d10f1601b7444b3 Mon Sep 17 00:00:00 2001 From: Alex Robson Date: Fri, 3 Dec 2021 15:00:17 +0000 Subject: [PATCH 7/8] Explicity symmetric test --- test/log.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/log.jl b/test/log.jl index d5a3256..c3f993c 100644 --- a/test/log.jl +++ b/test/log.jl @@ -1,13 +1,13 @@ @testset "log" begin - V1 = [1; 2; 3; 4; 0; 6] - V2 = [1; 2; -3; 4; 0; 6] + V1 = [1; -2; 3; 4; 0; -6] + V2 = -V1 M = [1 1 0.5; 0.0 1.0 2.0] @testset "LogTransform" begin - logV1 = [log(2); log(3); log(4); log(5); log(1); log(7)] - logV2 = [log(2); log(3); -log(4); log(5); log(1); log(7)] + logV1 = [log(2); -log(3); log(4); log(5); log(1); -log(7)] + logV2 = -logV1 logM = [log(2) log(2) log(1.5); log(1) log(2) log(3)] @testset "simple" for x in (V1, V2, M) From bc8b0ffb797c411cf291c779167885eeb8443a46 Mon Sep 17 00:00:00 2001 From: Alex Robson Date: Fri, 3 Dec 2021 15:00:30 +0000 Subject: [PATCH 8/8] Add to docs --- docs/src/api.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/api.md b/docs/src/api.md index 9f96ecf..a34c30e 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -15,7 +15,9 @@ Power Periodic MeanStdScaling IdentityScaling +InverseHyperbolicSine LinearCombination +LogTransform OneHotEncoding ```