def predict_agument(data, **kwargs):
    """
        模型预测,单张图片复制
        :param
            data(tensor) -- 图片数据
        :kwargs

        :return(numpy)
            预测结果
    """
    # 选择运行的cpu或gpu
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    # 加载模型
    models = []
    for k, v in kwargs.items():
        if k == '1':
            model = MFFNet()
        elif k == '2':
            # 299 x 299
            model = inception(pretrained = False)
        elif k == '3':
            model = resnet(pretrained = False)
        elif k == '4':
            model = densenet(pretrained = False)
        elif k == '5':
            model = senet(pretrained = False)
        # 加载权重
        model.load_state_dict(torch.load(v))
        model = model.to(device)
        # 测试模式
        model.eval()
        models.append(model)

    # 使用平均策略获取集成模型输出
    data = data.to(device)
    sum = None
    # 平均策略
    for model in models:
        output = model(data)
        output = output.detach()
        val = torch.zeros(7)
        for i in range(output.size(0)):
            val = val + output[i]
        val = val / output.size(0)

        if sum is None:
            sum = val
        else:
            sum += val
    val = sum / len(models)
    _, a = torch.max(val, 0)

    return a.item()
def predict(data, **kwargs):
    """
    模型预测,单张图片不复制
    :param
        data(tensor) -- 图片数据
    :kwargs

    :return(numpy)
        预测结果
    """
    # 选择运行的cpu或gpu
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    # 加载模型
    models = []
    for k, v in kwargs.items():
        if k == '1':
            model = MFFNet()
        elif k == '2':
            # 299 x 299
            model = inception(pretrained = False)
        elif k == '3':
            model = resnet(pretrained = False)
        elif k == '4':
            model = densenet(pretrained = False)
        elif k == '5':
            model = senet(pretrained = False)
        # 加载权重
        model.load_state_dict(torch.load(v))
        model = model.to(device)
        # 测试模式
        model.eval()
        models.append(model)

    # 使用平均策略获取集成模型输出
    data = data.to(device)
    output = None
    # 平均策略
    for model in models:
        if output is None:
            output = model(data).detach()
        else:
            output += model(data).detach()
    output = output / len(models)
    _, a = torch.max(output, 1)
    a = a.cpu().detach().numpy()

    # 预测结果
    return a
