Yang 提取Cifar-100的特征
不同的点:特征选择需要4096维的特征,而我们的代码可能64维就可以了
步骤:①保存模型②提取模型特征,然后应保存为mat
备注:MetaSAug_1
①保存模型
import os
import time
import argparse
import random
import copy
import torch
import torchvision
import numpy as np
import torch.nn.functional as F
from torch.autograd import Variable
import torchvision.transforms as transforms
from data_utils import *
from resnet import *
import shutil
from loss import *
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.utils.data.sampler import WeightedRandomSampler
import torch.nn.functional as F
import os
parser = argparse.ArgumentParser(description='Imbalanced Example')
parser.add_argument('--dataset', default='cifar100', type=str,
help='dataset (cifar10 or cifar100[default])')
parser.add_argument('--batch-size', type=int, default=100, metavar='N',
help='input batch size for training (default: 64)')
parser.add_argument('--num_classes', type=int, default=100)
parser.add_argument('--num_meta', type=int, default=0,
help='The number of meta data for each class.')
parser.add_argument('--imb_factor', type=float, default=0.005) #100 #200=0.005
parser.add_argument('--test-batch-size', type=int, default=100, metavar='N',
help='input batch size for testing (default: 100)')
parser.add_argument('--epochs', type=int, default=200, metavar='N',
help='number of epochs to train')
parser.add_argument('--lr', '--learning-rate', default=1e-1, type=float,
help='initial learning rate')
parser.add_argument('--momentum', default=0.9, type=float, help='momentum')
parser.add_argument('--nesterov', default=True, type=bool, help='nesterov momentum')
parser.add_argument('--weight-decay', '--wd', default=5e-4, type=float,
help='weight decay (default: 5e-4)')
parser.add_argument('--no-cuda', action='store_true', default=False,
help='disables CUDA training')
parser.add_argument('--split', type=int, default=1000)
parser.add_argument('--seed', type=int, default=42, metavar='S',
help='random seed (default: 42)')
parser.add_argument('--print-freq', '-p', default=100, type=int,
help='print frequency (default: 10)')
parser.add_argument('--lam', default=0.25, type=float, help='[0.25, 0.5, 0.75, 1.0]') #default=0.25
parser.add_argument('--gpu', default=0, type=int)
parser.add_argument('--meta_lr', default=0.1, type=float)
parser.add_argument('--save_name', default='name', type=str)
parser.add_argument('--idx', default='0', type=str)
# 定义基本的ResNet块
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, in_planes, planes, stride=1):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(planes)
self.shortcut = nn.Sequential()
if stride != 1 or in_planes != self.expansion * planes:
self.shortcut = nn.Sequential(
nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(self.expansion * planes)
)
def forward(self, x):
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += self.shortcut(x)
out = F.relu(out)
return out
class ResNet32(nn.Module):
def __init__(self, block, num_blocks, num_classes=100, feature_size=4096):
super(ResNet32, self).__init__()
self.in_planes = 16
self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(16)
self.layer1 = self._make_layer(block, 16, num_blocks[0], stride=1)
self.layer2 = self._make_layer(block, 32, num_blocks[1], stride=2)
self.layer3 = self._make_layer(block, 64, num_blocks[2], stride=2)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(64 * block.expansion, feature_size)
def _make_layer(self, block, planes, num_blocks, stride):
strides = [stride] + [1] * (num_blocks - 1)
layers = []
for stride in strides:
layers.append(block(self.in_planes, planes, stride))
self.in_planes = planes * block.expansion
return nn.Sequential(*layers)
def forward_features(self, x):
out = F.relu(self.bn1(self.conv1(x)))
out = self.layer1(out)
out = self.layer2(out)
out = self.layer3(out)
out = self.avgpool(out)
out = out.view(out.size(0), -1)
out = self.fc(out)
features = out
# print("Shape of features in forward_features:", features.shape) # 添加这行代码来打印特征的形状
# print("Shape of fc weight matrix:", self.fc.weight.shape)
return out, features
def forward(self, x):
return self.forward_features(x)[0] # 返回 forward_features 的第一个输出
def ResNet32_100():
return ResNet32(BasicBlock, [5, 5, 5], num_classes=100, feature_size=4096) # 添加 feature_size 参数
args = parser.parse_args()
# for arg in vars(args):
# print("{}={}".format(arg, getattr(args, arg)))
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"]= str(args.gpu)
kwargs = {'num_workers': 1, 'pin_memory': False}
use_cuda = not args.no_cuda and torch.cuda.is_available()
torch.manual_seed(args.seed)
device = torch.device("cuda" if use_cuda else "cpu")
train_data_meta, train_data, test_dataset = build_dataset(args.dataset, args.num_meta)
print(f'length of meta dataset:{len(train_data_meta)}')
print(f'length of train dataset: {len(train_data)}')
train_loader = torch.utils.data.DataLoader(
train_data, batch_size=args.batch_size, shuffle=True, **kwargs)
np.random.seed(42)
random.seed(42)
torch.manual_seed(args.seed)
classe_labels = range(args.num_classes)
data_list = {}
for j in range(args.num_classes):
data_list[j] = [i for i, label in enumerate(train_loader.dataset.targets) if label == j]
img_num_list = get_img_num_per_cls(args.dataset, args.imb_factor, args.num_meta*args.num_classes)
print(img_num_list)
print(sum(img_num_list))
im_data = {}
idx_to_del = []
for cls_idx, img_id_list in data_list.items():
random.shuffle(img_id_list)
img_num = img_num_list[int(cls_idx)]
im_data[cls_idx] = img_id_list[img_num:]
idx_to_del.extend(img_id_list[img_num:])
print(len(idx_to_del))
imbalanced_train_dataset = copy.deepcopy(train_data)
imbalanced_train_dataset.targets = np.delete(train_loader.dataset.targets, idx_to_del, axis=0)
imbalanced_train_dataset.data = np.delete(train_loader.dataset.data, idx_to_del, axis=0)
print(len(imbalanced_train_dataset))
imbalanced_train_loader = torch.utils.data.DataLoader(
imbalanced_train_dataset, batch_size=args.batch_size, shuffle=True, **kwargs)
test_loader = torch.utils.data.DataLoader(
test_dataset, batch_size=args.batch_size, shuffle=False, **kwargs)
best_prec1 = 0
# 初始化模型、损失函数和优化器
net = ResNet32_100()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
# 将模型转移到GPU(如果可用)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
# 训练模型
best_prec1 = 0
def main():
global best_prec1
for epoch in range(200): # 你可以调整这个值来增加训练轮数
net.train()
running_loss = 0.0
for i, data in enumerate(imbalanced_train_loader, 0):
inputs, labels = data[0].to(device), data[1].to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99: # 每100个小批量打印一次损失
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 100))
running_loss = 0.0
# 评估模型
prec1 = validate(test_loader, net, criterion, device)
print("epoch:{},prec1:{}".format(epoch, prec1))
# 保存模型
is_best = prec1 > best_prec1
best_prec1 = max(prec1, best_prec1)
save_checkpoint({
'epoch': epoch + 1,
'state_dict': net.state_dict(),
'best_prec1': best_prec1,
'optimizer': optimizer.state_dict(),
}, is_best, epoch + 1, prec1) # 传递 is_best 参数
print('Finished Training')
print('Best accuracy: ', best_prec1)
def validate(val_loader, model, criterion, device):
model.eval()
correct = 0
total = 0
with torch.no_grad():
for data in val_loader:
inputs, labels = data[0].to(device), data[1].to(device)
outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
acc = 100 * correct / total
return acc
# 定义基本的ResNet块
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, in_planes, planes, stride=1):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(planes)
self.shortcut = nn.Sequential()
if stride != 1 or in_planes != self.expansion * planes:
self.shortcut = nn.Sequential(
nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(self.expansion * planes)
)
def forward(self, x):
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += self.shortcut(x)
out = F.relu(out)
return out
def save_checkpoint(state, is_best, epoch, accuracy):
path = 'checkpoint/zhangYang_IR200/'
if not os.path.exists(path):
os.makedirs(path)
if is_best:
filename = str(epoch) + '_best_' + str(accuracy) + '.pth.tar' # 将整数转换为字符串
else:
filename = str(epoch) + '_' + str(accuracy) + '.pth.tar' # 将整数转换为字符串
torch.save(state, os.path.join(path, filename)) # 修正保存路径
if __name__ == '__main__':
main()
②保存mat
import argparse
import random
from data_utils import *
from loss import *
import torch.nn as nn
import torch.optim as optim
from torch.utils.data.sampler import WeightedRandomSampler
import os
import torch
import scipy.io as sio
from Meta_train import ResNet32_100
parser = argparse.ArgumentParser(description='Imbalanced Example')
parser.add_argument('--dataset', default='cifar100', type=str,
help='dataset (cifar10 or cifar100[default])')
parser.add_argument('--batch-size', type=int, default=100, metavar='N',
help='input batch size for training (default: 64)')
parser.add_argument('--num_classes', type=int, default=100)
parser.add_argument('--num_meta', type=int, default=0,
help='The number of meta data for each class.')
parser.add_argument('--imb_factor', type=float, default=0.01) #100
parser.add_argument('--test-batch-size', type=int, default=100, metavar='N',
help='input batch size for testing (default: 100)')
parser.add_argument('--epochs', type=int, default=200, metavar='N',
help='number of epochs to train')
parser.add_argument('--lr', '--learning-rate', default=1e-1, type=float,
help='initial learning rate')
parser.add_argument('--momentum', default=0.9, type=float, help='momentum')
parser.add_argument('--nesterov', default=True, type=bool, help='nesterov momentum')
parser.add_argument('--weight-decay', '--wd', default=5e-4, type=float,
help='weight decay (default: 5e-4)')
parser.add_argument('--no-cuda', action='store_true', default=False,
help='disables CUDA training')
parser.add_argument('--split', type=int, default=1000)
parser.add_argument('--seed', type=int, default=42, metavar='S',
help='random seed (default: 42)')
parser.add_argument('--print-freq', '-p', default=100, type=int,
help='print frequency (default: 10)')
parser.add_argument('--lam', default=0.25, type=float, help='[0.25, 0.5, 0.75, 1.0]') #default=0.25
parser.add_argument('--gpu', default=0, type=int)
parser.add_argument('--meta_lr', default=0.1, type=float)
parser.add_argument('--save_name', default='name', type=str)
parser.add_argument('--idx', default='0', type=str)
args = parser.parse_args()
for arg in vars(args):
print("{}={}".format(arg, getattr(args, arg)))
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"]= str(args.gpu)
kwargs = {'num_workers': 1, 'pin_memory': False}
use_cuda = not args.no_cuda and torch.cuda.is_available()
torch.manual_seed(args.seed)
device = torch.device("cuda" if use_cuda else "cpu")
train_data_meta, train_data, test_dataset = build_dataset(args.dataset, args.num_meta)
print(f'length of meta dataset:{len(train_data_meta)}')
print(f'length of train dataset: {len(train_data)}')
train_loader = torch.utils.data.DataLoader(
train_data, batch_size=args.batch_size, shuffle=True, **kwargs)
np.random.seed(42)
random.seed(42)
torch.manual_seed(args.seed)
classe_labels = range(args.num_classes)
data_list = {}
for j in range(args.num_classes):
data_list[j] = [i for i, label in enumerate(train_loader.dataset.targets) if label == j]
img_num_list = get_img_num_per_cls(args.dataset, args.imb_factor, args.num_meta*args.num_classes)
print(img_num_list)
print(sum(img_num_list))
im_data = {}
idx_to_del = []
for cls_idx, img_id_list in data_list.items():
random.shuffle(img_id_list)
img_num = img_num_list[int(cls_idx)]
im_data[cls_idx] = img_id_list[img_num:]
idx_to_del.extend(img_id_list[img_num:])
print(len(idx_to_del))
imbalanced_train_dataset = copy.deepcopy(train_data)
imbalanced_train_dataset.targets = np.delete(train_loader.dataset.targets, idx_to_del, axis=0)
imbalanced_train_dataset.data = np.delete(train_loader.dataset.data, idx_to_del, axis=0)
print(len(imbalanced_train_dataset))
imbalanced_train_loader = torch.utils.data.DataLoader(
imbalanced_train_dataset, batch_size=args.batch_size, shuffle=True, **kwargs)
test_loader = torch.utils.data.DataLoader(
test_dataset, batch_size=args.batch_size, shuffle=False, **kwargs)
best_prec1 = 0
# 初始化模型、损失函数和优化器
net = ResNet32_100()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
# 将模型转移到GPU(如果可用)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
# 训练模型
best_prec1 = 0
def load_model(model, checkpoint_path):
checkpoint = torch.load(checkpoint_path)
model.load_state_dict(checkpoint['state_dict'])
return model
# 定义一个函数来提取特征并保存为.mat文件
def extract_features(model, dataloader):
model.eval()
features_list = []
labels_list = [] # 存储标签
with torch.no_grad():
for images, labels in dataloader: # 获取标签
outputs, features = model.forward_features(images)
features_list.append(features)
labels_list.append(labels)
features = torch.cat(features_list, dim=0)
labels = torch.cat(labels_list, dim=0) # 连接所有标签
labels = labels.view(-1, 1) # 调整标签形状以便连接到特征数组
features = torch.cat((features, labels.float()), dim=1) # 在特征数组中添加标签
print("Shape of features:", features.shape) # 打印特征的形状
return features # 返回特征
def main():
# 加载已保存的模型
model = ResNet32_100()
model = load_model(model, '/home/zy/pycharm/project/temp/MetaSAug_1/test/checkpoint/ours/183_33.16.pth.tar')
# 提取特征 train
# features = extract_features(model, imbalanced_train_loader)
# 提取特征 test
features = extract_features(model, test_loader)
# 将特征保存为.mat文件
filename = 'Test1_183_33.16'
sio.savemat('/home/zy/pycharm/project/temp/MetaSAug_1/test/matFile/' + filename + '.mat',
{'data_array': features.cpu().numpy()})
# 打印.mat文件的大小
print("The size of the .mat file is:", features.shape[0], "x", features.shape[1])
if __name__ == '__main__':
main()