#集成学习#:bagging、boosting、stacking和blending

集成学习是一种机器学习方法,旨在提高单个模型的性能和鲁棒性。它基于这样一个假设:通过结合多个模型的预测结果,可以获得更好的预测性能,因为每个模型都可能从数据中提取不同的信息,因此他们的错误也可能是不同的,通过整合他们的预测结果可以减少这种错误的影响。

集成学习可以分为两类:bagging和boosting。

Bagging:是bootstrap aggregating的缩写,即自举汇聚法。它通过从原始数据集中进行有放回的随机抽样来创建多个训练集,每个训练集都用于训练一个独立的模型。这些模型的预测结果被组合起来,例如通过平均,以生成最终的集成模型的预测结果。Bagging可以用于降低模型方差,因为通过使用不同的训练集训练多个模型,我们可以减少模型对特定训练集的敏感性。

  1. Boosting:是一种迭代算法,它通过逐步改善模型的预测能力来构建一个强大的集成模型。每个迭代的模型都是在先前模型的基础上构建的,即每个模型都尝试学习之前模型的错误。通过这种方式,Boosting可以减少模型偏差,因为它们能够逐步拟合训练数据中更复杂的模式。

  2. 除了Bagging和Boosting,还有其他类型的集成学习方法,例如Stacking和Blending。Stacking通过训练多个不同类型的基本模型,并使用第二个元模型(或叫做“超级学习器”)来组合它们的预测结果。Blending是一种类似于Stacking的技术,它在训练数据集上训练多个不同的模型,并使用一个加权平均来组合它们的预测结果。

集成学习可以提高预测性能和鲁棒性,但需要更多的计算资源和时间。它适用于大型数据集和需要高度精确的预测的情况。

使用pytorch分别实现bagging、boosting、stacking和blending

下面是使用PyTorch实现集成学习的例子:

首先,我们需要准备数据。这里我们使用PyTorch的MNIST数据集作为例子。我们将训练集和测试集分别加载进来:

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as datasets
import torchvision.transforms as transforms

# 定义数据转换
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])

# 加载数据集
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

# 定义数据加载器
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False)

接下来,我们可以定义基本模型,这里使用简单的卷积神经网络:

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.dropout = nn.Dropout2d()
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = nn.functional.relu(nn.functional.max_pool2d(x, 2))
        x = self.conv2(x)
        x = nn.functional.relu(nn.functional.max_pool2d(self.dropout(x), 2))
        x = x.view(-1, 320)
        x = nn.functional.relu(self.fc1(x))
        x = self.dropout(x)
        x = self.fc2(x)
        return nn.functional.log_softmax(x, dim=1)

现在,我们可以使用这个基本模型来构建集成学习模型。

bagging

首先是Bagging。在Bagging中,我们通过随机抽样训练集数据来构建多个基本模型。每个模型都是独立训练的,我们可以将它们的预测结果平均得到集成模型的输出。

# Bagging
n_models = 5
models = []
for i in range(n_models):
    model = CNN()
    optimizer = optim.Adam(model.parameters(), lr=0.01)
    criterion = nn.CrossEntropyLoss()
    for epoch in range(10):
        for batch_idx, (data, target) in enumerate(train_loader):
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
    models.append(model)

# 预测
def bagging_predict(models, data):
    outputs = torch.zeros(data.shape[0], 10)
    for model in models:
        output = torch.exp(model(data))
        outputs += output
    return outputs.argmax(dim=1)

# 评估
correct = 0
total = 0
with torch.no_grad():
    for data, target in test_loader:
        outputs = bagging_predict(models, data)
        total += target.size(0)
        correct += (outputs == target).sum().item()
print(f"Accuracy: {100 * correct / total:.2f}%")

boosting

下一步是Boosting。在Boosting中,我们构建多个基本模型,每个模型都在前一个模型训练的基础上进行训练。每个模型的训练都会依据之前模型的预测结果进行加权,以便更好地捕获错误分类的样本。

# Boosting
n_models = 5
models = []
train_dataset_boost = list(train_dataset)
for i in range(n_models):
    model = CNN()
    optimizer = optim.Adam(model.parameters(), lr=0.01)
    criterion = nn.CrossEntropyLoss()
    for epoch in range(10):
        for batch_idx, (data, target) in enumerate(train_loader):
            if i == 0:
                weights = torch.ones(len(train_dataset))
            else:
                outputs = torch.exp(models[-1](data))
                weights = torch.zeros(len(train_dataset))
                for j, (d, t) in enumerate(train_dataset_boost):
                    if t == outputs.argmax(dim=1)[j]:
                        weights[j] = 1 / (outputs[j][t] + 1e-6)
            weights = weights / weights.sum()
            sampler = torch.utils.data.sampler.WeightedRandomSampler(weights, len(weights), replacement=True)
            train_loader_boost = torch.utils.data.DataLoader(train_dataset_boost, batch_size=64, sampler=sampler)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
    models.append(model)

    # 更新训练集权重
    outputs = torch.exp(model(torch.stack([d for d, t in train_dataset_boost])))
    weights = torch.zeros(len(train_dataset))
    for j, (d, t) in enumerate(train_dataset_boost):
        if t == outputs.argmax(dim=1)[j]:
            weights[j] = 1 / (outputs[j][t] + 1e-6)
    weights = weights / weights.sum()
    train_dataset_boost = list(zip(train_dataset, weights))
    train_dataset_boost = [(d, t, w) for (d, t), w in train_dataset_boost]