Exemplo n.º 3
0
def test(test_path, agumentation, **kwargs):
    """
    测试模型性能
    :param
        test_path(str) -- 测试集地址
        agumentation(bool) -- 是否对单个图片多次复制
    :kwargs
        model(int) -- 模型
    """
    # 设置超参数
    if agumentation:
        BATCH_SIZE = 1
    else:
        BATCH_SIZE = 32

    # 选择运行的cpu或gpu
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    # 定义损失函数
    # N / n,权重为各类别频率的倒数
    weight = torch.Tensor([9., 1.5, 19.48, 30.62, 9.11, 86.86, 71.])
    weight = weight.to(device)
    criterion = nn.CrossEntropyLoss(weight=weight)

    # 数据处理
    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
    test_transform = transforms.Compose(
        [transforms.RandomCrop(224),
         transforms.ToTensor(), normalize])

    # 加载数据
    # 定义test_loader
    test_dataset = SkinDiseaseDataset(test_path,
                                      transforms=test_transform,
                                      agumentation=agumentation)
    test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE)

    # 加载模型
    if kwargs['model'] == 1:
        model = MFFNet()
    elif kwargs['model'] == 2:
        # 299 x 299
        model = inception(pretrained=False)
    elif kwargs['model'] == 3:
        model = resnet(pretrained=False)
    elif kwargs['model'] == 4:
        model = densenet(pretrained=False)
    elif kwargs['model'] == 5:
        model = senet(pretrained=False)
    # 加载模型权重
    model.load_state_dict(torch.load(CONFIG.best_model))
    model = model.to(device)

    # 测试模式
    model.eval()
    # 各类别预测正确个数
    class_correct = list(0. for i in range(7))
    # 各类别总个数
    class_total = list(0. for i in range(7))
    # 损失
    sum_loss = 0.0
    # 总预测正确个数
    correct = 0
    # 总个数
    total = 0
    # 总迭代次数
    cnt = 0
    # 测试集增强模式
    if agumentation:
        # 预测标签情况
        x = []
        # 真实标签情况
        y = []
        for data in test_loader:
            cnt += 1

            # 加载数据
            image, label = data
            image = image.view(-1, 3, 224, 224)
            label = label[0]
            image, label = image.to(device), label.to(device)

            # 前向传播
            output = model(image)

            # 使用平均策略获取预测值
            output = output.detach()
            # 平均策略
            val = None
            for i in range(output.size(0)):
                if val is None:
                    val = output[i]
                else:
                    val = val + output[i]
            val = val / output.size(0)
            _, a = torch.max(val, 0)

            # 统计各个类预测正确的个数
            m = label.detach()
            class_correct[m] += 1 if a == m else 0
            class_total[m] += 1
            # 统计预测正确总个数
            correct += 1 if a == m else 0

            x.append(a.item())
            y.append(m.item())
        # list转化为numpy
        x = np.array(x)
        y = np.array(y)
    else:
        # 预测标签情况
        x = None
        # 真实标签情况
        y = None
        for data in test_loader:
            cnt += 1

            # 加载数据
            image, label = data
            image, label = image.to(device), label.to(device)

            # 前向传播
            output = model(image)
            loss = criterion(output, label)

            # 计算loss和acc
            sum_loss += loss.item()
            _, a = torch.max(output.detach(), 1)
            b = label.detach()
            total += label.size(0)
            correct += (a == b).sum()

            # 预测和真实标签情况
            if x is None:
                x = a
                y = b
            else:
                x = torch.cat((x, a))
                y = torch.cat((y, b))

            # 统计每个类别的正确预测情况
            for i in range(label.size(0)):
                m = b[i]
                class_correct[m] += 1 if a[i] == m else 0
                class_total[m] += 1
        # tensor转化为numpy
        x = x.cpu().detach().numpy()
        y = y.cpu().detach().numpy()

    # 打印结果
    cm_plot_labels = ['MEL', 'NV', 'BCC', 'AKIEC', 'BKL', 'DF', 'VASC']
    # 判断测试集是否增强
    if agumentation:
        # 打印acc
        print("test_acc:%.2f%%\n" % (100 * correct / cnt))
    else:
        # 打印loss和acc
        print("test_loss:%.2f test_acc:%.2f%%\n" %
              (sum_loss / cnt, 100 * correct / total))
    # 打印每个类别的acc
    for i in range(7):
        if class_total[i] > 0:
            print('Test Accuracy of %5s: %.2f%% (%2d/%2d)' %
                  (cm_plot_labels[i], 100 * class_correct[i] / class_total[i],
                   class_correct[i], class_total[i]))
        else:
            print('Test Accuracy of %5s: N/A (no training examples)' %
                  cm_plot_labels[i])
    print('')

    # 计算混淆矩阵
    cm = confusion_matrix(y, x)
    print('')

    # 计算BMC
    balanced_multiclass_accuracy(cm)
    print('')

    # 可视化混淆矩阵
    plot_confusion_matrix(cm, cm_plot_labels, title='Confusion Matrix')
    print('')

    # 打印分类报告
    report = classification_report(y, x, target_names=cm_plot_labels)
    print(report)
