CUDA memory issue 123

username: CH_REDDY_RA211102601
cooked: <p>import torch<br>
import torch.nn as nn<br>
import torchvision.datasets as datasets<br>
import torchvision.transforms as transforms<br>
from torch.utils.data import DataLoader<br>
from PIL import Image<br>
import os<br>
import matplotlib.pyplot as plt<br>
from sklearn.metrics import confusion_matrix<br>
import seaborn as sns<br>
import numpy as np<br>
from torch.cuda.amp import autocast, GradScaler</p>
<p>class ChannelAttention(nn.Module):<br>
def <strong>init</strong>(self, in_channels, reduction_ratio=16):<br>
super(ChannelAttention, self).<strong>init</strong>()<br>
self.avg_pool = nn.AdaptiveAvgPool2d(1)<br>
self.max_pool = nn.AdaptiveMaxPool2d(1)<br>
self.reduction_ratio = reduction_ratio<br>
# Set a minimum value for in_channels to avoid division by zero<br>
self.in_channels = max(in_channels, reduction_ratio)<br>
self.fc1 = nn.Conv2d(self.in_channels, self.in_channels // reduction_ratio, kernel_size=1, stride=1, padding=0)<br>
self.relu = nn.ReLU()<br>
self.fc2 = nn.Conv2d(self.in_channels // reduction_ratio, self.in_channels, kernel_size=1, stride=1, padding=0)</p>
<pre><code>def forward(self, x):
    avg_out = self.fc2(self.relu(self.fc1(self.avg_pool(x))))
    max_out = self.fc2(self.relu(self.fc1(self.max_pool(x))))
    out = avg_out + max_out
    return torch.sigmoid(out) * x
</code></pre>
<p>class SpatialAttention(nn.Module):<br>
def <strong>init</strong>(self, kernel_size=7):<br>
super(SpatialAttention, self).<strong>init</strong>()<br>
assert kernel_size in (3, 7), “kernel size must be 3 or 7”<br>
padding = 3 if kernel_size == 7 else 1<br>
self.conv = nn.Conv2d(2, 1, kernel_size, padding=padding)</p>
<pre><code>def forward(self, x):
    avg_out = torch.mean(x, dim=1, keepdim=True)
    max_out, _ = torch.max(x, dim=1, keepdim=True)
    out = torch.cat([avg_out, max_out], dim=1)
    out = self.conv(out)
    return torch.sigmoid(out) * x
</code></pre>
<p>class DualAttentionModule(nn.Module):<br>
def <strong>init</strong>(self, in_channels):<br>
super(DualAttentionModule, self).<strong>init</strong>()<br>
self.channel_attention = ChannelAttention(in_channels)<br>
self.spatial_attention = SpatialAttention()</p>
<pre><code>def forward(self, x):
    out = self.channel_attention(x) * x
    out = self.spatial_attention(out) * out
    return out
</code></pre>
<p>class DualAttentionNetwork(nn.Module):<br>
def <strong>init</strong>(self, num_classes=10):<br>
super(DualAttentionNetwork, self).<strong>init</strong>()<br>
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)<br>
self.relu = nn.ReLU()<br>
self.dual_attention1 = DualAttentionModule(32)<br>
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)<br>
self.avg_pool = nn.AdaptiveAvgPool2d(7)  # AdaptiveAvgPool2d to replace MaxPool2d<br>
self.dual_attention2 = DualAttentionModule(64)<br>
self.flatten = nn.Flatten()  # Add a Flatten layer<br>
self.fc1 = nn.Linear(64<em>7</em>7, 512)  # Adjusted the input size for fc1<br>
self.fc2 = nn.Linear(512, num_classes)</p>
<pre><code>def forward(self, x):
    out = self.conv1(x)
    out = self.relu(out)
    out = self.dual_attention1(out)
    out = self.conv2(out)
    out = self.relu(out)
    out = self.dual_attention2(out)
    out = self.avg_pool(out)  # Use AdaptiveAvgPool2d to reduce spatial dimensions
    out = self.flatten(out)  # Flatten the output before fc1
    out = self.fc1(out)
    out = self.relu(out)
    out = self.fc2(out)
    return out
