পান্ডার সাহায্যে বিশ্লেষণের জন্য একটি 20 জিবি ফাইল খোলা হচ্ছে


33

আমি বর্তমানে মেশিন লার্নিংয়ের জন্য পান্ডাস এবং অজগর সহ একটি ফাইল খোলার চেষ্টা করছি এটি আমার কাছে সমস্ত ডেটা ফ্রেমে রাখাই আদর্শ হবে। এখন ফাইলটি 18 গিগাবাইট বড় এবং আমার র‍্যাম 32 গিগাবাইট তবে আমি মেমরির ত্রুটি পেতে থাকি।

আপনার অভিজ্ঞতা থেকে এটা সম্ভব? যদি না হয় আপনি এই কাছাকাছি যেতে আরও ভাল উপায় জানেন? (মধুচক্রের টেবিল? আমার র‌্যামের আকার বাড়িয়ে to৪ করা? একটি ডাটাবেস তৈরি করুন এবং অজগর থেকে এটি অ্যাক্সেস করুন)


আমার একই সমস্যা ছিল, আমি আপনাকে আপনার হার্ড ড্রাইভের অদলবদল, পেজিং, আকার বাড়ানোর পরামর্শ দিচ্ছি।
মিডিয়া

ডেটা লোড করার সময় থাম্বের নিয়মটি pandasহল, আপনার আরও 5-10 গুণ বেশি র্যাম থাকতে হবে। আমি inplaceঅপারেশনগুলি করার পরামর্শ দিচ্ছি , স্পষ্টভাবে garbage.collectorডি-বরাদ্দ করা অবজেক্টগুলিকে কল করুন ।
কিরিতি গাক

4
আপনার শেষ লক্ষ্যটি উল্লেখ করে এই প্রশ্নটিকে আরও ভাল করুন। আপনি অনুসন্ধানের ডেটা বিশ্লেষণ, ডেটা পরিষ্কার, কোনও মডেলকে প্রশিক্ষণ দিচ্ছেন বা কী করছেন? কি ধরনের তথ্য?
পিট

1
আপনি কি ডাস্ক ব্যবহার বিবেচনা করেছেন ?
rpanai

উত্তর:


32

যদি এটি কোনও সিএসভি ফাইল হয় এবং আপনার অ্যালগরিদম প্রশিক্ষণের সময় আপনার একবারে সমস্ত ডেটা অ্যাক্সেস করার প্রয়োজন না হয়, আপনি খণ্ডে এটি পড়তে পারেন। pandas.read_csvপদ্ধতি আপনি ভালো খন্ডে একটি ফাইল পড়তে অনুমতি দেয়:

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

এখানে পদ্ধতির ডকুমেন্টেশন রয়েছে


এটি কি জিপ ফাইলের ক্ষেত্রেও প্রযোজ্য?
জেমস ওয়েয়ারজবা

এটি কাজ করা উচিত যদি জিপ করা ফাইলটিও একটি সিএসভি ফাইল হয় তবে আপনাকে পদ্ধতির আর্গুমেন্ট হিসাবে সংকোচনের ধরণটি পাস করতে হবে
ধরণটি

22

দুই সম্ভাবনার আছে: হয় আপনি প্রয়োজন (যেমন আপনার মেশিন লার্নিং আলগোরিদিম একবারে এটা সব গ্রাস করতে চায়) প্রক্রিয়াকরণের জন্য মেমরি আপনার সমস্ত ডেটা আছে, অথবা আপনি এটা ছাড়া কি করতে পারেন (উদাঃ আপনার অ্যালগরিদম শুধুমাত্র সারির নমুনা প্রয়োজন বা কলাম একবারে)।

প্রথম ক্ষেত্রে, আপনার একটি স্মৃতি সমস্যা সমাধান করা দরকার । আপনার মেমরির আকার বাড়ান, একটি উচ্চ-মেমরি ক্লাউড মেশিন ভাড়া করুন, ইনপ্লেস অপারেশনগুলি ব্যবহার করুন, আপনি যে ধরণের ডেটা পড়ছেন সে সম্পর্কে তথ্য সরবরাহ করুন, সমস্ত অব্যবহৃত ভেরিয়েবলগুলি মুছে ফেলা এবং আবর্জনা সংগ্রহ ইত্যাদি নিশ্চিত করুন etc.