Exemplo n.º 4
0
def train(train_path, val_path, **kwargs):
    """
    训练模型
    :param
        train_path(str) -- 训练集地址
        val_path(str) -- 验证集地址
    : kwargs
        model(int) -- 训练模型
        epoch(int) -- 训练轮数
        batch_size(int) -- 训练批次大小
        learn_rate(int) -- 学习率
    :return
        返回训练集损失(list)、验证集损失(list)
    """
    # 设置超参数
    lrs = [1e-3, 1e-4, 1e-5]
    # 学习率
    LR = lrs[kwargs['learn_rate'] - 1]
    # 训练轮数
    EPOCH = kwargs['epoch']
    # 批次大小
    BATCH_SIZE = kwargs['batch_size']

    # 数据处理
    normalize = transforms.Normalize(mean=[0.76209545, 0.54330575, 0.5679443],
                                     std=[0.14312604, 0.154518, 0.17225058])
    train_transform = transforms.Compose([
        transforms.RandomCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.RandomVerticalFlip(),
        transforms.RandomRotation(degrees=180),
        transforms.ColorJitter(brightness=0.1, contrast=0.1, saturation=0.1),
        transforms.ToTensor(), normalize
    ])
    val_transform = transforms.Compose(
        [transforms.RandomCrop(224),
         transforms.ToTensor(), normalize])

    # 加载数据
    #定义trainloader
    train_dataset = SkinDiseaseDataset(train_path,
                                       transforms=train_transform,
                                       agumentation=False)
    train_loader = DataLoader(
        train_dataset, batch_size=BATCH_SIZE,
        shuffle=True)  # sampler = ImbalancedDatasetSampler(train_dataset)

    #定义valloader
    val_dataset = SkinDiseaseDataset(val_path,
                                     transforms=val_transform,
                                     agumentation=False)
    val_loader = DataLoader(val_dataset, batch_size=BATCH_SIZE)

    # 选择运行的cpu或gpu
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    # 加载模型
    if kwargs['model'] == 1:
        model = MFFNet()
    elif kwargs['model'] == 2:
        # 299 x 299
        model = inception()
    elif kwargs['model'] == 3:
        model = resnet()
    elif kwargs['model'] == 4:
        model = densenet()
    elif kwargs['model'] == 5:
        model = senet()
    # # 断点训练,加载模型权重
    # model.load_state_dict(torch.load(CONFIG.best_model))
    model = model.to(device)

    # 定义损失函数
    # N / n,权重为各类别频率的倒数
    weight = torch.Tensor([9., 1.5, 19.48, 30.62, 9.11, 86.86, 71.])
    weight = weight.to(device)
    criterion = nn.CrossEntropyLoss(weight=weight)

    # 定义优化器
    # optimizer = optim.SGD(model.parameters(), lr = LR, weight_decay = 1e-5)
    optimizer = optim.Adam(model.parameters(), lr=LR, weight_decay=1e-5)

    # 定义学习率调度策略
    scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,
                                                     patience=7,
                                                     verbose=True)

    # 可视化模型
    if kwargs['model'] == 2:
        summary(model, (3, 299, 299))
    else:
        summary(model, (3, 224, 224))
    print(model)

    # 在模型训练过程中,跟踪每一轮平均训练集损失
    avg_train_losses = []
    # 在模型训练过程中,跟踪每一轮平均验证集损失
    avg_valid_losses = []

    # EarlyStopping机制
    early_stopping = EarlyStopping(patience=12, verbose=True)

    # 训练模型
    for epoch in range(EPOCH):
        # 训练模式
        model.train()
        # 损失
        sum_loss = 0.0
        # 预测正确样本数
        correct = 0
        # 总样本数
        total = 0
        # 迭代次数
        cnt = 0
        for data in train_loader:
            cnt += 1

            # 加载数据
            image, label = data
            image, label = image.to(device), label.to(device)

            # 梯度置零
            optimizer.zero_grad()

            # 前向传播、后向传播
            output = model(image)
            loss = criterion(output, label)
            # inceptionV3
            # loss = criterion(output, label) + 0.4 * criterion(aux, label)
            loss.backward()
            optimizer.step()

            # 计算loss and acc
            sum_loss += loss.item()
            _, a = torch.max(output.detach(), 1)
            b = label.detach()
            total += label.size(0)
            correct += (a == b).sum()
        # 打印loss和acc
        print('[ %d/%d ] train_loss:%.2f train_acc:%.2f%%' %
              (epoch + 1, EPOCH, sum_loss / cnt, 100 * correct / total))
        avg_train_losses.append(sum_loss / cnt)

        # 验证模式
        model.eval()
        # 损失
        sum_loss = 0.0
        # 预测正确样本数
        correct = 0
        # 总样本数
        total = 0
        # 迭代次数
        cnt = 0
        for data in val_loader:
            cnt += 1

            # 加载数据
            image, label = data
            image, label = image.to(device), label.to(device)

            # 前向传播
            output = model(image)
            loss = criterion(output, label)

            # 计算loss和acc
            sum_loss += loss.item()
            _, a = torch.max(output.detach(), 1)
            b = label.detach()
            total += label.size(0)
            correct += (a == b).sum()
        # 打印loss和acc
        print("          val_loss:%.2f val_acc:%.2f%%" %
              (sum_loss / cnt, 100 * correct / total))
        avg_valid_losses.append(sum_loss / cnt)

        # earlyStopping机制
        early_stopping(sum_loss / cnt, model)
        # 学习率调度机制
        scheduler.step(sum_loss / cnt)

        # 保存模型
        torch.save(
            model.state_dict(),
            CONFIG.intermediate_model + '/checkpoint_%d.pt' % (epoch + 1))

        # 判断是否停止训练
        if early_stopping.early_stop:
            print("Early stopping")
            break

    return avg_train_losses, avg_valid_losses
