如何从PyTorch的GhostNet模型提取分类器层的1280维输入特征?
获取GhostNet分类器输入特征的替代方法
不用钩子也能轻松拿到分类器的1280维输入特征,这里提供两种直观的方案:
方案1:手动调用模型子模块计算特征
无需修改模型源码,直接在评估代码里分步计算到分类器前的特征:
操作步骤
- 先确认你的GhostNet模型结构,通常包含
backbone(特征提取)、global_pool(全局池化)和classifier(最后全连接层)三个核心部分。如果不清楚模块命名,可通过print(list(model.named_children()))查看。 - 在评估循环中,跳过直接调用
model(imgs),改为分步计算特征与分类输出。
修改后的评估代码
def model_valid(model, val_data): model.eval() correct = 0 total = 0 pred = np.array([]) lbs = np.array([]) features_list = [] # 存储所有样本的1280维特征 with torch.no_grad(): for imgs, labels in tqdm(val_data): imgs = imgs.to(device='cuda') labels = labels.to(device='cuda') # 分步计算到分类器前的特征 x = model.backbone(imgs) x = model.global_pool(x) features = x.flatten(1) # 此处即为分类器的1280维输入 outputs = model.classifier(features) _, predicted = torch.max(outputs, dim=1) _, labels = torch.max(labels, dim=1) total += labels.shape[0] correct += int((predicted == labels).sum()) pred = np.append(pred, predicted.cpu().numpy(), axis=0) lbs = np.append(lbs, labels.cpu().numpy(), axis=0) features_list.append(features.cpu().numpy()) # 保存当前batch的特征 print(f'model accuracy is {correct/total}') # 将所有batch的特征拼接为一个数组 all_features = np.concatenate(features_list, axis=0) return correct/total, [lbs, pred], all_features
方案2:修改模型forward方法,同时返回特征与分类输出
如果允许修改模型代码,直接在forward函数里返回特征值,逻辑更简洁:
操作步骤
- 找到GhostNet模型的forward函数,原结构通常如下:
def forward(self, x): x = self.backbone(x) x = self.global_pool(x) x = x.flatten(1) x = self.classifier(x) return x
- 修改为同时返回特征和分类输出:
def forward(self, x): x = self.backbone(x) x = self.global_pool(x) features = x.flatten(1) # 保存1280维特征 outputs = self.classifier(features) return features, outputs
对应的评估代码修改
def model_valid(model, val_data): model.eval() correct = 0 total = 0 pred = np.array([]) lbs = np.array([]) features_list = [] with torch.no_grad(): for imgs, labels in tqdm(val_data): imgs = imgs.to(device='cuda') labels = labels.to(device='cuda') # 直接获取特征和分类输出 features, outputs = model(imgs) _, predicted = torch.max(outputs, dim=1) _, labels = torch.max(labels, dim=1) total += labels.shape[0] correct += int((predicted == labels).sum()) pred = np.append(pred, predicted.cpu().numpy(), axis=0) lbs = np.append(lbs, labels.cpu().numpy(), axis=0) features_list.append(features.cpu().numpy()) print(f'model accuracy is {correct/total}') all_features = np.concatenate(features_list, axis=0) return correct/total, [lbs, pred], all_features
两种方案对比
- 方案1:无需改动模型源码,适合不想修改模型的场景,但需要明确模型的层级结构。
- 方案2:代码更简洁,但需要修改模型的forward方法,适合可调整模型代码的场景。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

