Dưới đây là một chức năng Python phân chia khung dữ liệu của Pandas thành Train, Xác thực và Kiểm tra DataFrames với lấy mẫu phân tầng. Nó thực hiện sự phân chia này bằng cách gọi chức năng của Scikit-Learn train_test_split() hai lần.
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_testDưới đây là một ví dụ làm việc hoàn chỉnh.
Hãy xem xét một bộ dữ liệu có nhãn mà bạn muốn thực hiện phân tầng. Nhãn này có phân phối riêng trong bộ dữ liệu gốc, giả sử 75% NO___Trans___Pre___6, 15% NO___Trans___Pre___7 và 10% NO___Trans___Pre___8. Bây giờ chúng ta hãy chia bộ dữ liệu thành đào tạo, xác thực và kiểm tra thành các tập hợp con bằng tỷ lệ 60/20/20, trong đó mỗi phân chia giữ lại cùng một phân phối của nhãn. Xem hình minh họa dưới đây:
Dưới đây là bộ dữ liệu ví dụ:
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: int64Bây giờ, chúng ta hãy gọi chức năng NO___TRANS___PRE___9 từ trên cao để có được các khung dữ liệu, xác thực và kiểm tra theo tỷ lệ 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)Ba DataFrames no___Trans___Pre___10, no___trans___pre___11 và no___trans___pre___12 chứa tất cả các hàng ban đầu nhưng kích thước của chúng sẽ tuân theo tỷ lệ trên.
df_train.shape #(60, 3) df_val.shape #(20, 3) df_test.shape #(20, 3)Hơn nữa, mỗi trong số ba lần phân chia sẽ có cùng phân phối của nhãn, cụ thể là 75% no___trans___pre___6, 15% no___trans___pre___7 và 10% no___trans___pre___8.
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