কীভাবে 3 টি সেটে ডেটা বিভক্ত করবেন (ট্রেন, বৈধতা এবং পরীক্ষা)?


145

আমার কাছে পান্ডাস ডেটাফ্রেম রয়েছে এবং আমি এটিকে 3 টি আলাদা সেটে ভাগ করতে চাই wish আমি জানি যে থেকে ট্রেন_স্টেট_স্প্লিট ব্যবহার করে sklearn.cross_validation, কেউ ডেটা দুটি সেটে বিভাজন করতে পারে (ট্রেন এবং পরীক্ষা)। তবে আমি তিনটি উপায়ে ডেটা বিভক্ত করার কোনও সমাধান খুঁজে পাইনি। সাধারণত, আমি মূল তথ্য সূচকগুলি পেতে চাই।

আমি জানি যে train_test_splitদু'বার ব্যবহার করা এবং কোনওভাবে সূচকগুলি সামঞ্জস্য করতে হবে। তবে 2 এর পরিবর্তে 3 সেটে ডেটা বিভক্ত করার আরও মানক / অন্তর্নির্মিত উপায় আছে কি?


5
এটি আপনার নির্দিষ্ট প্রশ্নের উত্তর দেয় না, তবে আমি মনে করি এটির জন্য আরও মানক পদ্ধতির দুটি সেট, ট্রেন এবং পরীক্ষা বিভক্ত হবে এবং প্রশিক্ষণের সেটটিতে ক্রস-বৈধকরণ চলবে ফলে একা স্ট্যান্ডের "উন্নয়ন" সেটকে অপসারণের প্রয়োজনীয়তা দূর করা হবে ।
ডেভিড

1
এটি আগে উঠে এসেছিল এবং যতদূর আমি জানি এটির জন্য এখনও কোনও অন্তর্নির্মিত পদ্ধতি নেই is
আয়ান

5
আমি হস্টি এট আল এর এলিমেন্টস অফ স্ট্যাটিস্টিকাল লার্নিংয়ের জন্য দুটি পরিবর্তে তিনটি সেট কেন ব্যবহার করতে হবে সে বিষয়ে আলোচনার জন্য পরামর্শ দিই ( ওয়েব.স্তানফোর্ড.ইডু / এহসিটি / লোকাল.ফট / এসপ্রিঞ্জার / গোল্ড মডেল মূল্যায়ন এবং নির্বাচনের অধ্যায়)
আয়ান

2
@ ডেভিড অতিরিক্ত মডেলগুলি রোধ করতে কিছু মডেলগুলিতে ২ এর পরিবর্তে ৩ টি সেট প্রয়োজন। এটি রোধ করতে একটি বিকাশ সেট প্রয়োজন। সুতরাং, ক্রস বৈধতা ব্যবহার করা যথেষ্ট হবে না।
সেন্টাউ

6
@ ইয়াহান, সেই বইটির একটি সংশোধন করা URL হ'ল স্টেটওয়েব.স্তানফোর্ড.ইডু / ~টিবস / এলমেস্ট্যাটলিয়ার / প্রিন্টিংস_ , অধ্যায় ((পৃষ্ঠা 219)।
ক্যামিল গৌডেসুন

উত্তর:


161

অদ্ভুত সমাধান। আমরা প্রথমে পুরো ডেটাসেটটি স্থানান্তরিত করব (df.sample (frac = 1)) এবং তারপরে আমাদের ডেটা সেটটিকে নীচের অংশগুলিতে বিভক্ত করব:

  • 60% - ট্রেন সেট,
  • 20% - বৈধতা সেট,
  • 20% - পরীক্ষা সেট

In [305]: train, validate, test = np.split(df.sample(frac=1), [int(.6*len(df)), int(.8*len(df))])

In [306]: train
Out[306]:
          A         B         C         D         E
0  0.046919  0.792216  0.206294  0.440346  0.038960
2  0.301010  0.625697  0.604724  0.936968  0.870064
1  0.642237  0.690403  0.813658  0.525379  0.396053
9  0.488484  0.389640  0.599637  0.122919  0.106505
8  0.842717  0.793315  0.554084  0.100361  0.367465
7  0.185214  0.603661  0.217677  0.281780  0.938540

In [307]: validate
Out[307]:
          A         B         C         D         E
5  0.806176  0.008896  0.362878  0.058903  0.026328
6  0.145777  0.485765  0.589272  0.806329  0.703479

In [308]: test
Out[308]:
          A         B         C         D         E
4  0.521640  0.332210  0.370177  0.859169  0.401087
3  0.333348  0.964011  0.083498  0.670386  0.169619

