Tình hìnhClojure: Nhóm-by quá chậm (nộp 13 triệu-lines)
Tôi có 13 triệu dòng CSV mà tôi muốn thực hiện hồi quy logistic (incanter) cho mỗi nhóm. tập tin của tôi là như thế (giá trị chỉ là mẫu)
ID Max Probability
1 1 0.5
1 5 0.6
1 10 0.99
2 1 0.1
2 7 0.95
Vì vậy, đầu tiên tôi đọc nó với một csv-reader, everithing là tốt.
Tôi có sau đó một cái gì đó như thế:
({"Id" "1", "Max" 1, "Probability" 0.5} {"Id" "1", "Max" 5, "Probability" 0.6} etc.
Tôi muốn nhóm theo các giá trị của Id, Nếu tôi nhớ không lầm thì có khoảng 1,2 triệu Id. (Tôi đã làm nó bằng Python với gấu trúc và nó là siêu nhanh)
Đây là chức năng của tôi để đọc và định dạng tập tin (nó hoạt động tốt trên các tập dữ liệu nhỏ hơn):
(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 {}))))
Tôi muốn cuối cùng để có một cái gì đó như vậy để thực hiện hồi quy logistic (tôi linh hoạt về điều đó, không cần vectơ cho: x và: y, seqs là ok)
{"1" {:x [1 5 10] :y [0.5 0.6 0.99]} "2" {:x [1 7] :y [0.1 0.95]} etc.
vấn đề
Tôi gặp sự cố với thao tác theo nhóm. Tôi đã thử nó một cách riêng biệt trên đầu ra từ CSV và điều này được lấy mãi mãi khi nó không chết vì bộ nhớ Java Heap Space. Tôi nghĩ rằng vấn đề là điều mapv của tôi nhưng đây là nhóm-by.
Tôi đã nghĩ về việc sử dụng giảm hoặc giảm kv nhưng tôi không biết cách sử dụng các chức năng này cho loại mục đích này.
Tôi không quan tâm đến thứ tự ": x" và ": y" (ngay khi chúng giống nhau giữa chúng, tôi có nghĩa là x và y có cùng chỉ mục ... không phải là vấn đề vì chúng trên cùng một dòng) và của các Id trên kết quả cuối cùng và tôi đọc nhóm đó bằng cách giữ nguyên thứ tự. Có thể đó là điều tốn kém cho hoạt động?
tôi cung cấp cho bạn dữ liệu mẫu nếu có người đã gặp rằng:
(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}))
lựa chọn thay thế khác
tôi có những ý tưởng khác, nhưng tôi không chắc chắn họ là "Clojure" -friendly.
Trong Python, vì bản chất của hàm và bởi vì các tập tin đã được ra lệnh, thay vì sử dụng nhóm-by, tôi đã viết trong một dataframe bắt đầu và chỉ số cuối cho mỗi nhóm vì vậy mà tôi chỉ phải chọn trực tiếp tiểu datatab.
Tôi cũng có thể tải danh sách các id thay vì tính toán nó từ Clojure. Giống như
(id id '("1" "2" v.v ...
Vì vậy, có lẽ chúng ta có thể bắt đầu với:
{"1" {:x [] :y []} "2" {:x [] :y []} etc.
từ seq trước và sau đó kết hợp các tập tin lớn trên mỗi ID.
Tôi không biết liệu thực tế có hiệu quả hơn hay không.
Tôi có tất cả các chức năng khác để hồi quy logistic, tôi chỉ thiếu phần này! Cảm ơn!
EDIT
Cảm ơn câu trả lời, cuối cùng tôi có giải pháp này.
Trong file project.clj tôi
:jvm-opts ["-Xmx13g"])
Code:
(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)))
Tôi bọc tất cả các mã của tôi và nó hoạt động. Việc phân chia mất khoảng 5 phút nhưng tôi không cần tốc độ lớn. Sử dụng bộ nhớ có thể tăng lên đến tất cả bộ nhớ để đọc tập tin sau đó ít hơn cho sigmoid.
là cardinality của id cao hay thấp? Các id trong csv có được sắp xếp không? Nếu vậy, bạn có thể thực hiện việc nhóm trong khi bạn đang đọc qua CSV trong một lần truyền. –
Xin chào, cảm ơn bạn đã trả lời. Tôi có khoảng 1,2-1,3 triệu id (thấp hơn 10 lần so với dữ liệu thực tế). Tệp được đặt hàng như ví dụ của tôi, tức là: cấp đầu tiên = ID, cấp hai = Max (Xác suất và Tối đa được sắp xếp giống nhau vì chúng được liên kết bằng đường cong đang phát triển). Vì vậy, có lẽ ý tưởng của bạn là tốt, tôi vẫn không biết làm thế nào để làm điều đó. Vòng lặp có phải là một ý tưởng hay không? Nó không mang lại lợi ích của đa xử lý tôi nghĩ. Tôi sẽ thử một cái gì đó với hợp nhất với firt định dạng lại dữ liệu. –