Usage examples
Arrays can be quantized through either the quantize
function or using the QuantizedArray
constructor directly.
If the quantization is done through sampling, the quantized arrays may differ with each run as the vector prototypes are randomly sampled.
julia> using QuantizedArrays
julia> v = collect(1:10)
10-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
10
julia> qv = quantize(v, k=2) # quantize by sampling 2 prototypes i.e. values
10-element QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Int64,1}:
1
1
4
4
4
4
4
4
4
4
julia> qv = QuantizedArray(v, k=2)
10-element QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Int64,1}:
9
9
9
9
9
9
9
9
9
10
julia> m = reshape(collect(1:60), (6,10))
6×10 Array{Int64,2}:
1 7 13 19 25 31 37 43 49 55
2 8 14 20 26 32 38 44 50 56
3 9 15 21 27 33 39 45 51 57
4 10 16 22 28 34 40 46 52 58
5 11 17 23 29 35 41 47 53 59
6 12 18 24 30 36 42 48 54 60
julia> qm = quantize(m, k=5, m=2) # 5 prototypes, 2 codebooks
6×10 QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Int64,2}:
31 31 31 31 31 31 37 43 49 55
32 32 32 32 32 32 38 44 50 56
33 33 33 33 33 33 39 45 51 57
10 10 22 22 28 34 34 58 58 58
11 11 23 23 29 35 35 59 59 59
12 12 24 24 30 36 36 60 60 60
julia> qm = QuantizedArray(m, k=5, m=2)
6×10 QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Int64,2}:
1 7 13 13 13 43 43 43 55 55
2 8 14 14 14 44 44 44 56 56
3 9 15 15 15 45 45 45 57 57
4 10 10 22 22 34 40 40 40 40
5 11 11 23 23 35 41 41 41 41
6 12 12 24 24 36 42 42 42 42
The compressed representation of the input arrays is stored in the data
field and the quantizer in the quantizer
field
julia> qm.data
2×10 Array{UInt8,2}:
0x00 0x01 0x04 0x04 0x04 0x03 0x03 0x03 0x02 0x02
0x01 0x00 0x00 0x02 0x02 0x04 0x03 0x03 0x03 0x03
julia> qm.quantizer
OrthogonalQuantizer{UInt8,Distances.SqEuclidean,Int64,2}, 2 quantizers, 5 codes
A new array can be quantized using the quantizers
julia> quantize(qv.quantizer, rand(1:10, 5))
5-element QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Int64,1}:
9
9
9
9
9
julia> quantize(qm.quantizer, rand(1:60, 6, 2))
6×2 QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Int64,2}:
13 7
14 8
15 9
34 40
35 41
36 42
The :pq
(k-means), :opq
('cartesian' k-means) and :rvq
('residual') quantization methods work for arrays with AbstractFloat
elements only and return the same result each run.
julia> quantize(Float32.(v), k=2, method=:pq)
10-element QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Float32,1}:
2.5
2.5
2.5
2.5
7.5
7.5
7.5
7.5
7.5
7.5
julia> quantize(Float32.(m), k=5, m=2, method=:pq)
6×10 QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Float32,2}:
4.0 4.0 13.0 19.0 31.0 31.0 31.0 49.0 49.0 49.0
5.0 5.0 14.0 20.0 32.0 32.0 32.0 50.0 50.0 50.0
6.0 6.0 15.0 21.0 33.0 33.0 33.0 51.0 51.0 51.0
4.0 13.0 13.0 28.0 28.0 28.0 43.0 43.0 55.0 55.0
5.0 14.0 14.0 29.0 29.0 29.0 44.0 44.0 56.0 56.0
6.0 15.0 15.0 30.0 30.0 30.0 45.0 45.0 57.0 57.0
Indexing can be performed as in regular arrays
julia> qm[1,1]
1
julia> qm[2,:]
10-element Array{Int64,1}:
2
8
14
14
14
44
44
44
56
56
julia> qm[1:1,:]
1×10 Array{Int64,2}:
1 7 13 13 13 43 43 43 55 55
however changing values is not supported
julia> qm[1,1] = 0
ERROR: setindex! not supported on QuantizedArrays
The element type of the compressed array representation is dynamically calculated to reflect the number of vector prototypes employed
julia> m = rand(1, 10_000);
julia> quantize(m, k=256) # 8 bits are used (UInt8)
1×10000 QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt8,Distances.SqEuclidean,Float64,2}:
0.456901 0.142213 0.296856 0.367847 … 0.388446 0.233503 0.784119
julia> quantize(m, k=257) # 16 bits are used (UInt16)
1×10000 QuantizedArray{QuantizedArrays.OrthogonalQuantization,UInt16,Distances.SqEuclidean,Float64,2}:
0.458133 0.142868 0.294317 0.370009 … 0.389731 0.231882 0.786546