Làm cách nào để tạo mẫu thử nghiệm và huấn luyện từ một khung dữ liệu với gấu trúc?


323

Tôi có một bộ dữ liệu khá lớn dưới dạng một khung dữ liệu và tôi đã tự hỏi làm thế nào tôi có thể chia khung dữ liệu thành hai mẫu ngẫu nhiên (80% và 20%) để đào tạo và thử nghiệm.

Cảm ơn!

Câu trả lời:


346

Tôi sẽ chỉ sử dụng numpy randn:

In [11]: df = pd.DataFrame(np.random.randn(100, 2))

In [12]: msk = np.random.rand(len(df)) < 0.8

In [13]: train = df[msk]

In [14]: test = df[~msk]

Và chỉ để thấy điều này đã làm việc:

In [15]: len(test)
Out[15]: 21

In [16]: len(train)
Out[16]: 79

3
Xin lỗi, là lỗi của tôi. Chừng nào msklà của dtype bool, df[msk], df.iloc[msk]df.loc[msk]luôn luôn trả lại kết quả tương tự.
unutbu

2
Tôi nghĩ bạn nên sử dụng randđể < 0.8có ý nghĩa bởi vì nó trả về các số ngẫu nhiên được phân phối đồng đều trong khoảng từ 0 đến 1.
R. Max

4
Ai đó có thể giải thích thuần túy về python chính xác những gì xảy ra trong dòng in[12], in[13], in[14]? Tôi muốn hiểu chính mã trăn ở đây
kuatroka

7
Câu trả lời sử dụng sklearn từ gobrewers14 là câu trả lời tốt hơn. Nó ít phức tạp hơn và dễ gỡ lỗi hơn. Tôi khuyên bạn nên sử dụng câu trả lời dưới đây.
Vậy

2
@kuatroka np.random.rand(len(df))là một mảng có kích thước len(df)với các giá trị float được phân phối ngẫu nhiên và đồng đều trong phạm vi [0, 1]. Việc < 0.8áp dụng các yếu tố so sánh khôn ngoan và lưu trữ kết quả tại chỗ. Do đó, các giá trị <0,8 trở thành Truevà giá trị> = 0,8 trở thànhFalse
Kentzo

623

scikit learn'strain_test_split là một trong những tốt.

from sklearn.model_selection import train_test_split

train, test = train_test_split(df, test_size=0.2)

22
Tuy nhiên, điều này sẽ trả về các mảng numpy và không phải là Pandas Dataframes
Bar

124
Btw, hiện tại nó trả về một Dataframe Pandas (vừa được thử nghiệm trên Sklearn 0.16.1)
Julien Marrec

5
Nếu bạn đang tìm kiếm KFold, thì đáng buồn hơn một chút. kf = KFold(n, n_folds=folds) for train_index, test_index in kf: X_train, X_test = X.ix[train_index], X.ix[test_index]xem ví dụ đầy đủ tại đây: quantstart.com/articles/ đá
ihadanny

12
Trong các phiên bản mới (0.18, có thể sớm hơn), nhập from sklearn.model_selection import train_test_splitthay thế.
Đánh dấu

7
Trong phiên bản SciKit mới nhất, bạn cần gọi nó ngay bây giờ là:from sklearn.cross_validation import train_test_split
móng ngựa

289

Mẫu ngẫu nhiên gấu trúc cũng sẽ làm việc

train=df.sample(frac=0.8,random_state=200) #random state is a seed value
test=df.drop(train.index)

.Index có nghĩa là gì / tài liệu cho .index trên DataFrame ở đâu? Tôi không thể tìm thấy nó.
độc quyền

1
những gì là random_statearg đang làm gì?
Rishabh Agrahari

1
@RishabhAgrahari ngẫu nhiên xáo trộn dữ liệu khác nhau mỗi lần theo frac arg. Nếu bạn muốn kiểm soát tính ngẫu nhiên, bạn có thể nêu hạt giống của mình, như trong ví dụ.
MikeL

4
Điều này dường như hoạt động tốt và một giải pháp thanh lịch hơn là mang vào sklearn. Có một lý do tại sao điều này không nên là một câu trả lời được chấp nhận tốt hơn?
RajV

1
@peer giới hạn đó dễ dàng được khắc phục nếu muốn có một testbộ xáo trộn như được chỉ ra ở đây stackoverflow.com/questions/29576430/shuffle-dataframe-rows . test=df.drop(train.index).sample(frac=1.0)
Alok Lal

32

Tôi sẽ sử dụng training_test_split của scikit-learn và tạo nó từ chỉ mục

from sklearn.model_selection import train_test_split


y = df.pop('output')
X = df

