cvgear, inauguration
cvgear 0.1.0 was released on 20 May, 2020.
CVGear means Computer Vision Gear. It is under MIT License and contains computer vision gears for good uses.
TorchNestedLoader
TorchNestedLoader
allows you to save/load between different modules with actually the same logic structure.
Suppose we have a SimpleNet:
import torch.nn as nn
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(
in_channels=3,
out_channels=32,
kernel_size=3,
stride=1,
padding=1,
bias=False
)
self.bn1 = nn.BatchNorm2d(32)
self.conv2 = nn.Conv2d(
in_channels=32,
out_channels=32,
kernel_size=3,
stride=1,
padding=1,
bias=False
)
self.bn2 = nn.BatchNorm2d(32)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.conv2(x)
x = self.bn2(x)
return x
simplenet = SimpleNet()
The structure of SimpleNet is:
SimpleNet(
(conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
And we have a more "wrapped" version WrappedSimpleNet:
import torch.nn as nn
class Conv2d(torch.nn.Conv2d):
def __init__(self, *args, **kwargs):
norm = kwargs.pop("norm", None)
super().__init__(*args, **kwargs)
self.norm = norm
def forward(self, x):
x = super().forward(x)
if self.norm is not None:
x = self.norm(x)
return x
class WrappedSimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.stem = Conv2d(
in_channels=3,
out_channels=32,
kernel_size=3,
stride=1,
padding=1,
bias=False,
norm=nn.BatchNorm2d(32)
)
self.conv1 = Conv2d(
in_channels=32,
out_channels=32,
kernel_size=3,
stride=1,
padding=1,
bias=False,
norm=nn.BatchNorm2d(32)
)
def forward(self, x):
x = self.stem(x)
x = self.conv1(x)
return x
wrappedsimplenet = WrappedSimpleNet()
The structure of WrappedSimpleNet is:
WrappedSimpleNet(
(stem): Conv2d(
3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(conv1): Conv2d(
32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
The logic structure of SimpleNet and WrappedSimpleNet is exactly the same. But they differ from submodule names and tree structure. So you cannot save/load state_dict
between these two modules using .state_dict()
and .load_state_dict()
methods easily.
But with TorchNestedLoader
, you can save/load nested_dict
between these two modules easily:
from cvgear.framework.torch import TorchNestedLoader
simplenetloader = TorchNestedLoader(simplenet)
wrappedsimplenetloader = TorchNestedLoader(wrappedsimplenet)
# save as nested_dict
nested_dict = simplenetloader.nested_dict()
# load nested_dict
wrappedsimplenetloader.load_nested_dict(nested_dict)
Imagine you just implement one state-of-the-art model in torch and want to test it. Train your model from scratch will be time-consuming. After downloading pre-trained model from the Internet then found it painful to load it to your model manually?
Use TorchNestedLoader
as your gear!
DarknetParser
Everyone loves darknet. It is very fast and in public domain.
The configuration file of the darknet network is often long and tedious(due to its sequential structure), hard to read through. With darknet installed, the network configuration file can be parsed easily and you can get a clear sense of what the network structure is from the information it displayed.
Without darknet installed:
from cvgear.framework.darknet import DarknetParser, build_darknet_parser
# create a DarknetParser instance, then load network configuration
darknet53 = DarknetParser("darknet53")
darknet53.load_darknet_cfg("path/to/darknet53.cfg")
# or build a DarknetParser from network configuration file directly
darknet53 = build_darknet_parser("path/to/darknet53.cfg")
print(darknet53)
Crystal clear!
DarknetNestedLoader
Save/load torch module...
Parse darknet network...
What about... Save/load darknet network?
Even more! Save/load between darknet network and torch.nn.Module
! DarknetNestedLoader
is made for save/load darknet network(DarknetParser) as binary weights(.weights
file) or as nested_dict
.
from cvgear.framework.darknet import DarknetNestedLoader, build_darknet_nested_loader
# create a DarknetNestedLoader instance with DarknetParser, then load from binary weights file
darknet53loader = DarknetNestedLoader(darknet53)
darknet53loader.load_darknet_weights("path/to/darknet53.weights")
# or build a DarknetNestedLoader from network configuration file and binary weights file
darknet53loader = build_darknet_nested_loader("path/to/darknet53.cfg", "path/to/darknet53.weights")
# save weights to nested_dict
nested_dict = darknet53loader.nested_dict()
# load nested_dict to a torch.nn.Module with TorchNestedLoader
# ...
Recap
DarknetParser
describes a darknet network(astorch.nn.Module
describes a torch module)DarknetNestedLoader
can save/load a darknet network asnested_dict
or binary fileTorchNestedLoader
can save/load a torch module asnested_dict
- So with
DarknetNestedLoader
andTorchNestedLoader
, you can convert between darknet weights and torch weights easily.
That is little cvgear 0.1.0
More gears are coming up...
Happy inauguration!🎉🎉🎉