</code></pre>
<p>####################################################################################################################<br>
class ResidualBlock(nn.Module):<br>
def <strong>init</strong>(self, channels):<br>
super(ResidualBlock, self).<strong>init</strong>()<br>
self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, stride=1, padding=1)<br>
self.relu = nn.ReLU()<br>
self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, stride=1, padding=1)</p>
<pre><code>def forward(self, x):
    residual = x
    out = self.conv1(x)
    out = self.relu(out)
    out = self.conv2(out)
    out += residual
    out = self.relu(out)
    return out
</code></pre>
<p>class ESRGenerator(nn.Module):<br>
def <strong>init</strong>(self, num_channels=3, num_residual_blocks=16):<br>
super(ESRGenerator, self).<strong>init</strong>()<br>
# ESRGAN uses the same DualAttentionModule as before<br>
self.dual_attention1 = DualAttentionModule(num_channels)<br>
self.conv1 = nn.Conv2d(num_channels, 64, kernel_size=3, stride=1, padding=1)<br>
self.relu = nn.ReLU()</p>
<pre><code>    # Residual blocks
    residual_blocks = []
    for _ in range(num_residual_blocks):
        residual_blocks.append(ResidualBlock(64))

    self.residual_blocks = nn.Sequential(*residual_blocks)

    # Post-residual blocks convolution
    self.post_residual_conv = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)

    # Pixel-shuffle upsampling
    self.upsample = nn.Sequential(
        nn.Conv2d(64, 256, kernel_size=3, stride=1, padding=1),
        nn.PixelShuffle(upscale_factor=2),
        nn.ReLU(),
        nn.Conv2d(64, 256, kernel_size=3, stride=1, padding=1),
        nn.PixelShuffle(upscale_factor=2),
        nn.ReLU(),
        nn.Conv2d(64, num_channels, kernel_size=3, stride=1, padding=1),
        nn.Tanh()  # Tanh activation for output (range -1 to 1)
    )

def forward(self, x):
    out = self.dual_attention1(x)
    out = self.conv1(out)
    out = self.relu(out)
    residual = self.residual_blocks(out)
    out = self.post_residual_conv(residual) + out
    out = self.upsample(out)
    return out
</code></pre>
<h1><a name="esrgan-discriminator-network-1" class="anchor" href="#esrgan-discriminator-network-1"></a>ESRGAN Discriminator Network</h1>
<p>class ESRDiscriminator(nn.Module):<br>
def <strong>init</strong>(self, num_channels=3):<br>
super(ESRDiscriminator, self).<em>init</em>()<br>
self.layers = nn.Sequential(<br>
nn.Conv2d(num_channels, 64, kernel_size=3, stride=1, padding=1),<br>
nn.LeakyReLU(0.2, inplace=True),<br>
nn.Conv2d(64, 64, kernel_size=3, stride=2, padding=1),<br>
nn.BatchNorm2d(64),<br>
nn.LeakyReLU(0.2, inplace=True),<br>
nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),<br>
nn.BatchNorm2d(128),<br>
nn.LeakyReLU(0.2, inplace=True),<br>
nn.Conv2d(128, 128, kernel_size=3, stride=2, padding=1),<br>
nn.BatchNorm2d(128),<br>
nn.LeakyReLU(0.2, inplace=True),<br>
nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),<br>
nn.BatchNorm2d(256),<br>
nn.LeakyReLU(0.2, inplace=True),<br>
nn.Conv2d(256, 256, kernel_size=3, stride=2, padding=1),<br>
nn.BatchNorm2d(256),<br>
nn.LeakyReLU(0.2, inplace=True),<br>
nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),<br>
nn.BatchNorm2d(512),<br>
nn.LeakyReLU(0.2, inplace=True),<br>
nn.Conv2d(512, 512, kernel_size=3, stride=2, padding=1),<br>
nn.BatchNorm2d(512),<br>
nn.LeakyReLU(0.2, inplace=True),<br>
nn.AdaptiveAvgPool2d(1),<br>
)<br>
self.fc = nn.Linear(512, 1)</p>
<pre><code>def forward(self, x):
    out = self.layers(x)
    out = out.view(out.size(0), -1)
    out = self.fc(out)
    return out
