koji/メガネ男の日誌

日々の学び、活動状況を記録します。仕事のことは少なめ。

julia と python の処理スピードを競わせてみた

f:id:kj_man666:20200808182929j:plain データサイエンス向きの新しい言語、julia を kaggle のタイタニックのデータセットで回して、python とどちらが処理速度が速いか、比較してみました。

コードはこちらになります。

なお、01 python.ipynbpython のコード、02 julia.ipynb がjulia がコードになっております。

タイタニックのデータセットこちら

タイタニックのコンペそのものの解説はこちらの記事をご参照ください。

なお、今回のコードは予測精度の向上は目指しておりませんことをご了承ください。

python、julia 共通のコードの流れ

csvデータをDataFrame型で読込む

統計量の表示

欠損値の処理

 - trainデータの Age の欠損値を含む行を削除

 - test データの Age、Fare の欠損値を平均値に置き換え

相関係数

特徴量の選定

 - 今回はラベルエンコーディングのやり方がまだわからないので数値データの PclassAgeSibSpParchFare の5つのみを特徴量にしています。

データの分割(ホールドアウト法)

学習モデルの作成 ‐ 誤差 ‐ 予測データの作成

 - ランダムフォレストを採用しました。

csvの出力

julia と python のコードの比較(抜粋)

csvデータをDataFrame型で読込む

julia は python と違いフォルダのパスを設定しなくてもカレントディレクトリを読み込めるようです。

train = pd.read_csv(csvのあるフォルダのパス + "train.csv")
  • julia
train = DataFrame(load("train.csv"))
統計量の表示
train.describe()

f:id:kj_man666:20200808180639p:plain

  • julia
describe(train)

f:id:kj_man666:20200808180652p:plain

julia と python では 統計量の表示の並びが違うようですね。

また、julia は デフォルトだと jupyter は 10行ほどしか表示してくれないため、設定を変更する必要があります。

下記のサイトを参考に変更してみましょう。

Windows の場合は、kernel.json は C:\ユーザー\AppData\Roaming\jupyter\kernels\julia-x.x にありました。

ki-chi.jp

欠損値の処理

欠損値のカウント

train.isnull().sum()
  • julia
Dict(zip(names(train), sum.(eachcol(ismissing.(train)))))

欠損値を含む行を削除

train = train.dropna(subset=["Age"])
  • julia
train = train[ismissing.(train)[:, :"Age"] .== 0, :]

欠損値を他の値で置き換え

test["Age"] = test["Age"].fillna(test["Age"].mean())
  • julia
test[:, :Age] = coalesce.(test[:, :Age], mean(test[ismissing.(test)[:, :Age] .== 0, :][:, :Age]))

julia の場合は 欠損値処理のための関数があまりないのか、少し複雑なコードになっています。

相関係数を表示
train.corr()["Survived"]
  • julia
[cor(train[:, i], train[:, "Survived"]) for i in ["PassengerId", "Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"]]

julia の場合は DataFrame 全体の相関係数を表示できず、for 文等を使ってすべてのカラムの相関係数を表示する必要があります。

特徴量の選定

x が説明変数、y が目的変数になっています。

x = train[["Pclass", "Age", "SibSp", "Parch", "Fare"]]

y = train["Survived"]
  • julia
x = Matrix(train[: , [:Pclass, :Age, :SibSp, :Parch, :Fare]])

y = train[:, :Survived]

julia の機械学習ライブラリはDataFrame 型のデータを読込めないようなので、Matrix() で Array型に変換する必要があります。

データの分割(ホールドアウト法)
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=0)
  • julia
using ScikitLearn.CrossValidation: train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=0);

julia に scikit-learn をインストールするには、こちらの GitHub が参考になります。

github.com

学習モデルの作成 ‐ 誤差 ‐ 予測データの作成
from sklearn.ensemble import RandomForestClassifier as classifier

clf = classifier(n_estimators = 100, random_state=0)

clf.fit(x_train, y_train)

y_pred = clf.predict(x_test)
  • julia
@sk_import ensemble: RandomForestClassifier

forest = RandomForestClassifier(n_estimators=100, random_state=0)

fit!(forest, x_train, y_train)

y_pred = predict(forest, x_test)

この辺はおおむね同じですね。

csvの出力
submission.to_csv('submission_rf.csv', index=False)
  • julia
submission |> CSV.write("submission.csv", delim=',' , writeheader=true)
経過時間の計測
# 処理前の時間を取得
import time
start = time.time()

# 処理後の経過時間を表示
elapsed_time = time.time() - start
print(elapsed_time)
  • julia
# 処理前の時間を取得
using Dates
start = Dates.now()

# 処理後の経過時間を表示
elapsed_time = Dates.now() - start
println(elapsed_time)

気になる処理速度を比較

  • python の処理時間 (秒)
0.7730164527893066
  • julia の処理時間 (ミリ秒 = 1/1000秒)
30270 milliseconds

なんと、julia は最初に最適化処理を行うせいか、圧倒的に python が早い結果となりました。

最適化後は julia は高速化するようなので、同じ処理を複数回行うような場合は julia の方が高速化するかもしれません。

今後も色々試してみたいと思います。

以上になります、最後までお読みいただきありがとうございました。