Mateusz
Mateusz

Reputation: 11

How to convert a vector of arrays into 4D array?

I'm trying to play a little bit with Knet.jl and CNNs. Every example I found requires the input for CNN to be in the form of [dim1, dim2, n_of_channels, N] where N is a number of the actual images. I'm a bit new to Julia and I don't know how to accomplish this.

I loaded images from some private directory and pushed them to a vector, so that their length is N.

images = Vector()
for img_file in readdir(dir)
    img = load("$dir/$img_file")
    images = vcat(images, [img])
end

typeof(image)
"320-element Array{Any,1}"

However in the following example xtrn is stored as 28x28x1x60000 Array and that is what I would like to accomplish with the private dataset.

using Knet; include(Knet.dir("data","mnist.jl"))
xtrn,ytrn,_,_= mnist()

typeof(xtrn)
Array{Float32,4}

I'm aware of functions as channelview, reshape and it's seems they should provide solution but I played with them a bit and got DimensionMismatch error all the time. I guess there's something I miss.

Upvotes: 1

Views: 255

Answers (2)

Mateusz
Mateusz

Reputation: 11

Just to fill in the answer of DNF, this code results in Array in the form of [dim1, dim2, 1, N]:

images = reduce((x,y)->cat(x, y, dims=4), load(joinpath(dir, img_file)) for img_file in readdir(dir))

I wanted the 3rd dimension to be the channel and hence, the expected output is produced by:

images = reduce((x, y) -> cat(x, y, dims=4), permutedims(channelview(load(joinpath(dir, img_file))), (2, 3, 1)) for img in readdir(dir))

Upvotes: 0

DNF
DNF

Reputation: 12664

I don't have the files you are using in your example. But I would use cat in conjunction with a generator. Here's an example of something you can do:

julia> reduce((x,y)->cat(x, y, dims=4), rand(3,3) for _ in 1:3)
3×3×1×3 Array{Float64,4}:
[:, :, 1, 1] =
 0.366818  0.847529  0.209042
 0.281807  0.467918  0.68881 
 0.179162  0.222919  0.348935

[:, :, 1, 2] =
 0.0418451  0.256611  0.609398
 0.65166    0.281397  0.340405
 0.11109    0.387638  0.974488

[:, :, 1, 3] =
 0.454959  0.37831   0.554323
 0.213613  0.980773  0.743419
 0.133154  0.782516  0.669733

In order to do this with your files, this might work (untested):

images = reduce((x,y)->cat(x, y, dims=4), load(joinpath(dir, img_file)) for img_file in readdir(dir))

BTW. You should not initialize vectors like this:

images = Vector()

This makes an untyped container, which will have very bad performance. Write e.g.

images = Matrix{Float32}[]

This initializes an empty vector of Matrix{Float32}s.

Upvotes: 1

Related Questions