文章目录[隐藏]
原始代码地址
源代码是来自facebook开源的一个github基于pytorch的项目,原始项目地址(maskrcnn-benchmark),因为原论文中的maskrcnn使用tensorflow构建的,但是目前很多小伙伴更偏向于用pytroch建模,因此,这里放一个facebook实现的基于pytorch的maskrcnn模型项目。
修改后的文件:修改后的文件
修改思想
我的修改方法是将使用c和cuda编写的文件替换为使用torchvision实现的部分方法替换。另外有一部分方法没有使用到就直接忽略掉,变成一个完全基于python语言的项目。
进行这种修改有两个原因,1.原代码使用pytorch-1.0 nightly版本,不是稳定版,而且在windows平台上基于vs进行配置并执行setup.py进行编译的效果并不好会出现很多问题,仍然不能运行,当然也有我自己的原因,可能没有配置好vs环境。2.目前很多教程是基于pytorch-1.0或者1.2进行构建的项目并且指定torchvision-0.2.1进行环境构建,单独为一个项目构建以新的环境使用不同版本同一种框架相对来说较麻烦。因此我才决定使用torchvision替换c和cuda,整一个纯python的mask-benchmark模型。
由于是使用windows10系统运行这个项目,因此缺少gcc的编译,会出现很多问题,最关键的是原项目用为提高计算效率使用了c和cuda编程设计了nms、RoiAlign和可形变卷积以及SigmoidFocalLoss等多种算法(或模型)。这里在默认配置中SigmoidFocalLoss并未用到,我在代码中改为只是用cpu版本,之后会进行gpu的优化。
代码修改部分
终于来到大家最关心的代码修改部分,我使用的是python3.7的环境因此,代码中有一部分是报错是关于PY3的改为PY37即可。
maskrcnn-benchmark-main\maskrcnn_benchmark\layers_init_.py文件修改
代码使用到c和cuda的主要部分是maskrcnn-benchmark-main\maskrcnn_benchmark\layers_init_.py这个文件。以下会该贴出修改后的代码,如果看代码麻烦,直接粘贴覆盖即可。
原始代码文件如下:
import torch
from .batch_norm import FrozenBatchNorm2d
from .misc import Conv2d
from .misc import DFConv2d
from .misc import ConvTranspose2d
from .misc import BatchNorm2d
from .misc import interpolate
from .nms import nms
from .roi_align import ROIAlign
from .roi_align import roi_align
from .roi_pool import ROIPool
from .roi_pool import roi_pool
from .smooth_l1_loss import smooth_l1_loss
from .sigmoid_focal_loss import SigmoidFocalLoss
from .dcn.deform_conv_func import deform_conv, modulated_deform_conv
from .dcn.deform_conv_module import DeformConv, ModulatedDeformConv, ModulatedDeformConvPack
from .dcn.deform_pool_func import deform_roi_pooling
from .dcn.deform_pool_module import DeformRoIPooling, DeformRoIPoolingPack, ModulatedDeformRoIPoolingPack
__all__ = [
"nms",
"roi_align",
"ROIAlign",
"roi_pool",
"ROIPool",
"smooth_l1_loss",
"Conv2d",
"DFConv2d",
"ConvTranspose2d",
"interpolate",
"BatchNorm2d",
"FrozenBatchNorm2d",
"SigmoidFocalLoss",
'deform_conv',
'modulated_deform_conv',
'DeformConv',
'ModulatedDeformConv',
'ModulatedDeformConvPack',
'deform_roi_pooling',
'DeformRoIPooling',
'DeformRoIPoolingPack',
'ModulatedDeformRoIPoolingPack',
]
根据第二节的思虑,修改后的代码如下:
import torch
from .batch_norm import FrozenBatchNorm2d
from .misc import Conv2d
from .misc import DFConv2d
from .misc import ConvTranspose2d
from .misc import BatchNorm2d
from .misc import interpolate
from torchvision.ops import nms
from torchvision.ops import RoIAlign as ROIAlign
from torchvision.ops import roi_align
from torchvision.ops import RoIPool as ROIPool
from torchvision.ops import roi_pool
from .smooth_l1_loss import smooth_l1_loss
from .sigmoid_focal_loss import SigmoidFocalLoss
__all__ = [
"nms",
"roi_align",
"ROIAlign",
"roi_pool",
"ROIPool",
"smooth_l1_loss",
"Conv2d",
"DFConv2d",
"ConvTranspose2d",
"interpolate",
"BatchNorm2d",
"FrozenBatchNorm2d",
"SigmoidFocalLoss"
]
SigmoidFocalLoss文件修改如下
然后由于使用到部分原文件中的算法,主要是SigmoidFocalLoss这个文件。其余文件种from maskrcnn_benchmark import _C这一行会报错,不需要理会,因为使用到了torchvision后及用不到了。只有SigmoidFocalLoss需要修改。集体修改会在下边贴代码描述。
SigmoidFocalLoss的修改,这里主要是将GPU部分注释掉,只是用cpu部分在运行maskrcnn时使用不到的,直接移除这部分也行,原代码如下:
import torch
from torch import nn
from torch.autograd import Function
from torch.autograd.function import once_differentiable
from maskrcnn_benchmark import _C
# TODO: Use JIT to replace CUDA implementation in the future.
class _SigmoidFocalLoss(Function):
@staticmethod
def forward(ctx, logits, targets, gamma, alpha):
ctx.save_for_backward(logits, targets)
num_classes = logits.shape[1]
ctx.num_classes = num_classes
ctx.gamma = gamma
ctx.alpha = alpha
losses = _C.sigmoid_focalloss_forward(
logits, targets, num_classes, gamma, alpha
)
return losses
@staticmethod
@once_differentiable
def backward(ctx, d_loss):
logits, targets = ctx.saved_tensors
num_classes = ctx.num_classes
gamma = ctx.gamma
alpha = ctx.alpha
d_loss = d_loss.contiguous()
d_logits = _C.sigmoid_focalloss_backward(
logits, targets, d_loss, num_classes, gamma, alpha
)
return d_logits, None, None, None, None
sigmoid_focal_loss_cuda = _SigmoidFocalLoss.apply
def sigmoid_focal_loss_cpu(logits, targets, gamma, alpha):
num_classes = logits.shape[1]
dtype = targets.dtype
device = targets.device
class_range = torch.arange(1, num_classes+1, dtype=dtype, device=device).unsqueeze(0)
t = targets.unsqueeze(1)
p = torch.sigmoid(logits)
term1 = (1 - p) ** gamma * torch.log(p)
term2 = p ** gamma * torch.log(1 - p)
return -(t == class_range).float() * term1 * alpha - ((t != class_range) * (t >= 0)).float() * term2 * (1 - alpha)
class SigmoidFocalLoss(nn.Module):
def __init__(self, gamma, alpha):
super(SigmoidFocalLoss, self).__init__()
self.gamma = gamma
self.alpha = alpha
def forward(self, logits, targets):
device = logits.device
if logits.is_cuda:
loss_func = sigmoid_focal_loss_cuda
else:
loss_func = sigmoid_focal_loss_cpu
loss = loss_func(logits, targets, self.gamma, self.alpha)
return loss.sum()
def __repr__(self):
tmpstr = self.__class__.__name__ + "("
tmpstr += "gamma=" + str(self.gamma)
tmpstr += ", alpha=" + str(self.alpha)
tmpstr += ")"
return tmpstr
修改后的代码如下:
import torch
from torch import nn
def sigmoid_focal_loss_cpu(logits, targets, gamma, alpha):
num_classes = logits.shape[1]
dtype = targets.dtype
device = targets.device
class_range = torch.arange(1, num_classes+1, dtype=dtype, device=device).unsqueeze(0)
t = targets.unsqueeze(1)
p = torch.sigmoid(logits)
term1 = (1 - p) ** gamma * torch.log(p)
term2 = p ** gamma * torch.log(1 - p)
return -(t == class_range).float() * term1 * alpha - ((t != class_range) * (t >= 0)).float() * term2 * (1 - alpha)
class SigmoidFocalLoss(nn.Module):
def __init__(self, gamma, alpha):
super(SigmoidFocalLoss, self).__init__()
self.gamma = gamma
self.alpha = alpha
def forward(self, logits, targets):
device = logits.device
if logits.is_cuda:
# loss_func = sigmoid_focal_loss_cuda
loss_func = sigmoid_focal_loss_cpu
else:
loss_func = sigmoid_focal_loss_cpu
loss = loss_func(logits, targets, self.gamma, self.alpha)
return loss.sum()
def __repr__(self):
tmpstr = self.__class__.__name__ + "("
tmpstr += "gamma=" + str(self.gamma)
tmpstr += ", alpha=" + str(self.alpha)
tmpstr += ")"
return tmpstr
数据集目录设置
这里我只下载了coco2014的数据集使用,但是在配置文件中使用到了更多的训练数据集,因此需要对配置文件进行修改,删除那部分数据集路径即可。
修改后的代码
基于上述修改,基本上没有难以解决的问题了,如果还不能运行可以使用我修改后的代码修改后的文件 下载资源的小伙伴可私信解决问题,微信二维码在项目包内。
pycocotools安装
再有一个麻烦的小问题就是pycocotools这个包的安装了,说实话,很多深度学习技术中包和环境、框架对windows都是十分不友好,这个给出一个能够正确在windows安装的方式。具体内容如下:
COCO 地址: https://github.com/cocodataset/cocoapi
由于这个项目是针对linux构建的,因此有大佬在GitHub改写另一个支持 Windows 的 COCO 地址:https://github.com/philferriere/cocoapi
这有两种安装方案(本文使用第二种安装方式)
参考自原文
1.cmd终端或pytorch终端中使用 pip 安装
pip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI
2.在https://github.com/philferriere/cocoapi下载源码,并进行解压。打开 CMD 终端(若有权限问题可使用管理员权限打开),并切换到 cocoapi\PythonAPI目录。运行以下指令:
# install pycocotools locally
python setup.py build_ext --inplace
# install pycocotools to the Python site-packages
python setup.py build_ext install
3.是安装这个包可能遇到的问题,这里根据网上可自己遇到过的有三个。
(1)error: command 'cl.exe' failed: No such file or directory // 或者 error: Unable to find vcvarsall.bat // 或者 error: Microsoft Visual C++ 14.0 is required.
因为没有Visual C++ 编译环境。需要安装Visual Studio 2017 (这里建议安装2017)。
(2)Wno-cpp和Wno-unused-function问题,我没有遇到,如果遇到可以用如下方法解决
cl: 命令行 error D8021 :无效的数值参数“/Wno-cpp” 和 cl: 命令行 error D8021 :无效的数值参数“/Wno-unused-function
解决方式: 删除cocoapi\PythonAPI\setup.py里的Wno-cpp和Wno-unused-function参数。
3.是ValueError: numpy.ufunc size changed, may indicate binary incompatibility.这个报错,原因是numpy的版本过低,我使用的是numpy1.19版本,然后我就替换到了numpy1.20.0版本。大家也可以替换更高的版本。
还有一些包也需要下载后离线安装,可自行百度解决。
版权声明:本文为CSDN博主「凉寒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lengxuelianhan/article/details/122660916
暂无评论