# 预测
def boosting_predict(models, data):
    outputs = torch.zeros(data.shape[0], 10)
    for model in models:
        output = torch.exp(model(data))
        outputs += output
    return outputs.argmax(dim=1)

# 评估
correct = 0
total = 0
with torch.no_grad():
    for data, target in test_loader:
        outputs = boosting_predict(models, data)
        total += target.size(0)
        correct += (outputs == target).sum().item()
print(f"Accuracy: {100 * correct / total:.2f}%")

stacking

下一个集成方法是Stacking。在Stacking中,我们首先将训练集分成两部分,第一部分用于训练一组基本模型,第二部分用于为最终模型生成预测。对于第一部分,我们使用多个基本模型对其进行训练。对于第二部分,我们使用第一部分的基本模型的预测结果来训练一个最终的元模型,该元模型将基本模型的预测结果作为输入,并输出最终的预测结果。

# Stacking
n_models = 5
models = []
train_dataset_base, train_dataset_meta = torch.utils.data.random_split(train_dataset, [50000, 10000])
for i in range(n_models):
    model = CNN()
    optimizer = optim.Adam(model.parameters(), lr=0.01)
    criterion = nn.CrossEntropyLoss()
    for epoch in range(10):
        for batch_idx, (data, target) in enumerate(train_loader):
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
    models.append(model)

# 构建元数据集
meta_data = []
with torch.no_grad():
    for data, target in train_loader:
        outputs = []
        for model in models:
            outputs.append(model(data))
        outputs = torch.stack(outputs, dim=1)
        meta_data.append((outputs, target))

# 构建元模型
class MetaModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(5*10, 100)
        self.fc2 = nn.Linear(100, 10)

    def forward(self, x):
        x = x.view(x.shape[0], -1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

meta_model = MetaModel()
optimizer = optim.Adam(meta_model.parameters(), lr=0.01)
criterion = nn.CrossEntropyLoss()

# 元训练
for epoch in range(10):
    for data, target in meta_data:
        optimizer.zero_grad()
        output = meta_model(data.view(data.shape[0], -1))
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()

# 预测
def stacking_predict(models, meta_model, data):
    outputs = []
    with torch.no_grad():
        for model in models:
            output = model(data)
            outputs.append(output)
        outputs = torch.stack(outputs, dim=1)
        meta_output = meta_model(outputs.view(outputs.shape[0], -1))
    return meta_output.argmax(dim=1)

# 评估
correct = 0
total = 0
with torch.no_grad():
    for data, target in test_loader:
        outputs = stacking_predict(models, meta_model, data)
        total += target.size(0)
        correct += (outputs == target).sum().item()
print(f"Accuracy: {100 * correct / total:.2f}%")

blending

最后一个集成方法是Blending。Blending类似于Stacking,但它只使用一部分训练数据进行元模型的训练,而不是使用训练集的全部数据。在Blending中,我们首先将训练集分成两部分,第一部分用于训练多个基本模型,第二部分用于为最终模型生成预测。对于第二部分,我们使用第一部分的基本模型的预测结果来训练一个最终的元模型,该元模型将基本模型的预测结果作为输入,并输出最终的预测结果。

# Blending
n_models = 5
models = []
train_dataset_base, train_dataset_blend = torch.utils.data.random_split(train_dataset, [50000, 10000])
for i in range(n_models):
    model = CNN()
    optimizer = optim.Adam(model.parameters(), lr=0.01)
    criterion = nn.CrossEntropyLoss()
    for epoch in range(10):
        for batch_idx, (data, target) in enumerate(train_loader):
            if batch_idx < len(train_loader) // 2:
                optimizer.zero_grad()
                output = model(data)
                loss = criterion(output, target)
                loss.backward()
                optimizer.step()
            else:
                break
    models.append(model)

# 生成元数据
meta_data = []
with torch.no_grad():
    for data, target in train_loader:
        outputs = []
        for model in models:
            output = model(data)
            outputs.append(output)
        meta_data.append((torch.cat(outputs, dim=1), target))

# 构建元模型
class MetaModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(5*10, 100)
        self.fc2 = nn.Linear(100, 10)

    def forward(self, x):
        x = x.view(x.shape[0], -1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

meta_model = MetaModel()
optimizer = optim.Adam(meta_model.parameters(), lr=0.01)
criterion = nn.CrossEntropyLoss()


# 元训练
for epoch in range(10):
    for data, target in meta_data:
        optimizer.zero_grad()
        output = meta_model(data.view(data.shape[0], -1))
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()

# 预测
def blending_predict(models, meta_model, data):
    outputs = []
    with torch.no_grad():
        for model in models:
            output = model(data)
            outputs.append(output)
        meta_output = meta_model(torch.cat(outputs, dim=1))
    return meta_output.argmax(dim=1)

# 评估
correct = 0
total = 0
with torch.no_grad():
    for data, target in test_loader:
        outputs = blending_predict(models, meta_model, data)
        total += target.size(0)
        correct += (outputs == target).sum().item()
print(f"Accuracy: {100 * correct / total:.2f}%")

这就是如何使用PyTorch实现Bagging、Boosting、Stacking和Blending的代码示例。这些集成方法是机器学习中非常有用的工具,可以帮助我们提高模型的准确性和稳健性,尤其是在处理大规模、高维度数据时。

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值