[int(.6*len(df)), int(.8*len(df))]- numpy.split () এরindices_or_sections জন্য একটি অ্যারে ।

np.split()ব্যবহারের জন্য এখানে একটি ছোট ডেমো রয়েছে - আসুন নীচের অংশগুলিতে 20-উপাদান অ্যারে বিভক্ত করুন: 80%, 10%, 10%:

In [45]: a = np.arange(1, 21)

In [46]: a
Out[46]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])

In [47]: np.split(a, [int(.8 * len(a)), int(.9 * len(a))])
Out[47]:
[array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16]),
 array([17, 18]),
 array([19, 20])]

@ রুট ঠিক কী frac = 1 পরামিতি করছে?
স্পাইডারওয়াস এমপি 2 2

1
@ স্পাইডারওয়াস এমপি 4, ফাংশনকে সমস্ত ( বা ভগ্নাংশ = ) সারিগুলি ফিরিয়ে আনতে frac=1নির্দেশ sample()দেয়100%1.0
ম্যাকসু

12
ধন্যবাদ @ ম্যাক্সইউ। জিনিসগুলি সরল রাখার জন্য আমি 2 টি বিষয়ের উল্লেখ করতে চাই। প্রথমে, np.random.seed(any_number)প্রতিটি রানের সাথে একই ফলাফল পেতে বিভক্ত লাইনের আগে ব্যবহার করুন । দ্বিতীয়ত, train:test:val::50:40:10ব্যবহারের মতো অসম অনুপাত তৈরি করা [int(.5*len(dfn)), int(.9*len(dfn))]। এখানে প্রথম উপাদানটি train(0.5%) এর আকারকে বোঝায়, দ্বিতীয় উপাদানটি val(1-0.9 = 0.1%) এর জন্য আকারকে চিহ্নিত করে এবং test(0.9-0.5 = 0.4%) জন্য দুটি নোটোটোর আকারের মধ্যে পার্থক্য । আমি ভুল হলে আমাকে সংশোধন করুন :)
ডেটাও

এইচআরএম আপনি যখন বলেন "এটি এনপি.স্প্লিট () ব্যবহারের জন্য একটি ছোট ডেমো রয়েছে - তখন আসুন নীচের অংশগুলিতে 20-উপাদান অ্যারে বিভক্ত করুন: 90%, 10%, 10%:" আমি নিশ্চিত আপনি 80 এর মানে %, 10%, 10%
কেভিন

আরে, @ ম্যাক্সইউতে আমার একটি কেস হয়েছিল, কিছুটা অনুরূপ। আমি ভাবছিলাম যে আপনি এটি আমার দিকে তাকান কিনা তা দেখার জন্য এবং সেখানে আমাকে সহায়তা করতে পারেন। আমার প্রশ্নটি এখানে স্ট্যাকওভারফ্লো.com
দীপক এম

55

বিঃদ্রঃ:

এলোমেলোভাবে সেট তৈরির সিডিং পরিচালনা করার জন্য ফাংশনটি লেখা হয়েছিল। আপনি সেট বিভাজনের উপর নির্ভর করবেন না যা সেটগুলি এলোমেলো করে না।

import numpy as np
import pandas as pd

def train_validate_test_split(df, train_percent=.6, validate_percent=.2, seed=None):
    np.random.seed(seed)
    perm = np.random.permutation(df.index)
    m = len(df.index)
    train_end = int(train_percent * m)
    validate_end = int(validate_percent * m) + train_end
    train = df.iloc[perm[:train_end]]
    validate = df.iloc[perm[train_end:validate_end]]
    test = df.iloc[perm[validate_end:]]
    return train, validate, test

প্রদর্শন

np.random.seed([3,1415])
df = pd.DataFrame(np.random.rand(10, 5), columns=list('ABCDE'))
df

এখানে চিত্র বর্ণনা লিখুন

train, validate, test = train_validate_test_split(df)

train

এখানে চিত্র বর্ণনা লিখুন

validate

এখানে চিত্র বর্ণনা লিখুন

test

এখানে চিত্র বর্ণনা লিখুন


1
আমি বিশ্বাস করি যে এই ফাংশনের জন্য 1 থেকে n এর সূচক মানগুলির সাথে একটি ডিএফ প্রয়োজন। আমার ক্ষেত্রে, আমি df.loc ব্যবহারের জন্য ফাংশনটি সংশোধন করেছি কারণ আমার সূচক মানগুলি এই সীমার মধ্যে অগত্যা ছিল না।
iOSBeginner

32

যাইহোক, মধ্যে ডেটা সেটটি বিভাজক এক পদ্ধতির train, test, cvসঙ্গে 0.6, 0.2, 0.2ব্যবহার করতে হবে train_test_splitপদ্ধতি দুইবার।