def test(test_path, agumentation, **kwargs):
    """
        测试集成模型性能
        :param
            test_path(str) -- 测试集地址
            agumentation(bool) -- 是否对单个图片多次复制
        :kwargs
            model(int) -- 模型
    """
    # 设置超参数
    if agumentation:
        BATCH_SIZE = 1
    else:
        BATCH_SIZE = 32

    # 选择运行的cpu或gpu
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    # 数据处理
    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
    test_transform = transforms.Compose(
        [transforms.RandomCrop(224),
         transforms.ToTensor(), normalize])

    # 加载数据
    # 定义test_loader
    test_dataset = SkinDiseaseDataset(test_path,
                                      transforms=test_transform,
                                      agumentation=agumentation)
    test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE)

    # 加载模型
    models = []
    for k, v in kwargs.items():
        if k == '1':
            model = MFFNet()
        elif k == '2':
            # 299 x 299
            model = inception(pretrained=False)
        elif k == '3':
            model = resnet(pretrained=False)
        elif k == '4':
            model = densenet(pretrained=False)
        elif k == '5':
            model = senet(pretrained=False)
        model.load_state_dict(torch.load(v))
        model = model.to(device)
        # 测试模式
        model.eval()
        models.append(model)

    # 测试模型
    # 各类别预测正确个数
    class_correct = list(0. for i in range(7))
    # 各类别总个数
    class_total = list(0. for i in range(7))
    # 总预测正确个数
    correct = 0
    # 总个数
    total = 0
    # 总迭代次数
    cnt = 0
    # 测试集增强模式
    if agumentation:
        # 预测标签情况
        x = []
        # 真实标签情况
        y = []
        for data in test_loader:
            cnt += 1

            # 加载数据
            image, label = data
            image = image.view(-1, 3, 224, 224)
            label = label[0]
            image, label = image.to(device), label.to(device)

            # 使用平均策略获取预测值,即最终的输出为各模型输出和的平均
            sum = None
            # 平均策略
            for model in models:
                output = model(image)

                # 使用平均策略获取模型的输出
                output = output.detach()
                # 平均策略
                val = None
                for i in range(output.size(0)):
                    if val is None:
                        val = output[i]
                    else:
                        val = val + output[i]
                val = val / output.size(0)

                if sum is None:
                    sum = val
                else:
                    sum += val
            val = sum / len(models)
            _, a = torch.max(val, 0)

            # 统计各个类预测正确的个数
            m = label.detach()
            class_correct[m] += 1 if a == m else 0
            correct += 1 if a == m else 0
            class_total[m] += 1

            x.append(a.item())
            y.append(m.item())
        # list转化为numpy
        x = np.array(x)
        y = np.array(y)
    else:
        # 预测标签情况
        x = None
        # 真实标签情况
        y = None
        for data in test_loader:
            cnt += 1

            # 加载数据
            image, label = data
            image, label = image.to(device), label.to(device)

            # 使用平均策略,获取输出,即最终的输出为各模型输出和的平均
            output = None
            # 平均策略
            for model in models:
                if output is None:
                    output = model(image).detach()
                else:
                    output += model(image).detach()
            output = output / len(models)

            # acc
            _, a = torch.max(output, 1)
            b = label.detach()
            total += label.size(0)
            correct += (a == b).sum()

            # 预测和真实标签情况
            if x is None:
                x = a
                y = b
            else:
                x = torch.cat((x, a))
                y = torch.cat((y, b))

            # 统计每个类别的正确预测情况
            for i in range(label.size(0)):
                m = b[i]
                class_correct[m] += 1 if a[i] == m else 0
                class_total[m] += 1
        # tensor转化为numpy
        x = x.cpu().detach().numpy()
        y = y.cpu().detach().numpy()

    # 打印结果
    cm_plot_labels = ['MEL', 'NV', 'BCC', 'AKIEC', 'BKL', 'DF', 'VASC']
    # 打印acc
    print("test_acc:%.2f%%\n" % (100 * correct / total))
    # 打印每个类别的acc
    for i in range(7):
        if class_total[i] > 0:
            print('Test Accuracy of %5s: %.2f%% (%2d/%2d)' %
                  (cm_plot_labels[i], 100 * class_correct[i] / class_total[i],
                   class_correct[i], class_total[i]))
        else:
            print('Test Accuracy of %5s: N/A (no training examples)' %
                  cm_plot_labels[i])
    print('')

    # 计算混淆矩阵
    cm = confusion_matrix(y, x)
    print('')

    # 计算BMC
    balanced_multiclass_accuracy(cm)
    print('')

    # 可视化混淆矩阵
    plot_confusion_matrix(cm, cm_plot_labels, title='Confusion Matrix')
    print('')

    # 打印分类报告
    report = classification_report(y, x, target_names=cm_plot_labels)
    print(report)