예제 #1
0
 def test_shape(self, input_data, expected_shape):
     if input_data["model"] == "densenet2d":
         model = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
     if input_data["model"] == "densenet3d":
         model = DenseNet(spatial_dims=3,
                          in_channels=1,
                          out_channels=3,
                          init_features=2,
                          growth_rate=2,
                          block_config=(6, ))
     if input_data["model"] == "senet2d":
         model = SEResNet50(spatial_dims=2, in_channels=3, num_classes=4)
     if input_data["model"] == "senet3d":
         model = SEResNet50(spatial_dims=3, in_channels=3, num_classes=4)
     device = "cuda:0" if torch.cuda.is_available() else "cpu"
     model.to(device)
     model.eval()
     cam = CAM(nn_module=model,
               target_layers=input_data["target_layers"],
               fc_layers=input_data["fc_layers"])
     image = torch.rand(input_data["shape"], device=device)
     result = cam(x=image, layer_idx=-1)
     fea_shape = cam.feature_map_size(input_data["shape"], device=device)
     self.assertTupleEqual(fea_shape, input_data["feature_shape"])
     self.assertTupleEqual(result.shape, expected_shape)
def run_inference_test(root_dir,
                       test_x,
                       test_y,
                       device="cuda:0",
                       num_workers=10):
    # define transforms for image and classification
    val_transforms = Compose(
        [LoadImage(image_only=True),
         AddChannel(),
         ScaleIntensity()])
    val_ds = MedNISTDataset(test_x, test_y, val_transforms)
    val_loader = DataLoader(val_ds, batch_size=300, num_workers=num_workers)

    model = DenseNet121(spatial_dims=2,
                        in_channels=1,
                        out_channels=len(np.unique(test_y))).to(device)

    model_filename = os.path.join(root_dir, "best_metric_model.pth")
    model.load_state_dict(torch.load(model_filename))
    y_true = []
    y_pred = []
    with eval_mode(model):
        for test_data in val_loader:
            test_images, test_labels = test_data[0].to(
                device), test_data[1].to(device)
            pred = model(test_images).argmax(dim=1)
            for i in range(len(pred)):
                y_true.append(test_labels[i].item())
                y_pred.append(pred[i].item())
    tps = [
        np.sum((np.asarray(y_true) == idx) & (np.asarray(y_pred) == idx))
        for idx in np.unique(test_y)
    ]
    return tps
예제 #3
0
 def test_shape(self, input_data, expected_shape):
     if input_data["model"] == "densenet2d":
         model = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
     if input_data["model"] == "densenet3d":
         model = DenseNet(spatial_dims=3,
                          in_channels=1,
                          out_channels=3,
                          init_features=2,
                          growth_rate=2,
                          block_config=(6, ))
     if input_data["model"] == "senet2d":
         model = SEResNet50(spatial_dims=2, in_channels=3, num_classes=4)
     if input_data["model"] == "senet3d":
         model = SEResNet50(spatial_dims=3, in_channels=3, num_classes=4)
     device = "cuda:0" if torch.cuda.is_available() else "cpu"
     model.to(device)
     model.eval()
     cam = GradCAM(nn_module=model,
                   target_layers=input_data["target_layers"])
     image = torch.rand(input_data["shape"], device=device)
     result = cam(x=image, layer_idx=-1)
     np.testing.assert_array_equal(cam.nn_module.class_idx.cpu(),
                                   model(image).max(1)[-1].cpu())
     fea_shape = cam.feature_map_size(input_data["shape"], device=device)
     self.assertTupleEqual(fea_shape, input_data["feature_shape"])
     self.assertTupleEqual(result.shape, expected_shape)
     # check result is same whether class_idx=None is used or not
     result2 = cam(x=image,
                   layer_idx=-1,
                   class_idx=model(image).max(1)[-1].cpu())
     np.testing.assert_array_almost_equal(result, result2)
예제 #4
0
 def test_ill(self):
     model = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
     for name, x in model.named_parameters():
         if "features" in name:
             x.requires_grad = False
     cam = GradCAM(nn_module=model, target_layers="class_layers.relu")
     image = torch.rand((2, 1, 48, 64))
     with self.assertRaises(IndexError):
         cam(x=image)
예제 #5
0
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest

import torch
from parameterized import parameterized

from monai.networks.nets import DenseNet, DenseNet121
from monai.visualize import OcclusionSensitivity

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
out_channels_2d = 4
out_channels_3d = 3
model_2d = DenseNet121(spatial_dims=2,
                       in_channels=1,
                       out_channels=out_channels_2d).to(device)
model_2d_2c = DenseNet121(spatial_dims=2,
                          in_channels=2,
                          out_channels=out_channels_2d).to(device)
model_3d = DenseNet(spatial_dims=3,
                    in_channels=1,
                    out_channels=out_channels_3d,
                    init_features=2,
                    growth_rate=2,
                    block_config=(6, )).to(device)
model_2d.eval()
model_2d_2c.eval()
model_3d.eval()

