图像分类实验的可视化热力图该怎么制作呀?

img


像这种热力图该怎么制作?本人在写论文实验部分,请懂得朋友回答一下。

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/770627
  • 这篇博客也不错, 你可以看下深度学习 卷积的过程中可训练参数的数量以及浮点乘法进行多少次的次数是如何计算的?
  • 除此之外, 这篇博客: 【源码解析】如何从零实现图像分类模型?中的 参数设置及训练 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • # "cuda" only when GPUs are available.
    device = "cuda" if torch.cuda.is_available() else "cpu"
    
    _exp_name = "sample"
    
    # The number of training epochs and patience.
    n_epochs = 4
    patience = 300 # If no improvement in 'patience' epochs, early stop
    
    # Initialize a model, and put it on the device specified.
    model = Classifier().to(device)
    
    # For the classification task, we use cross-entropy as the measurement of performance.
    criterion = nn.CrossEntropyLoss()
    
    # Initialize optimizer, you may fine-tune some hyperparameters such as learning rate on your own.
    optimizer = torch.optim.Adam(model.parameters(), lr=0.0003, weight_decay=1e-5) 
    
    # Initialize trackers, these are not parameters and should not be changed
    stale = 0
    best_acc = 0
    
    for epoch in range(n_epochs):
    
        # ---------- Training ----------
        # Make sure the model is in train mode before training.
        model.train()
    
        # These are used to record information in training.
        train_loss = []
        train_accs = []
    
        for batch in tqdm(train_loader):
    
            # A batch consists of image data and corresponding labels.
            imgs, labels = batch
            #imgs = imgs.half()
            #print(imgs.shape,labels.shape)
    
            # Forward the data. (Make sure data and model are on the same device.)
            logits = model(imgs.to(device))
    
            # Calculate the cross-entropy loss.
            # We don't need to apply softmax before computing cross-entropy as it is done automatically.
            loss = criterion(logits, labels.to(device))
    
            # Gradients stored in the parameters in the previous step should be cleared out first.
            optimizer.zero_grad()
    
            # Compute the gradients for parameters.
            loss.backward()
    
            # Clip the gradient norms for stable training.
            grad_norm = nn.utils.clip_grad_norm_(model.parameters(), max_norm=10)
    
            # Update the parameters with computed gradients.
            optimizer.step()
    
            # Compute the accuracy for current batch.
            # 取全连接层最后输出的概率最大值作为预测的类别
            acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()
    
            # Record the loss and accuracy.
            train_loss.append(loss.item())
            train_accs.append(acc)
            
        train_loss = sum(train_loss) / len(train_loss)
        train_acc = sum(train_accs) / len(train_accs)
    
        # Print the information.
        print(f"[ Train | {epoch + 1:03d}/{n_epochs:03d} ] loss = {train_loss:.5f}, acc = {train_acc:.5f}")
    
        # ---------- Validation ----------
        # Make sure the model is in eval mode so that some modules like dropout are disabled and work normally.
        model.eval()
    
        # These are used to record information in validation.
        valid_loss = []
        valid_accs = []
    
        # Iterate the validation set by batches.
        for batch in tqdm(valid_loader):
    
            # A batch consists of image data and corresponding labels.
            imgs, labels = batch
            #imgs = imgs.half()
    
            # We don't need gradient in validation.
            # Using torch.no_grad() accelerates the forward process.
            with torch.no_grad():
                logits = model(imgs.to(device))
    
            # We can still compute the loss (but not the gradient).
            loss = criterion(logits, labels.to(device))
    
            # Compute the accuracy for current batch.
            acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()
    
            # Record the loss and accuracy.
            valid_loss.append(loss.item())
            valid_accs.append(acc)
            #break
    
        # The average loss and accuracy for entire validation set is the average of the recorded values.
        valid_loss = sum(valid_loss) / len(valid_loss)
        valid_acc = sum(valid_accs) / len(valid_accs)
    
        # Print the information.
        print(f"[ Valid | {epoch + 1:03d}/{n_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f}")
    
    
        # update logs
        if valid_acc > best_acc:
            with open(f"./{_exp_name}_log.txt","a"):
                print(f"[ Valid | {epoch + 1:03d}/{n_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f} -> best")
        else:
            with open(f"./{_exp_name}_log.txt","a"):
                print(f"[ Valid | {epoch + 1:03d}/{n_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f}")
    
    
        # save models
        if valid_acc > best_acc:
            print(f"Best model found at epoch {epoch}, saving model")
            torch.save(model.state_dict(), f"{_exp_name}_best.ckpt") # only save best to prevent output memory exceed error
            best_acc = valid_acc
            stale = 0
        else:
            stale += 1
            if stale > patience:
                print(f"No improvment {patience} consecutive epochs, early stopping")
                break
    
  • 您还可以看一下 张传波老师的软件设计是怎样炼成的?课程中的 整个程序需要考虑的设计规范小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    针对如何制作图像分类实验结果的可视化热力图,以下是解决方案:

    1. 首先,需要通过训练一个图像分类模型来获取分类结果。可以使用参考资料中提供的代码段落1来构建一个基本的卷积神经网络分类器,也可以根据自己的需要进行修改和优化。
    2. 在训练过程中,需要统计每个图像被分类到每个类别的概率,可以在代码训练过程中记录这些概率。在PyTorch中,可以使用softmax函数将线性输出转换为概率分布。例如,可以在forward函数中添加以下代码来获取分类概率分布:
    def forward(self, x):
        out = self.cnn(x)
        out = out.view(out.size()[0], -1)
        logits = self.fc(out)
        probs = nn.functional.softmax(logits, dim=1)
        return probs
    
    1. 在得到每个图像的分类概率后,可以将这些概率绘制成热力图来直观地展示分类结果。可以使用Python中的matplotlib包来生成热力图。
    2. 对于每一张图片,将它分类到每个类别的概率按照类别顺序排成一行,并以该行作为热力图中的一个横坐标。可以使用以下代码实现将每个图像的分类结果存储在一个DataFrame中:
    import pandas as pd
    import os
    from PIL import Image
    from torchvision import transforms
    
    def get_image_probs(model, image_path):
        transform = transforms.Compose([
            transforms.Resize(size=(128, 128)),
            transforms.ToTensor(),
        ])
        image = Image.open(image_path)
        inputs = transform(image).unsqueeze(0)
        probs = model(inputs)
        return probs.detach().numpy()[0]
    
    def get_classification_results(model, data_directory):
        results = []
        for class_name in sorted(os.listdir(data_directory)):
            class_directory = os.path.join(data_directory, class_name)
            for image_name in os.listdir(class_directory):
                image_path = os.path.join(class_directory, image_name)
                probs = get_image_probs(model, image_path)
                result = {"ImageName": image_name, "ClassName": class_name}
                for class_idx, class_prob in enumerate(probs):
                    result[f"Class{class_idx}Prob"] = class_prob
                results.append(result)
        return pd.DataFrame(results)
    
    model = Classifier()
    result_df = get_classification_results(model, data_directory)
    

    上述代码将每个图像的分类概率存储在一个DataFrame中,每一行表示一个图像,包含ImageName(图像文件名)、ClassName(类别名)和每个类别的概率。结果可以按照需要进行处理和分析。 5. 使用pandas的pivot_table函数将分类结果转换为热力图的输入格式。以下代码示例将结果转换为以Class为列、ImageName为行、ClassProb为值的DataFrame,然后使用matplotlib的imshow函数生成热力图。

    result_pivot = result_df.pivot_table(
        index="ImageName",
        columns="ClassName",
        values=[f"Class{i}Prob" for i in range(11)],
    )
    result_pivot = result_pivot.reindex(sorted(result_pivot.columns), axis=1)
    
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots(figsize=(10, 10))
    ax.imshow(result_pivot, aspect="auto", cmap="jet")
    ax.set_yticks(range(len(result_pivot)))
    ax.set_xticks(range(len(result_pivot.columns)))
    ax.set_yticklabels(result_pivot.index)
    ax.set_xticklabels(result_pivot.columns, rotation=90)
    ax.set_xlabel("Class")
    ax.set_ylabel("ImageName")
    plt.show()
    

    上述代码中,cmap参数指定使用jet颜色映射,aspect参数指定热力图的宽高比例为1:1,这样热力图就不会因为图片名称太长而变形。set_yticks和set_xticks方法用于设置刻度位置,set_yticklabels和set_xticklabels方法用于设置刻度标签。最终用show方法显示热力图。

    综上所述,以上是制作图像分类实验结果的可视化热力图的具体解决方案。