from sklearn.model_selection import train_test_split

x, x_test, y, y_test = train_test_split(xtrain,labels,test_size=0.2,train_size=0.8)
x_train, x_cv, y_train, y_cv = train_test_split(x,y,test_size = 0.25,train_size =0.75)

বৃহত্তর ডেটাসেটের জন্য সাবপটিমাল
ম্যাকসিম গ্যানেনকো

@ ম্যাক্সেমগ্যানেনকো আপনি কি দয়া করে বিস্তারিত বলতে পারবেন?
blitu12345

আপনি দুটি পৃথক অপারেশন দিয়ে ডেটা বিভক্ত করার পরামর্শ দিন। প্রতিটি ডেটা বিভক্তিতে ডেটা অনুলিপি জড়িত। সুতরাং আপনি যখন কোনওটির পরিবর্তে দুটি পৃথক স্প্লিট অপারেশন ব্যবহার করার পরামর্শ দিচ্ছেন আপনি কৃত্রিমভাবে র‌্যাম এবং সিপিইউ উভয়কেই বোঝা তৈরি করেন। সুতরাং আপনার সমাধান suboptimal হয়। যেমন একক অপারেশন দিয়ে ডেটা স্প্লিট করা উচিত np.split()। এছাড়াও, এটির জন্য অতিরিক্ত নির্ভরতার প্রয়োজন হয় না sklearn
ম্যাকসিম গ্যানেনকো

@ ম্যাক্সেমগ্যানেনকো মেমরির অতিরিক্ত চাপের বিষয়ে একমত হয়েছিলেন এবং তার জন্য আমরা মেমরি থেকে আসল তথ্যটি মুছে ফেলতে পারি অর্থাৎ (xtrain এবং Labels)! এবং নিম্পি ব্যবহারের জন্য আপনার পরামর্শ সম্পর্কে কেবলমাত্র পূর্ণসংখ্যার ডেটা টাইপের মধ্যে সীমাবদ্ধ অন্য ডেটা ধরণের কী?
blitu12345

1
এই পদ্ধতির আরেকটি সুবিধা হ'ল আপনি স্ট্রেটিফিকেশন প্যারামিটারগুলি ব্যবহার করতে পারেন।
অমি টাভরি

7

এখানে একটি পাইথন ফাংশন যা স্ট্র্যাটেড নমুনা সহ একটি পান্ডাস ডেটা ফ্রেমকে ট্রেন, যাচাইকরণ এবং টেস্ট ডেটাফ্রেমে বিভক্ত করে। এটি বিজ্ঞান-শিখার ফাংশনটিকে train_test_split()দু'বার কল করে এই বিভাজনটি সম্পাদন করে।

import pandas as pd
from sklearn.model_selection import train_test_split

def split_stratified_into_train_val_test(df_input, stratify_colname='y',
                                         frac_train=0.6, frac_val=0.15, frac_test=0.25,
                                         random_state=None):
    '''
    Splits a Pandas dataframe into three subsets (train, val, and test)
    following fractional ratios provided by the user, where each subset is
    stratified by the values in a specific column (that is, each subset has
    the same relative frequency of the values in the column). It performs this
    splitting by running train_test_split() twice.

    Parameters
    ----------
    df_input : Pandas dataframe
        Input dataframe to be split.
    stratify_colname : str
        The name of the column that will be used for stratification. Usually
        this column would be for the label.
    frac_train : float
    frac_val   : float
    frac_test  : float
        The ratios with which the dataframe will be split into train, val, and
        test data. The values should be expressed as float fractions and should
        sum to 1.0.
    random_state : int, None, or RandomStateInstance
        Value to be passed to train_test_split().

    Returns
    -------
    df_train, df_val, df_test :
        Dataframes containing the three splits.
    '''

    if frac_train + frac_val + frac_test != 1.0:
        raise ValueError('fractions %f, %f, %f do not add up to 1.0' % \
                         (frac_train, frac_val, frac_test))

    if stratify_colname not in df_input.columns:
        raise ValueError('%s is not a column in the dataframe' % (stratify_colname))

    X = df_input # Contains all columns.
    y = df_input[[stratify_colname]] # Dataframe of just the column on which to stratify.

    # Split original dataframe into train and temp dataframes.
    df_train, df_temp, y_train, y_temp = train_test_split(X,
                                                          y,
                                                          stratify=y,
                                                          test_size=(1.0 - frac_train),
                                                          random_state=random_state)

    # Split the temp dataframe into val and test dataframes.
    relative_frac_test = frac_test / (frac_val + frac_test)
    df_val, df_test, y_val, y_test = train_test_split(df_temp,
                                                      y_temp,
                                                      stratify=y_temp,
                                                      test_size=relative_frac_test,
                                                      random_state=random_state)

    assert len(df_input) == len(df_train) + len(df_val) + len(df_test)

    return df_train, df_val, df_test