এটি খুব সম্ভবত যে পান্ডাদের আপনার ডেটা হ্যান্ডেল করার জন্য 32 গিগাবাইট র‍্যাম যথেষ্ট হবে না। নোট করুন যে পাঠ্য হিসাবে সঞ্চিত হলে পূর্ণসংখ্যা "1" কেবল একটি বাইট হয় তবে 8 বাইট হিসাবে উপস্থাপিত হয় int64(যা পাণ্ডগণ যখন পাঠ্য থেকে পাঠ করে এটি ডিফল্ট হয়)। আপনি ভাসমান পয়েন্ট নম্বর "1.0" দিয়ে একই উদাহরণ তৈরি করতে পারেন যা 3-বাইট স্ট্রিং থেকে float64ডিফল্টরূপে 8-বাইটে প্রসারিত হয় । পান্ডাদের প্রতিটি কলামে কোন প্রকারটি ব্যবহার করতে হবে এবং ছোট্ট সম্ভাব্য উপস্থাপনাগুলি জোর করে সুনির্দিষ্টভাবে জানতে দিয়ে আপনি কিছু জায়গা জিততে পারেন, তবে আমরা পাইথনের ডেটা স্ট্রাকচারের ওভারহেডের কথা বলতে শুরু করি নি, যা এখানে অতিরিক্ত বা পয়েন্ট দুটি যুক্ত করতে পারে বা সহজেই সেখানে , এবং পয়েন্টারগুলি একটি 64-বিট মেশিনে প্রতিটি 8 বাইট।

সংক্ষিপ্তসার হিসাবে: না, পান্ডাসের জন্য একটি 20 গিগাবাইট ফাইল পরিচালনা করতে 32 জিবি র‍্যাম সম্ভবত যথেষ্ট নয়।

দ্বিতীয় ক্ষেত্রে (যা আরও বাস্তবসম্মত এবং সম্ভবত এটি আপনার জন্য প্রযোজ্য), আপনার একটি ডেটা ম্যানেজমেন্ট সমস্যা সমাধান করা দরকার । প্রকৃতপক্ষে, যখন প্রক্রিয়াজাতকরণের জন্য আপনাকে কেবল তার কিছু অংশের প্রয়োজন হয় তখন সমস্ত ডেটা লোড করে রাখা খারাপ ডেটা ম্যানেজমেন্টের লক্ষণ হতে পারে। এখানে একাধিক বিকল্প রয়েছে:

  1. একটি এসকিউএল ডাটাবেস ব্যবহার করুন। আপনি যদি পারেন তবে এটি প্রায় সর্বদা প্রথম পছন্দ এবং একটি শালীন আরামদায়ক সমাধান। আকারের মতো 20 জিবি শোনাচ্ছে যে বেশিরভাগ এসকিউএল ডাটাবেসগুলি এমনকি একটি (উচ্চ-শেষ) ল্যাপটপে বিতরণ করার প্রয়োজন ছাড়াই ভাল পরিচালনা করবে। আপনি কলামগুলি সূচী করতে সক্ষম হবেন, এসকিউএল এর মাধ্যমে প্রাথমিক সংগ্রহগুলি করতে পারবেন এবং একটি সহজ ব্যবহার করে আরও জটিল প্রক্রিয়াকরণের জন্য পান্ডায় প্রয়োজনীয় সাবমেলগুলি পাবেনpd.read_sql । ডেটাবেসে ডেটা স্থানান্তর করা আপনাকে আপনার কলামগুলির প্রকৃত ডেটা এবং ধরণের সম্পর্কে চিন্তাভাবনা করার সুযোগও সরবরাহ করবে ।

  2. যদি আপনার ডেটা বেশিরভাগ সংখ্যাসূচক হয় (যেমন অ্যারে বা টেনারগুলি ) তবে আপনি এটি এইচডিএফ 5 ফর্ম্যাটে ধারণ করতে পারেন (পাই টেবিলগুলি দেখুন ), যা আপনাকে কেবলমাত্র ডিস্ক থেকে বিশাল অ্যারেগুলির প্রয়োজনীয় স্লাইসগুলি সহজেই পড়তে দেয়। বেসিক numpy.save এবং numpy.load এছাড়াও ডিস্কে অ্যারে মেমরি-ম্যাপিংয়ের মাধ্যমে একই প্রভাব অর্জন করে। জিআইএস এবং সম্পর্কিত রাস্টার ডেটাগুলির জন্য ডেডিকেটেড ডেটাবেস রয়েছে , যা প্যান্ডাসের সাথে সরাসরি এসকিউএল হিসাবে সংযুক্ত নাও হতে পারে, তবে আপনাকে উপযুক্তভাবে সুবিধাজনকভাবে স্লাইস এবং কোয়েরি করতে দেওয়া উচিত।

  3. পান্ডস এইচডিএফ 5 বা নাম্পার অ্যারেগুলির এই জাতীয় "আংশিক" মেমরি-ম্যাপিং সমর্থন করে না, যতদূর আমি জানি। আপনি যদি এখনও একটি ধরণের "খাঁটি-পান্ডাস" সমাধান চান তবে আপনি "শারডিং" করে কাজ করার চেষ্টা করতে পারেন: হয় আপনার বিশাল টেবিলের কলামগুলি পৃথকভাবে সংরক্ষণ করুন (যেমন পৃথক ফাইলগুলিতে বা একটি একক এইচডিএফ 5 এর পৃথক "টেবিলগুলিতে" ফাইল) এবং চাহিদা অনুযায়ী প্রয়োজনীয় লোড করা বা সারিগুলির অংশগুলি পৃথকভাবে সঞ্চয় করা। তবে, আপনাকে প্রয়োজনীয় অংশগুলি লোড করার জন্য যুক্তিটি বাস্তবায়ন করতে হবে, সুতরাং বেশিরভাগ এসকিউএল ডাটাবেসে ইতিমধ্যে অন্তর্ভুক্ত সাইকেলগুলিকে পুনর্বহাল করা, সুতরাং সম্ভবত বিকল্প 1 এখানে আরও সহজ হতে পারে। যদি আপনার ডেটা কোনও সিএসভিতে আসে তবে আপনি chunksizeপ্যারামিটারটি নির্দিষ্ট করে বিশদভাবে এটি প্রক্রিয়া করতে পারেন pd.read_csv


