Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fluctuation complexity, restrict possibilites to formally defined self-informations #413

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/core/information_functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,17 @@ function information(::InformationMeasure, ::DifferentialInfoEstimator, args...)
end

"""
self_information(measure::InformationMeasure, pᵢ)
self_information(measure::InformationMeasure, p, N::Int)

Compute the "self-information"/"surprisal" of a single probability `pᵢ` under the given
information measure.
Compute the "self-information"/"surprisal" of a single probability `p` under the given
information measure, assuming that `p` is part of a length-`N` probability distribution.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately I don't agree with the latest change of requiring N. It seems simpler, and more reasonable, to simply not allow Curado to be part of this interface. The opposite, defining the information unit as depending on N, doesn't make much sense at least not with how Shannon introduced it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Datseris Curado is not the only information measure whose surprisal/self-information depends explicitly on N, when following the definition of an information measure as a probability weighted average of the surprisal (as I do in the paper).

The opposite, defining the information unit as depending on N, doesn't make much sense at least not with how Shannon introduced it.

In the context of Shannon information unit alone, I agree. But the point of this interface is to generalize the Shannon information unit. This inevitably introduces N as a parameter.

Can we discuss the final API when I'm done with writing up the paper? I'm not too far from finishing it; I just need to generate a few example applications. Since I am using this PR for the paper analyses, it would be nice to not change anything in this draft PR until the paper is ready.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alternative is to have information_content/information_unit which dispatches to a subset of InformationMeasures, and then generalized_information_content/generalized_information_unit which dispatches to those InformationMeasures whose generalization of information unit depends on N. But that kind of defeats the purpose of having an interface to begin with - since we're back at defining multiple functions with different names for things that are fundamentally identical (modulo the parameter N).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS: I sent you a link to the paper draft, @Datseris


This function assumes `pᵢ > 0`, so make sure to pre-filter your probabilities.
For some `measure`s, the information content is independent of `N`, while for others
it depends on `N`. For consistency, we require that you always provide `N` (`N` will be
ignored if not relevant).

This function requires `p > 0`; giving `0` can yield `Inf` or `NaN` for certain
`measure`s.

## Definition

Expand All @@ -302,12 +307,12 @@ sum of the self-information equals the information measure.

!!! note "Motivation for this definition"
This definition is motivated by the desire to compute generalized
[`FluctuationComplexity`](@ref), which is a measure of fluctuations of local self-information
[`InformationFluctuation`](@ref), which is a measure of fluctuations of local self-information
relative to some information-theoretic summary statistic of a distribution. Defining
these self-information functions has, as far as we know, not been treated in the literature
before, and will be part of an upcoming paper we're writing!
"""
function self_information(measure::InformationMeasure, pᵢ)
function self_information(measure::InformationMeasure, pᵢ, N = nothing)
throw(ArgumentError(
"""`InformationMeasure` $(typeof(measure)) does not implement `self_information`."""
))
Expand Down
2 changes: 1 addition & 1 deletion src/core/information_measures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ for usage examples.
- [`RenyiExtropy`](@ref).
- [`TsallisExtropy`](@ref).
- [`ShannonExtropy`](@ref), which is a subcase of the above two in the limit `q → 1`.
- [`FluctuationComplexity`](@ref).
- [`InformationFluctuation`](@ref).

## Estimators

Expand Down
5 changes: 5 additions & 0 deletions src/information_measure_definitions/curado.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ function information_maximum(e::Curado, L::Int)
# Maximized for the uniform distribution, which for distribution of length L is
return L * (1 - exp(-b/L)) + exp(-b) - 1
end

function self_information(e::Curado, p, N::Int)
b = e.b
return exp(-b*p)/p + (exp(-b) - 1)/N
end
60 changes: 41 additions & 19 deletions src/information_measure_definitions/fluctuation_complexity.jl
Original file line number Diff line number Diff line change
@@ -1,62 +1,84 @@
export FluctuationComplexity
export InformationFluctuation

