Mở tệp 20 GB để phân tích với gấu trúc


33

Tôi hiện đang cố gắng mở một tệp với gấu trúc và trăn cho mục đích học máy, thật lý tưởng cho tôi khi có tất cả chúng trong DataFrame. Bây giờ Tệp có dung lượng lớn 18 GB và RAM của tôi là 32 GB nhưng tôi vẫn bị lỗi bộ nhớ.

Từ kinh nghiệm của bạn là nó có thể? Nếu không bạn có biết một cách tốt hơn để đi xung quanh này? (bảng hive? tăng kích thước RAM của tôi lên 64? tạo cơ sở dữ liệu và truy cập nó từ python)


Tôi cũng gặp vấn đề tương tự, tôi khuyên bạn nên tăng khả năng trao đổi, phân trang, kích thước của ổ cứng.
Truyền thông

Nguyên tắc khi tải dữ liệu pandaslà, bạn cần có RAM gấp 5-10 lần. Tôi khuyên bạn nên thực hiện các inplacehoạt động, gọi một cách rõ ràng garbage.collectorđể phân bổ lại các đối tượng.
Kiritee Gak

4
Làm cho câu hỏi này tốt hơn bằng cách nêu mục tiêu cuối cùng của bạn. Bạn đang làm phân tích dữ liệu thăm dò, làm sạch dữ liệu, đào tạo một mô hình, hoặc những gì? Những loại dữ liệu?
Pete

1
Bạn đã xem xét để sử dụng dask ?
rpanai

Câu trả lời:


32

Nếu đó là tệp csv và bạn không cần phải truy cập tất cả dữ liệu cùng một lúc khi đào tạo thuật toán của mình, bạn có thể đọc nó theo từng đoạn. Các pandas.read_csvphương pháp cho phép bạn đọc một tập tin trong khối như thế này:

import pandas as pd
for chunk in pd.read_csv(<filepath>, chunksize=<your_chunksize_here>)
    do_processing()
    train_algorithm()

Đây là tài liệu của phương pháp


điều này có áp dụng cho tập tin zip không?
James Wierzba

Nó sẽ hoạt động nếu tệp nén cũng là tệp csv, bạn cần truyền loại nén làm đối số cho phương thức
Olel Daniel

22

Có hai khả năng: hoặc bạn cần có tất cả dữ liệu trong bộ nhớ để xử lý (ví dụ: thuật toán học máy của bạn sẽ muốn sử dụng tất cả dữ liệu đó cùng một lúc) hoặc bạn có thể làm mà không cần nó (ví dụ: thuật toán của bạn chỉ cần các mẫu hàng hoặc cột cùng một lúc).

Trong trường hợp đầu tiên, bạn sẽ cần giải quyết vấn đề về bộ nhớ . Tăng kích thước bộ nhớ của bạn, thuê một máy đám mây bộ nhớ cao, sử dụng các thao tác tại chỗ, cung cấp thông tin về loại dữ liệu bạn đang đọc, đảm bảo xóa tất cả các biến không sử dụng và thu thập rác, v.v.

Rất có khả năng 32GB RAM sẽ không đủ để Pandas xử lý dữ liệu của bạn. Lưu ý rằng số nguyên "1" chỉ là một byte khi được lưu dưới dạng văn bản nhưng 8 byte khi được biểu thị dưới dạng int64(là mặc định khi Pandas đọc nó từ văn bản). Bạn có thể tạo ví dụ tương tự với số dấu phẩy động "1.0" mở rộng từ chuỗi 3 byte thành 8 byte float64theo mặc định. Bạn có thể giành được một số không gian bằng cách cho Pandas biết chính xác loại nào sẽ được sử dụng cho mỗi cột và buộc các biểu diễn nhỏ nhất có thể, nhưng chúng tôi thậm chí không bắt đầu nói về cấu trúc dữ liệu của Python ở đây, có thể thêm một con trỏ phụ hoặc hai ở đây hoặc ở đó một cách dễ dàng và con trỏ là 8 byte mỗi máy trên một máy 64 bit.

Tóm lại: không, RAM 32 GB có lẽ không đủ để Pandas xử lý tệp 20 GB.