</code></pre>
<p>device = torch.device(“cuda” if torch.cuda.is_available() else “cpu”)</p>
<h1><a name="initialize-the-gradscaler-and-set-the-model-to-use-autocast-2" class="anchor" href="#initialize-the-gradscaler-and-set-the-model-to-use-autocast-2"></a>Initialize the GradScaler and set the model to use autocast</h1>
<p>model = DualAttentionNetwork().to(device)<br>
criterion = nn.CrossEntropyLoss()<br>
scaler = GradScaler()</p>
<h1><a name="initialize-the-esrgan-generator-and-discriminator-3" class="anchor" href="#initialize-the-esrgan-generator-and-discriminator-3"></a>Initialize the ESRGAN Generator and Discriminator</h1>
<p>esr_generator = ESRGenerator(num_channels=3).to(device)<br>
esr_discriminator = ESRDiscriminator(num_channels=3).to(device)</p>
<h1><a name="define-loss-functions-for-generator-and-discriminator-4" class="anchor" href="#define-loss-functions-for-generator-and-discriminator-4"></a>Define loss functions for generator and discriminator</h1>
<p>adv_criterion = nn.BCEWithLogitsLoss()<br>
pixel_criterion = nn.L1Loss()</p>
<h1><a name="define-optimizers-for-generator-and-discriminator-5" class="anchor" href="#define-optimizers-for-generator-and-discriminator-5"></a>Define optimizers for generator and discriminator</h1>
<h1><a name="define-hyperparameters-6" class="anchor" href="#define-hyperparameters-6"></a>Define hyperparameters</h1>
<p>num_epochs = 25<br>
batch_size = 4<br>
gradient_accumulation_steps = 4  # Accumulate gradients over 4 batches before performing an optimizer step<br>
learning_rate = 0.001</p>
<h1><a name="define-optimizers-for-generator-and-discriminator-7" class="anchor" href="#define-optimizers-for-generator-and-discriminator-7"></a>Define optimizers for generator and discriminator</h1>
<p>esr_generator_optimizer = torch.optim.Adam(esr_generator.parameters(), lr=learning_rate)<br>
esr_discriminator_optimizer = torch.optim.Adam(esr_discriminator.parameters(), lr=learning_rate)</p>
<h1><a name="set-device-gpu-or-cpu-8" class="anchor" href="#set-device-gpu-or-cpu-8"></a>Set device (GPU or CPU)</h1>
<p>device = torch.device(“cuda” if torch.cuda.is_available() else “cpu”)</p>
<h1><a name="load-the-dataset-and-apply-transformations-9" class="anchor" href="#load-the-dataset-and-apply-transformations-9"></a>Load the dataset and apply transformations</h1>
<p>transform = transforms.Compose([<br>
transforms.Resize((96, 96)),<br>
transforms.ToTensor(),<br>
transforms.Normalize((0.5,), (0.5,))<br>
])</p>
<p>train_dataset = datasets.ImageFolder(root=r’/home/praveen_2221cs11/UAVWeedSegmentation-main/data/trainval’, transform=transform)<br>
test_dataset = datasets.ImageFolder(root=r"/home/praveen_2221cs11/UAVWeedSegmentation-main/data/test_different_bbch", transform=transform)<br>
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)<br>
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)</p>
<h1><a name="initialize-the-dual-attention-network-10" class="anchor" href="#initialize-the-dual-attention-network-10"></a>Initialize the Dual Attention Network</h1>
<p>model = DualAttentionNetwork().to(device)</p>
<h1><a name="define-loss-function-and-optimizer-11" class="anchor" href="#define-loss-function-and-optimizer-11"></a>Define loss function and optimizer</h1>
<p>criterion = nn.CrossEntropyLoss()<br>
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)</p>
<p>###############################################################################################################</p>
<p>#################################################################################################################################</p>
<h1><a name="training-loop-12" class="anchor" href="#training-loop-12"></a>Training loop</h1>
<h1><a name="training-loop-13" class="anchor" href="#training-loop-13"></a>Training loop</h1>
<p>torch.cuda.empty_cache()<br>
train_accuracy_list = []<br>
total_steps = len(train_loader)<br>
for epoch in range(num_epochs):<br>
correct = 0<br>
total = 0<br>
for i, (images, labels) in enumerate(train_loader):<br>
images = images.to(device)  # Convert images to full-precision<br>
labels = labels.to(device)</p>
<pre><code>    # Use autocast to perform forward and backward passes in half-precision
    with autocast():
        # Forward pass
        outputs = model(images)
        loss = criterion(outputs, labels)

    # Compute accuracy for this batch
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum().item()

    # Backward pass and optimize
    optimizer.zero_grad()
    scaler.scale(loss).backward()
    
    # Use scaler.step() to update the model's parameters
    if (i + 1) % gradient_accumulation_steps == 0:
        scaler.step(optimizer)
        scaler.update()
        optimizer.zero_grad()

    # Print training progress
    if (i + 1) % 100 == 0:
        print(f"Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{total_steps}], Loss: {loss.item():.4f}")