# 2D w/ bounding box
def run_training_test(root_dir, train_x, train_y, val_x, val_y, device="cuda:0", num_workers=10):

    monai.config.print_config()
    # define transforms for image and classification
    train_transforms = Compose(
        [
            LoadImage(image_only=True),
            AddChannel(),
            Transpose(indices=[0, 2, 1]),
            ScaleIntensity(),
            RandRotate(range_x=np.pi / 12, prob=0.5, keep_size=True, dtype=np.float64),
            RandFlip(spatial_axis=0, prob=0.5),
            RandZoom(min_zoom=0.9, max_zoom=1.1, prob=0.5),
            ToTensor(),
        ]
    )
    train_transforms.set_random_state(1234)
    val_transforms = Compose(
        [LoadImage(image_only=True), AddChannel(), Transpose(indices=[0, 2, 1]), ScaleIntensity(), ToTensor()]
    )
    y_pred_trans = Compose([ToTensor(), Activations(softmax=True)])
    y_trans = Compose([ToTensor(), AsDiscrete(to_onehot=len(np.unique(train_y)))])
    auc_metric = ROCAUCMetric()

    # create train, val data loaders
    train_ds = MedNISTDataset(train_x, train_y, train_transforms)
    train_loader = DataLoader(train_ds, batch_size=300, shuffle=True, num_workers=num_workers)

    val_ds = MedNISTDataset(val_x, val_y, val_transforms)
    val_loader = DataLoader(val_ds, batch_size=300, num_workers=num_workers)

    model = DenseNet121(spatial_dims=2, in_channels=1, out_channels=len(np.unique(train_y))).to(device)
    loss_function = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), 1e-5)
    epoch_num = 4
    val_interval = 1

    # start training validation
    best_metric = -1
    best_metric_epoch = -1
    epoch_loss_values = []
    metric_values = []
    model_filename = os.path.join(root_dir, "best_metric_model.pth")
    for epoch in range(epoch_num):
        print("-" * 10)
        print(f"Epoch {epoch + 1}/{epoch_num}")
        model.train()
        epoch_loss = 0
        step = 0
        for batch_data in train_loader:
            step += 1
            inputs, labels = batch_data[0].to(device), batch_data[1].to(device)
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = loss_function(outputs, labels)
            loss.backward()
            optimizer.step()
            epoch_loss += loss.item()
        epoch_loss /= step
        epoch_loss_values.append(epoch_loss)
        print(f"epoch {epoch + 1} average loss:{epoch_loss:0.4f}")

        if (epoch + 1) % val_interval == 0:
            with eval_mode(model):
                y_pred = torch.tensor([], dtype=torch.float32, device=device)
                y = torch.tensor([], dtype=torch.long, device=device)
                for val_data in val_loader:
                    val_images, val_labels = val_data[0].to(device), val_data[1].to(device)
                    y_pred = torch.cat([y_pred, model(val_images)], dim=0)
                    y = torch.cat([y, val_labels], dim=0)

                # compute accuracy
                acc_value = torch.eq(y_pred.argmax(dim=1), y)
                acc_metric = acc_value.sum().item() / len(acc_value)
                # decollate prediction and label and execute post processing
                y_pred = [y_pred_trans(i) for i in decollate_batch(y_pred)]
                y = [y_trans(i) for i in decollate_batch(y)]
                # compute AUC
                auc_metric(y_pred, y)
                auc_value = auc_metric.aggregate()
                auc_metric.reset()
                metric_values.append(auc_value)
                if auc_value > best_metric:
                    best_metric = auc_value
                    best_metric_epoch = epoch + 1
                    torch.save(model.state_dict(), model_filename)
                    print("saved new best metric model")
                print(
                    f"current epoch {epoch +1} current AUC: {auc_value:0.4f} "
                    f"current accuracy: {acc_metric:0.4f} best AUC: {best_metric:0.4f} at epoch {best_metric_epoch}"
                )
    print(f"train completed, best_metric: {best_metric:0.4f}  at epoch: {best_metric_epoch}")
    return epoch_loss_values, best_metric, best_metric_epoch
예제 #7
0
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest

import torch
from parameterized import parameterized

from monai.networks.nets import DenseNet, DenseNet121, SEResNet50
from monai.visualize import GuidedBackpropGrad, GuidedBackpropSmoothGrad, SmoothGrad, VanillaGrad

DENSENET2D = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
DENSENET3D = DenseNet(spatial_dims=3,
                      in_channels=1,
                      out_channels=3,
                      init_features=2,
                      growth_rate=2,
                      block_config=(6, ))
SENET2D = SEResNet50(spatial_dims=2, in_channels=3, num_classes=4)
SENET3D = SEResNet50(spatial_dims=3, in_channels=3, num_classes=4)

TESTS = []
for type in (VanillaGrad, SmoothGrad, GuidedBackpropGrad,
             GuidedBackpropSmoothGrad):
    # 2D densenet
    TESTS.append([type, DENSENET2D, (1, 1, 48, 64), (1, 1, 48, 64)])
    # 3D densenet
예제 #8
0
    val_loader = torch.utils.data.DataLoader(val_ds,
                                             batch_size=BATCH_SIZE,
                                             num_workers=0)

    test_ds = MedNISTDataset(test_x, test_y, val_transforms)
    test_loader = torch.utils.data.DataLoader(test_ds,
                                              batch_size=BATCH_SIZE,
                                              num_workers=0)

    # Defining Network and Optimizer
    if torch.cuda.is_available():
        device = torch.device('cuda:0')
    else:
        device = torch.device('cpu')

    model = DenseNet121(spatial_dims=2, in_channels=1,
                        out_channels=num_class).to(device)
    loss_function = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), 1e-5)
    max_epochs = 4
    val_interval = 1

    # Model training
    best_metric = -1
    best_metric_epoch = -1
    epoch_loss_values = []
    metric_values = []

    for epoch in range(max_epochs):
        print("-" * 10)
        print(f"epoch {epoch + 1}/{max_epochs}")
        model.train()
예제 #9
0
 def setUp(self):
     self.net = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
     self.num_relus = self.get_num_modules(torch.nn.ReLU)
     self.total = self.get_num_modules()
     self.assertGreater(self.num_relus, 0)