Skip to content

Commit 3d9c1a5

Browse files
authored
Merge pull request JuliaLogging#125 from nomadbl/fix_histogram_logger_interface
Fix logger interface for histograms
2 parents a79d8bd + 85de35a commit 3d9c1a5

File tree

8 files changed

+22
-69
lines changed

8 files changed

+22
-69
lines changed

docs/src/custom_behaviour.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ value is sent to:
55

66
- `::AbstractVector{<:Real}` -> [Histogram backend](https://www.tensorflow.org/guide/tensorboard_histograms) as a vector
77
- `::StatsBase.Histogram` -> [Histogram backend](https://www.tensorflow.org/guide/tensorboard_histograms)
8-
- `(bin_edges, weights)::Tuple{AbstractVector,AbstractVector}` where `length(bin_edges)==length(weights)+1`, is interpreted as an histogram. (*Will be deprecated.* Please use `TBHistogram(edges, weights)` for this).
8+
<!-- - `(bin_edges, weights)::Tuple{AbstractVector,AbstractVector}` where `length(bin_edges)==length(weights)+1`, is interpreted as an histogram. (*Will be deprecated.* Please use `TBHistogram(edges, weights)` for this). -->
99
- `::Real` -> Scalar backend
1010
- `::AbstractArray{<:Colorant}` -> [Image backend](https://www.tensorflow.org/tensorboard/r2/image_summaries)
1111
- `::Any` -> Text Backend

docs/src/extending_behaviour.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ At the end of this step, every pair in `objects` will be logged to a specific
1212
backend, according to the following rules:
1313

1414
- `::AbstractVector{<:Real}` -> [Histogram backend](https://www.tensorflow.org/guide/tensorboard_histograms) as a vector
15-
- `::Tuple{AbstractVector,AbstractVector}` [Histogram backend](https://www.tensorflow.org/guide/tensorboard_histograms) as an histogram
15+
<!-- - `::Tuple{AbstractVector,AbstractVector}` [Histogram backend](https://www.tensorflow.org/guide/tensorboard_histograms) as an histogram -->
1616
- `::Real` -> Scalar backend
1717
- `::AbstractArray{<:Colorant}` -> [Image backend](https://www.tensorflow.org/tensorboard/r2/image_summaries)
1818
- `::Any` -> Text Backend

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ at [Reading back TensorBoard data](@ref)
111111
We also support logging custom types from a the following third-party libraries:
112112
- [Plots.jl](https://github.com/JuliaPlots/Plots.jl): the `Plots.Plot` type will be rendered to PNG at the resolution specified by the object and logged as an image
113113
- [PyPlot.jl](https://github.com/JuliaPy/PyPlot.jl): the `PyPlot.Figure` type will be rendered to PNG at the resolution specified by the object and logged as an image
114-
- [Gadfly.jl](https://github.com/GiovineItalia/Gadfly.jl) type will be rendered to PNG at the resolution specified by the object and logged as an image. `Cairo` and `Fontconfig` packages must be imported for this functionality to work as it is required by `Gadfly`.
114+
- [Gadfly.jl](https://github.com/GiovineItalia/Gadfly.jl): the `Gadfly.Plot` type will be rendered to PNG at the resolution specified by the object and logged as an image. `Cairo` and `Fontconfig` packages must be imported for this functionality to work as it is required by `Gadfly`.
115115
- [Tracker.jl](https://github.com/FluxML/Tracker.jl): the `TrackedReal` and `TrackedArray` types will be logged as vector data
116116
- [ValueHistories.jl](https://github.com/JuliaML/ValueHistories.jl): the `MVHistory` type is used to store the deserialized content of .proto files.
117117

examples/Histograms.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ with_logger(logger) do
1010
x0 = 0.5+i/30; s0 = 0.5/(i/20);
1111
edges = collect(-5:0.1:5)
1212
centers = collect(edges[1:end-1] .+0.05)
13-
histvals = [exp(-((c-x0)/s0)^2) for c = centers]
13+
histvals = s0 * randn(length(centers)) .+ x0
1414
data_tuple = (edges, histvals)
15-
@info "histogram/loggerinterface" autobin=rand(10).+0.1*i manualbin=data_tuple
15+
@info "histogram/loggerinterface" autobin=s0 .* randn(100) .+ x0
16+
@info "histogram/loggerinterface" manualbin=data_tuple
1617
end
1718
end
1819

@@ -21,8 +22,8 @@ for i in 1:100
2122
x0 = 0.5+i/30; s0 = 0.5/(i/20);
2223
edges = collect(-5:0.1:5)
2324
centers = collect(edges[1:end-1] .+0.05)
24-
histvals = [exp(-((c-x0)/s0)^2) for c = centers]
25+
histvals = s0 * randn(length(centers)) .+ x0
2526
data_tuple = (edges, histvals)
26-
log_histogram(logger, "histogram/explicitinterface/autobin", rand(10).+0.1*i, step = i) #automatic bins
27+
log_histogram(logger, "histogram/explicitinterface/autobin", s0 .* randn(100) .+ x0, step = i) #automatic bins
2728
log_histogram(logger, "histogram/explicitinterface/manualbin", data_tuple, step = i) #manual bins
2829
end

src/Deserialization/histograms.jl

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,4 @@
11
function deserialize_histogram_summary(summary::Summary_Value)
2-
# custom deserialization
3-
if hasproperty(summary, :metadata)
4-
histo = summary.value.value
5-
if summary.metadata.plugin_data.plugin_name == TB_PLUGIN_JLARRAY_NAME
6-
val = reshape(histo.bucket,
7-
reinterpret(Int,
8-
summary.metadata.plugin_data.content)...)
9-
10-
return val
11-
end
12-
end
13-
142
# deserialize histogramproto
153
hist_proto = summary.value.value
164
bin_edges = similar(hist_proto.bucket_limit, length(hist_proto.bucket_limit)+1)

src/Loggers/LogHistograms.jl

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ be used to bin the data.
1212
function log_histogram(logger::TBLogger, name::AbstractString, (bins,weights)::Tuple{AbstractVector, AbstractArray};
1313
step=nothing)
1414
weights = collect(vec(weights))
15-
summ = SummaryCollection(histogram_summary(name, collect(bins), weights))
15+
hist = fit(Histogram, weights, bins)
16+
summ = SummaryCollection(histogram_summary(name, hist))
1617
write_event(logger.file, make_event(logger, summ, step=step))
1718
end
1819

@@ -24,27 +25,22 @@ Bins the values found in `data` and logs them as an histogram under the tag
2425
"""
2526
function log_histogram(logger::TBLogger, name::AbstractString, data::AbstractArray;
2627
step=nothing)
27-
data = vec(data)
28-
hvals = fit(Histogram, data)
29-
summ = SummaryCollection(histogram_summary(name, collect(hvals.edges[1]), hvals.weights))
28+
data = collect(vec(data))
29+
hist = fit(Histogram, data)
30+
summ = SummaryCollection(histogram_summary(name, hist))
3031
write_event(logger.file, make_event(logger, summ, step=step))
3132
end
3233

3334
"""
3435
log_vector(logger, name, data::Vector; step=step(logger))
35-
3636
Logs the vector found in `data` as an histogram under the name `name`.
3737
"""
3838
function log_vector(logger::TBLogger, name::AbstractString, data::AbstractVector; step=nothing)
39-
summ = SummaryCollection(histogram_summary(name, collect(0:length(data)),data))
39+
hist = Histogram(collect(0:length(data)), data)
40+
summ = SummaryCollection(histogram_summary(name, hist))
4041
write_event(logger.file, make_event(logger, summ, step=step))
4142
end
4243

43-
function histogram_summary(name::AbstractString, edges::AbstractVector{<:Number}, hist_vals::AbstractVector{<:Number})
44-
@assert length(edges) == length(hist_vals)+1
45-
return histogram_summary(name, Histogram(edges, hist_vals))
46-
end
47-
4844
function histogram_summary(name::AbstractString, hist::Histogram{T,1}) where T
4945
edges = first(hist.edges)
5046
hist_vals = hist.weights
@@ -59,25 +55,3 @@ function histogram_summary(name::AbstractString, hist::Histogram{T,1}) where T
5955
hist_vals)
6056
return Summary_Value(name, name, nothing, OneOf(:histo, hp))
6157
end
62-
63-
# Writes to an Histogram summary the flattened version of the array.
64-
# Also stores the shape of the array as a field in a plugin, which allows to
65-
# reconstruct the original shape when read back into Julia
66-
function histogram_arr_summary(name::AbstractString, tensor::AbstractArray)
67-
68-
smpd = SummaryMetadata_PluginData(TB_PLUGIN_JLARRAY_NAME, reinterpret(UInt8, collect(size(tensor))))
69-
sm = SummaryMetadata(smpd, name, "", DataClass.DATA_CLASS_TENSOR)
70-
71-
num = length(tensor)
72-
edges = collect(0:num)
73-
histsum = sum(tensor)
74-
histsumsqr = sum(tensor.^2)
75-
hp = HistogramProto(minimum(edges), maximum(edges),
76-
num,
77-
histsum,
78-
histsumsqr,
79-
edges[2:end],
80-
vec(tensor))
81-
82-
return Summary_Value(name, name, sm, OneOf(:histo, hp))
83-
end

src/logger_dispatch.jl

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,7 @@ summary_impl(name, value::Any) = text_summary(name, value)
7979
preprocess(name, hist::Histogram{<:Any,1}, data) = push!(data, name=>hist)
8080
summary_impl(name, hist::Histogram) = histogram_summary(name, hist)
8181

82-
# TODO: maybe deprecate? tuple means histogram (only if bins/weights match)
83-
function preprocess(name, (bins,weights)::Tuple{AbstractVector,AbstractVector}, data)
84-
# if ... this is an histogram
85-
if length(bins) == length(weights)+1
86-
return preprocess(name, Histogram(bins,weights), data)
87-
end
88-
preprocess(name*"/1", bins, data)
89-
preprocess(name*"/2", weights, data)
90-
end
91-
92-
preprocess(name, val::AbstractArray{<:Real}, data) = push!(data, name=>val)
93-
summary_impl(name, val::AbstractArray{<:Real}) = histogram_arr_summary(name, val)
82+
preprocess(name, val::AbstractArray{<:Real}, data) = return preprocess(name, fit(Histogram, collect(vec(val))), data)
9483

9584
# Split complex numbers into real/complex pairs
9685
preprocess(name, val::AbstractArray{<:Complex}, data) = push!(data, name*"/re"=>real.(val), name*"/im"=>imag.(val))

test/runtests.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ using TestImages
55
using ImageCore
66
using FileIO
77
using LightGraphs
8+
using StatsBase: fit, Histogram
89

910
ENV["DATADEPS_ALWAYS_ACCEPT"] = true
1011
ENV["GKSwstype"] = "100"
@@ -70,15 +71,15 @@ end
7071
centers = collect(edges[1:end-1] .+0.05)
7172
histvals = [exp(-((c-x0)/s0)^2) for c=centers]
7273
data_tuple = (edges, histvals)
73-
74-
ss = TensorBoardLogger.histogram_summary("test", edges, histvals)
74+
hist = fit(Histogram, histvals, edges)
75+
ss = TensorBoardLogger.histogram_summary("test", hist)
7576
@test isa(ss, TensorBoardLogger.Summary_Value)
7677
@test ss.tag == "test"
7778
@test isa(ss.value.value, TensorBoardLogger.HistogramProto)
7879
@test ss.value.value.min == minimum(edges)
7980
@test ss.value.value.max == maximum(edges)
8081
@test all(ss.value.value.bucket_limit .== edges[2:end])
81-
@test all(ss.value.value.bucket .== histvals)
82+
@test ss.value.value.bucket == hist.weights
8283

8384
log_histogram(logger, "hist/cust", data_tuple, step=step)
8485
log_histogram(logger, "hist/cust", rand(100), step=step)
@@ -93,7 +94,7 @@ end
9394
vals = rand(10)
9495
@test data == preprocess("test1", vals, data)
9596
@test first(data[1]) == "test1"
96-
@test last(data[1]) == vals
97+
@test last(data[1]) == fit(Histogram, collect(vec(vals)))
9798

9899
vals = rand(ComplexF32, 10)
99100
preprocess("test2", vals, data)
@@ -104,7 +105,7 @@ end
104105

105106
vals = rand(10, 10)
106107
preprocess("test2", vals, data)
107-
@test last(data[4]) == vals
108+
@test last(data[4]) == fit(Histogram, collect(vec(vals)))
108109

109110
end
110111

0 commit comments

Comments
 (0)