Я пытаюсь реализовать обрезку модели на PyTorch с помощью ResNet18. Учитывая экземпляр ResNet18, я запускаю следующий код, чтобы загрузить предварительно обученную модель, сократить ее и сохранить сокращенную модель:
def random_unstructured_pruning(pruning_rate: float, device, log_file):
trained_model=retrieve_file(folder = "./models", file_name='trained_model.pth')
model=ResNet18(num_classes=10, input_channels=1).to(device)
model.load_state_dict(torch.load(trained_model))
modules_list=filter(lambda x: isinstance(x[1], (nn.Conv2d, nn.Linear, nn.BatchNorm2d)), model.named_modules())
modules_list = map(lambda x: (x[1], 'weight'), modules_list)
modules_list=tuple(modules_list)
prune.global_unstructured(modules_list, pruning_method=prune.L1Unstructured, amount=0.8)
for module in modules_list:
prune.remove(module[0], module[1])
pruning_rate_str= "{:02d}".format(int(pruning_rate * 10))
path=f"{model_saving_path}pruned_{pruning_rate_str}.pth"
#
torch.save(model.state_dict(), f"{path}")
В конце приведенной выше функции файл .pth имеет тот же размер, что и файл, который я загружаю в начале, хотя я ожидаю, что он будет меньше, поскольку я сокращаю 80% весов.
Может кто-нибудь объяснить мне, почему это происходит? Что я не так? Спасибо!!
Я думаю, что проблема в части сохранения функции, похоже, я сохраняю всегда одну и ту же модель, которую перезагружаю в начале, и обрезка не эффективна.
Я так и сделал, но PyTorch не поддерживает прямое копирование данных между плотными и разреженными тензорами на устройствах CUDA. Я получил эту ошибку: '('copy_() между плотными и разреженными тензорами не реализован! Найден собственный тип = torch.cuda.FloatTensor и тип src = torch.cuda.sparse.FloatTensor',)'
Утилита обрезки в Pytorch действует как маскирующая оболочка слоя, который подвергается обрезке. Это означает, что у вас по-прежнему есть доступ к исходным весам модели, а размер сети остается неизменным, если не больше, из-за инициализации маски для каждого сокращенного тензора.
Если вы посмотрите страницу документации prune.global_unstructured:
Изменяет модули на месте:
добавление именованного буфера с именем
name+'_mask'
, соответствующего двоичному файлу маска, применяемая к имени параметра методом сокращения.заменив имя параметра его сокращенной версией, в то время как исходное (необрезанный) параметр сохраняется в новом параметре с именем
name+'_orig'
.
Вот минимальный пример, показывающий, что необрезанные веса все еще доступны:
net = nn.Sequential(OrderedDict(
f1=nn.Linear(10, 5),
f2=nn.Linear(5, 1)))
pruned = ((net.f1, 'weight'),)
prune.global_unstructured(pruned, prune.L1Unstructured, amount=0.8)
Затем вы можете получить доступ к обрезанным весам:
>>> net.f1.weight
tensor([[0.0000, 0.0000, 0.0000, -0.0000, 0.0000],
[0.0000, 0.3599, 0.0000, -0.0000, 0.4034]])
Исходный необрезанный вес:
>>> net.f1.weight_orig
Parameter containing:
tensor([[ 0.1312, 0.1105, 0.0910, -0.2650, 0.3439],
[ 0.0412, 0.3599, 0.2040, -0.2672, 0.4034]])
И маска для обрезки:
>>> net.f1.weight_mask
tensor([[0., 0., 0., 0., 0.],
[0., 1., 0., 0., 1.]])
Спасибо за ответ и разъяснение, теперь все более понятно! У меня все еще есть сомнения: какие показатели я могу сравнить, чтобы показать эффективность моей стратегии сокращения? Я думал о размере модели, но, как вы сказали, он не меняется при обрезке; Я также думал о ненулевых параметрах, и они уменьшаются, когда я применяю обрезку к своей модели, но что еще? Время обучения? Использование графического процессора?
Возможно, посмотрите на флопы, но, как правило, для такого подхода важно сообщать о размере модели.
Извините, но я немного в замешательстве. Вначале вы сказали мне, что размер файла .pth не должен меняться после сокращения, так как я могу вычислить размер модели, чтобы увидеть эффект сокращения?
Размер часто указывается в виде количества параметров, поэтому нет необходимости сравнивать размеры файлов.
Хорошо, спасибо. И последнее: предлагаете ли вы какую-нибудь библиотеку Python для оценки количества FLOP во время обучения или вывода?
Я не использовал такие инструменты, но, возможно, вы можете обратиться к этой другой теме.
возможно, стоит попробовать сохранить модель в разреженном формате