নীচে একটি সম্পূর্ণ কাজের উদাহরণ।

এমন একটি ডেটাসেট বিবেচনা করুন যার একটি লেবেল রয়েছে যার উপরে আপনি স্তরকে সম্পাদন করতে চান। মূল লেবেসেটে এই লেবেলের নিজস্ব বিতরণ রয়েছে, বলুন 75% foo, 15% barএবং 10% baz। এখন আসুন ডেটাসেটকে ট্রেন, বৈধকরণ এবং 60/20/20 অনুপাত ব্যবহার করে সাবটেটগুলিতে পরীক্ষায় বিভক্ত করুন, যেখানে প্রতিটি বিভাজন লেবেলের একই বন্টন ধরে রাখে। নীচের চিত্র দেখুন:

এখানে চিত্র বর্ণনা লিখুন

এখানে ডেটাসেটের উদাহরণ দেওয়া হল:

df = pd.DataFrame( { 'A': list(range(0, 100)),
                     'B': list(range(100, 0, -1)),
                     'label': ['foo'] * 75 + ['bar'] * 15 + ['baz'] * 10 } )

df.head()
#    A    B label
# 0  0  100   foo
# 1  1   99   foo
# 2  2   98   foo
# 3  3   97   foo
# 4  4   96   foo

df.shape
# (100, 3)

df.label.value_counts()
# foo    75
# bar    15
# baz    10
# Name: label, dtype: int64

এখন, split_stratified_into_train_val_test()ট্রেন, বৈধতা এবং 60/20/20 অনুপাত অনুসরণ করে ডেটা ফ্রেমগুলি পরীক্ষা করতে উপরে থেকে ফাংশনটি কল করি ।

df_train, df_val, df_test = \
    split_stratified_into_train_val_test(df, stratify_colname='label', frac_train=0.60, frac_val=0.20, frac_test=0.20)

তিন dataframes df_train, df_valএবং df_testসব মূল সারি ধারণ কিন্তু তাদের মাপ উপরে অনুপাত অনুসরণ করা হবে।

df_train.shape
#(60, 3)

df_val.shape
#(20, 3)

df_test.shape
#(20, 3)

তদ্ব্যতীত, তিনটি স্প্লিটের প্রত্যেকটিরই লেবেলের একই বন্টন থাকবে, যথা 75% foo, 15% barএবং 10% baz

df_train.label.value_counts()
# foo    45
# bar     9
# baz     6
# Name: label, dtype: int64

df_val.label.value_counts()
# foo    15
# bar     3
# baz     2
# Name: label, dtype: int64

df_test.label.value_counts()
# foo    15
# bar     3
# baz     2
# Name: label, dtype: int64

NameError: নাম 'df' সংজ্ঞায়িত করা হয় না। 'ডিএফ' স্প্লিট_স্ট্রেটেড_ইন্টো_ট্রেইন_ওয়াল_টেষ্ট () এ 'ডিএফ_ইনপুট' দিয়ে প্রতিস্থাপন করা উচিত।
ফ্যান্টাসি পোলক

ধন্যবাদ। আমি এটা ঠিক করেছি. সমস্যাটি কোডের একটি ত্রুটি-পরিচালনার পথে ছিল।
stackoverflowuser2010

1

train_test_splitবেশ কয়েকটি সেটে বিভাজন এবং কিছু অতিরিক্ত কোড না লিখে পুনর্নির্মাণের সম্পাদনা না করে ব্যবহার করা খুব সুবিধাজনক । উপরের সেরা উত্তরে উল্লেখ করা যায় না যে train_test_splitপার্টিশনের আকার পরিবর্তন না করে দুটি বার পৃথক করে প্রাথমিকভাবে পার্টিশন দেবে না:

x_train, x_remain = train_test_split(x, test_size=(val_size + test_size))

তারপরে বৈধতা এবং পরীক্ষার অংশটি x_remain পরিবর্তনতে সেট করে এবং এটি গণনা করা যেতে পারে

new_test_size = np.around(test_size / (val_size + test_size), 2)
# To preserve (new_test_size + new_val_size) = 1.0 
new_val_size = 1.0 - new_test_size

x_val, x_test = train_test_split(x_remain, test_size=new_test_size)

এই উপলক্ষে সমস্ত প্রাথমিক পার্টিশন সংরক্ষণ করা হয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.