X_train,X_test,y_train,y_test = train_test_split(X.index,y,test_size=0.2)
X.iloc[X_train] # return dataframe train

3
Các cross_validationmô-đun hiện đang bị phản đối:DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
Harry

20

Có nhiều cách để tạo một mẫu thử nghiệm / thử nghiệm và thậm chí xác nhận.

Trường hợp 1: cách cổ điển train_test_splitmà không có bất kỳ tùy chọn:

from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.3)

Trường hợp 2: trường hợp bộ dữ liệu rất nhỏ (<500 hàng): để có kết quả cho tất cả các dòng của bạn với xác thực chéo này. Cuối cùng, bạn sẽ có một dự đoán cho mỗi dòng trong tập huấn luyện có sẵn của bạn.

from sklearn.model_selection import KFold
kf = KFold(n_splits=10, random_state=0)
y_hat_all = []
for train_index, test_index in kf.split(X, y):
    reg = RandomForestRegressor(n_estimators=50, random_state=0)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    clf = reg.fit(X_train, y_train)
    y_hat = clf.predict(X_test)
    y_hat_all.append(y_hat)

Trường hợp 3a: Bộ dữ liệu không cân bằng cho mục đích phân loại. Sau trường hợp 1, đây là giải pháp tương đương:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size=0.3)

Trường hợp 3b: Bộ dữ liệu không cân bằng cho mục đích phân loại. Sau trường hợp 2, đây là giải pháp tương đương:

from sklearn.model_selection import StratifiedKFold
kf = StratifiedKFold(n_splits=10, random_state=0)
y_hat_all = []
for train_index, test_index in kf.split(X, y):
    reg = RandomForestRegressor(n_estimators=50, random_state=0)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    clf = reg.fit(X_train, y_train)
    y_hat = clf.predict(X_test)
    y_hat_all.append(y_hat)

Trường hợp 4: bạn cần tạo một bộ kiểm tra / kiểm tra / xác thực trên dữ liệu lớn để điều chỉnh siêu âm (60% đào tạo, 20% kiểm tra và 20% val).

from sklearn.model_selection import train_test_split
X_train, X_test_val, y_train, y_test_val = train_test_split(X, y, test_size=0.6)
X_test, X_val, y_test, y_val = train_test_split(X_test_val, y_test_val, stratify=y, test_size=0.5)

13

Bạn có thể sử dụng mã dưới đây để tạo mẫu thử nghiệm và đào tạo:

from sklearn.model_selection import train_test_split
trainingSet, testSet = train_test_split(df, test_size=0.2)

Kích thước thử nghiệm có thể thay đổi tùy thuộc vào tỷ lệ phần trăm dữ liệu bạn muốn đưa vào dữ liệu thử nghiệm và đào tạo của bạn.


7

Có nhiều câu trả lời hợp lệ. Thêm một người nữa vào bó. từ sklearn.cross_validation nhập train_test_split

#gets a random 80% of the entire set
X_train = X.sample(frac=0.8, random_state=1)
#gets the left out portion of the dataset
X_test = X.loc[~df_model.index.isin(X_train.index)]

5

Bạn cũng có thể xem xét phân chia phân tầng thành tập huấn luyện và kiểm tra. Bộ phận bắt đầu cũng tạo ra tập huấn và kiểm tra ngẫu nhiên nhưng theo cách mà tỷ lệ lớp gốc được bảo toàn. Điều này làm cho tập huấn luyện và kiểm tra phản ánh tốt hơn các thuộc tính của tập dữ liệu gốc.

import numpy as np  

def get_train_test_inds(y,train_proportion=0.7):
    '''Generates indices, making random stratified split into training set and testing sets
    with proportions train_proportion and (1-train_proportion) of initial sample.
    y is any iterable indicating classes of each observation in the sample.
    Initial proportions of classes inside training and 
    testing sets are preserved (stratified sampling).
    '''

    y=np.array(y)
    train_inds = np.zeros(len(y),dtype=bool)
    test_inds = np.zeros(len(y),dtype=bool)
    values = np.unique(y)
    for value in values:
        value_inds = np.nonzero(y==value)[0]
        np.random.shuffle(value_inds)
        n = int(train_proportion*len(value_inds))

        train_inds[value_inds[:n]]=True
        test_inds[value_inds[n:]]=True

    return train_inds,test_inds

df [train_inds] và df [test_inds] cung cấp cho bạn các bộ huấn luyện và thử nghiệm của df DataFrame gốc của bạn.


Đây là chiến lược thích hợp hơn cho các nhiệm vụ học tập có giám sát.
vincentmajor

Khi cố gắng sử dụng điều này tôi nhận được một lỗi. ValueError: đích chỉ định là chỉ đọc trong dòng "np.random.shuffle (value_inds)"
Markus W

