데이터를 3세트(교육, 검증 및 테스트)로 분할하는 방법은 무엇입니까?
저는 판다 데이터 프레임을 가지고 있는데 3개의 세트로 나누고 싶습니다.train_test_split을 사용하는 것을 알고 있습니다.sklearn.cross_validation
데이터를 두 집합(훈련 및 테스트)으로 나눌 수 있습니다.하지만, 저는 데이터를 세 세트로 나누는 것에 대한 해결책을 찾을 수 없었습니다.가급적이면 원본 데이터의 인덱스를 갖고 싶습니다.
방법은 사할수있해방법은결는을 입니다.train_test_split
두 번 그리고 어떻게든 지수를 조정합니다.하지만 데이터를 2개가 아닌 3개의 세트로 분할할 수 있는 더 표준적인 내장 방식이 있습니까?
바보 같은 해결책.는 먼저 데이터 세트를 입니다.df.sample(frac=1, random_state=42)
에서 데이터 세트를 나눕니다.
- 60% - 열차 세트,
- 20% - 유효성 검사 세트,
- 20% - 테스트 세트
In [305]: train, validate, test = \
np.split(df.sample(frac=1, random_state=42),
[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))]
입니다.indices_or_sections
numpy.dll에 대한 배열
다음은 에 대한 소규모 데모입니다.np.split()
- 10%로 나누어 - 배열은 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])]
그러나 데이터 세트를 다음과 같이 나누는 하나의 접근 방식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)
참고:
무작위 세트 생성의 시드를 처리하기 위해 함수가 작성되었습니다.집합을 랜덤화하지 않는 집합 분할에 의존해서는 안 됩니다.
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
Pandas 데이터 프레임을 계층화된 샘플링을 사용하여 Train, Validation 및 Test 데이터 프레임으로 분할하는 Python 함수가 있습니다.은 scikit-learn의 scikit-learn을 호출함으로써 수행됩니다.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)
프레임 3은 다음과 .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
지도 학습의 경우 X와 y를 모두 분할할 수 있습니다(여기서 X는 입력이고 y는 접지 실측 출력임).분할하기 전에 X와 Y를 같은 방식으로 섞는 것에 주의를 기울이면 됩니다.
여기서는 X와 y가 동일한 데이터 프레임에 있으므로 이들을 셔플하고 분리하여 각각에 대해 분할을 적용하거나(선택한 답변과 마찬가지로) X와 y가 서로 다른 두 데이터 프레임에 있으므로 X를 셔플하고 X와 동일한 방식으로 재정렬한 후 분할을 각각 적용합니다.
# 1st case: df contains X and y (where y is the "target" column of df)
df_shuffled = df.sample(frac=1)
X_shuffled = df_shuffled.drop("target", axis = 1)
y_shuffled = df_shuffled["target"]
# 2nd case: X and y are two separated dataframes
X_shuffled = X.sample(frac=1)
y_shuffled = y[X_shuffled.index]
# We do the split as in the chosen answer
X_train, X_validation, X_test = np.split(X_shuffled, [int(0.6*len(X)),int(0.8*len(X))])
y_train, y_validation, y_test = np.split(y_shuffled, [int(0.6*len(X)),int(0.8*len(X))])
그것은 사용하기에 매우 편리합니다.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)
이 경우 모든 초기 파티션이 저장됩니다.
def train_val_test_split(X, y, train_size, val_size, test_size):
X_train_val, X_test, y_train_val, y_test = train_test_split(X, y, test_size = test_size)
relative_train_size = train_size / (val_size + train_size)
X_train, X_val, y_train, y_val = train_test_split(X_train_val, y_train_val,
train_size = relative_train_size, test_size = 1-relative_train_size)
return X_train, X_val, X_test, y_train, y_val, y_test
의 sklearn으로 합니다.train_test_split
을 고려해서 면하려을고▁thatering면.df
id 래원데프레임터:
1 - 먼저 차량과 테스트 간에 데이터를 분할합니다(10%).
my_test_size = 0.10
X_train_, X_test, y_train_, y_test = train_test_split(
df.index.values,
df.label.values,
test_size=my_test_size,
random_state=42,
stratify=df.label.values,
)
2 - 그런 다음 열차 세트를 열차와 유효성 검사(20%) 간에 분할합니다.
my_val_size = 0.20
X_train, X_val, y_train, y_val = train_test_split(
df.loc[X_train_].index.values,
df.loc[X_train_].label.values,
test_size=my_val_size,
random_state=42,
stratify=df.loc[X_train_].label.values,
)
3 - 그런 다음 위의 단계에서 생성된 인덱스에 따라 원본 데이터 프레임을 슬라이스합니다.
# data_type is not necessary.
df['data_type'] = ['not_set']*df.shape[0]
df.loc[X_train, 'data_type'] = 'train'
df.loc[X_val, 'data_type'] = 'val'
df.loc[X_test, 'data_type'] = 'test'
결과는 다음과 같습니다.
참고: 이 솔루션은 질문에 언급된 해결 방법을 사용합니다.
다음을 사용하여 다른 답변과 같이 교육 및 테스트 세트에서 데이터 세트를 분할합니다.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
그런 다음 모형에 적합한 경우 다음을 추가할 수 있습니다.validation_split
검사 할 필요가 없습니다.그러면 유효성 검사 세트를 미리 생성할 필요가 없습니다.예:
from tensorflow.keras import Model
model = Model(input_layer, out)
[...]
history = model.fit(x=X_train, y=y_train, [...], validation_split = 0.3)
유효성 검사 세트는 k배 교차 유효성 검사(권장)를 통해 또는 다음과 같이 전적으로 교육 세트에서 가져온 교육 세트의 교육 동안 대표적인 현장 테스트 세트로 사용됩니다.validation_split
그러면 검증 세트를 별도로 생성할 필요가 없고 데이터 세트를 요청하는 세 세트로 분할할 수 있습니다.
하위 세트의 양에 대한 답변:
def _separate_dataset(patches, label_patches, percentage, shuffle: bool = True):
"""
:param patches: data patches
:param label_patches: label patches
:param percentage: list of percentages for each value, example [0.9, 0.02, 0.08] to get 90% train, 2% val and 8% test.
:param shuffle: Shuffle dataset before split.
:return: tuple of two lists of size = len(percentage), one with data x and other with labels y.
"""
x_test = patches
y_test = label_patches
percentage = list(percentage) # need it to be mutable
assert sum(percentage) == 1., f"percentage must add to 1, but it adds to sum{percentage} = {sum(percentage)}"
x = []
y = []
for i, per in enumerate(percentage[:-1]):
x_train, x_test, y_train, y_test = train_test_split(x_test, y_test, test_size=1-per, shuffle=shuffle)
percentage[i+1:] = [value / (1-percentage[i]) for value in percentage[i+1:]]
x.append(x_train)
y.append(y_train)
x.append(x_test)
y.append(y_test)
return x, y
이 작업은 모든 크기의 백분율에 적용됩니다.당의경우, 은해합니다야당신신▁do를 해야 합니다.percentage = [train_percentage, val_percentage, test_percentage]
.
제가 생각할 수 있는 가장 쉬운 방법은 다음과 같이 분할 분수를 배열 인덱스에 매핑하는 것입니다.
train_set = data[:int((len(data)+1)*train_fraction)]
test_set = data[int((len(data)+1)*train_fraction):int((len(data)+1)*(train_fraction+test_fraction))]
val_set = data[int((len(data)+1)*(train_fraction+test_fraction)):]
data = random.shuffle(data)
저는 항상 이 방법을 사용하여 열차, 테스트, 검증 분할을 수행하고 있습니다.데이터를 항상 원하는 크기로 분할합니다.
def train_test_val_split(df, train_size, val_size, test_size, random_state=42):
"""
Splits a pandas dataframe into training, validation, and test sets.
Args:
- df: pandas dataframe to split.
- train_size: float between 0 and 1 indicating the proportion of the dataframe to include in the training set.
- val_size: float between 0 and 1 indicating the proportion of the dataframe to include in the validation set.
- test_size: float between 0 and 1 indicating the proportion of the dataframe to include in the test set.
- random_state: int or None, optional (default=42). The seed used by the random number generator.
Returns:
- train_df: pandas dataframe containing the training set.
- val_df: pandas dataframe containing the validation set.
- test_df: pandas dataframe containing the test set.
Raises:
- AssertionError: if the sum of train_size, val_size, and test_size is not equal to 1.
"""
assert train_size + val_size + test_size == 1, "Train, validation, and test sizes must add up to 1."
# Split the dataframe into training and test sets
train_df, test_df = train_test_split(df, test_size=test_size, random_state=random_state)
# Calculate the size of the validation set relative to the original dataframe
val_ratio = val_size / (1 - test_size)
# Split the training set into training and validation sets
train_df, val_df = train_test_split(train_df, test_size=val_ratio, random_state=random_state)
return train_df, val_df, test_df
편집: X와 y를 트레인, 테스트, 밸브 세트로 분할하는 것을 직접 포함할 수도 있습니다.
def train_test_val_split(X, y, train_size, val_size, test_size, random_state=42):
"""
Splits X and y into training, validation, and test sets.
Args:
- X: pandas dataframe or array containing the independent variables.
- y: pandas series or array containing the dependent variable.
- train_size: float between 0 and 1 indicating the proportion of the data to include in the training set.
- val_size: float between 0 and 1 indicating the proportion of the data to include in the validation set.
- test_size: float between 0 and 1 indicating the proportion of the data to include in the test set.
- random_state: int or None, optional (default=42). The seed used by the random number generator.
Returns:
- X_train: pandas dataframe or array containing the independent variables for the training set.
- X_val: pandas dataframe or array containing the independent variables for the validation set.
- X_test: pandas dataframe or array containing the independent variables for the test set.
- y_train: pandas series or array containing the dependent variable for the training set.
- y_val: pandas series or array containing the dependent variable for the validation set.
- y_test: pandas series or array containing the dependent variable for the test set.
Raises:
- AssertionError: if the sum of train_size, val_size, and test_size is not equal to 1.
"""
assert train_size + val_size + test_size == 1, "Train, validation, and test sizes must add up to 1."
# Concatenate X and y into a single dataframe
df = pd.concat([X, y], axis=1)
# Split the dataframe into training and test sets
train_df, test_df = train_test_split(df, test_size=test_size, random_state=random_state)
# Calculate the size of the validation set relative to the original dataframe
val_ratio = val_size / (1 - test_size)
# Split the training set into training and validation sets
train_df, val_df = train_test_split(train_df, test_size=val_ratio, random_state=random_state)
# Split the training, validation, and test dataframes into X and y values
X_train, y_train = train_df.drop(columns=y.name), train_df[y.name]
X_val, y_val = val_df.drop(columns=y.name), val_df[y.name]
X_test, y_test = test_df.drop(columns=y.name), test_df[y.name]
return X_train, X_val, X_test, y_train, y_val, y_test
▁that▁the를 사용하여 입력 을 으로 분할하는 sklearn
의train_test_split
기능.따라서 임의의 수의 입력 배열을 처리합니다(마치sklearn
version)에 임의의 수의 분할이 추가됩니다.3개의 입력 어레이와 4개의 분할에서 테스트했습니다.
from typing import Any, Iterable, List, Union
import numpy as np
from sklearn.model_selection import train_test_split as _train_test_split
def train_test_split(
*arrays: Any,
sizes: Union[float, Iterable[float]] = None,
random_state: Any = None,
shuffle: bool = True,
stratify: Any = None
) -> List:
"""Like ``sklearn.model_selection.train_test_split`` but handles multiple splits.
Returns:
A list of array splits. The first ``n`` elements are the splits of the first array and so
on. For example, ``X_train``, ``X_valid``, ``X_test``.
Examples:
>>> train_test_split(list(range(10)), sizes=(0.7, 0.2, 0.1))
[[0, 1, 9, 6, 5, 8, 2], [3, 7], [4]]
>>> train_test_split(features, labels, sizes=(0.7, 0.2, 0.1))
"""
if isinstance(sizes, float):
sizes = [sizes]
else:
sizes = np.array(sizes, dtype="float")
if len(sizes) > 1:
sizes /= sizes.sum()
train_size = sizes[0]
common_args = dict(random_state=random_state, shuffle=shuffle, stratify=stratify)
if len(sizes) <= 2:
return _train_test_split(*arrays, train_size=train_size, **common_args)
else:
n = len(arrays)
left_arrays = _train_test_split(*arrays, train_size=train_size, **common_args)
right_arrays = train_test_split(*left_arrays[1::2], sizes=sizes[1:], **common_args)
interleaved = []
s = len(sizes) - 1
for i in range(n):
interleaved.append(left_arrays[i * 2])
interleaved.extend(right_arrays[i * s : (i + 1) * s])
return interleaved
언급URL : https://stackoverflow.com/questions/38250710/how-to-split-data-into-3-sets-train-validation-and-test
'programing' 카테고리의 다른 글
'input' 요소의 'change' 이벤트와 'input' 이벤트 간의 차이 (0) | 2023.08.12 |
---|---|
Oracle/TOAD의 컴파일 오류에 대한 정보를 가져오는 방법 (0) | 2023.08.12 |
Spring Data REST가 DTO를 사용하지 않고 REST 리소스를 통해 엔티티를 노출하는 것이 문제가 있습니까? (0) | 2023.08.12 |
jQuery Delayed 배열을 사용하는 방법은 무엇입니까? (0) | 2023.08.12 |
Minikube용 VM에 SSH하려면 어떻게 해야 합니까? (0) | 2023.08.12 |