"""
FluctuationComplexity <: InformationMeasure
FluctuationComplexity(; definition = Shannon())
InformationFluctuation <: InformationMeasure
InformationFluctuation(; definition = Shannon())

The "fluctuation complexity" quantifies the standard deviation of the information content of the states
The information fluctuation quantifies the standard deviation of the information content of the states
``\\omega_i`` around some summary statistic ([`InformationMeasure`](@ref)) of a PMF. Specifically, given some
outcome space ``\\Omega`` with outcomes ``\\omega_i \\in \\Omega``
and a probability mass function ``p(\\Omega) = \\{ p(\\omega_i) \\}_{i=1}^N``, it is defined as

```math
\\sigma_I_Q(p) := \\sqrt{\\sum_{i=1}^N p_i(I_Q(p_i) - H_*)^2}
\\sigma_I_Q(p) := \\sqrt{\\sum_{i=1}^N p_i(I_Q(p_i) - F_Q)^2}
```

where ``I_Q(p_i)`` is the [`self_information`](@ref) of the i-th outcome with respect to the information
measure of type ``Q`` (controlled by `definition`).
where ``I_Q(p_i)`` is the [`information_content`](@ref) of the i-th outcome with respect to the information
measure ``F_Q`` (controlled by `definition`).

## Compatible with

- [`Shannon`](@ref)
- [`Tsallis`](@ref)
- [`Curado`](@ref)
- [`StretchedExponential`](@ref)
- [`ShannonExtropy`](@ref)

If `definition` is the [`Shannon`](@ref) entropy, then we recover the
[Shannon-type "information fluctuation complexity"](https://en.wikipedia.org/wiki/Information_fluctuation_complexity)
from [Bates1993](@cite).

## Properties

If `definition` is the [`Shannon`](@ref) entropy, then we recover the
[Shannon-type information fluctuation complexity](https://en.wikipedia.org/wiki/Information_fluctuation_complexity)
from [Bates1993](@cite). Then the fluctuation complexity is zero for PMFs with only a single non-zero element, or
Then the information fluctuation is zero for PMFs with only a single non-zero element, or
for the uniform distribution.

If `definition` is not Shannon entropy, then the properties of the measure varies, and does not necessarily share the
properties [Bates1993](@cite).
## Examples

```julia
using ComplexityMeasures
using Random; rng = Xoshiro(55543)

# Information fluctuation for a time series encoded by ordinal patterns
x = rand(rng, 10000)
def = Tsallis(q = 2) # information measure definition
pest = RelativeAmount() # probabilities estimator
o = OrdinalPatterns(m = 3) # outcome space / discretization method
information(InformationFluctuation(definition = def), pest, o, x)
```

!!! note "Potential for new research"
As far as we know, using other information measures besides Shannon entropy for the
fluctuation complexity hasn't been explored in the literature yet. Our implementation, however, allows for it.
We're currently writing a paper outlining the generalizations to other measures. For now, we verify
correctness of the measure through numerical examples in our test-suite.
"""
struct FluctuationComplexity{M <: InformationMeasure, I <: Integer} <: InformationMeasure
struct InformationFluctuation{M <: InformationMeasure, I <: Integer} <: InformationMeasure
definition::M
base::I

function FluctuationComplexity(; definition::D = Shannon(base = 2), base::I = 2) where {D, I}
if D isa FluctuationComplexity
throw(ArgumentError("Cannot use `FluctuationComplexity` as the summary statistic for `FluctuationComplexity`. Please select some other information measures, like `Shannon`."))
function InformationFluctuation(; definition::D = Shannon(base = 2), base::I = 2) where {D, I}
if D isa InformationFluctuation
throw(ArgumentError("Cannot use `InformationFluctuation` as the summary statistic for `InformationFluctuation`. Please select some other information measures, like `Shannon`."))
end
return new{D, I}(definition, base)
end
end

# Fluctuation complexity is zero when p_i = 1/N or when p = (1, 0, 0, ...).
function information(e::FluctuationComplexity, probs::Probabilities)
function information(e::InformationFluctuation, probs::Probabilities)
def = e.definition
non0_probs = Iterators.filter(!iszero, vec(probs))
h = information(def, probs)
return sqrt(sum(pᵢ * (self_information(def, pᵢ, length(probs)) - h)^2 for pᵢ in non0_probs))
end