# Calculate the accuracy for the epoch and store it in the list
accuracy = 100 * correct / total
train_accuracy_list.append(accuracy)
</code></pre>
<h1><a name="plot-the-training-accuracy-graph-14" class="anchor" href="#plot-the-training-accuracy-graph-14"></a>Plot the training accuracy graph</h1>
<p>plt.plot(range(1, num_epochs + 1), train_accuracy_list, label=‘Training Accuracy’)<br>
plt.xlabel(‘Epoch’)<br>
plt.ylabel(‘Accuracy (%)’)<br>
plt.title(‘Training Accuracy’)<br>
plt.legend()<br>
plt.grid(True)<br>
plt.show()<br>
plt.savefig(“training_accuracy_graph.png”)</p>
<h1><a name="save-the-trained-model-15" class="anchor" href="#save-the-trained-model-15"></a>Save the trained model</h1>
<p>torch.save(model.state_dict(), “dual_attention_model.pt”)</p>
<h1><a name="load-the-saved-model-for-inference-16" class="anchor" href="#load-the-saved-model-for-inference-16"></a>Load the saved model for inference</h1>
<p>model_load = DualAttentionNetwork()<br>
model_load.load_state_dict(torch.load(“dual_attention_model.pt”))<br>
model_load.to(device)<br>
model_load.eval()</p>
<h1><a name="rest-of-the-code-for-generating-confusion-matrix-and-inference-remains-unchanged-17" class="anchor" href="#rest-of-the-code-for-generating-confusion-matrix-and-inference-remains-unchanged-17"></a>Rest of the code for generating confusion matrix and inference remains unchanged</h1>
<p>def get_predictions(model, dataloader):<br>
all_predictions = []<br>
all_labels = []<br>
model.eval()<br>
with torch.no_grad():<br>
for images, labels in dataloader:<br>
images = images.to(device)<br>
labels = labels.to(device)<br>
outputs = model(images)<br>
_, predicted_class = torch.max(outputs, 1)<br>
all_predictions.extend(predicted_class.cpu().numpy())<br>
all_labels.extend(labels.cpu().numpy())<br>
return all_predictions, all_labels</p>
<p>def generate_confusion_matrix(model, dataloader):<br>
# Get predictions for the test dataset<br>
predicted_classes, true_labels = get_predictions(model, dataloader)</p>
<pre><code># Define class labels
class_labels = ["BG", "S", "W"]

# Initialize confusion matrix for all classes
conf_matrix = np.zeros((len(class_labels), len(class_labels)), dtype=np.int64)

# Fill the confusion matrix with true positives, false positives, and false negatives
for predicted, true in zip(predicted_classes, true_labels):
    if true &gt;= len(class_labels) or predicted &gt;= len(class_labels):
        continue
    conf_matrix[true, predicted] += 1

# Calculate per-class accuracies
per_class_accuracies = {}
for i, label in enumerate(class_labels):
    total_samples = conf_matrix[i, :].sum()
    correct_predictions = conf_matrix[i, i]
    accuracy = correct_predictions / total_samples if total_samples &gt; 0 else 0.0
    per_class_accuracies[label] = accuracy

# Print the confusion matrix
print("Confusion Matrix:")
print(conf_matrix)

# Handle NaN values in the normalized confusion matrix
conf_matrix_normalized = np.nan_to_num(
    conf_matrix.astype('float') / conf_matrix.sum(axis=1, keepdims=True),
    nan=0.0,
    posinf=0.0,
    neginf=0.0
)

# Print the normalized confusion matrix
print("\nNormalized Confusion Matrix:")
print(conf_matrix_normalized)

