Skip to content
Closed
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
41 changes: 41 additions & 0 deletions src/layers/upsample.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
struct BilinearUpsample{T<:Integer}
factor::Tuple{T,T}
end

function (b::BilinearUpsample)(x::AbstractArray)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
function (b::BilinearUpsample)(x::AbstractArray)
function (b::BilinearUpsample)(x::AbstractArray{T, 4}) where T

W, H, C, N = size(x)
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be better to swap W and H but it's still okay to keep it as it is, since most people confuse them.

Copy link
Author

Choose a reason for hiding this comment

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

The data in Flux is stored in WHCN order isn’t it?

Data should be stored in WHCN order (width, height, # channels, batch size).

Copy link
Contributor

@johnnychen94 johnnychen94 Apr 24, 2020

Choose a reason for hiding this comment

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

It is, but I prefer to read it as a misunderstanding. I just wanted to mention it here in case you're not aware of it.

It's okay to abuse the usage of WH since it's relative to the column/row-first order.


newW = W * b.factor[1]
newH = H * b.factor[2]

out = similar(x, (newW, newH, C, N))

for n = 1:N, c = 1:C, w = 1:newW, h = 1:newH
Copy link
Contributor

Choose a reason for hiding this comment

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

This scalar loop would be extremely slow when x is CuArray

Copy link
Author

Choose a reason for hiding this comment

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

Agreed, but I must admit I don't have experience optimizing Julia for CUDA usage. Do you have suggestions in this case?

Choose a reason for hiding this comment

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

Broadcast would be fast on GPU

w₀ = (w - 0.5) / b.factor[1] + 0.5
h₀ = (h - 0.5) / b.factor[2] + 0.5

w1 = floor(Int, w₀)
w2 = w1 + 1
h1 = floor(Int, h₀)
h2 = h1 + 1

i1 = clamp(w1, 1, W)
i2 = clamp(w2, 1, W)
j1 = clamp(h1, 1, H)
j2 = clamp(h2, 1, H)

out[w, h, c, n] =
(
x[i1, j1, c, n] * (w2 - w₀) * (h2 - h₀) +
x[i1, j2, c, n] * (w2 - w₀) * (h₀ - h1) +
x[i2, j1, c, n] * (w₀ - w1) * (h2 - h₀) +
x[i2, j2, c, n] * (w₀ - w1) * (h₀ - h1)
) / (w2 - w1 * h2 - h1)
end

out
end

function Base.show(io::IO, b::BilinearUpsample)
print(io, "BilinearUpsample(", b.factor[1], ", ", b.factor[2], ")")
end