Pandas或Scikit-learn中是否有内置函数用于根据指定策略重新采样?我想根据分类变量对数据进行重新采样。
例如,如果我的数据中有75%的男性和25%的女性,但我想在50%的男性和50%的女性身上训练我的模型。(我也希望能够推广到不是50/50的情况)
我需要的是根据指定的比例对数据进行重新采样。
下面是我对函数的尝试。希望这对其他人有帮助。
假设CCD_ 1和CCD_。
def resample(X, y, sample_type=None, sample_size=None, class_weights=None, seed=None):
# Nothing to do if sample_type is 'abs' or not set. sample_size should then be int
# If sample type is 'min' or 'max' then sample_size should be float
if sample_type == 'min':
sample_size_ = np.round(sample_size * y.value_counts().min()).astype(int)
elif sample_type == 'max':
sample_size_ = np.round(sample_size * y.value_counts().max()).astype(int)
else:
sample_size_ = max(int(sample_size), 1)
if seed is not None:
np.random.seed(seed)
if class_weights is None:
class_weights = dict()
X_resampled = pd.DataFrame()
for yi in y.unique():
size = np.round(sample_size_ * class_weights.get(yi, 1.)).astype(int)
X_yi = X[y == yi]
sample_index = np.random.choice(X_yi.index, size=size)
X_resampled = X_resampled.append(X_yi.reindex(sample_index))
return X_resampled
如果您对导入库持开放态度,我发现不平衡学习库在处理重新采样时很有用。这里的分类变量是目标"y",要重新采样的数据是"X"。在下面的示例中,对鱼进行重新采样,使其等于狗的数量3:3。
该代码是从关于不平衡学习的文档中稍微修改的:2.1.1。天真的随机过度抽样。您可以将此方法用于数字数据和字符串。
import numpy as np
from collections import Counter
from imblearn.over_sampling import RandomOverSampler
y = np.array([1,1,0,0,0]); # Fish / Dog
print('target:n', y)
X = np.array([['red fish'],['blue fish'],['dog'],['dog'],['dog']]);
print('data:n',X);
print('Original dataset shape {}'.format(Counter(y))) # Original dataset shape Counter({1: 900, 0: 100})
print(type(X)); print(X);
print(y);
ros = RandomOverSampler(ratio='auto', random_state=42);
X_res, y_res = ros.fit_sample(X, y);
print('Resampled dataset shape {}'.format(Counter(y_res))) # Resampled dataset shape Counter({0: 900, 1: 900});
print(type(X_res)); print(X_res); print(y_res);
分层采样意味着保留了类分布。如果你正在寻找这个,你仍然可以使用StratifiedKFold
和StratifiedShuffleSplit
,只要你有一个分类变量,你想确保它在每个折叠中都有相同的分布。只需使用变量而不是目标变量。例如,如果在i
列中有一个分类变量,
skf = cross_validation.StratifiedKFold(X[:,i])
但是,如果我理解正确,您希望对其中一个分类特征的特定目标分布(例如50/50)进行重新采样。我想你必须想出自己的方法来获得这样的样本(按变量值分割数据集,然后从每次分割中抽取相同数量的随机样本)。如果你的主要动机是平衡分类器的训练集,那么一个技巧可能是调整sample_weights
。您可以设置权重,使其根据所需变量平衡训练集:
sample_weights = sklearn.preprocessing.balance_weights(X[:,i])
clf = svm.SVC()
clf_weights.fit(X, y, sample_weight=sample_weights)
对于非均匀的目标分布,必须相应地调整sample_weights。