function information_normalized(e::InformationFluctuation, probs::Probabilities)
def = e.definition
non0_probs = Iterators.filter(!iszero, vec(probs))
h = information(def, probs)
s = self_information(def, probs)
return sqrt(sum(pᵢ * (s - h)^2 for pᵢ in non0_probs))
info_fluct = sqrt(sum(pᵢ * (self_information(def, pᵢ, length(probs)) - h)^2 for pᵢ in non0_probs))
return info_fluct / h
end

# The maximum is not generally known.
2 changes: 1 addition & 1 deletion src/information_measure_definitions/kaniadakis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function information_maximum(e::Kaniadakis, L::Int)
throw(ErrorException("information_maximum not implemeted for Kaniadakis entropy yet"))
end

function self_information(e::Kaniadakis, pᵢ)
function self_information(e::Kaniadakis, pᵢ, N = nothing)
κ = e.κ
return (pᵢ^(-κ) - pᵢ^κ) / (2κ)
end
2 changes: 1 addition & 1 deletion src/information_measure_definitions/shannon.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function information(e::Shannon, probs::Probabilities)
return -sum(x*logf(x) for x in non0_probs)
end

function self_information(e::Shannon, pᵢ)
function self_information(e::Shannon, pᵢ, N)
return -log(e.base, pᵢ)
end

Expand Down
2 changes: 1 addition & 1 deletion src/information_measure_definitions/shannon_extropy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ function information_maximum(e::ShannonExtropy, L::Int)
return (L - 1) * log(e.base, L / (L - 1))
end

function self_information(e::ShannonExtropy, pᵢ)
function self_information(e::ShannonExtropy, pᵢ, N = nothing)
return -log(e.base, 1 - pᵢ)
end
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function information_maximum(e::StretchedExponential, L::Int)
L * gamma_inc(x, log(e.base, L))[2] * Γx - Γx
end

function self_information(e::StretchedExponential, pᵢ)
function self_information(e::StretchedExponential, pᵢ, N)
η, base = e.η, e.base
Γ₁ = gamma((η + 1) / η, -log(base, pᵢ))
Γ₂ = gamma((η + 1) / η)
Expand Down
2 changes: 1 addition & 1 deletion src/information_measure_definitions/tsallis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ function information_maximum(e::Tsallis, L::Int)
end
end

function self_information(e::Tsallis, pᵢ)
function self_information(e::Tsallis, pᵢ, N = nothing)
return (1 - pᵢ^(e.q- 1)) / (e.q - 1)
end
16 changes: 9 additions & 7 deletions test/infomeasures/infomeasure_types/fluctuation_complexity.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Examples from https://en.wikipedia.org/wiki/Information_fluctuation_complexity
# for the Shannon fluctuation complexity.
p = Probabilities([2//17, 2//17, 1//34, 5//34, 2//17, 2//17, 2//17, 4//17])
def = Shannon(base = 2)
c = FluctuationComplexity(definition = def, base = 2)
@test round(information(c, p), digits = 2) ≈ 0.56
# Zero both for uniform and single-element PMFs.
@test information(c, Probabilities([0.2, 0.2, 0.2, 0.2, 0.2])) == 0.0
@test information(c, Probabilities([1.0, 0.0])) == 0.0
@testset "fluctuation_complexity" begin
probs = Probabilities([2//17, 2//17, 1//34, 5//34, 2//17, 2//17, 2//17, 4//17])
def = Shannon(base = 2)
c = FluctuationComplexity(definition = def, base = 2)
@test round(information(c, probs), digits = 2) ≈ 0.56
# Zero both for uniform and single-element PMFs.
@test information(c, Probabilities([0.2, 0.2, 0.2, 0.2, 0.2])) == 0.0
@test information(c, Probabilities([1.0, 0.0])) == 0.0
end
Loading