8

Tôi có một bộ 2000 cây hồi quy ngẫu nhiên được huấn luyện (từ Random Forest Regressor của scikit learn with n_estimators=1). Đào tạo cây song song (50 lõi) trên một tập dữ liệu lớn (~ 100000 * 700000 = 70GB @ 8-bit) sử dụng multiprocessing và bộ nhớ dùng chung hoạt động như một nét duyên dáng. Lưu ý, tôi không sử dụng hỗ trợ đa lõi sẵn có của RF kể từ khi tôi đang làm tính năng lựa chọn trước.hiểu scikit tìm hiểu Yêu cầu bộ nhớ rừng ngẫu nhiên để dự đoán

Vấn đề: khi thử nghiệm một ma trận lớn (~ 20000 * 700000) song song tôi luôn luôn hết bộ nhớ (tôi có quyền truy cập vào máy chủ có 500 GB RAM).

Chiến lược của tôi là có ma trận thử nghiệm trong bộ nhớ và chia sẻ nó trong tất cả các quy trình. Theo yêu cầu statement by one of the developers yêu cầu bộ nhớ để thử nghiệm là 2 * n_jobs * sizeof (X), và trong trường hợp của tôi, một yếu tố khác của * 4 là có liên quan, vì các mục ma trận 8 bit được truyền lên float32 trong RF.

Bằng số, tôi nghĩ để thử nghiệm tôi cần:
14GB để giữ ma trận kiểm tra trong bộ nhớ + 50 (= n_jobs) * 20000 (N_SAMPLES) * 700 (= n_features) * 4 (upcasting nổi) * 2 bytes = 14 gb + 5.6 gb = ~ 21GB bộ nhớ.

Tuy nhiên, nó luôn thổi lên hàng trăm GB. Tôi thiếu gì ở đây? (Tôi đang trên phiên bản mới nhất của scikit-học, vì vậy các vấn đề bộ nhớ cũ cần được giải quyết)

Một quan sát:
Chạy trên một lõi duy nhất sử dụng bộ nhớ để thử nghiệm dao động từ 30 đến 100 GB (được đo bởi free)

mã của tôi:

#---------------- 
#helper functions 
def initializeRFtest(*args): 
    global df_test, pt_test #initialize test data and test labels as globals in shared memory 
    df_test, pt_test = args 


def star_testTree(model_featidx): 
    return predTree(*model_featidx) 

#end of helper functions 
#------------------- 

def RFtest(models, df_test, pt_test, features_idx, no_trees): 
    #test trees in parallel 
    ncores = 50 
    p = Pool(ncores, initializer=initializeRFtest, initargs=(df_test, pt_test)) 
    args = itertools.izip(models, features_idx) 
    out_list = p.map(star_testTree, args) 
    p.close() 
    p.join() 
    return out_list 

def predTree(model, feat_idx): 
    #get all indices of samples that meet feature subset requirement 
    nan_rows = np.unique(np.where(df_test.iloc[:,feat_idx] == settings.nan_enc)[0]) 
    all_rows = np.arange(df_test.shape[0]) 
    rows = all_rows[np.invert(np.in1d(all_rows, nan_rows))] #discard rows with missing values in the given features 

    #predict 
    pred = model.predict(df_test.iloc[rows,feat_idx]) 
    return predicted 

#main program 
out = RFtest(models, df_test, pt_test, features_idx, no_trees) 

Edit: quan sát khác: Khi chunking dữ liệu thử nghiệm chương trình chạy s một cách nhẹ nhàng với mức sử dụng bộ nhớ giảm nhiều. Đây là những gì tôi sử dụng để làm cho chương trình chạy.
Đoạn mã cho cập nhật predTree chức năng:

def predTree(model, feat_idx): 
    # get all indices of samples that meet feature subset requirement 
    nan_rows = np.unique(np.where(test_df.iloc[:,feat_idx] == settings.nan_enc)[0]) 
    all_rows = np.arange(test_df.shape[0]) 
    rows = all_rows[np.invert(np.in1d(all_rows, nan_rows))] #discard rows with missing values in the given features 

    # predict height per valid sample 
    chunksize = 500 
    n_chunks = np.int(math.ceil(np.float(rows.shape[0])/chunksize)) 


    pred = [] 
    for i in range(n_chunks): 
     if n_chunks == 1: 
      pred_chunked = model.predict(test_df.iloc[rows[i*chunksize:], feat_idx]) 
      pred.append(pred_chunked) 
      break 
     if i == n_chunks-1: 
      pred_chunked = model.predict(test_df.iloc[rows[i*chunksize:], feat_idx]) 
     else: 
      pred_chunked = model.predict(test_df.iloc[rows[i*chunksize:(i+1)*chunksize], feat_idx]) 
     print pred_chunked.shape 
     pred.append(pred_chunked) 
    pred = np.concatenate(pred) 

    # populate matrix 
    predicted = np.empty(test_df.shape[0]) 
    predicted.fill(np.nan) 
    predicted[rows] = pred 
    return predicted 
+0

Có bao nhiêu bộ nhớ mà các cây hồi quy ngẫu nhiên được huấn luyện năm 2000 của bạn? Chúng có được sao chép cho mỗi lõi trong số 50 lõi không? –

+0

@ BrianO'Donnell bạn có phải là kích thước của mô hình không? Tôi không có quyền truy cập vào mô hình nữa, nhưng nó chắc chắn có thể quản lý được. – Dahlai

+0

Có, kích thước của mô hình. –

Trả lời

0

Tôi không chắc chắn nếu vấn đề bộ nhớ không liên quan đến việc sử dụng của itertools.izip trong args = itertools.izip(models, features_idx) có thể kích hoạt tạo ra các bản sao của iterator cùng với đối số của nó trên tất cả các chủ đề . Bạn đã thử sử dụng zip chưa?

Giả thuyết khác có thể là thu gom rác không hiệu quả - không được kích hoạt khi bạn cần. Tôi sẽ kiểm tra xem có chạy gc.collect() ngay trước model.predict trong predTree không giúp ích gì.

Ngoài ra còn có lý do tiềm năng thứ 3 (có thể là đáng tin cậy nhất). Hãy để tôi trích dẫn Python FAQ on How does Python manage memory?:

Trong bản phát hành hiện tại của CPython, mỗi lần gán mới cho x bên trong vòng lặp sẽ giải phóng tài nguyên được phân bổ trước đó.

Trong chức năng chunked của bạn, bạn làm chính xác điều đó - lặp lại chỉ định cho pred_chunked.

Các vấn đề liên quan