游乐游手机版
首页/AI热点日报/热点详情

机器学习采样方法有哪些?全面解析与分类

类型:热点整理2026-07-20
机器学习的常用采样方法包括简单随机抽样、分层采样和水塘采样。简单随机抽样确保每个样本被等概率选中;分层采样按比例从各子群抽取样本以减少偏差;水塘采样适用于未知长度的数据流,保证每个元素被等概率抽取。

简单随机抽样:最基础的采样方法

我们先从最基础的抽样策略入手。假设你拥有一个群体,希望从中选出一个子集,并且要求每个成员被选中的概率完全相同——这在数据科学领域极为常见。下面这段代码能够从数据集中随机抽取100个样本,实现起来非常简洁:

sample_df = df.sample(100)

分层采样:按比例分配样本,降低估计误差

再来看一个现实场景:估算一场选举中每位候选人的平均得票数。假设整个国家有三个城镇——A镇有100万工人,B镇有200万工人,C镇有300万退休人员。如果直接从全体人口中随机抽取60个样本,由于各镇人口结构差异显著,结果很可能产生较大偏差,导致估计误差过高。

更有效的做法是按比例分配样本:从A、B、C三镇分别抽取10、20、30个样本。在总样本量相同的情况下,这样得到的估计误差会显著减小。用Python实现起来也非常直观:

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.25)

这里的stratify参数专门用于分层处理,能够自动按照类别比例完成采样任务,极大地简化了操作流程。

水塘采样:应对数据流中的随机抽取

这个场景非常有趣:当你面对一个长度未知、规模巨大的数据流,只能从头到尾遍历一遍时,需要设计一种算法,从该流中随机选出一个元素,并确保每个元素被选中的概率完全相同。听起来有些挑战性?

举个例子:从无限大的数据流中抽取5个对象,保证每个元素被选中的概率相等。实现代码如下:

import random

def generator(max):
    number = 1
    while number < max:
        number += 1
        yield number

stream = generator(10000)
k = 5
reservoir = []
for i, element in enumerate(stream):
    if i+1 <= k:
        reservoir.append(element)
    else:
        probability = k/(i+1)
        if random.random() < probability:
            reservoir[random.choice(range(0,k))] = element

print(reservoir)
# 输出示例:[1369, 4108, 9986, 828, 5589]

数学上可以证明,流中每个元素被选中的概率确实是相等的。如何理解这一结论?从一个简单问题入手会很有帮助。考虑只有3个项目的数据流,我们只保留其中2个。

  • 看到第一个项目——将其放入水塘,此时水塘还有空间。
  • 看到第二个项目——也放入水塘,水塘依然有空间。
  • 看到第三个项目——关键步骤来了:它有2/3的概率被放入列表。

那么第一个项目最终被选中的概率是多少?它被移除的概率等于:第三个项目被选中(2/3)乘以第一个项目被随机选为替代对象的概率(1/2),即2/3 × 1/2 = 1/3。因此第一个项目被保留的概率是2/3。同样的推理也适用于第二个项目。推广到一般情况,每个项目被选中的概率为K/N。

随机欠采样与过采样:处理不平衡数据集

在实际应用中,不平衡数据集是非常常见的问题。处理这类问题的一种常用方法是重采样:从多数类中删除一些样本(欠采样),或者为少数类增加更多样本(过采样)。首先,我们构建一个不平衡数据集:

from sklearn.datasets import make_classification
X, y = make_classification(
    n_classes=2, class_sep=1.5, weights=[0.9, 0.1],
    n_informative=3, n_redundant=1, flip_y=0,
    n_features=20, n_clusters_per_class=1,
    n_samples=100, random_state=10)
X = pd.DataFrame(X)
X['target'] = y

接下来,演示随机过采样和欠采样的实现:

num_0 = len(X[X['target']==0])
num_1 = len(X[X['target']==1])
print(num_0, num_1)

# 随机欠采样:从多数类中随机抽取与少数类数量相等的样本
undersampled_data = pd.concat([X[X['target']==0].sample(num_1), X[X['target']==1]])
print(len(undersampled_data))

# 随机过采样:对少数类进行有放回抽样,使其数量与多数类一致
oversampled_data = pd.concat([X[X['target']==0], X[X['target']==1].sample(num_0, replace=True)])
print(len(oversampled_data))

# 输出:
# 90 10
# 20
# 180

使用 imbalanced-learn 进行欠采样与过采样

imbalanced-learn(简称imblearn)是一个专门解决不平衡问题的Python库,它提供了多种成熟的欠采样和过采样方法,极大地方便了数据预处理工作。

a. 使用 Tomek Links 进行欠采样

Tomek Links 指的是两个属于不同类别且彼此距离最近的样本。在该算法中,我们会从这些Tomek Links对中移除多数类的元素,从而为分类器提供更清晰的决策边界,提升模型性能。

from imblearn.under_sampling import TomekLinks
tl = TomekLinks(return_indices=True, ratio='majority')
X_tl, y_tl, id_tl = tl.fit_sample(X, y)

b. 使用 SMOTE 进行过采样

SMOTE(Synthetic Minority Oversampling Technique)的核心思路是在已有少数类样本的附近,人工合成新的少数类样本,而不是简单地进行复制。这种方法能够有效缓解过拟合问题,并增强模型对少数类的识别能力。

from imblearn.over_sampling import SMOTE
smote = SMOTE(ratio='minority')
X_sm, y_sm = smote.fit_sample(X, y)

值得一提的是,imblearn包中还提供了许多其他方法,例如用于欠采样的 Cluster Centroids、NearMiss,以及用于过采样的 ADASYN 和 bSMOTE。在实际项目中,可以根据具体场景灵活选择最合适的采样策略。

结论:采样策略是数据科学成功的关键

算法无疑是数据科学的核心驱动力,这一点毋庸置疑。而采样作为数据科学中一个基础且重要的环节,却常常被忽视。一个优秀的采样策略能够显著推动项目进展,而一个不当的策略则可能导致结果完全偏离预期。因此,在选择采样方法时,多投入一些精力进行权衡,绝对是一个值得的付出。

来源:https://m.elecfans.com/article/2266214.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。