5
"প্রথম ক্ষেত্রে" উল্লেখ করা উচিত এমন কিছু হ'ল যদি ওপিতে ডাটাতে একই মান (শূন্যের মতো) সহ প্রচুর এন্ট্রি থাকে তবে ডেটা অপ্রয়োজনীয় বলে মনে করা হয় এবং স্ক্রি স্পার্স ম্যাট্রিক্স পরিবর্তে ব্যবহার করা যেতে পারে a পান্ডাস ডেটা ফ্রেম - স্পার্স ডেটার জন্য অনেক কম মেমরি দরকার।
রিকার্ডো ক্রুজ

9

কিছুদিন আগে আমার এই সমস্যাটি ছিল! নিশ্চিত না যে এটি আপনার নির্দিষ্ট ক্ষেত্রে সহায়তা করে যেহেতু আপনি এত বেশি বিশদ সরবরাহ করছেন না, তবে আমার পরিস্থিতিটি একটি 'বড়' ডেটাসেটে অফলাইনে কাজ করা ছিল। শক্তিটি মিটার থেকে 20 গিগাবাইট সিএসভি ফাইল হিসাবে ডেটা প্রাপ্ত হয়েছিল, বেশ কয়েক সেকেন্ডের ব্যবধানে সময় সিরিজের ডেটা।

ফাইল আইও:

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

সরাসরি জিজিপ ফাইলের উপর একটি খণ্ড পুনরাবৃত্তি তৈরি করুন (আনজিপ করবেন না!)

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,
                     )

খণ্ড খণ্ড খণ্ডিত

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

খণ্ড লুপের ভিতরে, আমি কিছু ফিল্টারিং করছি এবং সময়মতো পুনরায় নমুনা নিচ্ছি। এটি করে আমি আরও অফলাইন ডেটা অনুসন্ধানের জন্য আকারটি 20 জিবি থেকে কয়েক শ এমবি এইচডিএফ 5 এ কমিয়েছি।


5

আমার অভিজ্ঞতায়, read_csv()পরামিতি দিয়ে আরম্ভ low_memory=Falseকরা বড় ফাইলগুলিতে পড়ার সময় সহায়তা করে। আমি মনে করি না আপনি যে ফাইলটি পড়েছেন তার উল্লেখ করেছেন, সুতরাং আপনার অবস্থার ক্ষেত্রে এটি কতটা প্রযোজ্য তা আমি নিশ্চিত নই।


1

যদি আপনার ফাইলটি কোনও সিএসভি হয় তবে আপনি তা সহজেই চুনক বাই চঙ্কে করতে পারেন। আপনি কেবল সহজভাবে করতে পারেন:

import pandas as pd
for chunk in pd.read_csv(FileName, chunksize=ChunkSizeHere)
(Do your processing and training here)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.