4

Nếu bạn cần phân chia dữ liệu của mình đối với cột lables trong bộ dữ liệu của bạn, bạn có thể sử dụng điều này:

def split_to_train_test(df, label_column, train_frac=0.8):
    train_df, test_df = pd.DataFrame(), pd.DataFrame()
    labels = df[label_column].unique()
    for lbl in labels:
        lbl_df = df[df[label_column] == lbl]
        lbl_train_df = lbl_df.sample(frac=train_frac)
        lbl_test_df = lbl_df.drop(lbl_train_df.index)
        print '\n%s:\n---------\ntotal:%d\ntrain_df:%d\ntest_df:%d' % (lbl, len(lbl_df), len(lbl_train_df), len(lbl_test_df))
        train_df = train_df.append(lbl_train_df)
        test_df = test_df.append(lbl_test_df)

    return train_df, test_df

và sử dụng nó:

train, test = split_to_train_test(data, 'class', 0.7)

bạn cũng có thể vượt qua Random_state nếu bạn muốn kiểm soát tính ngẫu nhiên phân chia hoặc sử dụng một số hạt giống ngẫu nhiên toàn cầu.


3
import pandas as pd

from sklearn.model_selection import train_test_split

datafile_name = 'path_to_data_file'

data = pd.read_csv(datafile_name)

target_attribute = data['column_name']

X_train, X_test, y_train, y_test = train_test_split(data, target_attribute, test_size=0.8)

2
Bạn có một sai lầm ngắn. Bạn nên bỏ cột mục tiêu trước, bạn đặt nó vào train_test_split. data = data.drop (Cột = ['cột_name'], trục = 1)
Anton Erjomin

3

Bạn có thể sử dụng ~ (toán tử dấu ngã) để loại trừ các hàng được lấy mẫu bằng cách sử dụng df.sample (), để gấu trúc một mình xử lý lấy mẫu và lọc chỉ mục, để có được hai bộ.

train_df = df.sample(frac=0.8, random_state=100)
test_df = df[~df.index.isin(train_df.index)]

2

Đây là những gì tôi đã viết khi tôi cần tách DataFrame. Tôi đã cân nhắc sử dụng phương pháp của Andy ở trên, nhưng không phải là tôi không thể kiểm soát chính xác kích thước của các tập dữ liệu (nghĩa là đôi khi là 79, đôi khi là 81, v.v.).

def make_sets(data_df, test_portion):
    import random as rnd

    tot_ix = range(len(data_df))
    test_ix = sort(rnd.sample(tot_ix, int(test_portion * len(data_df))))
    train_ix = list(set(tot_ix) ^ set(test_ix))

    test_df = data_df.ix[test_ix]
    train_df = data_df.ix[train_ix]

    return train_df, test_df


train_df, test_df = make_sets(data_df, 0.2)
test_df.head()

2

Chỉ cần chọn phạm vi hàng từ df như thế này

row_count = df.shape[0]
split_point = int(row_count*1/5)
test_data, train_data = df[:split_point], df[split_point:]

3
Điều này sẽ chỉ hoạt động nếu dữ liệu trong khung dữ liệu đã được sắp xếp ngẫu nhiên. Nếu tập dữ liệu được lấy từ các nguồn siêu nhỏ và đã được thêm vào cùng một khung dữ liệu thì bạn hoàn toàn có thể lấy một tập dữ liệu rất sai lệch để đào tạo / kiểm tra bằng cách sử dụng ở trên.
Emil H

1
Bạn có thể xáo trộn khung dữ liệu trước khi tách nó stackoverflow.com/questions/29576430/shuffle-dataframe-rows
Makio

1
Tuyệt đối! Nếu bạn thêm rằng dftrong đoạn mã của bạn được (hoặc nên) được xáo trộn, nó sẽ cải thiện câu trả lời.
Emil H

2

Có nhiều câu trả lời tuyệt vời ở trên, vì vậy tôi chỉ muốn thêm một ví dụ nữa trong trường hợp bạn muốn chỉ định số lượng mẫu chính xác cho các bộ thử nghiệm và xe lửa bằng cách chỉ sử dụng numpythư viện.

# set the random seed for the reproducibility
np.random.seed(17)

# e.g. number of samples for the training set is 1000
n_train = 1000

# shuffle the indexes
shuffled_indexes = np.arange(len(data_df))
np.random.shuffle(shuffled_indexes)

# use 'n_train' samples for training and the rest for testing
train_ids = shuffled_indexes[:n_train]
test_ids = shuffled_indexes[n_train:]

train_data = data_df.iloc[train_ids]
train_labels = labels_df.iloc[train_ids]

