Array でしていた計算を、JuliaDB の table ですると早くなる例その2
Array でしていた計算を、JuliaDB の table ですると早くなる例その2です。
ユークリッド距離の2乗の距離行列を求めてみましょう。データの例は、かって知りたる iris です。
iris を読み込んで、Array と table (正確には、IndexedTables.NextTable) に変換します。
using RDatasets, DataFrames, JuliaDB iris = dataset("datasets", "iris") A = Array(iris[:,1:4]) table_iris = table(iris[:,1:4])
table への変換は、Array からの変換は結構、面倒で、DataFrame を1回通す方が楽です。ただし、この場合、DataFrames と JuliaDB が一緒に動くので、後から立ち上げた方の stack, aggregate、 groupby などが使えなくなることがあります。
では、おたがいの距離行列の計算式を関数化します。
# JuliaDB function tb_dist(indexed_table::IndexedTables.NextTable) dist_mat = [sum((rows(indexed_table)[i] .- rows(indexed_table)[1]).^2) for i in 1:length(indexed_table)] for j in 2:length(indexed_table) dist_mat = hcat( dist_mat, [sum((rows(indexed_table)[i] .- rows(indexed_table)[j]).^2) for i in 1:length(indexed_table)] ) end return dist_mat end #Array function Array_dist(A::Array) dist_mat = [ sum((A[i,:] .- A[1,:]).^2) for i in 1:size(A)[1]] for j in 2:size(A)[1] dist_mat = hcat( dist_mat, [ sum((A[i,:] .- A[j,:]).^2) for i in 1:size(A)[1]] ) end return dist_mat end
再帰的に書いているので、読み難いかもしれませんが、形は一緒です。
では、お楽しみの時間測定です。
julia> for i in 1:5; @time tb_dist(tb_iris); end 0.024816 seconds (181.48 k allocations: 18.685 MiB) 0.042909 seconds (181.48 k allocations: 18.685 MiB, 43.25% gc time) 0.051451 seconds (181.48 k allocations: 18.685 MiB, 23.65% gc time) 0.038076 seconds (181.48 k allocations: 18.685 MiB, 25.34% gc time) 0.035940 seconds (181.48 k allocations: 18.685 MiB, 24.48% gc time)julia> for i in 1:5; @time Array_dist(A); end 0.284643 seconds (784.48 k allocations: 46.666 MiB, 7.35% gc time) 0.291637 seconds (784.48 k allocations: 46.666 MiB, 6.07% gc time) 0.293948 seconds (784.48 k allocations: 46.666 MiB, 5.17% gc time) 0.293481 seconds (784.48 k allocations: 46.666 MiB, 7.67% gc time) 0.289398 seconds (784.48 k allocations: 46.666 MiB, 8.02% gc time)
DataFrame と同じような使い方をしているだけです。しかし、1桁、JuliaDB の方が早いです。 やはり、JuliaDB って、すごい気がします。使えるなら使う方が良いみたいです。