Trong trường hợp thứ hai (thực tế hơn và có thể áp dụng cho bạn), bạn cần giải quyết vấn đề quản lý dữ liệu . Thật vậy, việc phải tải tất cả dữ liệu khi bạn thực sự chỉ cần các phần của nó để xử lý, có thể là một dấu hiệu của quản lý dữ liệu xấu. Có nhiều lựa chọn ở đây:

  1. Sử dụng cơ sở dữ liệu SQL. Nếu bạn có thể, nó gần như luôn luôn là lựa chọn đầu tiên và một giải pháp thoải mái. Âm thanh 20 GB giống như kích thước hầu hết các cơ sở dữ liệu SQL sẽ xử lý tốt mà không cần phải phân phối ngay cả trên máy tính xách tay (cao cấp). Bạn sẽ có thể lập chỉ mục các cột, thực hiện các tập hợp cơ bản thông qua SQL và nhận các mẫu con cần thiết vào Pandas để xử lý phức tạp hơn bằng cách sử dụng đơn giản pd.read_sql. Di chuyển dữ liệu đến cơ sở dữ liệu cũng sẽ cung cấp cho bạn cơ hội để suy nghĩ về các loại dữ liệu và kích thước thực tế của các cột.

  2. Nếu dữ liệu của bạn chủ yếu là số (tức là mảng hoặc tenxơ), bạn có thể xem xét giữ nó ở định dạng HDF5 (xem PyTables ), cho phép bạn chỉ đọc thuận tiện các lát cần thiết của các mảng lớn từ đĩa. Basic numpy.save và numpy.load cũng đạt được hiệu quả tương tự thông qua bộ nhớ ánh xạ các mảng trên đĩa. Đối với GIS và dữ liệu raster có liên quan, có các cơ sở dữ liệu chuyên dụng , có thể không kết nối trực tiếp với gấu trúc như SQL, nhưng cũng cho phép bạn thực hiện các lát cắt và truy vấn hợp lý một cách thuận tiện.

  3. Pandas không hỗ trợ ánh xạ bộ nhớ "một phần" như vậy của HDF5 hoặc mảng numpy, theo như tôi biết. Nếu bạn vẫn muốn có một loại giải pháp "gấu trúc thuần túy", bạn có thể thử xử lý bằng cách "shending": lưu trữ các cột của bảng lớn của bạn (ví dụ: trong các tệp riêng biệt hoặc trong các "bảng" riêng biệt của một HDF5 tệp) và chỉ tải những thứ cần thiết theo yêu cầu hoặc lưu trữ các khối hàng riêng biệt. Tuy nhiên, sau đó bạn cần triển khai logic để tải các đoạn cần thiết, do đó phát minh lại các xe đạp đã được đưa vào trong hầu hết các cơ sở dữ liệu SQL, vì vậy có lẽ tùy chọn 1 vẫn dễ dàng hơn ở đây. Tuy nhiên, nếu dữ liệu của bạn xuất hiện trong một CSV, bạn có thể xử lý dữ liệu theo từng khối bằng cách chỉ định chunksizetham số pd.read_csv.


5
Một điều cần được đề cập trong "trường hợp đầu tiên" là nếu OP có nhiều mục nhập có cùng giá trị trong dữ liệu (như số không), dữ liệu được cho là thưa thớt và có thể sử dụng ma trận thưa thớt hơn là một ma trận thưa thớt pandas dataframe - dữ liệu thưa thớt đòi hỏi ít bộ nhớ hơn.
Ricardo Cruz

9

Tôi chỉ có vấn đề này một vài ngày trước! Không chắc điều này có giúp ích gì trong trường hợp cụ thể của bạn không vì bạn không cung cấp quá nhiều chi tiết, nhưng tình huống của tôi là làm việc ngoại tuyến trên bộ dữ liệu 'lớn'. Dữ liệu được lấy là các tệp CSV được nén 20GB từ các đồng hồ đo năng lượng, dữ liệu chuỗi thời gian trong khoảng thời gian vài giây.

Tệp IO:

data_root = r"/media/usr/USB STICK"
fname = r"meters001-050-timestamps.csv.gz"
this_file = os.path.join(data_root,fname)
assert os.path.exists(this_file), this_file
this_file

Tạo một trình vòng lặp chunk trực tiếp trên tệp gzip (không giải nén!)

cols_to_keep = [0,1,2,3,7]
column_names = ['METERID','TSTAMP','ENERGY','POWER_ALL','ENERGY_OUT',]
parse_dates = ['TSTAMP']
dtype={'METERID': np.int32, 
       'ENERGY': np.int32,
       'POWER_ALL': np.int32,
       'ENERGY_OUT': np.int32,
      }
df_iterator = pd.read_csv(this_file, 
                        skiprows=0, 
                        compression='gzip',
                        chunksize=1000000, 
                        usecols=cols_to_keep,
                        delimiter=";",
                        header=None,
                        names = column_names,
                      dtype=dtype,
                     parse_dates=parse_dates,
                     index_col=1,
                     )

Lặp đi lặp lại trên khối

new_df = pd.DataFrame()
count = 0
for df in df_iterator:
    chunk_df_15min = df.resample('15T').first()
    #chunk_df_30min = df.resample('30T').first()
    #chunk_df_hourly = df.resample('H').first()
    this_df = chunk_df_15min
    this_df = this_df.pipe(lambda x: x[x.METERID == 1])
    #print("chunk",i)
    new_df = pd.concat([new_df,chunk_df_15min])
    print("chunk",count, len(chunk_df_15min), 'rows added')
    #print("chunk",i, len(temp_df),'rows added')
    #break
    count += 1

Trong vòng lặp chunk, tôi đang thực hiện một số bộ lọc và lấy mẫu lại đúng thời gian. Làm điều này tôi đã giảm kích thước từ 20 GB xuống vài trăm MB HDF5 để khám phá dữ liệu ngoại tuyến hơn nữa.


5

Theo kinh nghiệm của tôi, khởi tạo read_csv()với tham số low_memory=Falsecó xu hướng giúp đỡ khi đọc trong các tệp lớn. Tôi không nghĩ rằng bạn đã đề cập đến loại tệp bạn đang đọc, vì vậy tôi không chắc cách này phù hợp với tình huống của bạn.


1

Nếu tệp của bạn là CSV thì bạn chỉ cần thực hiện trong Chunk by Chunk. Bạn chỉ có thể làm đơn giản:

import pandas as pd
for chunk in pd.read_csv(FileName, chunksize=ChunkSizeHere)
(Do your processing and training here)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.