test_data = data_df.iloc[test_ids]
test_labels = data_df.iloc[test_ids]

2

Để chia thành nhiều hơn hai lớp như đào tạo, kiểm tra và xác nhận, người ta có thể làm:

probs = np.random.rand(len(df))
training_mask = probs < 0.7
test_mask = (probs>=0.7) & (probs < 0.85)
validatoin_mask = probs >= 0.85


df_training = df[training_mask]
df_test = df[test_mask]
df_validation = df[validatoin_mask]

Điều này sẽ đưa khoảng 70% dữ liệu vào đào tạo, 15% trong kiểm tra và 15% trong xác nhận.


1
Bạn có thể muốn chỉnh sửa câu trả lời của mình để thêm "xấp xỉ", nếu bạn chạy mã bạn sẽ thấy rằng nó có thể khá khác biệt so với tỷ lệ phần trăm chính xác. ví dụ: tôi đã thử nó trên 1000 mặt hàng và nhận được: 700, 141, 159 - vì vậy 70%, 14% và 16%.
stason

2

bạn cần chuyển đổi dataframe thành mảng numpy và sau đó chuyển mảng numpy trở lại dataframe

 import pandas as pd
df=pd.read_csv('/content/drive/My Drive/snippet.csv', sep='\t')
from sklearn.model_selection import train_test_split

train, test = train_test_split(df, test_size=0.2)
train1=pd.DataFrame(train)
test1=pd.DataFrame(test)
train1.to_csv('/content/drive/My Drive/train.csv',sep="\t",header=None, encoding='utf-8', index = False)
test1.to_csv('/content/drive/My Drive/test.csv',sep="\t",header=None, encoding='utf-8', index = False)

Câu trả lời chỉ có mã không được chấp nhận trên Stack Overflow.
VFDan

1

Nếu mong muốn của bạn là có một dataframe trong và hai dataframes (không phải là mảng numpy), thì điều này sẽ thực hiện thủ thuật:

def split_data(df, train_perc = 0.8):

   df['train'] = np.random.rand(len(df)) < train_perc

   train = df[df.train == 1]

   test = df[df.train == 0]

   split_data ={'train': train, 'test': test}

   return split_data

1

Bạn có thể sử dụng hàm df.as_matrix () và tạo mảng Numpy và truyền nó.

Y = df.pop()
X = df.as_matrix()
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size = 0.2)
model.fit(x_train, y_train)
model.test(x_test)

1

Thanh lịch hơn một chút theo sở thích của tôi là tạo một cột ngẫu nhiên và sau đó phân chia theo nó, bằng cách này chúng ta có thể có được một phân chia phù hợp với nhu cầu của chúng ta và sẽ là ngẫu nhiên.

def split_df(df, p=[0.8, 0.2]):
import numpy as np
df["rand"]=np.random.choice(len(p), len(df), p=p)
r = [df[df["rand"]==val] for val in df["rand"].unique()]
return r

1

Không cần phải chuyển đổi để numpy. Chỉ cần sử dụng một con gấu trúc df để thực hiện việc phân chia và nó sẽ trả lại một con gấu trúc df.

from sklearn.model_selection import train_test_split

train, test = train_test_split(df, test_size=0.2)

0

Tôi nghĩ bạn cũng cần lấy một bản sao chứ không phải một lát dữ liệu nếu bạn muốn thêm các cột sau này.

msk = np.random.rand(len(df)) < 0.8
train, test = df[msk].copy(deep = True), df[~msk].copy(deep = True)

0

Còn cái này thì sao? df là khung dữ liệu của tôi

total_size=len(df)

train_size=math.floor(0.66*total_size) (2/3 part of my dataset)

#training dataset
train=df.head(train_size)
#test dataset
test=df.tail(len(df) -train_size)

0
shuffle = np.random.permutation(len(df))
test_size = int(len(df) * 0.2)
test_aux = shuffle[:test_size]
train_aux = shuffle[test_size:]
TRAIN_DF =df.iloc[train_aux]
TEST_DF = df.iloc[test_aux]

2
Đây sẽ là một câu trả lời tốt hơn nếu bạn giải thích cách mã bạn cung cấp trả lời câu hỏi.
pppery

Mặc dù mã này có thể trả lời câu hỏi, việc cung cấp ngữ cảnh bổ sung về cách thức và / hoặc lý do giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời.
shaunakde

dòng thứ nhất trả về một phạm vi được xáo trộn (liên quan đến kích thước của khung dữ liệu). Dòng thứ hai biểu thị phần mong muốn của tập kiểm tra. Dòng thứ ba và thứ ba kết hợp phân số vào phạm vi được xáo trộn. Các dòng còn lại sẽ tự giải thích .Trân trọng.
Elyte D General
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.