# Save the confusion matrix and normalized confusion matrix in separate files
np.savetxt("confusion_matrix.txt", conf_matrix, fmt="%d", delimiter="\t")
np.savetxt("confusion_matrix_normalized.txt", conf_matrix_normalized, fmt="%.2f", delimiter="\t")

# Create a heatmap for the confusion matrix
plt.figure(figsize=(6, 4))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted Labels')
plt.ylabel('True Labels')
plt.title('Confusion Matrix')
plt.savefig("confusion_matrix_heatmap.png")  # Save the heatmap as PNG
plt.show()

# Create a heatmap for the normalized confusion matrix
plt.figure(figsize=(6, 4))
sns.heatmap(conf_matrix_normalized, annot=True, fmt='.2f', cmap='Blues')
plt.xlabel('Predicted Labels')
plt.ylabel('True Labels')
plt.title('Normalized Confusion Matrix')
plt.savefig("confusion_matrix_normalized_heatmap.png")  # Save the heatmap as PNG
plt.show()
</code></pre>
<h1><a name="generate-confusion-matrix-and-heatmaps-for-the-test-dataset-18" class="anchor" href="#generate-confusion-matrix-and-heatmaps-for-the-test-dataset-18"></a>Generate confusion matrix and heatmaps for the test dataset</h1>
<p>generate_confusion_matrix(model_load, test_loader)</p>
<h1><a name="function-to-perform-inference-on-a-single-image-19" class="anchor" href="#function-to-perform-inference-on-a-single-image-19"></a>Function to perform inference on a single image</h1>
<p>def test_single_image(image_path, model):<br>
transform = transforms.Compose([<br>
transforms.Resize((224, 224)),<br>
transforms.ToTensor(),<br>
transforms.Normalize((0.5,), (0.5,))<br>
])<br>
image = Image.open(image_path).convert(‘RGB’)<br>
image = transform(image).unsqueeze(0)</p>
<pre><code># Move the image tensor to the same device as the model (GPU)
image = image.to(device)

with torch.no_grad():
    output = model(image)
    _, predicted_class = torch.max(output, 1)
return predicted_class.item()
</code></pre>
<p>class_labels = train_dataset.classes</p>
<h1><a name="list-of-image-file-paths-for-testing-20" class="anchor" href="#list-of-image-file-paths-for-testing-20"></a>List of image file paths for testing</h1>
<p>test_image_paths = [<br>
“/home/praveen_2221cs11/UAVWeedSegmentation-main/data/test/img/test/test_01.jpg”,<br>
“/home/praveen_2221cs11/UAVWeedSegmentation-main/data/test/img/test/test_02.jpg”,<br>
“/home/praveen_2221cs11/UAVWeedSegmentation-main/data/test/img/test/test_03.jpg”<br>
# Add more image file paths here if needed<br>
]</p>
<h1><a name="perform-inference-on-the-entire-test-dataset-21" class="anchor" href="#perform-inference-on-the-entire-test-dataset-21"></a>Perform inference on the entire test dataset</h1>
<p>results = []<br>
for image_path in test_image_paths:<br>
predicted_class = test_single_image(image_path, model_load)<br>
class_label = class_labels[predicted_class]<br>
results.append((image_path, class_label))</p>
<h1><a name="print-or-save-the-inference-results-22" class="anchor" href="#print-or-save-the-inference-results-22"></a>Print or save the inference results:</h1>
<p>for image_path, class_label in results:<br>
print(f"Image: {image_path}, Predicted Class: {class_label}")</p>
<p>I am new to pytorch, i have reduced the batch size kindly resolve the error<br>
RuntimeError: CUDA error: out of memory<br>
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.<br>
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.</p>

username: ptrblck
cooked: <aside class="quote no-group" data-username="CH_REDDY_RA211102601" data-post="1" data-topic="185648">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/ch_reddy_ra211102601/48/62878_2.png" class="avatar"> CH_REDDY_RA211102601:</div>
<blockquote>
<p>RuntimeError: CUDA error: out of memory</p>
</blockquote>
</aside>
<p>You are running out of memory so reduce the batch size further or use a model with a lower memory requirement. Also, your code is not properly formatted, which makes debugging hard. Please don’t post the same questions with different user accounts, as it’s also causing unnecessary noise.</p>