状況
グループごとにロジスティック回帰 (インカンター) を実行したい 1,300 万行の CSV があります。私のファイルはそのようなものです(値は単なるサンプルです)
ID Max Probability
1 1 0.5
1 5 0.6
1 10 0.99
2 1 0.1
2 7 0.95
だから私は最初にcsvリーダーでそれを読んだ。
私はそのようなものを持っています:
( {"Id" "1", "Max" 1, "Probability" 0.5} {"Id" "1", "Max" 5, "Probability" 0.6} etc.
これらの値を Id でグループ化したいと思います。私の記憶が正しければ、約 120 万の Id があります。(私は pandas を使って Python で実行しましたが、超高速です)
これは、ファイルを読み取ってフォーマットするための私の関数です (小さなデータセットでは問題なく動作します)。
(defn read-file
[]
(let [path (:path-file @config)
content-csv (take-csv path \,)]
(->> (group-by :Id content-csv)
(map (fn [[k v]]
[k {:x (mapv :Max v) :y (mapv :Probability v)}]))
(into {}))))
最終的に、ロジスティック回帰を実行するためにそのようなものが必要です(私はそれについて柔軟であり、 :x および :y のベクトルは必要ありません、seqsは問題ありません)
{"1" {:x [1 5 10] :y [0.5 0.6 0.99]} "2" {:x [1 7] :y [0.1 0.95]} etc.
問題
グループバイ操作に問題があります。CSV からの出力で個別に試してみましたが、Java ヒープ スペース メモリが原因で消えない場合、これは永遠にかかります。問題は私の mapv だと思っていましたが、これは group-by です。
reduce または reduce-kv を使用することを考えましたが、この種の目的でこれらの関数を使用する方法がわかりません。
":x" と ":y" の順序は気にしません (それらの間で同じであるとすぐに、x と y が同じインデックスを持つことを意味します...同じ上にあるので問題ではありません行) と最終結果の Ids を読み取り、そのグループバイを読み取り、順序を維持します。多分それは操作に費用がかかるものですか?
誰かがそれに遭遇した場合は、サンプルデータを提供します:
(def sample '({"Id" "1" "Max" 1 "Probability" 0.5} {"Id" "1" "Max" 5 "Probability" 0.6} {"Id" "1" "Max" 10 "Probability" 0.99} {"Id" "2" "Max" 1 "Probability" 0.1} {"Id" "2" "Max" 7 "Probability" 0.95}))
その他の代替手段
他にもアイデアはありますが、それらが「Clojure」に適しているかどうかはわかりません。
Python では、関数の性質上、またファイルが既に順序付けされているため、group-by を使用する代わりに、各グループの開始インデックスと終了インデックスをデータフレームに書き込んで、サブデータタブを直接選択するだけで済みました。
Clojure から計算する代わりに、ID のリストをロードすることもできます。お気に入り
(定義 ID '("1" "2" など。
だから多分それはで始めることが可能です:
{"1" {:x [] :y []} "2" {:x [] :y []} etc.
前の seq から取得し、各 ID の大きなファイルと照合します。
実際にそれがより効率的かどうかはわかりません。
私はロジスティック回帰のための他のすべての機能を持っていますが、この部分が欠けているだけです! ありがとう !
編集
答えてくれてありがとう、私は最終的にこの解決策を見つけました。
私のproject.cljファイルで
:jvm-opts ["-Xmx13g"])
コード :
(defn data-group->map [group]
{(:Id (first group))
{:x (map :Max group)
:y (map :Probability group)}})
(defn prob-cumsum [data]
(cag/fmap
(fn [x]
(assoc x :y (reductions + (x :y))))
data))
(defn process-data-splitter [data]
(->> (partition-by :Id data)
(map data-group->map)
(into {})
(prob-cumsum)))
すべてのコードをラップしましたが、動作します。スプリットは約5分かかりますが、メガスピードは必要ありません。メモリ使用量は、ファイル読み取りの場合はすべてのメモリにまで達し、シグモイドの場合はそれより少なくなる可能性があります。