功能描述:

一段涉及模型蒸馏、剪枝和量化的代码

代码:

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.utils.prune as prune

# 定义量化函数
def quantize_weights(module, num_bits=8):
    for name, param in module.named_parameters():
        if 'weight' in name:
            scale = torch.max(torch.abs(param))
            # 把参数值调整到指定的量化范围
            param.data = torch.round(param / scale * (2 ** (num_bits - 1) - 1)) 

# 定义教师模型
class TeacherModel(nn.Module):
    def __init__(self):
        super(TeacherModel, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding=1)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 32, 3, padding=1)
        self.fc1 = nn.Linear(32 * 8 * 8, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.pool(torch.relu(self.conv1(x)))
        x = self.pool(torch.relu(self.conv2(x)))
        x = x.view(-1, 32 * 8 * 8)
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 定义学生模型
class StudentModel(nn.Module):
    def __init__(self):
        super(StudentModel, self).__init__()
        self.conv1 = nn.Conv2d(3, 8, 3, padding=1)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(8, 16, 3, padding=1)
        self.fc1 = nn.Linear(16 * 8 * 8, 64)
        self.fc2 = nn.Linear(64, 10)

    def forward(self, x):
        x = self.pool(torch.relu(self.conv1(x)))
        x = self.pool(torch.relu(self.conv2(x)))
        x = x.view(-1, 16 * 8 * 8)
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 定义损失函数
loss_func = nn.CrossEntropyLoss()

# 定义优化器
teacher_optimizer = optim.SGD(teacher_model.parameters(), lr=0.01)
student_optimizer = optim.SGD(student_model.parameters(), lr=0.01)

# 剪枝函数
def prune_model(model, prune_ratio):
    for name, module in model.named_modules():
        if isinstance(module, nn.Conv2d) or isinstance(module, nn.Linear):
            prune.l1_unstructured(module, name='weight', amount=prune_ratio)

# 训练函数
def train(teacher_model, student_model, train_loader, epochs):
    for epoch in range(epochs):
        for data, target in train_loader:
            # 教师模型前向传播
            teacher_output = teacher_model(data)
            # 学生模型前向传播
            student_output = student_model(data)

            # 计算教师模型的损失
            teacher_loss = loss_func(teacher_output, target)
            # 计算学生模型的损失
            student_loss = loss_func(student_output, target)

            # 教师模型反向传播和优化
            teacher_optimizer.zero_grad()
            teacher_loss.backward()
            teacher_optimizer.step()

            # 计算蒸馏损失(例如,使用 KL 散度)
            distillation_loss = nn.KLDivLoss()(student_output, teacher_output)

            # 总的学生模型损失
            total_student_loss = student_loss + distillation_loss

            # 学生模型反向传播和优化
            student_optimizer.zero_grad()
            total_student_loss.backward()
            student_optimizer.step()

            # 每隔一定的 epoch 进行剪枝
            if epoch % 5 == 0:
                prune_model(student_model, 0.2)  # 这里假设剪枝比例为 0.2

            # 每隔一定的 epoch 进行量化
            if epoch % 3 == 0:
                quantize_weights(student_model)
# 定义教师和学生模型
teacher_model = TeacherModel()
student_model = StudentModel()

# 假设已有训练数据加载器 train_loader
train(teacher_model, student_model, train_loader, epochs=10)

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