Commit 8802dece authored by 刘哲(21硕)'s avatar 刘哲(21硕)

code

parents
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Remote Python 3.5.2 (sftp://liuzhe@10.214.199.205:22/usr/bin/python3.5)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="pytest" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" autoUpload="Always" serverName="liuzhe@10.214.199.205:22 password" remoteFilesAllowedToDisappearOnAutoupload="false">
<serverData>
<paths name="liuzhe@10.214.199.205:22 password">
<serverdata>
<mappings>
<mapping deploy="/home/liuzhe/Unet" local="$PROJECT_DIR$" />
</mappings>
</serverdata>
</paths>
<paths name="server">
<serverdata>
<mappings>
<mapping deploy="/" local="$PROJECT_DIR$" web="/" />
</mappings>
</serverdata>
</paths>
</serverData>
<option name="myAutoUpload" value="ALWAYS" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N803" />
</list>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Remote Python 3.5.2 (sftp://liuzhe@10.214.199.205:22/usr/bin/python3.5)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/QDlab.iml" filepath="$PROJECT_DIR$/.idea/QDlab.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebServers">
<option name="servers">
<webServer id="2cf9e263-2be4-41ec-9190-ed844cb67638" name="server">
<fileTransfer rootFolder="/home/liuzhe/Unet" accessType="SFTP" host="10.214.199.205" port="22" sshConfigId="42d80445-df33-442f-97f6-eee45e44b904" sshConfig="liuzhe@10.214.199.205:22 password">
<advancedOptions>
<advancedOptions dataProtectionLevel="Private" passiveMode="true" shareSSLContext="true" />
</advancedOptions>
</fileTransfer>
</webServer>
</option>
</component>
</project>
\ No newline at end of file
This is QD's private research program
\ No newline at end of file
"""
@Time : 2020/6/1 16:27
@Author : Qin Dian
@Manual :
"""
\ No newline at end of file
"""
@Time : 2020/6/30 11:23
@Author : Qin Dian
@Manual : liver tumor dataset
"""
from torch.utils.data import Dataset
import numpy as np
import os
import torch
import utils.data_utils as du
from glob import glob
LOWER_BOUND = -60
UPPER_BOUND = 140
class SliceDataset(Dataset):
def __init__(self, load_path, index_path, task='3tumors', series_index=None):
super(SliceDataset, self).__init__()
self.load_path = load_path
self.series_index = series_index
self.task = task
if series_index is not None:
self.tumor_slices = np.load(os.path.join(index_path, f'tumor_slices_s{series_index}.npy'))
def __len__(self):
return len(self.tumor_slices)
def __getitem__(self, item):
# Data loading
f_name = self.tumor_slices[item]
npz = np.load(os.path.join(self.load_path, f_name), allow_pickle=True)
ct = npz.get('ct')
mask = npz.get('mask') >> 1
# Preprocess
if self.task == '3tumors':
mask[(mask == 6) | (mask == 2) | (mask == 3)] = 1
mask[mask > 3] -= 2
if self.series_index is not None:
ct = ct[self.series_index]
mask = mask[self.series_index]
ct = du.window_standardize(ct, LOWER_BOUND, UPPER_BOUND)
ct = du.to_3channel_replica(ct)
mask = du.to_3channel_replica(mask)
# To tensor & cut to 384
ct = torch.from_numpy(du.cut_384(ct.copy())).float()
# self replication to 3 channel for adapting RGB channel
mask = torch.from_numpy(du.cut_384(mask.copy())).float()
return ct, mask
class CTDataset(Dataset):
def __init__(self, load_path, task='3tumors', series_index=None):
self.files = glob(os.path.join(load_path, 'ct*.npz'))
self.series_index = series_index
self.task = task
def __len__(self):
return len(self.files)
def __getitem__(self, item):
file = np.load(self.files[item], allow_pickle=True)
ct = file.get('arrays', file.get('arr_0'))
ct = ct.reshape(3, -1, 512, 512)
if self.series_index is not None:
ct = ct[self.series_index]
ct = du.window_standardize(ct, LOWER_BOUND, UPPER_BOUND)
ct = du.cut_384(ct)
ct = du.to_3channel_replica(ct)
ct = torch.from_numpy(ct.copy()).float()
return ct
# class Images_Dataset_folder(torch.utils.data.Dataset):
# """Class for getting individual transformations and data
# Args:
# images_dir = path of input images
# labels_dir = path of labeled images
# transformI = Input Images transformation (default: None)
# transformM = Input Labels transformation (default: None)
# Output:
# tx = Transformed images
# lx = Transformed labels
# """
#
# def __init__(self, images_dir, labels_dir, transformI=None, transformM=None):
# self.images = sorted(os.listdir(images_dir))
# self.labels = sorted(os.listdir(labels_dir))
# self.images_dir = images_dir
# self.labels_dir = labels_dir
# self.transformI = transformI
# self.transformM = transformM
#
# if self.transformI:
# self.tx = self.transformI
# else:
# self.tx = torchvision.transforms.Compose([
# # torchvision.transforms.Resize((128,128)),
# torchvision.transforms.CenterCrop(96),
# torchvision.transforms.RandomRotation((-10, 10)),
# # torchvision.transforms.RandomHorizontalFlip(),
# torchvision.transforms.ColorJitter(brightness=0.4, contrast=0.4, saturation=0.4),
# torchvision.transforms.ToTensor(),
# torchvision.transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
# ])
#
# if self.transformM:
# self.lx = self.transformM
# else:
# self.lx = torchvision.transforms.Compose([
# # torchvision.transforms.Resize((128,128)),
# torchvision.transforms.CenterCrop(96),
# torchvision.transforms.RandomRotation((-10, 10)),
# torchvision.transforms.Grayscale(),
# torchvision.transforms.ToTensor(),
# # torchvision.transforms.Lambda(lambda x: torch.cat([x, 1 - x], dim=0))
# ])
#
# def __len__(self):
#
# return len(self.images)
#
# def __getitem__(self, i):
# i1 = Image.open(self.images_dir + self.images[i])
# l1 = Image.open(self.labels_dir + self.labels[i])
#
# seed = np.random.randint(0, 2 ** 32) # make a seed with numpy generator
#
# # apply this seed to img tranfsorms
# random.seed(seed)
# torch.manual_seed(seed)
# img = self.tx(i1)
#
# # apply this seed to target/label tranfsorms
# random.seed(seed)
# torch.manual_seed(seed)
# label = self.lx(l1)
# return img, label
"""
@Time : 2020/6/2 14:55
@Author : Qin Dian
@Manual :
"""
import os
import torch
import pytorch_lightning as pl
from pytorch_lightning import Trainer
from pytorch_lightning.callbacks import ModelCheckpoint
from torch.utils.data import DataLoader
import argparse
from networks.deep_snake import U_Net
from datasets.liver import SliceDataset, CTDataset
import utils.net_utils as nu
import supports.loss_functions as lf
import torch.nn.functional as F
pl.seed_everything(123)
parser = argparse.ArgumentParser('deep snake')
parser.add_argument('--data_path', type=str, default=r'D:\A_UNET\out')
parser.add_argument('--tumor_index_path', type=str, default=r'D:\A_UNET')
parser.add_argument('--checkpoint_path', type=str, default=r'D:\A_UNET\out\checkpoints')
parser.add_argument('--test_path', type=str, default='/data/ts4.0')
parser.add_argument('--series_index', type=int, default=0)
parser.add_argument('--batch_size', type=int, default=2)
parser.add_argument('--max_epochs', type=int, default=50)
parser.add_argument('--gpu', type=list, default=[0])
def dice_loss(prediction, target):
"""Calculating the dice loss
Args:
prediction = predicted image
target = Targeted image
Output:
dice_loss"""
smooth = 1.0
i_flat = prediction.view(-1)
t_flat = target.view(-1)
intersection = (i_flat * t_flat).sum()
return 1 - ((2. * intersection + smooth) / (i_flat.sum() + t_flat.sum() + smooth))
def calc_loss(prediction, target, bce_weight=0.5):
"""Calculating the loss and metrics
Args:
prediction = predicted image
target = Targeted image
metrics = Metrics printed
bce_weight = 0.5 (default)
Output:
loss : dice loss of the epoch """
bce = F.binary_cross_entropy_with_logits(prediction, target)
prediction = F.sigmoid(prediction)
dice = dice_loss(prediction, target)
loss = bce * bce_weight + dice * (1 - bce_weight)
return loss
class DeepSnake(pl.LightningModule):
def __init__(self, params):
super(DeepSnake, self).__init__()
self.params = params
self.net = U_Net(in_ch=3, out_ch=3)
def forward(self, x):
return self.net(x)
def training_step(self, batch, batch_idx):
ct, mask = batch
output = self.forward(ct)
lossT = calc_loss(output, mask) # Dice_loss Used
loss = lossT.item() * ct.size(0)
logs = {'train_loss': loss}
return {'loss': loss, 'log': logs}
def test_step(self, batch, batch_idx):
x = batch[0]
num = int(x.size()[0])
for i in range(num//8 + 1):
if i < num//8:
out = self(x[i*8:i*8+8])
out = nu.clipped_sigmoid(out['ct_hm'])
else:
out = self(x[-8:])
out = nu.clipped_sigmoid(out['ct_hm'])
def train_dataloader(self):
return DataLoader(SliceDataset(load_path=self.params.data_path, index_path=self.params.tumor_index_path,
series_index=self.params.series_index), batch_size=self.params.batch_size,
num_workers=8, pin_memory=True, shuffle=True)
def test_dataloader(self):
return DataLoader(CTDataset(load_path='/data/ts4.0', series_index=2),
batch_size=1, num_workers=2, pin_memory=True)
def configure_optimizers(self):
return torch.optim.Adam(self.parameters(), lr=1e-4, betas=(0.5, 0.999))
def main():
args = parser.parse_args()
model = DeepSnake(args)
# checkpoint
checkpoint_callback = ModelCheckpoint(
filepath=os.path.join(args.checkpoint_path, 'checkpoint_{epoch}')
# save_last=True # always saves the model at the end of the epoch
)
# trainer = Trainer.from_argparse_args(args, gpus=args.gpu, amp_level='O2', precision=16)
trainer = Trainer.from_argparse_args(args, gpus=args.gpu, checkpoint_callback=checkpoint_callback)
trainer.fit(model)
def test():
args = parser.parse_args()
model = DeepSnake.load_from_checkpoint(
'/data/checkpoints/deep_snake/last.ckpt',
)
trainer = Trainer(gpus=[0])
trainer.test(model)
if __name__ == '__main__':
main()
# test()
\ No newline at end of file
"""
@Time : 2020/6/17 13:38
@Author : Qin Dian
@Manual :
"""
\ No newline at end of file
"""
@Time : 2020/6/17 13:38
@Author : Qin Dian
@Manual :
"""
\ No newline at end of file
.vscode
.idea
*.so
*.o
*pyc
_ext
build
DCNv2.egg-info
dist
\ No newline at end of file
BSD 3-Clause License
Copyright (c) 2019, Charles Shang
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
## Deformable Convolutional Networks V2 with Pytorch 1.0
### Build
```bash
./make.sh # build
python test.py # run examples and gradient check
```
### An Example
- deformable conv
```python
from dcn_v2 import DCN
input = torch.randn(2, 64, 128, 128).cuda()
# wrap all things (offset and mask) in DCN
dcn = DCN(64, 64, kernel_size=(3,3), stride=1, padding=1, deformable_groups=2).cuda()
output = dcn(input)
print(output.shape)
```
- deformable roi pooling
```python
from dcn_v2 import DCNPooling
input = torch.randn(2, 32, 64, 64).cuda()
batch_inds = torch.randint(2, (20, 1)).cuda().float()
x = torch.randint(256, (20, 1)).cuda().float()
y = torch.randint(256, (20, 1)).cuda().float()
w = torch.randint(64, (20, 1)).cuda().float()
h = torch.randint(64, (20, 1)).cuda().float()
rois = torch.cat((batch_inds, x, y, x + w, y + h), dim=1)
# mdformable pooling (V2)
# wrap all things (offset and mask) in DCNPooling
dpooling = DCNPooling(spatial_scale=1.0 / 4,
pooled_size=7,
output_dim=32,
no_trans=False,
group_size=1,
trans_std=0.1).cuda()
dout = dpooling(input, rois)
```
### Note
Now the master branch is for pytorch 1.0 (new ATen API), you can switch back to pytorch 0.4 with,
```bash
git checkout pytorch_0.4
```
### Known Issues:
- [x] Gradient check w.r.t offset (solved)
- [ ] Backward is not reentrant (minor)
This is an adaption of the official [Deformable-ConvNets](https://github.com/msracver/Deformable-ConvNets/tree/master/DCNv2_op).
<s>I have ran the gradient check for many times with DOUBLE type. Every tensor **except offset** passes.
However, when I set the offset to 0.5, it passes. I'm still wondering what cause this problem. Is it because some
non-differential points? </s>
Update: all gradient check passes with double precision.
Another issue is that it raises `RuntimeError: Backward is not reentrant`. However, the error is very small (`<1e-7` for
float `<1e-15` for double),
so it may not be a serious problem (?)
Please post an issue or PR if you have any comments.
\ No newline at end of file
#!/usr/bin/env python
import os
import glob
import torch
from torch.utils.cpp_extension import CUDA_HOME
from torch.utils.cpp_extension import CppExtension
from torch.utils.cpp_extension import CUDAExtension
from setuptools import find_packages
from setuptools import setup
requirements = ["torch", "torchvision"]
def get_extensions():
this_dir = os.path.dirname(os.path.abspath(__file__))
extensions_dir = os.path.join(this_dir, "src")
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
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)]
extra_compile_args["nvcc"] = [
"-DCUDA_HAS_FP16=1",
"-D__CUDA_NO_HALF_OPERATORS__",
"-D__CUDA_NO_HALF_CONVERSIONS__",
"-D__CUDA_NO_HALF2_OPERATORS__",
]
else:
raise NotImplementedError('Cuda is not availabel')
sources = [os.path.join(extensions_dir, s) for s in sources]
include_dirs = [extensions_dir]
ext_modules = [
extension(
"_ext",
sources,
include_dirs=include_dirs,
define_macros=define_macros,
extra_compile_args=extra_compile_args,
)
]
return ext_modules
setup(
name="DCNv2",
version="0.1",
author="charlesshang",
url="https://github.com/charlesshang/DCNv2",
description="deformable convolutional networks",
packages=find_packages(exclude=("configs", "tests",)),
# install_requires=requirements,
ext_modules=get_extensions(),
cmdclass={"build_ext": torch.utils.cpp_extension.BuildExtension},
)
\ No newline at end of file
#include <vector>
#include <ATen/ATen.h>
#include <ATen/cuda/CUDAContext.h>
at::Tensor
dcn_v2_cpu_forward(const at::Tensor &input,
const at::Tensor &weight,
const at::Tensor &bias,
const at::Tensor &offset,
const at::Tensor &mask,
const int kernel_h,
const int kernel_w,
const int stride_h,
const int stride_w,
const int pad_h,
const int pad_w,
const int dilation_h,
const int dilation_w,
const int deformable_group)
{
AT_ERROR("Not implement on cpu");
}
std::vector<at::Tensor>
dcn_v2_cpu_backward(const at::Tensor &input,
const at::Tensor &weight,
const at::Tensor &bias,
const at::Tensor &offset,
const at::Tensor &mask,
const at::Tensor &grad_output,
int kernel_h, int kernel_w,
int stride_h, int stride_w,
int pad_h, int pad_w,
int dilation_h, int dilation_w,
int deformable_group)
{
AT_ERROR("Not implement on cpu");
}
std::tuple<at::Tensor, at::Tensor>
dcn_v2_psroi_pooling_cpu_forward(const at::Tensor &input,
const at::Tensor &bbox,
const at::Tensor &trans,
const int no_trans,
const float spatial_scale,
const int output_dim,
const int group_size,
const int pooled_size,
const int part_size,
const int sample_per_part,
const float trans_std)
{
AT_ERROR("Not implement on cpu");
}
std::tuple<at::Tensor, at::Tensor>
dcn_v2_psroi_pooling_cpu_backward(const at::Tensor &out_grad,
const at::Tensor &input,
const at::Tensor &bbox,
const at::Tensor &trans,
const at::Tensor &top_count,
const int no_trans,
const float spatial_scale,
const int output_dim,
const int group_size,
const int pooled_size,
const int part_size,
const int sample_per_part,
const float trans_std)
{
AT_ERROR("Not implement on cpu");
}
\ No newline at end of file
#pragma once
#include <torch/extension.h>
at::Tensor
dcn_v2_cpu_forward(const at::Tensor &input,
const at::Tensor &weight,
const at::Tensor &bias,
const at::Tensor &offset,
const at::Tensor &mask,
const int kernel_h,
const int kernel_w,
const int stride_h,
const int stride_w,
const int pad_h,
const int pad_w,
const int dilation_h,
const int dilation_w,
const int deformable_group);
std::vector<at::Tensor>
dcn_v2_cpu_backward(const at::Tensor &input,
const at::Tensor &weight,
const at::Tensor &bias,
const at::Tensor &offset,
const at::Tensor &mask,
const at::Tensor &grad_output,
int kernel_h, int kernel_w,
int stride_h, int stride_w,
int pad_h, int pad_w,
int dilation_h, int dilation_w,
int deformable_group);
std::tuple<at::Tensor, at::Tensor>
dcn_v2_psroi_pooling_cpu_forward(const at::Tensor &input,
const at::Tensor &bbox,
const at::Tensor &trans,
const int no_trans,
const float spatial_scale,
const int output_dim,
const int group_size,
const int pooled_size,
const int part_size,
const int sample_per_part,
const float trans_std);
std::tuple<at::Tensor, at::Tensor>
dcn_v2_psroi_pooling_cpu_backward(const at::Tensor &out_grad,
const at::Tensor &input,
const at::Tensor &bbox,
const at::Tensor &trans,
const at::Tensor &top_count,
const int no_trans,
const float spatial_scale,
const int output_dim,
const int group_size,
const int pooled_size,
const int part_size,
const int sample_per_part,
const float trans_std);
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
/*!
******************* BEGIN Caffe Copyright Notice and Disclaimer ****************
*
* COPYRIGHT
*
* All contributions by the University of California:
* Copyright (c) 2014-2017 The Regents of the University of California (Regents)
* All rights reserved.
*
* All other contributions:
* Copyright (c) 2014-2017, the respective contributors
* All rights reserved.
*
* Caffe uses a shared copyright model: each contributor holds copyright over
* their contributions to Caffe. The project versioning records all such
* contribution and copyright details. If a contributor wants to further mark
* their specific copyright on a particular contribution, they should indicate
* their copyright solely in the commit message of the change when it is
* committed.
*
* LICENSE
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* CONTRIBUTION AGREEMENT
*
* By contributing to the BVLC/caffe repository through pull-request, comment,
* or otherwise, the contributor releases their content to the
* license and copyright terms herein.
*
***************** END Caffe Copyright Notice and Disclaimer ********************
*
* Copyright (c) 2018 Microsoft
* Licensed under The MIT License [see LICENSE for details]
* \file modulated_deformable_im2col.h
* \brief Function definitions of converting an image to
* column matrix based on kernel, padding, dilation, and offset.
* These functions are mainly used in deformable convolution operators.
* \ref: https://arxiv.org/abs/1811.11168
* \author Yuwen Xiong, Haozhi Qi, Jifeng Dai, Xizhou Zhu, Han Hu
*/
/***************** Adapted by Charles Shang *********************/
#ifndef DCN_V2_IM2COL_CUDA
#define DCN_V2_IM2COL_CUDA
#ifdef __cplusplus
extern "C"
{
#endif
void modulated_deformable_im2col_cuda(cudaStream_t stream,
const float *data_im, const float *data_offset, const float *data_mask,
const int batch_size, const int channels, const int height_im, const int width_im,
const int height_col, const int width_col, const int kernel_h, const int kenerl_w,
const int pad_h, const int pad_w, const int stride_h, const int stride_w,
const int dilation_h, const int dilation_w,
const int deformable_group, float *data_col);
void modulated_deformable_col2im_cuda(cudaStream_t stream,
const float *data_col, const float *data_offset, const float *data_mask,
const int batch_size, const int channels, const int height_im, const int width_im,
const int height_col, const int width_col, const int kernel_h, const int kenerl_w,
const int pad_h, const int pad_w, const int stride_h, const int stride_w,
const int dilation_h, const int dilation_w,
const int deformable_group, float *grad_im);
void modulated_deformable_col2im_coord_cuda(cudaStream_t stream,
const float *data_col, const float *data_im, const float *data_offset, const float *data_mask,
const int batch_size, const int channels, const int height_im, const int width_im,
const int height_col, const int width_col, const int kernel_h, const int kenerl_w,
const int pad_h, const int pad_w, const int stride_h, const int stride_w,
const int dilation_h, const int dilation_w,
const int deformable_group,
float *grad_offset, float *grad_mask);
#ifdef __cplusplus
}
#endif
#endif
\ No newline at end of file
This diff is collapsed.
#pragma once
#include <torch/extension.h>
at::Tensor
dcn_v2_cuda_forward(const at::Tensor &input,
const at::Tensor &weight,
const at::Tensor &bias,
const at::Tensor &offset,
const at::Tensor &mask,
const int kernel_h,
const int kernel_w,
const int stride_h,
const int stride_w,
const int pad_h,
const int pad_w,
const int dilation_h,
const int dilation_w,
const int deformable_group);
std::vector<at::Tensor>
dcn_v2_cuda_backward(const at::Tensor &input,
const at::Tensor &weight,
const at::Tensor &bias,
const at::Tensor &offset,
const at::Tensor &mask,
const at::Tensor &grad_output,
int kernel_h, int kernel_w,
int stride_h, int stride_w,
int pad_h, int pad_w,
int dilation_h, int dilation_w,
int deformable_group);
std::tuple<at::Tensor, at::Tensor>
dcn_v2_psroi_pooling_cuda_forward(const at::Tensor &input,
const at::Tensor &bbox,
const at::Tensor &trans,
const int no_trans,
const float spatial_scale,
const int output_dim,
const int group_size,
const int pooled_size,
const int part_size,
const int sample_per_part,
const float trans_std);
std::tuple<at::Tensor, at::Tensor>
dcn_v2_psroi_pooling_cuda_backward(const at::Tensor &out_grad,
const at::Tensor &input,
const at::Tensor &bbox,
const at::Tensor &trans,
const at::Tensor &top_count,
const int no_trans,
const float spatial_scale,
const int output_dim,
const int group_size,
const int pooled_size,
const int part_size,
const int sample_per_part,
const float trans_std);
\ No newline at end of file
#pragma once
#include "cpu/vision.h"
#ifdef WITH_CUDA
#include "cuda/vision.h"
#endif
at::Tensor
dcn_v2_forward(const at::Tensor &input,
const at::Tensor &weight,
const at::Tensor &bias,
const at::Tensor &offset,
const at::Tensor &mask,
const int kernel_h,
const int kernel_w,
const int stride_h,
const int stride_w,
const int pad_h,
const int pad_w,
const int dilation_h,
const int dilation_w,
const int deformable_group)
{
if (input.type().is_cuda())
{
#ifdef WITH_CUDA
return dcn_v2_cuda_forward(input, weight, bias, offset, mask,
kernel_h, kernel_w,
stride_h, stride_w,
pad_h, pad_w,
dilation_h, dilation_w,
deformable_group);
#else
AT_ERROR("Not compiled with GPU support");
#endif
}
AT_ERROR("Not implemented on the CPU");
}
std::vector<at::Tensor>
dcn_v2_backward(const at::Tensor &input,
const at::Tensor &weight,
const at::Tensor &bias,
const at::Tensor &offset,
const at::Tensor &mask,
const at::Tensor &grad_output,
int kernel_h, int kernel_w,
int stride_h, int stride_w,
int pad_h, int pad_w,
int dilation_h, int dilation_w,
int deformable_group)
{
if (input.type().is_cuda())
{
#ifdef WITH_CUDA
return dcn_v2_cuda_backward(input,
weight,
bias,
offset,
mask,
grad_output,
kernel_h, kernel_w,
stride_h, stride_w,
pad_h, pad_w,
dilation_h, dilation_w,
deformable_group);
#else
AT_ERROR("Not compiled with GPU support");
#endif
}
AT_ERROR("Not implemented on the CPU");
}
std::tuple<at::Tensor, at::Tensor>
dcn_v2_psroi_pooling_forward(const at::Tensor &input,
const at::Tensor &bbox,
const at::Tensor &trans,
const int no_trans,
const float spatial_scale,
const int output_dim,
const int group_size,
const int pooled_size,
const int part_size,
const int sample_per_part,
const float trans_std)
{
if (input.type().is_cuda())
{
#ifdef WITH_CUDA
return dcn_v2_psroi_pooling_cuda_forward(input,
bbox,
trans,
no_trans,
spatial_scale,
output_dim,
group_size,
pooled_size,
part_size,
sample_per_part,
trans_std);
#else
AT_ERROR("Not compiled with GPU support");
#endif
}
AT_ERROR("Not implemented on the CPU");
}
std::tuple<at::Tensor, at::Tensor>
dcn_v2_psroi_pooling_backward(const at::Tensor &out_grad,
const at::Tensor &input,
const at::Tensor &bbox,
const at::Tensor &trans,
const at::Tensor &top_count,
const int no_trans,
const float spatial_scale,
const int output_dim,
const int group_size,
const int pooled_size,
const int part_size,
const int sample_per_part,
const float trans_std)
{
if (input.type().is_cuda())
{
#ifdef WITH_CUDA
return dcn_v2_psroi_pooling_cuda_backward(out_grad,
input,
bbox,
trans,
top_count,
no_trans,
spatial_scale,
output_dim,
group_size,
pooled_size,
part_size,
sample_per_part,
trans_std);
#else
AT_ERROR("Not compiled with GPU support");
#endif
}
AT_ERROR("Not implemented on the CPU");
}
\ No newline at end of file
#include "dcn_v2.h"
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("dcn_v2_forward", &dcn_v2_forward, "dcn_v2_forward");
m.def("dcn_v2_backward", &dcn_v2_backward, "dcn_v2_backward");
m.def("dcn_v2_psroi_pooling_forward", &dcn_v2_psroi_pooling_forward, "dcn_v2_psroi_pooling_forward");
m.def("dcn_v2_psroi_pooling_backward", &dcn_v2_psroi_pooling_backward, "dcn_v2_psroi_pooling_backward");
}
#!/usr/bin/env python
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
import time
import torch
import torch.nn as nn
from torch.autograd import gradcheck
from dcn_v2 import dcn_v2_conv, DCNv2, DCN
from dcn_v2 import dcn_v2_pooling, DCNv2Pooling, DCNPooling
deformable_groups = 1
N, inC, inH, inW = 2, 2, 4, 4
outC = 2
kH, kW = 3, 3
def conv_identify(weight, bias):
weight.data.zero_()
bias.data.zero_()
o, i, h, w = weight.shape
y = h//2
x = w//2
for p in range(i):
for q in range(o):
if p == q:
weight.data[q, p, y, x] = 1.0
def check_zero_offset():
conv_offset = nn.Conv2d(inC, deformable_groups * 2 * kH * kW,
kernel_size=(kH, kW),
stride=(1, 1),
padding=(1, 1),
bias=True).cuda()
conv_mask = nn.Conv2d(inC, deformable_groups * 1 * kH * kW,
kernel_size=(kH, kW),
stride=(1, 1),
padding=(1, 1),
bias=True).cuda()
dcn_v2 = DCNv2(inC, outC, (kH, kW),
stride=1, padding=1, dilation=1,
deformable_groups=deformable_groups).cuda()
conv_offset.weight.data.zero_()
conv_offset.bias.data.zero_()
conv_mask.weight.data.zero_()
conv_mask.bias.data.zero_()
conv_identify(dcn_v2.weight, dcn_v2.bias)
input = torch.randn(N, inC, inH, inW).cuda()
offset = conv_offset(input)
mask = conv_mask(input)
mask = torch.sigmoid(mask)
output = dcn_v2(input, offset, mask)
output *= 2
d = (input - output).abs().max()
if d < 1e-10:
print('Zero offset passed')
else:
print('Zero offset failed')
print(input)
print(output)
def check_gradient_dconv():
input = torch.rand(N, inC, inH, inW).cuda() * 0.01
input.requires_grad = True
offset = torch.randn(N, deformable_groups * 2 * kW * kH, inH, inW).cuda() * 2
# offset.data.zero_()
# offset.data -= 0.5
offset.requires_grad = True
mask = torch.rand(N, deformable_groups * 1 * kW * kH, inH, inW).cuda()
# mask.data.zero_()
mask.requires_grad = True
mask = torch.sigmoid(mask)
weight = torch.randn(outC, inC, kH, kW).cuda()
weight.requires_grad = True
bias = torch.rand(outC).cuda()
bias.requires_grad = True
stride = 1
padding = 1
dilation = 1
print('check_gradient_dconv: ',
gradcheck(dcn_v2_conv, (input, offset, mask, weight, bias,
stride, padding, dilation, deformable_groups),
eps=1e-3, atol=1e-4, rtol=1e-2))
def check_pooling_zero_offset():
input = torch.randn(2, 16, 64, 64).cuda().zero_()
input[0, :, 16:26, 16:26] = 1.
input[1, :, 10:20, 20:30] = 2.
rois = torch.tensor([
[0, 65, 65, 103, 103],
[1, 81, 41, 119, 79],
]).cuda().float()
pooling = DCNv2Pooling(spatial_scale=1.0 / 4,
pooled_size=7,
output_dim=16,
no_trans=True,
group_size=1,
trans_std=0.0).cuda()
out = pooling(input, rois, input.new())
s = ', '.join(['%f' % out[i, :, :, :].mean().item()
for i in range(rois.shape[0])])
print(s)
dpooling = DCNv2Pooling(spatial_scale=1.0 / 4,
pooled_size=7,
output_dim=16,
no_trans=False,
group_size=1,
trans_std=0.0).cuda()
offset = torch.randn(20, 2, 7, 7).cuda().zero_()
dout = dpooling(input, rois, offset)
s = ', '.join(['%f' % dout[i, :, :, :].mean().item()
for i in range(rois.shape[0])])
print(s)
def check_gradient_dpooling():
input = torch.randn(2, 3, 5, 5).cuda() * 0.01
N = 4
batch_inds = torch.randint(2, (N, 1)).cuda().float()
x = torch.rand((N, 1)).cuda().float() * 15
y = torch.rand((N, 1)).cuda().float() * 15
w = torch.rand((N, 1)).cuda().float() * 10
h = torch.rand((N, 1)).cuda().float() * 10
rois = torch.cat((batch_inds, x, y, x + w, y + h), dim=1)
offset = torch.randn(N, 2, 3, 3).cuda()
input.requires_grad = True
offset.requires_grad = True
spatial_scale = 1.0 / 4
pooled_size = 3
output_dim = 3
no_trans = 0
group_size = 1
trans_std = 0.0
sample_per_part = 4
part_size = pooled_size
print('check_gradient_dpooling:',
gradcheck(dcn_v2_pooling, (input, rois, offset,
spatial_scale,
pooled_size,
output_dim,
no_trans,
group_size,
part_size,
sample_per_part,
trans_std),
eps=1e-4))
def example_dconv():
input = torch.randn(2, 64, 128, 128).cuda()
# wrap all things (offset and mask) in DCN
dcn = DCN(64, 64, kernel_size=(3, 3), stride=1,
padding=1, deformable_groups=2).cuda()
# print(dcn.weight.shape, input.shape)
output = dcn(input)
targert = output.new(*output.size())
targert.data.uniform_(-0.01, 0.01)
error = (targert - output).mean()
error.backward()
print(output.shape)
def example_dpooling():
input = torch.randn(2, 32, 64, 64).cuda()
batch_inds = torch.randint(2, (20, 1)).cuda().float()
x = torch.randint(256, (20, 1)).cuda().float()
y = torch.randint(256, (20, 1)).cuda().float()
w = torch.randint(64, (20, 1)).cuda().float()
h = torch.randint(64, (20, 1)).cuda().float()
rois = torch.cat((batch_inds, x, y, x + w, y + h), dim=1)
offset = torch.randn(20, 2, 7, 7).cuda()
input.requires_grad = True
offset.requires_grad = True
# normal roi_align
pooling = DCNv2Pooling(spatial_scale=1.0 / 4,
pooled_size=7,
output_dim=32,
no_trans=True,
group_size=1,
trans_std=0.1).cuda()
# deformable pooling
dpooling = DCNv2Pooling(spatial_scale=1.0 / 4,
pooled_size=7,
output_dim=32,
no_trans=False,
group_size=1,
trans_std=0.1).cuda()
out = pooling(input, rois, offset)
dout = dpooling(input, rois, offset)
print(out.shape)
print(dout.shape)
target_out = out.new(*out.size())
target_out.data.uniform_(-0.01, 0.01)
target_dout = dout.new(*dout.size())
target_dout.data.uniform_(-0.01, 0.01)
e = (target_out - out).mean()
e.backward()
e = (target_dout - dout).mean()
e.backward()
def example_mdpooling():
input = torch.randn(2, 32, 64, 64).cuda()
input.requires_grad = True
batch_inds = torch.randint(2, (20, 1)).cuda().float()
x = torch.randint(256, (20, 1)).cuda().float()
y = torch.randint(256, (20, 1)).cuda().float()
w = torch.randint(64, (20, 1)).cuda().float()
h = torch.randint(64, (20, 1)).cuda().float()
rois = torch.cat((batch_inds, x, y, x + w, y + h), dim=1)
# mdformable pooling (V2)
dpooling = DCNPooling(spatial_scale=1.0 / 4,
pooled_size=7,
output_dim=32,
no_trans=False,
group_size=1,
trans_std=0.1,
deform_fc_dim=1024).cuda()
dout = dpooling(input, rois)
target = dout.new(*dout.size())
target.data.uniform_(-0.1, 0.1)
error = (target - dout).mean()
error.backward()
print(dout.shape)
if __name__ == '__main__':
example_dconv()
example_dpooling()
example_mdpooling()
check_pooling_zero_offset()
# zero offset check
if inC == outC:
check_zero_offset()
check_gradient_dpooling()
check_gradient_dconv()
# """
# ****** Note: backward is not reentrant error may not be a serious problem,
# ****** since the max error is less than 1e-7,
# ****** Still looking for what trigger this problem
# """
"""
@Time : 2020/6/1 16:24
@Author : Qin Dian
@Manual :
"""
\ No newline at end of file
"""
@Time : 2020/6/1 16:31
@Author : Qin Dian
@Manual :
"""
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
"""
@Time : 2020/6/2 14:55
@Author : Qin Dian
@Manual : Deep Snake Network
"""
import torch.nn as nn
# from networks.backbones.dla import DLASeg
# from utils import data_utils, net_utils
import torch
# class Network(nn.Module):
# def __init__(self, num_layers, heads, head_conv=256, down_ratio=1):
# super(Network, self).__init__()
#
# self.dla = DLASeg('dla{}'.format(num_layers), heads,
# pretrained=True,
# down_ratio=down_ratio,
# final_kernel=1,
# last_level=5,
# head_conv=head_conv)
#
# @staticmethod
# def decode_detection(output, h, w):
# ct_hm = output['ct_hm']
# wh = output['hw']
# ct, detection = net_utils.extract_top_k_ctp_dt(torch.sigmoid(ct_hm), wh)
# detection[..., :4] = data_utils.clip_to_image(detection[..., :4], h, w)
# output.update({'ct': ct, 'detection': detection})
# return ct, detection
#
# @staticmethod
# def use_gt_detection(output, batch):
# _, _, height, width = output['ct_hm'].size()
# ct_01 = batch['ct_01'].byte()
#
# ct_ind = batch['ct_ind'][ct_01]
# xs, ys = ct_ind % width, ct_ind // width
# xs, ys = xs[:, None].float(), ys[:, None].float()
# ct = torch.cat([xs, ys], dim=1)
#
# wh = batch['hw'][ct_01]
# bboxes = torch.cat([xs - wh[..., 0:1] / 2,
# ys - wh[..., 1:2] / 2,
# xs + wh[..., 0:1] / 2,
# ys + wh[..., 1:2] / 2], dim=1)
# score = torch.ones([len(bboxes)]).to(bboxes)[:, None]
# ct_cls = batch['ct_cls'][ct_01].float()[:, None]
# detection = torch.cat([bboxes, score, ct_cls], dim=1)
#
# output['ct'] = ct[None]
# output['detection'] = detection[None]
#
# return output
#
# def forward(self, x, batch=None):
# # output 为目标检测特征
# output, cnn_feature = self.dla(x)
# with torch.no_grad():
# # 处理目标检测特征为中心点和轮廓
# self.decode_detection(output, cnn_feature.size(2), cnn_feature.size(3))
# return output
class conv_block(nn.Module):
"""
Convolution Block
"""
def __init__(self, in_ch, out_ch):
super(conv_block, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(in_ch, out_ch, kernel_size=3, stride=1, padding=1, bias=True),
nn.BatchNorm2d(out_ch),
nn.ReLU(inplace=True),
nn.Conv2d(out_ch, out_ch, kernel_size=3, stride=1, padding=1, bias=True),
nn.BatchNorm2d(out_ch),
nn.ReLU(inplace=True))
def forward(self, x):
x = self.conv(x)
return x
class up_conv(nn.Module):
"""
Up Convolution Block
"""
def __init__(self, in_ch, out_ch):
super(up_conv, self).__init__()
self.up = nn.Sequential(
nn.Upsample(scale_factor=2),
nn.Conv2d(in_ch, out_ch, kernel_size=3, stride=1, padding=1, bias=True),
nn.BatchNorm2d(out_ch),
nn.ReLU(inplace=True)
)
def forward(self, x):
x = self.up(x)
return x
class U_Net(nn.Module):
"""
UNet - Basic Implementation
Paper : https://arxiv.org/abs/1505.04597
"""
def __init__(self, in_ch=3, out_ch=1):
super(U_Net, self).__init__()
n1 = 64
filters = [n1, n1 * 2, n1 * 4, n1 * 8, n1 * 16]
self.Maxpool1 = nn.MaxPool2d(kernel_size=2, stride=2)
self.Maxpool2 = nn.MaxPool2d(kernel_size=2, stride=2)
self.Maxpool3 = nn.MaxPool2d(kernel_size=2, stride=2)
self.Maxpool4 = nn.MaxPool2d(kernel_size=2, stride=2)
self.Conv1 = conv_block(in_ch, filters[0])
self.Conv2 = conv_block(filters[0], filters[1])
self.Conv3 = conv_block(filters[1], filters[2])
self.Conv4 = conv_block(filters[2], filters[3])
self.Conv5 = conv_block(filters[3], filters[4])
self.Up5 = up_conv(filters[4], filters[3])
self.Up_conv5 = conv_block(filters[4], filters[3])
self.Up4 = up_conv(filters[3], filters[2])
self.Up_conv4 = conv_block(filters[3], filters[2])
self.Up3 = up_conv(filters[2], filters[1])
self.Up_conv3 = conv_block(filters[2], filters[1])
self.Up2 = up_conv(filters[1], filters[0])
self.Up_conv2 = conv_block(filters[1], filters[0])
self.Conv = nn.Conv2d(filters[0], out_ch, kernel_size=1, stride=1, padding=0)
# self.active = torch.nn.Sigmoid()
def forward(self, x):
e1 = self.Conv1(x)
e2 = self.Maxpool1(e1)
e2 = self.Conv2(e2)
e3 = self.Maxpool2(e2)
e3 = self.Conv3(e3)
e4 = self.Maxpool3(e3)
e4 = self.Conv4(e4)
e5 = self.Maxpool4(e4)
e5 = self.Conv5(e5)
d5 = self.Up5(e5)
d5 = torch.cat((e4, d5), dim=1)
d5 = self.Up_conv5(d5)
d4 = self.Up4(d5)
d4 = torch.cat((e3, d4), dim=1)
d4 = self.Up_conv4(d4)
d3 = self.Up3(d4)
d3 = torch.cat((e2, d3), dim=1)
d3 = self.Up_conv3(d3)
d2 = self.Up2(d3)
d2 = torch.cat((e1, d2), dim=1)
d2 = self.Up_conv2(d2)
out = self.Conv(d2)
# d1 = self.active(out)
return out
if __name__ == '__main__':
net = Network(num_layers=34, heads={'ct_hm': 7, 'hw': 2})
net.eval()
net.cuda()
tmp_ct = torch.randn((10, 3, 512, 512)).cuda()
out = net(tmp_ct)
print(out['ct_hm'].size())
\ No newline at end of file
## MNIST
In this readme, give instructions on how to run your code.
In this case, we remove the datasets from the lightningModule as you
might want to use the same model with many datasets
#### CPU
```bash
python mnist_trainer.py
```
#### Multiple-GPUs
```bash
python mnist_trainer.py --gpus 4
```
or specific GPUs
```bash
python mnist_trainer.py --gpus '0,3'
```
#### On multiple nodes
```bash
python mnist_trainer.py --gpus 4 --nodes 4 --precision 16
```
"""
@Time : 2020/5/28 19:33
@Author : Qin Dian
@Manual :
"""
\ No newline at end of file
"""
This file defines the core research contribution
"""
import os
import torch
from torch.nn import functional as F
from argparse import ArgumentParser
import pytorch_lightning as pl
class CoolSystem(pl.LightningModule):
def __init__(self, hparams):
super(CoolSystem, self).__init__()
# not the best model...
self.hparams = hparams
self.l1 = torch.nn.Linear(28 * 28, 10)
def forward(self, x):
return torch.relu(self.l1(x.view(x.size(0), -1)))
def training_step(self, batch, batch_idx):
# REQUIRED
x, y = batch
y_hat = self.forward(x)
loss = F.cross_entropy(y_hat, y)
tensorboard_logs = {'train_loss': loss}
return {'loss': loss, 'log': tensorboard_logs}
def validation_step(self, batch, batch_idx):
# OPTIONAL
x, y = batch
y_hat = self.forward(x)
return {'val_loss': F.cross_entropy(y_hat, y)}
def validation_epoch_end(self, outputs):
# OPTIONAL
avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()
tensorboard_logs = {'avg_val_loss': avg_loss}
return {'val_loss': avg_loss, 'log': tensorboard_logs}
def configure_optimizers(self):
# REQUIRED
# can return multiple optimizers and learning_rate schedulers
return torch.optim.Adam(self.parameters(), lr=self.hparams.learning_rate)
@staticmethod
def add_model_specific_args(parent_parser):
"""
Specify the hyperparams for this LightningModule
"""
# MODEL specific
parser = ArgumentParser(parents=[parent_parser], add_help=False)
parser.add_argument('--learning_rate', default=0.02, type=float)
parser.add_argument('--batch_size', default=32, type=int)
# training specific (for this model)
parser.add_argument('--max_nb_epochs', default=2, type=int)
return parser
"""
This file runs the main training/val loop, etc... using Lightning Trainer
"""
import os
from pytorch_lightning import Trainer, seed_everything
from argparse import ArgumentParser
from production_demo.mnist import CoolSystem
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
import torchvision.transforms as transforms
# sets seeds for numpy, torch, etc...
# must do for DDP to work well
seed_everything(123)
def main(args):
# init module
model = CoolSystem(hparams=args)
train_loader = DataLoader(MNIST(os.getcwd(), train=True, download=True, transform=transforms.ToTensor()), batch_size=args.batch_size)
val_loader = DataLoader(MNIST(os.getcwd(), train=True, download=True, transform=transforms.ToTensor()), batch_size=args.batch_size)
# makes all flags available to trainer from cli
trainer = Trainer.from_argparse_args(args)
trainer.fit(model, train_loader, val_loader)
if __name__ == '__main__':
parser = ArgumentParser(add_help=False)
parser.add_argument('--gpus', default=2)
# add args from trainer
parser = Trainer.add_argparse_args(parser)
# give the module a chance to add own params
# good practice to define LightningModule speficic params in the module
parser = CoolSystem.add_model_specific_args(parser)
# parse params
args = parser.parse_args()
main(args)
## MNIST
In this readme, give instructions on how to run your code.
#### CPU
```bash
python mnist_trainer.py
```
#### Multiple-GPUs
```bash
python mnist_trainer.py --gpus 4
```
or specific GPUs
```bash
python mnist_trainer.py --gpus '0,3'
```
#### On multiple nodes
```bash
python mnist_trainer.py --gpus 4 --nodes 4 --precision 16
```
"""
@Time : 2020/6/23 12:53
@Author : Qin Dian
@Manual :
"""
from pytorch_lightning import Trainer, seed_everything
import os
import torch
from torch.nn import functional as F
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
import torchvision.transforms as transforms
from argparse import ArgumentParser
import pytorch_lightning as pl
class CoolSystem(pl.LightningModule):
def __init__(self, hparams):
super(CoolSystem, self).__init__()
# not the best model...
self.hparams = hparams
self.l1 = torch.nn.Linear(28 * 28, 10)
def forward(self, x):
return torch.relu(self.l1(x.view(x.size(0), -1)))
def training_step(self, batch, batch_idx):
# REQUIRED
x, y = batch
y_hat = self.forward(x)
loss = F.cross_entropy(y_hat, y)
tensorboard_logs = {'train_loss': loss}
return {'loss': loss, 'log': tensorboard_logs}
def validation_step(self, batch, batch_idx):
# OPTIONAL
x, y = batch
y_hat = self.forward(x)
return {'val_loss': F.cross_entropy(y_hat, y)}
def validation_epoch_end(self, outputs):
# OPTIONAL
avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()
tensorboard_logs = {'avg_val_loss': avg_loss}
return {'val_loss': avg_loss, 'log': tensorboard_logs}
def test_step(self, batch, batch_idx):
# OPTIONAL
x, y = batch
y_hat = self.forward(x)
return {'test_loss': F.cross_entropy(y_hat, y)}
def test_epoch_end(self, outputs):
# OPTIONAL
avg_loss = torch.stack([x['test_loss'] for x in outputs]).mean()
tensorboard_logs = {'test_val_loss': avg_loss}
return {'test_loss': avg_loss, 'log': tensorboard_logs}
def configure_optimizers(self):
# REQUIRED
# can return multiple optimizers and learning_rate schedulers
return torch.optim.Adam(self.parameters(), lr=self.hparams.learning_rate)
def train_dataloader(self):
# REQUIRED
return DataLoader(MNIST(os.getcwd(), train=True, download=True, transform=transforms.ToTensor()),
batch_size=self.hparams.batch_size)
def val_dataloader(self):
# OPTIONAL
return DataLoader(MNIST(os.getcwd(), train=True, download=True, transform=transforms.ToTensor()),
batch_size=self.hparams.batch_size)
def test_dataloader(self):
# OPTIONAL
return DataLoader(MNIST(os.getcwd(), train=True, download=True, transform=transforms.ToTensor()),
batch_size=self.hparams.batch_size)
@staticmethod
def add_model_specific_args(parent_parser):
"""
Specify the hyperparams for this LightningModule
"""
# MODEL specific
parser = ArgumentParser(parents=[parent_parser], add_help=False)
parser.add_argument('--learning_rate', default=0.02, type=float)
parser.add_argument('--batch_size', default=240, type=int)
# training specific (for this model)
parser.add_argument('--max_nb_epochs', default=100, type=int)
return parser
seed_everything(123)
def main(args):
# init module
model = CoolSystem(hparams=args)
# most basic trainer, uses good defaults
trainer = Trainer.from_argparse_args(args, gpus=2)
trainer.fit(model)
trainer.test()
if __name__ == '__main__':
parser = ArgumentParser(add_help=False)
# add args from trainer
parser = Trainer.add_argparse_args(parser)
# give the module a chance to add own params
# good practice to define LightningModule speficic params in the module
parser = CoolSystem.add_model_specific_args(parser)
# parse params
args = parser.parse_args()
main(args)
"""
This file defines the core research contribution
"""
import os
import torch
from torch.nn import functional as F
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
import torchvision.transforms as transforms
from argparse import ArgumentParser
import pytorch_lightning as pl
class CoolSystem(pl.LightningModule):
def __init__(self, hparams):
super(CoolSystem, self).__init__()
# not the best model...
self.hparams = hparams
self.l1 = torch.nn.Linear(28 * 28, 10)
def forward(self, x):
return torch.relu(self.l1(x.view(x.size(0), -1)))
def training_step(self, batch, batch_idx):
# REQUIRED
x, y = batch
y_hat = self.forward(x)
loss = F.cross_entropy(y_hat, y)
tensorboard_logs = {'train_loss': loss}
return {'loss': loss, 'log': tensorboard_logs}
def validation_step(self, batch, batch_idx):
# OPTIONAL
x, y = batch
y_hat = self.forward(x)
return {'val_loss': F.cross_entropy(y_hat, y)}
def validation_epoch_end(self, outputs):
# OPTIONAL
avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()
tensorboard_logs = {'avg_val_loss': avg_loss}
return {'val_loss': avg_loss, 'log': tensorboard_logs}
def test_step(self, batch, batch_idx):
# OPTIONAL
x, y = batch
y_hat = self.forward(x)
return {'test_loss': F.cross_entropy(y_hat, y)}
def test_epoch_end(self, outputs):
# OPTIONAL
avg_loss = torch.stack([x['test_loss'] for x in outputs]).mean()
tensorboard_logs = {'test_val_loss': avg_loss}
return {'test_loss': avg_loss, 'log': tensorboard_logs}
def configure_optimizers(self):
# REQUIRED
# can return multiple optimizers and learning_rate schedulers
return torch.optim.Adam(self.parameters(), lr=self.hparams.learning_rate)
def train_dataloader(self):
# REQUIRED
return DataLoader(MNIST(os.getcwd(), train=True, download=True, transform=transforms.ToTensor()), batch_size=self.hparams.batch_size)
def val_dataloader(self):
# OPTIONAL
return DataLoader(MNIST(os.getcwd(), train=True, download=True, transform=transforms.ToTensor()), batch_size=self.hparams.batch_size)
def test_dataloader(self):
# OPTIONAL
return DataLoader(MNIST(os.getcwd(), train=True, download=True, transform=transforms.ToTensor()), batch_size=self.hparams.batch_size)
@staticmethod
def add_model_specific_args(parent_parser):
"""
Specify the hyperparams for this LightningModule
"""
# MODEL specific
parser = ArgumentParser(parents=[parent_parser], add_help=False)
parser.add_argument('--learning_rate', default=0.02, type=float)
parser.add_argument('--batch_size', default=32, type=int)
# training specific (for this model)
parser.add_argument('--max_nb_epochs', default=2, type=int)
return parser
"""
This file runs the main training/val loop, etc... using Lightning Trainer
"""
from pytorch_lightning import Trainer, seed_everything
from argparse import ArgumentParser
from mnist import CoolSystem
# sets seeds for numpy, torch, etc...
# must do for DDP to work well
seed_everything(123)
def main(args):
# init module
model = CoolSystem(hparams=args)
# most basic trainer, uses good defaults
trainer = Trainer.from_argparse_args(args)
trainer.fit(model)
trainer.test()
if __name__ == '__main__':
parser = ArgumentParser(add_help=False)
parser.add_argument('--gpus', default=2)
# add args from trainer
parser = Trainer.add_argparse_args(parser)
# give the module a chance to add own params
# good practice to define LightningModule speficic params in the module
parser = CoolSystem.add_model_specific_args(parser)
# parse params
args = parser.parse_args()
main(args)
"""
@Time : 2019/12/10 14:29
@Author : Qin Dian
@Manual :
"""
import numpy as np
import os
import argparse
from glob import glob
from multiprocessing.dummy import Pool
from skimage import measure
parser = argparse.ArgumentParser(description='Slice Maker')
parser.add_argument('--in_path', type=str, default=r'D:\A_UNET\in')
parser.add_argument('--out_path', type=str, default=r'D:\A_UNET\out')
parser.add_argument('--generate_tumor_index', type=bool, default=True, help='是否生成肿瘤指示列表文件')
parser.add_argument('--series_index', type=int, default=0, help='哪一期的肿瘤指示列表')
parser.add_argument('--list_path', type=str, default=r'D:\A_UNET')
parser.add_argument('--process_num', type=int, default=20)
args = parser.parse_args()
def main():
if not os.path.exists(args.out_path):
os.mkdir(args.out_path)
paths = glob(os.path.join(args.in_path, "ct*.npz"))
pool = Pool(args.process_num)
result = pool.map(make_slice, paths)
if args.generate_tumor_index:
tumor_slices = []
for i in result:
tumor_slices += i
np.save(os.path.join(args.list_path, f'tumor_slices_s{args.series_index}.npy'), tumor_slices)
def make_slice(path):
result = []
ct = np.load(path, allow_pickle=True)
names = os.path.split(path)
mask = np.load(os.path.join(names[0], names[1][3:]), allow_pickle=True)
ct = ct.get('arrays', ct.get('arr_0'))
ct = ct.reshape(3, -1, 512, 512)
mask = mask.get('arrays', mask.get('arr_0'))
mask = mask.reshape(3, -1, 512, 512)
case = names[1][3:].split('.')[0]
for i in range(ct.shape[1]):
ct_slice = ct[:, i, ...]
mask_slice = mask[:, i, ...]
if np.any(mask_slice > 1):
# format of center: {0:[[x,y,h,w,c], ...], 1:[[x,y,h,w,c], ...], 2:[[x,y,h,w,c]}
# h:max_x-min_x, w: max_y-min_y,
# 即三期各期的中心点list
centers = {}
for series_i in range(3):
t_mask = mask_slice[series_i] >> 1
tumors = measure.label((t_mask > 0).astype(np.uint8), connectivity=1)
regions = measure.regionprops(tumors)
s_centers = []
for region in regions:
min_x, min_y, max_x, max_y = region.bbox
s_centers.append([(min_x+max_x)//2, (min_y+max_y)//2, max_x-min_x, max_y-min_y,
t_mask[(min_x+max_x)//2, (min_y+max_y)//2]])
centers[series_i] = s_centers
np.savez_compressed(f'{args.out_path}/{case}_{i}.npz', ct=ct_slice, mask=mask_slice, centers=centers)
# 只记录有tumor的slice
if args.generate_tumor_index and np.any(mask_slice[args.series_index] > 1):
print(f'{case}_{i}.npz')
result.append(f'{case}_{i}.npz')
else:
np.savez_compressed(f'{args.out_path}/{case}_{i}.npz', ct=ct_slice, mask=mask_slice)
print(f'complete making slices of {case}')
return result
if __name__ == '__main__':
main()
"""
@Time : 2020/6/1 16:30
@Author : Qin Dian
@Manual :
"""
\ No newline at end of file
"""
@Time : 2020/7/3 11:13
@Author : Qin Dian
@Manual :
"""
import torch
from torch import nn
import torch.nn.functional as f
class FocalLoss(nn.Module):
'''nn.Module warpper for focal loss'''
def __init__(self):
super(FocalLoss, self).__init__()
self.neg_loss = _neg_loss
def forward(self, out, target):
return self.neg_loss(out, target)
class IndL1Loss1d(nn.Module):
def __init__(self, task='l1'):
super(IndL1Loss1d, self).__init__()
if task == 'l1':
self.loss = f.l1_loss
elif task == 'smooth_l1':
self.loss = f.smooth_l1_loss
def forward(self, output, target):
output = output * target.bool()
loss = self.loss(output, target, reduction='sum')
loss = loss / (target.bool().sum() + 1e-4)
return loss
def _neg_loss(pred, gt):
"""
Modified focal loss. Exactly the same as CornerNet.
Runs faster and costs a little bit more memory
Arguments:
pred (batch x c x h x w)
gt (batch x c x h x w)
"""
pos_inds = gt.eq(1).float()
neg_inds = gt.lt(1).float()
neg_weights = torch.pow(1 - gt, 4)
loss = 0
pos_loss = torch.log(pred) * torch.pow(1 - pred, 2) * pos_inds
neg_loss = torch.log(1 - pred) * torch.pow(pred, 2) * neg_weights * neg_inds
num_pos = pos_inds.float().sum()
pos_loss = pos_loss.sum()
neg_loss = neg_loss.sum()
if num_pos == 0:
loss = loss - neg_loss
else:
loss = loss - (pos_loss + neg_loss) / num_pos
return loss
"""
@Time : 2020/6/17 14:08
@Author : Qin Dian
@Manual :
"""
"""
@Time : 2020/6/17 14:09
@Author : Qin Dian
@Manual :
"""
import torch
import numpy as np
def to_3channel_replica(img):
"""
convert 1 channel gray image to 3 channel by replicate itself 3 times
:param img:
:return:
"""
if len(img.shape) > 2:
ret = np.stack((img, img, img), axis=1)
else:
ret = np.stack((img, img, img), axis=0)
return ret
def cut_384(img):
"""
cut a 512*512 ct img to 385*384
:param img:
:return:
"""
if len(img.shape) > 2:
ret = img[:, 50:434, 60:444]
else:
ret = img[50:434, 60:444]
return ret
def clip_to_image(bbox, h, w):
"""
keep bbox in the image
"""
bbox[..., :2] = torch.clamp(bbox[..., :2], min=0)
bbox[..., 2] = torch.clamp(bbox[..., 2], max=w-1)
bbox[..., 3] = torch.clamp(bbox[..., 3], max=h-1)
return bbox
def window_standardize(img, lower_bound, upper_bound):
"""
clip the pixel values into [lower_bound, upper_bound], and standardize them
"""
img = np.clip(img, lower_bound, upper_bound)
# x=x*2-1: map x to [-1,1]
img = 2 * (img - lower_bound) / (upper_bound - lower_bound) - 1
return img
def draw_umich_gaussian(heat_map, center, h, w, k=1):
"""
draw gaussian radius for 'center' in 'heat_map'
:param heat_map: heat_map canvas
:param center: gaussian center
:param w: width
:param h: height
:param k:
:return:
"""
radius = _gaussian_radius((h, w))
radius = max(0, int(radius))
diameter = 2 * radius + 1
gaussian = _gaussian2d((diameter, diameter), sigma=diameter / 6)
x, y = int(center[0]), int(center[1])
height, width = heat_map.shape[:2]
left, right = min(x, radius), min(width - x, radius + 1)
top, bottom = min(y, radius), min(height - y, radius + 1)
masked_heat_map = heat_map[y - top:y + bottom, x - left:x + right]
masked_gaussian = gaussian[radius - top:radius + bottom, radius - left:radius + right]
if min(masked_gaussian.shape) > 0 and min(masked_heat_map.shape) > 0:
np.maximum(masked_heat_map, masked_gaussian * k, out=masked_heat_map)
return heat_map
def _gaussian2d(shape, sigma=(1, 1), rho=0):
if not isinstance(sigma, tuple):
sigma = (sigma, sigma)
sigma_x, sigma_y = sigma
m, n = [(ss - 1.) / 2. for ss in shape]
y, x = np.ogrid[-m:m+1, -n:n+1]
energy = (x * x) / (sigma_x * sigma_x) - 2 * rho * x * y / (sigma_x * sigma_y) + (y * y) / (sigma_y * sigma_y)
h = np.exp(-energy / (2 * (1 - rho * rho)))
h[h < np.finfo(h.dtype).eps * h.max()] = 0
return h
def _gaussian_radius(det_size, min_overlap=0.7):
height, width = det_size
a1 = 1
b1 = (height + width)
c1 = width * height * (1 - min_overlap) / (1 + min_overlap)
sq1 = np.sqrt(b1 ** 2 - 4 * a1 * c1)
r1 = (b1 + sq1) / 2
a2 = 4
b2 = 2 * (height + width)
c2 = (1 - min_overlap) * width * height
sq2 = np.sqrt(b2 ** 2 - 4 * a2 * c2)
r2 = (b2 + sq2) / 2
a3 = 4 * min_overlap
b3 = -2 * min_overlap * (height + width)
c3 = (min_overlap - 1) * width * height
if b3 ** 2 - 4 * a3 * c3 < 0:
r3 = min(r1, r2)
else:
sq3 = np.sqrt(b3 ** 2 - 4 * a3 * c3)
r3 = (b3 + sq3) / 2
return min(r1, r2, r3)
\ No newline at end of file
"""
@Time : 2020/7/9 16:09
@Author : Qin Dian
@Manual :
"""
import matplotlib.pyplot as plt
plt.subplot(221)
plt.imshow(ct[1,2].cpu(), cmap='gray')
plt.subplot(222)
plt.imshow(hm[1,2].cpu())
plt.subplot(223)
plt.imshow(wh[1,0].cpu())
plt.subplot(224)
plt.imshow(wh[1,1].cpu())
plt.show()
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi']=300
plt.subplot(321)
plt.imshow(ct, cmap='gray')
plt.subplot(322)
plt.imshow(hm[0])
plt.subplot(323)
plt.imshow(hm[1])
plt.subplot(324)
plt.imshow(hm[2])
plt.subplot(325)
plt.imshow(mask)
plt.show()
import matplotlib.pyplot as plt
plt.subplot(221)
plt.imshow(x[74,0].cpu(), cmap='gray')
plt.subplot(222)
plt.imshow(out[2,0].cpu())
plt.subplot(223)
plt.imshow(out[2,0].cpu())
plt.subplot(224)
plt.imshow(out[2,0].cpu())
plt.show()
\ No newline at end of file
"""
@Time : 2020/6/17 14:19
@Author : Qin Dian
@Manual :
"""
import torch
import torch.nn.functional as F
def clipped_sigmoid(x):
y = torch.clamp(x.sigmoid(), min=1e-4, max=1 - 1e-4)
return y
def nms(heat, kernel=3):
"""
Make finding top k center points more convenient by using max pooling
"""
pad = (kernel - 1) // 2
hmax = F.max_pool2d(
heat, (kernel, kernel), stride=1, padding=pad)
keep = (hmax == heat).type(torch.FloatTensor).to(heat.device)
return heat * keep
def gather_feat(feat, ind, mask=None):
dim = feat.size(2)
ind = ind.unsqueeze(2).expand(ind.size(0), ind.size(1), dim)
feat = feat.gather(1, ind)
if mask is not None:
mask = mask.unsqueeze(2).expand_as(feat)
feat = feat[mask]
feat = feat.view(-1, dim)
return feat
def topk(scores, k=40):
batch, cat, height, width = scores.size()
topk_scores, topk_inds = torch.topk(scores.view(batch, cat, -1), k)
topk_inds = topk_inds % (height * width)
topk_ys = (topk_inds / width).int().float()
topk_xs = (topk_inds % width).int().float()
topk_score, topk_ind = torch.topk(topk_scores.view(batch, -1), k)
topk_clses = (topk_ind / k).int()
topk_inds = gather_feat(
topk_inds.view(batch, -1, 1), topk_ind).view(batch, k)
topk_ys = gather_feat(topk_ys.view(batch, -1, 1), topk_ind).view(batch, k)
topk_xs = gather_feat(topk_xs.view(batch, -1, 1), topk_ind).view(batch, k)
return topk_score, topk_inds, topk_clses, topk_ys, topk_xs
def transpose_and_gather_feat(feat, ind):
feat = feat.permute(0, 2, 3, 1).contiguous()
feat = feat.view(feat.size(0), -1, feat.size(3))
feat = gather_feat(feat, ind)
return feat
def extract_top_k_ctp_dt(ct_hm, wh, reg=None, k=100):
batch, cat, height, width = ct_hm.size()
ct_hm = nms(ct_hm)
scores, inds, clses, ys, xs = topk(ct_hm, k=k)
wh = transpose_and_gather_feat(wh, inds)
wh = wh.view(batch, k, 2)
if reg is not None:
reg = transpose_and_gather_feat(reg, inds)
reg = reg.view(batch, k, 2)
xs = xs.view(batch, k, 1) + reg[:, :, 0:1]
ys = ys.view(batch, k, 1) + reg[:, :, 1:2]
else:
xs = xs.view(batch, k, 1)
ys = ys.view(batch, k, 1)
clses = clses.view(batch, k, 1).float()
scores = scores.view(batch, k, 1)
ct = torch.cat([xs, ys], dim=2)
bboxes = torch.cat([xs - wh[..., 0:1] / 2,
ys - wh[..., 1:2] / 2,
xs + wh[..., 0:1] / 2,
ys + wh[..., 1:2] / 2], dim=2)
detection = torch.cat([bboxes, scores, clses], dim=2)
return ct, detection
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment