From bf23f2ff119a6a312ecc325a56fc9b54df868dad Mon Sep 17 00:00:00 2001 From: Shahriar Date: Fri, 18 Jan 2019 00:47:39 +0330 Subject: [PATCH 01/48] Added the existing code --- torchvision/CMakeLists.txt | 10 ++ torchvision/cmodels/alexnet.cpp | 42 +++++++ torchvision/cmodels/alexnet.h | 22 ++++ torchvision/cmodels/main.cpp | 67 +++++++++++ torchvision/cmodels/resnet.cpp | 122 ++++++++++++++++++++ torchvision/cmodels/resnet.h | 190 +++++++++++++++++++++++++++++++ torchvision/cmodels/vgg.cpp | 139 ++++++++++++++++++++++ torchvision/cmodels/vgg.h | 85 ++++++++++++++ torchvision/cmodels/vision.h | 8 ++ torchvision/cmodels/visionimpl.h | 67 +++++++++++ 10 files changed, 752 insertions(+) create mode 100644 torchvision/CMakeLists.txt create mode 100644 torchvision/cmodels/alexnet.cpp create mode 100644 torchvision/cmodels/alexnet.h create mode 100644 torchvision/cmodels/main.cpp create mode 100644 torchvision/cmodels/resnet.cpp create mode 100644 torchvision/cmodels/resnet.h create mode 100644 torchvision/cmodels/vgg.cpp create mode 100644 torchvision/cmodels/vgg.h create mode 100644 torchvision/cmodels/vision.h create mode 100644 torchvision/cmodels/visionimpl.h diff --git a/torchvision/CMakeLists.txt b/torchvision/CMakeLists.txt new file mode 100644 index 00000000000..d0f06b9ef35 --- /dev/null +++ b/torchvision/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8) +project(torchvision) +set(CMAKE_CXX_STANDARD 11) + +file(GLOB_RECURSE SOURCES cmodels/*.h cmodels/*.cpp) +add_executable(${PROJECT_NAME} ${SOURCES}) + +set(CUDNN_INCLUDE_DIR /usr/include/cuda) +find_package(Torch REQUIRED) +target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}") diff --git a/torchvision/cmodels/alexnet.cpp b/torchvision/cmodels/alexnet.cpp new file mode 100644 index 00000000000..5921d35d982 --- /dev/null +++ b/torchvision/cmodels/alexnet.cpp @@ -0,0 +1,42 @@ +#include "alexnet.h" + +torchvision::AlexNetImpl::AlexNetImpl(int classes) +{ + // clang-format off + features = torch::nn::Sequential( + visionimpl::Conv(3, 64, 11, 2, 4), + visionimpl::Relu(true), + visionimpl::MaxPool(3, 2), + visionimpl::Conv(64, 192, 5, 2), + visionimpl::Relu(true), + visionimpl::MaxPool(3, 2), + visionimpl::Conv(192, 384, 3, 1), + visionimpl::Relu(true), + visionimpl::Conv(384, 256, 3, 1), + visionimpl::Relu(true), + visionimpl::Conv(256, 256, 3, 1), + visionimpl::Relu(true), + visionimpl::MaxPool(3, 2)); + + classifier = torch::nn::Sequential( + torch::nn::Dropout(), + torch::nn::Linear(256 * 6 * 6, 4096), + visionimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, 4096), + visionimpl::Relu(true), + torch::nn::Linear(4096, classes)); + // clang-format on + + register_module("features", features); + register_module("clasifier", classifier); +} + +torch::Tensor torchvision::AlexNetImpl::forward(at::Tensor X) +{ + X = features->forward(X); + X = X.view({X.size(0), 256 * 6 * 6}); + X = classifier->forward(X); + + return X; +} diff --git a/torchvision/cmodels/alexnet.h b/torchvision/cmodels/alexnet.h new file mode 100644 index 00000000000..d302249424e --- /dev/null +++ b/torchvision/cmodels/alexnet.h @@ -0,0 +1,22 @@ +#ifndef ALEXNET_H +#define ALEXNET_H + +#include "visionimpl.h" + +namespace torchvision +{ +class AlexNetImpl : public torch::nn::Module +{ + torch::nn::Sequential features, classifier; + +public: + AlexNetImpl(int classes = 1000); + + torch::Tensor forward(torch::Tensor X); +}; + +TORCH_MODULE(AlexNet); + +} // namespace torchvision + +#endif // ALEXNET_H diff --git a/torchvision/cmodels/main.cpp b/torchvision/cmodels/main.cpp new file mode 100644 index 00000000000..8ede7cf1660 --- /dev/null +++ b/torchvision/cmodels/main.cpp @@ -0,0 +1,67 @@ +#include +#include "vision.h" + +using namespace torchvision; + +int main() +{ + auto X = torch::rand({1, 3, 224, 224}); + + AlexNet A; + A->forward(X); + std::cout << "AlexNet Done" << std::endl; + + VGG11 V11; + V11->forward(X); + std::cout << "VGG11 Done" << std::endl; + + VGG13 V13; + V13->forward(X); + std::cout << "VGG13 Done" << std::endl; + + VGG16 V16; + V16->forward(X); + std::cout << "VGG16 Done" << std::endl; + + VGG19 V19; + V19->forward(X); + std::cout << "VGG19 Done" << std::endl; + + VGG11BN V11BN; + V11BN->forward(X); + std::cout << "VGG11BN Done" << std::endl; + + VGG13BN V13BN; + V13BN->forward(X); + std::cout << "VGG13BN Done" << std::endl; + + VGG16BN V16BN; + V16BN->forward(X); + std::cout << "VGG16BN Done" << std::endl; + + VGG19BN V19BN; + V19BN->forward(X); + std::cout << "VGG19BN Done" << std::endl; + + ResNet18 R18; + R18->forward(X); + std::cout << "ResNet18 Done" << std::endl; + + ResNet34 R34; + R34->forward(X); + std::cout << "ResNet34 Done" << std::endl; + + ResNet50 R50; + R50->forward(X); + std::cout << "ResNet50 Done" << std::endl; + + ResNet101 R101; + R101->forward(X); + std::cout << "ResNet101 Done" << std::endl; + + ResNet152 R152; + R152->forward(X); + std::cout << "ResNet152 Done" << std::endl; + + return 0; +} diff --git a/torchvision/cmodels/resnet.cpp b/torchvision/cmodels/resnet.cpp new file mode 100644 index 00000000000..ce4557b0d87 --- /dev/null +++ b/torchvision/cmodels/resnet.cpp @@ -0,0 +1,122 @@ +#include "resnet.h" + +int torchvision::resnetimpl::BasicBlock::expantion = 1; +int torchvision::resnetimpl::Bottleneck::expantion = 4; + +torch::nn::Conv2d torchvision::resnetimpl::conv3x3(int64_t in, int64_t out, + int64_t stride) +{ + torch::nn::Conv2dOptions O(in, out, 3); + O.padding(1).stride(stride).with_bias(false); + return torch::nn::Conv2d(O); +} + +torch::nn::Conv2d torchvision::resnetimpl::conv1x1(int64_t in, int64_t out, + int64_t stride) +{ + torch::nn::Conv2dOptions O(in, out, 1); + O.stride(stride).with_bias(false); + return torch::nn::Conv2d(O); +} + +torchvision::resnetimpl::BasicBlock::BasicBlock( + int64_t inplanes, int64_t planes, int64_t stride, + torch::nn::Sequential downsample) + : stride(stride), + downsample(downsample), + conv1(conv3x3(inplanes, planes, stride)), + conv2(conv3x3(planes, planes)), + bn1(planes), + bn2(planes) +{ + register_module("conv1", conv1); + register_module("conv2", conv2); + + register_module("bn1", bn1); + register_module("bn2", bn2); + + if (!downsample.is_empty()) register_module("downsample", downsample); +} + +torch::Tensor torchvision::resnetimpl::BasicBlock::forward(at::Tensor X) +{ + auto identity = X; + + auto out = conv1->forward(X); + out = bn1->forward(out).relu_(); + + out = conv2->forward(out); + out = bn2->forward(out); + + if (!downsample.is_empty()) identity = downsample->forward(X); + + out += identity; + return out.relu_(); +} + +torchvision::resnetimpl::Bottleneck::Bottleneck( + int64_t inplanes, int64_t planes, int64_t stride, + torch::nn::Sequential downsample) + : stride(stride), + downsample(downsample), + conv1(conv1x1(inplanes, planes)), + conv2(conv3x3(planes, planes, stride)), + conv3(conv1x1(planes, planes * expantion)), + bn1(planes), + bn2(planes), + bn3(planes * expantion) +{ + register_module("conv1", conv1); + register_module("conv2", conv2); + register_module("conv3", conv3); + + register_module("bn1", bn1); + register_module("bn2", bn2); + register_module("bn3", bn3); + + if (!downsample.is_empty()) register_module("downsample", downsample); +} + +torch::Tensor torchvision::resnetimpl::Bottleneck::forward(at::Tensor X) +{ + auto identity = X; + + auto out = conv1->forward(X); + out = bn1->forward(out).relu_(); + + out = conv2->forward(out); + out = bn2->forward(out).relu_(); + + out = conv3->forward(out); + out = bn3->forward(out); + + if (!downsample.is_empty()) identity = downsample->forward(X); + + out += identity; + return out.relu_(); +} + +torchvision::ResNet18Impl::ResNet18Impl(int classes, bool zeroInitResidual) + : ResNetImpl({2, 2, 2, 2}, classes, zeroInitResidual) +{ +} + +torchvision::ResNet34Impl::ResNet34Impl(int classes, bool zeroInitResidual) + : ResNetImpl({3, 4, 6, 3}, classes, zeroInitResidual) +{ +} + +torchvision::ResNet50Impl::ResNet50Impl(int classes, bool zeroInitResidual) + : ResNetImpl({3, 4, 6, 3}, classes, zeroInitResidual) +{ +} + +torchvision::ResNet101Impl::ResNet101Impl(int classes, bool zeroInitResidual) + : ResNetImpl({3, 4, 23, 3}, classes, zeroInitResidual) +{ +} + +torchvision::ResNet152Impl::ResNet152Impl(int classes, bool zeroInitResidual) + : ResNetImpl({3, 8, 36, 3}, classes, zeroInitResidual) +{ +} diff --git a/torchvision/cmodels/resnet.h b/torchvision/cmodels/resnet.h new file mode 100644 index 00000000000..0c8e46025e9 --- /dev/null +++ b/torchvision/cmodels/resnet.h @@ -0,0 +1,190 @@ +#ifndef RESNET_H +#define RESNET_H + +#include "visionimpl.h" + +namespace torchvision +{ +template +class ResNetImpl; + +namespace resnetimpl +{ +torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride = 1); +torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride = 1); + +class BasicBlock : public torch::nn::Module +{ + template + friend class torchvision::ResNetImpl; + + int64_t stride; + torch::nn::Sequential downsample; + + torch::nn::Conv2d conv1, conv2; + torch::nn::BatchNorm bn1, bn2; + +public: + static int expantion; + + BasicBlock(int64_t inplanes, int64_t planes, int64_t stride = 1, + torch::nn::Sequential downsample = nullptr); + + torch::Tensor forward(torch::Tensor X); +}; + +class Bottleneck : public torch::nn::Module +{ + template + friend class torchvision::ResNetImpl; + + int64_t stride; + torch::nn::Sequential downsample; + + torch::nn::Conv2d conv1, conv2, conv3; + torch::nn::BatchNorm bn1, bn2, bn3; + +public: + static int expantion; + + Bottleneck(int64_t inplanes, int64_t planes, int64_t stride = 1, + torch::nn::Sequential downsample = nullptr); + + torch::Tensor forward(torch::Tensor X); +}; +} // namespace resnetimpl + +template +class ResNetImpl : public torch::nn::Module +{ + int64_t inplanes; + torch::nn::Conv2d conv1; + torch::nn::BatchNorm bn1; + torch::nn::Linear fc; + torch::nn::Sequential layer1, layer2, layer3, layer4; + + torch::nn::Sequential makeLayer(int64_t planes, int64_t blocks, + int64_t stride = 1); + +public: + ResNetImpl(const std::vector &layers, int classes = 1000, + bool zeroInitResidual = false); + + torch::Tensor forward(torch::Tensor X); +}; + +template +torch::nn::Sequential ResNetImpl::makeLayer(int64_t planes, + int64_t blocks, + int64_t stride) +{ + torch::nn::Sequential downsample = nullptr; + if (stride != 1 || inplanes != planes * Block::expantion) + { + downsample = torch::nn::Sequential( + resnetimpl::conv1x1(inplanes, planes * Block::expantion, stride), + torch::nn::BatchNorm(planes * Block::expantion)); + } + + torch::nn::Sequential layers; + layers->push_back(Block(inplanes, planes, stride, downsample)); + + inplanes = planes * Block::expantion; + + for (int i = 1; i < blocks; ++i) layers->push_back(Block(inplanes, planes)); + + return layers; +} + +template +ResNetImpl::ResNetImpl(const std::vector &layers, int classes, + bool zeroInitResidual) + : inplanes(64), + conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( + false)), + bn1(64), + layer1(makeLayer(64, layers[0])), + layer2(makeLayer(128, layers[1], 2)), + layer3(makeLayer(256, layers[2], 2)), + layer4(makeLayer(512, layers[3], 2)), + fc(512 * Block::expantion, classes) +{ + if (zeroInitResidual) + for (auto &module : modules(false)) + { + if (resnetimpl::Bottleneck *M = + dynamic_cast(module.get())) + torch::nn::init::constant_(M->bn3->weight, 0); + else if (resnetimpl::BasicBlock *M = + dynamic_cast(module.get())) + torch::nn::init::constant_(M->bn2->weight, 0); + } + + register_module("conv1", conv1); + register_module("bn1", bn1); + register_module("fc", fc); + + register_module("layer1", layer1); + register_module("layer2", layer2); + register_module("layer3", layer3); + register_module("layer4", layer4); +} + +template +torch::Tensor ResNetImpl::forward(at::Tensor X) +{ + X = conv1->forward(X); + X = bn1->forward(X).relu_(); + X = torch::max_pool2d(X, 3, 2, 1); + + X = layer1->forward(X); + X = layer2->forward(X); + X = layer3->forward(X); + X = layer4->forward(X); + + X = torch::adaptive_avg_pool2d(X, {1, 1}); + X = X.view({X.size(0), -1}); + X = fc->forward(X); + + return X; +} + +class ResNet18Impl : public ResNetImpl +{ +public: + ResNet18Impl(int classes = 1000, bool zeroInitResidual = false); +}; + +class ResNet34Impl : public ResNetImpl +{ +public: + ResNet34Impl(int classes = 1000, bool zeroInitResidual = false); +}; + +class ResNet50Impl : public ResNetImpl +{ +public: + ResNet50Impl(int classes = 1000, bool zeroInitResidual = false); +}; + +class ResNet101Impl : public ResNetImpl +{ +public: + ResNet101Impl(int classes = 1000, bool zeroInitResidual = false); +}; + +class ResNet152Impl : public ResNetImpl +{ +public: + ResNet152Impl(int classes = 1000, bool zeroInitResidual = false); +}; + +TORCH_MODULE(ResNet18); +TORCH_MODULE(ResNet34); +TORCH_MODULE(ResNet50); +TORCH_MODULE(ResNet101); +TORCH_MODULE(ResNet152); + +} // namespace torchvision + +#endif // RESNET_H diff --git a/torchvision/cmodels/vgg.cpp b/torchvision/cmodels/vgg.cpp new file mode 100644 index 00000000000..c528a029298 --- /dev/null +++ b/torchvision/cmodels/vgg.cpp @@ -0,0 +1,139 @@ +#include "vgg.h" + +void torchvision::VGGImpl::initializeWeights() +{ + for (auto &module : modules(false)) + { + if (torch::nn::Conv2dImpl *M = + dynamic_cast(module.get())) + { + torch::nn::init::xavier_normal_(M->weight); + torch::nn::init::constant_(M->bias, 0); + } + else if (torch::nn::BatchNormImpl *M = + dynamic_cast(module.get())) + { + torch::nn::init::constant_(M->weight, 1); + torch::nn::init::constant_(M->bias, 0); + } + else if (torch::nn::LinearImpl *M = + dynamic_cast(module.get())) + { + torch::nn::init::normal_(M->weight, 0, 0.01); + torch::nn::init::normal_(M->bias, 0); + } + } +} + +torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, int classes, + bool initWeights) +{ + // clang-format off + classifier = torch::nn::Sequential( + torch::nn::Linear(512 * 7 * 7, 4096), + visionimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, 4096), + visionimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, classes)); + // clang-format on + + this->features = features; + + register_module("features", features); + register_module("classifier", classifier); + + if (initWeights) initializeWeights(); +} + +torch::Tensor torchvision::VGGImpl::forward(at::Tensor X) +{ + X = features->forward(X); + X = X.view({X.size(0), -1}); + X = classifier->forward(X); + return X; +} + +torch::nn::Sequential torchvision::makeLayers(const std::vector &cfg, + bool batchNorm) +{ + torch::nn::Sequential seq; + auto channels = 3; + + for (const auto &V : cfg) + { + if (V <= -1) + seq->push_back(visionimpl::MaxPool(2, 2)); + else + { + seq->push_back(visionimpl::Conv(channels, V, 3, 1)); + if (batchNorm) seq->push_back(torch::nn::BatchNorm(V)); + seq->push_back(visionimpl::Relu(true)); + + channels = V; + } + } + + return seq; +} + +torchvision::VGG11Impl::VGG11Impl(int classes, bool initWeights) + : VGGImpl(makeLayers( + {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}), + classes, initWeights) +{ +} + +torchvision::VGG13Impl::VGG13Impl(int classes, bool initWeights) + : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, + 512, 512, -1}), + classes, initWeights) +{ +} + +torchvision::VGG16Impl::VGG16Impl(int classes, bool initWeights) + : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, + 512, -1, 512, 512, 512, -1}), + classes, initWeights) +{ +} + +torchvision::VGG19Impl::VGG19Impl(int classes, bool initWeights) + : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, + 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}), + classes, initWeights) +{ +} + +torchvision::VGG11BNImpl::VGG11BNImpl(int classes, bool initWeights) + : VGGImpl(makeLayers( + {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}, + true), + classes, initWeights) +{ +} + +torchvision::VGG13BNImpl::VGG13BNImpl(int classes, bool initWeights) + : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, + 512, 512, -1}, + true), + classes, initWeights) +{ +} + +torchvision::VGG16BNImpl::VGG16BNImpl(int classes, bool initWeights) + : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, + 512, -1, 512, 512, 512, -1}, + true), + classes, initWeights) +{ +} + +torchvision::VGG19BNImpl::VGG19BNImpl(int classes, bool initWeights) + : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, + 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}, + true), + classes, initWeights) +{ +} diff --git a/torchvision/cmodels/vgg.h b/torchvision/cmodels/vgg.h new file mode 100644 index 00000000000..add3a34cb11 --- /dev/null +++ b/torchvision/cmodels/vgg.h @@ -0,0 +1,85 @@ +#ifndef VGG_H +#define VGG_H + +#include "visionimpl.h" + +namespace torchvision +{ +class VGGImpl : public torch::nn::Module +{ + torch::nn::Sequential features; + torch::nn::Sequential classifier; + + void initializeWeights(); + +public: + VGGImpl(torch::nn::Sequential features, int classes = 1000, + bool initWeights = true); + + torch::Tensor forward(torch::Tensor X); +}; + +torch::nn::Sequential makeLayers(const std::vector &cfg, + bool batchNorm = false); + +class VGG11Impl : public VGGImpl +{ +public: + VGG11Impl(int classes = 1000, bool initWeights = true); +}; + +class VGG13Impl : public VGGImpl +{ +public: + VGG13Impl(int classes = 1000, bool initWeights = true); +}; + +class VGG16Impl : public VGGImpl +{ +public: + VGG16Impl(int classes = 1000, bool initWeights = true); +}; + +class VGG19Impl : public VGGImpl +{ +public: + VGG19Impl(int classes = 1000, bool initWeights = true); +}; + +class VGG11BNImpl : public VGGImpl +{ +public: + VGG11BNImpl(int classes = 1000, bool initWeights = true); +}; + +class VGG13BNImpl : public VGGImpl +{ +public: + VGG13BNImpl(int classes = 1000, bool initWeights = true); +}; + +class VGG16BNImpl : public VGGImpl +{ +public: + VGG16BNImpl(int classes = 1000, bool initWeights = true); +}; + +class VGG19BNImpl : public VGGImpl +{ +public: + VGG19BNImpl(int classes = 1000, bool initWeights = true); +}; + +TORCH_MODULE(VGG11); +TORCH_MODULE(VGG13); +TORCH_MODULE(VGG16); +TORCH_MODULE(VGG19); + +TORCH_MODULE(VGG11BN); +TORCH_MODULE(VGG13BN); +TORCH_MODULE(VGG16BN); +TORCH_MODULE(VGG19BN); + +} // namespace torchvision + +#endif // VGG_H diff --git a/torchvision/cmodels/vision.h b/torchvision/cmodels/vision.h new file mode 100644 index 00000000000..5ed842912a5 --- /dev/null +++ b/torchvision/cmodels/vision.h @@ -0,0 +1,8 @@ +#ifndef VISION_H +#define VISION_H + +#include "alexnet.h" +#include "resnet.h" +#include "vgg.h" + +#endif // VISION_H diff --git a/torchvision/cmodels/visionimpl.h b/torchvision/cmodels/visionimpl.h new file mode 100644 index 00000000000..54a082e7d1e --- /dev/null +++ b/torchvision/cmodels/visionimpl.h @@ -0,0 +1,67 @@ +#ifndef VISIONIMPL_H +#define VISIONIMPL_H + +#include + +namespace torchvision +{ +namespace visionimpl +{ +class Conv : public torch::nn::Conv2d +{ +public: + inline Conv(int64_t input, int64_t output, int64_t kernel, + int64_t padding = 0, int64_t stride = 1) + : Conv2d(torch::nn::Conv2dOptions(input, output, kernel) + .padding(padding) + .stride(stride)) + { + } +}; + +class ReluImpl : public torch::nn::Module +{ + bool inplace; + +public: + inline ReluImpl(bool inplace = false) + : torch::nn::Module(), inplace(inplace) + { + } + + inline torch::Tensor forward(torch::Tensor X) + { + if (inplace) + { + X.relu_(); + return X; + } + + return torch::relu(X); + } +}; + +class MaxPoolImpl : public torch::nn::Module +{ + int64_t kernel; + int64_t stride; + +public: + inline MaxPoolImpl(int64_t kernel, int64_t stride) + : torch::nn::Module(), kernel(kernel), stride(stride) + { + } + + inline torch::Tensor forward(torch::Tensor X) + { + return torch::max_pool2d(X, kernel, stride); + } +}; + +TORCH_MODULE(Relu); +TORCH_MODULE(MaxPool); + +} // namespace visionimpl +} // namespace torchvision + +#endif // VISIONIMPL_H From de9a8425e3b3b4ea1556601fd8eb587d014a1e0a Mon Sep 17 00:00:00 2001 From: Shahriar Date: Fri, 18 Jan 2019 01:54:27 +0330 Subject: [PATCH 02/48] Added squeezenet and fixed some stuff in the other models --- torchvision/cmodels/alexnet.cpp | 14 ++-- torchvision/cmodels/alexnet.h | 4 +- torchvision/cmodels/main.cpp | 10 +++ torchvision/cmodels/resnet.cpp | 37 +++++----- torchvision/cmodels/resnet.h | 48 ++++++------- torchvision/cmodels/squeezenet.cpp | 105 +++++++++++++++++++++++++++++ torchvision/cmodels/squeezenet.h | 52 ++++++++++++++ torchvision/cmodels/vgg.cpp | 58 ++++++++-------- torchvision/cmodels/vgg.h | 26 +++---- torchvision/cmodels/vision.h | 1 + torchvision/cmodels/visionimpl.h | 26 ++++++- 11 files changed, 287 insertions(+), 94 deletions(-) create mode 100644 torchvision/cmodels/squeezenet.cpp create mode 100644 torchvision/cmodels/squeezenet.h diff --git a/torchvision/cmodels/alexnet.cpp b/torchvision/cmodels/alexnet.cpp index 5921d35d982..eab183b764d 100644 --- a/torchvision/cmodels/alexnet.cpp +++ b/torchvision/cmodels/alexnet.cpp @@ -1,6 +1,6 @@ #include "alexnet.h" -torchvision::AlexNetImpl::AlexNetImpl(int classes) +torchvision::AlexNetImpl::AlexNetImpl(int num_classes) { // clang-format off features = torch::nn::Sequential( @@ -25,18 +25,18 @@ torchvision::AlexNetImpl::AlexNetImpl(int classes) torch::nn::Dropout(), torch::nn::Linear(4096, 4096), visionimpl::Relu(true), - torch::nn::Linear(4096, classes)); + torch::nn::Linear(4096, num_classes)); // clang-format on register_module("features", features); register_module("clasifier", classifier); } -torch::Tensor torchvision::AlexNetImpl::forward(at::Tensor X) +torch::Tensor torchvision::AlexNetImpl::forward(at::Tensor x) { - X = features->forward(X); - X = X.view({X.size(0), 256 * 6 * 6}); - X = classifier->forward(X); + x = features->forward(x); + x = x.view({x.size(0), 256 * 6 * 6}); + x = classifier->forward(x); - return X; + return x; } diff --git a/torchvision/cmodels/alexnet.h b/torchvision/cmodels/alexnet.h index d302249424e..464876c6ab1 100644 --- a/torchvision/cmodels/alexnet.h +++ b/torchvision/cmodels/alexnet.h @@ -10,9 +10,9 @@ class AlexNetImpl : public torch::nn::Module torch::nn::Sequential features, classifier; public: - AlexNetImpl(int classes = 1000); + AlexNetImpl(int num_classes = 1000); - torch::Tensor forward(torch::Tensor X); + torch::Tensor forward(torch::Tensor x); }; TORCH_MODULE(AlexNet); diff --git a/torchvision/cmodels/main.cpp b/torchvision/cmodels/main.cpp index 8ede7cf1660..4bf7187c059 100644 --- a/torchvision/cmodels/main.cpp +++ b/torchvision/cmodels/main.cpp @@ -3,6 +3,8 @@ using namespace torchvision; +// TODO change num_classes from int to int64_t + int main() { auto X = torch::rand({1, 3, 224, 224}); @@ -63,5 +65,13 @@ int main() R152->forward(X); std::cout << "ResNet152 Done" << std::endl; + SqueezeNet1_0 S10; + S10->forward(X); + std::cout << "SqueezeNet1.0 Done" << std::endl; + + SqueezeNet1_1 S11; + S11->forward(X); + std::cout << "SqueezeNet1.1 Done" << std::endl; + return 0; } diff --git a/torchvision/cmodels/resnet.cpp b/torchvision/cmodels/resnet.cpp index ce4557b0d87..b03cd0e5bc4 100644 --- a/torchvision/cmodels/resnet.cpp +++ b/torchvision/cmodels/resnet.cpp @@ -35,20 +35,20 @@ torchvision::resnetimpl::BasicBlock::BasicBlock( register_module("bn1", bn1); register_module("bn2", bn2); - if (!downsample.is_empty()) register_module("downsample", downsample); + if (!downsample.is_empty()) register_module("downsample", this->downsample); } -torch::Tensor torchvision::resnetimpl::BasicBlock::forward(at::Tensor X) +torch::Tensor torchvision::resnetimpl::BasicBlock::forward(at::Tensor x) { - auto identity = X; + auto identity = x; - auto out = conv1->forward(X); + auto out = conv1->forward(x); out = bn1->forward(out).relu_(); out = conv2->forward(out); out = bn2->forward(out); - if (!downsample.is_empty()) identity = downsample->forward(X); + if (!downsample.is_empty()) identity = downsample->forward(x); out += identity; return out.relu_(); @@ -74,7 +74,7 @@ torchvision::resnetimpl::Bottleneck::Bottleneck( register_module("bn2", bn2); register_module("bn3", bn3); - if (!downsample.is_empty()) register_module("downsample", downsample); + if (!downsample.is_empty()) register_module("downsample", this->downsample); } torch::Tensor torchvision::resnetimpl::Bottleneck::forward(at::Tensor X) @@ -96,27 +96,32 @@ torch::Tensor torchvision::resnetimpl::Bottleneck::forward(at::Tensor X) return out.relu_(); } -torchvision::ResNet18Impl::ResNet18Impl(int classes, bool zeroInitResidual) - : ResNetImpl({2, 2, 2, 2}, classes, zeroInitResidual) +torchvision::ResNet18Impl::ResNet18Impl(int num_classes, + bool zero_init_residual) + : ResNetImpl({2, 2, 2, 2}, num_classes, zero_init_residual) { } -torchvision::ResNet34Impl::ResNet34Impl(int classes, bool zeroInitResidual) - : ResNetImpl({3, 4, 6, 3}, classes, zeroInitResidual) +torchvision::ResNet34Impl::ResNet34Impl(int num_classes, + bool zero_init_residual) + : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet50Impl::ResNet50Impl(int classes, bool zeroInitResidual) - : ResNetImpl({3, 4, 6, 3}, classes, zeroInitResidual) +torchvision::ResNet50Impl::ResNet50Impl(int num_classes, + bool zero_init_residual) + : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet101Impl::ResNet101Impl(int classes, bool zeroInitResidual) - : ResNetImpl({3, 4, 23, 3}, classes, zeroInitResidual) +torchvision::ResNet101Impl::ResNet101Impl(int num_classes, + bool zero_init_residual) + : ResNetImpl({3, 4, 23, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet152Impl::ResNet152Impl(int classes, bool zeroInitResidual) - : ResNetImpl({3, 8, 36, 3}, classes, zeroInitResidual) +torchvision::ResNet152Impl::ResNet152Impl(int num_classes, + bool zero_init_residual) + : ResNetImpl({3, 8, 36, 3}, num_classes, zero_init_residual) { } diff --git a/torchvision/cmodels/resnet.h b/torchvision/cmodels/resnet.h index 0c8e46025e9..a9b547ac675 100644 --- a/torchvision/cmodels/resnet.h +++ b/torchvision/cmodels/resnet.h @@ -30,7 +30,7 @@ class BasicBlock : public torch::nn::Module BasicBlock(int64_t inplanes, int64_t planes, int64_t stride = 1, torch::nn::Sequential downsample = nullptr); - torch::Tensor forward(torch::Tensor X); + torch::Tensor forward(torch::Tensor x); }; class Bottleneck : public torch::nn::Module @@ -67,8 +67,8 @@ class ResNetImpl : public torch::nn::Module int64_t stride = 1); public: - ResNetImpl(const std::vector &layers, int classes = 1000, - bool zeroInitResidual = false); + ResNetImpl(const std::vector &layers, int num_classes = 1000, + bool zero_init_residual = false); torch::Tensor forward(torch::Tensor X); }; @@ -97,8 +97,8 @@ torch::nn::Sequential ResNetImpl::makeLayer(int64_t planes, } template -ResNetImpl::ResNetImpl(const std::vector &layers, int classes, - bool zeroInitResidual) +ResNetImpl::ResNetImpl(const std::vector &layers, int num_classes, + bool zero_init_residual) : inplanes(64), conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( false)), @@ -107,9 +107,9 @@ ResNetImpl::ResNetImpl(const std::vector &layers, int classes, layer2(makeLayer(128, layers[1], 2)), layer3(makeLayer(256, layers[2], 2)), layer4(makeLayer(512, layers[3], 2)), - fc(512 * Block::expantion, classes) + fc(512 * Block::expantion, num_classes) { - if (zeroInitResidual) + if (zero_init_residual) for (auto &module : modules(false)) { if (resnetimpl::Bottleneck *M = @@ -131,52 +131,52 @@ ResNetImpl::ResNetImpl(const std::vector &layers, int classes, } template -torch::Tensor ResNetImpl::forward(at::Tensor X) +torch::Tensor ResNetImpl::forward(at::Tensor x) { - X = conv1->forward(X); - X = bn1->forward(X).relu_(); - X = torch::max_pool2d(X, 3, 2, 1); + x = conv1->forward(x); + x = bn1->forward(x).relu_(); + x = torch::max_pool2d(x, 3, 2, 1); - X = layer1->forward(X); - X = layer2->forward(X); - X = layer3->forward(X); - X = layer4->forward(X); + x = layer1->forward(x); + x = layer2->forward(x); + x = layer3->forward(x); + x = layer4->forward(x); - X = torch::adaptive_avg_pool2d(X, {1, 1}); - X = X.view({X.size(0), -1}); - X = fc->forward(X); + x = torch::adaptive_avg_pool2d(x, {1, 1}); + x = x.view({x.size(0), -1}); + x = fc->forward(x); - return X; + return x; } class ResNet18Impl : public ResNetImpl { public: - ResNet18Impl(int classes = 1000, bool zeroInitResidual = false); + ResNet18Impl(int num_classes = 1000, bool zero_init_residual = false); }; class ResNet34Impl : public ResNetImpl { public: - ResNet34Impl(int classes = 1000, bool zeroInitResidual = false); + ResNet34Impl(int num_classes = 1000, bool zero_init_residual = false); }; class ResNet50Impl : public ResNetImpl { public: - ResNet50Impl(int classes = 1000, bool zeroInitResidual = false); + ResNet50Impl(int num_classes = 1000, bool zero_init_residual = false); }; class ResNet101Impl : public ResNetImpl { public: - ResNet101Impl(int classes = 1000, bool zeroInitResidual = false); + ResNet101Impl(int num_classes = 1000, bool zero_init_residual = false); }; class ResNet152Impl : public ResNetImpl { public: - ResNet152Impl(int classes = 1000, bool zeroInitResidual = false); + ResNet152Impl(int num_classes = 1000, bool zero_init_residual = false); }; TORCH_MODULE(ResNet18); diff --git a/torchvision/cmodels/squeezenet.cpp b/torchvision/cmodels/squeezenet.cpp new file mode 100644 index 00000000000..a9e3c1eac3a --- /dev/null +++ b/torchvision/cmodels/squeezenet.cpp @@ -0,0 +1,105 @@ +#include "squeezenet.h" + +torchvision::squeezenetimpl::Fire::Fire(int64_t inplanes, + int64_t squeeze_planes, + int64_t expand1x1_planes, + int64_t expand3x3_planes) + : inplanes(inplanes), + squeeze(torch::nn::Conv2dOptions(inplanes, squeeze_planes, 1)), + expand1x1(torch::nn::Conv2dOptions(squeeze_planes, expand1x1_planes, 1)), + expand3x3(torch::nn::Conv2dOptions(squeeze_planes, expand3x3_planes, 3) + .padding(1)) +{ + register_module("squeeze", squeeze); + register_module("expand1x1", expand1x1); + register_module("expand3x3", expand3x3); +} + +torch::Tensor torchvision::squeezenetimpl::Fire::forward(at::Tensor x) +{ + x = torch::relu(squeeze->forward(x)); + return torch::cat({torch::relu(expand1x1->forward(x)), + torch::relu(expand3x3->forward(x))}, + 1); +} + +torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int num_classes) + : num_classes(num_classes) +{ + // TODO change double compare + + if (version == 1.0) + { + features = torch::nn::Sequential( + torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), + visionimpl::Relu(true), visionimpl::MaxPool(3, 2, true), + squeezenetimpl::Fire(96, 16, 64, 64), + squeezenetimpl::Fire(128, 16, 64, 64), + squeezenetimpl::Fire(128, 32, 128, 128), + visionimpl::MaxPool(3, 2, true), + squeezenetimpl::Fire(256, 32, 128, 128), + squeezenetimpl::Fire(256, 48, 192, 192), + squeezenetimpl::Fire(384, 48, 192, 192), + squeezenetimpl::Fire(384, 64, 256, 256), + visionimpl::MaxPool(3, 2, true), + squeezenetimpl::Fire(512, 64, 256, 256)); + } + else if (version == 1.1) + { + features = torch::nn::Sequential( + torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), + visionimpl::Relu(true), visionimpl::MaxPool(3, 2, true), + squeezenetimpl::Fire(64, 16, 64, 64), + squeezenetimpl::Fire(128, 16, 64, 64), + visionimpl::MaxPool(3, 2, true), + squeezenetimpl::Fire(128, 32, 128, 128), + squeezenetimpl::Fire(256, 32, 128, 128), + visionimpl::MaxPool(3, 2, true), + squeezenetimpl::Fire(256, 48, 192, 192), + squeezenetimpl::Fire(384, 48, 192, 192), + squeezenetimpl::Fire(384, 64, 256, 256), + squeezenetimpl::Fire(512, 64, 256, 256)); + } + + auto final_conv = + torch::nn::Conv2d(torch::nn::Conv2dOptions(512, num_classes, 1)); + + classifier = torch::nn::Sequential( + torch::nn::Dropout(0.5), final_conv, visionimpl::Relu(true), + visionimpl::AdaptiveAvgPool2D(torch::IntList({1, 1}))); + + for (auto &module : modules(false)) + { + if (torch::nn::Conv2dImpl *M = + dynamic_cast(module.get())) + { + if (M == final_conv.get()) + torch::nn::init::normal_(M->weight, 0.0, 0.01); + else + torch::nn::init::xavier_uniform_( + M->weight); // TODO this should be kaiming + + if (M->options.with_bias()) torch::nn::init::constant_(M->bias, 0); + } + } + + register_module("features", features); + register_module("classifier", classifier); +} + +torch::Tensor torchvision::SqueezeNetImpl::forward(at::Tensor x) +{ + x = features->forward(x); + x = classifier->forward(x); + return x.view({x.size(0), num_classes}); +} + +torchvision::SqueezeNet1_0Impl::SqueezeNet1_0Impl(int num_classes) + : SqueezeNetImpl(1.0, num_classes) +{ +} + +torchvision::SqueezeNet1_1Impl::SqueezeNet1_1Impl(int num_classes) + : SqueezeNetImpl(1.1, num_classes) +{ +} diff --git a/torchvision/cmodels/squeezenet.h b/torchvision/cmodels/squeezenet.h new file mode 100644 index 00000000000..2d3226c59c1 --- /dev/null +++ b/torchvision/cmodels/squeezenet.h @@ -0,0 +1,52 @@ +#ifndef SQUEEZENET_H +#define SQUEEZENET_H + +#include "visionimpl.h" + +namespace torchvision +{ +namespace squeezenetimpl +{ +class Fire : public torch::nn::Module +{ + int64_t inplanes; + torch::nn::Conv2d squeeze, expand1x1, expand3x3; + +public: + Fire(int64_t inplanes, int64_t squeeze_planes, int64_t expand1x1_planes, + int64_t expand3x3_planes); + + torch::Tensor forward(torch::Tensor x); +}; + +} // namespace squeezenetimpl + +class SqueezeNetImpl : public torch::nn::Module +{ + int num_classes; + torch::nn::Sequential features, classifier; + +public: + SqueezeNetImpl(double version = 1.0, int num_classes = 1000); + + torch::Tensor forward(torch::Tensor x); +}; + +class SqueezeNet1_0Impl : public SqueezeNetImpl +{ +public: + SqueezeNet1_0Impl(int num_classes = 1000); +}; + +class SqueezeNet1_1Impl : public SqueezeNetImpl +{ +public: + SqueezeNet1_1Impl(int num_classes = 1000); +}; + +TORCH_MODULE(SqueezeNet1_0); +TORCH_MODULE(SqueezeNet1_1); + +} // namespace torchvision + +#endif // SQUEEZENET_H diff --git a/torchvision/cmodels/vgg.cpp b/torchvision/cmodels/vgg.cpp index c528a029298..247d94c9496 100644 --- a/torchvision/cmodels/vgg.cpp +++ b/torchvision/cmodels/vgg.cpp @@ -1,6 +1,6 @@ #include "vgg.h" -void torchvision::VGGImpl::initializeWeights() +void torchvision::VGGImpl::_initialize_weights() { for (auto &module : modules(false)) { @@ -25,8 +25,8 @@ void torchvision::VGGImpl::initializeWeights() } } -torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, int classes, - bool initWeights) +torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, int num_classes, + bool initialize_weights) { // clang-format off classifier = torch::nn::Sequential( @@ -36,27 +36,27 @@ torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, int classes, torch::nn::Linear(4096, 4096), visionimpl::Relu(true), torch::nn::Dropout(), - torch::nn::Linear(4096, classes)); + torch::nn::Linear(4096, num_classes)); // clang-format on this->features = features; - register_module("features", features); + register_module("features", this->features); register_module("classifier", classifier); - if (initWeights) initializeWeights(); + if (initialize_weights) _initialize_weights(); } -torch::Tensor torchvision::VGGImpl::forward(at::Tensor X) +torch::Tensor torchvision::VGGImpl::forward(at::Tensor x) { - X = features->forward(X); - X = X.view({X.size(0), -1}); - X = classifier->forward(X); - return X; + x = features->forward(x); + x = x.view({x.size(0), -1}); + x = classifier->forward(x); + return x; } torch::nn::Sequential torchvision::makeLayers(const std::vector &cfg, - bool batchNorm) + bool batch_norm) { torch::nn::Sequential seq; auto channels = 3; @@ -68,7 +68,7 @@ torch::nn::Sequential torchvision::makeLayers(const std::vector &cfg, else { seq->push_back(visionimpl::Conv(channels, V, 3, 1)); - if (batchNorm) seq->push_back(torch::nn::BatchNorm(V)); + if (batch_norm) seq->push_back(torch::nn::BatchNorm(V)); seq->push_back(visionimpl::Relu(true)); channels = V; @@ -78,62 +78,62 @@ torch::nn::Sequential torchvision::makeLayers(const std::vector &cfg, return seq; } -torchvision::VGG11Impl::VGG11Impl(int classes, bool initWeights) +torchvision::VGG11Impl::VGG11Impl(int num_classes, bool initialize_weights) : VGGImpl(makeLayers( {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}), - classes, initWeights) + num_classes, initialize_weights) { } -torchvision::VGG13Impl::VGG13Impl(int classes, bool initWeights) +torchvision::VGG13Impl::VGG13Impl(int num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}), - classes, initWeights) + num_classes, initWeights) { } -torchvision::VGG16Impl::VGG16Impl(int classes, bool initWeights) +torchvision::VGG16Impl::VGG16Impl(int num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}), - classes, initWeights) + num_classes, initWeights) { } -torchvision::VGG19Impl::VGG19Impl(int classes, bool initWeights) +torchvision::VGG19Impl::VGG19Impl(int num_classes, bool initialize_weights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}), - classes, initWeights) + num_classes, initialize_weights) { } -torchvision::VGG11BNImpl::VGG11BNImpl(int classes, bool initWeights) +torchvision::VGG11BNImpl::VGG11BNImpl(int num_classes, bool initWeights) : VGGImpl(makeLayers( {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}, true), - classes, initWeights) + num_classes, initWeights) { } -torchvision::VGG13BNImpl::VGG13BNImpl(int classes, bool initWeights) +torchvision::VGG13BNImpl::VGG13BNImpl(int num_classes, bool initialize_weights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}, true), - classes, initWeights) + num_classes, initialize_weights) { } -torchvision::VGG16BNImpl::VGG16BNImpl(int classes, bool initWeights) +torchvision::VGG16BNImpl::VGG16BNImpl(int num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}, true), - classes, initWeights) + num_classes, initWeights) { } -torchvision::VGG19BNImpl::VGG19BNImpl(int classes, bool initWeights) +torchvision::VGG19BNImpl::VGG19BNImpl(int num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}, true), - classes, initWeights) + num_classes, initWeights) { } diff --git a/torchvision/cmodels/vgg.h b/torchvision/cmodels/vgg.h index add3a34cb11..acf90b9d3ed 100644 --- a/torchvision/cmodels/vgg.h +++ b/torchvision/cmodels/vgg.h @@ -10,64 +10,64 @@ class VGGImpl : public torch::nn::Module torch::nn::Sequential features; torch::nn::Sequential classifier; - void initializeWeights(); + void _initialize_weights(); public: - VGGImpl(torch::nn::Sequential features, int classes = 1000, - bool initWeights = true); + VGGImpl(torch::nn::Sequential features, int num_classes = 1000, + bool initialize_weights = true); - torch::Tensor forward(torch::Tensor X); + torch::Tensor forward(torch::Tensor x); }; torch::nn::Sequential makeLayers(const std::vector &cfg, - bool batchNorm = false); + bool batch_norm = false); class VGG11Impl : public VGGImpl { public: - VGG11Impl(int classes = 1000, bool initWeights = true); + VGG11Impl(int num_classes = 1000, bool initialize_weights = true); }; class VGG13Impl : public VGGImpl { public: - VGG13Impl(int classes = 1000, bool initWeights = true); + VGG13Impl(int num_classes = 1000, bool initialize_weights = true); }; class VGG16Impl : public VGGImpl { public: - VGG16Impl(int classes = 1000, bool initWeights = true); + VGG16Impl(int num_classes = 1000, bool initialize_weights = true); }; class VGG19Impl : public VGGImpl { public: - VGG19Impl(int classes = 1000, bool initWeights = true); + VGG19Impl(int num_classes = 1000, bool initialize_weights = true); }; class VGG11BNImpl : public VGGImpl { public: - VGG11BNImpl(int classes = 1000, bool initWeights = true); + VGG11BNImpl(int num_classes = 1000, bool initialize_weights = true); }; class VGG13BNImpl : public VGGImpl { public: - VGG13BNImpl(int classes = 1000, bool initWeights = true); + VGG13BNImpl(int num_classes = 1000, bool initialize_weights = true); }; class VGG16BNImpl : public VGGImpl { public: - VGG16BNImpl(int classes = 1000, bool initWeights = true); + VGG16BNImpl(int num_classes = 1000, bool initialize_weights = true); }; class VGG19BNImpl : public VGGImpl { public: - VGG19BNImpl(int classes = 1000, bool initWeights = true); + VGG19BNImpl(int num_classes = 1000, bool initialize_weights = true); }; TORCH_MODULE(VGG11); diff --git a/torchvision/cmodels/vision.h b/torchvision/cmodels/vision.h index 5ed842912a5..1af6b36af81 100644 --- a/torchvision/cmodels/vision.h +++ b/torchvision/cmodels/vision.h @@ -3,6 +3,7 @@ #include "alexnet.h" #include "resnet.h" +#include "squeezenet.h" #include "vgg.h" #endif // VISION_H diff --git a/torchvision/cmodels/visionimpl.h b/torchvision/cmodels/visionimpl.h index 54a082e7d1e..00648a51d26 100644 --- a/torchvision/cmodels/visionimpl.h +++ b/torchvision/cmodels/visionimpl.h @@ -45,21 +45,41 @@ class MaxPoolImpl : public torch::nn::Module { int64_t kernel; int64_t stride; + bool ceil_mode; public: - inline MaxPoolImpl(int64_t kernel, int64_t stride) - : torch::nn::Module(), kernel(kernel), stride(stride) + inline MaxPoolImpl(int64_t kernel, int64_t stride, bool ceil_mode = false) + : torch::nn::Module(), + kernel(kernel), + stride(stride), + ceil_mode(ceil_mode) { } inline torch::Tensor forward(torch::Tensor X) { - return torch::max_pool2d(X, kernel, stride); + return torch::max_pool2d(X, kernel, stride, 0, 1, ceil_mode); + } +}; + +class AdaptiveAvgPool2DImpl : public torch::nn::Module +{ + torch::IntList output_size; + +public: + AdaptiveAvgPool2DImpl(torch::IntList output_size) : output_size(output_size) + { + } + + inline torch::Tensor forward(torch::Tensor x) + { + return torch::adaptive_avg_pool2d(x, output_size); } }; TORCH_MODULE(Relu); TORCH_MODULE(MaxPool); +TORCH_MODULE(AdaptiveAvgPool2D); } // namespace visionimpl } // namespace torchvision From eb5c277fa010e248b065384e00a78ef95f630ace Mon Sep 17 00:00:00 2001 From: Shahriar Date: Mon, 21 Jan 2019 20:22:00 +0330 Subject: [PATCH 03/48] Wrote DenseNet and a part of InceptionV3 Going to clean and check all of the models and finish inception --- torchvision/cmodels/alexnet.cpp | 39 ++- torchvision/cmodels/alexnet.h | 4 +- torchvision/cmodels/densenet.cpp | 148 +++++++++++ torchvision/cmodels/densenet.h | 91 +++++++ torchvision/cmodels/inception.cpp | 1 + torchvision/cmodels/inception.h | 405 +++++++++++++++++++++++++++++ torchvision/cmodels/main.cpp | 190 +++++++++----- torchvision/cmodels/squeezenet.cpp | 18 +- torchvision/cmodels/vgg.cpp | 6 +- torchvision/cmodels/vgg.h | 3 +- torchvision/cmodels/vision.h | 2 + torchvision/cmodels/visionimpl.h | 42 +-- 12 files changed, 835 insertions(+), 114 deletions(-) create mode 100644 torchvision/cmodels/densenet.cpp create mode 100644 torchvision/cmodels/densenet.h create mode 100644 torchvision/cmodels/inception.cpp create mode 100644 torchvision/cmodels/inception.h diff --git a/torchvision/cmodels/alexnet.cpp b/torchvision/cmodels/alexnet.cpp index eab183b764d..c5dd34a18ba 100644 --- a/torchvision/cmodels/alexnet.cpp +++ b/torchvision/cmodels/alexnet.cpp @@ -1,32 +1,25 @@ #include "alexnet.h" -torchvision::AlexNetImpl::AlexNetImpl(int num_classes) +torchvision::AlexNetImpl::AlexNetImpl(int64_t num_classes) { - // clang-format off features = torch::nn::Sequential( - visionimpl::Conv(3, 64, 11, 2, 4), - visionimpl::Relu(true), - visionimpl::MaxPool(3, 2), - visionimpl::Conv(64, 192, 5, 2), - visionimpl::Relu(true), - visionimpl::MaxPool(3, 2), - visionimpl::Conv(192, 384, 3, 1), - visionimpl::Relu(true), - visionimpl::Conv(384, 256, 3, 1), - visionimpl::Relu(true), - visionimpl::Conv(256, 256, 3, 1), - visionimpl::Relu(true), - visionimpl::MaxPool(3, 2)); + torch::nn::Conv2d( + torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), + visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2), + torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 192, 5).padding(2)), + visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2), + torch::nn::Conv2d(torch::nn::Conv2dOptions(192, 384, 3).padding(1)), + visionimpl::Relu(true), + torch::nn::Conv2d(torch::nn::Conv2dOptions(384, 256, 3).padding(1)), + visionimpl::Relu(true), + torch::nn::Conv2d(torch::nn::Conv2dOptions(256, 256, 3).padding(1)), + visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2)); classifier = torch::nn::Sequential( - torch::nn::Dropout(), - torch::nn::Linear(256 * 6 * 6, 4096), - visionimpl::Relu(true), - torch::nn::Dropout(), - torch::nn::Linear(4096, 4096), - visionimpl::Relu(true), - torch::nn::Linear(4096, num_classes)); - // clang-format on + torch::nn::Dropout(), torch::nn::Linear(256 * 6 * 6, 4096), + visionimpl::Relu(true), torch::nn::Dropout(), + torch::nn::Linear(4096, 4096), visionimpl::Relu(true), + torch::nn::Linear(4096, num_classes)); register_module("features", features); register_module("clasifier", classifier); diff --git a/torchvision/cmodels/alexnet.h b/torchvision/cmodels/alexnet.h index 464876c6ab1..a9e49a38df4 100644 --- a/torchvision/cmodels/alexnet.h +++ b/torchvision/cmodels/alexnet.h @@ -7,10 +7,10 @@ namespace torchvision { class AlexNetImpl : public torch::nn::Module { - torch::nn::Sequential features, classifier; + torch::nn::Sequential features{nullptr}, classifier{nullptr}; public: - AlexNetImpl(int num_classes = 1000); + AlexNetImpl(int64_t num_classes = 1000); torch::Tensor forward(torch::Tensor x); }; diff --git a/torchvision/cmodels/densenet.cpp b/torchvision/cmodels/densenet.cpp new file mode 100644 index 00000000000..88c2fc37fd7 --- /dev/null +++ b/torchvision/cmodels/densenet.cpp @@ -0,0 +1,148 @@ +#include "densenet.h" + +torchvision::densenetimpl::_DenseLayerImpl::_DenseLayerImpl( + int64_t num_input_features, int64_t growth_rate, int64_t bn_size, + double drop_rate) + : drop_rate(drop_rate) +{ + push_back(torch::nn::BatchNorm(num_input_features)); + push_back(visionimpl::Relu(true)); + push_back(torch::nn::Conv2d( + torch::nn::Conv2dOptions(num_input_features, bn_size * growth_rate, 1) + .stride(1) + .with_bias(false))); + push_back(torch::nn::BatchNorm(bn_size * growth_rate)); + push_back(visionimpl::Relu(true)); + push_back(torch::nn::Conv2d( + torch::nn::Conv2dOptions(bn_size * growth_rate, growth_rate, 3) + .stride(1) + .padding(1) + .with_bias(false))); +} + +torch::Tensor torchvision::densenetimpl::_DenseLayerImpl::forward(at::Tensor x) +{ + auto new_features = torch::nn::SequentialImpl::forward(x); + if (drop_rate > 0) + new_features = + torch::dropout(new_features, drop_rate, this->is_training()); + return torch::cat({x, new_features}, 1); +} + +torchvision::densenetimpl::_DenseBlockImpl::_DenseBlockImpl( + int64_t num_layers, int64_t num_input_features, int64_t bn_size, + int64_t growth_rate, double drop_rate) +{ + for (int64_t i = 0; i < num_layers; ++i) + { + auto layer = _DenseLayer(num_input_features + i * growth_rate, + growth_rate, bn_size, drop_rate); + push_back(layer); + } +} + +torch::Tensor torchvision::densenetimpl::_DenseBlockImpl::forward(at::Tensor x) +{ + return torch::nn::SequentialImpl::forward(x); +} + +torchvision::densenetimpl::_TransitionImpl::_TransitionImpl( + int64_t num_input_features, int64_t num_output_features) +{ + push_back(torch::nn::BatchNorm(num_input_features)); + push_back(visionimpl::Relu(true)); + push_back(torch::nn::Conv2d( + torch::nn::Conv2dOptions(num_input_features, num_output_features, 1) + .stride(1) + .with_bias(false))); + push_back(visionimpl::AvgPool2D(torch::IntList({2}), torch::IntList({2}))); +} + +torch::Tensor torchvision::densenetimpl::_TransitionImpl::forward(at::Tensor x) +{ + return torch::nn::SequentialImpl::forward(x); +} + +torchvision::DenseNetImpl::DenseNetImpl(int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, + int64_t bn_size, int64_t drop_rate, + int64_t num_classes) +{ + features = torch::nn::Sequential( + torch::nn::Conv2d(torch::nn::Conv2dOptions(3, num_init_features, 7) + .stride(2) + .padding(3) + .with_bias(false)), + torch::nn::BatchNorm(num_init_features), visionimpl::Relu(true), + visionimpl::MaxPool2D(3, 2, false, torch::IntList({1}))); + + auto num_features = num_init_features; + for (size_t i = 0; i < block_config.size(); ++i) + { + auto num_layers = block_config[i]; + auto block = densenetimpl::_DenseBlock(num_layers, num_features, + bn_size, growth_rate, drop_rate); + features->push_back(block); + num_features = num_features + num_layers * growth_rate; + + if (i != block_config.size() - 1) + { + auto trans = + densenetimpl::_Transition(num_features, num_features / 2); + features->push_back(trans); + num_features = num_features / 2; + } + } + + features->push_back(torch::nn::BatchNorm(num_features)); + classifier = torch::nn::Linear(num_features, num_classes); + + for (auto &module : modules(false)) + { + if (torch::nn::Conv2dImpl *M = + dynamic_cast(module.get())) + torch::nn::init::xavier_normal_(M->weight); + else if (torch::nn::BatchNormImpl *M = + dynamic_cast(module.get())) + { + torch::nn::init::constant_(M->weight, 1); + torch::nn::init::constant_(M->bias, 0); + } + else if (torch::nn::LinearImpl *M = + dynamic_cast(module.get())) + torch::nn::init::normal_(M->bias, 0); + } + + register_module("features", features); + register_module("classifier", classifier); +} + +torch::Tensor torchvision::DenseNetImpl::forward(at::Tensor x) +{ + auto features = this->features->forward(x); + auto out = torch::relu_(features); + out = torch::adaptive_avg_pool2d(out, {1, 1}).view({features.size(0), -1}); + out = this->classifier->forward(out); + return out; +} + +torchvision::DenseNet121Impl::DenseNet121Impl() + : DenseNetImpl(32, {6, 12, 32, 32}, 64) +{ +} + +torchvision::DenseNet169Impl::DenseNet169Impl() + : DenseNetImpl(32, {6, 12, 32, 32}, 64) +{ +} + +torchvision::DenseNet201Impl::DenseNet201Impl() + : DenseNetImpl(32, {6, 12, 48, 32}, 64) +{ +} + +torchvision::DenseNet161Impl::DenseNet161Impl() + : DenseNetImpl(48, {6, 12, 36, 24}, 96) +{ +} diff --git a/torchvision/cmodels/densenet.h b/torchvision/cmodels/densenet.h new file mode 100644 index 00000000000..1339a658be0 --- /dev/null +++ b/torchvision/cmodels/densenet.h @@ -0,0 +1,91 @@ +#ifndef DENSENET_H +#define DENSENET_H + +#include "visionimpl.h" + +namespace torchvision +{ +namespace densenetimpl +{ +// TODO give modules names in sequential subclasses +class _DenseLayerImpl : public torch::nn::SequentialImpl +{ + double drop_rate; + +public: + _DenseLayerImpl(int64_t num_input_features, int64_t growth_rate, + int64_t bn_size, double drop_rate); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(_DenseLayer); + +class _DenseBlockImpl : public torch::nn::SequentialImpl +{ +public: + _DenseBlockImpl(int64_t num_layers, int64_t num_input_features, + int64_t bn_size, int64_t growth_rate, double drop_rate); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(_DenseBlock); + +class _TransitionImpl : public torch::nn::SequentialImpl +{ +public: + _TransitionImpl(int64_t num_input_features, int64_t num_output_features); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(_Transition); +} // namespace densenetimpl + +class DenseNetImpl : public torch::nn::Module +{ + torch::nn::Sequential features{nullptr}; + torch::nn::Linear classifier{nullptr}; + +public: + DenseNetImpl(int64_t growth_rate = 32, + std::vector block_config = {6, 12, 24, 16}, + int64_t num_init_features = 64, int64_t bn_size = 4, + int64_t drop_rate = 0, int64_t num_classes = 1000); + + torch::Tensor forward(torch::Tensor x); +}; + +class DenseNet121Impl : public DenseNetImpl +{ +public: + DenseNet121Impl(); +}; + +class DenseNet169Impl : public DenseNetImpl +{ +public: + DenseNet169Impl(); +}; + +class DenseNet201Impl : public DenseNetImpl +{ +public: + DenseNet201Impl(); +}; + +class DenseNet161Impl : public DenseNetImpl +{ +public: + DenseNet161Impl(); +}; + +TORCH_MODULE(DenseNet121); +TORCH_MODULE(DenseNet169); +TORCH_MODULE(DenseNet201); +TORCH_MODULE(DenseNet161); + +} // namespace torchvision + +#endif // DENSENET_H diff --git a/torchvision/cmodels/inception.cpp b/torchvision/cmodels/inception.cpp new file mode 100644 index 00000000000..f9157440087 --- /dev/null +++ b/torchvision/cmodels/inception.cpp @@ -0,0 +1 @@ +#include "inception.h" diff --git a/torchvision/cmodels/inception.h b/torchvision/cmodels/inception.h new file mode 100644 index 00000000000..31055423e02 --- /dev/null +++ b/torchvision/cmodels/inception.h @@ -0,0 +1,405 @@ +#ifndef INCEPTION_H +#define INCEPTION_H + +#include "visionimpl.h" + +namespace torchvision +{ +namespace inceptionimpl +{ +class BasicConv2dImpl : public torch::nn::Module +{ + torch::nn::Conv2d conv; + torch::nn::BatchNorm bn; + +public: + BasicConv2dImpl(int64_t in_channels, int64_t out_channels, + torch::IntList kernel_size, torch::IntList padding = 0, + torch::IntList stride = 1) + : conv(torch::nn::Conv2dOptions(in_channels, out_channels, kernel_size) + .padding(padding) + .stride(stride) + .with_bias(false)), + bn(torch::nn::BatchNormOptions(out_channels).eps(0.001)) + { + register_module("conv", conv); + register_module("bn", bn); + } + + torch::Tensor forward(torch::Tensor x) + { + x = conv->forward(x); + x = bn->forward(x); + return torch::relu_(x); + } +}; + +TORCH_MODULE(BasicConv2d); + +class InceptionAImpl : public torch::nn::Module +{ + BasicConv2d branch1x1, branch5x5_1, branch5x5_2, branch3x3dbl_1, + branch3x3dbl_2, branch3x3dbl_3, branch_pool; + +public: + InceptionAImpl(int64_t in_channels, int64_t pool_features) + : branch1x1(in_channels, 64, 1), + branch5x5_1(in_channels, 48, 1), + branch5x5_2(48, 64, 5, 2), + branch3x3dbl_1(in_channels, 64, 1), + branch3x3dbl_2(64, 96, 3, 1), + branch3x3dbl_3(96, 96, 3, 1), + branch_pool(in_channels, pool_features, 1) + { + register_module("branch1x1", branch1x1); + register_module("branch5x5_1", branch5x5_1); + register_module("branch5x5_2", branch5x5_2); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3", branch3x3dbl_3); + register_module("branch_pool", branch_pool); + } + + torch::Tensor forward(torch::Tensor x) + { + auto branch1x1 = this->branch1x1->forward(x); + + auto branch5x5 = this->branch5x5_1->forward(x); + branch5x5 = this->branch5x5_2->forward(branch5x5); + + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); + + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + branch_pool = this->branch_pool->forward(branch_pool); + + return torch::cat({branch1x1, branch5x5, branch3x3dbl, branch_pool}, 1); + } +}; + +class InceptionBImpl : public torch::nn::Module +{ + BasicConv2d branch3x3, branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3; + +public: + InceptionBImpl(int64_t in_channels) + : branch3x3(in_channels, 384, 3, 0, 2), + branch3x3dbl_1(in_channels, 64, 1), + branch3x3dbl_2(64, 96, 3, 1), + branch3x3dbl_3(96, 96, 3, 0, 2) + { + register_module("branch3x3", branch3x3); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3", branch3x3dbl_3); + } + + torch::Tensor forward(torch::Tensor x) + { + auto branch3x3 = this->branch3x3->forward(x); + + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); + + auto branch_pool = torch::max_pool2d(x, 3, 2); + return torch::cat({branch3x3, branch3x3dbl, branch_pool}, 1); + } +}; + +class InceptionCImpl : public torch::nn::Module +{ + BasicConv2d branch1x1{nullptr}, branch7x7_1{nullptr}, branch7x7_2{nullptr}, + branch7x7_3{nullptr}, branch7x7dbl_1{nullptr}, branch7x7dbl_2{nullptr}, + branch7x7dbl_3{nullptr}, branch7x7dbl_4{nullptr}, + branch7x7dbl_5{nullptr}, branch_pool{nullptr}; + +public: + InceptionCImpl(int64_t in_channels, int64_t channels_7x7) + { + branch1x1 = BasicConv2d(in_channels, 192, 1); + + auto c7 = channels_7x7; + branch7x7_1 = BasicConv2d(in_channels, c7, 1); + branch7x7_2 = + BasicConv2d(c7, c7, torch::IntList({1, 7}), torch::IntList({0, 3})); + branch7x7_3 = BasicConv2d(c7, 192, torch::IntList({7, 1}), + torch::IntList({3, 0})); + + branch7x7dbl_1 = BasicConv2d(in_channels, c7, 1); + branch7x7dbl_2 = + BasicConv2d(c7, c7, torch::IntList({7, 1}), torch::IntList({3, 0})); + branch7x7dbl_3 = + BasicConv2d(c7, c7, torch::IntList({1, 7}), torch::IntList({0, 3})); + branch7x7dbl_4 = + BasicConv2d(c7, c7, torch::IntList({7, 1}), torch::IntList({3, 0})); + branch7x7dbl_5 = BasicConv2d(c7, 192, torch::IntList({1, 7}), + torch::IntList({0, 3})); + + branch_pool = BasicConv2d(in_channels, 192, 1); + + register_module("branch1x1", branch1x1); + register_module("branch7x7_1", branch7x7_1); + register_module("branch7x7_2", branch7x7_2); + register_module("branch7x7_3", branch7x7_3); + register_module("branch7x7dbl_1", branch7x7dbl_1); + register_module("branch7x7dbl_2", branch7x7dbl_2); + register_module("branch7x7dbl_3", branch7x7dbl_3); + register_module("branch7x7dbl_4", branch7x7dbl_4); + register_module("branch7x7dbl_5", branch7x7dbl_5); + register_module("branch_pool", branch_pool); + } + + torch::Tensor forward(torch::Tensor x) + { + auto branch1x1 = this->branch1x1->forward(x); + + auto branch7x7 = this->branch7x7_1->forward(x); + branch7x7 = this->branch7x7_2->forward(branch7x7); + branch7x7 = this->branch7x7_3->forward(branch7x7); + + auto branch7x7dbl = this->branch7x7dbl_1->forward(x); + branch7x7dbl = this->branch7x7dbl_2->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_3->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_4->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_5->forward(branch7x7dbl); + + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + branch_pool = this->branch_pool->forward(branch_pool); + + return torch::cat({branch1x1, branch7x7, branch7x7dbl, branch_pool}, 1); + } +}; + +class InceptionDImpl : public torch::nn::Module +{ + BasicConv2d branch3x3_1, branch3x3_2, branch7x7x3_1, branch7x7x3_2, + branch7x7x3_3, branch7x7x3_4; + +public: + InceptionDImpl(int64_t in_channels) + : branch3x3_1(in_channels, 192, 1), + branch3x3_2(192, 320, 3, 0, 2), + branch7x7x3_1(in_channels, 192, 1), + branch7x7x3_2(192, 192, torch::IntList({1, 7}), + torch::IntList({0, 3})), + branch7x7x3_3(192, 192, torch::IntList({7, 1}), + torch::IntList({3, 0})), + branch7x7x3_4(192, 192, 3, 0, 2) + + { + register_module("branch3x3_1", branch3x3_1); + register_module("branch3x3_2", branch3x3_2); + register_module("branch7x7x3_1", branch7x7x3_1); + register_module("branch7x7x3_2", branch7x7x3_2); + register_module("branch7x7x3_3", branch7x7x3_3); + register_module("branch7x7x3_4", branch7x7x3_4); + } + + torch::Tensor forward(torch::Tensor x) + { + auto branch3x3 = this->branch3x3_1->forward(x); + branch3x3 = this->branch3x3_2->forward(branch3x3); + + auto branch7x7x3 = this->branch7x7x3_1->forward(x); + branch7x7x3 = this->branch7x7x3_2->forward(branch3x3); + branch7x7x3 = this->branch7x7x3_3->forward(branch3x3); + branch7x7x3 = this->branch7x7x3_4->forward(branch3x3); + + auto branch_pool = torch::max_pool2d(x, 3, 2); + return torch::cat({branch3x3, branch7x7x3, branch_pool}, 1); + } +}; + +class InceptionEImpl : public torch::nn::Module +{ + BasicConv2d branch1x1, branch3x3_1, branch3x3_2a, branch3x3_2b, + branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3a, branch3x3dbl_3b, + branch_pool; + +public: + InceptionEImpl(int64_t in_channels) + : branch1x1(in_channels, 320, 1), + branch3x3_1(in_channels, 384, 1), + branch3x3_2a(384, 384, torch::IntList({1, 3}), + torch::IntList({0, 1})), + branch3x3_2b(384, 384, torch::IntList({3, 1}), + torch::IntList({1, 0})), + branch3x3dbl_1(in_channels, 448, 1), + branch3x3dbl_2(448, 384, 3, 1), + branch3x3dbl_3a(384, 384, torch::IntList({1, 3}), + torch::IntList({0, 1})), + branch3x3dbl_3b(384, 384, torch::IntList({3, 1}), + torch::IntList({1, 0})), + branch_pool(in_channels, 192, 1) + { + register_module("branch1x1", branch1x1); + register_module("branch3x3_1", branch3x3_1); + register_module("branch3x3_2a", branch3x3_2a); + register_module("branch3x3_2b", branch3x3_2b); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3a", branch3x3dbl_3a); + register_module("branch3x3dbl_3b", branch3x3dbl_3b); + register_module("branch_pool", branch_pool); + } + + torch::Tensor forward(torch::Tensor x) + { + auto branch1x1 = this->branch1x1->forward(x); + + auto branch3x3 = this->branch3x3_1->forward(x); + branch3x3 = torch::cat( + { + this->branch3x3_2a->forward(branch3x3), + this->branch3x3_2b->forward(branch3x3), + }, + 1); + + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = + torch::cat({this->branch3x3dbl_3a->forward(branch3x3dbl), + this->branch3x3dbl_3b->forward(branch3x3dbl)}, + 1); + + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + return torch::cat({branch1x1, branch3x3, branch3x3dbl, branch_pool}, 1); + } +}; + +class InceptionAuxImpl : public torch::nn::Module +{ + BasicConv2d conv0, conv1; + torch::nn::Linear fc; + +public: + InceptionAuxImpl(int64_t in_channels, int64_t num_classes) + : conv0(BasicConv2d(in_channels, 128, 1)), + conv1(BasicConv2d(128, 768, 5)), + fc(768, num_classes) + { + // TODO set these + // self.conv1.stddev = 0.01 + // self.fc.stddev = 0.001 + + register_module("conv0", conv0); + register_module("conv1", conv1); + register_module("fc", fc); + } + + torch::Tensor forward(torch::Tensor x) + { + x = torch::avg_pool2d(x, 5, 3); + x = conv0->forward(x); + x = conv1->forward(x); + x = x.view({x.size(0), -1}); + x = fc->forward(x); + return x; + } +}; + +TORCH_MODULE(InceptionA); +TORCH_MODULE(InceptionB); +TORCH_MODULE(InceptionC); +TORCH_MODULE(InceptionD); +TORCH_MODULE(InceptionE); +TORCH_MODULE(InceptionAux); + +} // namespace inceptionimpl + +class Inception_V3Impl : public torch::nn::Module +{ + bool aux_logits, transform_input; + inceptionimpl::BasicConv2d Conv2d_1a_3x3{nullptr}, Conv2d_2a_3x3{nullptr}, + Conv2d_2b_3x3{nullptr}, Conv2d_3b_1x1{nullptr}, Conv2d_4a_3x3{nullptr}; + inceptionimpl::InceptionA Mixed_5b{nullptr}, Mixed_5c{nullptr}, + Mixed_5d{nullptr}; + inceptionimpl::InceptionB Mixed_6a{nullptr}; + inceptionimpl::InceptionC Mixed_6b{nullptr}, Mixed_6c{nullptr}, + Mixed_6d{nullptr}, Mixed_6e{nullptr}; + inceptionimpl::InceptionD Mixed_7a{nullptr}; + inceptionimpl::InceptionE Mixed_7b{nullptr}, Mixed_7c{nullptr}; + torch::nn::Linear fc{nullptr}; + + inceptionimpl::InceptionAux AuxLogits{nullptr}; + +public: + Inception_V3Impl(int64_t num_classes = 1000, bool aux_logits = true, + bool transform_input = false) + : aux_logits(aux_logits), transform_input(transform_input) + { + Conv2d_1a_3x3 = inceptionimpl::BasicConv2d(3, 32, 3, 0, 2); + Conv2d_2a_3x3 = inceptionimpl::BasicConv2d(32, 32, 3); + Conv2d_2b_3x3 = inceptionimpl::BasicConv2d(32, 64, 3, 1); + Conv2d_3b_1x1 = inceptionimpl::BasicConv2d(64, 80, 1); + Conv2d_4a_3x3 = inceptionimpl::BasicConv2d(80, 192, 3); + + Mixed_5b = inceptionimpl::InceptionA(192, 32); + Mixed_5c = inceptionimpl::InceptionA(256, 64); + Mixed_5d = inceptionimpl::InceptionA(288, 64); + + Mixed_6a = inceptionimpl::InceptionB(288); + Mixed_6b = inceptionimpl::InceptionC(768, 128); + Mixed_6c = inceptionimpl::InceptionC(768, 160); + Mixed_6d = inceptionimpl::InceptionC(768, 160); + Mixed_6e = inceptionimpl::InceptionC(768, 192); + + if (aux_logits) + AuxLogits = inceptionimpl::InceptionAux(768, num_classes); + + Mixed_7a = inceptionimpl::InceptionD(768); + Mixed_7b = inceptionimpl::InceptionE(1280); + Mixed_7c = inceptionimpl::InceptionE(2048); + + fc = torch::nn::Linear(2048, num_classes); + + register_module("Conv2d_1a_3x3", Conv2d_1a_3x3); + register_module("Conv2d_2a_3x3", Conv2d_2a_3x3); + register_module("Conv2d_2b_3x3", Conv2d_2b_3x3); + register_module("Conv2d_3b_1x1", Conv2d_3b_1x1); + register_module("Conv2d_4a_3x3", Conv2d_4a_3x3); + register_module("Mixed_5b", Mixed_5b); + register_module("Mixed_5c", Mixed_5c); + register_module("Mixed_5d", Mixed_5d); + register_module("Mixed_6a", Mixed_6a); + register_module("Mixed_6b", Mixed_6b); + register_module("Mixed_6c", Mixed_6c); + register_module("Mixed_6d", Mixed_6d); + register_module("Mixed_6e", Mixed_6e); + + if (!AuxLogits.is_empty()) register_module("AuxLogits", AuxLogits); + + register_module("Mixed_7a", Mixed_7a); + register_module("Mixed_7b", Mixed_7b); + register_module("Mixed_7c", Mixed_7c); + register_module("fc", fc); + + // TODO + // for m in self.modules(): + // if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): + // import scipy.stats as stats + // stddev = m.stddev if hasattr(m, 'stddev') else 0.1 + // X = stats.truncnorm(-2, 2, scale=stddev) + // values = torch.Tensor(X.rvs(m.weight.numel())) + // values = values.view(m.weight.size()) + // m.weight.data.copy_(values) + // elif isinstance(m, nn.BatchNorm2d): + // nn.init.constant_(m.weight, 1) + // nn.init.constant_(m.bias, 0) + } + + torch::Tensor forward(torch::Tensor x) + { + if (transform_input) + { + } + } +}; + +TORCH_MODULE(Inception_V3); + +} // namespace torchvision + +#endif // INCEPTION_H diff --git a/torchvision/cmodels/main.cpp b/torchvision/cmodels/main.cpp index 4bf7187c059..a210be5bef1 100644 --- a/torchvision/cmodels/main.cpp +++ b/torchvision/cmodels/main.cpp @@ -4,74 +4,140 @@ using namespace torchvision; // TODO change num_classes from int to int64_t +// TODO in some classes I have initialized weights of submodules before +// registering them. this is wrong. fix it -int main() +template +long params(T &M) { - auto X = torch::rand({1, 3, 224, 224}); - - AlexNet A; - A->forward(X); - std::cout << "AlexNet Done" << std::endl; - - VGG11 V11; - V11->forward(X); - std::cout << "VGG11 Done" << std::endl; - - VGG13 V13; - V13->forward(X); - std::cout << "VGG13 Done" << std::endl; - - VGG16 V16; - V16->forward(X); - std::cout << "VGG16 Done" << std::endl; - - VGG19 V19; - V19->forward(X); - std::cout << "VGG19 Done" << std::endl; - - VGG11BN V11BN; - V11BN->forward(X); - std::cout << "VGG11BN Done" << std::endl; - - VGG13BN V13BN; - V13BN->forward(X); - std::cout << "VGG13BN Done" << std::endl; - - VGG16BN V16BN; - V16BN->forward(X); - std::cout << "VGG16BN Done" << std::endl; - - VGG19BN V19BN; - V19BN->forward(X); - std::cout << "VGG19BN Done" << std::endl; - - ResNet18 R18; - R18->forward(X); - std::cout << "ResNet18 Done" << std::endl; - - ResNet34 R34; - R34->forward(X); - std::cout << "ResNet34 Done" << std::endl; - - ResNet50 R50; - R50->forward(X); - std::cout << "ResNet50 Done" << std::endl; + long sum = 0; + for (const auto &P : M->parameters()) + { + long size = 1; + for (const auto &S : P.sizes()) size *= S; + sum += size; + } + + return sum; +} - ResNet101 R101; - R101->forward(X); - std::cout << "ResNet101 Done" << std::endl; +template +void process(torch::Tensor X, std::string name) +{ + T M; + M->forward(X); + std::cout << name + " Done. Params: " << params(M) << " : " + << params(M) / 1000000 << std::endl; +} - ResNet152 R152; - R152->forward(X); - std::cout << "ResNet152 Done" << std::endl; +#define PROCESS(M, X) process(X, #M) - SqueezeNet1_0 S10; - S10->forward(X); - std::cout << "SqueezeNet1.0 Done" << std::endl; +int main() +{ + auto X = torch::rand({1, 3, 224, 224}); - SqueezeNet1_1 S11; - S11->forward(X); - std::cout << "SqueezeNet1.1 Done" << std::endl; + // AlexNet A; + // A->forward(X); + // std::cout << "AlexNet Done. #Params: " << params(A) << std::endl; + + // VGG11 V11; + // V11->forward(X); + // std::cout << "VGG11 Done. #Params: " << params(V11) << std::endl; + + // VGG13 V13; + // V13->forward(X); + // std::cout << "VGG13 Done. #Params: " << params(V13) << std::endl; + + // VGG16 V16; + // V16->forward(X); + // std::cout << "VGG16 Done. #Params: " << params(V16) << std::endl; + + // VGG19 V19; + // V19->forward(X); + // std::cout << "VGG19 Done. #Params: " << params(V19) << std::endl; + + // VGG11BN V11BN; + // V11BN->forward(X); + // std::cout << "VGG11BN Done. #Params: " << params(V11BN) << std::endl; + + // VGG13BN V13BN; + // V13BN->forward(X); + // std::cout << "VGG13BN Done. #Params: " << params(V13BN) << std::endl; + + // VGG16BN V16BN; + // V16BN->forward(X); + // std::cout << "VGG16BN Done. #Params: " << params(V16BN) << std::endl; + + // VGG19BN V19BN; + // V19BN->forward(X); + // std::cout << "VGG19BN Done. #Params: " << params(V19BN) << std::endl; + + // ResNet18 R18; + // R18->forward(X); + // std::cout << "ResNet18 Done. #Params: " << params(R18) << std::endl; + + // ResNet34 R34; + // R34->forward(X); + // std::cout << "ResNet34 Done. #Params: " << params(R34) << std::endl; + + // ResNet50 R50; + // R50->forward(X); + // std::cout << "ResNet50 Done. #Params: " << params(R50) << std::endl; + + // ResNet101 R101; + // R101->forward(X); + // std::cout << "ResNet101 Done. #Params: " << params(R101) << std::endl; + + // ResNet152 R152; + // R152->forward(X); + // std::cout << "ResNet152 Done. #Params: " << params(R152) << std::endl; + + // SqueezeNet1_0 S10; + // S10->forward(X); + // std::cout << "SqueezeNet1.0 Done. #Params: " << params(S10) << + // std::endl; + + // SqueezeNet1_1 S11; + // S11->forward(X); + // std::cout << "SqueezeNet1.1 Done. #Params: " << params(S11) << + // std::endl; + + // DenseNet121 D121; + // D121->forward(X); + // std::cout << "DenseNet121 Done. #Params: " << params(D121) << std::endl; + + // DenseNet169 D169; + // D169->forward(X); + // std::cout << "DenseNet169 Done. #Params: " << params(D169) << std::endl; + + // DenseNet201 D201; + // D201->forward(X); + // std::cout << "DenseNet201 Done. #Params: " << params(D201) << std::endl; + + // DenseNet161 D161; + // D161->forward(X); + // std::cout << "DenseNet161 Done. #Params: " << params(D161) << std::endl; + + PROCESS(AlexNet, X); + PROCESS(VGG11, X); + PROCESS(VGG13, X); + PROCESS(VGG16, X); + PROCESS(VGG19, X); + PROCESS(VGG11BN, X); + PROCESS(VGG13BN, X); + PROCESS(VGG16BN, X); + PROCESS(VGG19BN, X); + PROCESS(ResNet18, X); + PROCESS(ResNet34, X); + PROCESS(ResNet50, X); + PROCESS(ResNet101, X); + PROCESS(ResNet152, X); + PROCESS(SqueezeNet1_0, X); + PROCESS(SqueezeNet1_1, X); + PROCESS(DenseNet121, X); + PROCESS(DenseNet169, X); + PROCESS(DenseNet201, X); + PROCESS(DenseNet161, X); return 0; } diff --git a/torchvision/cmodels/squeezenet.cpp b/torchvision/cmodels/squeezenet.cpp index a9e3c1eac3a..3c5aa7d7162 100644 --- a/torchvision/cmodels/squeezenet.cpp +++ b/torchvision/cmodels/squeezenet.cpp @@ -32,34 +32,40 @@ torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int num_classes) { features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), - visionimpl::Relu(true), visionimpl::MaxPool(3, 2, true), + visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(96, 16, 64, 64), squeezenetimpl::Fire(128, 16, 64, 64), squeezenetimpl::Fire(128, 32, 128, 128), - visionimpl::MaxPool(3, 2, true), + visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(256, 32, 128, 128), squeezenetimpl::Fire(256, 48, 192, 192), squeezenetimpl::Fire(384, 48, 192, 192), squeezenetimpl::Fire(384, 64, 256, 256), - visionimpl::MaxPool(3, 2, true), + visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(512, 64, 256, 256)); } else if (version == 1.1) { features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), - visionimpl::Relu(true), visionimpl::MaxPool(3, 2, true), + visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(64, 16, 64, 64), squeezenetimpl::Fire(128, 16, 64, 64), - visionimpl::MaxPool(3, 2, true), + visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(128, 32, 128, 128), squeezenetimpl::Fire(256, 32, 128, 128), - visionimpl::MaxPool(3, 2, true), + visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(256, 48, 192, 192), squeezenetimpl::Fire(384, 48, 192, 192), squeezenetimpl::Fire(384, 64, 256, 256), squeezenetimpl::Fire(512, 64, 256, 256)); } + else + { + std::cerr << "Wrong version number is passed th SqueeseNet constructor!" + << std::endl; + assert(false); + } auto final_conv = torch::nn::Conv2d(torch::nn::Conv2dOptions(512, num_classes, 1)); diff --git a/torchvision/cmodels/vgg.cpp b/torchvision/cmodels/vgg.cpp index 247d94c9496..b72dcb6a199 100644 --- a/torchvision/cmodels/vgg.cpp +++ b/torchvision/cmodels/vgg.cpp @@ -64,10 +64,12 @@ torch::nn::Sequential torchvision::makeLayers(const std::vector &cfg, for (const auto &V : cfg) { if (V <= -1) - seq->push_back(visionimpl::MaxPool(2, 2)); + seq->push_back(visionimpl::MaxPool2D(2, 2)); else { - seq->push_back(visionimpl::Conv(channels, V, 3, 1)); + seq->push_back(torch::nn::Conv2d( + torch::nn::Conv2dOptions(channels, V, 3).padding(1))); + if (batch_norm) seq->push_back(torch::nn::BatchNorm(V)); seq->push_back(visionimpl::Relu(true)); diff --git a/torchvision/cmodels/vgg.h b/torchvision/cmodels/vgg.h index acf90b9d3ed..edf41e8f9fd 100644 --- a/torchvision/cmodels/vgg.h +++ b/torchvision/cmodels/vgg.h @@ -7,8 +7,7 @@ namespace torchvision { class VGGImpl : public torch::nn::Module { - torch::nn::Sequential features; - torch::nn::Sequential classifier; + torch::nn::Sequential features{nullptr}, classifier{nullptr}; void _initialize_weights(); diff --git a/torchvision/cmodels/vision.h b/torchvision/cmodels/vision.h index 1af6b36af81..43d87bcc8df 100644 --- a/torchvision/cmodels/vision.h +++ b/torchvision/cmodels/vision.h @@ -2,6 +2,8 @@ #define VISION_H #include "alexnet.h" +#include "densenet.h" +#include "inception.h" #include "resnet.h" #include "squeezenet.h" #include "vgg.h" diff --git a/torchvision/cmodels/visionimpl.h b/torchvision/cmodels/visionimpl.h index 00648a51d26..88b0ba2e33f 100644 --- a/torchvision/cmodels/visionimpl.h +++ b/torchvision/cmodels/visionimpl.h @@ -7,18 +7,6 @@ namespace torchvision { namespace visionimpl { -class Conv : public torch::nn::Conv2d -{ -public: - inline Conv(int64_t input, int64_t output, int64_t kernel, - int64_t padding = 0, int64_t stride = 1) - : Conv2d(torch::nn::Conv2dOptions(input, output, kernel) - .padding(padding) - .stride(stride)) - { - } -}; - class ReluImpl : public torch::nn::Module { bool inplace; @@ -41,24 +29,27 @@ class ReluImpl : public torch::nn::Module } }; -class MaxPoolImpl : public torch::nn::Module +class MaxPool2DImpl : public torch::nn::Module { int64_t kernel; int64_t stride; bool ceil_mode; + torch::IntList padding; public: - inline MaxPoolImpl(int64_t kernel, int64_t stride, bool ceil_mode = false) + inline MaxPool2DImpl(int64_t kernel, int64_t stride, bool ceil_mode = false, + torch::IntList padding = torch::IntList({0})) : torch::nn::Module(), kernel(kernel), stride(stride), - ceil_mode(ceil_mode) + ceil_mode(ceil_mode), + padding(padding) { } inline torch::Tensor forward(torch::Tensor X) { - return torch::max_pool2d(X, kernel, stride, 0, 1, ceil_mode); + return torch::max_pool2d(X, kernel, stride, padding, 1, ceil_mode); } }; @@ -77,8 +68,25 @@ class AdaptiveAvgPool2DImpl : public torch::nn::Module } }; +class AvgPool2DImpl : public torch::nn::Module +{ + torch::IntList kernel_size, stride; + +public: + AvgPool2DImpl(torch::IntList kernel_size, torch::IntList stride) + : kernel_size(kernel_size), stride(stride) + { + } + + inline torch::Tensor forward(torch::Tensor x) + { + return torch::avg_pool2d(x, kernel_size, stride); + } +}; + TORCH_MODULE(Relu); -TORCH_MODULE(MaxPool); +TORCH_MODULE(MaxPool2D); +TORCH_MODULE(AvgPool2D); TORCH_MODULE(AdaptiveAvgPool2D); } // namespace visionimpl From 5da78be0fcb095c169dec93e7f329fc259c6b712 Mon Sep 17 00:00:00 2001 From: Shahriar Date: Mon, 21 Jan 2019 21:35:18 +0330 Subject: [PATCH 04/48] Fixed some errors in the models Next step is writing inception and comparing with python code again. --- torchvision/cmodels/alexnet.cpp | 39 +++++++++++++--------- torchvision/cmodels/densenet.cpp | 30 +++++++++-------- torchvision/cmodels/densenet.h | 8 ++--- torchvision/cmodels/main.cpp | 4 +-- torchvision/cmodels/resnet.cpp | 14 ++++---- torchvision/cmodels/resnet.h | 53 ++++++++++++++++++++---------- torchvision/cmodels/squeezenet.cpp | 50 +++++++++++++++++----------- torchvision/cmodels/squeezenet.h | 11 +++---- torchvision/cmodels/vgg.cpp | 43 ++++++++++++------------ torchvision/cmodels/vgg.h | 18 +++++----- 10 files changed, 152 insertions(+), 118 deletions(-) diff --git a/torchvision/cmodels/alexnet.cpp b/torchvision/cmodels/alexnet.cpp index c5dd34a18ba..5af0b3136f9 100644 --- a/torchvision/cmodels/alexnet.cpp +++ b/torchvision/cmodels/alexnet.cpp @@ -2,30 +2,37 @@ torchvision::AlexNetImpl::AlexNetImpl(int64_t num_classes) { + // clang-format off features = torch::nn::Sequential( - torch::nn::Conv2d( - torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), - visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2), - torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 192, 5).padding(2)), - visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2), - torch::nn::Conv2d(torch::nn::Conv2dOptions(192, 384, 3).padding(1)), - visionimpl::Relu(true), - torch::nn::Conv2d(torch::nn::Conv2dOptions(384, 256, 3).padding(1)), - visionimpl::Relu(true), - torch::nn::Conv2d(torch::nn::Conv2dOptions(256, 256, 3).padding(1)), - visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2)); + torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), + visionimpl::Relu(true), + visionimpl::MaxPool2D(3, 2), + torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 192, 5).padding(2)), + visionimpl::Relu(true), + visionimpl::MaxPool2D(3, 2), + torch::nn::Conv2d(torch::nn::Conv2dOptions(192, 384, 3).padding(1)), + visionimpl::Relu(true), + torch::nn::Conv2d(torch::nn::Conv2dOptions(384, 256, 3).padding(1)), + visionimpl::Relu(true), + torch::nn::Conv2d(torch::nn::Conv2dOptions(256, 256, 3).padding(1)), + visionimpl::Relu(true), + visionimpl::MaxPool2D(3, 2)); classifier = torch::nn::Sequential( - torch::nn::Dropout(), torch::nn::Linear(256 * 6 * 6, 4096), - visionimpl::Relu(true), torch::nn::Dropout(), - torch::nn::Linear(4096, 4096), visionimpl::Relu(true), - torch::nn::Linear(4096, num_classes)); + torch::nn::Dropout(), + torch::nn::Linear(256 * 6 * 6, 4096), + visionimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, 4096), + visionimpl::Relu(true), + torch::nn::Linear(4096, num_classes)); + // clang-format on register_module("features", features); register_module("clasifier", classifier); } -torch::Tensor torchvision::AlexNetImpl::forward(at::Tensor x) +torch::Tensor torchvision::AlexNetImpl::forward(torch::Tensor x) { x = features->forward(x); x = x.view({x.size(0), 256 * 6 * 6}); diff --git a/torchvision/cmodels/densenet.cpp b/torchvision/cmodels/densenet.cpp index 88c2fc37fd7..caecac0743d 100644 --- a/torchvision/cmodels/densenet.cpp +++ b/torchvision/cmodels/densenet.cpp @@ -20,7 +20,8 @@ torchvision::densenetimpl::_DenseLayerImpl::_DenseLayerImpl( .with_bias(false))); } -torch::Tensor torchvision::densenetimpl::_DenseLayerImpl::forward(at::Tensor x) +torch::Tensor torchvision::densenetimpl::_DenseLayerImpl::forward( + torch::Tensor x) { auto new_features = torch::nn::SequentialImpl::forward(x); if (drop_rate > 0) @@ -41,7 +42,8 @@ torchvision::densenetimpl::_DenseBlockImpl::_DenseBlockImpl( } } -torch::Tensor torchvision::densenetimpl::_DenseBlockImpl::forward(at::Tensor x) +torch::Tensor torchvision::densenetimpl::_DenseBlockImpl::forward( + torch::Tensor x) { return torch::nn::SequentialImpl::forward(x); } @@ -98,6 +100,9 @@ torchvision::DenseNetImpl::DenseNetImpl(int64_t growth_rate, features->push_back(torch::nn::BatchNorm(num_features)); classifier = torch::nn::Linear(num_features, num_classes); + register_module("features", features); + register_module("classifier", classifier); + for (auto &module : modules(false)) { if (torch::nn::Conv2dImpl *M = @@ -113,12 +118,9 @@ torchvision::DenseNetImpl::DenseNetImpl(int64_t growth_rate, dynamic_cast(module.get())) torch::nn::init::normal_(M->bias, 0); } - - register_module("features", features); - register_module("classifier", classifier); } -torch::Tensor torchvision::DenseNetImpl::forward(at::Tensor x) +torch::Tensor torchvision::DenseNetImpl::forward(torch::Tensor x) { auto features = this->features->forward(x); auto out = torch::relu_(features); @@ -127,22 +129,22 @@ torch::Tensor torchvision::DenseNetImpl::forward(at::Tensor x) return out; } -torchvision::DenseNet121Impl::DenseNet121Impl() - : DenseNetImpl(32, {6, 12, 32, 32}, 64) +torchvision::DenseNet121Impl::DenseNet121Impl(int64_t num_classes) + : DenseNetImpl(32, {6, 12, 32, 32}, 64, 4, 0, num_classes) { } -torchvision::DenseNet169Impl::DenseNet169Impl() - : DenseNetImpl(32, {6, 12, 32, 32}, 64) +torchvision::DenseNet169Impl::DenseNet169Impl(int64_t num_classes) + : DenseNetImpl(32, {6, 12, 32, 32}, 64, 4, 0, num_classes) { } -torchvision::DenseNet201Impl::DenseNet201Impl() - : DenseNetImpl(32, {6, 12, 48, 32}, 64) +torchvision::DenseNet201Impl::DenseNet201Impl(int64_t num_classes) + : DenseNetImpl(32, {6, 12, 48, 32}, 64, 4, 0, num_classes) { } -torchvision::DenseNet161Impl::DenseNet161Impl() - : DenseNetImpl(48, {6, 12, 36, 24}, 96) +torchvision::DenseNet161Impl::DenseNet161Impl(int64_t num_classes) + : DenseNetImpl(48, {6, 12, 36, 24}, 96, 4, 0, num_classes) { } diff --git a/torchvision/cmodels/densenet.h b/torchvision/cmodels/densenet.h index 1339a658be0..f43257bf846 100644 --- a/torchvision/cmodels/densenet.h +++ b/torchvision/cmodels/densenet.h @@ -60,25 +60,25 @@ class DenseNetImpl : public torch::nn::Module class DenseNet121Impl : public DenseNetImpl { public: - DenseNet121Impl(); + DenseNet121Impl(int64_t num_classes = 1000); }; class DenseNet169Impl : public DenseNetImpl { public: - DenseNet169Impl(); + DenseNet169Impl(int64_t num_classes = 1000); }; class DenseNet201Impl : public DenseNetImpl { public: - DenseNet201Impl(); + DenseNet201Impl(int64_t num_classes = 1000); }; class DenseNet161Impl : public DenseNetImpl { public: - DenseNet161Impl(); + DenseNet161Impl(int64_t num_classes = 1000); }; TORCH_MODULE(DenseNet121); diff --git a/torchvision/cmodels/main.cpp b/torchvision/cmodels/main.cpp index a210be5bef1..828fcc34058 100644 --- a/torchvision/cmodels/main.cpp +++ b/torchvision/cmodels/main.cpp @@ -3,9 +3,7 @@ using namespace torchvision; -// TODO change num_classes from int to int64_t -// TODO in some classes I have initialized weights of submodules before -// registering them. this is wrong. fix it +// TODO change xavier fill template long params(T &M) diff --git a/torchvision/cmodels/resnet.cpp b/torchvision/cmodels/resnet.cpp index b03cd0e5bc4..6a636bffb26 100644 --- a/torchvision/cmodels/resnet.cpp +++ b/torchvision/cmodels/resnet.cpp @@ -38,7 +38,7 @@ torchvision::resnetimpl::BasicBlock::BasicBlock( if (!downsample.is_empty()) register_module("downsample", this->downsample); } -torch::Tensor torchvision::resnetimpl::BasicBlock::forward(at::Tensor x) +torch::Tensor torchvision::resnetimpl::BasicBlock::forward(torch::Tensor x) { auto identity = x; @@ -77,7 +77,7 @@ torchvision::resnetimpl::Bottleneck::Bottleneck( if (!downsample.is_empty()) register_module("downsample", this->downsample); } -torch::Tensor torchvision::resnetimpl::Bottleneck::forward(at::Tensor X) +torch::Tensor torchvision::resnetimpl::Bottleneck::forward(torch::Tensor X) { auto identity = X; @@ -96,31 +96,31 @@ torch::Tensor torchvision::resnetimpl::Bottleneck::forward(at::Tensor X) return out.relu_(); } -torchvision::ResNet18Impl::ResNet18Impl(int num_classes, +torchvision::ResNet18Impl::ResNet18Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({2, 2, 2, 2}, num_classes, zero_init_residual) { } -torchvision::ResNet34Impl::ResNet34Impl(int num_classes, +torchvision::ResNet34Impl::ResNet34Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet50Impl::ResNet50Impl(int num_classes, +torchvision::ResNet50Impl::ResNet50Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet101Impl::ResNet101Impl(int num_classes, +torchvision::ResNet101Impl::ResNet101Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 4, 23, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet152Impl::ResNet152Impl(int num_classes, +torchvision::ResNet152Impl::ResNet152Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 8, 36, 3}, num_classes, zero_init_residual) { diff --git a/torchvision/cmodels/resnet.h b/torchvision/cmodels/resnet.h index a9b547ac675..8617b830651 100644 --- a/torchvision/cmodels/resnet.h +++ b/torchvision/cmodels/resnet.h @@ -67,7 +67,7 @@ class ResNetImpl : public torch::nn::Module int64_t stride = 1); public: - ResNetImpl(const std::vector &layers, int num_classes = 1000, + ResNetImpl(const std::vector &layers, int64_t num_classes = 1000, bool zero_init_residual = false); torch::Tensor forward(torch::Tensor X); @@ -78,6 +78,9 @@ torch::nn::Sequential ResNetImpl::makeLayer(int64_t planes, int64_t blocks, int64_t stride) { + // TODO Blocks that are created here are not shared_ptr. see if that is a + // problem (the layers in blocks are used in the resnet constructor). + torch::nn::Sequential downsample = nullptr; if (stride != 1 || inplanes != planes * Block::expantion) { @@ -97,8 +100,8 @@ torch::nn::Sequential ResNetImpl::makeLayer(int64_t planes, } template -ResNetImpl::ResNetImpl(const std::vector &layers, int num_classes, - bool zero_init_residual) +ResNetImpl::ResNetImpl(const std::vector &layers, + int64_t num_classes, bool zero_init_residual) : inplanes(64), conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( false)), @@ -109,6 +112,29 @@ ResNetImpl::ResNetImpl(const std::vector &layers, int num_classes, layer4(makeLayer(512, layers[3], 2)), fc(512 * Block::expantion, num_classes) { + register_module("conv1", conv1); + register_module("bn1", bn1); + register_module("fc", fc); + + register_module("layer1", layer1); + register_module("layer2", layer2); + register_module("layer3", layer3); + register_module("layer4", layer4); + + for (auto &module : modules(false)) + { + if (torch::nn::Conv2dImpl *M = + dynamic_cast(module.get())) + { + torch::nn::init::xavier_normal_(M->weight); + } + else if (torch::nn::BatchNormImpl *M = + dynamic_cast(module.get())) + { + torch::nn::init::constant_(M->weight, 1); + torch::nn::init::constant_(M->bias, 0); + } + } if (zero_init_residual) for (auto &module : modules(false)) { @@ -119,19 +145,10 @@ ResNetImpl::ResNetImpl(const std::vector &layers, int num_classes, dynamic_cast(module.get())) torch::nn::init::constant_(M->bn2->weight, 0); } - - register_module("conv1", conv1); - register_module("bn1", bn1); - register_module("fc", fc); - - register_module("layer1", layer1); - register_module("layer2", layer2); - register_module("layer3", layer3); - register_module("layer4", layer4); } template -torch::Tensor ResNetImpl::forward(at::Tensor x) +torch::Tensor ResNetImpl::forward(torch::Tensor x) { x = conv1->forward(x); x = bn1->forward(x).relu_(); @@ -152,31 +169,31 @@ torch::Tensor ResNetImpl::forward(at::Tensor x) class ResNet18Impl : public ResNetImpl { public: - ResNet18Impl(int num_classes = 1000, bool zero_init_residual = false); + ResNet18Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; class ResNet34Impl : public ResNetImpl { public: - ResNet34Impl(int num_classes = 1000, bool zero_init_residual = false); + ResNet34Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; class ResNet50Impl : public ResNetImpl { public: - ResNet50Impl(int num_classes = 1000, bool zero_init_residual = false); + ResNet50Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; class ResNet101Impl : public ResNetImpl { public: - ResNet101Impl(int num_classes = 1000, bool zero_init_residual = false); + ResNet101Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; class ResNet152Impl : public ResNetImpl { public: - ResNet152Impl(int num_classes = 1000, bool zero_init_residual = false); + ResNet152Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; TORCH_MODULE(ResNet18); diff --git a/torchvision/cmodels/squeezenet.cpp b/torchvision/cmodels/squeezenet.cpp index 3c5aa7d7162..eed737a31ce 100644 --- a/torchvision/cmodels/squeezenet.cpp +++ b/torchvision/cmodels/squeezenet.cpp @@ -1,11 +1,12 @@ #include "squeezenet.h" +#include + torchvision::squeezenetimpl::Fire::Fire(int64_t inplanes, int64_t squeeze_planes, int64_t expand1x1_planes, int64_t expand3x3_planes) - : inplanes(inplanes), - squeeze(torch::nn::Conv2dOptions(inplanes, squeeze_planes, 1)), + : squeeze(torch::nn::Conv2dOptions(inplanes, squeeze_planes, 1)), expand1x1(torch::nn::Conv2dOptions(squeeze_planes, expand1x1_planes, 1)), expand3x3(torch::nn::Conv2dOptions(squeeze_planes, expand3x3_planes, 3) .padding(1)) @@ -15,7 +16,7 @@ torchvision::squeezenetimpl::Fire::Fire(int64_t inplanes, register_module("expand3x3", expand3x3); } -torch::Tensor torchvision::squeezenetimpl::Fire::forward(at::Tensor x) +torch::Tensor torchvision::squeezenetimpl::Fire::forward(torch::Tensor x) { x = torch::relu(squeeze->forward(x)); return torch::cat({torch::relu(expand1x1->forward(x)), @@ -23,16 +24,20 @@ torch::Tensor torchvision::squeezenetimpl::Fire::forward(at::Tensor x) 1); } -torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int num_classes) +torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) : num_classes(num_classes) { - // TODO change double compare + auto double_compare = [](double a, double b) { + return double(std::abs(a - b)) < std::numeric_limits::epsilon(); + }; - if (version == 1.0) + if (double_compare(version, 1.0)) { + // clang-format off features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), - visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2, true), + visionimpl::Relu(true), + visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(96, 16, 64, 64), squeezenetimpl::Fire(128, 16, 64, 64), squeezenetimpl::Fire(128, 32, 128, 128), @@ -43,12 +48,15 @@ torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int num_classes) squeezenetimpl::Fire(384, 64, 256, 256), visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(512, 64, 256, 256)); + // clang-format on } - else if (version == 1.1) + else if (double_compare(version, 1.1)) { + // clang-format off features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), - visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2, true), + visionimpl::Relu(true), + visionimpl::MaxPool2D(3, 2, true), squeezenetimpl::Fire(64, 16, 64, 64), squeezenetimpl::Fire(128, 16, 64, 64), visionimpl::MaxPool2D(3, 2, true), @@ -59,6 +67,7 @@ torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int num_classes) squeezenetimpl::Fire(384, 48, 192, 192), squeezenetimpl::Fire(384, 64, 256, 256), squeezenetimpl::Fire(512, 64, 256, 256)); + // clang-format on } else { @@ -70,42 +79,43 @@ torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int num_classes) auto final_conv = torch::nn::Conv2d(torch::nn::Conv2dOptions(512, num_classes, 1)); + // clang-format off classifier = torch::nn::Sequential( - torch::nn::Dropout(0.5), final_conv, visionimpl::Relu(true), + torch::nn::Dropout(0.5), + final_conv, + visionimpl::Relu(true), visionimpl::AdaptiveAvgPool2D(torch::IntList({1, 1}))); + // clang-format on + + register_module("features", features); + register_module("classifier", classifier); for (auto &module : modules(false)) - { if (torch::nn::Conv2dImpl *M = dynamic_cast(module.get())) { if (M == final_conv.get()) torch::nn::init::normal_(M->weight, 0.0, 0.01); else - torch::nn::init::xavier_uniform_( - M->weight); // TODO this should be kaiming + torch::nn::init::xavier_uniform_(M->weight); if (M->options.with_bias()) torch::nn::init::constant_(M->bias, 0); } - } - - register_module("features", features); - register_module("classifier", classifier); } -torch::Tensor torchvision::SqueezeNetImpl::forward(at::Tensor x) +torch::Tensor torchvision::SqueezeNetImpl::forward(torch::Tensor x) { x = features->forward(x); x = classifier->forward(x); return x.view({x.size(0), num_classes}); } -torchvision::SqueezeNet1_0Impl::SqueezeNet1_0Impl(int num_classes) +torchvision::SqueezeNet1_0Impl::SqueezeNet1_0Impl(int64_t num_classes) : SqueezeNetImpl(1.0, num_classes) { } -torchvision::SqueezeNet1_1Impl::SqueezeNet1_1Impl(int num_classes) +torchvision::SqueezeNet1_1Impl::SqueezeNet1_1Impl(int64_t num_classes) : SqueezeNetImpl(1.1, num_classes) { } diff --git a/torchvision/cmodels/squeezenet.h b/torchvision/cmodels/squeezenet.h index 2d3226c59c1..470423ce9de 100644 --- a/torchvision/cmodels/squeezenet.h +++ b/torchvision/cmodels/squeezenet.h @@ -9,7 +9,6 @@ namespace squeezenetimpl { class Fire : public torch::nn::Module { - int64_t inplanes; torch::nn::Conv2d squeeze, expand1x1, expand3x3; public: @@ -23,11 +22,11 @@ class Fire : public torch::nn::Module class SqueezeNetImpl : public torch::nn::Module { - int num_classes; - torch::nn::Sequential features, classifier; + int64_t num_classes; + torch::nn::Sequential features{nullptr}, classifier{nullptr}; public: - SqueezeNetImpl(double version = 1.0, int num_classes = 1000); + SqueezeNetImpl(double version = 1.0, int64_t num_classes = 1000); torch::Tensor forward(torch::Tensor x); }; @@ -35,13 +34,13 @@ class SqueezeNetImpl : public torch::nn::Module class SqueezeNet1_0Impl : public SqueezeNetImpl { public: - SqueezeNet1_0Impl(int num_classes = 1000); + SqueezeNet1_0Impl(int64_t num_classes = 1000); }; class SqueezeNet1_1Impl : public SqueezeNetImpl { public: - SqueezeNet1_1Impl(int num_classes = 1000); + SqueezeNet1_1Impl(int64_t num_classes = 1000); }; TORCH_MODULE(SqueezeNet1_0); diff --git a/torchvision/cmodels/vgg.cpp b/torchvision/cmodels/vgg.cpp index b72dcb6a199..b6436542a6e 100644 --- a/torchvision/cmodels/vgg.cpp +++ b/torchvision/cmodels/vgg.cpp @@ -25,21 +25,21 @@ void torchvision::VGGImpl::_initialize_weights() } } -torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, int num_classes, - bool initialize_weights) +torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, + int64_t num_classes, bool initialize_weights) { - // clang-format off + // clang-format off classifier = torch::nn::Sequential( - torch::nn::Linear(512 * 7 * 7, 4096), - visionimpl::Relu(true), - torch::nn::Dropout(), - torch::nn::Linear(4096, 4096), - visionimpl::Relu(true), - torch::nn::Dropout(), - torch::nn::Linear(4096, num_classes)); - // clang-format on + torch::nn::Linear(512 * 7 * 7, 4096), + visionimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, 4096), + visionimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, num_classes)); + // clang-format on - this->features = features; + this->features = features; register_module("features", this->features); register_module("classifier", classifier); @@ -47,7 +47,7 @@ torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, int num_classes, if (initialize_weights) _initialize_weights(); } -torch::Tensor torchvision::VGGImpl::forward(at::Tensor x) +torch::Tensor torchvision::VGGImpl::forward(torch::Tensor x) { x = features->forward(x); x = x.view({x.size(0), -1}); @@ -80,35 +80,35 @@ torch::nn::Sequential torchvision::makeLayers(const std::vector &cfg, return seq; } -torchvision::VGG11Impl::VGG11Impl(int num_classes, bool initialize_weights) +torchvision::VGG11Impl::VGG11Impl(int64_t num_classes, bool initialize_weights) : VGGImpl(makeLayers( {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}), num_classes, initialize_weights) { } -torchvision::VGG13Impl::VGG13Impl(int num_classes, bool initWeights) +torchvision::VGG13Impl::VGG13Impl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}), num_classes, initWeights) { } -torchvision::VGG16Impl::VGG16Impl(int num_classes, bool initWeights) +torchvision::VGG16Impl::VGG16Impl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}), num_classes, initWeights) { } -torchvision::VGG19Impl::VGG19Impl(int num_classes, bool initialize_weights) +torchvision::VGG19Impl::VGG19Impl(int64_t num_classes, bool initialize_weights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}), num_classes, initialize_weights) { } -torchvision::VGG11BNImpl::VGG11BNImpl(int num_classes, bool initWeights) +torchvision::VGG11BNImpl::VGG11BNImpl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers( {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}, true), @@ -116,7 +116,8 @@ torchvision::VGG11BNImpl::VGG11BNImpl(int num_classes, bool initWeights) { } -torchvision::VGG13BNImpl::VGG13BNImpl(int num_classes, bool initialize_weights) +torchvision::VGG13BNImpl::VGG13BNImpl(int64_t num_classes, + bool initialize_weights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}, true), @@ -124,7 +125,7 @@ torchvision::VGG13BNImpl::VGG13BNImpl(int num_classes, bool initialize_weights) { } -torchvision::VGG16BNImpl::VGG16BNImpl(int num_classes, bool initWeights) +torchvision::VGG16BNImpl::VGG16BNImpl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}, true), @@ -132,7 +133,7 @@ torchvision::VGG16BNImpl::VGG16BNImpl(int num_classes, bool initWeights) { } -torchvision::VGG19BNImpl::VGG19BNImpl(int num_classes, bool initWeights) +torchvision::VGG19BNImpl::VGG19BNImpl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}, true), diff --git a/torchvision/cmodels/vgg.h b/torchvision/cmodels/vgg.h index edf41e8f9fd..06c47ef0810 100644 --- a/torchvision/cmodels/vgg.h +++ b/torchvision/cmodels/vgg.h @@ -12,7 +12,7 @@ class VGGImpl : public torch::nn::Module void _initialize_weights(); public: - VGGImpl(torch::nn::Sequential features, int num_classes = 1000, + VGGImpl(torch::nn::Sequential features, int64_t num_classes = 1000, bool initialize_weights = true); torch::Tensor forward(torch::Tensor x); @@ -24,49 +24,49 @@ torch::nn::Sequential makeLayers(const std::vector &cfg, class VGG11Impl : public VGGImpl { public: - VGG11Impl(int num_classes = 1000, bool initialize_weights = true); + VGG11Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; class VGG13Impl : public VGGImpl { public: - VGG13Impl(int num_classes = 1000, bool initialize_weights = true); + VGG13Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; class VGG16Impl : public VGGImpl { public: - VGG16Impl(int num_classes = 1000, bool initialize_weights = true); + VGG16Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; class VGG19Impl : public VGGImpl { public: - VGG19Impl(int num_classes = 1000, bool initialize_weights = true); + VGG19Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; class VGG11BNImpl : public VGGImpl { public: - VGG11BNImpl(int num_classes = 1000, bool initialize_weights = true); + VGG11BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; class VGG13BNImpl : public VGGImpl { public: - VGG13BNImpl(int num_classes = 1000, bool initialize_weights = true); + VGG13BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; class VGG16BNImpl : public VGGImpl { public: - VGG16BNImpl(int num_classes = 1000, bool initialize_weights = true); + VGG16BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; class VGG19BNImpl : public VGGImpl { public: - VGG19BNImpl(int num_classes = 1000, bool initialize_weights = true); + VGG19BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; TORCH_MODULE(VGG11); From de08ccae058d3fc12711c1f837ae0451eedf8705 Mon Sep 17 00:00:00 2001 From: Shahriar Date: Wed, 23 Jan 2019 01:14:34 +0330 Subject: [PATCH 05/48] Completed inception and changed models directory --- torchvision/CMakeLists.txt | 2 +- torchvision/cmodels/densenet.cpp | 150 ------- torchvision/cmodels/inception.cpp | 1 - torchvision/cmodels/inception.h | 405 ------------------ .../{cmodels => csrc/models}/alexnet.cpp | 10 +- .../{cmodels => csrc/models}/alexnet.h | 2 +- torchvision/csrc/models/densenet.cpp | 172 ++++++++ .../{cmodels => csrc/models}/densenet.h | 40 +- torchvision/csrc/models/inception.cpp | 374 ++++++++++++++++ torchvision/csrc/models/inception.h | 155 +++++++ torchvision/{cmodels => csrc/models}/main.cpp | 51 ++- .../{cmodels => csrc/models}/resnet.cpp | 78 ++-- torchvision/{cmodels => csrc/models}/resnet.h | 45 +- .../{cmodels => csrc/models}/squeezenet.cpp | 89 ++-- .../{cmodels => csrc/models}/squeezenet.h | 17 +- torchvision/{cmodels => csrc/models}/vgg.cpp | 81 ++-- torchvision/{cmodels => csrc/models}/vgg.h | 5 +- torchvision/{cmodels => csrc/models}/vision.h | 0 .../{cmodels => csrc/models}/visionimpl.h | 0 19 files changed, 899 insertions(+), 778 deletions(-) delete mode 100644 torchvision/cmodels/densenet.cpp delete mode 100644 torchvision/cmodels/inception.cpp delete mode 100644 torchvision/cmodels/inception.h rename torchvision/{cmodels => csrc/models}/alexnet.cpp (87%) rename torchvision/{cmodels => csrc/models}/alexnet.h (93%) create mode 100644 torchvision/csrc/models/densenet.cpp rename torchvision/{cmodels => csrc/models}/densenet.h (54%) create mode 100644 torchvision/csrc/models/inception.cpp create mode 100644 torchvision/csrc/models/inception.h rename torchvision/{cmodels => csrc/models}/main.cpp (81%) rename torchvision/{cmodels => csrc/models}/resnet.cpp (62%) rename torchvision/{cmodels => csrc/models}/resnet.h (80%) rename torchvision/{cmodels => csrc/models}/squeezenet.cpp (52%) rename torchvision/{cmodels => csrc/models}/squeezenet.h (66%) rename torchvision/{cmodels => csrc/models}/vgg.cpp (71%) rename torchvision/{cmodels => csrc/models}/vgg.h (92%) rename torchvision/{cmodels => csrc/models}/vision.h (100%) rename torchvision/{cmodels => csrc/models}/visionimpl.h (100%) diff --git a/torchvision/CMakeLists.txt b/torchvision/CMakeLists.txt index d0f06b9ef35..e19b93f357d 100644 --- a/torchvision/CMakeLists.txt +++ b/torchvision/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8) project(torchvision) set(CMAKE_CXX_STANDARD 11) -file(GLOB_RECURSE SOURCES cmodels/*.h cmodels/*.cpp) +file(GLOB_RECURSE SOURCES csrc/models/*.h csrc/models/*.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) set(CUDNN_INCLUDE_DIR /usr/include/cuda) diff --git a/torchvision/cmodels/densenet.cpp b/torchvision/cmodels/densenet.cpp deleted file mode 100644 index caecac0743d..00000000000 --- a/torchvision/cmodels/densenet.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "densenet.h" - -torchvision::densenetimpl::_DenseLayerImpl::_DenseLayerImpl( - int64_t num_input_features, int64_t growth_rate, int64_t bn_size, - double drop_rate) - : drop_rate(drop_rate) -{ - push_back(torch::nn::BatchNorm(num_input_features)); - push_back(visionimpl::Relu(true)); - push_back(torch::nn::Conv2d( - torch::nn::Conv2dOptions(num_input_features, bn_size * growth_rate, 1) - .stride(1) - .with_bias(false))); - push_back(torch::nn::BatchNorm(bn_size * growth_rate)); - push_back(visionimpl::Relu(true)); - push_back(torch::nn::Conv2d( - torch::nn::Conv2dOptions(bn_size * growth_rate, growth_rate, 3) - .stride(1) - .padding(1) - .with_bias(false))); -} - -torch::Tensor torchvision::densenetimpl::_DenseLayerImpl::forward( - torch::Tensor x) -{ - auto new_features = torch::nn::SequentialImpl::forward(x); - if (drop_rate > 0) - new_features = - torch::dropout(new_features, drop_rate, this->is_training()); - return torch::cat({x, new_features}, 1); -} - -torchvision::densenetimpl::_DenseBlockImpl::_DenseBlockImpl( - int64_t num_layers, int64_t num_input_features, int64_t bn_size, - int64_t growth_rate, double drop_rate) -{ - for (int64_t i = 0; i < num_layers; ++i) - { - auto layer = _DenseLayer(num_input_features + i * growth_rate, - growth_rate, bn_size, drop_rate); - push_back(layer); - } -} - -torch::Tensor torchvision::densenetimpl::_DenseBlockImpl::forward( - torch::Tensor x) -{ - return torch::nn::SequentialImpl::forward(x); -} - -torchvision::densenetimpl::_TransitionImpl::_TransitionImpl( - int64_t num_input_features, int64_t num_output_features) -{ - push_back(torch::nn::BatchNorm(num_input_features)); - push_back(visionimpl::Relu(true)); - push_back(torch::nn::Conv2d( - torch::nn::Conv2dOptions(num_input_features, num_output_features, 1) - .stride(1) - .with_bias(false))); - push_back(visionimpl::AvgPool2D(torch::IntList({2}), torch::IntList({2}))); -} - -torch::Tensor torchvision::densenetimpl::_TransitionImpl::forward(at::Tensor x) -{ - return torch::nn::SequentialImpl::forward(x); -} - -torchvision::DenseNetImpl::DenseNetImpl(int64_t growth_rate, - std::vector block_config, - int64_t num_init_features, - int64_t bn_size, int64_t drop_rate, - int64_t num_classes) -{ - features = torch::nn::Sequential( - torch::nn::Conv2d(torch::nn::Conv2dOptions(3, num_init_features, 7) - .stride(2) - .padding(3) - .with_bias(false)), - torch::nn::BatchNorm(num_init_features), visionimpl::Relu(true), - visionimpl::MaxPool2D(3, 2, false, torch::IntList({1}))); - - auto num_features = num_init_features; - for (size_t i = 0; i < block_config.size(); ++i) - { - auto num_layers = block_config[i]; - auto block = densenetimpl::_DenseBlock(num_layers, num_features, - bn_size, growth_rate, drop_rate); - features->push_back(block); - num_features = num_features + num_layers * growth_rate; - - if (i != block_config.size() - 1) - { - auto trans = - densenetimpl::_Transition(num_features, num_features / 2); - features->push_back(trans); - num_features = num_features / 2; - } - } - - features->push_back(torch::nn::BatchNorm(num_features)); - classifier = torch::nn::Linear(num_features, num_classes); - - register_module("features", features); - register_module("classifier", classifier); - - for (auto &module : modules(false)) - { - if (torch::nn::Conv2dImpl *M = - dynamic_cast(module.get())) - torch::nn::init::xavier_normal_(M->weight); - else if (torch::nn::BatchNormImpl *M = - dynamic_cast(module.get())) - { - torch::nn::init::constant_(M->weight, 1); - torch::nn::init::constant_(M->bias, 0); - } - else if (torch::nn::LinearImpl *M = - dynamic_cast(module.get())) - torch::nn::init::normal_(M->bias, 0); - } -} - -torch::Tensor torchvision::DenseNetImpl::forward(torch::Tensor x) -{ - auto features = this->features->forward(x); - auto out = torch::relu_(features); - out = torch::adaptive_avg_pool2d(out, {1, 1}).view({features.size(0), -1}); - out = this->classifier->forward(out); - return out; -} - -torchvision::DenseNet121Impl::DenseNet121Impl(int64_t num_classes) - : DenseNetImpl(32, {6, 12, 32, 32}, 64, 4, 0, num_classes) -{ -} - -torchvision::DenseNet169Impl::DenseNet169Impl(int64_t num_classes) - : DenseNetImpl(32, {6, 12, 32, 32}, 64, 4, 0, num_classes) -{ -} - -torchvision::DenseNet201Impl::DenseNet201Impl(int64_t num_classes) - : DenseNetImpl(32, {6, 12, 48, 32}, 64, 4, 0, num_classes) -{ -} - -torchvision::DenseNet161Impl::DenseNet161Impl(int64_t num_classes) - : DenseNetImpl(48, {6, 12, 36, 24}, 96, 4, 0, num_classes) -{ -} diff --git a/torchvision/cmodels/inception.cpp b/torchvision/cmodels/inception.cpp deleted file mode 100644 index f9157440087..00000000000 --- a/torchvision/cmodels/inception.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "inception.h" diff --git a/torchvision/cmodels/inception.h b/torchvision/cmodels/inception.h deleted file mode 100644 index 31055423e02..00000000000 --- a/torchvision/cmodels/inception.h +++ /dev/null @@ -1,405 +0,0 @@ -#ifndef INCEPTION_H -#define INCEPTION_H - -#include "visionimpl.h" - -namespace torchvision -{ -namespace inceptionimpl -{ -class BasicConv2dImpl : public torch::nn::Module -{ - torch::nn::Conv2d conv; - torch::nn::BatchNorm bn; - -public: - BasicConv2dImpl(int64_t in_channels, int64_t out_channels, - torch::IntList kernel_size, torch::IntList padding = 0, - torch::IntList stride = 1) - : conv(torch::nn::Conv2dOptions(in_channels, out_channels, kernel_size) - .padding(padding) - .stride(stride) - .with_bias(false)), - bn(torch::nn::BatchNormOptions(out_channels).eps(0.001)) - { - register_module("conv", conv); - register_module("bn", bn); - } - - torch::Tensor forward(torch::Tensor x) - { - x = conv->forward(x); - x = bn->forward(x); - return torch::relu_(x); - } -}; - -TORCH_MODULE(BasicConv2d); - -class InceptionAImpl : public torch::nn::Module -{ - BasicConv2d branch1x1, branch5x5_1, branch5x5_2, branch3x3dbl_1, - branch3x3dbl_2, branch3x3dbl_3, branch_pool; - -public: - InceptionAImpl(int64_t in_channels, int64_t pool_features) - : branch1x1(in_channels, 64, 1), - branch5x5_1(in_channels, 48, 1), - branch5x5_2(48, 64, 5, 2), - branch3x3dbl_1(in_channels, 64, 1), - branch3x3dbl_2(64, 96, 3, 1), - branch3x3dbl_3(96, 96, 3, 1), - branch_pool(in_channels, pool_features, 1) - { - register_module("branch1x1", branch1x1); - register_module("branch5x5_1", branch5x5_1); - register_module("branch5x5_2", branch5x5_2); - register_module("branch3x3dbl_1", branch3x3dbl_1); - register_module("branch3x3dbl_2", branch3x3dbl_2); - register_module("branch3x3dbl_3", branch3x3dbl_3); - register_module("branch_pool", branch_pool); - } - - torch::Tensor forward(torch::Tensor x) - { - auto branch1x1 = this->branch1x1->forward(x); - - auto branch5x5 = this->branch5x5_1->forward(x); - branch5x5 = this->branch5x5_2->forward(branch5x5); - - auto branch3x3dbl = this->branch3x3dbl_1->forward(x); - branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); - branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); - - auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); - branch_pool = this->branch_pool->forward(branch_pool); - - return torch::cat({branch1x1, branch5x5, branch3x3dbl, branch_pool}, 1); - } -}; - -class InceptionBImpl : public torch::nn::Module -{ - BasicConv2d branch3x3, branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3; - -public: - InceptionBImpl(int64_t in_channels) - : branch3x3(in_channels, 384, 3, 0, 2), - branch3x3dbl_1(in_channels, 64, 1), - branch3x3dbl_2(64, 96, 3, 1), - branch3x3dbl_3(96, 96, 3, 0, 2) - { - register_module("branch3x3", branch3x3); - register_module("branch3x3dbl_1", branch3x3dbl_1); - register_module("branch3x3dbl_2", branch3x3dbl_2); - register_module("branch3x3dbl_3", branch3x3dbl_3); - } - - torch::Tensor forward(torch::Tensor x) - { - auto branch3x3 = this->branch3x3->forward(x); - - auto branch3x3dbl = this->branch3x3dbl_1->forward(x); - branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); - branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); - - auto branch_pool = torch::max_pool2d(x, 3, 2); - return torch::cat({branch3x3, branch3x3dbl, branch_pool}, 1); - } -}; - -class InceptionCImpl : public torch::nn::Module -{ - BasicConv2d branch1x1{nullptr}, branch7x7_1{nullptr}, branch7x7_2{nullptr}, - branch7x7_3{nullptr}, branch7x7dbl_1{nullptr}, branch7x7dbl_2{nullptr}, - branch7x7dbl_3{nullptr}, branch7x7dbl_4{nullptr}, - branch7x7dbl_5{nullptr}, branch_pool{nullptr}; - -public: - InceptionCImpl(int64_t in_channels, int64_t channels_7x7) - { - branch1x1 = BasicConv2d(in_channels, 192, 1); - - auto c7 = channels_7x7; - branch7x7_1 = BasicConv2d(in_channels, c7, 1); - branch7x7_2 = - BasicConv2d(c7, c7, torch::IntList({1, 7}), torch::IntList({0, 3})); - branch7x7_3 = BasicConv2d(c7, 192, torch::IntList({7, 1}), - torch::IntList({3, 0})); - - branch7x7dbl_1 = BasicConv2d(in_channels, c7, 1); - branch7x7dbl_2 = - BasicConv2d(c7, c7, torch::IntList({7, 1}), torch::IntList({3, 0})); - branch7x7dbl_3 = - BasicConv2d(c7, c7, torch::IntList({1, 7}), torch::IntList({0, 3})); - branch7x7dbl_4 = - BasicConv2d(c7, c7, torch::IntList({7, 1}), torch::IntList({3, 0})); - branch7x7dbl_5 = BasicConv2d(c7, 192, torch::IntList({1, 7}), - torch::IntList({0, 3})); - - branch_pool = BasicConv2d(in_channels, 192, 1); - - register_module("branch1x1", branch1x1); - register_module("branch7x7_1", branch7x7_1); - register_module("branch7x7_2", branch7x7_2); - register_module("branch7x7_3", branch7x7_3); - register_module("branch7x7dbl_1", branch7x7dbl_1); - register_module("branch7x7dbl_2", branch7x7dbl_2); - register_module("branch7x7dbl_3", branch7x7dbl_3); - register_module("branch7x7dbl_4", branch7x7dbl_4); - register_module("branch7x7dbl_5", branch7x7dbl_5); - register_module("branch_pool", branch_pool); - } - - torch::Tensor forward(torch::Tensor x) - { - auto branch1x1 = this->branch1x1->forward(x); - - auto branch7x7 = this->branch7x7_1->forward(x); - branch7x7 = this->branch7x7_2->forward(branch7x7); - branch7x7 = this->branch7x7_3->forward(branch7x7); - - auto branch7x7dbl = this->branch7x7dbl_1->forward(x); - branch7x7dbl = this->branch7x7dbl_2->forward(branch7x7dbl); - branch7x7dbl = this->branch7x7dbl_3->forward(branch7x7dbl); - branch7x7dbl = this->branch7x7dbl_4->forward(branch7x7dbl); - branch7x7dbl = this->branch7x7dbl_5->forward(branch7x7dbl); - - auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); - branch_pool = this->branch_pool->forward(branch_pool); - - return torch::cat({branch1x1, branch7x7, branch7x7dbl, branch_pool}, 1); - } -}; - -class InceptionDImpl : public torch::nn::Module -{ - BasicConv2d branch3x3_1, branch3x3_2, branch7x7x3_1, branch7x7x3_2, - branch7x7x3_3, branch7x7x3_4; - -public: - InceptionDImpl(int64_t in_channels) - : branch3x3_1(in_channels, 192, 1), - branch3x3_2(192, 320, 3, 0, 2), - branch7x7x3_1(in_channels, 192, 1), - branch7x7x3_2(192, 192, torch::IntList({1, 7}), - torch::IntList({0, 3})), - branch7x7x3_3(192, 192, torch::IntList({7, 1}), - torch::IntList({3, 0})), - branch7x7x3_4(192, 192, 3, 0, 2) - - { - register_module("branch3x3_1", branch3x3_1); - register_module("branch3x3_2", branch3x3_2); - register_module("branch7x7x3_1", branch7x7x3_1); - register_module("branch7x7x3_2", branch7x7x3_2); - register_module("branch7x7x3_3", branch7x7x3_3); - register_module("branch7x7x3_4", branch7x7x3_4); - } - - torch::Tensor forward(torch::Tensor x) - { - auto branch3x3 = this->branch3x3_1->forward(x); - branch3x3 = this->branch3x3_2->forward(branch3x3); - - auto branch7x7x3 = this->branch7x7x3_1->forward(x); - branch7x7x3 = this->branch7x7x3_2->forward(branch3x3); - branch7x7x3 = this->branch7x7x3_3->forward(branch3x3); - branch7x7x3 = this->branch7x7x3_4->forward(branch3x3); - - auto branch_pool = torch::max_pool2d(x, 3, 2); - return torch::cat({branch3x3, branch7x7x3, branch_pool}, 1); - } -}; - -class InceptionEImpl : public torch::nn::Module -{ - BasicConv2d branch1x1, branch3x3_1, branch3x3_2a, branch3x3_2b, - branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3a, branch3x3dbl_3b, - branch_pool; - -public: - InceptionEImpl(int64_t in_channels) - : branch1x1(in_channels, 320, 1), - branch3x3_1(in_channels, 384, 1), - branch3x3_2a(384, 384, torch::IntList({1, 3}), - torch::IntList({0, 1})), - branch3x3_2b(384, 384, torch::IntList({3, 1}), - torch::IntList({1, 0})), - branch3x3dbl_1(in_channels, 448, 1), - branch3x3dbl_2(448, 384, 3, 1), - branch3x3dbl_3a(384, 384, torch::IntList({1, 3}), - torch::IntList({0, 1})), - branch3x3dbl_3b(384, 384, torch::IntList({3, 1}), - torch::IntList({1, 0})), - branch_pool(in_channels, 192, 1) - { - register_module("branch1x1", branch1x1); - register_module("branch3x3_1", branch3x3_1); - register_module("branch3x3_2a", branch3x3_2a); - register_module("branch3x3_2b", branch3x3_2b); - register_module("branch3x3dbl_1", branch3x3dbl_1); - register_module("branch3x3dbl_2", branch3x3dbl_2); - register_module("branch3x3dbl_3a", branch3x3dbl_3a); - register_module("branch3x3dbl_3b", branch3x3dbl_3b); - register_module("branch_pool", branch_pool); - } - - torch::Tensor forward(torch::Tensor x) - { - auto branch1x1 = this->branch1x1->forward(x); - - auto branch3x3 = this->branch3x3_1->forward(x); - branch3x3 = torch::cat( - { - this->branch3x3_2a->forward(branch3x3), - this->branch3x3_2b->forward(branch3x3), - }, - 1); - - auto branch3x3dbl = this->branch3x3dbl_1->forward(x); - branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); - branch3x3dbl = - torch::cat({this->branch3x3dbl_3a->forward(branch3x3dbl), - this->branch3x3dbl_3b->forward(branch3x3dbl)}, - 1); - - auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); - return torch::cat({branch1x1, branch3x3, branch3x3dbl, branch_pool}, 1); - } -}; - -class InceptionAuxImpl : public torch::nn::Module -{ - BasicConv2d conv0, conv1; - torch::nn::Linear fc; - -public: - InceptionAuxImpl(int64_t in_channels, int64_t num_classes) - : conv0(BasicConv2d(in_channels, 128, 1)), - conv1(BasicConv2d(128, 768, 5)), - fc(768, num_classes) - { - // TODO set these - // self.conv1.stddev = 0.01 - // self.fc.stddev = 0.001 - - register_module("conv0", conv0); - register_module("conv1", conv1); - register_module("fc", fc); - } - - torch::Tensor forward(torch::Tensor x) - { - x = torch::avg_pool2d(x, 5, 3); - x = conv0->forward(x); - x = conv1->forward(x); - x = x.view({x.size(0), -1}); - x = fc->forward(x); - return x; - } -}; - -TORCH_MODULE(InceptionA); -TORCH_MODULE(InceptionB); -TORCH_MODULE(InceptionC); -TORCH_MODULE(InceptionD); -TORCH_MODULE(InceptionE); -TORCH_MODULE(InceptionAux); - -} // namespace inceptionimpl - -class Inception_V3Impl : public torch::nn::Module -{ - bool aux_logits, transform_input; - inceptionimpl::BasicConv2d Conv2d_1a_3x3{nullptr}, Conv2d_2a_3x3{nullptr}, - Conv2d_2b_3x3{nullptr}, Conv2d_3b_1x1{nullptr}, Conv2d_4a_3x3{nullptr}; - inceptionimpl::InceptionA Mixed_5b{nullptr}, Mixed_5c{nullptr}, - Mixed_5d{nullptr}; - inceptionimpl::InceptionB Mixed_6a{nullptr}; - inceptionimpl::InceptionC Mixed_6b{nullptr}, Mixed_6c{nullptr}, - Mixed_6d{nullptr}, Mixed_6e{nullptr}; - inceptionimpl::InceptionD Mixed_7a{nullptr}; - inceptionimpl::InceptionE Mixed_7b{nullptr}, Mixed_7c{nullptr}; - torch::nn::Linear fc{nullptr}; - - inceptionimpl::InceptionAux AuxLogits{nullptr}; - -public: - Inception_V3Impl(int64_t num_classes = 1000, bool aux_logits = true, - bool transform_input = false) - : aux_logits(aux_logits), transform_input(transform_input) - { - Conv2d_1a_3x3 = inceptionimpl::BasicConv2d(3, 32, 3, 0, 2); - Conv2d_2a_3x3 = inceptionimpl::BasicConv2d(32, 32, 3); - Conv2d_2b_3x3 = inceptionimpl::BasicConv2d(32, 64, 3, 1); - Conv2d_3b_1x1 = inceptionimpl::BasicConv2d(64, 80, 1); - Conv2d_4a_3x3 = inceptionimpl::BasicConv2d(80, 192, 3); - - Mixed_5b = inceptionimpl::InceptionA(192, 32); - Mixed_5c = inceptionimpl::InceptionA(256, 64); - Mixed_5d = inceptionimpl::InceptionA(288, 64); - - Mixed_6a = inceptionimpl::InceptionB(288); - Mixed_6b = inceptionimpl::InceptionC(768, 128); - Mixed_6c = inceptionimpl::InceptionC(768, 160); - Mixed_6d = inceptionimpl::InceptionC(768, 160); - Mixed_6e = inceptionimpl::InceptionC(768, 192); - - if (aux_logits) - AuxLogits = inceptionimpl::InceptionAux(768, num_classes); - - Mixed_7a = inceptionimpl::InceptionD(768); - Mixed_7b = inceptionimpl::InceptionE(1280); - Mixed_7c = inceptionimpl::InceptionE(2048); - - fc = torch::nn::Linear(2048, num_classes); - - register_module("Conv2d_1a_3x3", Conv2d_1a_3x3); - register_module("Conv2d_2a_3x3", Conv2d_2a_3x3); - register_module("Conv2d_2b_3x3", Conv2d_2b_3x3); - register_module("Conv2d_3b_1x1", Conv2d_3b_1x1); - register_module("Conv2d_4a_3x3", Conv2d_4a_3x3); - register_module("Mixed_5b", Mixed_5b); - register_module("Mixed_5c", Mixed_5c); - register_module("Mixed_5d", Mixed_5d); - register_module("Mixed_6a", Mixed_6a); - register_module("Mixed_6b", Mixed_6b); - register_module("Mixed_6c", Mixed_6c); - register_module("Mixed_6d", Mixed_6d); - register_module("Mixed_6e", Mixed_6e); - - if (!AuxLogits.is_empty()) register_module("AuxLogits", AuxLogits); - - register_module("Mixed_7a", Mixed_7a); - register_module("Mixed_7b", Mixed_7b); - register_module("Mixed_7c", Mixed_7c); - register_module("fc", fc); - - // TODO - // for m in self.modules(): - // if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): - // import scipy.stats as stats - // stddev = m.stddev if hasattr(m, 'stddev') else 0.1 - // X = stats.truncnorm(-2, 2, scale=stddev) - // values = torch.Tensor(X.rvs(m.weight.numel())) - // values = values.view(m.weight.size()) - // m.weight.data.copy_(values) - // elif isinstance(m, nn.BatchNorm2d): - // nn.init.constant_(m.weight, 1) - // nn.init.constant_(m.bias, 0) - } - - torch::Tensor forward(torch::Tensor x) - { - if (transform_input) - { - } - } -}; - -TORCH_MODULE(Inception_V3); - -} // namespace torchvision - -#endif // INCEPTION_H diff --git a/torchvision/cmodels/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp similarity index 87% rename from torchvision/cmodels/alexnet.cpp rename to torchvision/csrc/models/alexnet.cpp index 5af0b3136f9..5b53b66d72b 100644 --- a/torchvision/cmodels/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -1,6 +1,10 @@ #include "alexnet.h" -torchvision::AlexNetImpl::AlexNetImpl(int64_t num_classes) +#include "visionimpl.h" + +namespace torchvision +{ +AlexNetImpl::AlexNetImpl(int64_t num_classes) { // clang-format off features = torch::nn::Sequential( @@ -32,7 +36,7 @@ torchvision::AlexNetImpl::AlexNetImpl(int64_t num_classes) register_module("clasifier", classifier); } -torch::Tensor torchvision::AlexNetImpl::forward(torch::Tensor x) +torch::Tensor AlexNetImpl::forward(torch::Tensor x) { x = features->forward(x); x = x.view({x.size(0), 256 * 6 * 6}); @@ -40,3 +44,5 @@ torch::Tensor torchvision::AlexNetImpl::forward(torch::Tensor x) return x; } + +} // namespace torchvision diff --git a/torchvision/cmodels/alexnet.h b/torchvision/csrc/models/alexnet.h similarity index 93% rename from torchvision/cmodels/alexnet.h rename to torchvision/csrc/models/alexnet.h index a9e49a38df4..7c0bc790987 100644 --- a/torchvision/cmodels/alexnet.h +++ b/torchvision/csrc/models/alexnet.h @@ -1,7 +1,7 @@ #ifndef ALEXNET_H #define ALEXNET_H -#include "visionimpl.h" +#include namespace torchvision { diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp new file mode 100644 index 00000000000..3065e35bcb8 --- /dev/null +++ b/torchvision/csrc/models/densenet.cpp @@ -0,0 +1,172 @@ +#include "densenet.h" + +#include "visionimpl.h" + +namespace torchvision +{ +// TODO give modules names in sequential subclasses +class _DenseLayerImpl : public torch::nn::SequentialImpl +{ + double drop_rate; + +public: + _DenseLayerImpl(int64_t num_input_features, int64_t growth_rate, + int64_t bn_size, double drop_rate) + : drop_rate(drop_rate) + { + push_back(torch::nn::BatchNorm(num_input_features)); + push_back(visionimpl::Relu(true)); + push_back( + torch::nn::Conv2d(torch::nn::Conv2dOptions(num_input_features, + bn_size * growth_rate, 1) + .stride(1) + .with_bias(false))); + push_back(torch::nn::BatchNorm(bn_size * growth_rate)); + push_back(visionimpl::Relu(true)); + push_back(torch::nn::Conv2d( + torch::nn::Conv2dOptions(bn_size * growth_rate, growth_rate, 3) + .stride(1) + .padding(1) + .with_bias(false))); + } + + torch::Tensor forward(torch::Tensor x) + { + auto new_features = torch::nn::SequentialImpl::forward(x); + if (drop_rate > 0) + new_features = + torch::dropout(new_features, drop_rate, this->is_training()); + return torch::cat({x, new_features}, 1); + } +}; + +TORCH_MODULE(_DenseLayer); + +class _DenseBlockImpl : public torch::nn::SequentialImpl +{ +public: + _DenseBlockImpl(int64_t num_layers, int64_t num_input_features, + int64_t bn_size, int64_t growth_rate, double drop_rate) + { + for (int64_t i = 0; i < num_layers; ++i) + { + auto layer = _DenseLayer(num_input_features + i * growth_rate, + growth_rate, bn_size, drop_rate); + push_back(layer); + } + } + + torch::Tensor forward(torch::Tensor x) + { + return torch::nn::SequentialImpl::forward(x); + } +}; + +TORCH_MODULE(_DenseBlock); + +class _TransitionImpl : public torch::nn::SequentialImpl +{ +public: + _TransitionImpl(int64_t num_input_features, int64_t num_output_features) + { + push_back(torch::nn::BatchNorm(num_input_features)); + push_back(visionimpl::Relu(true)); + push_back(torch::nn::Conv2d( + torch::nn::Conv2dOptions(num_input_features, num_output_features, 1) + .stride(1) + .with_bias(false))); + push_back( + visionimpl::AvgPool2D(torch::IntList({2}), torch::IntList({2}))); + } + + torch::Tensor forward(torch::Tensor x) + { + return torch::nn::SequentialImpl::forward(x); + } +}; + +TORCH_MODULE(_Transition); + +DenseNetImpl::DenseNetImpl(int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, int64_t bn_size, + int64_t drop_rate, int64_t num_classes) +{ + features = torch::nn::Sequential( + torch::nn::Conv2d(torch::nn::Conv2dOptions(3, num_init_features, 7) + .stride(2) + .padding(3) + .with_bias(false)), + torch::nn::BatchNorm(num_init_features), visionimpl::Relu(true), + visionimpl::MaxPool2D(3, 2, false, torch::IntList({1}))); + + auto num_features = num_init_features; + for (size_t i = 0; i < block_config.size(); ++i) + { + auto num_layers = block_config[i]; + auto block = _DenseBlock(num_layers, num_features, bn_size, growth_rate, + drop_rate); + features->push_back(block); + num_features = num_features + num_layers * growth_rate; + + if (i != block_config.size() - 1) + { + auto trans = _Transition(num_features, num_features / 2); + features->push_back(trans); + num_features = num_features / 2; + } + } + + features->push_back(torch::nn::BatchNorm(num_features)); + classifier = torch::nn::Linear(num_features, num_classes); + + register_module("features", features); + register_module("classifier", classifier); + + for (auto &module : modules(false)) + { + if (torch::nn::Conv2dImpl *M = + dynamic_cast(module.get())) + torch::nn::init::xavier_normal_(M->weight); + else if (torch::nn::BatchNormImpl *M = + dynamic_cast(module.get())) + { + torch::nn::init::constant_(M->weight, 1); + torch::nn::init::constant_(M->bias, 0); + } + else if (torch::nn::LinearImpl *M = + dynamic_cast(module.get())) + torch::nn::init::normal_(M->bias, 0); + } +} + +torch::Tensor DenseNetImpl::forward(torch::Tensor x) +{ + auto features = this->features->forward(x); + auto out = torch::relu_(features); + out = torch::adaptive_avg_pool2d(out, {1, 1}).view({features.size(0), -1}); + out = this->classifier->forward(out); + return out; +} + +DenseNet121Impl::DenseNet121Impl(int64_t num_classes) + : DenseNetImpl(32, {6, 12, 32, 32}, 64, 4, 0, num_classes) +{ +} + +DenseNet169Impl::DenseNet169Impl(int64_t num_classes) + : DenseNetImpl(32, {6, 12, 32, 32}, 64, 4, 0, num_classes) +{ +} + +DenseNet201Impl::DenseNet201Impl(int64_t num_classes) + : DenseNetImpl(32, {6, 12, 48, 32}, 64, 4, 0, num_classes) +{ +} + +DenseNet161Impl::DenseNet161Impl(int64_t num_classes) + : DenseNetImpl(48, {6, 12, 36, 24}, 96, 4, 0, num_classes) +{ +} + +} // namespace torchvision diff --git a/torchvision/cmodels/densenet.h b/torchvision/csrc/models/densenet.h similarity index 54% rename from torchvision/cmodels/densenet.h rename to torchvision/csrc/models/densenet.h index f43257bf846..7fe6d2b52e7 100644 --- a/torchvision/cmodels/densenet.h +++ b/torchvision/csrc/models/densenet.h @@ -1,48 +1,10 @@ #ifndef DENSENET_H #define DENSENET_H -#include "visionimpl.h" +#include namespace torchvision { -namespace densenetimpl -{ -// TODO give modules names in sequential subclasses -class _DenseLayerImpl : public torch::nn::SequentialImpl -{ - double drop_rate; - -public: - _DenseLayerImpl(int64_t num_input_features, int64_t growth_rate, - int64_t bn_size, double drop_rate); - - torch::Tensor forward(torch::Tensor x); -}; - -TORCH_MODULE(_DenseLayer); - -class _DenseBlockImpl : public torch::nn::SequentialImpl -{ -public: - _DenseBlockImpl(int64_t num_layers, int64_t num_input_features, - int64_t bn_size, int64_t growth_rate, double drop_rate); - - torch::Tensor forward(torch::Tensor x); -}; - -TORCH_MODULE(_DenseBlock); - -class _TransitionImpl : public torch::nn::SequentialImpl -{ -public: - _TransitionImpl(int64_t num_input_features, int64_t num_output_features); - - torch::Tensor forward(torch::Tensor x); -}; - -TORCH_MODULE(_Transition); -} // namespace densenetimpl - class DenseNetImpl : public torch::nn::Module { torch::nn::Sequential features{nullptr}; diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp new file mode 100644 index 00000000000..64105534c4a --- /dev/null +++ b/torchvision/csrc/models/inception.cpp @@ -0,0 +1,374 @@ +#include "inception.h" + +namespace torchvision +{ +namespace _inceptionimpl +{ +BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions options) +{ + options.with_bias(false); + conv = torch::nn::Conv2d(options); + bn = torch::nn::BatchNorm( + torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); + + register_module("conv", conv); + register_module("bn", bn); +} + +torch::Tensor BasicConv2dImpl::forward(torch::Tensor x) +{ + x = conv->forward(x); + x = bn->forward(x); + return torch::relu_(x); +} + +InceptionAImpl::InceptionAImpl(int64_t in_channels, int64_t pool_features) + : branch1x1(Options(in_channels, 64, 1)), + branch5x5_1(Options(in_channels, 48, 1)), + branch5x5_2(Options(48, 64, 5).padding(2)), + branch3x3dbl_1(Options(in_channels, 64, 1)), + branch3x3dbl_2(Options(64, 96, 3).padding(1)), + branch3x3dbl_3(Options(96, 96, 3).padding(1)), + branch_pool(Options(in_channels, pool_features, 1)) +{ + register_module("branch1x1", branch1x1); + register_module("branch5x5_1", branch5x5_1); + register_module("branch5x5_2", branch5x5_2); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3", branch3x3dbl_3); + register_module("branch_pool", branch_pool); +} + +torch::Tensor InceptionAImpl::forward(torch::Tensor x) +{ + auto branch1x1 = this->branch1x1->forward(x); + + auto branch5x5 = this->branch5x5_1->forward(x); + branch5x5 = this->branch5x5_2->forward(branch5x5); + + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); + + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + branch_pool = this->branch_pool->forward(branch_pool); + + return torch::cat({branch1x1, branch5x5, branch3x3dbl, branch_pool}, 1); +} + +InceptionBImpl::InceptionBImpl(int64_t in_channels) + : branch3x3(Options(in_channels, 384, 3).stride(2)), + branch3x3dbl_1(Options(in_channels, 64, 1)), + branch3x3dbl_2(Options(64, 96, 3).padding(1)), + branch3x3dbl_3(Options(96, 96, 3).stride(2)) +{ + register_module("branch3x3", branch3x3); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3", branch3x3dbl_3); +} + +torch::Tensor InceptionBImpl::forward(torch::Tensor x) +{ + auto branch3x3 = this->branch3x3->forward(x); + + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); + + auto branch_pool = torch::max_pool2d(x, 3, 2); + return torch::cat({branch3x3, branch3x3dbl, branch_pool}, 1); +} + +InceptionCImpl::InceptionCImpl(int64_t in_channels, int64_t channels_7x7) +{ + branch1x1 = BasicConv2d(Options(in_channels, 192, 1)); + + auto c7 = channels_7x7; + branch7x7_1 = BasicConv2d(Options(in_channels, c7, 1)); + branch7x7_2 = BasicConv2d(Options(c7, c7, {1, 7}).padding({0, 3})); + branch7x7_3 = BasicConv2d(Options(c7, 192, {7, 1}).padding({3, 0})); + + branch7x7dbl_1 = BasicConv2d(Options(in_channels, c7, 1)); + branch7x7dbl_2 = BasicConv2d(Options(c7, c7, {7, 1}).padding({3, 0})); + branch7x7dbl_3 = BasicConv2d(Options(c7, c7, {1, 7}).padding({0, 3})); + branch7x7dbl_4 = BasicConv2d(Options(c7, c7, {7, 1}).padding({3, 0})); + branch7x7dbl_5 = BasicConv2d(Options(c7, 192, {1, 7}).padding({0, 3})); + + branch_pool = BasicConv2d(Options(in_channels, 192, 1)); + + register_module("branch1x1", branch1x1); + register_module("branch7x7_1", branch7x7_1); + register_module("branch7x7_2", branch7x7_2); + register_module("branch7x7_3", branch7x7_3); + register_module("branch7x7dbl_1", branch7x7dbl_1); + register_module("branch7x7dbl_2", branch7x7dbl_2); + register_module("branch7x7dbl_3", branch7x7dbl_3); + register_module("branch7x7dbl_4", branch7x7dbl_4); + register_module("branch7x7dbl_5", branch7x7dbl_5); + register_module("branch_pool", branch_pool); +} + +torch::Tensor InceptionCImpl::forward(torch::Tensor x) +{ + auto branch1x1 = this->branch1x1->forward(x); + + auto branch7x7 = this->branch7x7_1->forward(x); + branch7x7 = this->branch7x7_2->forward(branch7x7); + branch7x7 = this->branch7x7_3->forward(branch7x7); + + auto branch7x7dbl = this->branch7x7dbl_1->forward(x); + branch7x7dbl = this->branch7x7dbl_2->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_3->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_4->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_5->forward(branch7x7dbl); + + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + branch_pool = this->branch_pool->forward(branch_pool); + + return torch::cat({branch1x1, branch7x7, branch7x7dbl, branch_pool}, 1); +} + +InceptionDImpl::InceptionDImpl(int64_t in_channels) + : branch3x3_1(Options(in_channels, 192, 1)), + branch3x3_2(Options(192, 320, 3).stride(2)), + branch7x7x3_1(Options(in_channels, 192, 1)), + branch7x7x3_2(Options(192, 192, {1, 7}).padding({0, 3})), + branch7x7x3_3(Options(192, 192, {7, 1}).padding({3, 0})), + branch7x7x3_4(Options(192, 192, 3).stride(2)) + +{ + register_module("branch3x3_1", branch3x3_1); + register_module("branch3x3_2", branch3x3_2); + register_module("branch7x7x3_1", branch7x7x3_1); + register_module("branch7x7x3_2", branch7x7x3_2); + register_module("branch7x7x3_3", branch7x7x3_3); + register_module("branch7x7x3_4", branch7x7x3_4); +} + +torch::Tensor InceptionDImpl::forward(torch::Tensor x) +{ + auto branch3x3 = this->branch3x3_1->forward(x); + branch3x3 = this->branch3x3_2->forward(branch3x3); + + auto branch7x7x3 = this->branch7x7x3_1->forward(x); + branch7x7x3 = this->branch7x7x3_2->forward(branch7x7x3); + branch7x7x3 = this->branch7x7x3_3->forward(branch7x7x3); + branch7x7x3 = this->branch7x7x3_4->forward(branch7x7x3); + + auto branch_pool = torch::max_pool2d(x, 3, 2); + return torch::cat({branch3x3, branch7x7x3, branch_pool}, 1); +} + +InceptionEImpl::InceptionEImpl(int64_t in_channels) + : branch1x1(Options(in_channels, 320, 1)), + branch3x3_1(Options(in_channels, 384, 1)), + branch3x3_2a(Options(384, 384, {1, 3}).padding({0, 1})), + branch3x3_2b(Options(384, 384, {3, 1}).padding({1, 0})), + branch3x3dbl_1(Options(in_channels, 448, 1)), + branch3x3dbl_2(Options(448, 384, 3).padding(1)), + branch3x3dbl_3a(Options(384, 384, {1, 3}).padding({0, 1})), + branch3x3dbl_3b(Options(384, 384, {3, 1}).padding({1, 0})), + branch_pool(Options(in_channels, 192, 1)) +{ + register_module("branch1x1", branch1x1); + register_module("branch3x3_1", branch3x3_1); + register_module("branch3x3_2a", branch3x3_2a); + register_module("branch3x3_2b", branch3x3_2b); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3a", branch3x3dbl_3a); + register_module("branch3x3dbl_3b", branch3x3dbl_3b); + register_module("branch_pool", branch_pool); +} + +torch::Tensor InceptionEImpl::forward(torch::Tensor x) +{ + auto branch1x1 = this->branch1x1->forward(x); + + auto branch3x3 = this->branch3x3_1->forward(x); + branch3x3 = torch::cat( + { + this->branch3x3_2a->forward(branch3x3), + this->branch3x3_2b->forward(branch3x3), + }, + 1); + + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = torch::cat({this->branch3x3dbl_3a->forward(branch3x3dbl), + this->branch3x3dbl_3b->forward(branch3x3dbl)}, + 1); + + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + branch_pool = this->branch_pool->forward(branch_pool); + + return torch::cat({branch1x1, branch3x3, branch3x3dbl, branch_pool}, 1); +} + +InceptionAuxImpl::InceptionAuxImpl(int64_t in_channels, int64_t num_classes) + : conv0(BasicConv2d(Options(in_channels, 128, 1))), + conv1(AuxBasicConv(Options(128, 768, 5))), + fc(768, num_classes) +{ + conv1->stddev = 0.01; + fc->stddev = 0.001; + + register_module("conv0", conv0); + register_module("conv1", conv1); + register_module("fc", fc); +} + +torch::Tensor InceptionAuxImpl::forward(torch::Tensor x) +{ + x = torch::avg_pool2d(x, 5, 3); + x = conv0->forward(x); + x = conv1->forward(x); + x = x.view({x.size(0), -1}); + x = fc->forward(x); + return x; +} + +} // namespace _inceptionimpl + +InceptionV3Impl::InceptionV3Impl(int64_t num_classes, bool aux_logits, + bool transform_input) + : aux_logits(aux_logits), transform_input(transform_input) +{ + Conv2d_1a_3x3 = _inceptionimpl::BasicConv2d(Options(3, 32, 3).stride(2)); + Conv2d_2a_3x3 = _inceptionimpl::BasicConv2d(Options(32, 32, 3)); + Conv2d_2b_3x3 = _inceptionimpl::BasicConv2d(Options(32, 64, 3).padding(1)); + Conv2d_3b_1x1 = _inceptionimpl::BasicConv2d(Options(64, 80, 1)); + Conv2d_4a_3x3 = _inceptionimpl::BasicConv2d(Options(80, 192, 3)); + + Mixed_5b = _inceptionimpl::InceptionA(192, 32); + Mixed_5c = _inceptionimpl::InceptionA(256, 64); + Mixed_5d = _inceptionimpl::InceptionA(288, 64); + + Mixed_6a = _inceptionimpl::InceptionB(288); + Mixed_6b = _inceptionimpl::InceptionC(768, 128); + Mixed_6c = _inceptionimpl::InceptionC(768, 160); + Mixed_6d = _inceptionimpl::InceptionC(768, 160); + Mixed_6e = _inceptionimpl::InceptionC(768, 192); + + if (aux_logits) AuxLogits = _inceptionimpl::InceptionAux(768, num_classes); + + Mixed_7a = _inceptionimpl::InceptionD(768); + Mixed_7b = _inceptionimpl::InceptionE(1280); + Mixed_7c = _inceptionimpl::InceptionE(2048); + + fc = torch::nn::Linear(2048, num_classes); + + register_module("Conv2d_1a_3x3", Conv2d_1a_3x3); + register_module("Conv2d_2a_3x3", Conv2d_2a_3x3); + register_module("Conv2d_2b_3x3", Conv2d_2b_3x3); + register_module("Conv2d_3b_1x1", Conv2d_3b_1x1); + register_module("Conv2d_4a_3x3", Conv2d_4a_3x3); + register_module("Mixed_5b", Mixed_5b); + register_module("Mixed_5c", Mixed_5c); + register_module("Mixed_5d", Mixed_5d); + register_module("Mixed_6a", Mixed_6a); + register_module("Mixed_6b", Mixed_6b); + register_module("Mixed_6c", Mixed_6c); + register_module("Mixed_6d", Mixed_6d); + register_module("Mixed_6e", Mixed_6e); + + if (!AuxLogits.is_empty()) register_module("AuxLogits", AuxLogits); + + register_module("Mixed_7a", Mixed_7a); + register_module("Mixed_7b", Mixed_7b); + register_module("Mixed_7c", Mixed_7c); + register_module("fc", fc); + + for (auto &module : modules(false)) + { + // TODO there is an error in inception that is related to AuxBasicConv + + if (_inceptionimpl::AuxLinearImpl *M = + dynamic_cast<_inceptionimpl::AuxLinearImpl *>(module.get())) + _inceptionimpl::init_weight(M->weight, M->stddev); + else if (torch::nn::Conv2dImpl *M = + dynamic_cast(module.get())) + _inceptionimpl::init_weight(M->weight, 0.1); + else if (torch::nn::LinearImpl *M = + dynamic_cast(module.get())) + _inceptionimpl::init_weight(M->weight, 0.1); + else if (torch::nn::BatchNormImpl *M = + dynamic_cast(module.get())) + { + torch::nn::init::constant_(M->weight, 1); + torch::nn::init::constant_(M->bias, 0); + } + } +} + +torch::TensorList InceptionV3Impl::forward(torch::Tensor x) +{ + if (transform_input) + { + auto x_ch0 = torch::unsqueeze(x.select(1, 0), 1) * (0.229 / 0.5) + + (0.485 - 0.5) / 0.5; + auto x_ch1 = torch::unsqueeze(x.select(1, 1), 1) * (0.224 / 0.5) + + (0.456 - 0.5) / 0.5; + auto x_ch2 = torch::unsqueeze(x.select(1, 2), 1) * (0.225 / 0.5) + + (0.406 - 0.5) / 0.5; + + x = torch::cat({x_ch0, x_ch1, x_ch2}, 1); + } + + // 299 x 299 x 3 + x = Conv2d_1a_3x3->forward(x); + // 149 x 149 x 32 + x = Conv2d_2a_3x3->forward(x); + // 147 x 147 x 32 + x = Conv2d_2b_3x3->forward(x); + // 147 x 147 x 64 + x = torch::max_pool2d(x, 3, 2); + // 73 x 73 x 64 + x = Conv2d_3b_1x1->forward(x); + // 73 x 73 x 80 + x = Conv2d_4a_3x3->forward(x); + // 71 x 71 x 192 + x = torch::max_pool2d(x, 3, 2); + // 35 x 35 x 192 + x = Mixed_5b->forward(x); + // 35 x 35 x 256 + x = Mixed_5c->forward(x); + // 35 x 35 x 288 + x = Mixed_5d->forward(x); + // 35 x 35 x 288 + x = Mixed_6a->forward(x); + // 17 x 17 x 768 + x = Mixed_6b->forward(x); + // 17 x 17 x 768 + x = Mixed_6c->forward(x); + // 17 x 17 x 768 + x = Mixed_6d->forward(x); + // 17 x 17 x 768 + x = Mixed_6e->forward(x); + // 17 x 17 x 768 + torch::Tensor aux; + if (is_training() and aux_logits) aux = AuxLogits->forward(x); + // 17 x 17 x 768 + x = Mixed_7a->forward(x); + // 8 x 8 x 1280 + x = Mixed_7b->forward(x); + // 8 x 8 x 2048 + x = Mixed_7c->forward(x); + // 8 x 8 x 2048 + x = torch::avg_pool2d(x, 8); + // 1 x 1 x 2048 + x = torch::dropout(x, 0.5, is_training()); + // 1 x 1 x 2048 + x = x.view({x.size(0), -1}); + // 2048 + x = fc->forward(x); + // 1000 (num_classes) + + if (is_training() and aux_logits) return {x, aux}; + return x; +} + +// namespace _inceptionimpl +} // namespace torchvision diff --git a/torchvision/csrc/models/inception.h b/torchvision/csrc/models/inception.h new file mode 100644 index 00000000000..c7592890009 --- /dev/null +++ b/torchvision/csrc/models/inception.h @@ -0,0 +1,155 @@ +#ifndef INCEPTION_H +#define INCEPTION_H + +#include + +namespace torchvision +{ +namespace _inceptionimpl +{ +class BasicConv2dImpl : public torch::nn::Module +{ +protected: + torch::nn::Conv2d conv{nullptr}; + torch::nn::BatchNorm bn{nullptr}; + +public: + BasicConv2dImpl(torch::nn::Conv2dOptions options); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(BasicConv2d); + +using Options = torch::nn::Conv2dOptions; + +class InceptionAImpl : public torch::nn::Module +{ + BasicConv2d branch1x1, branch5x5_1, branch5x5_2, branch3x3dbl_1, + branch3x3dbl_2, branch3x3dbl_3, branch_pool; + +public: + InceptionAImpl(int64_t in_channels, int64_t pool_features); + + torch::Tensor forward(torch::Tensor x); +}; + +class InceptionBImpl : public torch::nn::Module +{ + BasicConv2d branch3x3, branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3; + +public: + InceptionBImpl(int64_t in_channels); + + torch::Tensor forward(torch::Tensor x); +}; + +class InceptionCImpl : public torch::nn::Module +{ + BasicConv2d branch1x1{nullptr}, branch7x7_1{nullptr}, branch7x7_2{nullptr}, + branch7x7_3{nullptr}, branch7x7dbl_1{nullptr}, branch7x7dbl_2{nullptr}, + branch7x7dbl_3{nullptr}, branch7x7dbl_4{nullptr}, + branch7x7dbl_5{nullptr}, branch_pool{nullptr}; + +public: + InceptionCImpl(int64_t in_channels, int64_t channels_7x7); + + torch::Tensor forward(torch::Tensor x); +}; + +class InceptionDImpl : public torch::nn::Module +{ + BasicConv2d branch3x3_1, branch3x3_2, branch7x7x3_1, branch7x7x3_2, + branch7x7x3_3, branch7x7x3_4; + +public: + InceptionDImpl(int64_t in_channels); + + torch::Tensor forward(torch::Tensor x); +}; + +class InceptionEImpl : public torch::nn::Module +{ + BasicConv2d branch1x1, branch3x3_1, branch3x3_2a, branch3x3_2b, + branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3a, branch3x3dbl_3b, + branch_pool; + +public: + InceptionEImpl(int64_t in_channels); + + torch::Tensor forward(torch::Tensor x); +}; + +class AuxBasicConvImpl : public BasicConv2dImpl +{ +public: + using BasicConv2dImpl::BasicConv2dImpl; + + using BasicConv2dImpl::conv; + double stddev{0}; +}; + +class AuxLinearImpl : public torch::nn::LinearImpl +{ +public: + using torch::nn::LinearImpl::LinearImpl; + + double stddev{0}; +}; + +TORCH_MODULE(AuxBasicConv); +TORCH_MODULE(AuxLinear); + +class InceptionAuxImpl : public torch::nn::Module +{ + BasicConv2d conv0; + AuxBasicConv conv1; + AuxLinear fc; + +public: + InceptionAuxImpl(int64_t in_channels, int64_t num_classes); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(InceptionA); +TORCH_MODULE(InceptionB); +TORCH_MODULE(InceptionC); +TORCH_MODULE(InceptionD); +TORCH_MODULE(InceptionE); +TORCH_MODULE(InceptionAux); + +inline void init_weight(torch::Tensor &weight, double stddev) {} + +} // namespace _inceptionimpl + +using _inceptionimpl::Options; + +class InceptionV3Impl : public torch::nn::Module +{ + bool aux_logits, transform_input; + _inceptionimpl::BasicConv2d Conv2d_1a_3x3{nullptr}, Conv2d_2a_3x3{nullptr}, + Conv2d_2b_3x3{nullptr}, Conv2d_3b_1x1{nullptr}, Conv2d_4a_3x3{nullptr}; + _inceptionimpl::InceptionA Mixed_5b{nullptr}, Mixed_5c{nullptr}, + Mixed_5d{nullptr}; + _inceptionimpl::InceptionB Mixed_6a{nullptr}; + _inceptionimpl::InceptionC Mixed_6b{nullptr}, Mixed_6c{nullptr}, + Mixed_6d{nullptr}, Mixed_6e{nullptr}; + _inceptionimpl::InceptionD Mixed_7a{nullptr}; + _inceptionimpl::InceptionE Mixed_7b{nullptr}, Mixed_7c{nullptr}; + torch::nn::Linear fc{nullptr}; + + _inceptionimpl::InceptionAux AuxLogits{nullptr}; + +public: + InceptionV3Impl(int64_t num_classes = 1000, bool aux_logits = false, + bool transform_input = false); + + torch::TensorList forward(torch::Tensor x); +}; + +TORCH_MODULE(InceptionV3); + +} // namespace torchvision + +#endif // INCEPTION_H diff --git a/torchvision/cmodels/main.cpp b/torchvision/csrc/models/main.cpp similarity index 81% rename from torchvision/cmodels/main.cpp rename to torchvision/csrc/models/main.cpp index 828fcc34058..3764fa80a80 100644 --- a/torchvision/cmodels/main.cpp +++ b/torchvision/csrc/models/main.cpp @@ -22,8 +22,16 @@ long params(T &M) template void process(torch::Tensor X, std::string name) { + auto device = torch::kCPU; T M; - M->forward(X); + M->to(device); + + M->train(); + M->forward(X.to(device)); + + M->eval(); + M->forward(X.to(device)); + std::cout << name + " Done. Params: " << params(M) << " : " << params(M) / 1000000 << std::endl; } @@ -116,26 +124,27 @@ int main() // D161->forward(X); // std::cout << "DenseNet161 Done. #Params: " << params(D161) << std::endl; - PROCESS(AlexNet, X); - PROCESS(VGG11, X); - PROCESS(VGG13, X); - PROCESS(VGG16, X); - PROCESS(VGG19, X); - PROCESS(VGG11BN, X); - PROCESS(VGG13BN, X); - PROCESS(VGG16BN, X); - PROCESS(VGG19BN, X); - PROCESS(ResNet18, X); - PROCESS(ResNet34, X); - PROCESS(ResNet50, X); - PROCESS(ResNet101, X); - PROCESS(ResNet152, X); - PROCESS(SqueezeNet1_0, X); - PROCESS(SqueezeNet1_1, X); - PROCESS(DenseNet121, X); - PROCESS(DenseNet169, X); - PROCESS(DenseNet201, X); - PROCESS(DenseNet161, X); + // PROCESS(AlexNet, X); + // PROCESS(VGG11, X); + // PROCESS(VGG13, X); + // PROCESS(VGG16, X); + // PROCESS(VGG19, X); + // PROCESS(VGG11BN, X); + // PROCESS(VGG13BN, X); + // PROCESS(VGG16BN, X); + // PROCESS(VGG19BN, X); + // PROCESS(ResNet18, X); + // PROCESS(ResNet34, X); + // PROCESS(ResNet50, X); + // PROCESS(ResNet101, X); + // PROCESS(ResNet152, X); + // PROCESS(SqueezeNet1_0, X); + // PROCESS(SqueezeNet1_1, X); + // PROCESS(DenseNet121, X); + // PROCESS(DenseNet169, X); + // PROCESS(DenseNet201, X); + // PROCESS(DenseNet161, X); + PROCESS(InceptionV3, X); return 0; } diff --git a/torchvision/cmodels/resnet.cpp b/torchvision/csrc/models/resnet.cpp similarity index 62% rename from torchvision/cmodels/resnet.cpp rename to torchvision/csrc/models/resnet.cpp index 6a636bffb26..c169c726504 100644 --- a/torchvision/cmodels/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -1,27 +1,30 @@ #include "resnet.h" -int torchvision::resnetimpl::BasicBlock::expantion = 1; -int torchvision::resnetimpl::Bottleneck::expantion = 4; +#include "visionimpl.h" -torch::nn::Conv2d torchvision::resnetimpl::conv3x3(int64_t in, int64_t out, - int64_t stride) +namespace torchvision +{ +namespace _resnetimpl +{ +torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride) { torch::nn::Conv2dOptions O(in, out, 3); O.padding(1).stride(stride).with_bias(false); return torch::nn::Conv2d(O); } -torch::nn::Conv2d torchvision::resnetimpl::conv1x1(int64_t in, int64_t out, - int64_t stride) +torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride) { torch::nn::Conv2dOptions O(in, out, 1); O.stride(stride).with_bias(false); return torch::nn::Conv2d(O); } -torchvision::resnetimpl::BasicBlock::BasicBlock( - int64_t inplanes, int64_t planes, int64_t stride, - torch::nn::Sequential downsample) +int BasicBlock::expantion = 1; +int Bottleneck::expantion = 4; + +BasicBlock::BasicBlock(int64_t inplanes, int64_t planes, int64_t stride, + torch::nn::Sequential downsample) : stride(stride), downsample(downsample), conv1(conv3x3(inplanes, planes, stride)), @@ -38,25 +41,8 @@ torchvision::resnetimpl::BasicBlock::BasicBlock( if (!downsample.is_empty()) register_module("downsample", this->downsample); } -torch::Tensor torchvision::resnetimpl::BasicBlock::forward(torch::Tensor x) -{ - auto identity = x; - - auto out = conv1->forward(x); - out = bn1->forward(out).relu_(); - - out = conv2->forward(out); - out = bn2->forward(out); - - if (!downsample.is_empty()) identity = downsample->forward(x); - - out += identity; - return out.relu_(); -} - -torchvision::resnetimpl::Bottleneck::Bottleneck( - int64_t inplanes, int64_t planes, int64_t stride, - torch::nn::Sequential downsample) +Bottleneck::Bottleneck(int64_t inplanes, int64_t planes, int64_t stride, + torch::nn::Sequential downsample) : stride(stride), downsample(downsample), conv1(conv1x1(inplanes, planes)), @@ -77,7 +63,7 @@ torchvision::resnetimpl::Bottleneck::Bottleneck( if (!downsample.is_empty()) register_module("downsample", this->downsample); } -torch::Tensor torchvision::resnetimpl::Bottleneck::forward(torch::Tensor X) +torch::Tensor Bottleneck::forward(torch::Tensor X) { auto identity = X; @@ -96,32 +82,46 @@ torch::Tensor torchvision::resnetimpl::Bottleneck::forward(torch::Tensor X) return out.relu_(); } -torchvision::ResNet18Impl::ResNet18Impl(int64_t num_classes, - bool zero_init_residual) +torch::Tensor BasicBlock::forward(torch::Tensor x) +{ + auto identity = x; + + auto out = conv1->forward(x); + out = bn1->forward(out).relu_(); + + out = conv2->forward(out); + out = bn2->forward(out); + + if (!downsample.is_empty()) identity = downsample->forward(x); + + out += identity; + return out.relu_(); +} +} // namespace _resnetimpl + +ResNet18Impl::ResNet18Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({2, 2, 2, 2}, num_classes, zero_init_residual) { } -torchvision::ResNet34Impl::ResNet34Impl(int64_t num_classes, - bool zero_init_residual) +ResNet34Impl::ResNet34Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet50Impl::ResNet50Impl(int64_t num_classes, - bool zero_init_residual) +ResNet50Impl::ResNet50Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet101Impl::ResNet101Impl(int64_t num_classes, - bool zero_init_residual) +ResNet101Impl::ResNet101Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 4, 23, 3}, num_classes, zero_init_residual) { } -torchvision::ResNet152Impl::ResNet152Impl(int64_t num_classes, - bool zero_init_residual) +ResNet152Impl::ResNet152Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 8, 36, 3}, num_classes, zero_init_residual) { } + +} // namespace torchvision diff --git a/torchvision/cmodels/resnet.h b/torchvision/csrc/models/resnet.h similarity index 80% rename from torchvision/cmodels/resnet.h rename to torchvision/csrc/models/resnet.h index 8617b830651..bd302a0cdd5 100644 --- a/torchvision/cmodels/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -1,14 +1,14 @@ #ifndef RESNET_H #define RESNET_H -#include "visionimpl.h" +#include namespace torchvision { template class ResNetImpl; -namespace resnetimpl +namespace _resnetimpl { torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride = 1); torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride = 1); @@ -52,7 +52,7 @@ class Bottleneck : public torch::nn::Module torch::Tensor forward(torch::Tensor X); }; -} // namespace resnetimpl +} // namespace _resnetimpl template class ResNetImpl : public torch::nn::Module @@ -63,8 +63,8 @@ class ResNetImpl : public torch::nn::Module torch::nn::Linear fc; torch::nn::Sequential layer1, layer2, layer3, layer4; - torch::nn::Sequential makeLayer(int64_t planes, int64_t blocks, - int64_t stride = 1); + torch::nn::Sequential _make_layer(int64_t planes, int64_t blocks, + int64_t stride = 1); public: ResNetImpl(const std::vector &layers, int64_t num_classes = 1000, @@ -74,9 +74,9 @@ class ResNetImpl : public torch::nn::Module }; template -torch::nn::Sequential ResNetImpl::makeLayer(int64_t planes, - int64_t blocks, - int64_t stride) +torch::nn::Sequential ResNetImpl::_make_layer(int64_t planes, + int64_t blocks, + int64_t stride) { // TODO Blocks that are created here are not shared_ptr. see if that is a // problem (the layers in blocks are used in the resnet constructor). @@ -85,7 +85,7 @@ torch::nn::Sequential ResNetImpl::makeLayer(int64_t planes, if (stride != 1 || inplanes != planes * Block::expantion) { downsample = torch::nn::Sequential( - resnetimpl::conv1x1(inplanes, planes * Block::expantion, stride), + _resnetimpl::conv1x1(inplanes, planes * Block::expantion, stride), torch::nn::BatchNorm(planes * Block::expantion)); } @@ -106,10 +106,10 @@ ResNetImpl::ResNetImpl(const std::vector &layers, conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( false)), bn1(64), - layer1(makeLayer(64, layers[0])), - layer2(makeLayer(128, layers[1], 2)), - layer3(makeLayer(256, layers[2], 2)), - layer4(makeLayer(512, layers[3], 2)), + layer1(_make_layer(64, layers[0])), + layer2(_make_layer(128, layers[1], 2)), + layer3(_make_layer(256, layers[2], 2)), + layer4(_make_layer(512, layers[3], 2)), fc(512 * Block::expantion, num_classes) { register_module("conv1", conv1); @@ -135,14 +135,15 @@ ResNetImpl::ResNetImpl(const std::vector &layers, torch::nn::init::constant_(M->bias, 0); } } + if (zero_init_residual) for (auto &module : modules(false)) { - if (resnetimpl::Bottleneck *M = - dynamic_cast(module.get())) + if (_resnetimpl::Bottleneck *M = + dynamic_cast<_resnetimpl::Bottleneck *>(module.get())) torch::nn::init::constant_(M->bn3->weight, 0); - else if (resnetimpl::BasicBlock *M = - dynamic_cast(module.get())) + else if (_resnetimpl::BasicBlock *M = + dynamic_cast<_resnetimpl::BasicBlock *>(module.get())) torch::nn::init::constant_(M->bn2->weight, 0); } } @@ -166,31 +167,31 @@ torch::Tensor ResNetImpl::forward(torch::Tensor x) return x; } -class ResNet18Impl : public ResNetImpl +class ResNet18Impl : public ResNetImpl<_resnetimpl::BasicBlock> { public: ResNet18Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; -class ResNet34Impl : public ResNetImpl +class ResNet34Impl : public ResNetImpl<_resnetimpl::BasicBlock> { public: ResNet34Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; -class ResNet50Impl : public ResNetImpl +class ResNet50Impl : public ResNetImpl<_resnetimpl::Bottleneck> { public: ResNet50Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; -class ResNet101Impl : public ResNetImpl +class ResNet101Impl : public ResNetImpl<_resnetimpl::Bottleneck> { public: ResNet101Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; -class ResNet152Impl : public ResNetImpl +class ResNet152Impl : public ResNetImpl<_resnetimpl::Bottleneck> { public: ResNet152Impl(int64_t num_classes = 1000, bool zero_init_residual = false); diff --git a/torchvision/cmodels/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp similarity index 52% rename from torchvision/cmodels/squeezenet.cpp rename to torchvision/csrc/models/squeezenet.cpp index eed737a31ce..d84de2f951f 100644 --- a/torchvision/cmodels/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -1,30 +1,39 @@ #include "squeezenet.h" #include +#include "visionimpl.h" -torchvision::squeezenetimpl::Fire::Fire(int64_t inplanes, - int64_t squeeze_planes, - int64_t expand1x1_planes, - int64_t expand3x3_planes) - : squeeze(torch::nn::Conv2dOptions(inplanes, squeeze_planes, 1)), - expand1x1(torch::nn::Conv2dOptions(squeeze_planes, expand1x1_planes, 1)), - expand3x3(torch::nn::Conv2dOptions(squeeze_planes, expand3x3_planes, 3) - .padding(1)) +namespace torchvision { - register_module("squeeze", squeeze); - register_module("expand1x1", expand1x1); - register_module("expand3x3", expand3x3); -} - -torch::Tensor torchvision::squeezenetimpl::Fire::forward(torch::Tensor x) +class Fire : public torch::nn::Module { - x = torch::relu(squeeze->forward(x)); - return torch::cat({torch::relu(expand1x1->forward(x)), - torch::relu(expand3x3->forward(x))}, - 1); -} + torch::nn::Conv2d squeeze, expand1x1, expand3x3; + +public: + Fire(int64_t inplanes, int64_t squeeze_planes, int64_t expand1x1_planes, + int64_t expand3x3_planes) + : squeeze(torch::nn::Conv2dOptions(inplanes, squeeze_planes, 1)), + expand1x1( + torch::nn::Conv2dOptions(squeeze_planes, expand1x1_planes, 1)), + expand3x3( + torch::nn::Conv2dOptions(squeeze_planes, expand3x3_planes, 3) + .padding(1)) + { + register_module("squeeze", squeeze); + register_module("expand1x1", expand1x1); + register_module("expand3x3", expand3x3); + } -torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) + torch::Tensor forward(torch::Tensor x) + { + x = torch::relu(squeeze->forward(x)); + return torch::cat({torch::relu(expand1x1->forward(x)), + torch::relu(expand3x3->forward(x))}, + 1); + } +}; + +SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) : num_classes(num_classes) { auto double_compare = [](double a, double b) { @@ -38,16 +47,16 @@ torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2, true), - squeezenetimpl::Fire(96, 16, 64, 64), - squeezenetimpl::Fire(128, 16, 64, 64), - squeezenetimpl::Fire(128, 32, 128, 128), + Fire(96, 16, 64, 64), + Fire(128, 16, 64, 64), + Fire(128, 32, 128, 128), visionimpl::MaxPool2D(3, 2, true), - squeezenetimpl::Fire(256, 32, 128, 128), - squeezenetimpl::Fire(256, 48, 192, 192), - squeezenetimpl::Fire(384, 48, 192, 192), - squeezenetimpl::Fire(384, 64, 256, 256), + Fire(256, 32, 128, 128), + Fire(256, 48, 192, 192), + Fire(384, 48, 192, 192), + Fire(384, 64, 256, 256), visionimpl::MaxPool2D(3, 2, true), - squeezenetimpl::Fire(512, 64, 256, 256)); + Fire(512, 64, 256, 256)); // clang-format on } else if (double_compare(version, 1.1)) @@ -57,16 +66,16 @@ torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2, true), - squeezenetimpl::Fire(64, 16, 64, 64), - squeezenetimpl::Fire(128, 16, 64, 64), + Fire(64, 16, 64, 64), + Fire(128, 16, 64, 64), visionimpl::MaxPool2D(3, 2, true), - squeezenetimpl::Fire(128, 32, 128, 128), - squeezenetimpl::Fire(256, 32, 128, 128), + Fire(128, 32, 128, 128), + Fire(256, 32, 128, 128), visionimpl::MaxPool2D(3, 2, true), - squeezenetimpl::Fire(256, 48, 192, 192), - squeezenetimpl::Fire(384, 48, 192, 192), - squeezenetimpl::Fire(384, 64, 256, 256), - squeezenetimpl::Fire(512, 64, 256, 256)); + Fire(256, 48, 192, 192), + Fire(384, 48, 192, 192), + Fire(384, 64, 256, 256), + Fire(512, 64, 256, 256)); // clang-format on } else @@ -103,19 +112,21 @@ torchvision::SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) } } -torch::Tensor torchvision::SqueezeNetImpl::forward(torch::Tensor x) +torch::Tensor SqueezeNetImpl::forward(torch::Tensor x) { x = features->forward(x); x = classifier->forward(x); return x.view({x.size(0), num_classes}); } -torchvision::SqueezeNet1_0Impl::SqueezeNet1_0Impl(int64_t num_classes) +SqueezeNet1_0Impl::SqueezeNet1_0Impl(int64_t num_classes) : SqueezeNetImpl(1.0, num_classes) { } -torchvision::SqueezeNet1_1Impl::SqueezeNet1_1Impl(int64_t num_classes) +SqueezeNet1_1Impl::SqueezeNet1_1Impl(int64_t num_classes) : SqueezeNetImpl(1.1, num_classes) { } + +} // namespace torchvision diff --git a/torchvision/cmodels/squeezenet.h b/torchvision/csrc/models/squeezenet.h similarity index 66% rename from torchvision/cmodels/squeezenet.h rename to torchvision/csrc/models/squeezenet.h index 470423ce9de..6aa7043fe1b 100644 --- a/torchvision/cmodels/squeezenet.h +++ b/torchvision/csrc/models/squeezenet.h @@ -1,25 +1,10 @@ #ifndef SQUEEZENET_H #define SQUEEZENET_H -#include "visionimpl.h" +#include namespace torchvision { -namespace squeezenetimpl -{ -class Fire : public torch::nn::Module -{ - torch::nn::Conv2d squeeze, expand1x1, expand3x3; - -public: - Fire(int64_t inplanes, int64_t squeeze_planes, int64_t expand1x1_planes, - int64_t expand3x3_planes); - - torch::Tensor forward(torch::Tensor x); -}; - -} // namespace squeezenetimpl - class SqueezeNetImpl : public torch::nn::Module { int64_t num_classes; diff --git a/torchvision/cmodels/vgg.cpp b/torchvision/csrc/models/vgg.cpp similarity index 71% rename from torchvision/cmodels/vgg.cpp rename to torchvision/csrc/models/vgg.cpp index b6436542a6e..e787d2e6f36 100644 --- a/torchvision/cmodels/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -1,6 +1,35 @@ #include "vgg.h" -void torchvision::VGGImpl::_initialize_weights() +#include "visionimpl.h" + +namespace torchvision +{ +torch::nn::Sequential makeLayers(const std::vector &cfg, + bool batch_norm = false) +{ + torch::nn::Sequential seq; + auto channels = 3; + + for (const auto &V : cfg) + { + if (V <= -1) + seq->push_back(visionimpl::MaxPool2D(2, 2)); + else + { + seq->push_back(torch::nn::Conv2d( + torch::nn::Conv2dOptions(channels, V, 3).padding(1))); + + if (batch_norm) seq->push_back(torch::nn::BatchNorm(V)); + seq->push_back(visionimpl::Relu(true)); + + channels = V; + } + } + + return seq; +} + +void VGGImpl::_initialize_weights() { for (auto &module : modules(false)) { @@ -25,8 +54,8 @@ void torchvision::VGGImpl::_initialize_weights() } } -torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, - int64_t num_classes, bool initialize_weights) +VGGImpl::VGGImpl(torch::nn::Sequential features, int64_t num_classes, + bool initialize_weights) { // clang-format off classifier = torch::nn::Sequential( @@ -47,7 +76,7 @@ torchvision::VGGImpl::VGGImpl(torch::nn::Sequential features, if (initialize_weights) _initialize_weights(); } -torch::Tensor torchvision::VGGImpl::forward(torch::Tensor x) +torch::Tensor VGGImpl::forward(torch::Tensor x) { x = features->forward(x); x = x.view({x.size(0), -1}); @@ -55,60 +84,35 @@ torch::Tensor torchvision::VGGImpl::forward(torch::Tensor x) return x; } -torch::nn::Sequential torchvision::makeLayers(const std::vector &cfg, - bool batch_norm) -{ - torch::nn::Sequential seq; - auto channels = 3; - - for (const auto &V : cfg) - { - if (V <= -1) - seq->push_back(visionimpl::MaxPool2D(2, 2)); - else - { - seq->push_back(torch::nn::Conv2d( - torch::nn::Conv2dOptions(channels, V, 3).padding(1))); - - if (batch_norm) seq->push_back(torch::nn::BatchNorm(V)); - seq->push_back(visionimpl::Relu(true)); - - channels = V; - } - } - - return seq; -} - -torchvision::VGG11Impl::VGG11Impl(int64_t num_classes, bool initialize_weights) +VGG11Impl::VGG11Impl(int64_t num_classes, bool initialize_weights) : VGGImpl(makeLayers( {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}), num_classes, initialize_weights) { } -torchvision::VGG13Impl::VGG13Impl(int64_t num_classes, bool initWeights) +VGG13Impl::VGG13Impl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}), num_classes, initWeights) { } -torchvision::VGG16Impl::VGG16Impl(int64_t num_classes, bool initWeights) +VGG16Impl::VGG16Impl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}), num_classes, initWeights) { } -torchvision::VGG19Impl::VGG19Impl(int64_t num_classes, bool initialize_weights) +VGG19Impl::VGG19Impl(int64_t num_classes, bool initialize_weights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}), num_classes, initialize_weights) { } -torchvision::VGG11BNImpl::VGG11BNImpl(int64_t num_classes, bool initWeights) +VGG11BNImpl::VGG11BNImpl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers( {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}, true), @@ -116,8 +120,7 @@ torchvision::VGG11BNImpl::VGG11BNImpl(int64_t num_classes, bool initWeights) { } -torchvision::VGG13BNImpl::VGG13BNImpl(int64_t num_classes, - bool initialize_weights) +VGG13BNImpl::VGG13BNImpl(int64_t num_classes, bool initialize_weights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}, true), @@ -125,7 +128,7 @@ torchvision::VGG13BNImpl::VGG13BNImpl(int64_t num_classes, { } -torchvision::VGG16BNImpl::VGG16BNImpl(int64_t num_classes, bool initWeights) +VGG16BNImpl::VGG16BNImpl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}, true), @@ -133,10 +136,12 @@ torchvision::VGG16BNImpl::VGG16BNImpl(int64_t num_classes, bool initWeights) { } -torchvision::VGG19BNImpl::VGG19BNImpl(int64_t num_classes, bool initWeights) +VGG19BNImpl::VGG19BNImpl(int64_t num_classes, bool initWeights) : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}, true), num_classes, initWeights) { } + +} // namespace torchvision diff --git a/torchvision/cmodels/vgg.h b/torchvision/csrc/models/vgg.h similarity index 92% rename from torchvision/cmodels/vgg.h rename to torchvision/csrc/models/vgg.h index 06c47ef0810..bac27887e60 100644 --- a/torchvision/cmodels/vgg.h +++ b/torchvision/csrc/models/vgg.h @@ -1,7 +1,7 @@ #ifndef VGG_H #define VGG_H -#include "visionimpl.h" +#include namespace torchvision { @@ -18,9 +18,6 @@ class VGGImpl : public torch::nn::Module torch::Tensor forward(torch::Tensor x); }; -torch::nn::Sequential makeLayers(const std::vector &cfg, - bool batch_norm = false); - class VGG11Impl : public VGGImpl { public: diff --git a/torchvision/cmodels/vision.h b/torchvision/csrc/models/vision.h similarity index 100% rename from torchvision/cmodels/vision.h rename to torchvision/csrc/models/vision.h diff --git a/torchvision/cmodels/visionimpl.h b/torchvision/csrc/models/visionimpl.h similarity index 100% rename from torchvision/cmodels/visionimpl.h rename to torchvision/csrc/models/visionimpl.h From df91685363d3693a9bc8ea568bfdef345f399d30 Mon Sep 17 00:00:00 2001 From: Shahriar Date: Wed, 23 Jan 2019 13:19:26 +0330 Subject: [PATCH 06/48] Fixed and wrote some stuff --- torchvision/CMakeLists.txt | 8 +++- torchvision/csrc/models/alexnet.h | 2 + torchvision/csrc/models/densenet.cpp | 41 +++++++++++++----- torchvision/csrc/models/densenet.h | 38 ++++++++++++++--- torchvision/csrc/models/inception.cpp | 12 +++++- torchvision/csrc/models/inception.h | 9 ++-- torchvision/csrc/models/main.cpp | 40 ++++++++--------- torchvision/csrc/models/resnet.h | 18 ++++++++ torchvision/csrc/models/squeezenet.cpp | 1 + torchvision/csrc/models/squeezenet.h | 8 ++++ torchvision/csrc/models/vgg.cpp | 45 ++++++++------------ torchvision/csrc/models/vgg.h | 10 +++++ torchvision/csrc/models/visionimpl.cpp | 56 ++++++++++++++++++++++++ torchvision/csrc/models/visionimpl.h | 59 ++++++-------------------- 14 files changed, 229 insertions(+), 118 deletions(-) create mode 100644 torchvision/csrc/models/visionimpl.cpp diff --git a/torchvision/CMakeLists.txt b/torchvision/CMakeLists.txt index e19b93f357d..b6fcfa4d763 100644 --- a/torchvision/CMakeLists.txt +++ b/torchvision/CMakeLists.txt @@ -1,10 +1,16 @@ cmake_minimum_required(VERSION 2.8) -project(torchvision) +project(TorchVision) set(CMAKE_CXX_STANDARD 11) +file(GLOB_RECURSE HEADERS csrc/models/*.h) file(GLOB_RECURSE SOURCES csrc/models/*.h csrc/models/*.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) set(CUDNN_INCLUDE_DIR /usr/include/cuda) find_package(Torch REQUIRED) target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}") + +set(INSTALL_PATH /usr/local/torchvision) + +install(TARGETS ${PROJECT_NAME} DESTINATION ${INSTALL_PATH}/lib) +install(FILES ${HEADERS} DESTINATION ${INSTALL_PATH}/include/torchvision) diff --git a/torchvision/csrc/models/alexnet.h b/torchvision/csrc/models/alexnet.h index 7c0bc790987..89ba7817cdc 100644 --- a/torchvision/csrc/models/alexnet.h +++ b/torchvision/csrc/models/alexnet.h @@ -5,6 +5,8 @@ namespace torchvision { +// AlexNet model architecture from the +// "One weird trick..." paper. class AlexNetImpl : public torch::nn::Module { torch::nn::Sequential features{nullptr}, classifier{nullptr}; diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index 3065e35bcb8..3bccd659791 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -87,11 +87,12 @@ class _TransitionImpl : public torch::nn::SequentialImpl TORCH_MODULE(_Transition); -DenseNetImpl::DenseNetImpl(int64_t growth_rate, +DenseNetImpl::DenseNetImpl(int64_t num_classes, int64_t growth_rate, std::vector block_config, int64_t num_init_features, int64_t bn_size, - int64_t drop_rate, int64_t num_classes) + double drop_rate) { + // First convolution features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, num_init_features, 7) .stride(2) @@ -100,6 +101,7 @@ DenseNetImpl::DenseNetImpl(int64_t growth_rate, torch::nn::BatchNorm(num_init_features), visionimpl::Relu(true), visionimpl::MaxPool2D(3, 2, false, torch::IntList({1}))); + // Each denseblock auto num_features = num_init_features; for (size_t i = 0; i < block_config.size(); ++i) { @@ -117,12 +119,15 @@ DenseNetImpl::DenseNetImpl(int64_t growth_rate, } } + // Final batch norm features->push_back(torch::nn::BatchNorm(num_features)); + // Linear layer classifier = torch::nn::Linear(num_features, num_classes); register_module("features", features); register_module("classifier", classifier); + // Official init from torch repo. for (auto &module : modules(false)) { if (torch::nn::Conv2dImpl *M = @@ -149,23 +154,39 @@ torch::Tensor DenseNetImpl::forward(torch::Tensor x) return out; } -DenseNet121Impl::DenseNet121Impl(int64_t num_classes) - : DenseNetImpl(32, {6, 12, 32, 32}, 64, 4, 0, num_classes) +DenseNet121Impl::DenseNet121Impl(int64_t num_classes, int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, int64_t bn_size, + double drop_rate) + : DenseNetImpl(num_classes, growth_rate, block_config, num_init_features, + bn_size, drop_rate) { } -DenseNet169Impl::DenseNet169Impl(int64_t num_classes) - : DenseNetImpl(32, {6, 12, 32, 32}, 64, 4, 0, num_classes) +DenseNet169Impl::DenseNet169Impl(int64_t num_classes, int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, int64_t bn_size, + double drop_rate) + : DenseNetImpl(num_classes, growth_rate, block_config, num_init_features, + bn_size, drop_rate) { } -DenseNet201Impl::DenseNet201Impl(int64_t num_classes) - : DenseNetImpl(32, {6, 12, 48, 32}, 64, 4, 0, num_classes) +DenseNet201Impl::DenseNet201Impl(int64_t num_classes, int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, int64_t bn_size, + double drop_rate) + : DenseNetImpl(num_classes, growth_rate, block_config, num_init_features, + bn_size, drop_rate) { } -DenseNet161Impl::DenseNet161Impl(int64_t num_classes) - : DenseNetImpl(48, {6, 12, 36, 24}, 96, 4, 0, num_classes) +DenseNet161Impl::DenseNet161Impl(int64_t num_classes, int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, int64_t bn_size, + double drop_rate) + : DenseNetImpl(num_classes, growth_rate, block_config, num_init_features, + bn_size, drop_rate) { } diff --git a/torchvision/csrc/models/densenet.h b/torchvision/csrc/models/densenet.h index 7fe6d2b52e7..d9d68c28f07 100644 --- a/torchvision/csrc/models/densenet.h +++ b/torchvision/csrc/models/densenet.h @@ -5,16 +5,29 @@ namespace torchvision { +// Densenet-BC model class, based on +// "Densely Connected Convolutional Networks" +// + +// Args: +// growth_rate (int) - how many filters to add each layer (`k` in paper) +// block_config (list of 4 ints) - how many layers in each pooling block +// num_init_features (int) - the number of filters to learn in the first +// convolution layer +// bn_size (int) - multiplicative factor for number of bottle neck layers +// (i.e. bn_size * k features in the bottleneck layer) +// drop_rate (float) - dropout rate after each dense layer +// num_classes (int) - number of classification classes class DenseNetImpl : public torch::nn::Module { torch::nn::Sequential features{nullptr}; torch::nn::Linear classifier{nullptr}; public: - DenseNetImpl(int64_t growth_rate = 32, + DenseNetImpl(int64_t num_classes = 1000, int64_t growth_rate = 32, std::vector block_config = {6, 12, 24, 16}, int64_t num_init_features = 64, int64_t bn_size = 4, - int64_t drop_rate = 0, int64_t num_classes = 1000); + double drop_rate = 0); torch::Tensor forward(torch::Tensor x); }; @@ -22,27 +35,40 @@ class DenseNetImpl : public torch::nn::Module class DenseNet121Impl : public DenseNetImpl { public: - DenseNet121Impl(int64_t num_classes = 1000); + DenseNet121Impl(int64_t num_classes = 1000, int64_t growth_rate = 32, + std::vector block_config = {6, 12, 24, 16}, + int64_t num_init_features = 64, int64_t bn_size = 4, + double drop_rate = 0); }; class DenseNet169Impl : public DenseNetImpl { public: - DenseNet169Impl(int64_t num_classes = 1000); + DenseNet169Impl(int64_t num_classes = 1000, int64_t growth_rate = 32, + std::vector block_config = {6, 12, 32, 32}, + int64_t num_init_features = 64, int64_t bn_size = 4, + double drop_rate = 0); }; class DenseNet201Impl : public DenseNetImpl { public: - DenseNet201Impl(int64_t num_classes = 1000); + DenseNet201Impl(int64_t num_classes = 1000, int64_t growth_rate = 32, + std::vector block_config = {6, 12, 48, 32}, + int64_t num_init_features = 64, int64_t bn_size = 4, + double drop_rate = 0); }; class DenseNet161Impl : public DenseNetImpl { public: - DenseNet161Impl(int64_t num_classes = 1000); + DenseNet161Impl(int64_t num_classes = 1000, int64_t growth_rate = 48, + std::vector block_config = {6, 12, 36, 24}, + int64_t num_init_features = 96, int64_t bn_size = 4, + double drop_rate = 0); }; +TORCH_MODULE(DenseNet); TORCH_MODULE(DenseNet121); TORCH_MODULE(DenseNet169); TORCH_MODULE(DenseNet201); diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 64105534c4a..2fa301d7d5b 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -2,6 +2,8 @@ namespace torchvision { +using Options = torch::nn::Conv2dOptions; + namespace _inceptionimpl { BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions options) @@ -222,11 +224,17 @@ InceptionAuxImpl::InceptionAuxImpl(int64_t in_channels, int64_t num_classes) torch::Tensor InceptionAuxImpl::forward(torch::Tensor x) { + // 17 x 17 x 768 x = torch::avg_pool2d(x, 5, 3); + // 5 x 5 x 768 x = conv0->forward(x); + // 5 x 5 x 128 x = conv1->forward(x); + // 1 x 1 x 768 x = x.view({x.size(0), -1}); + // 768 x = fc->forward(x); + // 1000 (num_classes) return x; } @@ -349,7 +357,7 @@ torch::TensorList InceptionV3Impl::forward(torch::Tensor x) x = Mixed_6e->forward(x); // 17 x 17 x 768 torch::Tensor aux; - if (is_training() and aux_logits) aux = AuxLogits->forward(x); + if (is_training() && aux_logits) aux = AuxLogits->forward(x); // 17 x 17 x 768 x = Mixed_7a->forward(x); // 8 x 8 x 1280 @@ -366,7 +374,7 @@ torch::TensorList InceptionV3Impl::forward(torch::Tensor x) x = fc->forward(x); // 1000 (num_classes) - if (is_training() and aux_logits) return {x, aux}; + if (is_training() && aux_logits) return {x, aux}; return x; } diff --git a/torchvision/csrc/models/inception.h b/torchvision/csrc/models/inception.h index c7592890009..bf538e76f5a 100644 --- a/torchvision/csrc/models/inception.h +++ b/torchvision/csrc/models/inception.h @@ -21,8 +21,6 @@ class BasicConv2dImpl : public torch::nn::Module TORCH_MODULE(BasicConv2d); -using Options = torch::nn::Conv2dOptions; - class InceptionAImpl : public torch::nn::Module { BasicConv2d branch1x1, branch5x5_1, branch5x5_2, branch3x3dbl_1, @@ -123,8 +121,9 @@ inline void init_weight(torch::Tensor &weight, double stddev) {} } // namespace _inceptionimpl -using _inceptionimpl::Options; - +// Inception v3 model architecture from +//"Rethinking the Inception Architecture for Computer Vision" +// class InceptionV3Impl : public torch::nn::Module { bool aux_logits, transform_input; @@ -142,7 +141,7 @@ class InceptionV3Impl : public torch::nn::Module _inceptionimpl::InceptionAux AuxLogits{nullptr}; public: - InceptionV3Impl(int64_t num_classes = 1000, bool aux_logits = false, + InceptionV3Impl(int64_t num_classes = 1000, bool aux_logits = true, bool transform_input = false); torch::TensorList forward(torch::Tensor x); diff --git a/torchvision/csrc/models/main.cpp b/torchvision/csrc/models/main.cpp index 3764fa80a80..a4f7bcd7f64 100644 --- a/torchvision/csrc/models/main.cpp +++ b/torchvision/csrc/models/main.cpp @@ -124,26 +124,26 @@ int main() // D161->forward(X); // std::cout << "DenseNet161 Done. #Params: " << params(D161) << std::endl; - // PROCESS(AlexNet, X); - // PROCESS(VGG11, X); - // PROCESS(VGG13, X); - // PROCESS(VGG16, X); - // PROCESS(VGG19, X); - // PROCESS(VGG11BN, X); - // PROCESS(VGG13BN, X); - // PROCESS(VGG16BN, X); - // PROCESS(VGG19BN, X); - // PROCESS(ResNet18, X); - // PROCESS(ResNet34, X); - // PROCESS(ResNet50, X); - // PROCESS(ResNet101, X); - // PROCESS(ResNet152, X); - // PROCESS(SqueezeNet1_0, X); - // PROCESS(SqueezeNet1_1, X); - // PROCESS(DenseNet121, X); - // PROCESS(DenseNet169, X); - // PROCESS(DenseNet201, X); - // PROCESS(DenseNet161, X); + PROCESS(AlexNet, X); + PROCESS(VGG11, X); + PROCESS(VGG13, X); + PROCESS(VGG16, X); + PROCESS(VGG19, X); + PROCESS(VGG11BN, X); + PROCESS(VGG13BN, X); + PROCESS(VGG16BN, X); + PROCESS(VGG19BN, X); + PROCESS(ResNet18, X); + PROCESS(ResNet34, X); + PROCESS(ResNet50, X); + PROCESS(ResNet101, X); + PROCESS(ResNet152, X); + PROCESS(SqueezeNet1_0, X); + PROCESS(SqueezeNet1_1, X); + PROCESS(DenseNet121, X); + PROCESS(DenseNet169, X); + PROCESS(DenseNet201, X); + PROCESS(DenseNet161, X); PROCESS(InceptionV3, X); return 0; diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index bd302a0cdd5..1c25f3b363d 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -10,7 +10,9 @@ class ResNetImpl; namespace _resnetimpl { +// 3x3 convolution with padding torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride = 1); +// 1x1 convolution torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride = 1); class BasicBlock : public torch::nn::Module @@ -136,6 +138,10 @@ ResNetImpl::ResNetImpl(const std::vector &layers, } } + // Zero-initialize the last BN in each residual branch, so that the residual + // branch starts with zeros, and each residual block behaves like an + // identity. This improves the model by 0.2~0.3% according to + // https://arxiv.org/abs/1706.02677 if (zero_init_residual) for (auto &module : modules(false)) { @@ -167,36 +173,48 @@ torch::Tensor ResNetImpl::forward(torch::Tensor x) return x; } +// ResNet-18 model class ResNet18Impl : public ResNetImpl<_resnetimpl::BasicBlock> { public: ResNet18Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; +// ResNet-34 model class ResNet34Impl : public ResNetImpl<_resnetimpl::BasicBlock> { public: ResNet34Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; +// ResNet-50 model class ResNet50Impl : public ResNetImpl<_resnetimpl::Bottleneck> { public: ResNet50Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; +// ResNet-101 model class ResNet101Impl : public ResNetImpl<_resnetimpl::Bottleneck> { public: ResNet101Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; +// ResNet-152 model class ResNet152Impl : public ResNetImpl<_resnetimpl::Bottleneck> { public: ResNet152Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; +template +class ResNet : public torch::nn::ModuleHolder> +{ +public: + using torch::nn::ModuleHolder>::ModuleHolder; +}; + TORCH_MODULE(ResNet18); TORCH_MODULE(ResNet34); TORCH_MODULE(ResNet50); diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index d84de2f951f..7277e250585 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -85,6 +85,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) assert(false); } + // Final convolution is initialized differently form the rest auto final_conv = torch::nn::Conv2d(torch::nn::Conv2dOptions(512, num_classes, 1)); diff --git a/torchvision/csrc/models/squeezenet.h b/torchvision/csrc/models/squeezenet.h index 6aa7043fe1b..fb326cea9e8 100644 --- a/torchvision/csrc/models/squeezenet.h +++ b/torchvision/csrc/models/squeezenet.h @@ -16,18 +16,26 @@ class SqueezeNetImpl : public torch::nn::Module torch::Tensor forward(torch::Tensor x); }; +// SqueezeNet model architecture from the "SqueezeNet: AlexNet-level +// accuracy with 50x fewer parameters and <0.5MB model size" +// paper. class SqueezeNet1_0Impl : public SqueezeNetImpl { public: SqueezeNet1_0Impl(int64_t num_classes = 1000); }; +// SqueezeNet 1.1 model from the official SqueezeNet repo +// . +// SqueezeNet 1.1 has 2.4x less computation and slightly fewer parameters +// than SqueezeNet 1.0, without sacrificing accuracy. class SqueezeNet1_1Impl : public SqueezeNetImpl { public: SqueezeNet1_1Impl(int64_t num_classes = 1000); }; +TORCH_MODULE(SqueezeNet); TORCH_MODULE(SqueezeNet1_0); TORCH_MODULE(SqueezeNet1_1); diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index e787d2e6f36..7e8c362e868 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -1,5 +1,6 @@ #include "vgg.h" +#include #include "visionimpl.h" namespace torchvision @@ -84,63 +85,51 @@ torch::Tensor VGGImpl::forward(torch::Tensor x) return x; } +// clang-format off +static std::map> cfg = { + {'A', {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}}, + {'B', {64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}}, + {'D', {64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}}, + {'E', {64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}}}; +// clang-format on + VGG11Impl::VGG11Impl(int64_t num_classes, bool initialize_weights) - : VGGImpl(makeLayers( - {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}), - num_classes, initialize_weights) + : VGGImpl(makeLayers(cfg['A']), num_classes, initialize_weights) { } VGG13Impl::VGG13Impl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, - 512, 512, -1}), - num_classes, initWeights) + : VGGImpl(makeLayers(cfg['B']), num_classes, initWeights) { } VGG16Impl::VGG16Impl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, - 512, -1, 512, 512, 512, -1}), - num_classes, initWeights) + : VGGImpl(makeLayers(cfg['D']), num_classes, initWeights) { } VGG19Impl::VGG19Impl(int64_t num_classes, bool initialize_weights) - : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, - 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}), - num_classes, initialize_weights) + : VGGImpl(makeLayers(cfg['E']), num_classes, initialize_weights) { } VGG11BNImpl::VGG11BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers( - {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}, - true), - num_classes, initWeights) + : VGGImpl(makeLayers(cfg['A'], true), num_classes, initWeights) { } VGG13BNImpl::VGG13BNImpl(int64_t num_classes, bool initialize_weights) - : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, - 512, 512, -1}, - true), - num_classes, initialize_weights) + : VGGImpl(makeLayers(cfg['B'], true), num_classes, initialize_weights) { } VGG16BNImpl::VGG16BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, - 512, -1, 512, 512, 512, -1}, - true), - num_classes, initWeights) + : VGGImpl(makeLayers(cfg['D'], true), num_classes, initWeights) { } VGG19BNImpl::VGG19BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers({64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, - 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}, - true), - num_classes, initWeights) + : VGGImpl(makeLayers(cfg['E'], true), num_classes, initWeights) { } diff --git a/torchvision/csrc/models/vgg.h b/torchvision/csrc/models/vgg.h index bac27887e60..15b878f957c 100644 --- a/torchvision/csrc/models/vgg.h +++ b/torchvision/csrc/models/vgg.h @@ -18,54 +18,64 @@ class VGGImpl : public torch::nn::Module torch::Tensor forward(torch::Tensor x); }; +// VGG 11-layer model (configuration "A") class VGG11Impl : public VGGImpl { public: VGG11Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; +// VGG 13-layer model (configuration "B") class VGG13Impl : public VGGImpl { public: VGG13Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; +// VGG 16-layer model (configuration "D") class VGG16Impl : public VGGImpl { public: VGG16Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; +// VGG 19-layer model (configuration "E") class VGG19Impl : public VGGImpl { public: VGG19Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; +// VGG 11-layer model (configuration "A") with batch normalization class VGG11BNImpl : public VGGImpl { public: VGG11BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; +// VGG 13-layer model (configuration "B") with batch normalization class VGG13BNImpl : public VGGImpl { public: VGG13BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; +// VGG 16-layer model (configuration "D") with batch normalization class VGG16BNImpl : public VGGImpl { public: VGG16BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; +// VGG 19-layer model (configuration 'E') with batch normalization class VGG19BNImpl : public VGGImpl { public: VGG19BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; +TORCH_MODULE(VGG); + TORCH_MODULE(VGG11); TORCH_MODULE(VGG13); TORCH_MODULE(VGG16); diff --git a/torchvision/csrc/models/visionimpl.cpp b/torchvision/csrc/models/visionimpl.cpp new file mode 100644 index 00000000000..a86174ffb7f --- /dev/null +++ b/torchvision/csrc/models/visionimpl.cpp @@ -0,0 +1,56 @@ +#include "visionimpl.h" + +namespace torchvision +{ +namespace visionimpl +{ +ReluImpl::ReluImpl(bool inplace) : torch::nn::Module(), inplace(inplace) {} + +torch::Tensor ReluImpl::forward(torch::Tensor X) +{ + if (inplace) + { + X.relu_(); + return X; + } + + return torch::relu(X); +} + +MaxPool2DImpl::MaxPool2DImpl(int64_t kernel, int64_t stride, bool ceil_mode, + c10::IntList padding) + : torch::nn::Module(), + kernel(kernel), + stride(stride), + ceil_mode(ceil_mode), + padding(padding) +{ +} + +torch::Tensor MaxPool2DImpl::forward(torch::Tensor X) +{ + return torch::max_pool2d(X, kernel, stride, padding, 1, ceil_mode); +} + +AdaptiveAvgPool2DImpl::AdaptiveAvgPool2DImpl(c10::IntList output_size) + : output_size(output_size) +{ +} + +torch::Tensor AdaptiveAvgPool2DImpl::forward(torch::Tensor x) +{ + return torch::adaptive_avg_pool2d(x, output_size); +} + +AvgPool2DImpl::AvgPool2DImpl(c10::IntList kernel_size, c10::IntList stride) + : kernel_size(kernel_size), stride(stride) +{ +} + +torch::Tensor AvgPool2DImpl::forward(torch::Tensor x) +{ + return torch::avg_pool2d(x, kernel_size, stride); +} + +} // namespace visionimpl +} // namespace torchvision diff --git a/torchvision/csrc/models/visionimpl.h b/torchvision/csrc/models/visionimpl.h index 88b0ba2e33f..e3df993887e 100644 --- a/torchvision/csrc/models/visionimpl.h +++ b/torchvision/csrc/models/visionimpl.h @@ -12,21 +12,9 @@ class ReluImpl : public torch::nn::Module bool inplace; public: - inline ReluImpl(bool inplace = false) - : torch::nn::Module(), inplace(inplace) - { - } - - inline torch::Tensor forward(torch::Tensor X) - { - if (inplace) - { - X.relu_(); - return X; - } - - return torch::relu(X); - } + ReluImpl(bool inplace = false); + + torch::Tensor forward(torch::Tensor X); }; class MaxPool2DImpl : public torch::nn::Module @@ -37,20 +25,10 @@ class MaxPool2DImpl : public torch::nn::Module torch::IntList padding; public: - inline MaxPool2DImpl(int64_t kernel, int64_t stride, bool ceil_mode = false, - torch::IntList padding = torch::IntList({0})) - : torch::nn::Module(), - kernel(kernel), - stride(stride), - ceil_mode(ceil_mode), - padding(padding) - { - } - - inline torch::Tensor forward(torch::Tensor X) - { - return torch::max_pool2d(X, kernel, stride, padding, 1, ceil_mode); - } + MaxPool2DImpl(int64_t kernel, int64_t stride, bool ceil_mode = false, + torch::IntList padding = torch::IntList({0})); + + torch::Tensor forward(torch::Tensor X); }; class AdaptiveAvgPool2DImpl : public torch::nn::Module @@ -58,14 +36,9 @@ class AdaptiveAvgPool2DImpl : public torch::nn::Module torch::IntList output_size; public: - AdaptiveAvgPool2DImpl(torch::IntList output_size) : output_size(output_size) - { - } - - inline torch::Tensor forward(torch::Tensor x) - { - return torch::adaptive_avg_pool2d(x, output_size); - } + AdaptiveAvgPool2DImpl(torch::IntList output_size); + + torch::Tensor forward(torch::Tensor x); }; class AvgPool2DImpl : public torch::nn::Module @@ -73,15 +46,9 @@ class AvgPool2DImpl : public torch::nn::Module torch::IntList kernel_size, stride; public: - AvgPool2DImpl(torch::IntList kernel_size, torch::IntList stride) - : kernel_size(kernel_size), stride(stride) - { - } - - inline torch::Tensor forward(torch::Tensor x) - { - return torch::avg_pool2d(x, kernel_size, stride); - } + AvgPool2DImpl(torch::IntList kernel_size, torch::IntList stride); + + torch::Tensor forward(torch::Tensor x); }; TORCH_MODULE(Relu); From d1d8327aa8e8dc6d20981300b3b730fa8e41b00c Mon Sep 17 00:00:00 2001 From: Shahriar Date: Wed, 23 Jan 2019 14:58:23 +0330 Subject: [PATCH 07/48] fixed maxpoool2d and avgpool2d and adaptiveavgpool2d --- torchvision/csrc/models/densenet.cpp | 27 ++++++++++---------- torchvision/csrc/models/squeezenet.cpp | 14 +++++------ torchvision/csrc/models/visionimpl.cpp | 24 +++++++++--------- torchvision/csrc/models/visionimpl.h | 34 ++++++++++++++++++-------- 4 files changed, 58 insertions(+), 41 deletions(-) diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index 3bccd659791..384cc1d4f1a 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -4,6 +4,8 @@ namespace torchvision { +using Options = torch::nn::Conv2dOptions; + // TODO give modules names in sequential subclasses class _DenseLayerImpl : public torch::nn::SequentialImpl { @@ -16,18 +18,17 @@ class _DenseLayerImpl : public torch::nn::SequentialImpl { push_back(torch::nn::BatchNorm(num_input_features)); push_back(visionimpl::Relu(true)); - push_back( - torch::nn::Conv2d(torch::nn::Conv2dOptions(num_input_features, - bn_size * growth_rate, 1) - .stride(1) - .with_bias(false))); - push_back(torch::nn::BatchNorm(bn_size * growth_rate)); - push_back(visionimpl::Relu(true)); push_back(torch::nn::Conv2d( - torch::nn::Conv2dOptions(bn_size * growth_rate, growth_rate, 3) + Options(num_input_features, bn_size * growth_rate, 1) .stride(1) - .padding(1) .with_bias(false))); + push_back(torch::nn::BatchNorm(bn_size * growth_rate)); + push_back(visionimpl::Relu(true)); + push_back( + torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) + .stride(1) + .padding(1) + .with_bias(false))); } torch::Tensor forward(torch::Tensor x) @@ -72,11 +73,10 @@ class _TransitionImpl : public torch::nn::SequentialImpl push_back(torch::nn::BatchNorm(num_input_features)); push_back(visionimpl::Relu(true)); push_back(torch::nn::Conv2d( - torch::nn::Conv2dOptions(num_input_features, num_output_features, 1) + Options(num_input_features, num_output_features, 1) .stride(1) .with_bias(false))); - push_back( - visionimpl::AvgPool2D(torch::IntList({2}), torch::IntList({2}))); + push_back(visionimpl::AvgPool2D(2, 2)); } torch::Tensor forward(torch::Tensor x) @@ -99,7 +99,8 @@ DenseNetImpl::DenseNetImpl(int64_t num_classes, int64_t growth_rate, .padding(3) .with_bias(false)), torch::nn::BatchNorm(num_init_features), visionimpl::Relu(true), - visionimpl::MaxPool2D(3, 2, false, torch::IntList({1}))); + visionimpl::MaxPool2D( + visionimpl::MaxPool2DOptions(3).stride(2).padding(1))); // Each denseblock auto num_features = num_init_features; diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index 7277e250585..b21dabf36df 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -46,16 +46,16 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), visionimpl::Relu(true), - visionimpl::MaxPool2D(3, 2, true), + visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(96, 16, 64, 64), Fire(128, 16, 64, 64), Fire(128, 32, 128, 128), - visionimpl::MaxPool2D(3, 2, true), + visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(256, 32, 128, 128), Fire(256, 48, 192, 192), Fire(384, 48, 192, 192), Fire(384, 64, 256, 256), - visionimpl::MaxPool2D(3, 2, true), + visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(512, 64, 256, 256)); // clang-format on } @@ -65,13 +65,13 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), visionimpl::Relu(true), - visionimpl::MaxPool2D(3, 2, true), + visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(64, 16, 64, 64), Fire(128, 16, 64, 64), - visionimpl::MaxPool2D(3, 2, true), + visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(128, 32, 128, 128), Fire(256, 32, 128, 128), - visionimpl::MaxPool2D(3, 2, true), + visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(256, 48, 192, 192), Fire(384, 48, 192, 192), Fire(384, 64, 256, 256), @@ -94,7 +94,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) torch::nn::Dropout(0.5), final_conv, visionimpl::Relu(true), - visionimpl::AdaptiveAvgPool2D(torch::IntList({1, 1}))); + visionimpl::AdaptiveAvgPool2D(1)); // clang-format on register_module("features", features); diff --git a/torchvision/csrc/models/visionimpl.cpp b/torchvision/csrc/models/visionimpl.cpp index a86174ffb7f..b93f0e9d4aa 100644 --- a/torchvision/csrc/models/visionimpl.cpp +++ b/torchvision/csrc/models/visionimpl.cpp @@ -4,7 +4,7 @@ namespace torchvision { namespace visionimpl { -ReluImpl::ReluImpl(bool inplace) : torch::nn::Module(), inplace(inplace) {} +ReluImpl::ReluImpl(bool inplace) : inplace(inplace) {} torch::Tensor ReluImpl::forward(torch::Tensor X) { @@ -17,22 +17,23 @@ torch::Tensor ReluImpl::forward(torch::Tensor X) return torch::relu(X); } -MaxPool2DImpl::MaxPool2DImpl(int64_t kernel, int64_t stride, bool ceil_mode, - c10::IntList padding) - : torch::nn::Module(), - kernel(kernel), - stride(stride), - ceil_mode(ceil_mode), - padding(padding) +MaxPool2DImpl::MaxPool2DImpl(torch::ExpandingArray<2> kernel, + torch::ExpandingArray<2> stride) + : options(MaxPool2DOptions(kernel).stride(stride)) { } +MaxPool2DImpl::MaxPool2DImpl(MaxPool2DOptions options) : options(options) {} + torch::Tensor MaxPool2DImpl::forward(torch::Tensor X) { - return torch::max_pool2d(X, kernel, stride, padding, 1, ceil_mode); + return torch::max_pool2d(X, options.kernel_size(), options.stride(), + options.padding(), options.dilation(), + options.ceil_mode()); } -AdaptiveAvgPool2DImpl::AdaptiveAvgPool2DImpl(c10::IntList output_size) +AdaptiveAvgPool2DImpl::AdaptiveAvgPool2DImpl( + torch::ExpandingArray<2> output_size) : output_size(output_size) { } @@ -42,7 +43,8 @@ torch::Tensor AdaptiveAvgPool2DImpl::forward(torch::Tensor x) return torch::adaptive_avg_pool2d(x, output_size); } -AvgPool2DImpl::AvgPool2DImpl(c10::IntList kernel_size, c10::IntList stride) +AvgPool2DImpl::AvgPool2DImpl(torch::ExpandingArray<2> kernel_size, + torch::ExpandingArray<2> stride) : kernel_size(kernel_size), stride(stride) { } diff --git a/torchvision/csrc/models/visionimpl.h b/torchvision/csrc/models/visionimpl.h index e3df993887e..89ac78e15fc 100644 --- a/torchvision/csrc/models/visionimpl.h +++ b/torchvision/csrc/models/visionimpl.h @@ -17,36 +17,50 @@ class ReluImpl : public torch::nn::Module torch::Tensor forward(torch::Tensor X); }; +struct MaxPool2DOptions +{ + MaxPool2DOptions(torch::ExpandingArray<2> kernel_size) + : kernel_size_(kernel_size), stride_(kernel_size) + { + } + + TORCH_ARG(torch::ExpandingArray<2>, kernel_size); + TORCH_ARG(torch::ExpandingArray<2>, stride); + TORCH_ARG(torch::ExpandingArray<2>, padding) = 0; + TORCH_ARG(torch::ExpandingArray<2>, dilation) = 1; + TORCH_ARG(bool, ceil_mode) = false; +}; + class MaxPool2DImpl : public torch::nn::Module { - int64_t kernel; - int64_t stride; - bool ceil_mode; - torch::IntList padding; + MaxPool2DOptions options; public: - MaxPool2DImpl(int64_t kernel, int64_t stride, bool ceil_mode = false, - torch::IntList padding = torch::IntList({0})); + MaxPool2DImpl(torch::ExpandingArray<2> kernel, + torch::ExpandingArray<2> stride); + + explicit MaxPool2DImpl(MaxPool2DOptions options); torch::Tensor forward(torch::Tensor X); }; class AdaptiveAvgPool2DImpl : public torch::nn::Module { - torch::IntList output_size; + torch::ExpandingArray<2> output_size; public: - AdaptiveAvgPool2DImpl(torch::IntList output_size); + AdaptiveAvgPool2DImpl(torch::ExpandingArray<2> output_size); torch::Tensor forward(torch::Tensor x); }; class AvgPool2DImpl : public torch::nn::Module { - torch::IntList kernel_size, stride; + torch::ExpandingArray<2> kernel_size, stride; public: - AvgPool2DImpl(torch::IntList kernel_size, torch::IntList stride); + AvgPool2DImpl(torch::ExpandingArray<2> kernel_size, + torch::ExpandingArray<2> stride); torch::Tensor forward(torch::Tensor x); }; From 24b543bf59b88170b5de43ce8aee8fda12d113b9 Mon Sep 17 00:00:00 2001 From: Shahriar Date: Fri, 25 Jan 2019 18:46:52 +0330 Subject: [PATCH 08/48] Fixed a few stuff Moved cmakelists to root and changed the namespace to vision and wrote weight initialization in inception --- CMakeLists.txt | 14 ++++ torchvision/CMakeLists.txt | 16 ----- torchvision/csrc/models/alexnet.cpp | 2 +- torchvision/csrc/models/alexnet.h | 2 +- torchvision/csrc/models/densenet.cpp | 2 +- torchvision/csrc/models/densenet.h | 6 +- torchvision/csrc/models/inception.cpp | 26 +++++-- torchvision/csrc/models/inception.h | 6 +- torchvision/csrc/models/main.cpp | 94 +++----------------------- torchvision/csrc/models/resnet.cpp | 2 +- torchvision/csrc/models/resnet.h | 6 +- torchvision/csrc/models/squeezenet.cpp | 2 +- torchvision/csrc/models/squeezenet.h | 2 +- torchvision/csrc/models/vgg.cpp | 2 +- torchvision/csrc/models/vgg.h | 2 +- torchvision/csrc/models/visionimpl.cpp | 2 +- torchvision/csrc/models/visionimpl.h | 4 +- 17 files changed, 64 insertions(+), 126 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 torchvision/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000000..b441d769119 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8) +project(TorchVision) +set(CMAKE_CXX_STANDARD 11) + +file(GLOB_RECURSE HEADERS torchvision/csrc/models/*.h) +file(GLOB_RECURSE SOURCES torchvision/csrc/models/*.h torchvision/csrc/models/*.cpp) +add_executable(${PROJECT_NAME} ${SOURCES}) + +set(CUDNN_INCLUDE_DIR /usr/include/cuda) +find_package(Torch REQUIRED) +target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}") + +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) +install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/torchvision) diff --git a/torchvision/CMakeLists.txt b/torchvision/CMakeLists.txt deleted file mode 100644 index b6fcfa4d763..00000000000 --- a/torchvision/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -project(TorchVision) -set(CMAKE_CXX_STANDARD 11) - -file(GLOB_RECURSE HEADERS csrc/models/*.h) -file(GLOB_RECURSE SOURCES csrc/models/*.h csrc/models/*.cpp) -add_executable(${PROJECT_NAME} ${SOURCES}) - -set(CUDNN_INCLUDE_DIR /usr/include/cuda) -find_package(Torch REQUIRED) -target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}") - -set(INSTALL_PATH /usr/local/torchvision) - -install(TARGETS ${PROJECT_NAME} DESTINATION ${INSTALL_PATH}/lib) -install(FILES ${HEADERS} DESTINATION ${INSTALL_PATH}/include/torchvision) diff --git a/torchvision/csrc/models/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp index 5b53b66d72b..0e521cb4ffb 100644 --- a/torchvision/csrc/models/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -2,7 +2,7 @@ #include "visionimpl.h" -namespace torchvision +namespace vision { AlexNetImpl::AlexNetImpl(int64_t num_classes) { diff --git a/torchvision/csrc/models/alexnet.h b/torchvision/csrc/models/alexnet.h index 89ba7817cdc..10a3c9aa0ae 100644 --- a/torchvision/csrc/models/alexnet.h +++ b/torchvision/csrc/models/alexnet.h @@ -3,7 +3,7 @@ #include -namespace torchvision +namespace vision { // AlexNet model architecture from the // "One weird trick..." paper. diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index 384cc1d4f1a..e898dabaed2 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -2,7 +2,7 @@ #include "visionimpl.h" -namespace torchvision +namespace vision { using Options = torch::nn::Conv2dOptions; diff --git a/torchvision/csrc/models/densenet.h b/torchvision/csrc/models/densenet.h index d9d68c28f07..53a54a264ea 100644 --- a/torchvision/csrc/models/densenet.h +++ b/torchvision/csrc/models/densenet.h @@ -3,13 +3,14 @@ #include -namespace torchvision +namespace vision { // Densenet-BC model class, based on // "Densely Connected Convolutional Networks" // // Args: +// num_classes (int) - number of classification classes // growth_rate (int) - how many filters to add each layer (`k` in paper) // block_config (list of 4 ints) - how many layers in each pooling block // num_init_features (int) - the number of filters to learn in the first @@ -17,7 +18,6 @@ namespace torchvision // bn_size (int) - multiplicative factor for number of bottle neck layers // (i.e. bn_size * k features in the bottleneck layer) // drop_rate (float) - dropout rate after each dense layer -// num_classes (int) - number of classification classes class DenseNetImpl : public torch::nn::Module { torch::nn::Sequential features{nullptr}; @@ -74,6 +74,6 @@ TORCH_MODULE(DenseNet169); TORCH_MODULE(DenseNet201); TORCH_MODULE(DenseNet161); -} // namespace torchvision +} // namespace vision #endif // DENSENET_H diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 2fa301d7d5b..6f601188d00 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -1,6 +1,6 @@ #include "inception.h" -namespace torchvision +namespace vision { using Options = torch::nn::Conv2dOptions; @@ -240,6 +240,22 @@ torch::Tensor InceptionAuxImpl::forward(torch::Tensor x) } // namespace _inceptionimpl +void init_weight(at::Tensor &weight, double stddev) +{ + // auto temp = torch::fmod(torch::randn(weight.sizes()), 2); + // weight = temp.mul(stddev); + + std::vector sizes; + for (auto i : weight.sizes()) sizes.push_back(i); + sizes.push_back(4); + + auto tmp = torch::empty(sizes, weight.options()).normal_(); + auto valid = (tmp < 2).__and__(tmp > -2); + auto ind = std::get<1>(valid.max(-1, true)); + weight = tmp.gather(-1, ind).squeeze(-1); + weight.mul_(stddev); +} + InceptionV3Impl::InceptionV3Impl(int64_t num_classes, bool aux_logits, bool transform_input) : aux_logits(aux_logits), transform_input(transform_input) @@ -295,13 +311,13 @@ InceptionV3Impl::InceptionV3Impl(int64_t num_classes, bool aux_logits, if (_inceptionimpl::AuxLinearImpl *M = dynamic_cast<_inceptionimpl::AuxLinearImpl *>(module.get())) - _inceptionimpl::init_weight(M->weight, M->stddev); + init_weight(M->weight, M->stddev); else if (torch::nn::Conv2dImpl *M = dynamic_cast(module.get())) - _inceptionimpl::init_weight(M->weight, 0.1); + init_weight(M->weight, 0.1); else if (torch::nn::LinearImpl *M = dynamic_cast(module.get())) - _inceptionimpl::init_weight(M->weight, 0.1); + init_weight(M->weight, 0.1); else if (torch::nn::BatchNormImpl *M = dynamic_cast(module.get())) { @@ -379,4 +395,4 @@ torch::TensorList InceptionV3Impl::forward(torch::Tensor x) } // namespace _inceptionimpl -} // namespace torchvision +} // namespace vision diff --git a/torchvision/csrc/models/inception.h b/torchvision/csrc/models/inception.h index bf538e76f5a..e9a795dcf6a 100644 --- a/torchvision/csrc/models/inception.h +++ b/torchvision/csrc/models/inception.h @@ -3,7 +3,7 @@ #include -namespace torchvision +namespace vision { namespace _inceptionimpl { @@ -117,8 +117,6 @@ TORCH_MODULE(InceptionD); TORCH_MODULE(InceptionE); TORCH_MODULE(InceptionAux); -inline void init_weight(torch::Tensor &weight, double stddev) {} - } // namespace _inceptionimpl // Inception v3 model architecture from @@ -149,6 +147,6 @@ class InceptionV3Impl : public torch::nn::Module TORCH_MODULE(InceptionV3); -} // namespace torchvision +} // namespace vision #endif // INCEPTION_H diff --git a/torchvision/csrc/models/main.cpp b/torchvision/csrc/models/main.cpp index a4f7bcd7f64..0e50e86b21d 100644 --- a/torchvision/csrc/models/main.cpp +++ b/torchvision/csrc/models/main.cpp @@ -1,7 +1,7 @@ #include #include "vision.h" -using namespace torchvision; +using namespace vision; // TODO change xavier fill @@ -38,91 +38,15 @@ void process(torch::Tensor X, std::string name) #define PROCESS(M, X) process(X, #M) -int main() +void init_weight(at::Tensor &weight, double stddev) { - auto X = torch::rand({1, 3, 224, 224}); - - // AlexNet A; - // A->forward(X); - // std::cout << "AlexNet Done. #Params: " << params(A) << std::endl; - - // VGG11 V11; - // V11->forward(X); - // std::cout << "VGG11 Done. #Params: " << params(V11) << std::endl; - - // VGG13 V13; - // V13->forward(X); - // std::cout << "VGG13 Done. #Params: " << params(V13) << std::endl; - - // VGG16 V16; - // V16->forward(X); - // std::cout << "VGG16 Done. #Params: " << params(V16) << std::endl; - - // VGG19 V19; - // V19->forward(X); - // std::cout << "VGG19 Done. #Params: " << params(V19) << std::endl; - - // VGG11BN V11BN; - // V11BN->forward(X); - // std::cout << "VGG11BN Done. #Params: " << params(V11BN) << std::endl; - - // VGG13BN V13BN; - // V13BN->forward(X); - // std::cout << "VGG13BN Done. #Params: " << params(V13BN) << std::endl; - - // VGG16BN V16BN; - // V16BN->forward(X); - // std::cout << "VGG16BN Done. #Params: " << params(V16BN) << std::endl; - - // VGG19BN V19BN; - // V19BN->forward(X); - // std::cout << "VGG19BN Done. #Params: " << params(V19BN) << std::endl; - - // ResNet18 R18; - // R18->forward(X); - // std::cout << "ResNet18 Done. #Params: " << params(R18) << std::endl; - - // ResNet34 R34; - // R34->forward(X); - // std::cout << "ResNet34 Done. #Params: " << params(R34) << std::endl; - - // ResNet50 R50; - // R50->forward(X); - // std::cout << "ResNet50 Done. #Params: " << params(R50) << std::endl; - - // ResNet101 R101; - // R101->forward(X); - // std::cout << "ResNet101 Done. #Params: " << params(R101) << std::endl; - - // ResNet152 R152; - // R152->forward(X); - // std::cout << "ResNet152 Done. #Params: " << params(R152) << std::endl; - - // SqueezeNet1_0 S10; - // S10->forward(X); - // std::cout << "SqueezeNet1.0 Done. #Params: " << params(S10) << - // std::endl; - - // SqueezeNet1_1 S11; - // S11->forward(X); - // std::cout << "SqueezeNet1.1 Done. #Params: " << params(S11) << - // std::endl; - - // DenseNet121 D121; - // D121->forward(X); - // std::cout << "DenseNet121 Done. #Params: " << params(D121) << std::endl; - - // DenseNet169 D169; - // D169->forward(X); - // std::cout << "DenseNet169 Done. #Params: " << params(D169) << std::endl; - - // DenseNet201 D201; - // D201->forward(X); - // std::cout << "DenseNet201 Done. #Params: " << params(D201) << std::endl; + auto temp = torch::fmod(torch::randn(weight.sizes()), 2); + weight = temp.mul(stddev); +} - // DenseNet161 D161; - // D161->forward(X); - // std::cout << "DenseNet161 Done. #Params: " << params(D161) << std::endl; +int main(int argc, const char *argv[]) +{ + auto X = torch::rand({1, 3, 224, 224}); PROCESS(AlexNet, X); PROCESS(VGG11, X); @@ -144,6 +68,8 @@ int main() PROCESS(DenseNet169, X); PROCESS(DenseNet201, X); PROCESS(DenseNet161, X); + + X = torch::rand({2, 3, 299, 299}); PROCESS(InceptionV3, X); return 0; diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index c169c726504..701847e1acb 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -2,7 +2,7 @@ #include "visionimpl.h" -namespace torchvision +namespace vision { namespace _resnetimpl { diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 1c25f3b363d..dae6176819a 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -3,7 +3,7 @@ #include -namespace torchvision +namespace vision { template class ResNetImpl; @@ -18,7 +18,7 @@ torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride = 1); class BasicBlock : public torch::nn::Module { template - friend class torchvision::ResNetImpl; + friend class vision::ResNetImpl; int64_t stride; torch::nn::Sequential downsample; @@ -38,7 +38,7 @@ class BasicBlock : public torch::nn::Module class Bottleneck : public torch::nn::Module { template - friend class torchvision::ResNetImpl; + friend class vision::ResNetImpl; int64_t stride; torch::nn::Sequential downsample; diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index b21dabf36df..2425f127d1d 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -3,7 +3,7 @@ #include #include "visionimpl.h" -namespace torchvision +namespace vision { class Fire : public torch::nn::Module { diff --git a/torchvision/csrc/models/squeezenet.h b/torchvision/csrc/models/squeezenet.h index fb326cea9e8..3c57e59242e 100644 --- a/torchvision/csrc/models/squeezenet.h +++ b/torchvision/csrc/models/squeezenet.h @@ -3,7 +3,7 @@ #include -namespace torchvision +namespace vision { class SqueezeNetImpl : public torch::nn::Module { diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index 7e8c362e868..760012c5f6e 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -3,7 +3,7 @@ #include #include "visionimpl.h" -namespace torchvision +namespace vision { torch::nn::Sequential makeLayers(const std::vector &cfg, bool batch_norm = false) diff --git a/torchvision/csrc/models/vgg.h b/torchvision/csrc/models/vgg.h index 15b878f957c..938919cc93b 100644 --- a/torchvision/csrc/models/vgg.h +++ b/torchvision/csrc/models/vgg.h @@ -3,7 +3,7 @@ #include -namespace torchvision +namespace vision { class VGGImpl : public torch::nn::Module { diff --git a/torchvision/csrc/models/visionimpl.cpp b/torchvision/csrc/models/visionimpl.cpp index b93f0e9d4aa..7d03d943278 100644 --- a/torchvision/csrc/models/visionimpl.cpp +++ b/torchvision/csrc/models/visionimpl.cpp @@ -1,6 +1,6 @@ #include "visionimpl.h" -namespace torchvision +namespace vision { namespace visionimpl { diff --git a/torchvision/csrc/models/visionimpl.h b/torchvision/csrc/models/visionimpl.h index 89ac78e15fc..3e91dafaf59 100644 --- a/torchvision/csrc/models/visionimpl.h +++ b/torchvision/csrc/models/visionimpl.h @@ -3,7 +3,7 @@ #include -namespace torchvision +namespace vision { namespace visionimpl { @@ -71,6 +71,6 @@ TORCH_MODULE(AvgPool2D); TORCH_MODULE(AdaptiveAvgPool2D); } // namespace visionimpl -} // namespace torchvision +} // namespace vision #endif // VISIONIMPL_H From a30b4b09187cf14f548c0d4cf734fb8229724484 Mon Sep 17 00:00:00 2001 From: Shahriar Date: Fri, 25 Jan 2019 19:35:46 +0330 Subject: [PATCH 09/48] Added models namespace and changed cmakelists the project is now installable --- CMakeLists.txt | 12 +-- torchvision/csrc/models/alexnet.cpp | 27 ++++--- torchvision/csrc/models/alexnet.h | 5 +- torchvision/csrc/models/densenet.cpp | 21 ++--- torchvision/csrc/models/densenet.h | 3 + torchvision/csrc/models/inception.cpp | 3 + torchvision/csrc/models/inception.h | 3 + torchvision/csrc/models/main.cpp | 76 ------------------- .../csrc/models/{vision.h => models.h} | 8 +- .../models/{visionimpl.cpp => modelsimpl.cpp} | 11 ++- .../models/{visionimpl.h => modelsimpl.h} | 13 ++-- torchvision/csrc/models/resnet.cpp | 7 +- torchvision/csrc/models/resnet.h | 9 ++- torchvision/csrc/models/squeezenet.cpp | 27 ++++--- torchvision/csrc/models/squeezenet.h | 5 +- torchvision/csrc/models/vgg.cpp | 15 ++-- torchvision/csrc/models/vgg.h | 5 +- torchvision/csrc/vision.h | 6 ++ 18 files changed, 116 insertions(+), 140 deletions(-) delete mode 100644 torchvision/csrc/models/main.cpp rename torchvision/csrc/models/{vision.h => models.h} (56%) rename torchvision/csrc/models/{visionimpl.cpp => modelsimpl.cpp} (89%) rename torchvision/csrc/models/{visionimpl.h => modelsimpl.h} (90%) create mode 100644 torchvision/csrc/vision.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b441d769119..ae34ab590af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,16 @@ cmake_minimum_required(VERSION 2.8) -project(TorchVision) +project(torchvision) set(CMAKE_CXX_STANDARD 11) -file(GLOB_RECURSE HEADERS torchvision/csrc/models/*.h) -file(GLOB_RECURSE SOURCES torchvision/csrc/models/*.h torchvision/csrc/models/*.cpp) -add_executable(${PROJECT_NAME} ${SOURCES}) +file(GLOB_RECURSE HEADERS torchvision/csrc/vision.h) +file(GLOB_RECURSE MODELS_HEADERS torchvision/csrc/models/*.h) +file(GLOB_RECURSE MODELS_SOURCES torchvision/csrc/models/*.h torchvision/csrc/models/*.cpp) +add_library (${PROJECT_NAME} SHARED ${MODELS_SOURCES}) set(CUDNN_INCLUDE_DIR /usr/include/cuda) find_package(Torch REQUIRED) target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}") install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) -install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/torchvision) +install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}) +install(FILES ${MODELS_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/models) diff --git a/torchvision/csrc/models/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp index 0e521cb4ffb..c7ad4ecbe0c 100644 --- a/torchvision/csrc/models/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -1,34 +1,36 @@ #include "alexnet.h" -#include "visionimpl.h" +#include "modelsimpl.h" namespace vision { +namespace models +{ AlexNetImpl::AlexNetImpl(int64_t num_classes) { // clang-format off features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), - visionimpl::Relu(true), - visionimpl::MaxPool2D(3, 2), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D(3, 2), torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 192, 5).padding(2)), - visionimpl::Relu(true), - visionimpl::MaxPool2D(3, 2), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D(3, 2), torch::nn::Conv2d(torch::nn::Conv2dOptions(192, 384, 3).padding(1)), - visionimpl::Relu(true), + modelsimpl::Relu(true), torch::nn::Conv2d(torch::nn::Conv2dOptions(384, 256, 3).padding(1)), - visionimpl::Relu(true), + modelsimpl::Relu(true), torch::nn::Conv2d(torch::nn::Conv2dOptions(256, 256, 3).padding(1)), - visionimpl::Relu(true), - visionimpl::MaxPool2D(3, 2)); + modelsimpl::Relu(true), + modelsimpl::MaxPool2D(3, 2)); classifier = torch::nn::Sequential( torch::nn::Dropout(), torch::nn::Linear(256 * 6 * 6, 4096), - visionimpl::Relu(true), + modelsimpl::Relu(true), torch::nn::Dropout(), torch::nn::Linear(4096, 4096), - visionimpl::Relu(true), + modelsimpl::Relu(true), torch::nn::Linear(4096, num_classes)); // clang-format on @@ -45,4 +47,5 @@ torch::Tensor AlexNetImpl::forward(torch::Tensor x) return x; } -} // namespace torchvision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/alexnet.h b/torchvision/csrc/models/alexnet.h index 10a3c9aa0ae..b155f401c1d 100644 --- a/torchvision/csrc/models/alexnet.h +++ b/torchvision/csrc/models/alexnet.h @@ -5,6 +5,8 @@ namespace vision { +namespace models +{ // AlexNet model architecture from the // "One weird trick..." paper. class AlexNetImpl : public torch::nn::Module @@ -19,6 +21,7 @@ class AlexNetImpl : public torch::nn::Module TORCH_MODULE(AlexNet); -} // namespace torchvision +} // namespace models +} // namespace vision #endif // ALEXNET_H diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index e898dabaed2..f5f4b2d6444 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -1,9 +1,11 @@ #include "densenet.h" -#include "visionimpl.h" +#include "modelsimpl.h" namespace vision { +namespace models +{ using Options = torch::nn::Conv2dOptions; // TODO give modules names in sequential subclasses @@ -17,13 +19,13 @@ class _DenseLayerImpl : public torch::nn::SequentialImpl : drop_rate(drop_rate) { push_back(torch::nn::BatchNorm(num_input_features)); - push_back(visionimpl::Relu(true)); + push_back(modelsimpl::Relu(true)); push_back(torch::nn::Conv2d( Options(num_input_features, bn_size * growth_rate, 1) .stride(1) .with_bias(false))); push_back(torch::nn::BatchNorm(bn_size * growth_rate)); - push_back(visionimpl::Relu(true)); + push_back(modelsimpl::Relu(true)); push_back( torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) .stride(1) @@ -71,12 +73,12 @@ class _TransitionImpl : public torch::nn::SequentialImpl _TransitionImpl(int64_t num_input_features, int64_t num_output_features) { push_back(torch::nn::BatchNorm(num_input_features)); - push_back(visionimpl::Relu(true)); + push_back(modelsimpl::Relu(true)); push_back(torch::nn::Conv2d( Options(num_input_features, num_output_features, 1) .stride(1) .with_bias(false))); - push_back(visionimpl::AvgPool2D(2, 2)); + push_back(modelsimpl::AvgPool2D(2, 2)); } torch::Tensor forward(torch::Tensor x) @@ -98,9 +100,9 @@ DenseNetImpl::DenseNetImpl(int64_t num_classes, int64_t growth_rate, .stride(2) .padding(3) .with_bias(false)), - torch::nn::BatchNorm(num_init_features), visionimpl::Relu(true), - visionimpl::MaxPool2D( - visionimpl::MaxPool2DOptions(3).stride(2).padding(1))); + torch::nn::BatchNorm(num_init_features), modelsimpl::Relu(true), + modelsimpl::MaxPool2D( + modelsimpl::MaxPool2DOptions(3).stride(2).padding(1))); // Each denseblock auto num_features = num_init_features; @@ -191,4 +193,5 @@ DenseNet161Impl::DenseNet161Impl(int64_t num_classes, int64_t growth_rate, { } -} // namespace torchvision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/densenet.h b/torchvision/csrc/models/densenet.h index 53a54a264ea..3dd85f6bc4b 100644 --- a/torchvision/csrc/models/densenet.h +++ b/torchvision/csrc/models/densenet.h @@ -5,6 +5,8 @@ namespace vision { +namespace models +{ // Densenet-BC model class, based on // "Densely Connected Convolutional Networks" // @@ -74,6 +76,7 @@ TORCH_MODULE(DenseNet169); TORCH_MODULE(DenseNet201); TORCH_MODULE(DenseNet161); +} // namespace models } // namespace vision #endif // DENSENET_H diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 6f601188d00..67648b2f952 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -2,6 +2,8 @@ namespace vision { +namespace models +{ using Options = torch::nn::Conv2dOptions; namespace _inceptionimpl @@ -395,4 +397,5 @@ torch::TensorList InceptionV3Impl::forward(torch::Tensor x) } // namespace _inceptionimpl +} // namespace models } // namespace vision diff --git a/torchvision/csrc/models/inception.h b/torchvision/csrc/models/inception.h index e9a795dcf6a..c61288f3705 100644 --- a/torchvision/csrc/models/inception.h +++ b/torchvision/csrc/models/inception.h @@ -5,6 +5,8 @@ namespace vision { +namespace models +{ namespace _inceptionimpl { class BasicConv2dImpl : public torch::nn::Module @@ -147,6 +149,7 @@ class InceptionV3Impl : public torch::nn::Module TORCH_MODULE(InceptionV3); +} // namespace models } // namespace vision #endif // INCEPTION_H diff --git a/torchvision/csrc/models/main.cpp b/torchvision/csrc/models/main.cpp deleted file mode 100644 index 0e50e86b21d..00000000000 --- a/torchvision/csrc/models/main.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include "vision.h" - -using namespace vision; - -// TODO change xavier fill - -template -long params(T &M) -{ - long sum = 0; - for (const auto &P : M->parameters()) - { - long size = 1; - for (const auto &S : P.sizes()) size *= S; - sum += size; - } - - return sum; -} - -template -void process(torch::Tensor X, std::string name) -{ - auto device = torch::kCPU; - T M; - M->to(device); - - M->train(); - M->forward(X.to(device)); - - M->eval(); - M->forward(X.to(device)); - - std::cout << name + " Done. Params: " << params(M) << " : " - << params(M) / 1000000 << std::endl; -} - -#define PROCESS(M, X) process(X, #M) - -void init_weight(at::Tensor &weight, double stddev) -{ - auto temp = torch::fmod(torch::randn(weight.sizes()), 2); - weight = temp.mul(stddev); -} - -int main(int argc, const char *argv[]) -{ - auto X = torch::rand({1, 3, 224, 224}); - - PROCESS(AlexNet, X); - PROCESS(VGG11, X); - PROCESS(VGG13, X); - PROCESS(VGG16, X); - PROCESS(VGG19, X); - PROCESS(VGG11BN, X); - PROCESS(VGG13BN, X); - PROCESS(VGG16BN, X); - PROCESS(VGG19BN, X); - PROCESS(ResNet18, X); - PROCESS(ResNet34, X); - PROCESS(ResNet50, X); - PROCESS(ResNet101, X); - PROCESS(ResNet152, X); - PROCESS(SqueezeNet1_0, X); - PROCESS(SqueezeNet1_1, X); - PROCESS(DenseNet121, X); - PROCESS(DenseNet169, X); - PROCESS(DenseNet201, X); - PROCESS(DenseNet161, X); - - X = torch::rand({2, 3, 299, 299}); - PROCESS(InceptionV3, X); - - return 0; -} diff --git a/torchvision/csrc/models/vision.h b/torchvision/csrc/models/models.h similarity index 56% rename from torchvision/csrc/models/vision.h rename to torchvision/csrc/models/models.h index 43d87bcc8df..8583c9c5a48 100644 --- a/torchvision/csrc/models/vision.h +++ b/torchvision/csrc/models/models.h @@ -1,5 +1,7 @@ -#ifndef VISION_H -#define VISION_H +#ifndef MODELS_H +#define MODELS_H + +// TODO change xavier fills to kaiming fills #include "alexnet.h" #include "densenet.h" @@ -8,4 +10,4 @@ #include "squeezenet.h" #include "vgg.h" -#endif // VISION_H +#endif // MODELS_H diff --git a/torchvision/csrc/models/visionimpl.cpp b/torchvision/csrc/models/modelsimpl.cpp similarity index 89% rename from torchvision/csrc/models/visionimpl.cpp rename to torchvision/csrc/models/modelsimpl.cpp index 7d03d943278..69b16330db0 100644 --- a/torchvision/csrc/models/visionimpl.cpp +++ b/torchvision/csrc/models/modelsimpl.cpp @@ -1,8 +1,10 @@ -#include "visionimpl.h" +#include "modelsimpl.h" namespace vision { -namespace visionimpl +namespace models +{ +namespace modelsimpl { ReluImpl::ReluImpl(bool inplace) : inplace(inplace) {} @@ -54,5 +56,6 @@ torch::Tensor AvgPool2DImpl::forward(torch::Tensor x) return torch::avg_pool2d(x, kernel_size, stride); } -} // namespace visionimpl -} // namespace torchvision +} // namespace modelsimpl +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/visionimpl.h b/torchvision/csrc/models/modelsimpl.h similarity index 90% rename from torchvision/csrc/models/visionimpl.h rename to torchvision/csrc/models/modelsimpl.h index 3e91dafaf59..b50a108b690 100644 --- a/torchvision/csrc/models/visionimpl.h +++ b/torchvision/csrc/models/modelsimpl.h @@ -1,11 +1,13 @@ -#ifndef VISIONIMPL_H -#define VISIONIMPL_H +#ifndef MODELSIMPL_H +#define MODELSIMPL_H #include namespace vision { -namespace visionimpl +namespace models +{ +namespace modelsimpl { class ReluImpl : public torch::nn::Module { @@ -70,7 +72,8 @@ TORCH_MODULE(MaxPool2D); TORCH_MODULE(AvgPool2D); TORCH_MODULE(AdaptiveAvgPool2D); -} // namespace visionimpl +} // namespace modelsimpl +} // namespace models } // namespace vision -#endif // VISIONIMPL_H +#endif // MODELSIMPL_H diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index 701847e1acb..743d44400be 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -1,9 +1,11 @@ #include "resnet.h" -#include "visionimpl.h" +#include "modelsimpl.h" namespace vision { +namespace models +{ namespace _resnetimpl { torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride) @@ -124,4 +126,5 @@ ResNet152Impl::ResNet152Impl(int64_t num_classes, bool zero_init_residual) { } -} // namespace torchvision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index dae6176819a..02ee3d25319 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -5,6 +5,8 @@ namespace vision { +namespace models +{ template class ResNetImpl; @@ -18,7 +20,7 @@ torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride = 1); class BasicBlock : public torch::nn::Module { template - friend class vision::ResNetImpl; + friend class vision::models::ResNetImpl; int64_t stride; torch::nn::Sequential downsample; @@ -38,7 +40,7 @@ class BasicBlock : public torch::nn::Module class Bottleneck : public torch::nn::Module { template - friend class vision::ResNetImpl; + friend class vision::models::ResNetImpl; int64_t stride; torch::nn::Sequential downsample; @@ -221,6 +223,7 @@ TORCH_MODULE(ResNet50); TORCH_MODULE(ResNet101); TORCH_MODULE(ResNet152); -} // namespace torchvision +} // namespace models +} // namespace vision #endif // RESNET_H diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index 2425f127d1d..dae057a5d32 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -1,10 +1,12 @@ #include "squeezenet.h" #include -#include "visionimpl.h" +#include "modelsimpl.h" namespace vision { +namespace models +{ class Fire : public torch::nn::Module { torch::nn::Conv2d squeeze, expand1x1, expand3x3; @@ -45,17 +47,17 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) // clang-format off features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), - visionimpl::Relu(true), - visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(96, 16, 64, 64), Fire(128, 16, 64, 64), Fire(128, 32, 128, 128), - visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(256, 32, 128, 128), Fire(256, 48, 192, 192), Fire(384, 48, 192, 192), Fire(384, 64, 256, 256), - visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(512, 64, 256, 256)); // clang-format on } @@ -64,14 +66,14 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) // clang-format off features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), - visionimpl::Relu(true), - visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(64, 16, 64, 64), Fire(128, 16, 64, 64), - visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(128, 32, 128, 128), Fire(256, 32, 128, 128), - visionimpl::MaxPool2D(visionimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(256, 48, 192, 192), Fire(384, 48, 192, 192), Fire(384, 64, 256, 256), @@ -93,8 +95,8 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) classifier = torch::nn::Sequential( torch::nn::Dropout(0.5), final_conv, - visionimpl::Relu(true), - visionimpl::AdaptiveAvgPool2D(1)); + modelsimpl::Relu(true), + modelsimpl::AdaptiveAvgPool2D(1)); // clang-format on register_module("features", features); @@ -130,4 +132,5 @@ SqueezeNet1_1Impl::SqueezeNet1_1Impl(int64_t num_classes) { } -} // namespace torchvision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/squeezenet.h b/torchvision/csrc/models/squeezenet.h index 3c57e59242e..da2678196ce 100644 --- a/torchvision/csrc/models/squeezenet.h +++ b/torchvision/csrc/models/squeezenet.h @@ -5,6 +5,8 @@ namespace vision { +namespace models +{ class SqueezeNetImpl : public torch::nn::Module { int64_t num_classes; @@ -39,6 +41,7 @@ TORCH_MODULE(SqueezeNet); TORCH_MODULE(SqueezeNet1_0); TORCH_MODULE(SqueezeNet1_1); -} // namespace torchvision +} // namespace models +} // namespace vision #endif // SQUEEZENET_H diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index 760012c5f6e..0c147f2b151 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -1,10 +1,12 @@ #include "vgg.h" #include -#include "visionimpl.h" +#include "modelsimpl.h" namespace vision { +namespace models +{ torch::nn::Sequential makeLayers(const std::vector &cfg, bool batch_norm = false) { @@ -14,14 +16,14 @@ torch::nn::Sequential makeLayers(const std::vector &cfg, for (const auto &V : cfg) { if (V <= -1) - seq->push_back(visionimpl::MaxPool2D(2, 2)); + seq->push_back(modelsimpl::MaxPool2D(2, 2)); else { seq->push_back(torch::nn::Conv2d( torch::nn::Conv2dOptions(channels, V, 3).padding(1))); if (batch_norm) seq->push_back(torch::nn::BatchNorm(V)); - seq->push_back(visionimpl::Relu(true)); + seq->push_back(modelsimpl::Relu(true)); channels = V; } @@ -61,10 +63,10 @@ VGGImpl::VGGImpl(torch::nn::Sequential features, int64_t num_classes, // clang-format off classifier = torch::nn::Sequential( torch::nn::Linear(512 * 7 * 7, 4096), - visionimpl::Relu(true), + modelsimpl::Relu(true), torch::nn::Dropout(), torch::nn::Linear(4096, 4096), - visionimpl::Relu(true), + modelsimpl::Relu(true), torch::nn::Dropout(), torch::nn::Linear(4096, num_classes)); // clang-format on @@ -133,4 +135,5 @@ VGG19BNImpl::VGG19BNImpl(int64_t num_classes, bool initWeights) { } -} // namespace torchvision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/vgg.h b/torchvision/csrc/models/vgg.h index 938919cc93b..932b30608a6 100644 --- a/torchvision/csrc/models/vgg.h +++ b/torchvision/csrc/models/vgg.h @@ -5,6 +5,8 @@ namespace vision { +namespace models +{ class VGGImpl : public torch::nn::Module { torch::nn::Sequential features{nullptr}, classifier{nullptr}; @@ -86,6 +88,7 @@ TORCH_MODULE(VGG13BN); TORCH_MODULE(VGG16BN); TORCH_MODULE(VGG19BN); -} // namespace torchvision +} // namespace models +} // namespace vision #endif // VGG_H diff --git a/torchvision/csrc/vision.h b/torchvision/csrc/vision.h new file mode 100644 index 00000000000..120eb034f38 --- /dev/null +++ b/torchvision/csrc/vision.h @@ -0,0 +1,6 @@ +#ifndef VISION_H +#define VISION_H + +#include + +#endif // VISION_H From 19eb406cd00b99864441454261a983a5c078b6c7 Mon Sep 17 00:00:00 2001 From: Shahriar Date: Sat, 26 Jan 2019 20:09:26 +0330 Subject: [PATCH 10/48] Removed some comments --- torchvision/csrc/models/densenet.cpp | 1 - torchvision/csrc/models/inception.cpp | 2 -- torchvision/csrc/models/models.h | 4 +--- torchvision/csrc/models/resnet.h | 3 --- 4 files changed, 1 insertion(+), 9 deletions(-) diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index f5f4b2d6444..b2c622c833f 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -8,7 +8,6 @@ namespace models { using Options = torch::nn::Conv2dOptions; -// TODO give modules names in sequential subclasses class _DenseLayerImpl : public torch::nn::SequentialImpl { double drop_rate; diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 67648b2f952..cab1d64907f 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -309,8 +309,6 @@ InceptionV3Impl::InceptionV3Impl(int64_t num_classes, bool aux_logits, for (auto &module : modules(false)) { - // TODO there is an error in inception that is related to AuxBasicConv - if (_inceptionimpl::AuxLinearImpl *M = dynamic_cast<_inceptionimpl::AuxLinearImpl *>(module.get())) init_weight(M->weight, M->stddev); diff --git a/torchvision/csrc/models/models.h b/torchvision/csrc/models/models.h index 8583c9c5a48..009717018c6 100644 --- a/torchvision/csrc/models/models.h +++ b/torchvision/csrc/models/models.h @@ -1,8 +1,6 @@ #ifndef MODELS_H #define MODELS_H -// TODO change xavier fills to kaiming fills - #include "alexnet.h" #include "densenet.h" #include "inception.h" @@ -10,4 +8,4 @@ #include "squeezenet.h" #include "vgg.h" -#endif // MODELS_H +#endif // MODELS_H diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 02ee3d25319..25b9807c295 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -82,9 +82,6 @@ torch::nn::Sequential ResNetImpl::_make_layer(int64_t planes, int64_t blocks, int64_t stride) { - // TODO Blocks that are created here are not shared_ptr. see if that is a - // problem (the layers in blocks are used in the resnet constructor). - torch::nn::Sequential downsample = nullptr; if (stride != 1 || inplanes != planes * Block::expantion) { From 6deac40483d85ce23d65c910b294bdd6507e90ec Mon Sep 17 00:00:00 2001 From: Shahriar Date: Tue, 12 Feb 2019 14:36:56 +0330 Subject: [PATCH 11/48] Changed style to pytorch style, added some comments and fixed some minor errors --- torchvision/csrc/models/alexnet.cpp | 32 +- torchvision/csrc/models/alexnet.h | 23 +- torchvision/csrc/models/densenet.cpp | 368 +++++++------- torchvision/csrc/models/densenet.h | 98 ++-- torchvision/csrc/models/inception.cpp | 654 ++++++++++++------------- torchvision/csrc/models/inception.h | 182 +++---- torchvision/csrc/models/models.h | 2 +- torchvision/csrc/models/modelsimpl.cpp | 76 ++- torchvision/csrc/models/modelsimpl.h | 94 ++-- torchvision/csrc/models/resnet.cpp | 181 ++++--- torchvision/csrc/models/resnet.h | 319 ++++++------ torchvision/csrc/models/squeezenet.cpp | 145 +++--- torchvision/csrc/models/squeezenet.h | 43 +- torchvision/csrc/models/vgg.cpp | 157 +++--- torchvision/csrc/models/vgg.h | 85 ++-- 15 files changed, 1171 insertions(+), 1288 deletions(-) diff --git a/torchvision/csrc/models/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp index c7ad4ecbe0c..b72a13dcc17 100644 --- a/torchvision/csrc/models/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -2,13 +2,10 @@ #include "modelsimpl.h" -namespace vision -{ -namespace models -{ -AlexNetImpl::AlexNetImpl(int64_t num_classes) -{ - // clang-format off +namespace vision { +namespace models { +AlexNetImpl::AlexNetImpl(int64_t num_classes) { + // clang-format off features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), modelsimpl::Relu(true), @@ -32,20 +29,19 @@ AlexNetImpl::AlexNetImpl(int64_t num_classes) torch::nn::Linear(4096, 4096), modelsimpl::Relu(true), torch::nn::Linear(4096, num_classes)); - // clang-format on + // clang-format on - register_module("features", features); - register_module("clasifier", classifier); + register_module("features", features); + register_module("clasifier", classifier); } -torch::Tensor AlexNetImpl::forward(torch::Tensor x) -{ - x = features->forward(x); - x = x.view({x.size(0), 256 * 6 * 6}); - x = classifier->forward(x); +torch::Tensor AlexNetImpl::forward(torch::Tensor x) { + x = features->forward(x); + x = x.view({x.size(0), 256 * 6 * 6}); + x = classifier->forward(x); - return x; + return x; } -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/alexnet.h b/torchvision/csrc/models/alexnet.h index b155f401c1d..ad28b89e2ac 100644 --- a/torchvision/csrc/models/alexnet.h +++ b/torchvision/csrc/models/alexnet.h @@ -3,25 +3,22 @@ #include -namespace vision -{ -namespace models -{ +namespace vision { +namespace models { // AlexNet model architecture from the // "One weird trick..." paper. -class AlexNetImpl : public torch::nn::Module -{ - torch::nn::Sequential features{nullptr}, classifier{nullptr}; +class AlexNetImpl : public torch::nn::Module { + torch::nn::Sequential features{nullptr}, classifier{nullptr}; -public: - AlexNetImpl(int64_t num_classes = 1000); + public: + AlexNetImpl(int64_t num_classes = 1000); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; TORCH_MODULE(AlexNet); -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision -#endif // ALEXNET_H +#endif // ALEXNET_H diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index b2c622c833f..0d60672aec7 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -2,195 +2,215 @@ #include "modelsimpl.h" -namespace vision -{ -namespace models -{ +namespace vision { +namespace models { using Options = torch::nn::Conv2dOptions; -class _DenseLayerImpl : public torch::nn::SequentialImpl -{ - double drop_rate; - -public: - _DenseLayerImpl(int64_t num_input_features, int64_t growth_rate, - int64_t bn_size, double drop_rate) - : drop_rate(drop_rate) - { - push_back(torch::nn::BatchNorm(num_input_features)); - push_back(modelsimpl::Relu(true)); - push_back(torch::nn::Conv2d( - Options(num_input_features, bn_size * growth_rate, 1) - .stride(1) - .with_bias(false))); - push_back(torch::nn::BatchNorm(bn_size * growth_rate)); - push_back(modelsimpl::Relu(true)); - push_back( - torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) - .stride(1) - .padding(1) - .with_bias(false))); - } - - torch::Tensor forward(torch::Tensor x) - { - auto new_features = torch::nn::SequentialImpl::forward(x); - if (drop_rate > 0) - new_features = - torch::dropout(new_features, drop_rate, this->is_training()); - return torch::cat({x, new_features}, 1); - } +class _DenseLayerImpl : public torch::nn::SequentialImpl { + double drop_rate; + + public: + _DenseLayerImpl( + int64_t num_input_features, + int64_t growth_rate, + int64_t bn_size, + double drop_rate) + : drop_rate(drop_rate) { + push_back(torch::nn::BatchNorm(num_input_features)); + push_back(modelsimpl::Relu(true)); + push_back( + torch::nn::Conv2d(Options(num_input_features, bn_size * growth_rate, 1) + .stride(1) + .with_bias(false))); + push_back(torch::nn::BatchNorm(bn_size * growth_rate)); + push_back(modelsimpl::Relu(true)); + push_back(torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) + .stride(1) + .padding(1) + .with_bias(false))); + } + + torch::Tensor forward(torch::Tensor x) { + auto new_features = torch::nn::SequentialImpl::forward(x); + if (drop_rate > 0) + new_features = + torch::dropout(new_features, drop_rate, this->is_training()); + return torch::cat({x, new_features}, 1); + } }; TORCH_MODULE(_DenseLayer); -class _DenseBlockImpl : public torch::nn::SequentialImpl -{ -public: - _DenseBlockImpl(int64_t num_layers, int64_t num_input_features, - int64_t bn_size, int64_t growth_rate, double drop_rate) - { - for (int64_t i = 0; i < num_layers; ++i) - { - auto layer = _DenseLayer(num_input_features + i * growth_rate, - growth_rate, bn_size, drop_rate); - push_back(layer); - } - } - - torch::Tensor forward(torch::Tensor x) - { - return torch::nn::SequentialImpl::forward(x); - } +class _DenseBlockImpl : public torch::nn::SequentialImpl { + public: + _DenseBlockImpl( + int64_t num_layers, + int64_t num_input_features, + int64_t bn_size, + int64_t growth_rate, + double drop_rate) { + for (int64_t i = 0; i < num_layers; ++i) { + auto layer = _DenseLayer( + num_input_features + i * growth_rate, + growth_rate, + bn_size, + drop_rate); + push_back(layer); + } + } + + torch::Tensor forward(torch::Tensor x) { + return torch::nn::SequentialImpl::forward(x); + } }; TORCH_MODULE(_DenseBlock); -class _TransitionImpl : public torch::nn::SequentialImpl -{ -public: - _TransitionImpl(int64_t num_input_features, int64_t num_output_features) - { - push_back(torch::nn::BatchNorm(num_input_features)); - push_back(modelsimpl::Relu(true)); - push_back(torch::nn::Conv2d( - Options(num_input_features, num_output_features, 1) - .stride(1) - .with_bias(false))); - push_back(modelsimpl::AvgPool2D(2, 2)); - } - - torch::Tensor forward(torch::Tensor x) - { - return torch::nn::SequentialImpl::forward(x); - } +class _TransitionImpl : public torch::nn::SequentialImpl { + public: + _TransitionImpl(int64_t num_input_features, int64_t num_output_features) { + push_back(torch::nn::BatchNorm(num_input_features)); + push_back(modelsimpl::Relu(true)); + push_back( + torch::nn::Conv2d(Options(num_input_features, num_output_features, 1) + .stride(1) + .with_bias(false))); + push_back(modelsimpl::AvgPool2D(2, 2)); + } + + torch::Tensor forward(torch::Tensor x) { + return torch::nn::SequentialImpl::forward(x); + } }; TORCH_MODULE(_Transition); -DenseNetImpl::DenseNetImpl(int64_t num_classes, int64_t growth_rate, - std::vector block_config, - int64_t num_init_features, int64_t bn_size, - double drop_rate) -{ - // First convolution - features = torch::nn::Sequential( - torch::nn::Conv2d(torch::nn::Conv2dOptions(3, num_init_features, 7) - .stride(2) - .padding(3) - .with_bias(false)), - torch::nn::BatchNorm(num_init_features), modelsimpl::Relu(true), - modelsimpl::MaxPool2D( - modelsimpl::MaxPool2DOptions(3).stride(2).padding(1))); - - // Each denseblock - auto num_features = num_init_features; - for (size_t i = 0; i < block_config.size(); ++i) - { - auto num_layers = block_config[i]; - auto block = _DenseBlock(num_layers, num_features, bn_size, growth_rate, - drop_rate); - features->push_back(block); - num_features = num_features + num_layers * growth_rate; - - if (i != block_config.size() - 1) - { - auto trans = _Transition(num_features, num_features / 2); - features->push_back(trans); - num_features = num_features / 2; - } - } - - // Final batch norm - features->push_back(torch::nn::BatchNorm(num_features)); - // Linear layer - classifier = torch::nn::Linear(num_features, num_classes); - - register_module("features", features); - register_module("classifier", classifier); - - // Official init from torch repo. - for (auto &module : modules(false)) - { - if (torch::nn::Conv2dImpl *M = - dynamic_cast(module.get())) - torch::nn::init::xavier_normal_(M->weight); - else if (torch::nn::BatchNormImpl *M = - dynamic_cast(module.get())) - { - torch::nn::init::constant_(M->weight, 1); - torch::nn::init::constant_(M->bias, 0); - } - else if (torch::nn::LinearImpl *M = - dynamic_cast(module.get())) - torch::nn::init::normal_(M->bias, 0); - } +DenseNetImpl::DenseNetImpl( + int64_t num_classes, + int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, + int64_t bn_size, + double drop_rate) { + // First convolution + features = torch::nn::Sequential( + torch::nn::Conv2d(torch::nn::Conv2dOptions(3, num_init_features, 7) + .stride(2) + .padding(3) + .with_bias(false)), + torch::nn::BatchNorm(num_init_features), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D( + modelsimpl::MaxPool2DOptions(3).stride(2).padding(1))); + + // Each denseblock + auto num_features = num_init_features; + for (size_t i = 0; i < block_config.size(); ++i) { + auto num_layers = block_config[i]; + auto block = + _DenseBlock(num_layers, num_features, bn_size, growth_rate, drop_rate); + features->push_back(block); + num_features = num_features + num_layers * growth_rate; + + if (i != block_config.size() - 1) { + auto trans = _Transition(num_features, num_features / 2); + features->push_back(trans); + num_features = num_features / 2; + } + } + + // Final batch norm + features->push_back(torch::nn::BatchNorm(num_features)); + // Linear layer + classifier = torch::nn::Linear(num_features, num_classes); + + register_module("features", features); + register_module("classifier", classifier); + + // Official init from torch repo. + for (auto& module : modules(false)) { + if (torch::nn::Conv2dImpl* M = + dynamic_cast(module.get())) + torch::nn::init::xavier_normal_(M->weight); // TODO kaiming + else if ( + torch::nn::BatchNormImpl* M = + dynamic_cast(module.get())) { + torch::nn::init::constant_(M->weight, 1); + torch::nn::init::constant_(M->bias, 0); + } else if ( + torch::nn::LinearImpl* M = + dynamic_cast(module.get())) + torch::nn::init::constant_(M->bias, 0); + } } -torch::Tensor DenseNetImpl::forward(torch::Tensor x) -{ - auto features = this->features->forward(x); - auto out = torch::relu_(features); - out = torch::adaptive_avg_pool2d(out, {1, 1}).view({features.size(0), -1}); - out = this->classifier->forward(out); - return out; +torch::Tensor DenseNetImpl::forward(torch::Tensor x) { + auto features = this->features->forward(x); + auto out = torch::relu_(features); + out = torch::adaptive_avg_pool2d(out, {1, 1}).view({features.size(0), -1}); + out = this->classifier->forward(out); + return out; } -DenseNet121Impl::DenseNet121Impl(int64_t num_classes, int64_t growth_rate, - std::vector block_config, - int64_t num_init_features, int64_t bn_size, - double drop_rate) - : DenseNetImpl(num_classes, growth_rate, block_config, num_init_features, - bn_size, drop_rate) -{ -} - -DenseNet169Impl::DenseNet169Impl(int64_t num_classes, int64_t growth_rate, - std::vector block_config, - int64_t num_init_features, int64_t bn_size, - double drop_rate) - : DenseNetImpl(num_classes, growth_rate, block_config, num_init_features, - bn_size, drop_rate) -{ -} - -DenseNet201Impl::DenseNet201Impl(int64_t num_classes, int64_t growth_rate, - std::vector block_config, - int64_t num_init_features, int64_t bn_size, - double drop_rate) - : DenseNetImpl(num_classes, growth_rate, block_config, num_init_features, - bn_size, drop_rate) -{ -} - -DenseNet161Impl::DenseNet161Impl(int64_t num_classes, int64_t growth_rate, - std::vector block_config, - int64_t num_init_features, int64_t bn_size, - double drop_rate) - : DenseNetImpl(num_classes, growth_rate, block_config, num_init_features, - bn_size, drop_rate) -{ -} - -} // namespace models -} // namespace vision +DenseNet121Impl::DenseNet121Impl( + int64_t num_classes, + int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, + int64_t bn_size, + double drop_rate) + : DenseNetImpl( + num_classes, + growth_rate, + block_config, + num_init_features, + bn_size, + drop_rate) {} + +DenseNet169Impl::DenseNet169Impl( + int64_t num_classes, + int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, + int64_t bn_size, + double drop_rate) + : DenseNetImpl( + num_classes, + growth_rate, + block_config, + num_init_features, + bn_size, + drop_rate) {} + +DenseNet201Impl::DenseNet201Impl( + int64_t num_classes, + int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, + int64_t bn_size, + double drop_rate) + : DenseNetImpl( + num_classes, + growth_rate, + block_config, + num_init_features, + bn_size, + drop_rate) {} + +DenseNet161Impl::DenseNet161Impl( + int64_t num_classes, + int64_t growth_rate, + std::vector block_config, + int64_t num_init_features, + int64_t bn_size, + double drop_rate) + : DenseNetImpl( + num_classes, + growth_rate, + block_config, + num_init_features, + bn_size, + drop_rate) {} + +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/densenet.h b/torchvision/csrc/models/densenet.h index 3dd85f6bc4b..556a4a90bec 100644 --- a/torchvision/csrc/models/densenet.h +++ b/torchvision/csrc/models/densenet.h @@ -3,10 +3,8 @@ #include -namespace vision -{ -namespace models -{ +namespace vision { +namespace models { // Densenet-BC model class, based on // "Densely Connected Convolutional Networks" // @@ -20,54 +18,64 @@ namespace models // bn_size (int) - multiplicative factor for number of bottle neck layers // (i.e. bn_size * k features in the bottleneck layer) // drop_rate (float) - dropout rate after each dense layer -class DenseNetImpl : public torch::nn::Module -{ - torch::nn::Sequential features{nullptr}; - torch::nn::Linear classifier{nullptr}; +class DenseNetImpl : public torch::nn::Module { + torch::nn::Sequential features{nullptr}; + torch::nn::Linear classifier{nullptr}; -public: - DenseNetImpl(int64_t num_classes = 1000, int64_t growth_rate = 32, - std::vector block_config = {6, 12, 24, 16}, - int64_t num_init_features = 64, int64_t bn_size = 4, - double drop_rate = 0); + public: + DenseNetImpl( + int64_t num_classes = 1000, + int64_t growth_rate = 32, + std::vector block_config = {6, 12, 24, 16}, + int64_t num_init_features = 64, + int64_t bn_size = 4, + double drop_rate = 0); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; -class DenseNet121Impl : public DenseNetImpl -{ -public: - DenseNet121Impl(int64_t num_classes = 1000, int64_t growth_rate = 32, - std::vector block_config = {6, 12, 24, 16}, - int64_t num_init_features = 64, int64_t bn_size = 4, - double drop_rate = 0); +class DenseNet121Impl : public DenseNetImpl { + public: + DenseNet121Impl( + int64_t num_classes = 1000, + int64_t growth_rate = 32, + std::vector block_config = {6, 12, 24, 16}, + int64_t num_init_features = 64, + int64_t bn_size = 4, + double drop_rate = 0); }; -class DenseNet169Impl : public DenseNetImpl -{ -public: - DenseNet169Impl(int64_t num_classes = 1000, int64_t growth_rate = 32, - std::vector block_config = {6, 12, 32, 32}, - int64_t num_init_features = 64, int64_t bn_size = 4, - double drop_rate = 0); +class DenseNet169Impl : public DenseNetImpl { + public: + DenseNet169Impl( + int64_t num_classes = 1000, + int64_t growth_rate = 32, + std::vector block_config = {6, 12, 32, 32}, + int64_t num_init_features = 64, + int64_t bn_size = 4, + double drop_rate = 0); }; -class DenseNet201Impl : public DenseNetImpl -{ -public: - DenseNet201Impl(int64_t num_classes = 1000, int64_t growth_rate = 32, - std::vector block_config = {6, 12, 48, 32}, - int64_t num_init_features = 64, int64_t bn_size = 4, - double drop_rate = 0); +class DenseNet201Impl : public DenseNetImpl { + public: + DenseNet201Impl( + int64_t num_classes = 1000, + int64_t growth_rate = 32, + std::vector block_config = {6, 12, 48, 32}, + int64_t num_init_features = 64, + int64_t bn_size = 4, + double drop_rate = 0); }; -class DenseNet161Impl : public DenseNetImpl -{ -public: - DenseNet161Impl(int64_t num_classes = 1000, int64_t growth_rate = 48, - std::vector block_config = {6, 12, 36, 24}, - int64_t num_init_features = 96, int64_t bn_size = 4, - double drop_rate = 0); +class DenseNet161Impl : public DenseNetImpl { + public: + DenseNet161Impl( + int64_t num_classes = 1000, + int64_t growth_rate = 48, + std::vector block_config = {6, 12, 36, 24}, + int64_t num_init_features = 96, + int64_t bn_size = 4, + double drop_rate = 0); }; TORCH_MODULE(DenseNet); @@ -76,7 +84,7 @@ TORCH_MODULE(DenseNet169); TORCH_MODULE(DenseNet201); TORCH_MODULE(DenseNet161); -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision -#endif // DENSENET_H +#endif // DENSENET_H diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index cab1d64907f..57ee6dcbc4c 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -1,399 +1,371 @@ #include "inception.h" -namespace vision -{ -namespace models -{ +namespace vision { +namespace models { using Options = torch::nn::Conv2dOptions; -namespace _inceptionimpl -{ -BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions options) -{ - options.with_bias(false); - conv = torch::nn::Conv2d(options); - bn = torch::nn::BatchNorm( - torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); +void init_weight(at::Tensor& weight, double stddev) { + std::vector sizes; + for (auto i : weight.sizes()) + sizes.push_back(i); + sizes.push_back(4); + + auto tmp = torch::empty(sizes, weight.options()).normal_(); + auto valid = (tmp < 2).__and__(tmp > -2); + auto ind = std::get<1>(valid.max(-1, true)); + weight = tmp.gather(-1, ind).squeeze(-1); + weight.mul_(stddev); +} - register_module("conv", conv); - register_module("bn", bn); +namespace _inceptionimpl { +BasicConv2dImpl::BasicConv2dImpl( + torch::nn::Conv2dOptions options, + double std_dev) { + options.with_bias(false); + conv = torch::nn::Conv2d(options); + bn = torch::nn::BatchNorm( + torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); + + register_module("conv", conv); + register_module("bn", bn); + + init_weight(conv->weight, std_dev); + torch::nn::init::constant_(bn->weight, 1); + torch::nn::init::constant_(bn->bias, 0); } -torch::Tensor BasicConv2dImpl::forward(torch::Tensor x) -{ - x = conv->forward(x); - x = bn->forward(x); - return torch::relu_(x); +torch::Tensor BasicConv2dImpl::forward(torch::Tensor x) { + x = conv->forward(x); + x = bn->forward(x); + return torch::relu_(x); } InceptionAImpl::InceptionAImpl(int64_t in_channels, int64_t pool_features) - : branch1x1(Options(in_channels, 64, 1)), - branch5x5_1(Options(in_channels, 48, 1)), - branch5x5_2(Options(48, 64, 5).padding(2)), - branch3x3dbl_1(Options(in_channels, 64, 1)), - branch3x3dbl_2(Options(64, 96, 3).padding(1)), - branch3x3dbl_3(Options(96, 96, 3).padding(1)), - branch_pool(Options(in_channels, pool_features, 1)) -{ - register_module("branch1x1", branch1x1); - register_module("branch5x5_1", branch5x5_1); - register_module("branch5x5_2", branch5x5_2); - register_module("branch3x3dbl_1", branch3x3dbl_1); - register_module("branch3x3dbl_2", branch3x3dbl_2); - register_module("branch3x3dbl_3", branch3x3dbl_3); - register_module("branch_pool", branch_pool); + : branch1x1(Options(in_channels, 64, 1)), + branch5x5_1(Options(in_channels, 48, 1)), + branch5x5_2(Options(48, 64, 5).padding(2)), + branch3x3dbl_1(Options(in_channels, 64, 1)), + branch3x3dbl_2(Options(64, 96, 3).padding(1)), + branch3x3dbl_3(Options(96, 96, 3).padding(1)), + branch_pool(Options(in_channels, pool_features, 1)) { + register_module("branch1x1", branch1x1); + register_module("branch5x5_1", branch5x5_1); + register_module("branch5x5_2", branch5x5_2); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3", branch3x3dbl_3); + register_module("branch_pool", branch_pool); } -torch::Tensor InceptionAImpl::forward(torch::Tensor x) -{ - auto branch1x1 = this->branch1x1->forward(x); +torch::Tensor InceptionAImpl::forward(torch::Tensor x) { + auto branch1x1 = this->branch1x1->forward(x); - auto branch5x5 = this->branch5x5_1->forward(x); - branch5x5 = this->branch5x5_2->forward(branch5x5); + auto branch5x5 = this->branch5x5_1->forward(x); + branch5x5 = this->branch5x5_2->forward(branch5x5); - auto branch3x3dbl = this->branch3x3dbl_1->forward(x); - branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); - branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); - auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); - branch_pool = this->branch_pool->forward(branch_pool); + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + branch_pool = this->branch_pool->forward(branch_pool); - return torch::cat({branch1x1, branch5x5, branch3x3dbl, branch_pool}, 1); + return torch::cat({branch1x1, branch5x5, branch3x3dbl, branch_pool}, 1); } InceptionBImpl::InceptionBImpl(int64_t in_channels) - : branch3x3(Options(in_channels, 384, 3).stride(2)), - branch3x3dbl_1(Options(in_channels, 64, 1)), - branch3x3dbl_2(Options(64, 96, 3).padding(1)), - branch3x3dbl_3(Options(96, 96, 3).stride(2)) -{ - register_module("branch3x3", branch3x3); - register_module("branch3x3dbl_1", branch3x3dbl_1); - register_module("branch3x3dbl_2", branch3x3dbl_2); - register_module("branch3x3dbl_3", branch3x3dbl_3); + : branch3x3(Options(in_channels, 384, 3).stride(2)), + branch3x3dbl_1(Options(in_channels, 64, 1)), + branch3x3dbl_2(Options(64, 96, 3).padding(1)), + branch3x3dbl_3(Options(96, 96, 3).stride(2)) { + register_module("branch3x3", branch3x3); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3", branch3x3dbl_3); } -torch::Tensor InceptionBImpl::forward(torch::Tensor x) -{ - auto branch3x3 = this->branch3x3->forward(x); +torch::Tensor InceptionBImpl::forward(torch::Tensor x) { + auto branch3x3 = this->branch3x3->forward(x); - auto branch3x3dbl = this->branch3x3dbl_1->forward(x); - branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); - branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = this->branch3x3dbl_3->forward(branch3x3dbl); - auto branch_pool = torch::max_pool2d(x, 3, 2); - return torch::cat({branch3x3, branch3x3dbl, branch_pool}, 1); + auto branch_pool = torch::max_pool2d(x, 3, 2); + return torch::cat({branch3x3, branch3x3dbl, branch_pool}, 1); } -InceptionCImpl::InceptionCImpl(int64_t in_channels, int64_t channels_7x7) -{ - branch1x1 = BasicConv2d(Options(in_channels, 192, 1)); - - auto c7 = channels_7x7; - branch7x7_1 = BasicConv2d(Options(in_channels, c7, 1)); - branch7x7_2 = BasicConv2d(Options(c7, c7, {1, 7}).padding({0, 3})); - branch7x7_3 = BasicConv2d(Options(c7, 192, {7, 1}).padding({3, 0})); - - branch7x7dbl_1 = BasicConv2d(Options(in_channels, c7, 1)); - branch7x7dbl_2 = BasicConv2d(Options(c7, c7, {7, 1}).padding({3, 0})); - branch7x7dbl_3 = BasicConv2d(Options(c7, c7, {1, 7}).padding({0, 3})); - branch7x7dbl_4 = BasicConv2d(Options(c7, c7, {7, 1}).padding({3, 0})); - branch7x7dbl_5 = BasicConv2d(Options(c7, 192, {1, 7}).padding({0, 3})); - - branch_pool = BasicConv2d(Options(in_channels, 192, 1)); - - register_module("branch1x1", branch1x1); - register_module("branch7x7_1", branch7x7_1); - register_module("branch7x7_2", branch7x7_2); - register_module("branch7x7_3", branch7x7_3); - register_module("branch7x7dbl_1", branch7x7dbl_1); - register_module("branch7x7dbl_2", branch7x7dbl_2); - register_module("branch7x7dbl_3", branch7x7dbl_3); - register_module("branch7x7dbl_4", branch7x7dbl_4); - register_module("branch7x7dbl_5", branch7x7dbl_5); - register_module("branch_pool", branch_pool); +InceptionCImpl::InceptionCImpl(int64_t in_channels, int64_t channels_7x7) { + branch1x1 = BasicConv2d(Options(in_channels, 192, 1)); + + auto c7 = channels_7x7; + branch7x7_1 = BasicConv2d(Options(in_channels, c7, 1)); + branch7x7_2 = BasicConv2d(Options(c7, c7, {1, 7}).padding({0, 3})); + branch7x7_3 = BasicConv2d(Options(c7, 192, {7, 1}).padding({3, 0})); + + branch7x7dbl_1 = BasicConv2d(Options(in_channels, c7, 1)); + branch7x7dbl_2 = BasicConv2d(Options(c7, c7, {7, 1}).padding({3, 0})); + branch7x7dbl_3 = BasicConv2d(Options(c7, c7, {1, 7}).padding({0, 3})); + branch7x7dbl_4 = BasicConv2d(Options(c7, c7, {7, 1}).padding({3, 0})); + branch7x7dbl_5 = BasicConv2d(Options(c7, 192, {1, 7}).padding({0, 3})); + + branch_pool = BasicConv2d(Options(in_channels, 192, 1)); + + register_module("branch1x1", branch1x1); + register_module("branch7x7_1", branch7x7_1); + register_module("branch7x7_2", branch7x7_2); + register_module("branch7x7_3", branch7x7_3); + register_module("branch7x7dbl_1", branch7x7dbl_1); + register_module("branch7x7dbl_2", branch7x7dbl_2); + register_module("branch7x7dbl_3", branch7x7dbl_3); + register_module("branch7x7dbl_4", branch7x7dbl_4); + register_module("branch7x7dbl_5", branch7x7dbl_5); + register_module("branch_pool", branch_pool); } -torch::Tensor InceptionCImpl::forward(torch::Tensor x) -{ - auto branch1x1 = this->branch1x1->forward(x); +torch::Tensor InceptionCImpl::forward(torch::Tensor x) { + auto branch1x1 = this->branch1x1->forward(x); - auto branch7x7 = this->branch7x7_1->forward(x); - branch7x7 = this->branch7x7_2->forward(branch7x7); - branch7x7 = this->branch7x7_3->forward(branch7x7); + auto branch7x7 = this->branch7x7_1->forward(x); + branch7x7 = this->branch7x7_2->forward(branch7x7); + branch7x7 = this->branch7x7_3->forward(branch7x7); - auto branch7x7dbl = this->branch7x7dbl_1->forward(x); - branch7x7dbl = this->branch7x7dbl_2->forward(branch7x7dbl); - branch7x7dbl = this->branch7x7dbl_3->forward(branch7x7dbl); - branch7x7dbl = this->branch7x7dbl_4->forward(branch7x7dbl); - branch7x7dbl = this->branch7x7dbl_5->forward(branch7x7dbl); + auto branch7x7dbl = this->branch7x7dbl_1->forward(x); + branch7x7dbl = this->branch7x7dbl_2->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_3->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_4->forward(branch7x7dbl); + branch7x7dbl = this->branch7x7dbl_5->forward(branch7x7dbl); - auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); - branch_pool = this->branch_pool->forward(branch_pool); + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + branch_pool = this->branch_pool->forward(branch_pool); - return torch::cat({branch1x1, branch7x7, branch7x7dbl, branch_pool}, 1); + return torch::cat({branch1x1, branch7x7, branch7x7dbl, branch_pool}, 1); } InceptionDImpl::InceptionDImpl(int64_t in_channels) - : branch3x3_1(Options(in_channels, 192, 1)), - branch3x3_2(Options(192, 320, 3).stride(2)), - branch7x7x3_1(Options(in_channels, 192, 1)), - branch7x7x3_2(Options(192, 192, {1, 7}).padding({0, 3})), - branch7x7x3_3(Options(192, 192, {7, 1}).padding({3, 0})), - branch7x7x3_4(Options(192, 192, 3).stride(2)) + : branch3x3_1(Options(in_channels, 192, 1)), + branch3x3_2(Options(192, 320, 3).stride(2)), + branch7x7x3_1(Options(in_channels, 192, 1)), + branch7x7x3_2(Options(192, 192, {1, 7}).padding({0, 3})), + branch7x7x3_3(Options(192, 192, {7, 1}).padding({3, 0})), + branch7x7x3_4(Options(192, 192, 3).stride(2)) { - register_module("branch3x3_1", branch3x3_1); - register_module("branch3x3_2", branch3x3_2); - register_module("branch7x7x3_1", branch7x7x3_1); - register_module("branch7x7x3_2", branch7x7x3_2); - register_module("branch7x7x3_3", branch7x7x3_3); - register_module("branch7x7x3_4", branch7x7x3_4); + register_module("branch3x3_1", branch3x3_1); + register_module("branch3x3_2", branch3x3_2); + register_module("branch7x7x3_1", branch7x7x3_1); + register_module("branch7x7x3_2", branch7x7x3_2); + register_module("branch7x7x3_3", branch7x7x3_3); + register_module("branch7x7x3_4", branch7x7x3_4); } -torch::Tensor InceptionDImpl::forward(torch::Tensor x) -{ - auto branch3x3 = this->branch3x3_1->forward(x); - branch3x3 = this->branch3x3_2->forward(branch3x3); +torch::Tensor InceptionDImpl::forward(torch::Tensor x) { + auto branch3x3 = this->branch3x3_1->forward(x); + branch3x3 = this->branch3x3_2->forward(branch3x3); - auto branch7x7x3 = this->branch7x7x3_1->forward(x); - branch7x7x3 = this->branch7x7x3_2->forward(branch7x7x3); - branch7x7x3 = this->branch7x7x3_3->forward(branch7x7x3); - branch7x7x3 = this->branch7x7x3_4->forward(branch7x7x3); + auto branch7x7x3 = this->branch7x7x3_1->forward(x); + branch7x7x3 = this->branch7x7x3_2->forward(branch7x7x3); + branch7x7x3 = this->branch7x7x3_3->forward(branch7x7x3); + branch7x7x3 = this->branch7x7x3_4->forward(branch7x7x3); - auto branch_pool = torch::max_pool2d(x, 3, 2); - return torch::cat({branch3x3, branch7x7x3, branch_pool}, 1); + auto branch_pool = torch::max_pool2d(x, 3, 2); + return torch::cat({branch3x3, branch7x7x3, branch_pool}, 1); } InceptionEImpl::InceptionEImpl(int64_t in_channels) - : branch1x1(Options(in_channels, 320, 1)), - branch3x3_1(Options(in_channels, 384, 1)), - branch3x3_2a(Options(384, 384, {1, 3}).padding({0, 1})), - branch3x3_2b(Options(384, 384, {3, 1}).padding({1, 0})), - branch3x3dbl_1(Options(in_channels, 448, 1)), - branch3x3dbl_2(Options(448, 384, 3).padding(1)), - branch3x3dbl_3a(Options(384, 384, {1, 3}).padding({0, 1})), - branch3x3dbl_3b(Options(384, 384, {3, 1}).padding({1, 0})), - branch_pool(Options(in_channels, 192, 1)) -{ - register_module("branch1x1", branch1x1); - register_module("branch3x3_1", branch3x3_1); - register_module("branch3x3_2a", branch3x3_2a); - register_module("branch3x3_2b", branch3x3_2b); - register_module("branch3x3dbl_1", branch3x3dbl_1); - register_module("branch3x3dbl_2", branch3x3dbl_2); - register_module("branch3x3dbl_3a", branch3x3dbl_3a); - register_module("branch3x3dbl_3b", branch3x3dbl_3b); - register_module("branch_pool", branch_pool); + : branch1x1(Options(in_channels, 320, 1)), + branch3x3_1(Options(in_channels, 384, 1)), + branch3x3_2a(Options(384, 384, {1, 3}).padding({0, 1})), + branch3x3_2b(Options(384, 384, {3, 1}).padding({1, 0})), + branch3x3dbl_1(Options(in_channels, 448, 1)), + branch3x3dbl_2(Options(448, 384, 3).padding(1)), + branch3x3dbl_3a(Options(384, 384, {1, 3}).padding({0, 1})), + branch3x3dbl_3b(Options(384, 384, {3, 1}).padding({1, 0})), + branch_pool(Options(in_channels, 192, 1)) { + register_module("branch1x1", branch1x1); + register_module("branch3x3_1", branch3x3_1); + register_module("branch3x3_2a", branch3x3_2a); + register_module("branch3x3_2b", branch3x3_2b); + register_module("branch3x3dbl_1", branch3x3dbl_1); + register_module("branch3x3dbl_2", branch3x3dbl_2); + register_module("branch3x3dbl_3a", branch3x3dbl_3a); + register_module("branch3x3dbl_3b", branch3x3dbl_3b); + register_module("branch_pool", branch_pool); } -torch::Tensor InceptionEImpl::forward(torch::Tensor x) -{ - auto branch1x1 = this->branch1x1->forward(x); - - auto branch3x3 = this->branch3x3_1->forward(x); - branch3x3 = torch::cat( - { - this->branch3x3_2a->forward(branch3x3), - this->branch3x3_2b->forward(branch3x3), - }, - 1); - - auto branch3x3dbl = this->branch3x3dbl_1->forward(x); - branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); - branch3x3dbl = torch::cat({this->branch3x3dbl_3a->forward(branch3x3dbl), - this->branch3x3dbl_3b->forward(branch3x3dbl)}, - 1); - - auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); - branch_pool = this->branch_pool->forward(branch_pool); - - return torch::cat({branch1x1, branch3x3, branch3x3dbl, branch_pool}, 1); -} +torch::Tensor InceptionEImpl::forward(torch::Tensor x) { + auto branch1x1 = this->branch1x1->forward(x); -InceptionAuxImpl::InceptionAuxImpl(int64_t in_channels, int64_t num_classes) - : conv0(BasicConv2d(Options(in_channels, 128, 1))), - conv1(AuxBasicConv(Options(128, 768, 5))), - fc(768, num_classes) -{ - conv1->stddev = 0.01; - fc->stddev = 0.001; + auto branch3x3 = this->branch3x3_1->forward(x); + branch3x3 = torch::cat( + { + this->branch3x3_2a->forward(branch3x3), + this->branch3x3_2b->forward(branch3x3), + }, + 1); - register_module("conv0", conv0); - register_module("conv1", conv1); - register_module("fc", fc); -} + auto branch3x3dbl = this->branch3x3dbl_1->forward(x); + branch3x3dbl = this->branch3x3dbl_2->forward(branch3x3dbl); + branch3x3dbl = torch::cat( + {this->branch3x3dbl_3a->forward(branch3x3dbl), + this->branch3x3dbl_3b->forward(branch3x3dbl)}, + 1); -torch::Tensor InceptionAuxImpl::forward(torch::Tensor x) -{ - // 17 x 17 x 768 - x = torch::avg_pool2d(x, 5, 3); - // 5 x 5 x 768 - x = conv0->forward(x); - // 5 x 5 x 128 - x = conv1->forward(x); - // 1 x 1 x 768 - x = x.view({x.size(0), -1}); - // 768 - x = fc->forward(x); - // 1000 (num_classes) - return x; + auto branch_pool = torch::avg_pool2d(x, 3, 1, 1); + branch_pool = this->branch_pool->forward(branch_pool); + + return torch::cat({branch1x1, branch3x3, branch3x3dbl, branch_pool}, 1); } -} // namespace _inceptionimpl +InceptionAuxImpl::InceptionAuxImpl(int64_t in_channels, int64_t num_classes) + : conv0(BasicConv2d(Options(in_channels, 128, 1))), + conv1(BasicConv2d(Options(128, 768, 5), 0.01)), + fc(768, num_classes) { + init_weight(fc->weight, 0.001); + + register_module("conv0", conv0); + register_module("conv1", conv1); + register_module("fc", fc); +} -void init_weight(at::Tensor &weight, double stddev) -{ - // auto temp = torch::fmod(torch::randn(weight.sizes()), 2); - // weight = temp.mul(stddev); - - std::vector sizes; - for (auto i : weight.sizes()) sizes.push_back(i); - sizes.push_back(4); - - auto tmp = torch::empty(sizes, weight.options()).normal_(); - auto valid = (tmp < 2).__and__(tmp > -2); - auto ind = std::get<1>(valid.max(-1, true)); - weight = tmp.gather(-1, ind).squeeze(-1); - weight.mul_(stddev); +torch::Tensor InceptionAuxImpl::forward(torch::Tensor x) { + // 17 x 17 x 768 + x = torch::avg_pool2d(x, 5, 3); + // 5 x 5 x 768 + x = conv0->forward(x); + // 5 x 5 x 128 + x = conv1->forward(x); + // 1 x 1 x 768 + x = x.view({x.size(0), -1}); + // 768 + x = fc->forward(x); + // 1000 (num_classes) + return x; } -InceptionV3Impl::InceptionV3Impl(int64_t num_classes, bool aux_logits, - bool transform_input) - : aux_logits(aux_logits), transform_input(transform_input) -{ - Conv2d_1a_3x3 = _inceptionimpl::BasicConv2d(Options(3, 32, 3).stride(2)); - Conv2d_2a_3x3 = _inceptionimpl::BasicConv2d(Options(32, 32, 3)); - Conv2d_2b_3x3 = _inceptionimpl::BasicConv2d(Options(32, 64, 3).padding(1)); - Conv2d_3b_1x1 = _inceptionimpl::BasicConv2d(Options(64, 80, 1)); - Conv2d_4a_3x3 = _inceptionimpl::BasicConv2d(Options(80, 192, 3)); - - Mixed_5b = _inceptionimpl::InceptionA(192, 32); - Mixed_5c = _inceptionimpl::InceptionA(256, 64); - Mixed_5d = _inceptionimpl::InceptionA(288, 64); - - Mixed_6a = _inceptionimpl::InceptionB(288); - Mixed_6b = _inceptionimpl::InceptionC(768, 128); - Mixed_6c = _inceptionimpl::InceptionC(768, 160); - Mixed_6d = _inceptionimpl::InceptionC(768, 160); - Mixed_6e = _inceptionimpl::InceptionC(768, 192); - - if (aux_logits) AuxLogits = _inceptionimpl::InceptionAux(768, num_classes); - - Mixed_7a = _inceptionimpl::InceptionD(768); - Mixed_7b = _inceptionimpl::InceptionE(1280); - Mixed_7c = _inceptionimpl::InceptionE(2048); - - fc = torch::nn::Linear(2048, num_classes); - - register_module("Conv2d_1a_3x3", Conv2d_1a_3x3); - register_module("Conv2d_2a_3x3", Conv2d_2a_3x3); - register_module("Conv2d_2b_3x3", Conv2d_2b_3x3); - register_module("Conv2d_3b_1x1", Conv2d_3b_1x1); - register_module("Conv2d_4a_3x3", Conv2d_4a_3x3); - register_module("Mixed_5b", Mixed_5b); - register_module("Mixed_5c", Mixed_5c); - register_module("Mixed_5d", Mixed_5d); - register_module("Mixed_6a", Mixed_6a); - register_module("Mixed_6b", Mixed_6b); - register_module("Mixed_6c", Mixed_6c); - register_module("Mixed_6d", Mixed_6d); - register_module("Mixed_6e", Mixed_6e); - - if (!AuxLogits.is_empty()) register_module("AuxLogits", AuxLogits); - - register_module("Mixed_7a", Mixed_7a); - register_module("Mixed_7b", Mixed_7b); - register_module("Mixed_7c", Mixed_7c); - register_module("fc", fc); - - for (auto &module : modules(false)) - { - if (_inceptionimpl::AuxLinearImpl *M = - dynamic_cast<_inceptionimpl::AuxLinearImpl *>(module.get())) - init_weight(M->weight, M->stddev); - else if (torch::nn::Conv2dImpl *M = - dynamic_cast(module.get())) - init_weight(M->weight, 0.1); - else if (torch::nn::LinearImpl *M = - dynamic_cast(module.get())) - init_weight(M->weight, 0.1); - else if (torch::nn::BatchNormImpl *M = - dynamic_cast(module.get())) - { - torch::nn::init::constant_(M->weight, 1); - torch::nn::init::constant_(M->bias, 0); - } - } +} // namespace _inceptionimpl + +InceptionV3Impl::InceptionV3Impl( + int64_t num_classes, + bool aux_logits, + bool transform_input) + : aux_logits(aux_logits), transform_input(transform_input) { + Conv2d_1a_3x3 = _inceptionimpl::BasicConv2d(Options(3, 32, 3).stride(2)); + Conv2d_2a_3x3 = _inceptionimpl::BasicConv2d(Options(32, 32, 3)); + Conv2d_2b_3x3 = _inceptionimpl::BasicConv2d(Options(32, 64, 3).padding(1)); + Conv2d_3b_1x1 = _inceptionimpl::BasicConv2d(Options(64, 80, 1)); + Conv2d_4a_3x3 = _inceptionimpl::BasicConv2d(Options(80, 192, 3)); + + Mixed_5b = _inceptionimpl::InceptionA(192, 32); + Mixed_5c = _inceptionimpl::InceptionA(256, 64); + Mixed_5d = _inceptionimpl::InceptionA(288, 64); + + Mixed_6a = _inceptionimpl::InceptionB(288); + Mixed_6b = _inceptionimpl::InceptionC(768, 128); + Mixed_6c = _inceptionimpl::InceptionC(768, 160); + Mixed_6d = _inceptionimpl::InceptionC(768, 160); + Mixed_6e = _inceptionimpl::InceptionC(768, 192); + + if (aux_logits) + AuxLogits = _inceptionimpl::InceptionAux(768, num_classes); + + Mixed_7a = _inceptionimpl::InceptionD(768); + Mixed_7b = _inceptionimpl::InceptionE(1280); + Mixed_7c = _inceptionimpl::InceptionE(2048); + + fc = torch::nn::Linear(2048, num_classes); + init_weight(fc->weight, 0.1); + + register_module("Conv2d_1a_3x3", Conv2d_1a_3x3); + register_module("Conv2d_2a_3x3", Conv2d_2a_3x3); + register_module("Conv2d_2b_3x3", Conv2d_2b_3x3); + register_module("Conv2d_3b_1x1", Conv2d_3b_1x1); + register_module("Conv2d_4a_3x3", Conv2d_4a_3x3); + register_module("Mixed_5b", Mixed_5b); + register_module("Mixed_5c", Mixed_5c); + register_module("Mixed_5d", Mixed_5d); + register_module("Mixed_6a", Mixed_6a); + register_module("Mixed_6b", Mixed_6b); + register_module("Mixed_6c", Mixed_6c); + register_module("Mixed_6d", Mixed_6d); + register_module("Mixed_6e", Mixed_6e); + + if (!AuxLogits.is_empty()) + register_module("AuxLogits", AuxLogits); + + register_module("Mixed_7a", Mixed_7a); + register_module("Mixed_7b", Mixed_7b); + register_module("Mixed_7c", Mixed_7c); + register_module("fc", fc); } -torch::TensorList InceptionV3Impl::forward(torch::Tensor x) -{ - if (transform_input) - { - auto x_ch0 = torch::unsqueeze(x.select(1, 0), 1) * (0.229 / 0.5) + - (0.485 - 0.5) / 0.5; - auto x_ch1 = torch::unsqueeze(x.select(1, 1), 1) * (0.224 / 0.5) + - (0.456 - 0.5) / 0.5; - auto x_ch2 = torch::unsqueeze(x.select(1, 2), 1) * (0.225 / 0.5) + - (0.406 - 0.5) / 0.5; - - x = torch::cat({x_ch0, x_ch1, x_ch2}, 1); - } - - // 299 x 299 x 3 - x = Conv2d_1a_3x3->forward(x); - // 149 x 149 x 32 - x = Conv2d_2a_3x3->forward(x); - // 147 x 147 x 32 - x = Conv2d_2b_3x3->forward(x); - // 147 x 147 x 64 - x = torch::max_pool2d(x, 3, 2); - // 73 x 73 x 64 - x = Conv2d_3b_1x1->forward(x); - // 73 x 73 x 80 - x = Conv2d_4a_3x3->forward(x); - // 71 x 71 x 192 - x = torch::max_pool2d(x, 3, 2); - // 35 x 35 x 192 - x = Mixed_5b->forward(x); - // 35 x 35 x 256 - x = Mixed_5c->forward(x); - // 35 x 35 x 288 - x = Mixed_5d->forward(x); - // 35 x 35 x 288 - x = Mixed_6a->forward(x); - // 17 x 17 x 768 - x = Mixed_6b->forward(x); - // 17 x 17 x 768 - x = Mixed_6c->forward(x); - // 17 x 17 x 768 - x = Mixed_6d->forward(x); - // 17 x 17 x 768 - x = Mixed_6e->forward(x); - // 17 x 17 x 768 - torch::Tensor aux; - if (is_training() && aux_logits) aux = AuxLogits->forward(x); - // 17 x 17 x 768 - x = Mixed_7a->forward(x); - // 8 x 8 x 1280 - x = Mixed_7b->forward(x); - // 8 x 8 x 2048 - x = Mixed_7c->forward(x); - // 8 x 8 x 2048 - x = torch::avg_pool2d(x, 8); - // 1 x 1 x 2048 - x = torch::dropout(x, 0.5, is_training()); - // 1 x 1 x 2048 - x = x.view({x.size(0), -1}); - // 2048 - x = fc->forward(x); - // 1000 (num_classes) - - if (is_training() && aux_logits) return {x, aux}; - return x; +std::vector InceptionV3Impl::forward(torch::Tensor x) { + if (transform_input) { + auto x_ch0 = torch::unsqueeze(x.select(1, 0), 1) * (0.229 / 0.5) + + (0.485 - 0.5) / 0.5; + auto x_ch1 = torch::unsqueeze(x.select(1, 1), 1) * (0.224 / 0.5) + + (0.456 - 0.5) / 0.5; + auto x_ch2 = torch::unsqueeze(x.select(1, 2), 1) * (0.225 / 0.5) + + (0.406 - 0.5) / 0.5; + + x = torch::cat({x_ch0, x_ch1, x_ch2}, 1); + } + + // 299 x 299 x 3 + x = Conv2d_1a_3x3->forward(x); + // 149 x 149 x 32 + x = Conv2d_2a_3x3->forward(x); + // 147 x 147 x 32 + x = Conv2d_2b_3x3->forward(x); + // 147 x 147 x 64 + x = torch::max_pool2d(x, 3, 2); + // 73 x 73 x 64 + x = Conv2d_3b_1x1->forward(x); + // 73 x 73 x 80 + x = Conv2d_4a_3x3->forward(x); + // 71 x 71 x 192 + x = torch::max_pool2d(x, 3, 2); + // 35 x 35 x 192 + x = Mixed_5b->forward(x); + // 35 x 35 x 256 + x = Mixed_5c->forward(x); + // 35 x 35 x 288 + x = Mixed_5d->forward(x); + // 35 x 35 x 288 + x = Mixed_6a->forward(x); + // 17 x 17 x 768 + x = Mixed_6b->forward(x); + // 17 x 17 x 768 + x = Mixed_6c->forward(x); + // 17 x 17 x 768 + x = Mixed_6d->forward(x); + // 17 x 17 x 768 + x = Mixed_6e->forward(x); + // 17 x 17 x 768 + torch::Tensor aux; + if (is_training() && aux_logits) + aux = AuxLogits->forward(x); + // 17 x 17 x 768 + x = Mixed_7a->forward(x); + // 8 x 8 x 1280 + x = Mixed_7b->forward(x); + // 8 x 8 x 2048 + x = Mixed_7c->forward(x); + // 8 x 8 x 2048 + x = torch::avg_pool2d(x, 8); + // 1 x 1 x 2048 + x = torch::dropout(x, 0.5, is_training()); + // 1 x 1 x 2048 + x = x.view({x.size(0), -1}); + // 2048 + x = fc->forward(x); + // 1000 (num_classes) + + if (is_training() && aux_logits) + return {x, aux}; + return {x}; } // namespace _inceptionimpl -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/inception.h b/torchvision/csrc/models/inception.h index c61288f3705..53ef21c6643 100644 --- a/torchvision/csrc/models/inception.h +++ b/torchvision/csrc/models/inception.h @@ -3,113 +3,82 @@ #include -namespace vision -{ -namespace models -{ -namespace _inceptionimpl -{ -class BasicConv2dImpl : public torch::nn::Module -{ -protected: - torch::nn::Conv2d conv{nullptr}; - torch::nn::BatchNorm bn{nullptr}; - -public: - BasicConv2dImpl(torch::nn::Conv2dOptions options); - - torch::Tensor forward(torch::Tensor x); -}; - -TORCH_MODULE(BasicConv2d); +namespace vision { +namespace models { +namespace _inceptionimpl { +class BasicConv2dImpl : public torch::nn::Module { + public: + torch::nn::Conv2d conv{nullptr}; + torch::nn::BatchNorm bn{nullptr}; -class InceptionAImpl : public torch::nn::Module -{ - BasicConv2d branch1x1, branch5x5_1, branch5x5_2, branch3x3dbl_1, - branch3x3dbl_2, branch3x3dbl_3, branch_pool; + BasicConv2dImpl(torch::nn::Conv2dOptions options, double std_dev = 0.1); -public: - InceptionAImpl(int64_t in_channels, int64_t pool_features); - - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; -class InceptionBImpl : public torch::nn::Module -{ - BasicConv2d branch3x3, branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3; +TORCH_MODULE(BasicConv2d); -public: - InceptionBImpl(int64_t in_channels); +class InceptionAImpl : public torch::nn::Module { + BasicConv2d branch1x1, branch5x5_1, branch5x5_2, branch3x3dbl_1, + branch3x3dbl_2, branch3x3dbl_3, branch_pool; - torch::Tensor forward(torch::Tensor x); + public: + InceptionAImpl(int64_t in_channels, int64_t pool_features); + + torch::Tensor forward(torch::Tensor x); }; -class InceptionCImpl : public torch::nn::Module -{ - BasicConv2d branch1x1{nullptr}, branch7x7_1{nullptr}, branch7x7_2{nullptr}, - branch7x7_3{nullptr}, branch7x7dbl_1{nullptr}, branch7x7dbl_2{nullptr}, - branch7x7dbl_3{nullptr}, branch7x7dbl_4{nullptr}, - branch7x7dbl_5{nullptr}, branch_pool{nullptr}; +class InceptionBImpl : public torch::nn::Module { + BasicConv2d branch3x3, branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3; -public: - InceptionCImpl(int64_t in_channels, int64_t channels_7x7); + public: + InceptionBImpl(int64_t in_channels); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; -class InceptionDImpl : public torch::nn::Module -{ - BasicConv2d branch3x3_1, branch3x3_2, branch7x7x3_1, branch7x7x3_2, - branch7x7x3_3, branch7x7x3_4; +class InceptionCImpl : public torch::nn::Module { + BasicConv2d branch1x1{nullptr}, branch7x7_1{nullptr}, branch7x7_2{nullptr}, + branch7x7_3{nullptr}, branch7x7dbl_1{nullptr}, branch7x7dbl_2{nullptr}, + branch7x7dbl_3{nullptr}, branch7x7dbl_4{nullptr}, branch7x7dbl_5{nullptr}, + branch_pool{nullptr}; -public: - InceptionDImpl(int64_t in_channels); + public: + InceptionCImpl(int64_t in_channels, int64_t channels_7x7); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; -class InceptionEImpl : public torch::nn::Module -{ - BasicConv2d branch1x1, branch3x3_1, branch3x3_2a, branch3x3_2b, - branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3a, branch3x3dbl_3b, - branch_pool; +class InceptionDImpl : public torch::nn::Module { + BasicConv2d branch3x3_1, branch3x3_2, branch7x7x3_1, branch7x7x3_2, + branch7x7x3_3, branch7x7x3_4; -public: - InceptionEImpl(int64_t in_channels); + public: + InceptionDImpl(int64_t in_channels); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; -class AuxBasicConvImpl : public BasicConv2dImpl -{ -public: - using BasicConv2dImpl::BasicConv2dImpl; - - using BasicConv2dImpl::conv; - double stddev{0}; -}; +class InceptionEImpl : public torch::nn::Module { + BasicConv2d branch1x1, branch3x3_1, branch3x3_2a, branch3x3_2b, + branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3a, branch3x3dbl_3b, + branch_pool; -class AuxLinearImpl : public torch::nn::LinearImpl -{ -public: - using torch::nn::LinearImpl::LinearImpl; + public: + InceptionEImpl(int64_t in_channels); - double stddev{0}; + torch::Tensor forward(torch::Tensor x); }; -TORCH_MODULE(AuxBasicConv); -TORCH_MODULE(AuxLinear); - -class InceptionAuxImpl : public torch::nn::Module -{ - BasicConv2d conv0; - AuxBasicConv conv1; - AuxLinear fc; +class InceptionAuxImpl : public torch::nn::Module { + BasicConv2d conv0; + BasicConv2d conv1; + torch::nn::Linear fc; -public: - InceptionAuxImpl(int64_t in_channels, int64_t num_classes); + public: + InceptionAuxImpl(int64_t in_channels, int64_t num_classes); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; TORCH_MODULE(InceptionA); @@ -119,37 +88,38 @@ TORCH_MODULE(InceptionD); TORCH_MODULE(InceptionE); TORCH_MODULE(InceptionAux); -} // namespace _inceptionimpl +} // namespace _inceptionimpl // Inception v3 model architecture from //"Rethinking the Inception Architecture for Computer Vision" // -class InceptionV3Impl : public torch::nn::Module -{ - bool aux_logits, transform_input; - _inceptionimpl::BasicConv2d Conv2d_1a_3x3{nullptr}, Conv2d_2a_3x3{nullptr}, - Conv2d_2b_3x3{nullptr}, Conv2d_3b_1x1{nullptr}, Conv2d_4a_3x3{nullptr}; - _inceptionimpl::InceptionA Mixed_5b{nullptr}, Mixed_5c{nullptr}, - Mixed_5d{nullptr}; - _inceptionimpl::InceptionB Mixed_6a{nullptr}; - _inceptionimpl::InceptionC Mixed_6b{nullptr}, Mixed_6c{nullptr}, - Mixed_6d{nullptr}, Mixed_6e{nullptr}; - _inceptionimpl::InceptionD Mixed_7a{nullptr}; - _inceptionimpl::InceptionE Mixed_7b{nullptr}, Mixed_7c{nullptr}; - torch::nn::Linear fc{nullptr}; - - _inceptionimpl::InceptionAux AuxLogits{nullptr}; - -public: - InceptionV3Impl(int64_t num_classes = 1000, bool aux_logits = true, - bool transform_input = false); - - torch::TensorList forward(torch::Tensor x); +class InceptionV3Impl : public torch::nn::Module { + bool aux_logits, transform_input; + _inceptionimpl::BasicConv2d Conv2d_1a_3x3{nullptr}, Conv2d_2a_3x3{nullptr}, + Conv2d_2b_3x3{nullptr}, Conv2d_3b_1x1{nullptr}, Conv2d_4a_3x3{nullptr}; + _inceptionimpl::InceptionA Mixed_5b{nullptr}, Mixed_5c{nullptr}, + Mixed_5d{nullptr}; + _inceptionimpl::InceptionB Mixed_6a{nullptr}; + _inceptionimpl::InceptionC Mixed_6b{nullptr}, Mixed_6c{nullptr}, + Mixed_6d{nullptr}, Mixed_6e{nullptr}; + _inceptionimpl::InceptionD Mixed_7a{nullptr}; + _inceptionimpl::InceptionE Mixed_7b{nullptr}, Mixed_7c{nullptr}; + torch::nn::Linear fc{nullptr}; + + _inceptionimpl::InceptionAux AuxLogits{nullptr}; + + public: + InceptionV3Impl( + int64_t num_classes = 1000, + bool aux_logits = true, + bool transform_input = false); + + std::vector forward(torch::Tensor x); }; TORCH_MODULE(InceptionV3); -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision -#endif // INCEPTION_H +#endif // INCEPTION_H diff --git a/torchvision/csrc/models/models.h b/torchvision/csrc/models/models.h index 009717018c6..0713810082d 100644 --- a/torchvision/csrc/models/models.h +++ b/torchvision/csrc/models/models.h @@ -8,4 +8,4 @@ #include "squeezenet.h" #include "vgg.h" -#endif // MODELS_H +#endif // MODELS_H diff --git a/torchvision/csrc/models/modelsimpl.cpp b/torchvision/csrc/models/modelsimpl.cpp index 69b16330db0..32e2f610b68 100644 --- a/torchvision/csrc/models/modelsimpl.cpp +++ b/torchvision/csrc/models/modelsimpl.cpp @@ -1,61 +1,53 @@ #include "modelsimpl.h" -namespace vision -{ -namespace models -{ -namespace modelsimpl -{ +namespace vision { +namespace models { +namespace modelsimpl { ReluImpl::ReluImpl(bool inplace) : inplace(inplace) {} -torch::Tensor ReluImpl::forward(torch::Tensor X) -{ - if (inplace) - { - X.relu_(); - return X; - } +torch::Tensor ReluImpl::forward(torch::Tensor X) { + if (inplace) { + X.relu_(); + return X; + } - return torch::relu(X); + return torch::relu(X); } -MaxPool2DImpl::MaxPool2DImpl(torch::ExpandingArray<2> kernel, - torch::ExpandingArray<2> stride) - : options(MaxPool2DOptions(kernel).stride(stride)) -{ -} +MaxPool2DImpl::MaxPool2DImpl( + torch::ExpandingArray<2> kernel, + torch::ExpandingArray<2> stride) + : options(MaxPool2DOptions(kernel).stride(stride)) {} MaxPool2DImpl::MaxPool2DImpl(MaxPool2DOptions options) : options(options) {} -torch::Tensor MaxPool2DImpl::forward(torch::Tensor X) -{ - return torch::max_pool2d(X, options.kernel_size(), options.stride(), - options.padding(), options.dilation(), - options.ceil_mode()); +torch::Tensor MaxPool2DImpl::forward(torch::Tensor X) { + return torch::max_pool2d( + X, + options.kernel_size(), + options.stride(), + options.padding(), + options.dilation(), + options.ceil_mode()); } AdaptiveAvgPool2DImpl::AdaptiveAvgPool2DImpl( - torch::ExpandingArray<2> output_size) - : output_size(output_size) -{ -} + torch::ExpandingArray<2> output_size) + : output_size(output_size) {} -torch::Tensor AdaptiveAvgPool2DImpl::forward(torch::Tensor x) -{ - return torch::adaptive_avg_pool2d(x, output_size); +torch::Tensor AdaptiveAvgPool2DImpl::forward(torch::Tensor x) { + return torch::adaptive_avg_pool2d(x, output_size); } -AvgPool2DImpl::AvgPool2DImpl(torch::ExpandingArray<2> kernel_size, - torch::ExpandingArray<2> stride) - : kernel_size(kernel_size), stride(stride) -{ -} +AvgPool2DImpl::AvgPool2DImpl( + torch::ExpandingArray<2> kernel_size, + torch::ExpandingArray<2> stride) + : kernel_size(kernel_size), stride(stride) {} -torch::Tensor AvgPool2DImpl::forward(torch::Tensor x) -{ - return torch::avg_pool2d(x, kernel_size, stride); +torch::Tensor AvgPool2DImpl::forward(torch::Tensor x) { + return torch::avg_pool2d(x, kernel_size, stride); } -} // namespace modelsimpl -} // namespace models -} // namespace vision +} // namespace modelsimpl +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/modelsimpl.h b/torchvision/csrc/models/modelsimpl.h index b50a108b690..4d703bd2f36 100644 --- a/torchvision/csrc/models/modelsimpl.h +++ b/torchvision/csrc/models/modelsimpl.h @@ -3,68 +3,60 @@ #include -namespace vision -{ -namespace models -{ -namespace modelsimpl -{ -class ReluImpl : public torch::nn::Module -{ - bool inplace; - -public: - ReluImpl(bool inplace = false); - - torch::Tensor forward(torch::Tensor X); +namespace vision { +namespace models { +namespace modelsimpl { +class ReluImpl : public torch::nn::Module { + bool inplace; + + public: + ReluImpl(bool inplace = false); + + torch::Tensor forward(torch::Tensor X); }; -struct MaxPool2DOptions -{ - MaxPool2DOptions(torch::ExpandingArray<2> kernel_size) - : kernel_size_(kernel_size), stride_(kernel_size) - { - } - - TORCH_ARG(torch::ExpandingArray<2>, kernel_size); - TORCH_ARG(torch::ExpandingArray<2>, stride); - TORCH_ARG(torch::ExpandingArray<2>, padding) = 0; - TORCH_ARG(torch::ExpandingArray<2>, dilation) = 1; - TORCH_ARG(bool, ceil_mode) = false; +struct MaxPool2DOptions { + MaxPool2DOptions(torch::ExpandingArray<2> kernel_size) + : kernel_size_(kernel_size), stride_(kernel_size) {} + + TORCH_ARG(torch::ExpandingArray<2>, kernel_size); + TORCH_ARG(torch::ExpandingArray<2>, stride); + TORCH_ARG(torch::ExpandingArray<2>, padding) = 0; + TORCH_ARG(torch::ExpandingArray<2>, dilation) = 1; + TORCH_ARG(bool, ceil_mode) = false; }; -class MaxPool2DImpl : public torch::nn::Module -{ - MaxPool2DOptions options; +class MaxPool2DImpl : public torch::nn::Module { + MaxPool2DOptions options; -public: - MaxPool2DImpl(torch::ExpandingArray<2> kernel, - torch::ExpandingArray<2> stride); + public: + MaxPool2DImpl( + torch::ExpandingArray<2> kernel, + torch::ExpandingArray<2> stride); - explicit MaxPool2DImpl(MaxPool2DOptions options); + explicit MaxPool2DImpl(MaxPool2DOptions options); - torch::Tensor forward(torch::Tensor X); + torch::Tensor forward(torch::Tensor X); }; -class AdaptiveAvgPool2DImpl : public torch::nn::Module -{ - torch::ExpandingArray<2> output_size; +class AdaptiveAvgPool2DImpl : public torch::nn::Module { + torch::ExpandingArray<2> output_size; -public: - AdaptiveAvgPool2DImpl(torch::ExpandingArray<2> output_size); + public: + AdaptiveAvgPool2DImpl(torch::ExpandingArray<2> output_size); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; -class AvgPool2DImpl : public torch::nn::Module -{ - torch::ExpandingArray<2> kernel_size, stride; +class AvgPool2DImpl : public torch::nn::Module { + torch::ExpandingArray<2> kernel_size, stride; -public: - AvgPool2DImpl(torch::ExpandingArray<2> kernel_size, - torch::ExpandingArray<2> stride); + public: + AvgPool2DImpl( + torch::ExpandingArray<2> kernel_size, + torch::ExpandingArray<2> stride); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; TORCH_MODULE(Relu); @@ -72,8 +64,8 @@ TORCH_MODULE(MaxPool2D); TORCH_MODULE(AvgPool2D); TORCH_MODULE(AdaptiveAvgPool2D); -} // namespace modelsimpl -} // namespace models -} // namespace vision +} // namespace modelsimpl +} // namespace models +} // namespace vision -#endif // MODELSIMPL_H +#endif // MODELSIMPL_H diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index 743d44400be..7eaaaebab40 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -2,129 +2,120 @@ #include "modelsimpl.h" -namespace vision -{ -namespace models -{ -namespace _resnetimpl -{ -torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride) -{ - torch::nn::Conv2dOptions O(in, out, 3); - O.padding(1).stride(stride).with_bias(false); - return torch::nn::Conv2d(O); +namespace vision { +namespace models { +namespace _resnetimpl { +torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride) { + torch::nn::Conv2dOptions O(in, out, 3); + O.padding(1).stride(stride).with_bias(false); + return torch::nn::Conv2d(O); } -torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride) -{ - torch::nn::Conv2dOptions O(in, out, 1); - O.stride(stride).with_bias(false); - return torch::nn::Conv2d(O); +torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride) { + torch::nn::Conv2dOptions O(in, out, 1); + O.stride(stride).with_bias(false); + return torch::nn::Conv2d(O); } -int BasicBlock::expantion = 1; -int Bottleneck::expantion = 4; - -BasicBlock::BasicBlock(int64_t inplanes, int64_t planes, int64_t stride, - torch::nn::Sequential downsample) - : stride(stride), - downsample(downsample), - conv1(conv3x3(inplanes, planes, stride)), - conv2(conv3x3(planes, planes)), - bn1(planes), - bn2(planes) -{ - register_module("conv1", conv1); - register_module("conv2", conv2); - - register_module("bn1", bn1); - register_module("bn2", bn2); - - if (!downsample.is_empty()) register_module("downsample", this->downsample); +int BasicBlock::expansion = 1; +int Bottleneck::expansion = 4; + +BasicBlock::BasicBlock( + int64_t inplanes, + int64_t planes, + int64_t stride, + torch::nn::Sequential downsample) + : stride(stride), + downsample(downsample), + conv1(conv3x3(inplanes, planes, stride)), + conv2(conv3x3(planes, planes)), + bn1(planes), + bn2(planes) { + register_module("conv1", conv1); + register_module("conv2", conv2); + + register_module("bn1", bn1); + register_module("bn2", bn2); + + if (!downsample.is_empty()) + register_module("downsample", this->downsample); } -Bottleneck::Bottleneck(int64_t inplanes, int64_t planes, int64_t stride, - torch::nn::Sequential downsample) - : stride(stride), - downsample(downsample), - conv1(conv1x1(inplanes, planes)), - conv2(conv3x3(planes, planes, stride)), - conv3(conv1x1(planes, planes * expantion)), - bn1(planes), - bn2(planes), - bn3(planes * expantion) -{ - register_module("conv1", conv1); - register_module("conv2", conv2); - register_module("conv3", conv3); - - register_module("bn1", bn1); - register_module("bn2", bn2); - register_module("bn3", bn3); - - if (!downsample.is_empty()) register_module("downsample", this->downsample); +Bottleneck::Bottleneck( + int64_t inplanes, + int64_t planes, + int64_t stride, + torch::nn::Sequential downsample) + : stride(stride), + downsample(downsample), + conv1(conv1x1(inplanes, planes)), + conv2(conv3x3(planes, planes, stride)), + conv3(conv1x1(planes, planes * expansion)), + bn1(planes), + bn2(planes), + bn3(planes * expansion) { + register_module("conv1", conv1); + register_module("conv2", conv2); + register_module("conv3", conv3); + + register_module("bn1", bn1); + register_module("bn2", bn2); + register_module("bn3", bn3); + + if (!downsample.is_empty()) + register_module("downsample", this->downsample); } -torch::Tensor Bottleneck::forward(torch::Tensor X) -{ - auto identity = X; +torch::Tensor Bottleneck::forward(torch::Tensor X) { + auto identity = X; - auto out = conv1->forward(X); - out = bn1->forward(out).relu_(); + auto out = conv1->forward(X); + out = bn1->forward(out).relu_(); - out = conv2->forward(out); - out = bn2->forward(out).relu_(); + out = conv2->forward(out); + out = bn2->forward(out).relu_(); - out = conv3->forward(out); - out = bn3->forward(out); + out = conv3->forward(out); + out = bn3->forward(out); - if (!downsample.is_empty()) identity = downsample->forward(X); + if (!downsample.is_empty()) + identity = downsample->forward(X); - out += identity; - return out.relu_(); + out += identity; + return out.relu_(); } -torch::Tensor BasicBlock::forward(torch::Tensor x) -{ - auto identity = x; +torch::Tensor BasicBlock::forward(torch::Tensor x) { + auto identity = x; - auto out = conv1->forward(x); - out = bn1->forward(out).relu_(); + auto out = conv1->forward(x); + out = bn1->forward(out).relu_(); - out = conv2->forward(out); - out = bn2->forward(out); + out = conv2->forward(out); + out = bn2->forward(out); - if (!downsample.is_empty()) identity = downsample->forward(x); + if (!downsample.is_empty()) + identity = downsample->forward(x); - out += identity; - return out.relu_(); + out += identity; + return out.relu_(); } -} // namespace _resnetimpl +} // namespace _resnetimpl ResNet18Impl::ResNet18Impl(int64_t num_classes, bool zero_init_residual) - : ResNetImpl({2, 2, 2, 2}, num_classes, zero_init_residual) -{ -} + : ResNetImpl({2, 2, 2, 2}, num_classes, zero_init_residual) {} ResNet34Impl::ResNet34Impl(int64_t num_classes, bool zero_init_residual) - : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) -{ -} + : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) {} ResNet50Impl::ResNet50Impl(int64_t num_classes, bool zero_init_residual) - : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) -{ -} + : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual) {} ResNet101Impl::ResNet101Impl(int64_t num_classes, bool zero_init_residual) - : ResNetImpl({3, 4, 23, 3}, num_classes, zero_init_residual) -{ -} + : ResNetImpl({3, 4, 23, 3}, num_classes, zero_init_residual) {} ResNet152Impl::ResNet152Impl(int64_t num_classes, bool zero_init_residual) - : ResNetImpl({3, 8, 36, 3}, num_classes, zero_init_residual) -{ -} + : ResNetImpl({3, 8, 36, 3}, num_classes, zero_init_residual) {} -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 25b9807c295..c7fdcbc64c0 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -3,215 +3,210 @@ #include -namespace vision -{ -namespace models -{ +namespace vision { +namespace models { template class ResNetImpl; -namespace _resnetimpl -{ +namespace _resnetimpl { // 3x3 convolution with padding torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride = 1); // 1x1 convolution torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride = 1); -class BasicBlock : public torch::nn::Module -{ - template - friend class vision::models::ResNetImpl; +class BasicBlock : public torch::nn::Module { + template + friend class vision::models::ResNetImpl; - int64_t stride; - torch::nn::Sequential downsample; + int64_t stride; + torch::nn::Sequential downsample; - torch::nn::Conv2d conv1, conv2; - torch::nn::BatchNorm bn1, bn2; + torch::nn::Conv2d conv1, conv2; + torch::nn::BatchNorm bn1, bn2; -public: - static int expantion; + public: + static int expansion; - BasicBlock(int64_t inplanes, int64_t planes, int64_t stride = 1, - torch::nn::Sequential downsample = nullptr); + BasicBlock( + int64_t inplanes, + int64_t planes, + int64_t stride = 1, + torch::nn::Sequential downsample = nullptr); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; -class Bottleneck : public torch::nn::Module -{ - template - friend class vision::models::ResNetImpl; +class Bottleneck : public torch::nn::Module { + template + friend class vision::models::ResNetImpl; - int64_t stride; - torch::nn::Sequential downsample; + int64_t stride; + torch::nn::Sequential downsample; - torch::nn::Conv2d conv1, conv2, conv3; - torch::nn::BatchNorm bn1, bn2, bn3; + torch::nn::Conv2d conv1, conv2, conv3; + torch::nn::BatchNorm bn1, bn2, bn3; -public: - static int expantion; + public: + static int expansion; - Bottleneck(int64_t inplanes, int64_t planes, int64_t stride = 1, - torch::nn::Sequential downsample = nullptr); + Bottleneck( + int64_t inplanes, + int64_t planes, + int64_t stride = 1, + torch::nn::Sequential downsample = nullptr); - torch::Tensor forward(torch::Tensor X); + torch::Tensor forward(torch::Tensor X); }; -} // namespace _resnetimpl +} // namespace _resnetimpl template -class ResNetImpl : public torch::nn::Module -{ - int64_t inplanes; - torch::nn::Conv2d conv1; - torch::nn::BatchNorm bn1; - torch::nn::Linear fc; - torch::nn::Sequential layer1, layer2, layer3, layer4; - - torch::nn::Sequential _make_layer(int64_t planes, int64_t blocks, - int64_t stride = 1); - -public: - ResNetImpl(const std::vector &layers, int64_t num_classes = 1000, - bool zero_init_residual = false); - - torch::Tensor forward(torch::Tensor X); +class ResNetImpl : public torch::nn::Module { + int64_t inplanes; + torch::nn::Conv2d conv1; + torch::nn::BatchNorm bn1; + torch::nn::Linear fc; + torch::nn::Sequential layer1, layer2, layer3, layer4; + + torch::nn::Sequential _make_layer( + int64_t planes, + int64_t blocks, + int64_t stride = 1); + + public: + ResNetImpl( + const std::vector& layers, + int64_t num_classes = 1000, + bool zero_init_residual = false); + + torch::Tensor forward(torch::Tensor X); }; template -torch::nn::Sequential ResNetImpl::_make_layer(int64_t planes, - int64_t blocks, - int64_t stride) -{ - torch::nn::Sequential downsample = nullptr; - if (stride != 1 || inplanes != planes * Block::expantion) - { - downsample = torch::nn::Sequential( - _resnetimpl::conv1x1(inplanes, planes * Block::expantion, stride), - torch::nn::BatchNorm(planes * Block::expantion)); - } - - torch::nn::Sequential layers; - layers->push_back(Block(inplanes, planes, stride, downsample)); - - inplanes = planes * Block::expantion; - - for (int i = 1; i < blocks; ++i) layers->push_back(Block(inplanes, planes)); - - return layers; +torch::nn::Sequential ResNetImpl::_make_layer( + int64_t planes, + int64_t blocks, + int64_t stride) { + torch::nn::Sequential downsample = nullptr; + if (stride != 1 || inplanes != planes * Block::expansion) { + downsample = torch::nn::Sequential( + _resnetimpl::conv1x1(inplanes, planes * Block::expansion, stride), + torch::nn::BatchNorm(planes * Block::expansion)); + } + + torch::nn::Sequential layers; + layers->push_back(Block(inplanes, planes, stride, downsample)); + + inplanes = planes * Block::expansion; + + for (int i = 1; i < blocks; ++i) + layers->push_back(Block(inplanes, planes)); + + return layers; } template -ResNetImpl::ResNetImpl(const std::vector &layers, - int64_t num_classes, bool zero_init_residual) - : inplanes(64), - conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( - false)), - bn1(64), - layer1(_make_layer(64, layers[0])), - layer2(_make_layer(128, layers[1], 2)), - layer3(_make_layer(256, layers[2], 2)), - layer4(_make_layer(512, layers[3], 2)), - fc(512 * Block::expantion, num_classes) -{ - register_module("conv1", conv1); - register_module("bn1", bn1); - register_module("fc", fc); - - register_module("layer1", layer1); - register_module("layer2", layer2); - register_module("layer3", layer3); - register_module("layer4", layer4); - - for (auto &module : modules(false)) - { - if (torch::nn::Conv2dImpl *M = - dynamic_cast(module.get())) - { - torch::nn::init::xavier_normal_(M->weight); - } - else if (torch::nn::BatchNormImpl *M = - dynamic_cast(module.get())) - { - torch::nn::init::constant_(M->weight, 1); - torch::nn::init::constant_(M->bias, 0); - } - } - - // Zero-initialize the last BN in each residual branch, so that the residual - // branch starts with zeros, and each residual block behaves like an - // identity. This improves the model by 0.2~0.3% according to - // https://arxiv.org/abs/1706.02677 - if (zero_init_residual) - for (auto &module : modules(false)) - { - if (_resnetimpl::Bottleneck *M = - dynamic_cast<_resnetimpl::Bottleneck *>(module.get())) - torch::nn::init::constant_(M->bn3->weight, 0); - else if (_resnetimpl::BasicBlock *M = - dynamic_cast<_resnetimpl::BasicBlock *>(module.get())) - torch::nn::init::constant_(M->bn2->weight, 0); - } +ResNetImpl::ResNetImpl( + const std::vector& layers, + int64_t num_classes, + bool zero_init_residual) + : inplanes(64), + conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( + false)), + bn1(64), + layer1(_make_layer(64, layers[0])), + layer2(_make_layer(128, layers[1], 2)), + layer3(_make_layer(256, layers[2], 2)), + layer4(_make_layer(512, layers[3], 2)), + fc(512 * Block::expansion, num_classes) { + register_module("conv1", conv1); + register_module("bn1", bn1); + register_module("fc", fc); + + register_module("layer1", layer1); + register_module("layer2", layer2); + register_module("layer3", layer3); + register_module("layer4", layer4); + + for (auto& module : modules(false)) { + if (torch::nn::Conv2dImpl* M = + dynamic_cast(module.get())) { + torch::nn::init::xavier_normal_(M->weight); // TODO kaiming + } else if ( + torch::nn::BatchNormImpl* M = + dynamic_cast(module.get())) { + torch::nn::init::constant_(M->weight, 1); + torch::nn::init::constant_(M->bias, 0); + } + } + + // Zero-initialize the last BN in each residual branch, so that the residual + // branch starts with zeros, and each residual block behaves like an + // identity. This improves the model by 0.2~0.3% according to + // https://arxiv.org/abs/1706.02677 + if (zero_init_residual) + for (auto& module : modules(false)) { + if (_resnetimpl::Bottleneck* M = + dynamic_cast<_resnetimpl::Bottleneck*>(module.get())) + torch::nn::init::constant_(M->bn3->weight, 0); + else if ( + _resnetimpl::BasicBlock* M = + dynamic_cast<_resnetimpl::BasicBlock*>(module.get())) + torch::nn::init::constant_(M->bn2->weight, 0); + } } template -torch::Tensor ResNetImpl::forward(torch::Tensor x) -{ - x = conv1->forward(x); - x = bn1->forward(x).relu_(); - x = torch::max_pool2d(x, 3, 2, 1); - - x = layer1->forward(x); - x = layer2->forward(x); - x = layer3->forward(x); - x = layer4->forward(x); - - x = torch::adaptive_avg_pool2d(x, {1, 1}); - x = x.view({x.size(0), -1}); - x = fc->forward(x); - - return x; +torch::Tensor ResNetImpl::forward(torch::Tensor x) { + x = conv1->forward(x); + x = bn1->forward(x).relu_(); + x = torch::max_pool2d(x, 3, 2, 1); + + x = layer1->forward(x); + x = layer2->forward(x); + x = layer3->forward(x); + x = layer4->forward(x); + + x = torch::adaptive_avg_pool2d(x, {1, 1}); + x = x.view({x.size(0), -1}); + x = fc->forward(x); + + return x; } // ResNet-18 model -class ResNet18Impl : public ResNetImpl<_resnetimpl::BasicBlock> -{ -public: - ResNet18Impl(int64_t num_classes = 1000, bool zero_init_residual = false); +class ResNet18Impl : public ResNetImpl<_resnetimpl::BasicBlock> { + public: + ResNet18Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; // ResNet-34 model -class ResNet34Impl : public ResNetImpl<_resnetimpl::BasicBlock> -{ -public: - ResNet34Impl(int64_t num_classes = 1000, bool zero_init_residual = false); +class ResNet34Impl : public ResNetImpl<_resnetimpl::BasicBlock> { + public: + ResNet34Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; // ResNet-50 model -class ResNet50Impl : public ResNetImpl<_resnetimpl::Bottleneck> -{ -public: - ResNet50Impl(int64_t num_classes = 1000, bool zero_init_residual = false); +class ResNet50Impl : public ResNetImpl<_resnetimpl::Bottleneck> { + public: + ResNet50Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; // ResNet-101 model -class ResNet101Impl : public ResNetImpl<_resnetimpl::Bottleneck> -{ -public: - ResNet101Impl(int64_t num_classes = 1000, bool zero_init_residual = false); +class ResNet101Impl : public ResNetImpl<_resnetimpl::Bottleneck> { + public: + ResNet101Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; // ResNet-152 model -class ResNet152Impl : public ResNetImpl<_resnetimpl::Bottleneck> -{ -public: - ResNet152Impl(int64_t num_classes = 1000, bool zero_init_residual = false); +class ResNet152Impl : public ResNetImpl<_resnetimpl::Bottleneck> { + public: + ResNet152Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; template -class ResNet : public torch::nn::ModuleHolder> -{ -public: - using torch::nn::ModuleHolder>::ModuleHolder; +class ResNet : public torch::nn::ModuleHolder> { + public: + using torch::nn::ModuleHolder>::ModuleHolder; }; TORCH_MODULE(ResNet18); @@ -220,7 +215,7 @@ TORCH_MODULE(ResNet50); TORCH_MODULE(ResNet101); TORCH_MODULE(ResNet152); -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision -#endif // RESNET_H +#endif // RESNET_H diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index dae057a5d32..3bf1d6dd2a4 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -3,48 +3,44 @@ #include #include "modelsimpl.h" -namespace vision -{ -namespace models -{ -class Fire : public torch::nn::Module -{ - torch::nn::Conv2d squeeze, expand1x1, expand3x3; +namespace vision { +namespace models { +class Fire : public torch::nn::Module { + torch::nn::Conv2d squeeze, expand1x1, expand3x3; -public: - Fire(int64_t inplanes, int64_t squeeze_planes, int64_t expand1x1_planes, - int64_t expand3x3_planes) - : squeeze(torch::nn::Conv2dOptions(inplanes, squeeze_planes, 1)), - expand1x1( - torch::nn::Conv2dOptions(squeeze_planes, expand1x1_planes, 1)), - expand3x3( - torch::nn::Conv2dOptions(squeeze_planes, expand3x3_planes, 3) - .padding(1)) - { - register_module("squeeze", squeeze); - register_module("expand1x1", expand1x1); - register_module("expand3x3", expand3x3); - } + public: + Fire( + int64_t inplanes, + int64_t squeeze_planes, + int64_t expand1x1_planes, + int64_t expand3x3_planes) + : squeeze(torch::nn::Conv2dOptions(inplanes, squeeze_planes, 1)), + expand1x1( + torch::nn::Conv2dOptions(squeeze_planes, expand1x1_planes, 1)), + expand3x3(torch::nn::Conv2dOptions(squeeze_planes, expand3x3_planes, 3) + .padding(1)) { + register_module("squeeze", squeeze); + register_module("expand1x1", expand1x1); + register_module("expand3x3", expand3x3); + } - torch::Tensor forward(torch::Tensor x) - { - x = torch::relu(squeeze->forward(x)); - return torch::cat({torch::relu(expand1x1->forward(x)), - torch::relu(expand3x3->forward(x))}, - 1); - } + torch::Tensor forward(torch::Tensor x) { + x = torch::relu(squeeze->forward(x)); + return torch::cat( + {torch::relu(expand1x1->forward(x)), + torch::relu(expand3x3->forward(x))}, + 1); + } }; SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) - : num_classes(num_classes) -{ - auto double_compare = [](double a, double b) { - return double(std::abs(a - b)) < std::numeric_limits::epsilon(); - }; + : num_classes(num_classes) { + auto double_compare = [](double a, double b) { + return double(std::abs(a - b)) < std::numeric_limits::epsilon(); + }; - if (double_compare(version, 1.0)) - { - // clang-format off + if (double_compare(version, 1.0)) { + // clang-format off features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), modelsimpl::Relu(true), @@ -59,11 +55,9 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) Fire(384, 64, 256, 256), modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), Fire(512, 64, 256, 256)); - // clang-format on - } - else if (double_compare(version, 1.1)) - { - // clang-format off + // clang-format on + } else if (double_compare(version, 1.1)) { + // clang-format off features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), modelsimpl::Relu(true), @@ -78,59 +72,52 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) Fire(384, 48, 192, 192), Fire(384, 64, 256, 256), Fire(512, 64, 256, 256)); - // clang-format on - } - else - { - std::cerr << "Wrong version number is passed th SqueeseNet constructor!" - << std::endl; - assert(false); - } + // clang-format on + } else { + std::cerr << "Wrong version number is passed th SqueeseNet constructor!" + << std::endl; + assert(false); + } - // Final convolution is initialized differently form the rest - auto final_conv = - torch::nn::Conv2d(torch::nn::Conv2dOptions(512, num_classes, 1)); + // Final convolution is initialized differently form the rest + auto final_conv = + torch::nn::Conv2d(torch::nn::Conv2dOptions(512, num_classes, 1)); - // clang-format off + // clang-format off classifier = torch::nn::Sequential( torch::nn::Dropout(0.5), final_conv, modelsimpl::Relu(true), modelsimpl::AdaptiveAvgPool2D(1)); - // clang-format on + // clang-format on - register_module("features", features); - register_module("classifier", classifier); + register_module("features", features); + register_module("classifier", classifier); - for (auto &module : modules(false)) - if (torch::nn::Conv2dImpl *M = - dynamic_cast(module.get())) - { - if (M == final_conv.get()) - torch::nn::init::normal_(M->weight, 0.0, 0.01); - else - torch::nn::init::xavier_uniform_(M->weight); + for (auto& module : modules(false)) + if (torch::nn::Conv2dImpl* M = + dynamic_cast(module.get())) { + if (M == final_conv.get()) + torch::nn::init::normal_(M->weight, 0.0, 0.01); + else + torch::nn::init::xavier_uniform_(M->weight); // TODO kaiming - if (M->options.with_bias()) torch::nn::init::constant_(M->bias, 0); - } + if (M->options.with_bias()) + torch::nn::init::constant_(M->bias, 0); + } } -torch::Tensor SqueezeNetImpl::forward(torch::Tensor x) -{ - x = features->forward(x); - x = classifier->forward(x); - return x.view({x.size(0), num_classes}); +torch::Tensor SqueezeNetImpl::forward(torch::Tensor x) { + x = features->forward(x); + x = classifier->forward(x); + return x.view({x.size(0), num_classes}); } SqueezeNet1_0Impl::SqueezeNet1_0Impl(int64_t num_classes) - : SqueezeNetImpl(1.0, num_classes) -{ -} + : SqueezeNetImpl(1.0, num_classes) {} SqueezeNet1_1Impl::SqueezeNet1_1Impl(int64_t num_classes) - : SqueezeNetImpl(1.1, num_classes) -{ -} + : SqueezeNetImpl(1.1, num_classes) {} -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/squeezenet.h b/torchvision/csrc/models/squeezenet.h index da2678196ce..23ff58ef20a 100644 --- a/torchvision/csrc/models/squeezenet.h +++ b/torchvision/csrc/models/squeezenet.h @@ -3,45 +3,40 @@ #include -namespace vision -{ -namespace models -{ -class SqueezeNetImpl : public torch::nn::Module -{ - int64_t num_classes; - torch::nn::Sequential features{nullptr}, classifier{nullptr}; - -public: - SqueezeNetImpl(double version = 1.0, int64_t num_classes = 1000); - - torch::Tensor forward(torch::Tensor x); +namespace vision { +namespace models { +class SqueezeNetImpl : public torch::nn::Module { + int64_t num_classes; + torch::nn::Sequential features{nullptr}, classifier{nullptr}; + + public: + SqueezeNetImpl(double version = 1.0, int64_t num_classes = 1000); + + torch::Tensor forward(torch::Tensor x); }; // SqueezeNet model architecture from the "SqueezeNet: AlexNet-level // accuracy with 50x fewer parameters and <0.5MB model size" // paper. -class SqueezeNet1_0Impl : public SqueezeNetImpl -{ -public: - SqueezeNet1_0Impl(int64_t num_classes = 1000); +class SqueezeNet1_0Impl : public SqueezeNetImpl { + public: + SqueezeNet1_0Impl(int64_t num_classes = 1000); }; // SqueezeNet 1.1 model from the official SqueezeNet repo // . // SqueezeNet 1.1 has 2.4x less computation and slightly fewer parameters // than SqueezeNet 1.0, without sacrificing accuracy. -class SqueezeNet1_1Impl : public SqueezeNetImpl -{ -public: - SqueezeNet1_1Impl(int64_t num_classes = 1000); +class SqueezeNet1_1Impl : public SqueezeNetImpl { + public: + SqueezeNet1_1Impl(int64_t num_classes = 1000); }; TORCH_MODULE(SqueezeNet); TORCH_MODULE(SqueezeNet1_0); TORCH_MODULE(SqueezeNet1_1); -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision -#endif // SQUEEZENET_H +#endif // SQUEEZENET_H diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index 0c147f2b151..f64a2d517dd 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -3,64 +3,57 @@ #include #include "modelsimpl.h" -namespace vision -{ -namespace models -{ -torch::nn::Sequential makeLayers(const std::vector &cfg, - bool batch_norm = false) -{ - torch::nn::Sequential seq; - auto channels = 3; - - for (const auto &V : cfg) - { - if (V <= -1) - seq->push_back(modelsimpl::MaxPool2D(2, 2)); - else - { - seq->push_back(torch::nn::Conv2d( - torch::nn::Conv2dOptions(channels, V, 3).padding(1))); - - if (batch_norm) seq->push_back(torch::nn::BatchNorm(V)); - seq->push_back(modelsimpl::Relu(true)); - - channels = V; - } - } - - return seq; +namespace vision { +namespace models { +torch::nn::Sequential makeLayers( + const std::vector& cfg, + bool batch_norm = false) { + torch::nn::Sequential seq; + auto channels = 3; + + for (const auto& V : cfg) { + if (V <= -1) + seq->push_back(modelsimpl::MaxPool2D(2, 2)); + else { + seq->push_back(torch::nn::Conv2d( + torch::nn::Conv2dOptions(channels, V, 3).padding(1))); + + if (batch_norm) + seq->push_back(torch::nn::BatchNorm(V)); + seq->push_back(modelsimpl::Relu(true)); + + channels = V; + } + } + + return seq; } -void VGGImpl::_initialize_weights() -{ - for (auto &module : modules(false)) - { - if (torch::nn::Conv2dImpl *M = - dynamic_cast(module.get())) - { - torch::nn::init::xavier_normal_(M->weight); - torch::nn::init::constant_(M->bias, 0); - } - else if (torch::nn::BatchNormImpl *M = - dynamic_cast(module.get())) - { - torch::nn::init::constant_(M->weight, 1); - torch::nn::init::constant_(M->bias, 0); - } - else if (torch::nn::LinearImpl *M = - dynamic_cast(module.get())) - { - torch::nn::init::normal_(M->weight, 0, 0.01); - torch::nn::init::normal_(M->bias, 0); - } +void VGGImpl::_initialize_weights() { + for (auto& module : modules(false)) { + if (torch::nn::Conv2dImpl* M = + dynamic_cast(module.get())) { + torch::nn::init::xavier_normal_(M->weight); // TODO kaiming + torch::nn::init::constant_(M->bias, 0); + } else if ( + torch::nn::BatchNormImpl* M = + dynamic_cast(module.get())) { + torch::nn::init::constant_(M->weight, 1); + torch::nn::init::constant_(M->bias, 0); + } else if ( + torch::nn::LinearImpl* M = + dynamic_cast(module.get())) { + torch::nn::init::normal_(M->weight, 0, 0.01); + torch::nn::init::constant_(M->bias, 0); } + } } -VGGImpl::VGGImpl(torch::nn::Sequential features, int64_t num_classes, - bool initialize_weights) -{ - // clang-format off +VGGImpl::VGGImpl( + torch::nn::Sequential features, + int64_t num_classes, + bool initialize_weights) { + // clang-format off classifier = torch::nn::Sequential( torch::nn::Linear(512 * 7 * 7, 4096), modelsimpl::Relu(true), @@ -69,22 +62,22 @@ VGGImpl::VGGImpl(torch::nn::Sequential features, int64_t num_classes, modelsimpl::Relu(true), torch::nn::Dropout(), torch::nn::Linear(4096, num_classes)); - // clang-format on + // clang-format on - this->features = features; + this->features = features; - register_module("features", this->features); - register_module("classifier", classifier); + register_module("features", this->features); + register_module("classifier", classifier); - if (initialize_weights) _initialize_weights(); + if (initialize_weights) + _initialize_weights(); } -torch::Tensor VGGImpl::forward(torch::Tensor x) -{ - x = features->forward(x); - x = x.view({x.size(0), -1}); - x = classifier->forward(x); - return x; +torch::Tensor VGGImpl::forward(torch::Tensor x) { + x = features->forward(x); + x = x.view({x.size(0), -1}); + x = classifier->forward(x); + return x; } // clang-format off @@ -96,44 +89,28 @@ static std::map> cfg = { // clang-format on VGG11Impl::VGG11Impl(int64_t num_classes, bool initialize_weights) - : VGGImpl(makeLayers(cfg['A']), num_classes, initialize_weights) -{ -} + : VGGImpl(makeLayers(cfg['A']), num_classes, initialize_weights) {} VGG13Impl::VGG13Impl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['B']), num_classes, initWeights) -{ -} + : VGGImpl(makeLayers(cfg['B']), num_classes, initWeights) {} VGG16Impl::VGG16Impl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['D']), num_classes, initWeights) -{ -} + : VGGImpl(makeLayers(cfg['D']), num_classes, initWeights) {} VGG19Impl::VGG19Impl(int64_t num_classes, bool initialize_weights) - : VGGImpl(makeLayers(cfg['E']), num_classes, initialize_weights) -{ -} + : VGGImpl(makeLayers(cfg['E']), num_classes, initialize_weights) {} VGG11BNImpl::VGG11BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['A'], true), num_classes, initWeights) -{ -} + : VGGImpl(makeLayers(cfg['A'], true), num_classes, initWeights) {} VGG13BNImpl::VGG13BNImpl(int64_t num_classes, bool initialize_weights) - : VGGImpl(makeLayers(cfg['B'], true), num_classes, initialize_weights) -{ -} + : VGGImpl(makeLayers(cfg['B'], true), num_classes, initialize_weights) {} VGG16BNImpl::VGG16BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['D'], true), num_classes, initWeights) -{ -} + : VGGImpl(makeLayers(cfg['D'], true), num_classes, initWeights) {} VGG19BNImpl::VGG19BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['E'], true), num_classes, initWeights) -{ -} + : VGGImpl(makeLayers(cfg['E'], true), num_classes, initWeights) {} -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/vgg.h b/torchvision/csrc/models/vgg.h index 932b30608a6..0a65ad06153 100644 --- a/torchvision/csrc/models/vgg.h +++ b/torchvision/csrc/models/vgg.h @@ -3,77 +3,68 @@ #include -namespace vision -{ -namespace models -{ -class VGGImpl : public torch::nn::Module -{ - torch::nn::Sequential features{nullptr}, classifier{nullptr}; +namespace vision { +namespace models { +class VGGImpl : public torch::nn::Module { + torch::nn::Sequential features{nullptr}, classifier{nullptr}; - void _initialize_weights(); + void _initialize_weights(); -public: - VGGImpl(torch::nn::Sequential features, int64_t num_classes = 1000, - bool initialize_weights = true); + public: + VGGImpl( + torch::nn::Sequential features, + int64_t num_classes = 1000, + bool initialize_weights = true); - torch::Tensor forward(torch::Tensor x); + torch::Tensor forward(torch::Tensor x); }; // VGG 11-layer model (configuration "A") -class VGG11Impl : public VGGImpl -{ -public: - VGG11Impl(int64_t num_classes = 1000, bool initialize_weights = true); +class VGG11Impl : public VGGImpl { + public: + VGG11Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 13-layer model (configuration "B") -class VGG13Impl : public VGGImpl -{ -public: - VGG13Impl(int64_t num_classes = 1000, bool initialize_weights = true); +class VGG13Impl : public VGGImpl { + public: + VGG13Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 16-layer model (configuration "D") -class VGG16Impl : public VGGImpl -{ -public: - VGG16Impl(int64_t num_classes = 1000, bool initialize_weights = true); +class VGG16Impl : public VGGImpl { + public: + VGG16Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 19-layer model (configuration "E") -class VGG19Impl : public VGGImpl -{ -public: - VGG19Impl(int64_t num_classes = 1000, bool initialize_weights = true); +class VGG19Impl : public VGGImpl { + public: + VGG19Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 11-layer model (configuration "A") with batch normalization -class VGG11BNImpl : public VGGImpl -{ -public: - VGG11BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); +class VGG11BNImpl : public VGGImpl { + public: + VGG11BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 13-layer model (configuration "B") with batch normalization -class VGG13BNImpl : public VGGImpl -{ -public: - VGG13BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); +class VGG13BNImpl : public VGGImpl { + public: + VGG13BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 16-layer model (configuration "D") with batch normalization -class VGG16BNImpl : public VGGImpl -{ -public: - VGG16BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); +class VGG16BNImpl : public VGGImpl { + public: + VGG16BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 19-layer model (configuration 'E') with batch normalization -class VGG19BNImpl : public VGGImpl -{ -public: - VGG19BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); +class VGG19BNImpl : public VGGImpl { + public: + VGG19BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; TORCH_MODULE(VGG); @@ -88,7 +79,7 @@ TORCH_MODULE(VGG13BN); TORCH_MODULE(VGG16BN); TORCH_MODULE(VGG19BN); -} // namespace models -} // namespace vision +} // namespace models +} // namespace vision -#endif // VGG_H +#endif // VGG_H From dd2420e06ee1bc0d900a44e1aa3d39bb25f1edce Mon Sep 17 00:00:00 2001 From: Shahriar Date: Tue, 12 Feb 2019 16:33:29 +0330 Subject: [PATCH 12/48] Removed truncated normal init --- torchvision/csrc/models/inception.cpp | 29 ++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 57ee6dcbc4c..7f5983a40f2 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -4,19 +4,6 @@ namespace vision { namespace models { using Options = torch::nn::Conv2dOptions; -void init_weight(at::Tensor& weight, double stddev) { - std::vector sizes; - for (auto i : weight.sizes()) - sizes.push_back(i); - sizes.push_back(4); - - auto tmp = torch::empty(sizes, weight.options()).normal_(); - auto valid = (tmp < 2).__and__(tmp > -2); - auto ind = std::get<1>(valid.max(-1, true)); - weight = tmp.gather(-1, ind).squeeze(-1); - weight.mul_(stddev); -} - namespace _inceptionimpl { BasicConv2dImpl::BasicConv2dImpl( torch::nn::Conv2dOptions options, @@ -29,7 +16,11 @@ BasicConv2dImpl::BasicConv2dImpl( register_module("conv", conv); register_module("bn", bn); - init_weight(conv->weight, std_dev); + torch::nn::init::normal_( + conv->weight, + 0, + std_dev); // Note: used instead of truncated normal initialization + torch::nn::init::constant_(bn->weight, 1); torch::nn::init::constant_(bn->bias, 0); } @@ -221,7 +212,10 @@ InceptionAuxImpl::InceptionAuxImpl(int64_t in_channels, int64_t num_classes) : conv0(BasicConv2d(Options(in_channels, 128, 1))), conv1(BasicConv2d(Options(128, 768, 5), 0.01)), fc(768, num_classes) { - init_weight(fc->weight, 0.001); + torch::nn::init::normal_( + fc->weight, + 0, + 0.001); // Note: used instead of truncated normal initialization register_module("conv0", conv0); register_module("conv1", conv1); @@ -274,7 +268,10 @@ InceptionV3Impl::InceptionV3Impl( Mixed_7c = _inceptionimpl::InceptionE(2048); fc = torch::nn::Linear(2048, num_classes); - init_weight(fc->weight, 0.1); + torch::nn::init::normal_( + fc->weight, + 0, + 0.1); // Note: used instead of truncated normal initialization register_module("Conv2d_1a_3x3", Conv2d_1a_3x3); register_module("Conv2d_2a_3x3", Conv2d_2a_3x3); From 45347c0681360603c2a499263f2b7d99bf2f245d Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Thu, 14 Feb 2019 17:58:39 +0330 Subject: [PATCH 13/48] Changed classes to structs and fixed a few errors --- CMakeLists.txt.user | 375 +++++++++++++++++++++++++ torchvision/csrc/models/alexnet.cpp | 47 ++-- torchvision/csrc/models/alexnet.h | 3 +- torchvision/csrc/models/densenet.cpp | 25 +- torchvision/csrc/models/densenet.h | 15 +- torchvision/csrc/models/inception.h | 24 +- torchvision/csrc/models/resnet.h | 45 +-- torchvision/csrc/models/squeezenet.cpp | 84 +++--- torchvision/csrc/models/squeezenet.h | 9 +- torchvision/csrc/models/vgg.cpp | 61 ++-- torchvision/csrc/models/vgg.h | 27 +- 11 files changed, 515 insertions(+), 200 deletions(-) create mode 100644 CMakeLists.txt.user diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user new file mode 100644 index 00000000000..6a9def38841 --- /dev/null +++ b/CMakeLists.txt.user @@ -0,0 +1,375 @@ + + + + + + EnvironmentId + {9126aafa-d39a-4626-9808-b244ffd2484f} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.12.0 GCC 64bit + Desktop Qt 5.12.0 GCC 64bit + qt.qt5.5120.gcc_64_kit + 0 + 0 + 0 + + + /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Default + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Default + Default + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=Debug + + /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Debug + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=Release + + /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=RelWithDebInfo + + /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Release with Debug Information + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release with Debug Information + Release with Debug Information + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=MinSizeRel + + /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Minimum Size Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Minimum Size Release + Minimum Size Release + CMakeProjectManager.CMakeBuildConfiguration + + 5 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy Configuration + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + + Custom Executable + + ProjectExplorer.CustomExecutableRunConfiguration + + 3768 + false + true + false + false + true + + + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 20 + + + Version + 20 + + diff --git a/torchvision/csrc/models/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp index b72a13dcc17..85e5d26d9bd 100644 --- a/torchvision/csrc/models/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -5,31 +5,30 @@ namespace vision { namespace models { AlexNetImpl::AlexNetImpl(int64_t num_classes) { - // clang-format off - features = torch::nn::Sequential( - torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D(3, 2), - torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 192, 5).padding(2)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D(3, 2), - torch::nn::Conv2d(torch::nn::Conv2dOptions(192, 384, 3).padding(1)), - modelsimpl::Relu(true), - torch::nn::Conv2d(torch::nn::Conv2dOptions(384, 256, 3).padding(1)), - modelsimpl::Relu(true), - torch::nn::Conv2d(torch::nn::Conv2dOptions(256, 256, 3).padding(1)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D(3, 2)); + features = torch::nn::Sequential( + torch::nn::Conv2d( + torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), + torch::nn::Functional(torch::relu), + modelsimpl::MaxPool2D(3, 2), + torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 192, 5).padding(2)), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D(3, 2), + torch::nn::Conv2d(torch::nn::Conv2dOptions(192, 384, 3).padding(1)), + modelsimpl::Relu(true), + torch::nn::Conv2d(torch::nn::Conv2dOptions(384, 256, 3).padding(1)), + modelsimpl::Relu(true), + torch::nn::Conv2d(torch::nn::Conv2dOptions(256, 256, 3).padding(1)), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D(3, 2)); - classifier = torch::nn::Sequential( - torch::nn::Dropout(), - torch::nn::Linear(256 * 6 * 6, 4096), - modelsimpl::Relu(true), - torch::nn::Dropout(), - torch::nn::Linear(4096, 4096), - modelsimpl::Relu(true), - torch::nn::Linear(4096, num_classes)); - // clang-format on + classifier = torch::nn::Sequential( + torch::nn::Dropout(), + torch::nn::Linear(256 * 6 * 6, 4096), + modelsimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, 4096), + modelsimpl::Relu(true), + torch::nn::Linear(4096, num_classes)); register_module("features", features); register_module("clasifier", classifier); diff --git a/torchvision/csrc/models/alexnet.h b/torchvision/csrc/models/alexnet.h index ad28b89e2ac..66694e0c982 100644 --- a/torchvision/csrc/models/alexnet.h +++ b/torchvision/csrc/models/alexnet.h @@ -7,10 +7,9 @@ namespace vision { namespace models { // AlexNet model architecture from the // "One weird trick..." paper. -class AlexNetImpl : public torch::nn::Module { +struct AlexNetImpl : torch::nn::Module { torch::nn::Sequential features{nullptr}, classifier{nullptr}; - public: AlexNetImpl(int64_t num_classes = 1000); torch::Tensor forward(torch::Tensor x); diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index 0d60672aec7..c518b48eb9b 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -6,10 +6,9 @@ namespace vision { namespace models { using Options = torch::nn::Conv2dOptions; -class _DenseLayerImpl : public torch::nn::SequentialImpl { +struct _DenseLayerImpl : torch::nn::SequentialImpl { double drop_rate; - public: _DenseLayerImpl( int64_t num_input_features, int64_t growth_rate, @@ -41,8 +40,7 @@ class _DenseLayerImpl : public torch::nn::SequentialImpl { TORCH_MODULE(_DenseLayer); -class _DenseBlockImpl : public torch::nn::SequentialImpl { - public: +struct _DenseBlockImpl : torch::nn::SequentialImpl { _DenseBlockImpl( int64_t num_layers, int64_t num_input_features, @@ -66,8 +64,7 @@ class _DenseBlockImpl : public torch::nn::SequentialImpl { TORCH_MODULE(_DenseBlock); -class _TransitionImpl : public torch::nn::SequentialImpl { - public: +struct _TransitionImpl : torch::nn::SequentialImpl { _TransitionImpl(int64_t num_input_features, int64_t num_output_features) { push_back(torch::nn::BatchNorm(num_input_features)); push_back(modelsimpl::Relu(true)); @@ -107,8 +104,9 @@ DenseNetImpl::DenseNetImpl( auto num_features = num_init_features; for (size_t i = 0; i < block_config.size(); ++i) { auto num_layers = block_config[i]; - auto block = - _DenseBlock(num_layers, num_features, bn_size, growth_rate, drop_rate); + _DenseBlock block( + num_layers, num_features, bn_size, growth_rate, drop_rate); + features->push_back(block); num_features = num_features + num_layers * growth_rate; @@ -129,17 +127,12 @@ DenseNetImpl::DenseNetImpl( // Official init from torch repo. for (auto& module : modules(false)) { - if (torch::nn::Conv2dImpl* M = - dynamic_cast(module.get())) + if (auto M = dynamic_cast(module.get())) torch::nn::init::xavier_normal_(M->weight); // TODO kaiming - else if ( - torch::nn::BatchNormImpl* M = - dynamic_cast(module.get())) { + else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); - } else if ( - torch::nn::LinearImpl* M = - dynamic_cast(module.get())) + } else if (auto M = dynamic_cast(module.get())) torch::nn::init::constant_(M->bias, 0); } } diff --git a/torchvision/csrc/models/densenet.h b/torchvision/csrc/models/densenet.h index 556a4a90bec..b27efc10a07 100644 --- a/torchvision/csrc/models/densenet.h +++ b/torchvision/csrc/models/densenet.h @@ -18,11 +18,10 @@ namespace models { // bn_size (int) - multiplicative factor for number of bottle neck layers // (i.e. bn_size * k features in the bottleneck layer) // drop_rate (float) - dropout rate after each dense layer -class DenseNetImpl : public torch::nn::Module { +struct DenseNetImpl : torch::nn::Module { torch::nn::Sequential features{nullptr}; torch::nn::Linear classifier{nullptr}; - public: DenseNetImpl( int64_t num_classes = 1000, int64_t growth_rate = 32, @@ -34,8 +33,7 @@ class DenseNetImpl : public torch::nn::Module { torch::Tensor forward(torch::Tensor x); }; -class DenseNet121Impl : public DenseNetImpl { - public: +struct DenseNet121Impl : DenseNetImpl { DenseNet121Impl( int64_t num_classes = 1000, int64_t growth_rate = 32, @@ -45,8 +43,7 @@ class DenseNet121Impl : public DenseNetImpl { double drop_rate = 0); }; -class DenseNet169Impl : public DenseNetImpl { - public: +struct DenseNet169Impl : DenseNetImpl { DenseNet169Impl( int64_t num_classes = 1000, int64_t growth_rate = 32, @@ -56,8 +53,7 @@ class DenseNet169Impl : public DenseNetImpl { double drop_rate = 0); }; -class DenseNet201Impl : public DenseNetImpl { - public: +struct DenseNet201Impl : DenseNetImpl { DenseNet201Impl( int64_t num_classes = 1000, int64_t growth_rate = 32, @@ -67,8 +63,7 @@ class DenseNet201Impl : public DenseNetImpl { double drop_rate = 0); }; -class DenseNet161Impl : public DenseNetImpl { - public: +struct DenseNet161Impl : DenseNetImpl { DenseNet161Impl( int64_t num_classes = 1000, int64_t growth_rate = 48, diff --git a/torchvision/csrc/models/inception.h b/torchvision/csrc/models/inception.h index 53ef21c6643..2657fb87435 100644 --- a/torchvision/csrc/models/inception.h +++ b/torchvision/csrc/models/inception.h @@ -6,8 +6,7 @@ namespace vision { namespace models { namespace _inceptionimpl { -class BasicConv2dImpl : public torch::nn::Module { - public: +struct BasicConv2dImpl : torch::nn::Module { torch::nn::Conv2d conv{nullptr}; torch::nn::BatchNorm bn{nullptr}; @@ -18,64 +17,58 @@ class BasicConv2dImpl : public torch::nn::Module { TORCH_MODULE(BasicConv2d); -class InceptionAImpl : public torch::nn::Module { +struct InceptionAImpl : torch::nn::Module { BasicConv2d branch1x1, branch5x5_1, branch5x5_2, branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3, branch_pool; - public: InceptionAImpl(int64_t in_channels, int64_t pool_features); torch::Tensor forward(torch::Tensor x); }; -class InceptionBImpl : public torch::nn::Module { +struct InceptionBImpl : torch::nn::Module { BasicConv2d branch3x3, branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3; - public: InceptionBImpl(int64_t in_channels); torch::Tensor forward(torch::Tensor x); }; -class InceptionCImpl : public torch::nn::Module { +struct InceptionCImpl : torch::nn::Module { BasicConv2d branch1x1{nullptr}, branch7x7_1{nullptr}, branch7x7_2{nullptr}, branch7x7_3{nullptr}, branch7x7dbl_1{nullptr}, branch7x7dbl_2{nullptr}, branch7x7dbl_3{nullptr}, branch7x7dbl_4{nullptr}, branch7x7dbl_5{nullptr}, branch_pool{nullptr}; - public: InceptionCImpl(int64_t in_channels, int64_t channels_7x7); torch::Tensor forward(torch::Tensor x); }; -class InceptionDImpl : public torch::nn::Module { +struct InceptionDImpl : torch::nn::Module { BasicConv2d branch3x3_1, branch3x3_2, branch7x7x3_1, branch7x7x3_2, branch7x7x3_3, branch7x7x3_4; - public: InceptionDImpl(int64_t in_channels); torch::Tensor forward(torch::Tensor x); }; -class InceptionEImpl : public torch::nn::Module { +struct InceptionEImpl : torch::nn::Module { BasicConv2d branch1x1, branch3x3_1, branch3x3_2a, branch3x3_2b, branch3x3dbl_1, branch3x3dbl_2, branch3x3dbl_3a, branch3x3dbl_3b, branch_pool; - public: InceptionEImpl(int64_t in_channels); torch::Tensor forward(torch::Tensor x); }; -class InceptionAuxImpl : public torch::nn::Module { +struct InceptionAuxImpl : torch::nn::Module { BasicConv2d conv0; BasicConv2d conv1; torch::nn::Linear fc; - public: InceptionAuxImpl(int64_t in_channels, int64_t num_classes); torch::Tensor forward(torch::Tensor x); @@ -93,7 +86,7 @@ TORCH_MODULE(InceptionAux); // Inception v3 model architecture from //"Rethinking the Inception Architecture for Computer Vision" // -class InceptionV3Impl : public torch::nn::Module { +struct InceptionV3Impl : torch::nn::Module { bool aux_logits, transform_input; _inceptionimpl::BasicConv2d Conv2d_1a_3x3{nullptr}, Conv2d_2a_3x3{nullptr}, Conv2d_2b_3x3{nullptr}, Conv2d_3b_1x1{nullptr}, Conv2d_4a_3x3{nullptr}; @@ -108,7 +101,6 @@ class InceptionV3Impl : public torch::nn::Module { _inceptionimpl::InceptionAux AuxLogits{nullptr}; - public: InceptionV3Impl( int64_t num_classes = 1000, bool aux_logits = true, diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index c7fdcbc64c0..02209942ab9 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -6,7 +6,7 @@ namespace vision { namespace models { template -class ResNetImpl; +struct ResNetImpl; namespace _resnetimpl { // 3x3 convolution with padding @@ -14,9 +14,9 @@ torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride = 1); // 1x1 convolution torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride = 1); -class BasicBlock : public torch::nn::Module { +struct BasicBlock : torch::nn::Module { template - friend class vision::models::ResNetImpl; + friend struct vision::models::ResNetImpl; int64_t stride; torch::nn::Sequential downsample; @@ -24,7 +24,6 @@ class BasicBlock : public torch::nn::Module { torch::nn::Conv2d conv1, conv2; torch::nn::BatchNorm bn1, bn2; - public: static int expansion; BasicBlock( @@ -36,9 +35,9 @@ class BasicBlock : public torch::nn::Module { torch::Tensor forward(torch::Tensor x); }; -class Bottleneck : public torch::nn::Module { +struct Bottleneck : torch::nn::Module { template - friend class vision::models::ResNetImpl; + friend struct vision::models::ResNetImpl; int64_t stride; torch::nn::Sequential downsample; @@ -46,7 +45,6 @@ class Bottleneck : public torch::nn::Module { torch::nn::Conv2d conv1, conv2, conv3; torch::nn::BatchNorm bn1, bn2, bn3; - public: static int expansion; Bottleneck( @@ -60,7 +58,7 @@ class Bottleneck : public torch::nn::Module { } // namespace _resnetimpl template -class ResNetImpl : public torch::nn::Module { +struct ResNetImpl : torch::nn::Module { int64_t inplanes; torch::nn::Conv2d conv1; torch::nn::BatchNorm bn1; @@ -72,7 +70,6 @@ class ResNetImpl : public torch::nn::Module { int64_t blocks, int64_t stride = 1); - public: ResNetImpl( const std::vector& layers, int64_t num_classes = 1000, @@ -128,12 +125,9 @@ ResNetImpl::ResNetImpl( register_module("layer4", layer4); for (auto& module : modules(false)) { - if (torch::nn::Conv2dImpl* M = - dynamic_cast(module.get())) { + if (auto M = dynamic_cast(module.get())) { torch::nn::init::xavier_normal_(M->weight); // TODO kaiming - } else if ( - torch::nn::BatchNormImpl* M = - dynamic_cast(module.get())) { + } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); } @@ -173,39 +167,28 @@ torch::Tensor ResNetImpl::forward(torch::Tensor x) { return x; } -// ResNet-18 model -class ResNet18Impl : public ResNetImpl<_resnetimpl::BasicBlock> { - public: +struct ResNet18Impl : ResNetImpl<_resnetimpl::BasicBlock> { ResNet18Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; -// ResNet-34 model -class ResNet34Impl : public ResNetImpl<_resnetimpl::BasicBlock> { - public: +struct ResNet34Impl : ResNetImpl<_resnetimpl::BasicBlock> { ResNet34Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; -// ResNet-50 model -class ResNet50Impl : public ResNetImpl<_resnetimpl::Bottleneck> { - public: +struct ResNet50Impl : ResNetImpl<_resnetimpl::Bottleneck> { ResNet50Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; -// ResNet-101 model -class ResNet101Impl : public ResNetImpl<_resnetimpl::Bottleneck> { - public: +struct ResNet101Impl : ResNetImpl<_resnetimpl::Bottleneck> { ResNet101Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; -// ResNet-152 model -class ResNet152Impl : public ResNetImpl<_resnetimpl::Bottleneck> { - public: +struct ResNet152Impl : ResNetImpl<_resnetimpl::Bottleneck> { ResNet152Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; template -class ResNet : public torch::nn::ModuleHolder> { - public: +struct ResNet : torch::nn::ModuleHolder> { using torch::nn::ModuleHolder>::ModuleHolder; }; diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index 3bf1d6dd2a4..ff00de75431 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -5,10 +5,9 @@ namespace vision { namespace models { -class Fire : public torch::nn::Module { +struct Fire : torch::nn::Module { torch::nn::Conv2d squeeze, expand1x1, expand3x3; - public: Fire( int64_t inplanes, int64_t squeeze_planes, @@ -40,39 +39,41 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) }; if (double_compare(version, 1.0)) { - // clang-format off - features = torch::nn::Sequential( - torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), - Fire(96, 16, 64, 64), - Fire(128, 16, 64, 64), - Fire(128, 32, 128, 128), - modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), - Fire(256, 32, 128, 128), - Fire(256, 48, 192, 192), - Fire(384, 48, 192, 192), - Fire(384, 64, 256, 256), - modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), - Fire(512, 64, 256, 256)); - // clang-format on + features = torch::nn::Sequential( + torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D( + modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + Fire(96, 16, 64, 64), + Fire(128, 16, 64, 64), + Fire(128, 32, 128, 128), + modelsimpl::MaxPool2D( + modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + Fire(256, 32, 128, 128), + Fire(256, 48, 192, 192), + Fire(384, 48, 192, 192), + Fire(384, 64, 256, 256), + modelsimpl::MaxPool2D( + modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + Fire(512, 64, 256, 256)); } else if (double_compare(version, 1.1)) { - // clang-format off - features = torch::nn::Sequential( - torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), - Fire(64, 16, 64, 64), - Fire(128, 16, 64, 64), - modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), - Fire(128, 32, 128, 128), - Fire(256, 32, 128, 128), - modelsimpl::MaxPool2D(modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), - Fire(256, 48, 192, 192), - Fire(384, 48, 192, 192), - Fire(384, 64, 256, 256), - Fire(512, 64, 256, 256)); - // clang-format on + features = torch::nn::Sequential( + torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), + modelsimpl::Relu(true), + modelsimpl::MaxPool2D( + modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + Fire(64, 16, 64, 64), + Fire(128, 16, 64, 64), + modelsimpl::MaxPool2D( + modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + Fire(128, 32, 128, 128), + Fire(256, 32, 128, 128), + modelsimpl::MaxPool2D( + modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + Fire(256, 48, 192, 192), + Fire(384, 48, 192, 192), + Fire(384, 64, 256, 256), + Fire(512, 64, 256, 256)); } else { std::cerr << "Wrong version number is passed th SqueeseNet constructor!" << std::endl; @@ -83,20 +84,17 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) auto final_conv = torch::nn::Conv2d(torch::nn::Conv2dOptions(512, num_classes, 1)); - // clang-format off - classifier = torch::nn::Sequential( - torch::nn::Dropout(0.5), - final_conv, - modelsimpl::Relu(true), - modelsimpl::AdaptiveAvgPool2D(1)); - // clang-format on + classifier = torch::nn::Sequential( + torch::nn::Dropout(0.5), + final_conv, + modelsimpl::Relu(true), + modelsimpl::AdaptiveAvgPool2D(1)); register_module("features", features); register_module("classifier", classifier); for (auto& module : modules(false)) - if (torch::nn::Conv2dImpl* M = - dynamic_cast(module.get())) { + if (auto M = dynamic_cast(module.get())) { if (M == final_conv.get()) torch::nn::init::normal_(M->weight, 0.0, 0.01); else diff --git a/torchvision/csrc/models/squeezenet.h b/torchvision/csrc/models/squeezenet.h index 23ff58ef20a..ee3350b4bf3 100644 --- a/torchvision/csrc/models/squeezenet.h +++ b/torchvision/csrc/models/squeezenet.h @@ -5,11 +5,10 @@ namespace vision { namespace models { -class SqueezeNetImpl : public torch::nn::Module { +struct SqueezeNetImpl : torch::nn::Module { int64_t num_classes; torch::nn::Sequential features{nullptr}, classifier{nullptr}; - public: SqueezeNetImpl(double version = 1.0, int64_t num_classes = 1000); torch::Tensor forward(torch::Tensor x); @@ -18,8 +17,7 @@ class SqueezeNetImpl : public torch::nn::Module { // SqueezeNet model architecture from the "SqueezeNet: AlexNet-level // accuracy with 50x fewer parameters and <0.5MB model size" // paper. -class SqueezeNet1_0Impl : public SqueezeNetImpl { - public: +struct SqueezeNet1_0Impl : SqueezeNetImpl { SqueezeNet1_0Impl(int64_t num_classes = 1000); }; @@ -27,8 +25,7 @@ class SqueezeNet1_0Impl : public SqueezeNetImpl { // . // SqueezeNet 1.1 has 2.4x less computation and slightly fewer parameters // than SqueezeNet 1.0, without sacrificing accuracy. -class SqueezeNet1_1Impl : public SqueezeNetImpl { - public: +struct SqueezeNet1_1Impl : SqueezeNetImpl { SqueezeNet1_1Impl(int64_t num_classes = 1000); }; diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index f64a2d517dd..042a2d8f7ec 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -1,6 +1,6 @@ #include "vgg.h" -#include +#include #include "modelsimpl.h" namespace vision { @@ -31,18 +31,13 @@ torch::nn::Sequential makeLayers( void VGGImpl::_initialize_weights() { for (auto& module : modules(false)) { - if (torch::nn::Conv2dImpl* M = - dynamic_cast(module.get())) { + if (auto M = dynamic_cast(module.get())) { torch::nn::init::xavier_normal_(M->weight); // TODO kaiming torch::nn::init::constant_(M->bias, 0); - } else if ( - torch::nn::BatchNormImpl* M = - dynamic_cast(module.get())) { + } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); - } else if ( - torch::nn::LinearImpl* M = - dynamic_cast(module.get())) { + } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::normal_(M->weight, 0, 0.01); torch::nn::init::constant_(M->bias, 0); } @@ -53,16 +48,14 @@ VGGImpl::VGGImpl( torch::nn::Sequential features, int64_t num_classes, bool initialize_weights) { - // clang-format off - classifier = torch::nn::Sequential( - torch::nn::Linear(512 * 7 * 7, 4096), - modelsimpl::Relu(true), - torch::nn::Dropout(), - torch::nn::Linear(4096, 4096), - modelsimpl::Relu(true), - torch::nn::Dropout(), - torch::nn::Linear(4096, num_classes)); - // clang-format on + classifier = torch::nn::Sequential( + torch::nn::Linear(512 * 7 * 7, 4096), + modelsimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, 4096), + modelsimpl::Relu(true), + torch::nn::Dropout(), + torch::nn::Linear(4096, num_classes)); this->features = features; @@ -81,36 +74,36 @@ torch::Tensor VGGImpl::forward(torch::Tensor x) { } // clang-format off -static std::map> cfg = { - {'A', {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}}, - {'B', {64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}}, - {'D', {64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}}, - {'E', {64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}}}; +static std::unordered_map> cfg = { + {'A', {64, -1, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}}, + {'B', {64, 64, -1, 128, 128, -1, 256, 256, -1, 512, 512, -1, 512, 512, -1}}, + {'D', {64, 64, -1, 128, 128, -1, 256, 256, 256, -1, 512, 512, 512, -1, 512, 512, 512, -1}}, + {'E', {64, 64, -1, 128, 128, -1, 256, 256, 256, 256, -1, 512, 512, 512, 512, -1, 512, 512, 512, 512, -1}}}; // clang-format on VGG11Impl::VGG11Impl(int64_t num_classes, bool initialize_weights) : VGGImpl(makeLayers(cfg['A']), num_classes, initialize_weights) {} -VGG13Impl::VGG13Impl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['B']), num_classes, initWeights) {} +VGG13Impl::VGG13Impl(int64_t num_classes, bool initialize_weights) + : VGGImpl(makeLayers(cfg['B']), num_classes, initialize_weights) {} -VGG16Impl::VGG16Impl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['D']), num_classes, initWeights) {} +VGG16Impl::VGG16Impl(int64_t num_classes, bool initialize_weights) + : VGGImpl(makeLayers(cfg['D']), num_classes, initialize_weights) {} VGG19Impl::VGG19Impl(int64_t num_classes, bool initialize_weights) : VGGImpl(makeLayers(cfg['E']), num_classes, initialize_weights) {} -VGG11BNImpl::VGG11BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['A'], true), num_classes, initWeights) {} +VGG11BNImpl::VGG11BNImpl(int64_t num_classes, bool initialize_weights) + : VGGImpl(makeLayers(cfg['A'], true), num_classes, initialize_weights) {} VGG13BNImpl::VGG13BNImpl(int64_t num_classes, bool initialize_weights) : VGGImpl(makeLayers(cfg['B'], true), num_classes, initialize_weights) {} -VGG16BNImpl::VGG16BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['D'], true), num_classes, initWeights) {} +VGG16BNImpl::VGG16BNImpl(int64_t num_classes, bool initialize_weights) + : VGGImpl(makeLayers(cfg['D'], true), num_classes, initialize_weights) {} -VGG19BNImpl::VGG19BNImpl(int64_t num_classes, bool initWeights) - : VGGImpl(makeLayers(cfg['E'], true), num_classes, initWeights) {} +VGG19BNImpl::VGG19BNImpl(int64_t num_classes, bool initialize_weights) + : VGGImpl(makeLayers(cfg['E'], true), num_classes, initialize_weights) {} } // namespace models } // namespace vision diff --git a/torchvision/csrc/models/vgg.h b/torchvision/csrc/models/vgg.h index 0a65ad06153..04f77007817 100644 --- a/torchvision/csrc/models/vgg.h +++ b/torchvision/csrc/models/vgg.h @@ -5,12 +5,11 @@ namespace vision { namespace models { -class VGGImpl : public torch::nn::Module { +struct VGGImpl : torch::nn::Module { torch::nn::Sequential features{nullptr}, classifier{nullptr}; void _initialize_weights(); - public: VGGImpl( torch::nn::Sequential features, int64_t num_classes = 1000, @@ -20,50 +19,42 @@ class VGGImpl : public torch::nn::Module { }; // VGG 11-layer model (configuration "A") -class VGG11Impl : public VGGImpl { - public: +struct VGG11Impl : VGGImpl { VGG11Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 13-layer model (configuration "B") -class VGG13Impl : public VGGImpl { - public: +struct VGG13Impl : VGGImpl { VGG13Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 16-layer model (configuration "D") -class VGG16Impl : public VGGImpl { - public: +struct VGG16Impl : VGGImpl { VGG16Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 19-layer model (configuration "E") -class VGG19Impl : public VGGImpl { - public: +struct VGG19Impl : VGGImpl { VGG19Impl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 11-layer model (configuration "A") with batch normalization -class VGG11BNImpl : public VGGImpl { - public: +struct VGG11BNImpl : VGGImpl { VGG11BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 13-layer model (configuration "B") with batch normalization -class VGG13BNImpl : public VGGImpl { - public: +struct VGG13BNImpl : VGGImpl { VGG13BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 16-layer model (configuration "D") with batch normalization -class VGG16BNImpl : public VGGImpl { - public: +struct VGG16BNImpl : VGGImpl { VGG16BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; // VGG 19-layer model (configuration 'E') with batch normalization -class VGG19BNImpl : public VGGImpl { - public: +struct VGG19BNImpl : VGGImpl { VGG19BNImpl(int64_t num_classes = 1000, bool initialize_weights = true); }; From 91501b0dc58661bfb83bee79d5b55e1278bfcd21 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Thu, 14 Feb 2019 18:10:22 +0330 Subject: [PATCH 14/48] Replaced modelsimpl structs with functional wherever possible --- CMakeLists.txt | 1 - CMakeLists.txt.user | 375 ------------------------- torchvision/csrc/models/alexnet.cpp | 20 +- torchvision/csrc/models/densenet.cpp | 13 +- torchvision/csrc/models/modelsimpl.cpp | 36 --- torchvision/csrc/models/modelsimpl.h | 49 +--- torchvision/csrc/models/resnet.cpp | 2 - torchvision/csrc/models/squeezenet.cpp | 24 +- torchvision/csrc/models/vgg.cpp | 9 +- 9 files changed, 35 insertions(+), 494 deletions(-) delete mode 100644 CMakeLists.txt.user diff --git a/CMakeLists.txt b/CMakeLists.txt index ae34ab590af..7e0eb7d1978 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,6 @@ file(GLOB_RECURSE MODELS_HEADERS torchvision/csrc/models/*.h) file(GLOB_RECURSE MODELS_SOURCES torchvision/csrc/models/*.h torchvision/csrc/models/*.cpp) add_library (${PROJECT_NAME} SHARED ${MODELS_SOURCES}) -set(CUDNN_INCLUDE_DIR /usr/include/cuda) find_package(Torch REQUIRED) target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}") diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user deleted file mode 100644 index 6a9def38841..00000000000 --- a/CMakeLists.txt.user +++ /dev/null @@ -1,375 +0,0 @@ - - - - - - EnvironmentId - {9126aafa-d39a-4626-9808-b244ffd2484f} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 80 - true - true - 1 - true - false - 0 - true - true - 0 - 8 - true - 1 - true - true - true - false - - - - ProjectExplorer.Project.PluginSettings - - - true - - - - ProjectExplorer.Project.Target.0 - - Desktop Qt 5.12.0 GCC 64bit - Desktop Qt 5.12.0 GCC 64bit - qt.qt5.5120.gcc_64_kit - 0 - 0 - 0 - - - /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Default - - - - - all - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Build - - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Default - Default - CMakeProjectManager.CMakeBuildConfiguration - - - - CMAKE_BUILD_TYPE:STRING=Debug - - /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Debug - - - - - all - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Build - - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Debug - Debug - CMakeProjectManager.CMakeBuildConfiguration - - - - CMAKE_BUILD_TYPE:STRING=Release - - /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Release - - - - - all - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Build - - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Release - Release - CMakeProjectManager.CMakeBuildConfiguration - - - - CMAKE_BUILD_TYPE:STRING=RelWithDebInfo - - /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Release with Debug Information - - - - - all - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Build - - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Release with Debug Information - Release with Debug Information - CMakeProjectManager.CMakeBuildConfiguration - - - - CMAKE_BUILD_TYPE:STRING=MinSizeRel - - /home/shahriar/build-vision-Desktop_Qt_5_12_0_GCC_64bit-Minimum Size Release - - - - - all - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Build - - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMake Build - - CMakeProjectManager.MakeStep - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Minimum Size Release - Minimum Size Release - CMakeProjectManager.CMakeBuildConfiguration - - 5 - - - 0 - Deploy - - ProjectExplorer.BuildSteps.Deploy - - 1 - Deploy Configuration - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - false - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - - Custom Executable - - ProjectExplorer.CustomExecutableRunConfiguration - - 3768 - false - true - false - false - true - - - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 20 - - - Version - 20 - - diff --git a/torchvision/csrc/models/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp index 85e5d26d9bd..8c2508308b4 100644 --- a/torchvision/csrc/models/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -8,26 +8,26 @@ AlexNetImpl::AlexNetImpl(int64_t num_classes) { features = torch::nn::Sequential( torch::nn::Conv2d( torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), - torch::nn::Functional(torch::relu), - modelsimpl::MaxPool2D(3, 2), + torch::nn::Functional(modelsimpl::relu_), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, false), torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 192, 5).padding(2)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D(3, 2), + torch::nn::Functional(modelsimpl::relu_), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, false), torch::nn::Conv2d(torch::nn::Conv2dOptions(192, 384, 3).padding(1)), - modelsimpl::Relu(true), + torch::nn::Functional(modelsimpl::relu_), torch::nn::Conv2d(torch::nn::Conv2dOptions(384, 256, 3).padding(1)), - modelsimpl::Relu(true), + torch::nn::Functional(modelsimpl::relu_), torch::nn::Conv2d(torch::nn::Conv2dOptions(256, 256, 3).padding(1)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D(3, 2)); + torch::nn::Functional(modelsimpl::relu_), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, false)); classifier = torch::nn::Sequential( torch::nn::Dropout(), torch::nn::Linear(256 * 6 * 6, 4096), - modelsimpl::Relu(true), + torch::nn::Functional(torch::relu), torch::nn::Dropout(), torch::nn::Linear(4096, 4096), - modelsimpl::Relu(true), + torch::nn::Functional(torch::relu), torch::nn::Linear(4096, num_classes)); register_module("features", features); diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index c518b48eb9b..5babcd1a722 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -16,13 +16,13 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { double drop_rate) : drop_rate(drop_rate) { push_back(torch::nn::BatchNorm(num_input_features)); - push_back(modelsimpl::Relu(true)); + push_back(torch::nn::Functional(modelsimpl::relu_)); push_back( torch::nn::Conv2d(Options(num_input_features, bn_size * growth_rate, 1) .stride(1) .with_bias(false))); push_back(torch::nn::BatchNorm(bn_size * growth_rate)); - push_back(modelsimpl::Relu(true)); + push_back(torch::nn::Functional(modelsimpl::relu_)); push_back(torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) .stride(1) .padding(1) @@ -67,12 +67,12 @@ TORCH_MODULE(_DenseBlock); struct _TransitionImpl : torch::nn::SequentialImpl { _TransitionImpl(int64_t num_input_features, int64_t num_output_features) { push_back(torch::nn::BatchNorm(num_input_features)); - push_back(modelsimpl::Relu(true)); + push_back(torch::nn::Functional(modelsimpl::relu_)); push_back( torch::nn::Conv2d(Options(num_input_features, num_output_features, 1) .stride(1) .with_bias(false))); - push_back(modelsimpl::AvgPool2D(2, 2)); + push_back(torch::nn::Functional(torch::avg_pool2d, 2, 2, 0, false, true)); } torch::Tensor forward(torch::Tensor x) { @@ -96,9 +96,8 @@ DenseNetImpl::DenseNetImpl( .padding(3) .with_bias(false)), torch::nn::BatchNorm(num_init_features), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D( - modelsimpl::MaxPool2DOptions(3).stride(2).padding(1))); + torch::nn::Functional(modelsimpl::relu_), + torch::nn::Functional(torch::max_pool2d, 3, 2, 1, 1, false)); // Each denseblock auto num_features = num_init_features; diff --git a/torchvision/csrc/models/modelsimpl.cpp b/torchvision/csrc/models/modelsimpl.cpp index 32e2f610b68..832934087b6 100644 --- a/torchvision/csrc/models/modelsimpl.cpp +++ b/torchvision/csrc/models/modelsimpl.cpp @@ -3,33 +3,6 @@ namespace vision { namespace models { namespace modelsimpl { -ReluImpl::ReluImpl(bool inplace) : inplace(inplace) {} - -torch::Tensor ReluImpl::forward(torch::Tensor X) { - if (inplace) { - X.relu_(); - return X; - } - - return torch::relu(X); -} - -MaxPool2DImpl::MaxPool2DImpl( - torch::ExpandingArray<2> kernel, - torch::ExpandingArray<2> stride) - : options(MaxPool2DOptions(kernel).stride(stride)) {} - -MaxPool2DImpl::MaxPool2DImpl(MaxPool2DOptions options) : options(options) {} - -torch::Tensor MaxPool2DImpl::forward(torch::Tensor X) { - return torch::max_pool2d( - X, - options.kernel_size(), - options.stride(), - options.padding(), - options.dilation(), - options.ceil_mode()); -} AdaptiveAvgPool2DImpl::AdaptiveAvgPool2DImpl( torch::ExpandingArray<2> output_size) @@ -39,15 +12,6 @@ torch::Tensor AdaptiveAvgPool2DImpl::forward(torch::Tensor x) { return torch::adaptive_avg_pool2d(x, output_size); } -AvgPool2DImpl::AvgPool2DImpl( - torch::ExpandingArray<2> kernel_size, - torch::ExpandingArray<2> stride) - : kernel_size(kernel_size), stride(stride) {} - -torch::Tensor AvgPool2DImpl::forward(torch::Tensor x) { - return torch::avg_pool2d(x, kernel_size, stride); -} - } // namespace modelsimpl } // namespace models } // namespace vision diff --git a/torchvision/csrc/models/modelsimpl.h b/torchvision/csrc/models/modelsimpl.h index 4d703bd2f36..7573c7ef583 100644 --- a/torchvision/csrc/models/modelsimpl.h +++ b/torchvision/csrc/models/modelsimpl.h @@ -6,38 +6,13 @@ namespace vision { namespace models { namespace modelsimpl { -class ReluImpl : public torch::nn::Module { - bool inplace; - public: - ReluImpl(bool inplace = false); - - torch::Tensor forward(torch::Tensor X); -}; - -struct MaxPool2DOptions { - MaxPool2DOptions(torch::ExpandingArray<2> kernel_size) - : kernel_size_(kernel_size), stride_(kernel_size) {} - - TORCH_ARG(torch::ExpandingArray<2>, kernel_size); - TORCH_ARG(torch::ExpandingArray<2>, stride); - TORCH_ARG(torch::ExpandingArray<2>, padding) = 0; - TORCH_ARG(torch::ExpandingArray<2>, dilation) = 1; - TORCH_ARG(bool, ceil_mode) = false; -}; - -class MaxPool2DImpl : public torch::nn::Module { - MaxPool2DOptions options; - - public: - MaxPool2DImpl( - torch::ExpandingArray<2> kernel, - torch::ExpandingArray<2> stride); +// TODO here torch::relu_ and torch::adaptive_avg_pool2d wrapped in +// torch::nn::Fuctional don't work. so keeping these for now - explicit MaxPool2DImpl(MaxPool2DOptions options); - - torch::Tensor forward(torch::Tensor X); -}; +inline torch::Tensor relu_(torch::Tensor x) { + return torch::relu_(x); +} class AdaptiveAvgPool2DImpl : public torch::nn::Module { torch::ExpandingArray<2> output_size; @@ -48,20 +23,6 @@ class AdaptiveAvgPool2DImpl : public torch::nn::Module { torch::Tensor forward(torch::Tensor x); }; -class AvgPool2DImpl : public torch::nn::Module { - torch::ExpandingArray<2> kernel_size, stride; - - public: - AvgPool2DImpl( - torch::ExpandingArray<2> kernel_size, - torch::ExpandingArray<2> stride); - - torch::Tensor forward(torch::Tensor x); -}; - -TORCH_MODULE(Relu); -TORCH_MODULE(MaxPool2D); -TORCH_MODULE(AvgPool2D); TORCH_MODULE(AdaptiveAvgPool2D); } // namespace modelsimpl diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index 7eaaaebab40..ea94e3253eb 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -1,7 +1,5 @@ #include "resnet.h" -#include "modelsimpl.h" - namespace vision { namespace models { namespace _resnetimpl { diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index ff00de75431..6611f29b418 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -41,35 +41,29 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) if (double_compare(version, 1.0)) { features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D( - modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + torch::nn::Functional(modelsimpl::relu_), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, true), Fire(96, 16, 64, 64), Fire(128, 16, 64, 64), Fire(128, 32, 128, 128), - modelsimpl::MaxPool2D( - modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, true), Fire(256, 32, 128, 128), Fire(256, 48, 192, 192), Fire(384, 48, 192, 192), Fire(384, 64, 256, 256), - modelsimpl::MaxPool2D( - modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, true), Fire(512, 64, 256, 256)); } else if (double_compare(version, 1.1)) { features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), - modelsimpl::Relu(true), - modelsimpl::MaxPool2D( - modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + torch::nn::Functional(modelsimpl::relu_), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, true), Fire(64, 16, 64, 64), Fire(128, 16, 64, 64), - modelsimpl::MaxPool2D( - modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, true), Fire(128, 32, 128, 128), Fire(256, 32, 128, 128), - modelsimpl::MaxPool2D( - modelsimpl::MaxPool2DOptions(3).stride(2).ceil_mode(true)), + torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, true), Fire(256, 48, 192, 192), Fire(384, 48, 192, 192), Fire(384, 64, 256, 256), @@ -87,7 +81,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) classifier = torch::nn::Sequential( torch::nn::Dropout(0.5), final_conv, - modelsimpl::Relu(true), + torch::nn::Functional(modelsimpl::relu_), modelsimpl::AdaptiveAvgPool2D(1)); register_module("features", features); diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index 042a2d8f7ec..f4802f647df 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -13,14 +13,15 @@ torch::nn::Sequential makeLayers( for (const auto& V : cfg) { if (V <= -1) - seq->push_back(modelsimpl::MaxPool2D(2, 2)); + seq->push_back( + torch::nn::Functional(torch::max_pool2d, 2, 2, 0, 1, false)); else { seq->push_back(torch::nn::Conv2d( torch::nn::Conv2dOptions(channels, V, 3).padding(1))); if (batch_norm) seq->push_back(torch::nn::BatchNorm(V)); - seq->push_back(modelsimpl::Relu(true)); + seq->push_back(torch::nn::Functional(modelsimpl::relu_)); channels = V; } @@ -50,10 +51,10 @@ VGGImpl::VGGImpl( bool initialize_weights) { classifier = torch::nn::Sequential( torch::nn::Linear(512 * 7 * 7, 4096), - modelsimpl::Relu(true), + torch::nn::Functional(modelsimpl::relu_), torch::nn::Dropout(), torch::nn::Linear(4096, 4096), - modelsimpl::Relu(true), + torch::nn::Functional(modelsimpl::relu_), torch::nn::Dropout(), torch::nn::Linear(4096, num_classes)); From 33f045d97e448ab17ef9323883b09907a1457032 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Thu, 14 Feb 2019 18:19:47 +0330 Subject: [PATCH 15/48] Changed adaptive average pool from struct to function --- torchvision/csrc/models/modelsimpl.cpp | 17 ----------------- torchvision/csrc/models/modelsimpl.h | 17 ++++++----------- torchvision/csrc/models/squeezenet.cpp | 2 +- 3 files changed, 7 insertions(+), 29 deletions(-) delete mode 100644 torchvision/csrc/models/modelsimpl.cpp diff --git a/torchvision/csrc/models/modelsimpl.cpp b/torchvision/csrc/models/modelsimpl.cpp deleted file mode 100644 index 832934087b6..00000000000 --- a/torchvision/csrc/models/modelsimpl.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "modelsimpl.h" - -namespace vision { -namespace models { -namespace modelsimpl { - -AdaptiveAvgPool2DImpl::AdaptiveAvgPool2DImpl( - torch::ExpandingArray<2> output_size) - : output_size(output_size) {} - -torch::Tensor AdaptiveAvgPool2DImpl::forward(torch::Tensor x) { - return torch::adaptive_avg_pool2d(x, output_size); -} - -} // namespace modelsimpl -} // namespace models -} // namespace vision diff --git a/torchvision/csrc/models/modelsimpl.h b/torchvision/csrc/models/modelsimpl.h index 7573c7ef583..6b14a1b026a 100644 --- a/torchvision/csrc/models/modelsimpl.h +++ b/torchvision/csrc/models/modelsimpl.h @@ -10,20 +10,15 @@ namespace modelsimpl { // TODO here torch::relu_ and torch::adaptive_avg_pool2d wrapped in // torch::nn::Fuctional don't work. so keeping these for now -inline torch::Tensor relu_(torch::Tensor x) { +inline torch::Tensor& relu_(torch::Tensor x) { return torch::relu_(x); } -class AdaptiveAvgPool2DImpl : public torch::nn::Module { - torch::ExpandingArray<2> output_size; - - public: - AdaptiveAvgPool2DImpl(torch::ExpandingArray<2> output_size); - - torch::Tensor forward(torch::Tensor x); -}; - -TORCH_MODULE(AdaptiveAvgPool2D); +inline torch::Tensor adaptive_avg_pool2d( + torch::Tensor x, + torch::ExpandingArray<2> output_size) { + return torch::adaptive_avg_pool2d(x, output_size); +} } // namespace modelsimpl } // namespace models diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index 6611f29b418..4e93fef8ba8 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -82,7 +82,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) torch::nn::Dropout(0.5), final_conv, torch::nn::Functional(modelsimpl::relu_), - modelsimpl::AdaptiveAvgPool2D(1)); + torch::nn::Functional(modelsimpl::adaptive_avg_pool2d, 1)); register_module("features", features); register_module("classifier", classifier); From 031deedbeb9c07f8a346d765a6a79cbdb9d5e831 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Fri, 15 Feb 2019 01:11:45 +0330 Subject: [PATCH 16/48] Wrote a max_pool2d wrapper and added some comments --- torchvision/csrc/models/alexnet.cpp | 6 +++--- torchvision/csrc/models/densenet.cpp | 2 +- torchvision/csrc/models/modelsimpl.h | 7 +++++++ torchvision/csrc/models/resnet.h | 4 ++-- torchvision/csrc/models/squeezenet.cpp | 2 +- torchvision/csrc/models/vgg.cpp | 5 ++--- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/torchvision/csrc/models/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp index 8c2508308b4..bb1934ae605 100644 --- a/torchvision/csrc/models/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -9,17 +9,17 @@ AlexNetImpl::AlexNetImpl(int64_t num_classes) { torch::nn::Conv2d( torch::nn::Conv2dOptions(3, 64, 11).stride(4).padding(2)), torch::nn::Functional(modelsimpl::relu_), - torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, false), + torch::nn::Functional(modelsimpl::max_pool2d, 3, 2), torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 192, 5).padding(2)), torch::nn::Functional(modelsimpl::relu_), - torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, false), + torch::nn::Functional(modelsimpl::max_pool2d, 3, 2), torch::nn::Conv2d(torch::nn::Conv2dOptions(192, 384, 3).padding(1)), torch::nn::Functional(modelsimpl::relu_), torch::nn::Conv2d(torch::nn::Conv2dOptions(384, 256, 3).padding(1)), torch::nn::Functional(modelsimpl::relu_), torch::nn::Conv2d(torch::nn::Conv2dOptions(256, 256, 3).padding(1)), torch::nn::Functional(modelsimpl::relu_), - torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, false)); + torch::nn::Functional(modelsimpl::max_pool2d, 3, 2)); classifier = torch::nn::Sequential( torch::nn::Dropout(), diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index 5babcd1a722..d202ce1f876 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -125,7 +125,7 @@ DenseNetImpl::DenseNetImpl( register_module("classifier", classifier); // Official init from torch repo. - for (auto& module : modules(false)) { + for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) torch::nn::init::xavier_normal_(M->weight); // TODO kaiming else if (auto M = dynamic_cast(module.get())) { diff --git a/torchvision/csrc/models/modelsimpl.h b/torchvision/csrc/models/modelsimpl.h index 6b14a1b026a..ce2e7d9d059 100644 --- a/torchvision/csrc/models/modelsimpl.h +++ b/torchvision/csrc/models/modelsimpl.h @@ -20,6 +20,13 @@ inline torch::Tensor adaptive_avg_pool2d( return torch::adaptive_avg_pool2d(x, output_size); } +inline torch::Tensor max_pool2d( + torch::Tensor x, + torch::ExpandingArray<2> kernel_size, + torch::ExpandingArray<2> stride) { + return torch::max_pool2d(x, kernel_size, stride); +} + } // namespace modelsimpl } // namespace models } // namespace vision diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 02209942ab9..783552e5e71 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -124,7 +124,7 @@ ResNetImpl::ResNetImpl( register_module("layer3", layer3); register_module("layer4", layer4); - for (auto& module : modules(false)) { + for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) { torch::nn::init::xavier_normal_(M->weight); // TODO kaiming } else if (auto M = dynamic_cast(module.get())) { @@ -138,7 +138,7 @@ ResNetImpl::ResNetImpl( // identity. This improves the model by 0.2~0.3% according to // https://arxiv.org/abs/1706.02677 if (zero_init_residual) - for (auto& module : modules(false)) { + for (auto& module : modules(/*include_self=*/false)) { if (_resnetimpl::Bottleneck* M = dynamic_cast<_resnetimpl::Bottleneck*>(module.get())) torch::nn::init::constant_(M->bn3->weight, 0); diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index 4e93fef8ba8..ede01b3687c 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -87,7 +87,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) register_module("features", features); register_module("classifier", classifier); - for (auto& module : modules(false)) + for (auto& module : modules(/*include_self=*/false)) if (auto M = dynamic_cast(module.get())) { if (M == final_conv.get()) torch::nn::init::normal_(M->weight, 0.0, 0.01); diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index f4802f647df..c598e6da3c1 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -13,8 +13,7 @@ torch::nn::Sequential makeLayers( for (const auto& V : cfg) { if (V <= -1) - seq->push_back( - torch::nn::Functional(torch::max_pool2d, 2, 2, 0, 1, false)); + seq->push_back(torch::nn::Functional(modelsimpl::max_pool2d, 2, 2)); else { seq->push_back(torch::nn::Conv2d( torch::nn::Conv2dOptions(channels, V, 3).padding(1))); @@ -31,7 +30,7 @@ torch::nn::Sequential makeLayers( } void VGGImpl::_initialize_weights() { - for (auto& module : modules(false)) { + for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) { torch::nn::init::xavier_normal_(M->weight); // TODO kaiming torch::nn::init::constant_(M->bias, 0); From a46df6c74cff31c6488853c8b24fde63919638c2 Mon Sep 17 00:00:00 2001 From: Shahriar Date: Sun, 17 Feb 2019 00:51:11 +0330 Subject: [PATCH 17/48] Replaced xavier init with kaiming init --- torchvision/csrc/models/densenet.cpp | 2 +- torchvision/csrc/models/resnet.h | 2 +- torchvision/csrc/models/squeezenet.cpp | 2 +- torchvision/csrc/models/vgg.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index d202ce1f876..f126581c09f 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -127,7 +127,7 @@ DenseNetImpl::DenseNetImpl( // Official init from torch repo. for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) - torch::nn::init::xavier_normal_(M->weight); // TODO kaiming + torch::nn::init::kaiming_normal_(M->weight); else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 783552e5e71..04171ffe96b 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -126,7 +126,7 @@ ResNetImpl::ResNetImpl( for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) { - torch::nn::init::xavier_normal_(M->weight); // TODO kaiming + torch::nn::init::kaiming_normal_(M->weight); } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index ede01b3687c..4e662dda2f1 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -92,7 +92,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) if (M == final_conv.get()) torch::nn::init::normal_(M->weight, 0.0, 0.01); else - torch::nn::init::xavier_uniform_(M->weight); // TODO kaiming + torch::nn::init::kaiming_uniform_(M->weight); if (M->options.with_bias()) torch::nn::init::constant_(M->bias, 0); diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index c598e6da3c1..1a75124c3e8 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -32,7 +32,7 @@ torch::nn::Sequential makeLayers( void VGGImpl::_initialize_weights() { for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) { - torch::nn::init::xavier_normal_(M->weight); // TODO kaiming + torch::nn::init::kaiming_normal_(M->weight); torch::nn::init::constant_(M->bias, 0); } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); From 03a3863d2a638ede3cf2edfe2d8bb63c53e0ab17 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Tue, 19 Feb 2019 18:04:14 +0330 Subject: [PATCH 18/48] Fixed an error in kaiming inits --- torchvision/csrc/models/resnet.h | 10 +++++++--- torchvision/csrc/models/vgg.cpp | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 04171ffe96b..d06e18c7110 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -125,9 +125,13 @@ ResNetImpl::ResNetImpl( register_module("layer4", layer4); for (auto& module : modules(/*include_self=*/false)) { - if (auto M = dynamic_cast(module.get())) { - torch::nn::init::kaiming_normal_(M->weight); - } else if (auto M = dynamic_cast(module.get())) { + if (auto M = dynamic_cast(module.get())) + torch::nn::init::kaiming_normal_( + M->weight, + /*a=*/0, + torch::nn::init::FanMode::FanOut, + torch::nn::init::Nonlinearity::ReLU); + else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); } diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index 1a75124c3e8..f392dbb62ca 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -32,7 +32,11 @@ torch::nn::Sequential makeLayers( void VGGImpl::_initialize_weights() { for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) { - torch::nn::init::kaiming_normal_(M->weight); + torch::nn::init::kaiming_normal_( + M->weight, + /*a=*/0, + torch::nn::init::FanMode::FanOut, + torch::nn::init::Nonlinearity::ReLU); torch::nn::init::constant_(M->bias, 0); } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); From d0e119ee3087ac4a6bcabde6b95930fcaeedc8dc Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Thu, 28 Mar 2019 12:40:04 +0430 Subject: [PATCH 19/48] Added model conversion and tests --- CMakeLists.txt | 14 ++- test/test_models.cpp | 109 ++++++++++++++++++ .../csrc/convert_models/convert_models.cpp | 59 ++++++++++ 3 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 test/test_models.cpp create mode 100644 torchvision/csrc/convert_models/convert_models.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e0eb7d1978..caa2831b822 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,14 +2,24 @@ cmake_minimum_required(VERSION 2.8) project(torchvision) set(CMAKE_CXX_STANDARD 11) +find_package(Torch REQUIRED) + file(GLOB_RECURSE HEADERS torchvision/csrc/vision.h) file(GLOB_RECURSE MODELS_HEADERS torchvision/csrc/models/*.h) file(GLOB_RECURSE MODELS_SOURCES torchvision/csrc/models/*.h torchvision/csrc/models/*.cpp) -add_library (${PROJECT_NAME} SHARED ${MODELS_SOURCES}) -find_package(Torch REQUIRED) +add_library (${PROJECT_NAME} SHARED ${MODELS_SOURCES}) target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}") +add_executable(convertmodels torchvision/csrc/convert_models/convert_models.cpp) +target_link_libraries(convertmodels "${PROJECT_NAME}") +target_link_libraries(convertmodels "${TORCH_LIBRARIES}") + +find_package(pybind11 REQUIRED) +add_executable(testmodels test/test_models.cpp) +target_link_libraries(testmodels "${PROJECT_NAME}") +target_link_libraries(testmodels "${TORCH_LIBRARIES}") + install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}) install(FILES ${MODELS_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/models) diff --git a/test/test_models.cpp b/test/test_models.cpp new file mode 100644 index 00000000000..368f397675a --- /dev/null +++ b/test/test_models.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include "../torchvision/csrc/models/models.h" + +#include + +using namespace vision::models; + +template +torch::Tensor test_model(torch::Tensor x, const std::string& input_path) +{ + Model network; + torch::load(network, input_path); + return network->forward(x); +} + +torch::Tensor test_alexnet(torch::Tensor x) +{ + return test_model(x, "alexnet.pt"); +} + +torch::Tensor test_vgg11(torch::Tensor x) +{ + return test_model(x, "vgg11.pt"); +} +torch::Tensor test_vgg13(torch::Tensor x) +{ + return test_model(x, "vgg13.pt"); +} +torch::Tensor test_vgg16(torch::Tensor x) +{ + return test_model(x, "vgg16.pt"); +} +torch::Tensor test_vgg19(torch::Tensor x) +{ + return test_model(x, "vgg19.pt"); +} + +torch::Tensor test_vgg11bn(torch::Tensor x) +{ + return test_model(x, "vgg11bn.pt"); +} +torch::Tensor test_vgg13bn(torch::Tensor x) +{ + return test_model(x, "vgg13bn.pt"); +} +torch::Tensor test_vgg16bn(torch::Tensor x) +{ + return test_model(x, "vgg16bn.pt"); +} +torch::Tensor test_vgg19bn(torch::Tensor x) +{ + return test_model(x, "vgg19bn.pt"); +} + +torch::Tensor test_resnet18(torch::Tensor x) +{ + return test_model(x, "resnet18.pt"); +} +torch::Tensor test_resnet34(torch::Tensor x) +{ + return test_model(x, "resnet34.pt"); +} +torch::Tensor test_resnet50(torch::Tensor x) +{ + return test_model(x, "resnet50.pt"); +} +torch::Tensor test_resnet101(torch::Tensor x) +{ + return test_model(x, "resnet101.pt"); +} +torch::Tensor test_resnet152(torch::Tensor x) +{ + return test_model(x, "resnet152.pt"); +} + +torch::Tensor test_squeezenet1_0(torch::Tensor x) +{ + return test_model(x, "squeezenet1_0.pt"); +} +torch::Tensor test_squeezenet1_1(torch::Tensor x) +{ + return test_model(x, "squeezenet1_1.pt"); +} + +torch::Tensor test_densenet121(torch::Tensor x) +{ + return test_model(x, "densenet121.pt"); +} +torch::Tensor test_densenet169(torch::Tensor x) +{ + return test_model(x, "densenet169.pt"); +} +torch::Tensor test_densenet201(torch::Tensor x) +{ + return test_model(x, "densenet201.pt"); +} +torch::Tensor test_densenet161(torch::Tensor x) +{ + return test_model(x, "densenet161.pt"); +} + +torch::Tensor test_inceptionv3(torch::Tensor x) +{ + InceptionV3 network; + torch::load(network, "inceptionv3.pt"); + return network->forward(x)[0]; +} diff --git a/torchvision/csrc/convert_models/convert_models.cpp b/torchvision/csrc/convert_models/convert_models.cpp new file mode 100644 index 00000000000..fc05ffd0cf5 --- /dev/null +++ b/torchvision/csrc/convert_models/convert_models.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +#include "../models/models.h" + +using namespace vision::models; + +template +void convert_and_save_model( + const std::string& input_path, + const std::string& output_path) { + Model network; + torch::load(network, input_path); + torch::save(network, output_path); + + auto index = input_path.find("_python"); + auto name = input_path.substr(0, index); + std::cout << "finished loading and saving " << name << std::endl; +} + +int main(int argc, const char* argv[]) { + convert_and_save_model("alexnet_python.pt", "alexnet_cpp.pt"); + + convert_and_save_model("vgg11_python.pt", "vgg11_cpp.pt"); + convert_and_save_model("vgg13_python.pt", "vgg13_cpp.pt"); + convert_and_save_model("vgg16_python.pt", "vgg16_cpp.pt"); + convert_and_save_model("vgg19_python.pt", "vgg19_cpp.pt"); + + convert_and_save_model("vgg11bn_python.pt", "vgg11bn_cpp.pt"); + convert_and_save_model("vgg13bn_python.pt", "vgg13bn_cpp.pt"); + convert_and_save_model("vgg16bn_python.pt", "vgg16bn_cpp.pt"); + convert_and_save_model("vgg19bn_python.pt", "vgg19bn_cpp.pt"); + + convert_and_save_model("resnet18_python.pt", "resnet18_cpp.pt"); + convert_and_save_model("resnet34_python.pt", "resnet34_cpp.pt"); + convert_and_save_model("resnet50_python.pt", "resnet50_cpp.pt"); + convert_and_save_model("resnet101_python.pt", "resnet101_cpp.pt"); + convert_and_save_model("resnet152_python.pt", "resnet152_cpp.pt"); + + convert_and_save_model( + "squeezenet1_0_python.pt", "squeezenet1_0_cpp.pt"); + convert_and_save_model( + "squeezenet1_1_python.pt", "squeezenet1_1_cpp.pt"); + + convert_and_save_model( + "densenet121_python.pt", "densenet121_cpp.pt"); + convert_and_save_model( + "densenet169_python.pt", "densenet169_cpp.pt"); + convert_and_save_model( + "densenet201_python.pt", "densenet201_cpp.pt"); + convert_and_save_model( + "densenet161_python.pt", "densenet161_cpp.pt"); + + convert_and_save_model( + "inceptionv3_python.pt", "inceptionv3_cpp.pt"); + + return 0; +} From 90b01be52759f2facbfa547b133adde2d370eecd Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Mon, 1 Apr 2019 23:51:06 +0430 Subject: [PATCH 20/48] Fixed a typo in alexnet and removed tests from cmake --- CMakeLists.txt | 7 +++---- torchvision/csrc/models/alexnet.cpp | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index caa2831b822..d1609f8e820 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,10 +15,9 @@ add_executable(convertmodels torchvision/csrc/convert_models/convert_models.cpp) target_link_libraries(convertmodels "${PROJECT_NAME}") target_link_libraries(convertmodels "${TORCH_LIBRARIES}") -find_package(pybind11 REQUIRED) -add_executable(testmodels test/test_models.cpp) -target_link_libraries(testmodels "${PROJECT_NAME}") -target_link_libraries(testmodels "${TORCH_LIBRARIES}") +#add_executable(testmodels test/test_models.cpp) +#target_link_libraries(testmodels "${PROJECT_NAME}") +#target_link_libraries(testmodels "${TORCH_LIBRARIES}") install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}) diff --git a/torchvision/csrc/models/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp index bb1934ae605..9a68a33c489 100644 --- a/torchvision/csrc/models/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -31,7 +31,7 @@ AlexNetImpl::AlexNetImpl(int64_t num_classes) { torch::nn::Linear(4096, num_classes)); register_module("features", features); - register_module("clasifier", classifier); + register_module("classifier", classifier); } torch::Tensor AlexNetImpl::forward(torch::Tensor x) { From f698fd445bf063c893d6dfb348259a80cbb43d30 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Wed, 3 Apr 2019 08:08:57 +0430 Subject: [PATCH 21/48] Made an extension of tests and added module names to Densenet --- setup.py | 33 ++++++ test/test_models.cpp | 151 ++++++++++++++------------- torchvision/csrc/models/densenet.cpp | 51 +++++---- 3 files changed, 142 insertions(+), 93 deletions(-) diff --git a/setup.py b/setup.py index 0346abc8d0c..b2adb33f18f 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,9 @@ from pkg_resources import get_distribution, DistributionNotFound import subprocess +import glob +import torch +from torch.utils.cpp_extension import CppExtension, CUDAExtension, CUDA_HOME def read(*names, **kwargs): with io.open( @@ -69,6 +72,33 @@ def write_version_file(): requirements.append(pillow_req + pillow_ver) +def get_extensions(): + this_dir = os.path.dirname(os.path.abspath(__file__)) + extensions_dir = os.path.join(this_dir, 'test') + + main_file = glob.glob(os.path.join(extensions_dir, '*.cpp')) + + sources = main_file + extension = CppExtension + + extra_compile_args = {'cxx': []} + define_macros = [] + + sources = [os.path.join(extensions_dir, s) for s in sources] + include_dirs = [extensions_dir] + + ext_modules = [ + extension( + 'torchvision._C', + sources, + include_dirs=include_dirs, + define_macros=define_macros, + extra_compile_args=extra_compile_args, + ) + ] + + return ext_modules + setup( # Metadata name=package_name, @@ -88,4 +118,7 @@ def write_version_file(): extras_require={ "scipy": ["scipy"], }, + + ext_modules=get_extensions(), + cmdclass={'build_ext': torch.utils.cpp_extension.BuildExtension} ) diff --git a/test/test_models.cpp b/test/test_models.cpp index 368f397675a..28c62130c97 100644 --- a/test/test_models.cpp +++ b/test/test_models.cpp @@ -1,109 +1,116 @@ #include #include #include -#include "../torchvision/csrc/models/models.h" -#include +#include "../torchvision/csrc/models/models.h" using namespace vision::models; template -torch::Tensor test_model(torch::Tensor x, const std::string& input_path) -{ - Model network; - torch::load(network, input_path); - return network->forward(x); +torch::Tensor test_model(torch::Tensor x, const std::string& input_path) { + Model network; + torch::load(network, input_path); + return network->forward(x); } -torch::Tensor test_alexnet(torch::Tensor x) -{ - return test_model(x, "alexnet.pt"); +torch::Tensor test_alexnet(torch::Tensor x) { + return test_model(x, "alexnet.pt"); } -torch::Tensor test_vgg11(torch::Tensor x) -{ - return test_model(x, "vgg11.pt"); +torch::Tensor test_vgg11(torch::Tensor x) { + return test_model(x, "vgg11.pt"); } -torch::Tensor test_vgg13(torch::Tensor x) -{ - return test_model(x, "vgg13.pt"); +torch::Tensor test_vgg13(torch::Tensor x) { + return test_model(x, "vgg13.pt"); } -torch::Tensor test_vgg16(torch::Tensor x) -{ - return test_model(x, "vgg16.pt"); +torch::Tensor test_vgg16(torch::Tensor x) { + return test_model(x, "vgg16.pt"); } -torch::Tensor test_vgg19(torch::Tensor x) -{ - return test_model(x, "vgg19.pt"); +torch::Tensor test_vgg19(torch::Tensor x) { + return test_model(x, "vgg19.pt"); } -torch::Tensor test_vgg11bn(torch::Tensor x) -{ - return test_model(x, "vgg11bn.pt"); +torch::Tensor test_vgg11bn(torch::Tensor x) { + return test_model(x, "vgg11bn.pt"); } -torch::Tensor test_vgg13bn(torch::Tensor x) -{ - return test_model(x, "vgg13bn.pt"); +torch::Tensor test_vgg13bn(torch::Tensor x) { + return test_model(x, "vgg13bn.pt"); } -torch::Tensor test_vgg16bn(torch::Tensor x) -{ - return test_model(x, "vgg16bn.pt"); +torch::Tensor test_vgg16bn(torch::Tensor x) { + return test_model(x, "vgg16bn.pt"); } -torch::Tensor test_vgg19bn(torch::Tensor x) -{ - return test_model(x, "vgg19bn.pt"); +torch::Tensor test_vgg19bn(torch::Tensor x) { + return test_model(x, "vgg19bn.pt"); } -torch::Tensor test_resnet18(torch::Tensor x) -{ - return test_model(x, "resnet18.pt"); +torch::Tensor test_resnet18(torch::Tensor x) { + return test_model(x, "resnet18.pt"); } -torch::Tensor test_resnet34(torch::Tensor x) -{ - return test_model(x, "resnet34.pt"); +torch::Tensor test_resnet34(torch::Tensor x) { + return test_model(x, "resnet34.pt"); } -torch::Tensor test_resnet50(torch::Tensor x) -{ - return test_model(x, "resnet50.pt"); +torch::Tensor test_resnet50(torch::Tensor x) { + return test_model(x, "resnet50.pt"); } -torch::Tensor test_resnet101(torch::Tensor x) -{ - return test_model(x, "resnet101.pt"); +torch::Tensor test_resnet101(torch::Tensor x) { + return test_model(x, "resnet101.pt"); } -torch::Tensor test_resnet152(torch::Tensor x) -{ - return test_model(x, "resnet152.pt"); +torch::Tensor test_resnet152(torch::Tensor x) { + return test_model(x, "resnet152.pt"); } -torch::Tensor test_squeezenet1_0(torch::Tensor x) -{ - return test_model(x, "squeezenet1_0.pt"); +torch::Tensor test_squeezenet1_0(torch::Tensor x) { + return test_model(x, "squeezenet1_0.pt"); } -torch::Tensor test_squeezenet1_1(torch::Tensor x) -{ - return test_model(x, "squeezenet1_1.pt"); +torch::Tensor test_squeezenet1_1(torch::Tensor x) { + return test_model(x, "squeezenet1_1.pt"); } -torch::Tensor test_densenet121(torch::Tensor x) -{ - return test_model(x, "densenet121.pt"); +torch::Tensor test_densenet121(torch::Tensor x) { + return test_model(x, "densenet121.pt"); } -torch::Tensor test_densenet169(torch::Tensor x) -{ - return test_model(x, "densenet169.pt"); +torch::Tensor test_densenet169(torch::Tensor x) { + return test_model(x, "densenet169.pt"); } -torch::Tensor test_densenet201(torch::Tensor x) -{ - return test_model(x, "densenet201.pt"); +torch::Tensor test_densenet201(torch::Tensor x) { + return test_model(x, "densenet201.pt"); } -torch::Tensor test_densenet161(torch::Tensor x) -{ - return test_model(x, "densenet161.pt"); +torch::Tensor test_densenet161(torch::Tensor x) { + return test_model(x, "densenet161.pt"); } -torch::Tensor test_inceptionv3(torch::Tensor x) -{ - InceptionV3 network; - torch::load(network, "inceptionv3.pt"); - return network->forward(x)[0]; +torch::Tensor test_inceptionv3(torch::Tensor x) { + InceptionV3 network; + torch::load(network, "inceptionv3.pt"); + return network->forward(x)[0]; +} + +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("test_alexnet", &test_alexnet, "test_alexnet"); + + m.def("test_vgg11", &test_vgg11, "test_vgg11"); + m.def("test_vgg13", &test_vgg13, "test_vgg13"); + m.def("test_vgg16", &test_vgg16, "test_vgg16"); + m.def("test_vgg19", &test_vgg19, "test_vgg19"); + + m.def("test_vgg11bn", &test_vgg11bn, "test_vgg11bn"); + m.def("test_vgg13bn", &test_vgg13bn, "test_vgg13bn"); + m.def("test_vgg16bn", &test_vgg16bn, "test_vgg16bn"); + m.def("test_vgg19bn", &test_vgg19bn, "test_vgg19bn"); + + m.def("test_resnet18", &test_resnet18, "test_resnet18"); + m.def("test_resnet34", &test_resnet34, "test_resnet34"); + m.def("test_resnet50", &test_resnet50, "test_resnet50"); + m.def("test_resnet101", &test_resnet101, "test_resnet101"); + m.def("test_resnet152", &test_resnet152, "test_resnet152"); + + m.def("test_squeezenet1_0", &test_squeezenet1_0, "test_squeezenet1_0"); + m.def("test_squeezenet1_1", &test_squeezenet1_1, "test_squeezenet1_1"); + + m.def("test_densenet121", &test_densenet121, "test_densenet121"); + m.def("test_densenet169", &test_densenet169, "test_densenet169"); + m.def("test_densenet201", &test_densenet201, "test_densenet201"); + m.def("test_densenet161", &test_densenet161, "test_densenet161"); + + m.def("test_inceptionv3", &test_inceptionv3, "test_inceptionv3"); } diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index f126581c09f..43876943c38 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -15,18 +15,21 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { int64_t bn_size, double drop_rate) : drop_rate(drop_rate) { - push_back(torch::nn::BatchNorm(num_input_features)); - push_back(torch::nn::Functional(modelsimpl::relu_)); + push_back("norm1", torch::nn::BatchNorm(num_input_features)); + push_back("relu1", torch::nn::Functional(modelsimpl::relu_)); push_back( + "conv1", torch::nn::Conv2d(Options(num_input_features, bn_size * growth_rate, 1) .stride(1) .with_bias(false))); - push_back(torch::nn::BatchNorm(bn_size * growth_rate)); - push_back(torch::nn::Functional(modelsimpl::relu_)); - push_back(torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) - .stride(1) - .padding(1) - .with_bias(false))); + push_back("norm2", torch::nn::BatchNorm(bn_size * growth_rate)); + push_back("relu2", torch::nn::Functional(modelsimpl::relu_)); + push_back( + "conv2", + torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) + .stride(1) + .padding(1) + .with_bias(false))); } torch::Tensor forward(torch::Tensor x) { @@ -53,7 +56,7 @@ struct _DenseBlockImpl : torch::nn::SequentialImpl { growth_rate, bn_size, drop_rate); - push_back(layer); + push_back("denselayer" + std::to_string(i + 1), layer); } } @@ -66,13 +69,15 @@ TORCH_MODULE(_DenseBlock); struct _TransitionImpl : torch::nn::SequentialImpl { _TransitionImpl(int64_t num_input_features, int64_t num_output_features) { - push_back(torch::nn::BatchNorm(num_input_features)); - push_back(torch::nn::Functional(modelsimpl::relu_)); + push_back("norm", torch::nn::BatchNorm(num_input_features)); + push_back("relu ", torch::nn::Functional(modelsimpl::relu_)); push_back( + "conv", torch::nn::Conv2d(Options(num_input_features, num_output_features, 1) .stride(1) .with_bias(false))); - push_back(torch::nn::Functional(torch::avg_pool2d, 2, 2, 0, false, true)); + push_back( + "pool", torch::nn::Functional(torch::avg_pool2d, 2, 2, 0, false, true)); } torch::Tensor forward(torch::Tensor x) { @@ -90,14 +95,18 @@ DenseNetImpl::DenseNetImpl( int64_t bn_size, double drop_rate) { // First convolution - features = torch::nn::Sequential( - torch::nn::Conv2d(torch::nn::Conv2dOptions(3, num_init_features, 7) + features = torch::nn::Sequential(); + features->push_back( + "conv0", + torch::nn::Conv2d(Options(3, num_init_features, 7) .stride(2) .padding(3) - .with_bias(false)), - torch::nn::BatchNorm(num_init_features), - torch::nn::Functional(modelsimpl::relu_), - torch::nn::Functional(torch::max_pool2d, 3, 2, 1, 1, false)); + .with_bias(false))); + + features->push_back("norm0", torch::nn::BatchNorm(num_init_features)); + features->push_back("relu0", torch::nn::Functional(modelsimpl::relu_)); + features->push_back( + "pool0", torch::nn::Functional(torch::max_pool2d, 3, 2, 1, 1, false)); // Each denseblock auto num_features = num_init_features; @@ -106,18 +115,18 @@ DenseNetImpl::DenseNetImpl( _DenseBlock block( num_layers, num_features, bn_size, growth_rate, drop_rate); - features->push_back(block); + features->push_back("denseblock" + std::to_string(i + 1), block); num_features = num_features + num_layers * growth_rate; if (i != block_config.size() - 1) { auto trans = _Transition(num_features, num_features / 2); - features->push_back(trans); + features->push_back("transition" + std::to_string(i + 1), trans); num_features = num_features / 2; } } // Final batch norm - features->push_back(torch::nn::BatchNorm(num_features)); + features->push_back("norm5", torch::nn::BatchNorm(num_features)); // Linear layer classifier = torch::nn::Linear(num_features, num_classes); From b31e1045d2221c58bad2cf8b70a2eeeb330d7b2b Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Mon, 15 Apr 2019 06:55:43 +0430 Subject: [PATCH 22/48] Added python tests --- test/test_cpp_models.py | 49 +++++++++++++++ test/test_models.cpp | 128 ++++++++++++++++++++-------------------- 2 files changed, 113 insertions(+), 64 deletions(-) create mode 100644 test/test_cpp_models.py diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py new file mode 100644 index 00000000000..b1ddaade54b --- /dev/null +++ b/test/test_cpp_models.py @@ -0,0 +1,49 @@ +import torch +from torchvision import models, transforms, _C + +from PIL import Image +import torchvision.transforms.functional as F + +def test_model(model, tensor, func, name): + traced_script_module = torch.jit.trace(model, tensor) + traced_script_module.save("model.pt") + + py_output = model.forward(tensor) + cpp_output = func("model.pt", tensor) + + assert torch.allclose(py_output, cpp_output), 'Output mismatch of ' + name + ' models' + +image = Image.open('assets/grace_hopper_517x606.jpg') +image = image.resize((224, 224)) +x = F.to_tensor(image) +x = x.view(1, 3, 224, 224) + +pretrained = False + +test_model(models.alexnet(pretrained), x, _C.forward_alexnet, 'Alexnet') + +test_model(models.vgg11(pretrained), x, _C.forward_vgg11, 'VGG11') +test_model(models.vgg13(pretrained), x, _C.forward_vgg13, 'VGG13') +test_model(models.vgg16(pretrained), x, _C.forward_vgg16, 'VGG16') +test_model(models.vgg19(pretrained), x, _C.forward_vgg19, 'VGG19') + +test_model(models.vgg11_bn(pretrained), x, _C.forward_vgg11bn, 'VGG11BN') +test_model(models.vgg13_bn(pretrained), x, _C.forward_vgg13bn, 'VGG13BN') +test_model(models.vgg16_bn(pretrained), x, _C.forward_vgg16bn, 'VGG16BN') +test_model(models.vgg19_bn(pretrained), x, _C.forward_vgg19bn, 'VGG19BN') + +test_model(models.resnet18(pretrained), x, _C.forward_resnet18, 'Resnet18') +test_model(models.resnet34(pretrained), x, _C.forward_resnet34, 'Resnet34') +test_model(models.resnet50(pretrained), x, _C.forward_resnet50, 'Resnet50') +test_model(models.resnet101(pretrained), x, _C.forward_resnet101, 'Resnet101') +test_model(models.resnet152(pretrained), x, _C.forward_resnet152, 'Resnet152') + +test_model(models.squeezenet1_0(pretrained), x, _C.forward_squeezenet1_0, 'Squeezenet1.0') +test_model(models.squeezenet1_1(pretrained), x, _C.forward_squeezenet1_1, 'Squeezenet1.1') + +test_model(models.densenet121(pretrained), x, _C.forward_densenet121, 'Densenet121') +test_model(models.densenet169(pretrained), x, _C.forward_densenet169, 'Densenet169') +test_model(models.densenet201(pretrained), x, _C.forward_densenet201, 'Densenet201') +test_model(models.densenet161(pretrained), x, _C.forward_densenet161, 'Densenet161') + +test_model(models.inception_v3(pretrained), x, _C.forward_inceptionv3, 'Inceptionv3') diff --git a/test/test_models.cpp b/test/test_models.cpp index 28c62130c97..979cce1ee43 100644 --- a/test/test_models.cpp +++ b/test/test_models.cpp @@ -7,110 +7,110 @@ using namespace vision::models; template -torch::Tensor test_model(torch::Tensor x, const std::string& input_path) { +torch::Tensor forward_model(const std::string& input_path, torch::Tensor x) { Model network; torch::load(network, input_path); return network->forward(x); } -torch::Tensor test_alexnet(torch::Tensor x) { - return test_model(x, "alexnet.pt"); +torch::Tensor forward_alexnet(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_vgg11(torch::Tensor x) { - return test_model(x, "vgg11.pt"); +torch::Tensor forward_vgg11(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_vgg13(torch::Tensor x) { - return test_model(x, "vgg13.pt"); +torch::Tensor forward_vgg13(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_vgg16(torch::Tensor x) { - return test_model(x, "vgg16.pt"); +torch::Tensor forward_vgg16(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_vgg19(torch::Tensor x) { - return test_model(x, "vgg19.pt"); +torch::Tensor forward_vgg19(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_vgg11bn(torch::Tensor x) { - return test_model(x, "vgg11bn.pt"); +torch::Tensor forward_vgg11bn(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_vgg13bn(torch::Tensor x) { - return test_model(x, "vgg13bn.pt"); +torch::Tensor forward_vgg13bn(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_vgg16bn(torch::Tensor x) { - return test_model(x, "vgg16bn.pt"); +torch::Tensor forward_vgg16bn(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_vgg19bn(torch::Tensor x) { - return test_model(x, "vgg19bn.pt"); +torch::Tensor forward_vgg19bn(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_resnet18(torch::Tensor x) { - return test_model(x, "resnet18.pt"); +torch::Tensor forward_resnet18(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_resnet34(torch::Tensor x) { - return test_model(x, "resnet34.pt"); +torch::Tensor forward_resnet34(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_resnet50(torch::Tensor x) { - return test_model(x, "resnet50.pt"); +torch::Tensor forward_resnet50(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_resnet101(torch::Tensor x) { - return test_model(x, "resnet101.pt"); +torch::Tensor forward_resnet101(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_resnet152(torch::Tensor x) { - return test_model(x, "resnet152.pt"); +torch::Tensor forward_resnet152(const std::string& input_path, torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_squeezenet1_0(torch::Tensor x) { - return test_model(x, "squeezenet1_0.pt"); +torch::Tensor forward_squeezenet1_0(torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_squeezenet1_1(torch::Tensor x) { - return test_model(x, "squeezenet1_1.pt"); +torch::Tensor forward_squeezenet1_1(torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_densenet121(torch::Tensor x) { - return test_model(x, "densenet121.pt"); +torch::Tensor forward_densenet121(torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_densenet169(torch::Tensor x) { - return test_model(x, "densenet169.pt"); +torch::Tensor forward_densenet169(torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_densenet201(torch::Tensor x) { - return test_model(x, "densenet201.pt"); +torch::Tensor forward_densenet201(torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_densenet161(torch::Tensor x) { - return test_model(x, "densenet161.pt"); +torch::Tensor forward_densenet161(torch::Tensor x) { + return forward_model(input_path, x); } -torch::Tensor test_inceptionv3(torch::Tensor x) { +torch::Tensor forward_inceptionv3(torch::Tensor x) { InceptionV3 network; - torch::load(network, "inceptionv3.pt"); + torch::load(input_path, x); return network->forward(x)[0]; } PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { - m.def("test_alexnet", &test_alexnet, "test_alexnet"); + m.def("forward_alexnet", &forward_alexnet, "forward_alexnet"); - m.def("test_vgg11", &test_vgg11, "test_vgg11"); - m.def("test_vgg13", &test_vgg13, "test_vgg13"); - m.def("test_vgg16", &test_vgg16, "test_vgg16"); - m.def("test_vgg19", &test_vgg19, "test_vgg19"); + m.def("forward_vgg11", &forward_vgg11, "forward_vgg11"); + m.def("forward_vgg13", &forward_vgg13, "forward_vgg13"); + m.def("forward_vgg16", &forward_vgg16, "forward_vgg16"); + m.def("forward_vgg19", &forward_vgg19, "forward_vgg19"); - m.def("test_vgg11bn", &test_vgg11bn, "test_vgg11bn"); - m.def("test_vgg13bn", &test_vgg13bn, "test_vgg13bn"); - m.def("test_vgg16bn", &test_vgg16bn, "test_vgg16bn"); - m.def("test_vgg19bn", &test_vgg19bn, "test_vgg19bn"); + m.def("forward_vgg11bn", &forward_vgg11bn, "forward_vgg11bn"); + m.def("forward_vgg13bn", &forward_vgg13bn, "forward_vgg13bn"); + m.def("forward_vgg16bn", &forward_vgg16bn, "forward_vgg16bn"); + m.def("forward_vgg19bn", &forward_vgg19bn, "forward_vgg19bn"); - m.def("test_resnet18", &test_resnet18, "test_resnet18"); - m.def("test_resnet34", &test_resnet34, "test_resnet34"); - m.def("test_resnet50", &test_resnet50, "test_resnet50"); - m.def("test_resnet101", &test_resnet101, "test_resnet101"); - m.def("test_resnet152", &test_resnet152, "test_resnet152"); + m.def("forward_resnet18", &forward_resnet18, "forward_resnet18"); + m.def("forward_resnet34", &forward_resnet34, "forward_resnet34"); + m.def("forward_resnet50", &forward_resnet50, "forward_resnet50"); + m.def("forward_resnet101", &forward_resnet101, "forward_resnet101"); + m.def("forward_resnet152", &forward_resnet152, "forward_resnet152"); - m.def("test_squeezenet1_0", &test_squeezenet1_0, "test_squeezenet1_0"); - m.def("test_squeezenet1_1", &test_squeezenet1_1, "test_squeezenet1_1"); + m.def("forward_squeezenet1_0", &forward_squeezenet1_0, "forward_squeezenet1_0"); + m.def("forward_squeezenet1_1", &forward_squeezenet1_1, "forward_squeezenet1_1"); - m.def("test_densenet121", &test_densenet121, "test_densenet121"); - m.def("test_densenet169", &test_densenet169, "test_densenet169"); - m.def("test_densenet201", &test_densenet201, "test_densenet201"); - m.def("test_densenet161", &test_densenet161, "test_densenet161"); + m.def("forward_densenet121", &forward_densenet121, "forward_densenet121"); + m.def("forward_densenet169", &forward_densenet169, "forward_densenet169"); + m.def("forward_densenet201", &forward_densenet201, "forward_densenet201"); + m.def("forward_densenet161", &forward_densenet161, "forward_densenet161"); - m.def("test_inceptionv3", &test_inceptionv3, "test_inceptionv3"); + m.def("forward_inceptionv3", &forward_inceptionv3, "forward_inceptionv3"); } From 943e621dcc6ad7841a7998aaad6448f5090ca7ab Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Fri, 19 Apr 2019 00:27:43 +0430 Subject: [PATCH 23/48] Added MobileNet and GoogLeNet models --- torchvision/csrc/models/googlenet.cpp | 224 ++++++++++++++++++++++++++ torchvision/csrc/models/googlenet.h | 86 ++++++++++ torchvision/csrc/models/inception.cpp | 5 +- torchvision/csrc/models/inception.h | 10 +- torchvision/csrc/models/mobilenet.cpp | 137 ++++++++++++++++ torchvision/csrc/models/mobilenet.h | 21 +++ torchvision/csrc/models/models.h | 2 + torchvision/csrc/models/modelsimpl.h | 4 + 8 files changed, 486 insertions(+), 3 deletions(-) create mode 100644 torchvision/csrc/models/googlenet.cpp create mode 100644 torchvision/csrc/models/googlenet.h create mode 100644 torchvision/csrc/models/mobilenet.cpp create mode 100644 torchvision/csrc/models/mobilenet.h diff --git a/torchvision/csrc/models/googlenet.cpp b/torchvision/csrc/models/googlenet.cpp new file mode 100644 index 00000000000..21efcb02798 --- /dev/null +++ b/torchvision/csrc/models/googlenet.cpp @@ -0,0 +1,224 @@ +#include "googlenet.h" + +#include "modelsimpl.h" + +namespace vision { +namespace models { + +using Options = torch::nn::Conv2dOptions; + +namespace _googlenetimpl { +BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions options) { + options.with_bias(false); + conv = torch::nn::Conv2d(options); + bn = torch::nn::BatchNorm( + torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); + + register_module("conv", conv); + register_module("bn", bn); +} + +torch::Tensor BasicConv2dImpl::forward(torch::Tensor x) { + x = conv->forward(x); + x = bn->forward(x); + return x.relu_(); +} + +InceptionImpl::InceptionImpl( + int64_t in_channels, + int64_t ch1x1, + int64_t ch3x3red, + int64_t ch3x3, + int64_t ch5x5red, + int64_t ch5x5, + int64_t pool_proj) { + branch1 = BasicConv2d(Options(in_channels, ch1x1, 1)); + + branch2->push_back(BasicConv2d(Options(in_channels, ch3x3red, 1))); + branch2->push_back(BasicConv2d(Options(ch3x3red, ch3x3, 3).padding(1))); + + branch3->push_back(BasicConv2d(Options(in_channels, ch5x5red, 1))); + branch3->push_back(BasicConv2d(Options(ch5x5red, ch5x5, 3).padding(1))); + + branch4->push_back( + torch::nn::Functional(torch::max_pool2d, 3, 1, 1, 1, true)); + branch4->push_back(BasicConv2d(Options(in_channels, pool_proj, 1))); +} + +torch::Tensor InceptionImpl::forward(torch::Tensor x) { + auto b1 = branch1->forward(x); + auto b2 = branch2->forward(x); + auto b3 = branch3->forward(x); + auto b4 = branch4->forward(x); + + return torch::cat({b1, b2, b3, b4}, 1); +} + +InceptionAuxImpl::InceptionAuxImpl(int64_t in_channels, int64_t num_classes) { + conv = BasicConv2d(Options(in_channels, 128, 1)); + fc1 = torch::nn::Linear(2048, 1024); + fc2 = torch::nn::Linear(1024, num_classes); + + register_module("conv", conv); + register_module("fc1", fc1); + register_module("fc2", fc2); +} + +torch::Tensor InceptionAuxImpl::forward(at::Tensor x) { + // aux1: N x 512 x 14 x 14, aux2: N x 528 x 14 x 14 + x = torch::adaptive_avg_pool2d(x, {4, 4}); + // aux1: N x 512 x 4 x 4, aux2: N x 528 x 4 x 4 + x = conv->forward(x); + // N x 128 x 4 x 4 + x = x.view({x.size(0), -1}); + // N x 2048 + x = fc1->forward(x).relu_(); + // N x 2048 + x = torch::dropout(x, 0.7, is_training()); + // N x 2048 + x = fc2->forward(x); + // N x 1024 + + return x; +} + +} // namespace _googlenetimpl + +GoogLeNet::GoogLeNet( + int64_t num_classes, + bool aux_logits, + bool transform_input, + bool init_weights) { + this->aux_logits = aux_logits; + this->transform_input = transform_input; + + conv1 = _googlenetimpl::BasicConv2d(Options(3, 64, 7).stride(2).padding(3)); + conv2 = _googlenetimpl::BasicConv2d(Options(64, 64, 1)); + conv3 = _googlenetimpl::BasicConv2d(Options(64, 192, 3).padding(1)); + + inception3a = _googlenetimpl::Inception(192, 64, 96, 128, 16, 32, 32); + inception3b = _googlenetimpl::Inception(256, 128, 128, 192, 32, 96, 64); + + inception4a = _googlenetimpl::Inception(480, 192, 96, 208, 16, 48, 64); + inception4b = _googlenetimpl::Inception(512, 160, 112, 224, 24, 64, 64); + inception4c = _googlenetimpl::Inception(512, 128, 128, 256, 24, 64, 64); + inception4d = _googlenetimpl::Inception(512, 112, 144, 288, 32, 64, 64); + inception4e = _googlenetimpl::Inception(528, 256, 160, 320, 32, 128, 128); + + inception5a = _googlenetimpl::Inception(832, 256, 160, 320, 32, 128, 128); + inception5b = _googlenetimpl::Inception(832, 384, 192, 384, 48, 128, 128); + + if (aux_logits) { + aux1 = _googlenetimpl::InceptionAux(512, num_classes); + aux2 = _googlenetimpl::InceptionAux(528, num_classes); + + register_module("aux1", aux1); + register_module("aux2", aux2); + } + + dropout = torch::nn::Dropout(0.2); + fc = torch::nn::Linear(1024, num_classes); + + register_module("conv1", conv1); + register_module("conv2", conv2); + register_module("conv3", conv3); + + register_module("inception3a", inception3a); + register_module("inception3b", inception3b); + + register_module("inception4a", inception4a); + register_module("inception4b", inception4b); + register_module("inception4c", inception4c); + register_module("inception4d", inception4d); + register_module("inception4e", inception4e); + + register_module("inception5a", inception5a); + register_module("inception5b", inception5b); + + register_module("dropout", dropout); + register_module("fc", fc); + + if (init_weights) + _initialize_weights(); +} + +void GoogLeNet::_initialize_weights() { + for (auto& module : modules(/*include_self=*/false)) { + if (auto M = dynamic_cast(module.get())) + torch::nn::init::normal_(M->weight); + else if (auto M = dynamic_cast(module.get())) { + torch::nn::init::ones_(M->weight); + torch::nn::init::zeros_(M->bias); + } else if (auto M = dynamic_cast(module.get())) + torch::nn::init::normal_(M->weight); + } +} + +GoogLeNetOutput GoogLeNet::forward(torch::Tensor x) { + if (transform_input) { + auto x_ch0 = torch::unsqueeze(x.select(1, 0), 1) * (0.229 / 0.5) + + (0.485 - 0.5) / 0.5; + auto x_ch1 = torch::unsqueeze(x.select(1, 1), 1) * (0.224 / 0.5) + + (0.456 - 0.5) / 0.5; + auto x_ch2 = torch::unsqueeze(x.select(1, 2), 1) * (0.225 / 0.5) + + (0.406 - 0.5) / 0.5; + + x = torch::cat({x_ch0, x_ch1, x_ch2}, 1); + } + + // N x 3 x 224 x 224 + x = conv1->forward(x); + // N x 64 x 112 x 112 + x = torch::max_pool2d(x, 3, 2, 0, 1, true); + // N x 64 x 56 x 56 + x = conv2->forward(x); + // N x 64 x 56 x 56 + x = conv3->forward(x); + // N x 192 x 56 x 56 + x = torch::max_pool2d(x, 3, 2, 0, 1, true); + + // N x 192 x 28 x 28 + x = inception3a->forward(x); + // N x 256 x 28 x 28 + x = inception3b->forward(x); + // N x 480 x 28 x 28 + x = torch::max_pool2d(x, 3, 2, 0, 1, true); + // N x 480 x 14 x 14 + x = inception4a->forward(x); + // N x 512 x 14 x 14 + torch::Tensor aux1; + if (is_training() && aux_logits) + aux1 = this->aux1->forward(x); + + x = inception4b->forward(x); + // N x 512 x 14 x 14 + x = inception4c->forward(x); + // N x 512 x 14 x 14 + x = inception4d->forward(x); + // N x 528 x 14 x 14 + torch::Tensor aux2; + if (is_training() && aux_logits) + aux2 = this->aux2->forward(x); + + x = inception4e(x); + // N x 832 x 14 x 14 + x = torch::max_pool2d(x, 2, 2, 0, 1, true); + // N x 832 x 7 x 7 + x = inception5a(x); + // N x 832 x 7 x 7 + x = inception5b(x); + // N x 1024 x 7 x 7 + + x = torch::adaptive_avg_pool2d(x, {1, 1}); + // N x 1024 x 1 x 1 + x = x.view({x.size(0), -1}); + // N x 1024 + x = dropout->forward(x); + x = fc->forward(x); + // N x 1000(num_classes) + + return {x, aux1, aux2}; +} + +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/googlenet.h b/torchvision/csrc/models/googlenet.h new file mode 100644 index 00000000000..3e8e05b88a0 --- /dev/null +++ b/torchvision/csrc/models/googlenet.h @@ -0,0 +1,86 @@ +#ifndef GOOGLENET_H +#define GOOGLENET_H + +#include + +namespace vision { +namespace models { + +namespace _googlenetimpl { +struct BasicConv2dImpl : torch::nn::Module { + torch::nn::Conv2d conv; + torch::nn::BatchNorm bn; + + BasicConv2dImpl(torch::nn::Conv2dOptions options); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(BasicConv2d); + +struct InceptionImpl : torch::nn::Module { + BasicConv2d branch1{nullptr}; + torch::nn::Sequential branch2, branch3, branch4; + + InceptionImpl( + int64_t in_channels, + int64_t ch1x1, + int64_t ch3x3red, + int64_t ch3x3, + int64_t ch5x5red, + int64_t ch5x5, + int64_t pool_proj); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(Inception); + +struct InceptionAuxImpl : torch::nn::Module { + BasicConv2d conv; + torch::nn::Linear fc1, fc2; + + InceptionAuxImpl(int64_t in_channels, int64_t num_classes); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(InceptionAux); + +} // namespace _googlenetimpl + +struct GoogLeNetOutput { + torch::Tensor output; + torch::Tensor aux1; + torch::Tensor aux2; +}; + +struct GoogLeNet : torch::nn::Module { + bool aux_logits, transform_input; + + _googlenetimpl::BasicConv2d conv1{nullptr}, conv2{nullptr}, conv3{nullptr}; + + _googlenetimpl::Inception inception3a{nullptr}, inception3b{nullptr}, + inception4a{nullptr}, inception4b{nullptr}, inception4c{nullptr}, + inception4d{nullptr}, inception4e{nullptr}, inception5a{nullptr}, + inception5b{nullptr}; + + _googlenetimpl::InceptionAux aux1{nullptr}, aux2{nullptr}; + + torch::nn::Dropout dropout{nullptr}; + torch::nn::Linear fc{nullptr}; + + GoogLeNet( + int64_t num_classes = 1000, + bool aux_logits = true, + bool transform_input = false, + bool init_weights = true); + + void _initialize_weights(); + + GoogLeNetOutput forward(torch::Tensor x); +}; +} // namespace models +} // namespace vision + +#endif // GOOGLENET_H diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 7f5983a40f2..2986706f9b9 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -2,6 +2,7 @@ namespace vision { namespace models { + using Options = torch::nn::Conv2dOptions; namespace _inceptionimpl { @@ -296,7 +297,7 @@ InceptionV3Impl::InceptionV3Impl( register_module("fc", fc); } -std::vector InceptionV3Impl::forward(torch::Tensor x) { +InceptionV3Output InceptionV3Impl::forward(torch::Tensor x) { if (transform_input) { auto x_ch0 = torch::unsqueeze(x.select(1, 0), 1) * (0.229 / 0.5) + (0.485 - 0.5) / 0.5; @@ -360,7 +361,7 @@ std::vector InceptionV3Impl::forward(torch::Tensor x) { if (is_training() && aux_logits) return {x, aux}; - return {x}; + return {x, {}}; } // namespace _inceptionimpl diff --git a/torchvision/csrc/models/inception.h b/torchvision/csrc/models/inception.h index 2657fb87435..213152f98dc 100644 --- a/torchvision/csrc/models/inception.h +++ b/torchvision/csrc/models/inception.h @@ -83,13 +83,20 @@ TORCH_MODULE(InceptionAux); } // namespace _inceptionimpl +struct InceptionV3Output { + torch::Tensor output; + torch::Tensor aux; +}; + // Inception v3 model architecture from //"Rethinking the Inception Architecture for Computer Vision" // struct InceptionV3Impl : torch::nn::Module { bool aux_logits, transform_input; + _inceptionimpl::BasicConv2d Conv2d_1a_3x3{nullptr}, Conv2d_2a_3x3{nullptr}, Conv2d_2b_3x3{nullptr}, Conv2d_3b_1x1{nullptr}, Conv2d_4a_3x3{nullptr}; + _inceptionimpl::InceptionA Mixed_5b{nullptr}, Mixed_5c{nullptr}, Mixed_5d{nullptr}; _inceptionimpl::InceptionB Mixed_6a{nullptr}; @@ -97,6 +104,7 @@ struct InceptionV3Impl : torch::nn::Module { Mixed_6d{nullptr}, Mixed_6e{nullptr}; _inceptionimpl::InceptionD Mixed_7a{nullptr}; _inceptionimpl::InceptionE Mixed_7b{nullptr}, Mixed_7c{nullptr}; + torch::nn::Linear fc{nullptr}; _inceptionimpl::InceptionAux AuxLogits{nullptr}; @@ -106,7 +114,7 @@ struct InceptionV3Impl : torch::nn::Module { bool aux_logits = true, bool transform_input = false); - std::vector forward(torch::Tensor x); + InceptionV3Output forward(torch::Tensor x); }; TORCH_MODULE(InceptionV3); diff --git a/torchvision/csrc/models/mobilenet.cpp b/torchvision/csrc/models/mobilenet.cpp new file mode 100644 index 00000000000..be53f0cff0e --- /dev/null +++ b/torchvision/csrc/models/mobilenet.cpp @@ -0,0 +1,137 @@ +#include "mobilenet.h" + +#include "modelsimpl.h" + +namespace vision { +namespace models { +using Options = torch::nn::Conv2dOptions; + +struct ConvBNReLUImpl : torch::nn::SequentialImpl { + ConvBNReLUImpl( + int64_t in_planes, + int64_t out_planes, + int64_t kernel_size = 3, + int64_t stride = 1, + int64_t groups = 1) { + auto padding = (kernel_size - 1) / 2; + push_back(torch::nn::Conv2d(Options(in_planes, out_planes, kernel_size) + .stride(stride) + .padding(padding) + .groups(groups) + .with_bias(false))); + push_back(torch::nn::BatchNorm(out_planes)); + push_back(torch::nn::Functional(modelsimpl::relu6_)); + } + + torch::Tensor forward(torch::Tensor x) { + return torch::nn::SequentialImpl::forward(x); + } +}; + +TORCH_MODULE(ConvBNReLU); + +struct InvertedResidualImpl : torch::nn::Module { + int64_t stride; + bool use_res_connect; + torch::nn::Sequential conv; + + InvertedResidualImpl( + int64_t input, + int64_t output, + int64_t stride, + double expand_ratio) + : stride(stride), use_res_connect(stride == 1 && input == output) { + auto double_compare = [](double a, double b) { + return double(std::abs(a - b)) < std::numeric_limits::epsilon(); + }; + + assert(stride == 1 || stride == 2); + auto hidden_dim = int64_t(std::round(input * expand_ratio)); + + if (double_compare(expand_ratio, 1)) + // pw + conv->push_back(ConvBNReLU(input, hidden_dim, 1)); + + // dw + conv->push_back(ConvBNReLU(hidden_dim, hidden_dim, 3, stride, hidden_dim)); + // pw-linear + conv->push_back(torch::nn::Conv2d( + Options(hidden_dim, output, 1).stride(1).padding(0).with_bias(false))); + conv->push_back(torch::nn::BatchNorm(output)); + + register_module("conv", conv); + } + + torch::Tensor forward(torch::Tensor x) { + if (use_res_connect) + return x + conv->forward(x); + return conv->forward(x); + } +}; + +TORCH_MODULE(InvertedResidual); + +MobileNetV2Impl::MobileNetV2Impl(int64_t num_classes, double width_mult) { + using Block = InvertedResidual; + int64_t input_channel = 32; + int64_t last_channel = 1280; + + std::vector> inverted_residual_settings = { + // t, c, n, s + {1, 16, 1, 1}, + {6, 24, 2, 2}, + {6, 32, 3, 2}, + {6, 64, 4, 2}, + {6, 96, 3, 1}, + {6, 160, 3, 2}, + {6, 320, 1, 1}, + }; + + input_channel = int64_t(input_channel * width_mult); + this->last_channel = int64_t(last_channel * std::max(1.0, width_mult)); + features->push_back(ConvBNReLU(3, input_channel, 3, 2)); + + for (auto setting : inverted_residual_settings) { + auto output_channel = int64_t(setting[1] * width_mult); + + for (int64_t i = 0; i < setting[2]; ++i) { + auto stride = i == 0 ? setting[3] : 1; + features->push_back( + Block(input_channel, output_channel, stride, setting[0])); + input_channel = output_channel; + } + + features->push_back(ConvBNReLU(input_channel, this->last_channel, 1)); + } + + classifier->push_back(torch::nn::Dropout(0.2)); + classifier->push_back(torch::nn::Linear(this->last_channel, num_classes)); + + register_module("features", features); + register_module("classifier", classifier); + + for (auto& module : modules(/*include_self=*/false)) { + if (auto M = dynamic_cast(module.get())) { + torch::nn::init::kaiming_normal_( + M->weight, 0, torch::nn::init::FanMode::FanOut); + if (M->options.with_bias()) + torch::nn::init::zeros_(M->bias); + } else if (auto M = dynamic_cast(module.get())) { + torch::nn::init::ones_(M->weight); + torch::nn::init::zeros_(M->bias); + } else if (auto M = dynamic_cast(module.get())) { + torch::nn::init::normal_(M->weight, 0, 0.01); + torch::nn::init::zeros_(M->bias); + } + } +} + +torch::Tensor MobileNetV2Impl::forward(at::Tensor x) { + x = features->forward(x); + x = x.mean({2, 3}); + x = classifier->forward(x); + return x; +} + +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/mobilenet.h b/torchvision/csrc/models/mobilenet.h new file mode 100644 index 00000000000..faf5e1597f1 --- /dev/null +++ b/torchvision/csrc/models/mobilenet.h @@ -0,0 +1,21 @@ +#ifndef MOBILENET_H +#define MOBILENET_H + +#include + +namespace vision { +namespace models { +struct MobileNetV2Impl : torch::nn::Module { + int64_t last_channel; + torch::nn::Sequential features, classifier; + + MobileNetV2Impl(int64_t num_classes, double width_mult = 1.0); + + torch::Tensor forward(torch::Tensor x); +}; + +TORCH_MODULE(MobileNetV2); +} // namespace models +} // namespace vision + +#endif // MOBILENET_H diff --git a/torchvision/csrc/models/models.h b/torchvision/csrc/models/models.h index 0713810082d..dada73a2690 100644 --- a/torchvision/csrc/models/models.h +++ b/torchvision/csrc/models/models.h @@ -3,7 +3,9 @@ #include "alexnet.h" #include "densenet.h" +#include "googlenet.h" #include "inception.h" +#include "mobilenet.h" #include "resnet.h" #include "squeezenet.h" #include "vgg.h" diff --git a/torchvision/csrc/models/modelsimpl.h b/torchvision/csrc/models/modelsimpl.h index ce2e7d9d059..52ec3b73a4c 100644 --- a/torchvision/csrc/models/modelsimpl.h +++ b/torchvision/csrc/models/modelsimpl.h @@ -14,6 +14,10 @@ inline torch::Tensor& relu_(torch::Tensor x) { return torch::relu_(x); } +inline torch::Tensor relu6_(torch::Tensor x) { + return torch::clamp_(x, 0, 6); +} + inline torch::Tensor adaptive_avg_pool2d( torch::Tensor x, torch::ExpandingArray<2> output_size) { From c321259cf43ffb70a1111ea395cebad45a110c2f Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Fri, 19 Apr 2019 11:47:14 +0430 Subject: [PATCH 24/48] Added tests and conversions for new models and fixed a few errors --- test/test_cpp_models.py | 3 +++ test/test_models.cpp | 14 +++++++++++++- .../csrc/convert_models/convert_models.cpp | 4 ++++ torchvision/csrc/models/googlenet.cpp | 6 +++--- torchvision/csrc/models/googlenet.h | 15 +++++++++------ torchvision/csrc/models/mobilenet.cpp | 10 ++++------ torchvision/csrc/models/mobilenet.h | 2 +- 7 files changed, 37 insertions(+), 17 deletions(-) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index b1ddaade54b..f5480441227 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -46,4 +46,7 @@ def test_model(model, tensor, func, name): test_model(models.densenet201(pretrained), x, _C.forward_densenet201, 'Densenet201') test_model(models.densenet161(pretrained), x, _C.forward_densenet161, 'Densenet161') +test_model(models.mobilenet_v2(pretrained), x, _C.forward_mobilenetv2, 'MobileNet') + +test_model(models.googlenet(pretrained), x, _C.forward_googlenet, 'GoogLeNet') test_model(models.inception_v3(pretrained), x, _C.forward_inceptionv3, 'Inceptionv3') diff --git a/test/test_models.cpp b/test/test_models.cpp index 979cce1ee43..841de848552 100644 --- a/test/test_models.cpp +++ b/test/test_models.cpp @@ -79,10 +79,19 @@ torch::Tensor forward_densenet161(torch::Tensor x) { return forward_model(input_path, x); } +torch::Tensor forward_mobilenetv2(torch::Tensor x) { + return forward_model(input_path, x); +} + +torch::Tensor forward_googlenet(torch::Tensor x) { + GoogLeNet network; + torch::load(input_path, x); + return network->forward(x).output; +} torch::Tensor forward_inceptionv3(torch::Tensor x) { InceptionV3 network; torch::load(input_path, x); - return network->forward(x)[0]; + return network->forward(x).output; } PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { @@ -112,5 +121,8 @@ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { m.def("forward_densenet201", &forward_densenet201, "forward_densenet201"); m.def("forward_densenet161", &forward_densenet161, "forward_densenet161"); + m.def("forward_mobilenetv2", &forward_mobilenetv2, "forward_mobilenetv2"); + + m.def("forward_googlenet", &forward_googlenet, "forward_googlenet"); m.def("forward_inceptionv3", &forward_inceptionv3, "forward_inceptionv3"); } diff --git a/torchvision/csrc/convert_models/convert_models.cpp b/torchvision/csrc/convert_models/convert_models.cpp index fc05ffd0cf5..b9c194402c3 100644 --- a/torchvision/csrc/convert_models/convert_models.cpp +++ b/torchvision/csrc/convert_models/convert_models.cpp @@ -52,6 +52,10 @@ int main(int argc, const char* argv[]) { convert_and_save_model( "densenet161_python.pt", "densenet161_cpp.pt"); + convert_and_save_model( + "mobilenetv2_python.pt", "mobilenetv2_cpp.pt"); + + convert_and_save_model("googlenet_python.pt", "googlenet_cpp.pt"); convert_and_save_model( "inceptionv3_python.pt", "inceptionv3_cpp.pt"); diff --git a/torchvision/csrc/models/googlenet.cpp b/torchvision/csrc/models/googlenet.cpp index 21efcb02798..daf679da00c 100644 --- a/torchvision/csrc/models/googlenet.cpp +++ b/torchvision/csrc/models/googlenet.cpp @@ -84,7 +84,7 @@ torch::Tensor InceptionAuxImpl::forward(at::Tensor x) { } // namespace _googlenetimpl -GoogLeNet::GoogLeNet( +GoogLeNetImpl::GoogLeNetImpl( int64_t num_classes, bool aux_logits, bool transform_input, @@ -142,7 +142,7 @@ GoogLeNet::GoogLeNet( _initialize_weights(); } -void GoogLeNet::_initialize_weights() { +void GoogLeNetImpl::_initialize_weights() { for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) torch::nn::init::normal_(M->weight); @@ -154,7 +154,7 @@ void GoogLeNet::_initialize_weights() { } } -GoogLeNetOutput GoogLeNet::forward(torch::Tensor x) { +GoogLeNetOutput GoogLeNetImpl::forward(torch::Tensor x) { if (transform_input) { auto x_ch0 = torch::unsqueeze(x.select(1, 0), 1) * (0.229 / 0.5) + (0.485 - 0.5) / 0.5; diff --git a/torchvision/csrc/models/googlenet.h b/torchvision/csrc/models/googlenet.h index 3e8e05b88a0..5324e8e758d 100644 --- a/torchvision/csrc/models/googlenet.h +++ b/torchvision/csrc/models/googlenet.h @@ -8,8 +8,8 @@ namespace models { namespace _googlenetimpl { struct BasicConv2dImpl : torch::nn::Module { - torch::nn::Conv2d conv; - torch::nn::BatchNorm bn; + torch::nn::Conv2d conv{nullptr}; + torch::nn::BatchNorm bn{nullptr}; BasicConv2dImpl(torch::nn::Conv2dOptions options); @@ -37,8 +37,8 @@ struct InceptionImpl : torch::nn::Module { TORCH_MODULE(Inception); struct InceptionAuxImpl : torch::nn::Module { - BasicConv2d conv; - torch::nn::Linear fc1, fc2; + BasicConv2d conv{nullptr}; + torch::nn::Linear fc1{nullptr}, fc2{nullptr}; InceptionAuxImpl(int64_t in_channels, int64_t num_classes); @@ -55,7 +55,7 @@ struct GoogLeNetOutput { torch::Tensor aux2; }; -struct GoogLeNet : torch::nn::Module { +struct GoogLeNetImpl : torch::nn::Module { bool aux_logits, transform_input; _googlenetimpl::BasicConv2d conv1{nullptr}, conv2{nullptr}, conv3{nullptr}; @@ -70,7 +70,7 @@ struct GoogLeNet : torch::nn::Module { torch::nn::Dropout dropout{nullptr}; torch::nn::Linear fc{nullptr}; - GoogLeNet( + GoogLeNetImpl( int64_t num_classes = 1000, bool aux_logits = true, bool transform_input = false, @@ -80,6 +80,9 @@ struct GoogLeNet : torch::nn::Module { GoogLeNetOutput forward(torch::Tensor x); }; + +TORCH_MODULE(GoogLeNet); + } // namespace models } // namespace vision diff --git a/torchvision/csrc/models/mobilenet.cpp b/torchvision/csrc/models/mobilenet.cpp index be53f0cff0e..6d7052f401d 100644 --- a/torchvision/csrc/models/mobilenet.cpp +++ b/torchvision/csrc/models/mobilenet.cpp @@ -14,6 +14,7 @@ struct ConvBNReLUImpl : torch::nn::SequentialImpl { int64_t stride = 1, int64_t groups = 1) { auto padding = (kernel_size - 1) / 2; + push_back(torch::nn::Conv2d(Options(in_planes, out_planes, kernel_size) .stride(stride) .padding(padding) @@ -48,13 +49,10 @@ struct InvertedResidualImpl : torch::nn::Module { assert(stride == 1 || stride == 2); auto hidden_dim = int64_t(std::round(input * expand_ratio)); - if (double_compare(expand_ratio, 1)) - // pw + if (!double_compare(expand_ratio, 1)) conv->push_back(ConvBNReLU(input, hidden_dim, 1)); - // dw conv->push_back(ConvBNReLU(hidden_dim, hidden_dim, 3, stride, hidden_dim)); - // pw-linear conv->push_back(torch::nn::Conv2d( Options(hidden_dim, output, 1).stride(1).padding(0).with_bias(false))); conv->push_back(torch::nn::BatchNorm(output)); @@ -100,10 +98,10 @@ MobileNetV2Impl::MobileNetV2Impl(int64_t num_classes, double width_mult) { Block(input_channel, output_channel, stride, setting[0])); input_channel = output_channel; } - - features->push_back(ConvBNReLU(input_channel, this->last_channel, 1)); } + features->push_back(ConvBNReLU(input_channel, this->last_channel, 1)); + classifier->push_back(torch::nn::Dropout(0.2)); classifier->push_back(torch::nn::Linear(this->last_channel, num_classes)); diff --git a/torchvision/csrc/models/mobilenet.h b/torchvision/csrc/models/mobilenet.h index faf5e1597f1..6cb296d820a 100644 --- a/torchvision/csrc/models/mobilenet.h +++ b/torchvision/csrc/models/mobilenet.h @@ -9,7 +9,7 @@ struct MobileNetV2Impl : torch::nn::Module { int64_t last_channel; torch::nn::Sequential features, classifier; - MobileNetV2Impl(int64_t num_classes, double width_mult = 1.0); + MobileNetV2Impl(int64_t num_classes = 1000, double width_mult = 1.0); torch::Tensor forward(torch::Tensor x); }; From e7196e4a91e86a259a4bca4604decc9eb11de28c Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 20 Apr 2019 11:11:14 +0430 Subject: [PATCH 25/48] Updated Alexnet ad VGG --- torchvision/csrc/models/alexnet.cpp | 3 ++- torchvision/csrc/models/vgg.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/torchvision/csrc/models/alexnet.cpp b/torchvision/csrc/models/alexnet.cpp index 9a68a33c489..e29674b706a 100644 --- a/torchvision/csrc/models/alexnet.cpp +++ b/torchvision/csrc/models/alexnet.cpp @@ -36,7 +36,8 @@ AlexNetImpl::AlexNetImpl(int64_t num_classes) { torch::Tensor AlexNetImpl::forward(torch::Tensor x) { x = features->forward(x); - x = x.view({x.size(0), 256 * 6 * 6}); + x = torch::adaptive_avg_pool2d(x, {6, 6}); + x = x.view({x.size(0), -1}); x = classifier->forward(x); return x; diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index f392dbb62ca..f0991b7b085 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -72,6 +72,7 @@ VGGImpl::VGGImpl( torch::Tensor VGGImpl::forward(torch::Tensor x) { x = features->forward(x); + x = torch::adaptive_avg_pool2d(x, {7, 7}); x = x.view({x.size(0), -1}); x = classifier->forward(x); return x; From e3ca869e3e7247c507ff8f4c1ef2d0bd10a8c0e2 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 20 Apr 2019 12:18:59 +0430 Subject: [PATCH 26/48] Updated Densenet, Squeezenet and Inception --- torchvision/csrc/models/densenet.cpp | 4 +- torchvision/csrc/models/inception.cpp | 66 ++++++++++++++------------ torchvision/csrc/models/squeezenet.cpp | 4 +- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index 43876943c38..4c50b509b10 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -148,7 +148,9 @@ DenseNetImpl::DenseNetImpl( torch::Tensor DenseNetImpl::forward(torch::Tensor x) { auto features = this->features->forward(x); auto out = torch::relu_(features); - out = torch::adaptive_avg_pool2d(out, {1, 1}).view({features.size(0), -1}); + out = torch::adaptive_avg_pool2d(out, {1, 1}); + + out = out.view({features.size(0), -1}); out = this->classifier->forward(out); return out; } diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 2986706f9b9..ebb35089d33 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -224,17 +224,19 @@ InceptionAuxImpl::InceptionAuxImpl(int64_t in_channels, int64_t num_classes) } torch::Tensor InceptionAuxImpl::forward(torch::Tensor x) { - // 17 x 17 x 768 + // N x 768 x 17 x 17 x = torch::avg_pool2d(x, 5, 3); - // 5 x 5 x 768 + // N x 768 x 5 x 5 x = conv0->forward(x); - // 5 x 5 x 128 + // N x 128 x 5 x 5 x = conv1->forward(x); - // 1 x 1 x 768 + // N x 768 x 1 x 1 + x = torch::adaptive_avg_pool2d(x, {1, 1}); + // N x 768 x 1 x 1 x = x.view({x.size(0), -1}); - // 768 + // N x 768 x = fc->forward(x); - // 1000 (num_classes) + // N x 1000 (num_classes) return x; } @@ -309,55 +311,57 @@ InceptionV3Output InceptionV3Impl::forward(torch::Tensor x) { x = torch::cat({x_ch0, x_ch1, x_ch2}, 1); } - // 299 x 299 x 3 + // N x 3 x 299 x 299 x = Conv2d_1a_3x3->forward(x); - // 149 x 149 x 32 + // N x 32 x 149 x 149 x = Conv2d_2a_3x3->forward(x); - // 147 x 147 x 32 + // N x 32 x 147 x 147 x = Conv2d_2b_3x3->forward(x); - // 147 x 147 x 64 + // N x 64 x 147 x 147 x = torch::max_pool2d(x, 3, 2); - // 73 x 73 x 64 + // N x 64 x 73 x 73 x = Conv2d_3b_1x1->forward(x); - // 73 x 73 x 80 + // N x 80 x 73 x 73 x = Conv2d_4a_3x3->forward(x); - // 71 x 71 x 192 + // N x 192 x 71 x 71 x = torch::max_pool2d(x, 3, 2); - // 35 x 35 x 192 + // N x 192 x 35 x 35 x = Mixed_5b->forward(x); - // 35 x 35 x 256 + // N x 256 x 35 x 35 x = Mixed_5c->forward(x); - // 35 x 35 x 288 + // N x 288 x 35 x 35 x = Mixed_5d->forward(x); - // 35 x 35 x 288 + // N x 288 x 35 x 35 x = Mixed_6a->forward(x); - // 17 x 17 x 768 + // N x 768 x 17 x 17 x = Mixed_6b->forward(x); - // 17 x 17 x 768 + // N x 768 x 17 x 17 x = Mixed_6c->forward(x); - // 17 x 17 x 768 + // N x 768 x 17 x 17 x = Mixed_6d->forward(x); - // 17 x 17 x 768 + // N x 768 x 17 x 17 x = Mixed_6e->forward(x); - // 17 x 17 x 768 + // N x 768 x 17 x 17 + torch::Tensor aux; if (is_training() && aux_logits) aux = AuxLogits->forward(x); - // 17 x 17 x 768 + + // N x 768 x 17 x 17 x = Mixed_7a->forward(x); - // 8 x 8 x 1280 + // N x 1280 x 8 x 8 x = Mixed_7b->forward(x); - // 8 x 8 x 2048 + // N x 2048 x 8 x 8 x = Mixed_7c->forward(x); - // 8 x 8 x 2048 - x = torch::avg_pool2d(x, 8); - // 1 x 1 x 2048 + // N x 2048 x 8 x 8 + x = torch::adaptive_avg_pool2d(x, {1, 1}); + // N x 2048 x 1 x 1 x = torch::dropout(x, 0.5, is_training()); - // 1 x 1 x 2048 + // N x 2048 x 1 x 1 x = x.view({x.size(0), -1}); - // 2048 + // N x 2048 x = fc->forward(x); - // 1000 (num_classes) + // N x 1000 (num_classes) if (is_training() && aux_logits) return {x, aux}; diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index 4e662dda2f1..c7d553f48da 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -74,7 +74,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) assert(false); } - // Final convolution is initialized differently form the rest + // Final convolution is initialized differently from the rest auto final_conv = torch::nn::Conv2d(torch::nn::Conv2dOptions(512, num_classes, 1)); @@ -102,7 +102,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) torch::Tensor SqueezeNetImpl::forward(torch::Tensor x) { x = features->forward(x); x = classifier->forward(x); - return x.view({x.size(0), num_classes}); + return x.view({x.size(0), -1}); } SqueezeNet1_0Impl::SqueezeNet1_0Impl(int64_t num_classes) From 277a74bad375d18320d1cbf686dd04f0edcfa2ea Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 20 Apr 2019 15:50:09 +0430 Subject: [PATCH 27/48] Added ResNexts and their conversions --- .../csrc/convert_models/convert_models.cpp | 4 ++ torchvision/csrc/models/resnet.cpp | 66 ++++++++++++++----- torchvision/csrc/models/resnet.h | 56 ++++++++++++---- 3 files changed, 95 insertions(+), 31 deletions(-) diff --git a/torchvision/csrc/convert_models/convert_models.cpp b/torchvision/csrc/convert_models/convert_models.cpp index b9c194402c3..bd0eff1cc29 100644 --- a/torchvision/csrc/convert_models/convert_models.cpp +++ b/torchvision/csrc/convert_models/convert_models.cpp @@ -37,6 +37,10 @@ int main(int argc, const char* argv[]) { convert_and_save_model("resnet50_python.pt", "resnet50_cpp.pt"); convert_and_save_model("resnet101_python.pt", "resnet101_cpp.pt"); convert_and_save_model("resnet152_python.pt", "resnet152_cpp.pt"); + convert_and_save_model( + "resnext50_32x4d_python.pt", "resnext50_32x4d_cpp.pt"); + convert_and_save_model( + "resnext101_32x8d_python.pt", "resnext101_32x8d_cpp.pt"); convert_and_save_model( "squeezenet1_0_python.pt", "squeezenet1_0_cpp.pt"); diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index ea94e3253eb..da9a2e25f25 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -3,9 +3,13 @@ namespace vision { namespace models { namespace _resnetimpl { -torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride) { +torch::nn::Conv2d conv3x3( + int64_t in, + int64_t out, + int64_t stride, + int64_t groups) { torch::nn::Conv2dOptions O(in, out, 3); - O.padding(1).stride(stride).with_bias(false); + O.padding(1).stride(stride).groups(groups).with_bias(false); return torch::nn::Conv2d(O); } @@ -22,13 +26,23 @@ BasicBlock::BasicBlock( int64_t inplanes, int64_t planes, int64_t stride, - torch::nn::Sequential downsample) - : stride(stride), - downsample(downsample), - conv1(conv3x3(inplanes, planes, stride)), - conv2(conv3x3(planes, planes)), - bn1(planes), - bn2(planes) { + torch::nn::Sequential downsample, + int64_t groups, + int64_t base_width) + : stride(stride), downsample(downsample) { + if (groups != 1 or base_width != 64) { + std::cerr << "BasicBlock only supports groups=1 and base_width=64" + << std::endl; + assert(false); + } + + // Both conv1 and downsample layers downsample the input when stride != 1 + conv1 = conv3x3(inplanes, planes, stride); + conv2 = conv3x3(planes, planes); + + bn1 = torch::nn::BatchNorm(planes); + bn2 = torch::nn::BatchNorm(planes); + register_module("conv1", conv1); register_module("conv2", conv2); @@ -43,15 +57,21 @@ Bottleneck::Bottleneck( int64_t inplanes, int64_t planes, int64_t stride, - torch::nn::Sequential downsample) - : stride(stride), - downsample(downsample), - conv1(conv1x1(inplanes, planes)), - conv2(conv3x3(planes, planes, stride)), - conv3(conv1x1(planes, planes * expansion)), - bn1(planes), - bn2(planes), - bn3(planes * expansion) { + torch::nn::Sequential downsample, + int64_t groups, + int64_t base_width) + : stride(stride), downsample(downsample) { + auto width = int64_t(planes * (base_width / 64.)) * groups; + + // Both conv2 and downsample layers downsample the input when stride != 1 + conv1 = conv1x1(inplanes, width); + conv2 = conv3x3(width, width, stride, groups); + conv3 = conv1x1(width, planes * expansion); + + bn1 = torch::nn::BatchNorm(width); + bn2 = torch::nn::BatchNorm(width); + bn3 = torch::nn::BatchNorm(planes * expansion); + register_module("conv1", conv1); register_module("conv2", conv2); register_module("conv3", conv3); @@ -115,5 +135,15 @@ ResNet101Impl::ResNet101Impl(int64_t num_classes, bool zero_init_residual) ResNet152Impl::ResNet152Impl(int64_t num_classes, bool zero_init_residual) : ResNetImpl({3, 8, 36, 3}, num_classes, zero_init_residual) {} +ResNext50_32x4dImpl::ResNext50_32x4dImpl( + int64_t num_classes, + bool zero_init_residual) + : ResNetImpl({3, 4, 6, 3}, num_classes, zero_init_residual, 32, 4) {} + +ResNext101_32x8dImpl::ResNext101_32x8dImpl( + int64_t num_classes, + bool zero_init_residual) + : ResNetImpl({3, 4, 23, 3}, num_classes, zero_init_residual, 32, 8) {} + } // namespace models } // namespace vision diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index d06e18c7110..593ba98e185 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -10,7 +10,12 @@ struct ResNetImpl; namespace _resnetimpl { // 3x3 convolution with padding -torch::nn::Conv2d conv3x3(int64_t in, int64_t out, int64_t stride = 1); +torch::nn::Conv2d conv3x3( + int64_t in, + int64_t out, + int64_t stride = 1, + int64_t groups = 1); + // 1x1 convolution torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride = 1); @@ -21,8 +26,8 @@ struct BasicBlock : torch::nn::Module { int64_t stride; torch::nn::Sequential downsample; - torch::nn::Conv2d conv1, conv2; - torch::nn::BatchNorm bn1, bn2; + torch::nn::Conv2d conv1{nullptr}, conv2{nullptr}; + torch::nn::BatchNorm bn1{nullptr}, bn2{nullptr}; static int expansion; @@ -30,7 +35,9 @@ struct BasicBlock : torch::nn::Module { int64_t inplanes, int64_t planes, int64_t stride = 1, - torch::nn::Sequential downsample = nullptr); + torch::nn::Sequential downsample = nullptr, + int64_t groups = 1, + int64_t base_width = 64); torch::Tensor forward(torch::Tensor x); }; @@ -42,8 +49,8 @@ struct Bottleneck : torch::nn::Module { int64_t stride; torch::nn::Sequential downsample; - torch::nn::Conv2d conv1, conv2, conv3; - torch::nn::BatchNorm bn1, bn2, bn3; + torch::nn::Conv2d conv1{nullptr}, conv2{nullptr}, conv3{nullptr}; + torch::nn::BatchNorm bn1{nullptr}, bn2{nullptr}, bn3{nullptr}; static int expansion; @@ -51,7 +58,9 @@ struct Bottleneck : torch::nn::Module { int64_t inplanes, int64_t planes, int64_t stride = 1, - torch::nn::Sequential downsample = nullptr); + torch::nn::Sequential downsample = nullptr, + int64_t groups = 1, + int64_t base_width = 64); torch::Tensor forward(torch::Tensor X); }; @@ -59,7 +68,7 @@ struct Bottleneck : torch::nn::Module { template struct ResNetImpl : torch::nn::Module { - int64_t inplanes; + int64_t groups, base_width, inplanes; torch::nn::Conv2d conv1; torch::nn::BatchNorm bn1; torch::nn::Linear fc; @@ -73,7 +82,9 @@ struct ResNetImpl : torch::nn::Module { ResNetImpl( const std::vector& layers, int64_t num_classes = 1000, - bool zero_init_residual = false); + bool zero_init_residual = false, + int64_t groups = 1, + int64_t width_per_group = 64); torch::Tensor forward(torch::Tensor X); }; @@ -91,12 +102,13 @@ torch::nn::Sequential ResNetImpl::_make_layer( } torch::nn::Sequential layers; - layers->push_back(Block(inplanes, planes, stride, downsample)); + layers->push_back( + Block(inplanes, planes, stride, downsample, groups, base_width)); inplanes = planes * Block::expansion; for (int i = 1; i < blocks; ++i) - layers->push_back(Block(inplanes, planes)); + layers->push_back(Block(inplanes, planes, 1, nullptr, groups, base_width)); return layers; } @@ -105,8 +117,12 @@ template ResNetImpl::ResNetImpl( const std::vector& layers, int64_t num_classes, - bool zero_init_residual) - : inplanes(64), + bool zero_init_residual, + int64_t groups, + int64_t width_per_group) + : groups(groups), + base_width(width_per_group), + inplanes(64), conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( false)), bn1(64), @@ -191,6 +207,18 @@ struct ResNet152Impl : ResNetImpl<_resnetimpl::Bottleneck> { ResNet152Impl(int64_t num_classes = 1000, bool zero_init_residual = false); }; +struct ResNext50_32x4dImpl : ResNetImpl<_resnetimpl::Bottleneck> { + ResNext50_32x4dImpl( + int64_t num_classes = 1000, + bool zero_init_residual = false); +}; + +struct ResNext101_32x8dImpl : ResNetImpl<_resnetimpl::Bottleneck> { + ResNext101_32x8dImpl( + int64_t num_classes = 1000, + bool zero_init_residual = false); +}; + template struct ResNet : torch::nn::ModuleHolder> { using torch::nn::ModuleHolder>::ModuleHolder; @@ -201,6 +229,8 @@ TORCH_MODULE(ResNet34); TORCH_MODULE(ResNet50); TORCH_MODULE(ResNet101); TORCH_MODULE(ResNet152); +TORCH_MODULE(ResNext50_32x4d); +TORCH_MODULE(ResNext101_32x8d); } // namespace models } // namespace vision From ecf6e5c0069c40d372da81ee064c84d691e147fb Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 20 Apr 2019 16:20:25 +0430 Subject: [PATCH 28/48] Added tests for ResNexts --- test/test_cpp_models.py | 2 ++ test/test_models.cpp | 34 +++++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index f5480441227..8fbb14529b1 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -37,6 +37,8 @@ def test_model(model, tensor, func, name): test_model(models.resnet50(pretrained), x, _C.forward_resnet50, 'Resnet50') test_model(models.resnet101(pretrained), x, _C.forward_resnet101, 'Resnet101') test_model(models.resnet152(pretrained), x, _C.forward_resnet152, 'Resnet152') +test_model(models.resnext50_32x4d(pretrained), x, _C.forward_resnext50_32x4d, 'ResNext50_32x4d') +test_model(models.resnext101_32x8d(pretrained), x, _C.forward_resnext101_32x8d, 'ResNext101_32x8d') test_model(models.squeezenet1_0(pretrained), x, _C.forward_squeezenet1_0, 'Squeezenet1.0') test_model(models.squeezenet1_1(pretrained), x, _C.forward_squeezenet1_1, 'Squeezenet1.1') diff --git a/test/test_models.cpp b/test/test_models.cpp index 841de848552..26700d10c80 100644 --- a/test/test_models.cpp +++ b/test/test_models.cpp @@ -52,12 +52,26 @@ torch::Tensor forward_resnet34(const std::string& input_path, torch::Tensor x) { torch::Tensor forward_resnet50(const std::string& input_path, torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_resnet101(const std::string& input_path, torch::Tensor x) { +torch::Tensor forward_resnet101( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_resnet152(const std::string& input_path, torch::Tensor x) { +torch::Tensor forward_resnet152( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } +torch::Tensor forward_resnext50_32x4d( + const std::string& input_path, + torch::Tensor x) { + return forward_model(input_path, x); +} +torch::Tensor forward_resnext101_32x8d( + const std::string& input_path, + torch::Tensor x) { + return forward_model(input_path, x); +} torch::Tensor forward_squeezenet1_0(torch::Tensor x) { return forward_model(input_path, x); @@ -112,9 +126,19 @@ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { m.def("forward_resnet50", &forward_resnet50, "forward_resnet50"); m.def("forward_resnet101", &forward_resnet101, "forward_resnet101"); m.def("forward_resnet152", &forward_resnet152, "forward_resnet152"); - - m.def("forward_squeezenet1_0", &forward_squeezenet1_0, "forward_squeezenet1_0"); - m.def("forward_squeezenet1_1", &forward_squeezenet1_1, "forward_squeezenet1_1"); + m.def( + "forward_resnext50_32x4d", + &forward_resnext50_32x4d, + "forward_resnext50_32x4d"); + m.def( + "forward_resnext101_32x8d", + &forward_resnext101_32x8d, + "forward_resnext101_32x8d"); + + m.def( + "forward_squeezenet1_0", &forward_squeezenet1_0, "forward_squeezenet1_0"); + m.def( + "forward_squeezenet1_1", &forward_squeezenet1_1, "forward_squeezenet1_1"); m.def("forward_densenet121", &forward_densenet121, "forward_densenet121"); m.def("forward_densenet169", &forward_densenet169, "forward_densenet169"); From 6ff7184931b09dc816ab0fa5fd440d72163af366 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Tue, 30 Apr 2019 21:17:36 +0430 Subject: [PATCH 29/48] Wrote tools nessesary to write ShuffleNet --- torchvision/csrc/models/models.h | 1 + torchvision/csrc/models/shufflenetv2.cpp | 88 ++++++++++++++++++++++++ torchvision/csrc/models/shufflenetv2.h | 10 +++ 3 files changed, 99 insertions(+) create mode 100644 torchvision/csrc/models/shufflenetv2.cpp create mode 100644 torchvision/csrc/models/shufflenetv2.h diff --git a/torchvision/csrc/models/models.h b/torchvision/csrc/models/models.h index dada73a2690..55127668be5 100644 --- a/torchvision/csrc/models/models.h +++ b/torchvision/csrc/models/models.h @@ -7,6 +7,7 @@ #include "inception.h" #include "mobilenet.h" #include "resnet.h" +#include "shufflenetv2.h" #include "squeezenet.h" #include "vgg.h" diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp new file mode 100644 index 00000000000..ae6b6f2bd3a --- /dev/null +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -0,0 +1,88 @@ +#include "shufflenetv2.h" + +#include "modelsimpl.h" + +namespace vision { +namespace models { +torch::Tensor channel_shuffle(torch::Tensor x, int64_t groups) { + auto shape = x.sizes(); + auto batchsize = shape[0]; + auto num_channels = shape[1]; + auto height = shape[2]; + auto width = shape[3]; + + auto channels_per_group = num_channels / groups; + + x = x.view({batchsize, groups, channels_per_group, height, width}); + x = torch::transpose(x, 1, 2).contiguous(); + x = x.view({batchsize, -1, height, width}); + + return x; +} + +torch::nn::Conv2d conv11(int64_t input, int64_t output) { + torch::nn::Conv2dOptions opts(input, output, 1); + opts = opts.stride(1).padding(0).with_bias(false); + return torch::nn::Conv2d(opts); +} + +torch::nn::Conv2d conv33(int64_t input, int64_t output, int64_t stride) { + torch::nn::Conv2dOptions opts(input, output, 3); + opts = opts.stride(stride).padding(1).with_bias(false).groups(input); + return torch::nn::Conv2d(opts); +} + +struct InvertedResidual : torch::nn::Module { + int64_t stride; + torch::nn::Sequential branch1{nullptr}, branch2{nullptr}; + + InvertedResidual(int64_t inp, int64_t oup, int64_t stride) : stride(stride) { + if (stride < 1 || stride > 3) { + std::cerr << "illegal stride value'" << std::endl; + assert(false); + } + + auto branch_features = oup / 2; + assert(stride != 1 || inp == branch_features << 1); + + if (stride > 1) { + branch1 = torch::nn::Sequential( + conv33(inp, inp, stride), + torch::nn::BatchNorm(inp), + conv11(inp, branch_features), + torch::nn::BatchNorm(branch_features), + torch::nn::Functional(modelsimpl::relu_)); + } + + branch2 = torch::nn::Sequential( + conv11(stride > 1 ? inp : branch_features, branch_features), + torch::nn::BatchNorm(branch_features), + torch::nn::Functional(modelsimpl::relu_), + conv33(branch_features, branch_features, stride), + torch::nn::BatchNorm(branch_features), + conv11(branch_features, branch_features), + torch::nn::BatchNorm(branch_features), + torch::nn::Functional(modelsimpl::relu_)); + + if (branch1) + register_module("branch1", branch1); + + register_module("branch2", branch2); + } + + torch::Tensor forward(torch::Tensor x) { + torch::Tensor out; + + if (stride == 1) { + auto chunks = x.chunk(2, 1); + out = torch::cat({chunks[0], branch2->forward(chunks[1])}, 1); + } else + out = torch::cat({branch1->forward(x), branch2->forward(x)}, 1); + + out = channel_shuffle(x, 2); + return out; + } +}; + +} // namespace models +} // namespace vision diff --git a/torchvision/csrc/models/shufflenetv2.h b/torchvision/csrc/models/shufflenetv2.h new file mode 100644 index 00000000000..c496c84f9bb --- /dev/null +++ b/torchvision/csrc/models/shufflenetv2.h @@ -0,0 +1,10 @@ +#ifndef SHUFFLENETV2_H +#define SHUFFLENETV2_H + +#include + +namespace vision { +namespace models {} +} // namespace vision + +#endif // SHUFFLENETV2_H From dc9dbbd190e9b3c0876d64506b8b731a21850e46 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Tue, 30 Apr 2019 23:25:21 +0430 Subject: [PATCH 30/48] Added ShuffleNetV2 --- torchvision/csrc/models/modelsimpl.h | 4 + torchvision/csrc/models/shufflenetv2.cpp | 122 ++++++++++++++++++++++- torchvision/csrc/models/shufflenetv2.h | 54 +++++++++- torchvision/csrc/models/squeezenet.cpp | 8 +- 4 files changed, 177 insertions(+), 11 deletions(-) diff --git a/torchvision/csrc/models/modelsimpl.h b/torchvision/csrc/models/modelsimpl.h index 52ec3b73a4c..5d0c9f3467d 100644 --- a/torchvision/csrc/models/modelsimpl.h +++ b/torchvision/csrc/models/modelsimpl.h @@ -31,6 +31,10 @@ inline torch::Tensor max_pool2d( return torch::max_pool2d(x, kernel_size, stride); } +inline bool double_compare(double a, double b) { + return double(std::abs(a - b)) < std::numeric_limits::epsilon(); +}; + } // namespace modelsimpl } // namespace models } // namespace vision diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp index ae6b6f2bd3a..a910ca42b30 100644 --- a/torchvision/csrc/models/shufflenetv2.cpp +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -4,6 +4,9 @@ namespace vision { namespace models { + +using Options = torch::nn::Conv2dOptions; + torch::Tensor channel_shuffle(torch::Tensor x, int64_t groups) { auto shape = x.sizes(); auto batchsize = shape[0]; @@ -21,22 +24,23 @@ torch::Tensor channel_shuffle(torch::Tensor x, int64_t groups) { } torch::nn::Conv2d conv11(int64_t input, int64_t output) { - torch::nn::Conv2dOptions opts(input, output, 1); + Options opts(input, output, 1); opts = opts.stride(1).padding(0).with_bias(false); return torch::nn::Conv2d(opts); } torch::nn::Conv2d conv33(int64_t input, int64_t output, int64_t stride) { - torch::nn::Conv2dOptions opts(input, output, 3); + Options opts(input, output, 3); opts = opts.stride(stride).padding(1).with_bias(false).groups(input); return torch::nn::Conv2d(opts); } -struct InvertedResidual : torch::nn::Module { +struct InvertedResidualImpl : torch::nn::Module { int64_t stride; torch::nn::Sequential branch1{nullptr}, branch2{nullptr}; - InvertedResidual(int64_t inp, int64_t oup, int64_t stride) : stride(stride) { + InvertedResidualImpl(int64_t inp, int64_t oup, int64_t stride) + : stride(stride) { if (stride < 1 || stride > 3) { std::cerr << "illegal stride value'" << std::endl; assert(false); @@ -84,5 +88,115 @@ struct InvertedResidual : torch::nn::Module { } }; +TORCH_MODULE(InvertedResidual); + +static std::unordered_map> channels = { + {0.5, {24, 48, 96, 192, 1024}}, + {1.0, {24, 116, 232, 464, 1024}}, + {1.5, {24, 176, 352, 704, 1024}}, + {2.0, {24, 244, 488, 976, 2048}}}; + +std::vector ShuffleNetV2Impl::_get_stages(double mult) { + for (const auto& P : channels) + if (modelsimpl::double_compare(mult, P.first)) + return P.second; + + std::cerr << "width_mult" << mult << "is not supported" << std::endl; + assert(false); +} + +ShuffleNetV2Impl::ShuffleNetV2Impl( + int64_t num_classes, + int64_t input_size, + double width_mult) { + stage_out_channels = _get_stages(width_mult); + + int64_t input_channels = 3; + auto output_channels = stage_out_channels[0]; + + conv1 = torch::nn::Sequential( + torch::nn::Conv2d(Options(input_channels, output_channels, 3) + .stride(2) + .padding(1) + .with_bias(false)), + torch::nn::BatchNorm(output_channels), + torch::nn::Functional(modelsimpl::relu_)); + + input_channels = output_channels; + std::vector stage_repeats = {4, 8, 4}; + std::vector stages = {&stage2, &stage3, &stage4}; + + for (size_t i = 0; i < stages.size(); ++i) { + auto seq = stages[i]; + auto repeats = stage_repeats[i]; + auto output_channels = stage_out_channels[i + 1]; + + *seq = torch::nn::Sequential( + InvertedResidual(input_channels, output_channels, 2)); + + for (size_t j = 0; j < size_t(repeats - 1); ++j) + seq->get()->push_back( + InvertedResidual(output_channels, output_channels, 1)); + + input_channels = output_channels; + } + + output_channels = stage_out_channels.back(); + conv5 = torch::nn::Sequential( + torch::nn::Conv2d(Options(input_channels, output_channels, 1) + .stride(1) + .padding(0) + .with_bias(false)), + torch::nn::BatchNorm(output_channels), + torch::nn::Functional(modelsimpl::relu_)); + + fc = torch::nn::Linear(output_channels, num_classes); + + register_module("conv1", conv1); + register_module("stage2", stage2); + register_module("stage3", stage3); + register_module("stage4", stage4); + register_module("conv2", conv5); + register_module("fc", fc); +} + +torch::Tensor ShuffleNetV2Impl::forward(torch::Tensor x) { + x = conv1->forward(x); + x = torch::max_pool2d(x, 3, 2, 1); + + x = stage2->forward(x); + x = stage3->forward(x); + x = stage4->forward(x); + x = conv5->forward(x); + + x = x.mean({2, 3}); + x = fc->forward(x); + return x; +} + +ShuffleNetV2_x0_5Impl::ShuffleNetV2_x0_5Impl( + int64_t num_classes, + int64_t input_size, + double width_mult) + : ShuffleNetV2Impl(num_classes, input_size, width_mult) {} + +ShuffleNetV2_x1_0Impl::ShuffleNetV2_x1_0Impl( + int64_t num_classes, + int64_t input_size, + double width_mult) + : ShuffleNetV2Impl(num_classes, input_size, width_mult) {} + +ShuffleNetV2_x1_5Impl::ShuffleNetV2_x1_5Impl( + int64_t num_classes, + int64_t input_size, + double width_mult) + : ShuffleNetV2Impl(num_classes, input_size, width_mult) {} + +ShuffleNetV2_x2_0Impl::ShuffleNetV2_x2_0Impl( + int64_t num_classes, + int64_t input_size, + double width_mult) + : ShuffleNetV2Impl(num_classes, input_size, width_mult) {} + } // namespace models } // namespace vision diff --git a/torchvision/csrc/models/shufflenetv2.h b/torchvision/csrc/models/shufflenetv2.h index c496c84f9bb..94ab49306ad 100644 --- a/torchvision/csrc/models/shufflenetv2.h +++ b/torchvision/csrc/models/shufflenetv2.h @@ -4,7 +4,59 @@ #include namespace vision { -namespace models {} +namespace models { + +struct ShuffleNetV2Impl : torch::nn::Module { + std::vector stage_out_channels; + std::vector _get_stages(double mult); + + torch::nn::Sequential conv1{nullptr}, stage2{nullptr}, stage3{nullptr}, + stage4{nullptr}, conv5{nullptr}; + torch::nn::Linear fc{nullptr}; + + ShuffleNetV2Impl( + int64_t num_classes = 1000, + int64_t input_size = 224, + double width_mult = 1); + + torch::Tensor forward(torch::Tensor x); +}; + +struct ShuffleNetV2_x0_5Impl : ShuffleNetV2Impl { + ShuffleNetV2_x0_5Impl( + int64_t num_classes = 1000, + int64_t input_size = 224, + double width_mult = 1); +}; + +struct ShuffleNetV2_x1_0Impl : ShuffleNetV2Impl { + ShuffleNetV2_x1_0Impl( + int64_t num_classes = 1000, + int64_t input_size = 224, + double width_mult = 1); +}; + +struct ShuffleNetV2_x1_5Impl : ShuffleNetV2Impl { + ShuffleNetV2_x1_5Impl( + int64_t num_classes = 1000, + int64_t input_size = 224, + double width_mult = 1); +}; + +struct ShuffleNetV2_x2_0Impl : ShuffleNetV2Impl { + ShuffleNetV2_x2_0Impl( + int64_t num_classes = 1000, + int64_t input_size = 224, + double width_mult = 1); +}; + +TORCH_MODULE(ShuffleNetV2); +TORCH_MODULE(ShuffleNetV2_x0_5); +TORCH_MODULE(ShuffleNetV2_x1_0); +TORCH_MODULE(ShuffleNetV2_x1_5); +TORCH_MODULE(ShuffleNetV2_x2_0); + +} // namespace models } // namespace vision #endif // SHUFFLENETV2_H diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index c7d553f48da..300415c2396 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -34,11 +34,7 @@ struct Fire : torch::nn::Module { SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) : num_classes(num_classes) { - auto double_compare = [](double a, double b) { - return double(std::abs(a - b)) < std::numeric_limits::epsilon(); - }; - - if (double_compare(version, 1.0)) { + if (modelsimpl::double_compare(version, 1.0)) { features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 96, 7).stride(2)), torch::nn::Functional(modelsimpl::relu_), @@ -53,7 +49,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) Fire(384, 64, 256, 256), torch::nn::Functional(torch::max_pool2d, 3, 2, 0, 1, true), Fire(512, 64, 256, 256)); - } else if (double_compare(version, 1.1)) { + } else if (modelsimpl::double_compare(version, 1.1)) { features = torch::nn::Sequential( torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 3).stride(2)), torch::nn::Functional(modelsimpl::relu_), From d18a30afc72f42a675128034bded474a6f52620f Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Wed, 1 May 2019 18:31:40 +0430 Subject: [PATCH 31/48] Fixed some errors in ShuffleNetV2 --- torchvision/csrc/models/mobilenet.cpp | 8 ++++---- torchvision/csrc/models/shufflenetv2.cpp | 22 +++++++++++----------- torchvision/csrc/models/shufflenetv2.h | 9 ++++----- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/torchvision/csrc/models/mobilenet.cpp b/torchvision/csrc/models/mobilenet.cpp index 6d7052f401d..e38b3d75594 100644 --- a/torchvision/csrc/models/mobilenet.cpp +++ b/torchvision/csrc/models/mobilenet.cpp @@ -31,12 +31,12 @@ struct ConvBNReLUImpl : torch::nn::SequentialImpl { TORCH_MODULE(ConvBNReLU); -struct InvertedResidualImpl : torch::nn::Module { +struct MobileNetInvertedResidualImpl : torch::nn::Module { int64_t stride; bool use_res_connect; torch::nn::Sequential conv; - InvertedResidualImpl( + MobileNetInvertedResidualImpl( int64_t input, int64_t output, int64_t stride, @@ -67,10 +67,10 @@ struct InvertedResidualImpl : torch::nn::Module { } }; -TORCH_MODULE(InvertedResidual); +TORCH_MODULE(MobileNetInvertedResidual); MobileNetV2Impl::MobileNetV2Impl(int64_t num_classes, double width_mult) { - using Block = InvertedResidual; + using Block = MobileNetInvertedResidual; int64_t input_channel = 32; int64_t last_channel = 1280; diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp index a910ca42b30..732396616b0 100644 --- a/torchvision/csrc/models/shufflenetv2.cpp +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -35,11 +35,11 @@ torch::nn::Conv2d conv33(int64_t input, int64_t output, int64_t stride) { return torch::nn::Conv2d(opts); } -struct InvertedResidualImpl : torch::nn::Module { +struct ShuffleNetV2InvertedResidualImpl : torch::nn::Module { int64_t stride; torch::nn::Sequential branch1{nullptr}, branch2{nullptr}; - InvertedResidualImpl(int64_t inp, int64_t oup, int64_t stride) + ShuffleNetV2InvertedResidualImpl(int64_t inp, int64_t oup, int64_t stride) : stride(stride) { if (stride < 1 || stride > 3) { std::cerr << "illegal stride value'" << std::endl; @@ -68,7 +68,7 @@ struct InvertedResidualImpl : torch::nn::Module { torch::nn::BatchNorm(branch_features), torch::nn::Functional(modelsimpl::relu_)); - if (branch1) + if (!branch1.is_empty()) register_module("branch1", branch1); register_module("branch2", branch2); @@ -83,12 +83,12 @@ struct InvertedResidualImpl : torch::nn::Module { } else out = torch::cat({branch1->forward(x), branch2->forward(x)}, 1); - out = channel_shuffle(x, 2); + out = channel_shuffle(out, 2); return out; } }; -TORCH_MODULE(InvertedResidual); +TORCH_MODULE(ShuffleNetV2InvertedResidual); static std::unordered_map> channels = { {0.5, {24, 48, 96, 192, 1024}}, @@ -124,19 +124,19 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( input_channels = output_channels; std::vector stage_repeats = {4, 8, 4}; - std::vector stages = {&stage2, &stage3, &stage4}; + std::vector stages = {stage2, stage3, stage4}; for (size_t i = 0; i < stages.size(); ++i) { - auto seq = stages[i]; + auto& seq = stages[i]; auto repeats = stage_repeats[i]; auto output_channels = stage_out_channels[i + 1]; - *seq = torch::nn::Sequential( - InvertedResidual(input_channels, output_channels, 2)); + seq->push_back( + ShuffleNetV2InvertedResidual(input_channels, output_channels, 2)); for (size_t j = 0; j < size_t(repeats - 1); ++j) - seq->get()->push_back( - InvertedResidual(output_channels, output_channels, 1)); + seq->push_back( + ShuffleNetV2InvertedResidual(output_channels, output_channels, 1)); input_channels = output_channels; } diff --git a/torchvision/csrc/models/shufflenetv2.h b/torchvision/csrc/models/shufflenetv2.h index 94ab49306ad..ed3719fd62f 100644 --- a/torchvision/csrc/models/shufflenetv2.h +++ b/torchvision/csrc/models/shufflenetv2.h @@ -10,8 +10,7 @@ struct ShuffleNetV2Impl : torch::nn::Module { std::vector stage_out_channels; std::vector _get_stages(double mult); - torch::nn::Sequential conv1{nullptr}, stage2{nullptr}, stage3{nullptr}, - stage4{nullptr}, conv5{nullptr}; + torch::nn::Sequential conv1{nullptr}, stage2, stage3, stage4, conv5{nullptr}; torch::nn::Linear fc{nullptr}; ShuffleNetV2Impl( @@ -26,7 +25,7 @@ struct ShuffleNetV2_x0_5Impl : ShuffleNetV2Impl { ShuffleNetV2_x0_5Impl( int64_t num_classes = 1000, int64_t input_size = 224, - double width_mult = 1); + double width_mult = .5); }; struct ShuffleNetV2_x1_0Impl : ShuffleNetV2Impl { @@ -40,14 +39,14 @@ struct ShuffleNetV2_x1_5Impl : ShuffleNetV2Impl { ShuffleNetV2_x1_5Impl( int64_t num_classes = 1000, int64_t input_size = 224, - double width_mult = 1); + double width_mult = 1.5); }; struct ShuffleNetV2_x2_0Impl : ShuffleNetV2Impl { ShuffleNetV2_x2_0Impl( int64_t num_classes = 1000, int64_t input_size = 224, - double width_mult = 1); + double width_mult = 2); }; TORCH_MODULE(ShuffleNetV2); From 45b045252db4a32364025a57cb513bbfee7701aa Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Tue, 7 May 2019 18:55:52 +0430 Subject: [PATCH 32/48] Added conversions for shufflenetv2 --- torchvision/csrc/convert_models/convert_models.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/torchvision/csrc/convert_models/convert_models.cpp b/torchvision/csrc/convert_models/convert_models.cpp index bd0eff1cc29..988bc83e948 100644 --- a/torchvision/csrc/convert_models/convert_models.cpp +++ b/torchvision/csrc/convert_models/convert_models.cpp @@ -59,6 +59,15 @@ int main(int argc, const char* argv[]) { convert_and_save_model( "mobilenetv2_python.pt", "mobilenetv2_cpp.pt"); + convert_and_save_model( + "shufflenetv2_x0_5_python.pt", "shufflenetv2_x0_5_cpp.pt"); + convert_and_save_model( + "shufflenetv2_x1_0_python.pt", "shufflenetv2_x1_0_cpp.pt"); + convert_and_save_model( + "shufflenetv2_x1_5_python.pt", "shufflenetv2_x1_5_cpp.pt"); + convert_and_save_model( + "shufflenetv2_x2_0_python.pt", "shufflenetv2_x2_0_cpp.pt"); + convert_and_save_model("googlenet_python.pt", "googlenet_cpp.pt"); convert_and_save_model( "inceptionv3_python.pt", "inceptionv3_cpp.pt"); From 289be31304887029c0779c7c453554d3f94a429c Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Wed, 8 May 2019 00:10:27 +0430 Subject: [PATCH 33/48] Fixed the errors in test_models.cpp --- test/test_models.cpp | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/test/test_models.cpp b/test/test_models.cpp index 26700d10c80..1219c96ca03 100644 --- a/test/test_models.cpp +++ b/test/test_models.cpp @@ -73,38 +73,56 @@ torch::Tensor forward_resnext101_32x8d( return forward_model(input_path, x); } -torch::Tensor forward_squeezenet1_0(torch::Tensor x) { +torch::Tensor forward_squeezenet1_0( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_squeezenet1_1(torch::Tensor x) { +torch::Tensor forward_squeezenet1_1( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_densenet121(torch::Tensor x) { +torch::Tensor forward_densenet121( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_densenet169(torch::Tensor x) { +torch::Tensor forward_densenet169( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_densenet201(torch::Tensor x) { +torch::Tensor forward_densenet201( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_densenet161(torch::Tensor x) { +torch::Tensor forward_densenet161( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_mobilenetv2(torch::Tensor x) { +torch::Tensor forward_mobilenetv2( + const std::string& input_path, + torch::Tensor x) { return forward_model(input_path, x); } -torch::Tensor forward_googlenet(torch::Tensor x) { +torch::Tensor forward_googlenet( + const std::string& input_path, + torch::Tensor x) { GoogLeNet network; - torch::load(input_path, x); + torch::load(network, input_path); return network->forward(x).output; } -torch::Tensor forward_inceptionv3(torch::Tensor x) { +torch::Tensor forward_inceptionv3( + const std::string& input_path, + torch::Tensor x) { InceptionV3 network; - torch::load(input_path, x); + torch::load(network, input_path); return network->forward(x).output; } From 744790cc1c49bd7133e69843e6ace9fc06aa2404 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Wed, 8 May 2019 16:09:09 +0430 Subject: [PATCH 34/48] Updated setup.py --- setup.py | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index b2adb33f18f..58ac84f4ec0 100644 --- a/setup.py +++ b/setup.py @@ -6,11 +6,14 @@ from setuptools import setup, find_packages from pkg_resources import get_distribution, DistributionNotFound import subprocess - +import distutils.command.clean import glob +import shutil + import torch from torch.utils.cpp_extension import CppExtension, CUDAExtension, CUDA_HOME + def read(*names, **kwargs): with io.open( os.path.join(os.path.dirname(__file__), *names), @@ -74,17 +77,26 @@ def write_version_file(): def get_extensions(): this_dir = os.path.dirname(os.path.abspath(__file__)) - extensions_dir = os.path.join(this_dir, 'test') + test_dir = os.path.join(this_dir, 'test') + extensions_dir = os.path.join(this_dir, 'torchvision', 'csrc') + test_file = glob.glob(os.path.join(test_dir, '*.cpp')) main_file = glob.glob(os.path.join(extensions_dir, '*.cpp')) + source_cpu = glob.glob(os.path.join(extensions_dir, 'cpu', '*.cpp')) + source_cuda = glob.glob(os.path.join(extensions_dir, 'cuda', '*.cu')) - sources = main_file + sources = main_file + source_cpu + test_file extension = CppExtension - extra_compile_args = {'cxx': []} define_macros = [] + if torch.cuda.is_available() and CUDA_HOME is not None: + extension = CUDAExtension + sources += source_cuda + define_macros += [('WITH_CUDA', None)] + sources = [os.path.join(extensions_dir, s) for s in sources] + include_dirs = [extensions_dir] ext_modules = [ @@ -93,12 +105,27 @@ def get_extensions(): sources, include_dirs=include_dirs, define_macros=define_macros, - extra_compile_args=extra_compile_args, ) ] return ext_modules + +class clean(distutils.command.clean.clean): + def run(self): + with open('.gitignore', 'r') as f: + ignores = f.read() + for wildcard in filter(None, ignores.split('\n')): + for filename in glob.glob(wildcard): + try: + os.remove(filename) + except OSError: + shutil.rmtree(filename, ignore_errors=True) + + # It's an old-style class in Python 2.7... + distutils.command.clean.clean.run(self) + + setup( # Metadata name=package_name, @@ -118,7 +145,6 @@ def get_extensions(): extras_require={ "scipy": ["scipy"], }, - ext_modules=get_extensions(), - cmdclass={'build_ext': torch.utils.cpp_extension.BuildExtension} + cmdclass={'build_ext': torch.utils.cpp_extension.BuildExtension, 'clean': clean} ) From 94c16741df53b6b230ce8c0a7e95b91f6052da7f Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Fri, 10 May 2019 23:14:40 +0430 Subject: [PATCH 35/48] Fixed flake8 error on test_cpp_models.py --- test/test_cpp_models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index 8fbb14529b1..40f5717765d 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -4,6 +4,7 @@ from PIL import Image import torchvision.transforms.functional as F + def test_model(model, tensor, func, name): traced_script_module = torch.jit.trace(model, tensor) traced_script_module.save("model.pt") @@ -13,6 +14,7 @@ def test_model(model, tensor, func, name): assert torch.allclose(py_output, cpp_output), 'Output mismatch of ' + name + ' models' + image = Image.open('assets/grace_hopper_517x606.jpg') image = image.resize((224, 224)) x = F.to_tensor(image) From 06b5071d0cc9dd53c8df1937e539d5dbb96df0d8 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 11 May 2019 15:39:46 +0430 Subject: [PATCH 36/48] Changed view to reshape in forward of ResNet --- torchvision/csrc/models/resnet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 593ba98e185..29dfa63f64f 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -181,7 +181,7 @@ torch::Tensor ResNetImpl::forward(torch::Tensor x) { x = layer4->forward(x); x = torch::adaptive_avg_pool2d(x, {1, 1}); - x = x.view({x.size(0), -1}); + x = x.reshape({x.size(0), -1}); x = fc->forward(x); return x; From 4d8959c417330264d6fe84b0c4f2646fea87132b Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 11 May 2019 20:18:51 +0430 Subject: [PATCH 37/48] Updated ShuffleNetV2 --- torchvision/csrc/models/shufflenetv2.cpp | 75 +++++++++--------------- torchvision/csrc/models/shufflenetv2.h | 30 +++------- 2 files changed, 37 insertions(+), 68 deletions(-) diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp index 732396616b0..79fad1a4a13 100644 --- a/torchvision/csrc/models/shufflenetv2.cpp +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -90,29 +90,25 @@ struct ShuffleNetV2InvertedResidualImpl : torch::nn::Module { TORCH_MODULE(ShuffleNetV2InvertedResidual); -static std::unordered_map> channels = { - {0.5, {24, 48, 96, 192, 1024}}, - {1.0, {24, 116, 232, 464, 1024}}, - {1.5, {24, 176, 352, 704, 1024}}, - {2.0, {24, 244, 488, 976, 2048}}}; - -std::vector ShuffleNetV2Impl::_get_stages(double mult) { - for (const auto& P : channels) - if (modelsimpl::double_compare(mult, P.first)) - return P.second; - - std::cerr << "width_mult" << mult << "is not supported" << std::endl; - assert(false); -} - ShuffleNetV2Impl::ShuffleNetV2Impl( - int64_t num_classes, - int64_t input_size, - double width_mult) { - stage_out_channels = _get_stages(width_mult); + const std::vector& stage_repeats, + const std::vector& stage_out_channels, + int64_t num_classes) { + if (stage_repeats.size() != 3) { + std::cerr << "expected stage_repeats as vector of 3 positive ints" + << std::endl; + assert(false); + } + + if (stage_out_channels.size() != 5) { + std::cerr << "expected stage_out_channels as vector of 5 positive ints" + << std::endl; + assert(false); + } + _stage_out_channels = stage_out_channels; int64_t input_channels = 3; - auto output_channels = stage_out_channels[0]; + auto output_channels = _stage_out_channels[0]; conv1 = torch::nn::Sequential( torch::nn::Conv2d(Options(input_channels, output_channels, 3) @@ -123,13 +119,12 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( torch::nn::Functional(modelsimpl::relu_)); input_channels = output_channels; - std::vector stage_repeats = {4, 8, 4}; std::vector stages = {stage2, stage3, stage4}; for (size_t i = 0; i < stages.size(); ++i) { auto& seq = stages[i]; auto repeats = stage_repeats[i]; - auto output_channels = stage_out_channels[i + 1]; + auto output_channels = _stage_out_channels[i + 1]; seq->push_back( ShuffleNetV2InvertedResidual(input_channels, output_channels, 2)); @@ -141,7 +136,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( input_channels = output_channels; } - output_channels = stage_out_channels.back(); + output_channels = _stage_out_channels.back(); conv5 = torch::nn::Sequential( torch::nn::Conv2d(Options(input_channels, output_channels, 1) .stride(1) @@ -174,29 +169,17 @@ torch::Tensor ShuffleNetV2Impl::forward(torch::Tensor x) { return x; } -ShuffleNetV2_x0_5Impl::ShuffleNetV2_x0_5Impl( - int64_t num_classes, - int64_t input_size, - double width_mult) - : ShuffleNetV2Impl(num_classes, input_size, width_mult) {} - -ShuffleNetV2_x1_0Impl::ShuffleNetV2_x1_0Impl( - int64_t num_classes, - int64_t input_size, - double width_mult) - : ShuffleNetV2Impl(num_classes, input_size, width_mult) {} - -ShuffleNetV2_x1_5Impl::ShuffleNetV2_x1_5Impl( - int64_t num_classes, - int64_t input_size, - double width_mult) - : ShuffleNetV2Impl(num_classes, input_size, width_mult) {} - -ShuffleNetV2_x2_0Impl::ShuffleNetV2_x2_0Impl( - int64_t num_classes, - int64_t input_size, - double width_mult) - : ShuffleNetV2Impl(num_classes, input_size, width_mult) {} +ShuffleNetV2_x0_5Impl::ShuffleNetV2_x0_5Impl(int64_t num_classes) + : ShuffleNetV2Impl({4, 8, 4}, {24, 48, 96, 192, 1024}, num_classes) {} + +ShuffleNetV2_x1_0Impl::ShuffleNetV2_x1_0Impl(int64_t num_classes) + : ShuffleNetV2Impl({4, 8, 4}, {24, 116, 232, 464, 1024}, num_classes) {} + +ShuffleNetV2_x1_5Impl::ShuffleNetV2_x1_5Impl(int64_t num_classes) + : ShuffleNetV2Impl({4, 8, 4}, {24, 176, 352, 704, 1024}, num_classes) {} + +ShuffleNetV2_x2_0Impl::ShuffleNetV2_x2_0Impl(int64_t num_classes) + : ShuffleNetV2Impl({4, 8, 4}, {24, 244, 488, 976, 2048}, num_classes) {} } // namespace models } // namespace vision diff --git a/torchvision/csrc/models/shufflenetv2.h b/torchvision/csrc/models/shufflenetv2.h index ed3719fd62f..ddb1bccbb14 100644 --- a/torchvision/csrc/models/shufflenetv2.h +++ b/torchvision/csrc/models/shufflenetv2.h @@ -7,46 +7,32 @@ namespace vision { namespace models { struct ShuffleNetV2Impl : torch::nn::Module { - std::vector stage_out_channels; - std::vector _get_stages(double mult); - + std::vector _stage_out_channels; torch::nn::Sequential conv1{nullptr}, stage2, stage3, stage4, conv5{nullptr}; torch::nn::Linear fc{nullptr}; ShuffleNetV2Impl( - int64_t num_classes = 1000, - int64_t input_size = 224, - double width_mult = 1); + const std::vector& stage_repeats, + const std::vector& stage_out_channels, + int64_t num_classes = 1000); torch::Tensor forward(torch::Tensor x); }; struct ShuffleNetV2_x0_5Impl : ShuffleNetV2Impl { - ShuffleNetV2_x0_5Impl( - int64_t num_classes = 1000, - int64_t input_size = 224, - double width_mult = .5); + ShuffleNetV2_x0_5Impl(int64_t num_classes = 1000); }; struct ShuffleNetV2_x1_0Impl : ShuffleNetV2Impl { - ShuffleNetV2_x1_0Impl( - int64_t num_classes = 1000, - int64_t input_size = 224, - double width_mult = 1); + ShuffleNetV2_x1_0Impl(int64_t num_classes = 1000); }; struct ShuffleNetV2_x1_5Impl : ShuffleNetV2Impl { - ShuffleNetV2_x1_5Impl( - int64_t num_classes = 1000, - int64_t input_size = 224, - double width_mult = 1.5); + ShuffleNetV2_x1_5Impl(int64_t num_classes = 1000); }; struct ShuffleNetV2_x2_0Impl : ShuffleNetV2Impl { - ShuffleNetV2_x2_0Impl( - int64_t num_classes = 1000, - int64_t input_size = 224, - double width_mult = 2); + ShuffleNetV2_x2_0Impl(int64_t num_classes = 1000); }; TORCH_MODULE(ShuffleNetV2); From 2a0d007211e190bae9975ff10e660ca73a1feb97 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Fri, 17 May 2019 21:24:06 +0430 Subject: [PATCH 38/48] Split extensions to tests and ops --- setup.py | 12 ++++++-- test/test_cpp_models.py | 52 ++++++++++++++++---------------- torchvision/csrc/models/resnet.h | 7 ++--- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/setup.py b/setup.py index 4d607705616..8f245128fa0 100644 --- a/setup.py +++ b/setup.py @@ -79,14 +79,14 @@ def get_extensions(): this_dir = os.path.dirname(os.path.abspath(__file__)) test_dir = os.path.join(this_dir, 'test') - extensions_dir = os.path.join(this_dir, 'torchvision', 'csrc') + tests = glob.glob(os.path.join(test_dir, '*.cpp')) - test_file = glob.glob(os.path.join(test_dir, '*.cpp')) + extensions_dir = os.path.join(this_dir, 'torchvision', 'csrc') main_file = glob.glob(os.path.join(extensions_dir, '*.cpp')) source_cpu = glob.glob(os.path.join(extensions_dir, 'cpu', '*.cpp')) source_cuda = glob.glob(os.path.join(extensions_dir, 'cuda', '*.cu')) - sources = main_file + source_cpu + test_file + sources = main_file + source_cpu extension = CppExtension define_macros = [] @@ -106,6 +106,12 @@ def get_extensions(): sources, include_dirs=include_dirs, define_macros=define_macros, + ), + extension( + 'torchvision._C_tests', + tests, + include_dirs=include_dirs, + define_macros=define_macros, ) ] diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index 40f5717765d..f3028f01302 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -1,5 +1,5 @@ import torch -from torchvision import models, transforms, _C +from torchvision import models, transforms, _C_tests from PIL import Image import torchvision.transforms.functional as F @@ -22,35 +22,35 @@ def test_model(model, tensor, func, name): pretrained = False -test_model(models.alexnet(pretrained), x, _C.forward_alexnet, 'Alexnet') +test_model(models.alexnet(pretrained), x, _C_tests.forward_alexnet, 'Alexnet') -test_model(models.vgg11(pretrained), x, _C.forward_vgg11, 'VGG11') -test_model(models.vgg13(pretrained), x, _C.forward_vgg13, 'VGG13') -test_model(models.vgg16(pretrained), x, _C.forward_vgg16, 'VGG16') -test_model(models.vgg19(pretrained), x, _C.forward_vgg19, 'VGG19') +test_model(models.vgg11(pretrained), x, _C_tests.forward_vgg11, 'VGG11') +test_model(models.vgg13(pretrained), x, _C_tests.forward_vgg13, 'VGG13') +test_model(models.vgg16(pretrained), x, _C_tests.forward_vgg16, 'VGG16') +test_model(models.vgg19(pretrained), x, _C_tests.forward_vgg19, 'VGG19') -test_model(models.vgg11_bn(pretrained), x, _C.forward_vgg11bn, 'VGG11BN') -test_model(models.vgg13_bn(pretrained), x, _C.forward_vgg13bn, 'VGG13BN') -test_model(models.vgg16_bn(pretrained), x, _C.forward_vgg16bn, 'VGG16BN') -test_model(models.vgg19_bn(pretrained), x, _C.forward_vgg19bn, 'VGG19BN') +test_model(models.vgg11_bn(pretrained), x, _C_tests.forward_vgg11bn, 'VGG11BN') +test_model(models.vgg13_bn(pretrained), x, _C_tests.forward_vgg13bn, 'VGG13BN') +test_model(models.vgg16_bn(pretrained), x, _C_tests.forward_vgg16bn, 'VGG16BN') +test_model(models.vgg19_bn(pretrained), x, _C_tests.forward_vgg19bn, 'VGG19BN') -test_model(models.resnet18(pretrained), x, _C.forward_resnet18, 'Resnet18') -test_model(models.resnet34(pretrained), x, _C.forward_resnet34, 'Resnet34') -test_model(models.resnet50(pretrained), x, _C.forward_resnet50, 'Resnet50') -test_model(models.resnet101(pretrained), x, _C.forward_resnet101, 'Resnet101') -test_model(models.resnet152(pretrained), x, _C.forward_resnet152, 'Resnet152') -test_model(models.resnext50_32x4d(pretrained), x, _C.forward_resnext50_32x4d, 'ResNext50_32x4d') -test_model(models.resnext101_32x8d(pretrained), x, _C.forward_resnext101_32x8d, 'ResNext101_32x8d') +test_model(models.resnet18(pretrained), x, _C_tests.forward_resnet18, 'Resnet18') +test_model(models.resnet34(pretrained), x, _C_tests.forward_resnet34, 'Resnet34') +test_model(models.resnet50(pretrained), x, _C_tests.forward_resnet50, 'Resnet50') +test_model(models.resnet101(pretrained), x, _C_tests.forward_resnet101, 'Resnet101') +test_model(models.resnet152(pretrained), x, _C_tests.forward_resnet152, 'Resnet152') +test_model(models.resnext50_32x4d(pretrained), x, _C_tests.forward_resnext50_32x4d, 'ResNext50_32x4d') +test_model(models.resnext101_32x8d(pretrained), x, _C_tests.forward_resnext101_32x8d, 'ResNext101_32x8d') -test_model(models.squeezenet1_0(pretrained), x, _C.forward_squeezenet1_0, 'Squeezenet1.0') -test_model(models.squeezenet1_1(pretrained), x, _C.forward_squeezenet1_1, 'Squeezenet1.1') +test_model(models.squeezenet1_0(pretrained), x, _C_tests.forward_squeezenet1_0, 'Squeezenet1.0') +test_model(models.squeezenet1_1(pretrained), x, _C_tests.forward_squeezenet1_1, 'Squeezenet1.1') -test_model(models.densenet121(pretrained), x, _C.forward_densenet121, 'Densenet121') -test_model(models.densenet169(pretrained), x, _C.forward_densenet169, 'Densenet169') -test_model(models.densenet201(pretrained), x, _C.forward_densenet201, 'Densenet201') -test_model(models.densenet161(pretrained), x, _C.forward_densenet161, 'Densenet161') +test_model(models.densenet121(pretrained), x, _C_tests.forward_densenet121, 'Densenet121') +test_model(models.densenet169(pretrained), x, _C_tests.forward_densenet169, 'Densenet169') +test_model(models.densenet201(pretrained), x, _C_tests.forward_densenet201, 'Densenet201') +test_model(models.densenet161(pretrained), x, _C_tests.forward_densenet161, 'Densenet161') -test_model(models.mobilenet_v2(pretrained), x, _C.forward_mobilenetv2, 'MobileNet') +test_model(models.mobilenet_v2(pretrained), x, _C_tests.forward_mobilenetv2, 'MobileNet') -test_model(models.googlenet(pretrained), x, _C.forward_googlenet, 'GoogLeNet') -test_model(models.inception_v3(pretrained), x, _C.forward_inceptionv3, 'Inceptionv3') +test_model(models.googlenet(pretrained), x, _C_tests.forward_googlenet, 'GoogLeNet') +test_model(models.inception_v3(pretrained), x, _C_tests.forward_inceptionv3, 'Inceptionv3') diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 29dfa63f64f..a01c2da7dc5 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -159,12 +159,9 @@ ResNetImpl::ResNetImpl( // https://arxiv.org/abs/1706.02677 if (zero_init_residual) for (auto& module : modules(/*include_self=*/false)) { - if (_resnetimpl::Bottleneck* M = - dynamic_cast<_resnetimpl::Bottleneck*>(module.get())) + if (auto* M = dynamic_cast<_resnetimpl::Bottleneck*>(module.get())) torch::nn::init::constant_(M->bn3->weight, 0); - else if ( - _resnetimpl::BasicBlock* M = - dynamic_cast<_resnetimpl::BasicBlock*>(module.get())) + else if (auto* M = dynamic_cast<_resnetimpl::BasicBlock*>(module.get())) torch::nn::init::constant_(M->bn2->weight, 0); } } From fcd9e8c75f0e7c423682c141cb8d8e0ae6a99a73 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 18 May 2019 01:08:40 +0430 Subject: [PATCH 39/48] Fixed test extension --- setup.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8f245128fa0..6086357d66a 100644 --- a/setup.py +++ b/setup.py @@ -79,7 +79,13 @@ def get_extensions(): this_dir = os.path.dirname(os.path.abspath(__file__)) test_dir = os.path.join(this_dir, 'test') - tests = glob.glob(os.path.join(test_dir, '*.cpp')) + models_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'models') + test_file = glob.glob(os.path.join(test_dir, '*.cpp')) + source_models = glob.glob(os.path.join(models_dir, '*.cpp')) + + test_file = [os.path.join(test_dir, s) for s in test_file] + source_models = [os.path.join(models_dir, s) for s in source_models] + tests = test_file + source_models extensions_dir = os.path.join(this_dir, 'torchvision', 'csrc') main_file = glob.glob(os.path.join(extensions_dir, '*.cpp')) From 65b207577ddf8ef0ea990111a7270d42e34859e4 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 18 May 2019 01:31:04 +0430 Subject: [PATCH 40/48] Fixed image path in test_cpp_models.py --- test/test_cpp_models.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index f3028f01302..88c8075f8ad 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -1,4 +1,5 @@ import torch +import os from torchvision import models, transforms, _C_tests from PIL import Image @@ -6,6 +7,7 @@ def test_model(model, tensor, func, name): + model.eval() traced_script_module = torch.jit.trace(model, tensor) traced_script_module.save("model.pt") @@ -15,7 +17,8 @@ def test_model(model, tensor, func, name): assert torch.allclose(py_output, cpp_output), 'Output mismatch of ' + name + ' models' -image = Image.open('assets/grace_hopper_517x606.jpg') +image_path = os.path.join(os.getcwd(), 'assets', 'grace_hopper_517x606.jpg') +image = Image.open(image_path) image = image.resize((224, 224)) x = F.to_tensor(image) x = x.view(1, 3, 224, 224) From 975f4944067cffe9fc15577e54695396278fffeb Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 18 May 2019 02:01:53 +0430 Subject: [PATCH 41/48] Fixed image path in test_cpp_models.py --- test/test_cpp_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index 88c8075f8ad..c92543708dd 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -17,7 +17,8 @@ def test_model(model, tensor, func, name): assert torch.allclose(py_output, cpp_output), 'Output mismatch of ' + name + ' models' -image_path = os.path.join(os.getcwd(), 'assets', 'grace_hopper_517x606.jpg') +image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'assets', 'grace_hopper_517x606.jpg') image = Image.open(image_path) image = image.resize((224, 224)) x = F.to_tensor(image) From 159e5e76e83d26834d49b90478f5a4077cb6d3fd Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Sat, 18 May 2019 02:22:53 +0430 Subject: [PATCH 42/48] Fixed a few things in test_cpp_models.py --- test/test_cpp_models.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index c92543708dd..8791857ccc2 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -17,8 +17,7 @@ def test_model(model, tensor, func, name): assert torch.allclose(py_output, cpp_output), 'Output mismatch of ' + name + ' models' -image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'assets', 'grace_hopper_517x606.jpg') +image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'grace_hopper_517x606.jpg') image = Image.open(image_path) image = image.resize((224, 224)) x = F.to_tensor(image) @@ -43,8 +42,8 @@ def test_model(model, tensor, func, name): test_model(models.resnet50(pretrained), x, _C_tests.forward_resnet50, 'Resnet50') test_model(models.resnet101(pretrained), x, _C_tests.forward_resnet101, 'Resnet101') test_model(models.resnet152(pretrained), x, _C_tests.forward_resnet152, 'Resnet152') -test_model(models.resnext50_32x4d(pretrained), x, _C_tests.forward_resnext50_32x4d, 'ResNext50_32x4d') -test_model(models.resnext101_32x8d(pretrained), x, _C_tests.forward_resnext101_32x8d, 'ResNext101_32x8d') +test_model(models.resnext50_32x4d(), x, _C_tests.forward_resnext50_32x4d, 'ResNext50_32x4d') +test_model(models.resnext101_32x8d(), x, _C_tests.forward_resnext101_32x8d, 'ResNext101_32x8d') test_model(models.squeezenet1_0(pretrained), x, _C_tests.forward_squeezenet1_0, 'Squeezenet1.0') test_model(models.squeezenet1_1(pretrained), x, _C_tests.forward_squeezenet1_1, 'Squeezenet1.1') @@ -57,4 +56,11 @@ def test_model(model, tensor, func, name): test_model(models.mobilenet_v2(pretrained), x, _C_tests.forward_mobilenetv2, 'MobileNet') test_model(models.googlenet(pretrained), x, _C_tests.forward_googlenet, 'GoogLeNet') + +image = Image.open(image_path) +image = image.resize((299, 299)) +x = F.to_tensor(image) +x = x.view(1, 3, 299, 299) +x = torch.cat([x, x], 0) + test_model(models.inception_v3(pretrained), x, _C_tests.forward_inceptionv3, 'Inceptionv3') From b25b3c22af74a8814f14235d230d2f83679e06ba Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Mon, 20 May 2019 03:31:16 +0430 Subject: [PATCH 43/48] Put the test models in evaluation mode --- test/test_models.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_models.cpp b/test/test_models.cpp index 1219c96ca03..17e76e8c9d1 100644 --- a/test/test_models.cpp +++ b/test/test_models.cpp @@ -10,6 +10,7 @@ template torch::Tensor forward_model(const std::string& input_path, torch::Tensor x) { Model network; torch::load(network, input_path); + network->eval(); return network->forward(x); } @@ -116,6 +117,7 @@ torch::Tensor forward_googlenet( torch::Tensor x) { GoogLeNet network; torch::load(network, input_path); + network->eval(); return network->forward(x).output; } torch::Tensor forward_inceptionv3( @@ -123,6 +125,7 @@ torch::Tensor forward_inceptionv3( torch::Tensor x) { InceptionV3 network; torch::load(network, input_path); + network->eval(); return network->forward(x).output; } From 930d0b37c4f2444a71d9c166916d2d3372a3399f Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Thu, 23 May 2019 22:11:07 +0430 Subject: [PATCH 44/48] Fixed registering error in GoogLeNet --- torchvision/csrc/models/googlenet.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/torchvision/csrc/models/googlenet.cpp b/torchvision/csrc/models/googlenet.cpp index daf679da00c..c053b65b4d6 100644 --- a/torchvision/csrc/models/googlenet.cpp +++ b/torchvision/csrc/models/googlenet.cpp @@ -43,6 +43,11 @@ InceptionImpl::InceptionImpl( branch4->push_back( torch::nn::Functional(torch::max_pool2d, 3, 1, 1, 1, true)); branch4->push_back(BasicConv2d(Options(in_channels, pool_proj, 1))); + + register_module("branch1", branch1); + register_module("branch2", branch2); + register_module("branch3", branch3); + register_module("branch4", branch4); } torch::Tensor InceptionImpl::forward(torch::Tensor x) { @@ -145,12 +150,15 @@ GoogLeNetImpl::GoogLeNetImpl( void GoogLeNetImpl::_initialize_weights() { for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) - torch::nn::init::normal_(M->weight); + torch::nn::init::normal_(M->weight); // Note: used instead of truncated + // normal initialization + else if (auto M = dynamic_cast(module.get())) + torch::nn::init::normal_(M->weight); // Note: used instead of truncated + // normal initialization else if (auto M = dynamic_cast(module.get())) { torch::nn::init::ones_(M->weight); torch::nn::init::zeros_(M->bias); - } else if (auto M = dynamic_cast(module.get())) - torch::nn::init::normal_(M->weight); + } } } From 4dff6b8bb51486cfb7534e90198a34c5f8c4d9d6 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Thu, 6 Jun 2019 18:16:00 +0430 Subject: [PATCH 45/48] Updated setup.py --- setup.py | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/setup.py b/setup.py index 6086357d66a..5e87a7a099a 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ def get_dist(pkgname): return None -version = '0.2.3a0' +version = '0.3.0a0' sha = 'Unknown' package_name = os.getenv('TORCHVISION_PACKAGE_NAME', 'torchvision') @@ -56,6 +56,9 @@ def write_version_file(): with open(version_path, 'w') as f: f.write("__version__ = '{}'\n".format(version)) f.write("git_version = {}\n".format(repr(sha))) + f.write("from torchvision import _C\n") + f.write("if hasattr(_C, 'CUDA_VERSION'):\n") + f.write(" cuda = _C.CUDA_VERSION\n") write_version_file() @@ -77,6 +80,14 @@ def write_version_file(): def get_extensions(): this_dir = os.path.dirname(os.path.abspath(__file__)) + extensions_dir = os.path.join(this_dir, 'torchvision', 'csrc') + + main_file = glob.glob(os.path.join(extensions_dir, '*.cpp')) + source_cpu = glob.glob(os.path.join(extensions_dir, 'cpu', '*.cpp')) + source_cuda = glob.glob(os.path.join(extensions_dir, 'cuda', '*.cu')) + + sources = main_file + source_cpu + extension = CppExtension test_dir = os.path.join(this_dir, 'test') models_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'models') @@ -87,24 +98,27 @@ def get_extensions(): source_models = [os.path.join(models_dir, s) for s in source_models] tests = test_file + source_models - extensions_dir = os.path.join(this_dir, 'torchvision', 'csrc') - main_file = glob.glob(os.path.join(extensions_dir, '*.cpp')) - source_cpu = glob.glob(os.path.join(extensions_dir, 'cpu', '*.cpp')) - source_cuda = glob.glob(os.path.join(extensions_dir, 'cuda', '*.cu')) - - sources = main_file + source_cpu - extension = CppExtension - define_macros = [] - if torch.cuda.is_available() and CUDA_HOME is not None: + extra_compile_args = {} + if (torch.cuda.is_available() and CUDA_HOME is not None) or os.getenv('FORCE_CUDA', '0') == '1': extension = CUDAExtension sources += source_cuda define_macros += [('WITH_CUDA', None)] + nvcc_flags = os.getenv('NVCC_FLAGS', '') + if nvcc_flags == '': + nvcc_flags = [] + else: + nvcc_flags = nvcc_flags.split(' ') + extra_compile_args = { + 'cxx': ['-O0'], + 'nvcc': nvcc_flags, + } sources = [os.path.join(extensions_dir, s) for s in sources] include_dirs = [extensions_dir] + tests_include_dirs = [test_dir, models_dir] ext_modules = [ extension( @@ -112,12 +126,14 @@ def get_extensions(): sources, include_dirs=include_dirs, define_macros=define_macros, + extra_compile_args=extra_compile_args, ), extension( 'torchvision._C_tests', tests, - include_dirs=include_dirs, + include_dirs=tests_include_dirs, define_macros=define_macros, + extra_compile_args=extra_compile_args, ) ] From 6acb64e5085ee541536fcd336b88d42497656fb2 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Mon, 10 Jun 2019 04:32:00 +0430 Subject: [PATCH 46/48] write test_cpp_models.py with unittest --- test/test_cpp_models.py | 126 ++++++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 36 deletions(-) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index 8791857ccc2..d81b0f55fb1 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -1,5 +1,6 @@ import torch import os +import unittest from torchvision import models, transforms, _C_tests from PIL import Image @@ -17,50 +18,103 @@ def test_model(model, tensor, func, name): assert torch.allclose(py_output, cpp_output), 'Output mismatch of ' + name + ' models' -image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'grace_hopper_517x606.jpg') -image = Image.open(image_path) -image = image.resize((224, 224)) -x = F.to_tensor(image) -x = x.view(1, 3, 224, 224) +def read_image1(): + image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'grace_hopper_517x606.jpg') + image = Image.open(image_path) + image = image.resize((224, 224)) + x = F.to_tensor(image) + return x.view(1, 3, 224, 224) -pretrained = False -test_model(models.alexnet(pretrained), x, _C_tests.forward_alexnet, 'Alexnet') +def read_image2(): + image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'grace_hopper_517x606.jpg') + image = Image.open(image_path) + image = image.resize((299, 299)) + x = F.to_tensor(image) + x = x.view(1, 3, 299, 299) + return torch.cat([x, x], 0) -test_model(models.vgg11(pretrained), x, _C_tests.forward_vgg11, 'VGG11') -test_model(models.vgg13(pretrained), x, _C_tests.forward_vgg13, 'VGG13') -test_model(models.vgg16(pretrained), x, _C_tests.forward_vgg16, 'VGG16') -test_model(models.vgg19(pretrained), x, _C_tests.forward_vgg19, 'VGG19') -test_model(models.vgg11_bn(pretrained), x, _C_tests.forward_vgg11bn, 'VGG11BN') -test_model(models.vgg13_bn(pretrained), x, _C_tests.forward_vgg13bn, 'VGG13BN') -test_model(models.vgg16_bn(pretrained), x, _C_tests.forward_vgg16bn, 'VGG16BN') -test_model(models.vgg19_bn(pretrained), x, _C_tests.forward_vgg19bn, 'VGG19BN') +class Tester(unittest.TestCase): + pretrained = False + image = read_image1() -test_model(models.resnet18(pretrained), x, _C_tests.forward_resnet18, 'Resnet18') -test_model(models.resnet34(pretrained), x, _C_tests.forward_resnet34, 'Resnet34') -test_model(models.resnet50(pretrained), x, _C_tests.forward_resnet50, 'Resnet50') -test_model(models.resnet101(pretrained), x, _C_tests.forward_resnet101, 'Resnet101') -test_model(models.resnet152(pretrained), x, _C_tests.forward_resnet152, 'Resnet152') -test_model(models.resnext50_32x4d(), x, _C_tests.forward_resnext50_32x4d, 'ResNext50_32x4d') -test_model(models.resnext101_32x8d(), x, _C_tests.forward_resnext101_32x8d, 'ResNext101_32x8d') + def test_alexnet(self): + test_model(models.alexnet(self.pretrained), self.image, _C_tests.forward_alexnet, 'Alexnet') -test_model(models.squeezenet1_0(pretrained), x, _C_tests.forward_squeezenet1_0, 'Squeezenet1.0') -test_model(models.squeezenet1_1(pretrained), x, _C_tests.forward_squeezenet1_1, 'Squeezenet1.1') + def test_vgg11(self): + test_model(models.vgg11(self.pretrained), self.image, _C_tests.forward_vgg11, 'VGG11') -test_model(models.densenet121(pretrained), x, _C_tests.forward_densenet121, 'Densenet121') -test_model(models.densenet169(pretrained), x, _C_tests.forward_densenet169, 'Densenet169') -test_model(models.densenet201(pretrained), x, _C_tests.forward_densenet201, 'Densenet201') -test_model(models.densenet161(pretrained), x, _C_tests.forward_densenet161, 'Densenet161') + def test_vgg13(self): + test_model(models.vgg13(self.pretrained), self.image, _C_tests.forward_vgg13, 'VGG13') -test_model(models.mobilenet_v2(pretrained), x, _C_tests.forward_mobilenetv2, 'MobileNet') + def test_vgg16(self): + test_model(models.vgg16(self.pretrained), self.image, _C_tests.forward_vgg16, 'VGG16') -test_model(models.googlenet(pretrained), x, _C_tests.forward_googlenet, 'GoogLeNet') + def test_vgg19(self): + test_model(models.vgg19(self.pretrained), self.image, _C_tests.forward_vgg19, 'VGG19') -image = Image.open(image_path) -image = image.resize((299, 299)) -x = F.to_tensor(image) -x = x.view(1, 3, 299, 299) -x = torch.cat([x, x], 0) + def test_vgg11_bn(self): + test_model(models.vgg11_bn(self.pretrained), self.image, _C_tests.forward_vgg11bn, 'VGG11BN') -test_model(models.inception_v3(pretrained), x, _C_tests.forward_inceptionv3, 'Inceptionv3') + def test_vgg13_bn(self): + test_model(models.vgg13_bn(self.pretrained), self.image, _C_tests.forward_vgg13bn, 'VGG13BN') + + def test_vgg16_bn(self): + test_model(models.vgg16_bn(self.pretrained), self.image, _C_tests.forward_vgg16bn, 'VGG16BN') + + def test_vgg19_bn(self): + test_model(models.vgg19_bn(self.pretrained), self.image, _C_tests.forward_vgg19bn, 'VGG19BN') + + def test_resnet18(self): + test_model(models.resnet18(self.pretrained), self.image, _C_tests.forward_resnet18, 'Resnet18') + + def test_resnet34(self): + test_model(models.resnet34(self.pretrained), self.image, _C_tests.forward_resnet34, 'Resnet34') + + def test_resnet50(self): + test_model(models.resnet50(self.pretrained), self.image, _C_tests.forward_resnet50, 'Resnet50') + + def test_resnet101(self): + test_model(models.resnet101(self.pretrained), self.image, _C_tests.forward_resnet101, 'Resnet101') + + def test_resnet152(self): + test_model(models.resnet152(self.pretrained), self.image, _C_tests.forward_resnet152, 'Resnet152') + + def test_resnext50_32x4d(self): + test_model(models.resnext50_32x4d(), self.image, _C_tests.forward_resnext50_32x4d, 'ResNext50_32x4d') + + def test_resnext101_32x8d(self): + test_model(models.resnext101_32x8d(), self.image, _C_tests.forward_resnext101_32x8d, 'ResNext101_32x8d') + + def test_squeezenet1_0(self): + test_model(models.squeezenet1_0(self.pretrained), self.image, _C_tests.forward_squeezenet1_0, 'Squeezenet1.0') + + def test_squeezenet1_1(self): + test_model(models.squeezenet1_1(self.pretrained), self.image, _C_tests.forward_squeezenet1_1, 'Squeezenet1.1') + + def test_densenet121(self): + test_model(models.densenet121(self.pretrained), self.image, _C_tests.forward_densenet121, 'Densenet121') + + def test_densenet169(self): + test_model(models.densenet169(self.pretrained), self.image, _C_tests.forward_densenet169, 'Densenet169') + + def test_densenet201(self): + test_model(models.densenet201(self.pretrained), self.image, _C_tests.forward_densenet201, 'Densenet201') + + def test_densenet161(self): + test_model(models.densenet161(self.pretrained), self.image, _C_tests.forward_densenet161, 'Densenet161') + + def test_mobilenet_v2(self): + test_model(models.mobilenet_v2(self.pretrained), self.image, _C_tests.forward_mobilenetv2, 'MobileNet') + + def test_googlenet(self): + test_model(models.googlenet(self.pretrained), self.image, _C_tests.forward_googlenet, 'GoogLeNet') + + def test_inception_v3(self): + self.image = read_image2() + test_model(models.inception_v3(self.pretrained), self.image, _C_tests.forward_inceptionv3, 'Inceptionv3') + + +if __name__ == '__main__': + unittest.main() From d98e7cfac828c34c7b9107f00d19adf7f418fb41 Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Mon, 10 Jun 2019 05:00:50 +0430 Subject: [PATCH 47/48] Fixed a problem with pytest in test_cpp_models.py --- test/test_cpp_models.py | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index d81b0f55fb1..0132ae92be7 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -7,7 +7,7 @@ import torchvision.transforms.functional as F -def test_model(model, tensor, func, name): +def process_model(model, tensor, func, name): model.eval() traced_script_module = torch.jit.trace(model, tensor) traced_script_module.save("model.pt") @@ -40,80 +40,80 @@ class Tester(unittest.TestCase): image = read_image1() def test_alexnet(self): - test_model(models.alexnet(self.pretrained), self.image, _C_tests.forward_alexnet, 'Alexnet') + process_model(models.alexnet(self.pretrained), self.image, _C_tests.forward_alexnet, 'Alexnet') def test_vgg11(self): - test_model(models.vgg11(self.pretrained), self.image, _C_tests.forward_vgg11, 'VGG11') + process_model(models.vgg11(self.pretrained), self.image, _C_tests.forward_vgg11, 'VGG11') def test_vgg13(self): - test_model(models.vgg13(self.pretrained), self.image, _C_tests.forward_vgg13, 'VGG13') + process_model(models.vgg13(self.pretrained), self.image, _C_tests.forward_vgg13, 'VGG13') def test_vgg16(self): - test_model(models.vgg16(self.pretrained), self.image, _C_tests.forward_vgg16, 'VGG16') + process_model(models.vgg16(self.pretrained), self.image, _C_tests.forward_vgg16, 'VGG16') def test_vgg19(self): - test_model(models.vgg19(self.pretrained), self.image, _C_tests.forward_vgg19, 'VGG19') + process_model(models.vgg19(self.pretrained), self.image, _C_tests.forward_vgg19, 'VGG19') def test_vgg11_bn(self): - test_model(models.vgg11_bn(self.pretrained), self.image, _C_tests.forward_vgg11bn, 'VGG11BN') + process_model(models.vgg11_bn(self.pretrained), self.image, _C_tests.forward_vgg11bn, 'VGG11BN') def test_vgg13_bn(self): - test_model(models.vgg13_bn(self.pretrained), self.image, _C_tests.forward_vgg13bn, 'VGG13BN') + process_model(models.vgg13_bn(self.pretrained), self.image, _C_tests.forward_vgg13bn, 'VGG13BN') def test_vgg16_bn(self): - test_model(models.vgg16_bn(self.pretrained), self.image, _C_tests.forward_vgg16bn, 'VGG16BN') + process_model(models.vgg16_bn(self.pretrained), self.image, _C_tests.forward_vgg16bn, 'VGG16BN') def test_vgg19_bn(self): - test_model(models.vgg19_bn(self.pretrained), self.image, _C_tests.forward_vgg19bn, 'VGG19BN') + process_model(models.vgg19_bn(self.pretrained), self.image, _C_tests.forward_vgg19bn, 'VGG19BN') def test_resnet18(self): - test_model(models.resnet18(self.pretrained), self.image, _C_tests.forward_resnet18, 'Resnet18') + process_model(models.resnet18(self.pretrained), self.image, _C_tests.forward_resnet18, 'Resnet18') def test_resnet34(self): - test_model(models.resnet34(self.pretrained), self.image, _C_tests.forward_resnet34, 'Resnet34') + process_model(models.resnet34(self.pretrained), self.image, _C_tests.forward_resnet34, 'Resnet34') def test_resnet50(self): - test_model(models.resnet50(self.pretrained), self.image, _C_tests.forward_resnet50, 'Resnet50') + process_model(models.resnet50(self.pretrained), self.image, _C_tests.forward_resnet50, 'Resnet50') def test_resnet101(self): - test_model(models.resnet101(self.pretrained), self.image, _C_tests.forward_resnet101, 'Resnet101') + process_model(models.resnet101(self.pretrained), self.image, _C_tests.forward_resnet101, 'Resnet101') def test_resnet152(self): - test_model(models.resnet152(self.pretrained), self.image, _C_tests.forward_resnet152, 'Resnet152') + process_model(models.resnet152(self.pretrained), self.image, _C_tests.forward_resnet152, 'Resnet152') def test_resnext50_32x4d(self): - test_model(models.resnext50_32x4d(), self.image, _C_tests.forward_resnext50_32x4d, 'ResNext50_32x4d') + process_model(models.resnext50_32x4d(), self.image, _C_tests.forward_resnext50_32x4d, 'ResNext50_32x4d') def test_resnext101_32x8d(self): - test_model(models.resnext101_32x8d(), self.image, _C_tests.forward_resnext101_32x8d, 'ResNext101_32x8d') + process_model(models.resnext101_32x8d(), self.image, _C_tests.forward_resnext101_32x8d, 'ResNext101_32x8d') def test_squeezenet1_0(self): - test_model(models.squeezenet1_0(self.pretrained), self.image, _C_tests.forward_squeezenet1_0, 'Squeezenet1.0') + process_model(models.squeezenet1_0(self.pretrained), self.image, _C_tests.forward_squeezenet1_0, 'Squeezenet1.0') def test_squeezenet1_1(self): - test_model(models.squeezenet1_1(self.pretrained), self.image, _C_tests.forward_squeezenet1_1, 'Squeezenet1.1') + process_model(models.squeezenet1_1(self.pretrained), self.image, _C_tests.forward_squeezenet1_1, 'Squeezenet1.1') def test_densenet121(self): - test_model(models.densenet121(self.pretrained), self.image, _C_tests.forward_densenet121, 'Densenet121') + process_model(models.densenet121(self.pretrained), self.image, _C_tests.forward_densenet121, 'Densenet121') def test_densenet169(self): - test_model(models.densenet169(self.pretrained), self.image, _C_tests.forward_densenet169, 'Densenet169') + process_model(models.densenet169(self.pretrained), self.image, _C_tests.forward_densenet169, 'Densenet169') def test_densenet201(self): - test_model(models.densenet201(self.pretrained), self.image, _C_tests.forward_densenet201, 'Densenet201') + process_model(models.densenet201(self.pretrained), self.image, _C_tests.forward_densenet201, 'Densenet201') def test_densenet161(self): - test_model(models.densenet161(self.pretrained), self.image, _C_tests.forward_densenet161, 'Densenet161') + process_model(models.densenet161(self.pretrained), self.image, _C_tests.forward_densenet161, 'Densenet161') def test_mobilenet_v2(self): - test_model(models.mobilenet_v2(self.pretrained), self.image, _C_tests.forward_mobilenetv2, 'MobileNet') + process_model(models.mobilenet_v2(self.pretrained), self.image, _C_tests.forward_mobilenetv2, 'MobileNet') def test_googlenet(self): - test_model(models.googlenet(self.pretrained), self.image, _C_tests.forward_googlenet, 'GoogLeNet') + process_model(models.googlenet(self.pretrained), self.image, _C_tests.forward_googlenet, 'GoogLeNet') def test_inception_v3(self): self.image = read_image2() - test_model(models.inception_v3(self.pretrained), self.image, _C_tests.forward_inceptionv3, 'Inceptionv3') + process_model(models.inception_v3(self.pretrained), self.image, _C_tests.forward_inceptionv3, 'Inceptionv3') if __name__ == '__main__': From a6873d9d6f12f95da04532e189a1764171b319be Mon Sep 17 00:00:00 2001 From: ShahriarSS Date: Mon, 10 Jun 2019 05:18:12 +0430 Subject: [PATCH 48/48] Fixed a lint problem --- test/test_cpp_models.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index 0132ae92be7..3331db112d1 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -88,10 +88,12 @@ def test_resnext101_32x8d(self): process_model(models.resnext101_32x8d(), self.image, _C_tests.forward_resnext101_32x8d, 'ResNext101_32x8d') def test_squeezenet1_0(self): - process_model(models.squeezenet1_0(self.pretrained), self.image, _C_tests.forward_squeezenet1_0, 'Squeezenet1.0') + process_model(models.squeezenet1_0(self.pretrained), self.image, + _C_tests.forward_squeezenet1_0, 'Squeezenet1.0') def test_squeezenet1_1(self): - process_model(models.squeezenet1_1(self.pretrained), self.image, _C_tests.forward_squeezenet1_1, 'Squeezenet1.1') + process_model(models.squeezenet1_1(self.pretrained), self.image, + _C_tests.forward_squeezenet1_1, 'Squeezenet1.1') def test_densenet121(self): process_model(models.densenet121(self.pretrained), self.image, _C_tests.forward_densenet121, 'Densenet121')