.../generalized_rcnn.py", line 64, in forward boxes = target["boxes"] TypeError: string indices must be integers

Tomash: <p>Hi, I am trying to train rcnn model, but I have few problems when I am using batch_size&gt;1.<br>
My function which make dataset returns a single img tensor and a single target (dictionary):</p>
<pre><code class="lang-auto">        return (
            img,
            target,
        )
</code></pre>
<p>Later I am loading datasets to dataloader which loads data to the training process.</p>
<pre><code class="lang-auto">   with tqdm(train_loader) as _tqdm:
        for x, y in _tqdm:
            x = x.to(device)
            for key, value in y.items():
                y[key] = torch.tensor(value).to(device)

            outputs = model(x, y)
</code></pre>
<p>When batch_size is f.e. == 2, then <code>x</code> is a list of two tensors of shape <code>[D, H, W]</code> but <code>y</code> is a <code>dict</code> where every <code>key</code> have two values. Then occurs error:</p>
<p><code>.../generalized_rcnn.py", line 64, in forward boxes = target["boxes"] TypeError: string indices must be integers</code><br>
So I assumed that probably it can’t handle with dictionaries and I pass:</p>
<blockquote>
<p>output(x, [y])</p>
</blockquote>
<p>Then error changes to:</p>
<pre><code class="lang-auto">.../transform.py", line 99, in forward
target_index = targets[i] if targets is not None else None
IndexError: list index out of range
</code></pre>
<p>Any ideas how to make it run properly?</p>

ptrblck: <aside class="quote no-group" data-username="Tomash" data-post="1" data-topic="102162">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/t/858c86/48.png" class="avatar"> Tomash:</div>
<blockquote>
<p>then <code>x</code> is a list of two tensors of shape <code>[D, H, W]</code> but <code>y</code> is a <code>dict</code> where every <code>key</code> have two values.</p>
</blockquote>
</aside>
<p>Would it work, if you pass <code>y</code> as a <code>list</code> of two <code>dicts</code>?</p>

Tomash: <p>Finally, I solved this by adding:</p>
<blockquote>
<pre><code>        y_list = []
        for i in range(0, len(x)):
            y_list.append(y)
</code></pre>
</blockquote>

markvanber: <aside class="quote no-group" data-username="Tomash" data-post="1" data-topic="102162">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/t/858c86/48.png" class="avatar"> Tomash:</div>
<blockquote>
<p>TypeError: string indices must be integers</p>
</blockquote>
</aside>
<p>TypeError:  means that you are trying to perform an operation on a value whose type is not compatible with that operation.  An Iterable is a collection of elements that can be accessed sequentially . In Python, iterable objects are indexed using numbers . When you try to access an iterable object using a string or a float as the index, an error will be returned as TypeError: string indices must be integers. This means that when you’re accessing an iterable object like a string or float value, you must do it using an integer value.</p>
<p>For example, str[hello"] and str[2.1] as indexes. As these are not integers, a TypeError exception is raised. This means that when you’re accessing an iterable object like a string or float value, you must do it using an integer value . If you are accessing items from a dictionary , make sure that you are accessing the dictionary itself and not a key in the dictionary.</p>
<p>Python supports slice notation for any sequential data type like lists, strings , tuples, bytes, bytearrays, and ranges. When working with strings and slice notation, it can happen that a TypeError: <a href="http://net-informations.com/python/err/indices.htm" rel="noopener nofollow ugc">string indices must be integers</a> is raised, pointing out that the indices must be integers, even if they obviously are.</p>

meeselizabeth: <p>I get this same error. I am trying to train a Mask RCNN.<br>
First I load my training data like this:<br>
rescaled_images_folder = ‘…’<br>
rescaled_json_folder = ‘…’</p>
<p>class ObjectDetectionDataset(Dataset):<br>
def <strong>init</strong>(self, image_folder, json_folder, transform=None):<br>
self.image_folder = image_folder<br>
self.json_folder = json_folder<br>
self.transform = transform<br>
self.image_files = [file for file in os.listdir(self.image_folder) if file.endswith(‘.png’)]  # Update file extension<br>
self.json_files = [file for file in os.listdir(self.json_folder) if file.endswith(‘.json’)]</p>
<pre><code>def __len__(self):
    return len(self.image_files)

def bbox_to_mask(self, bboxes, width, height):
    masks = []
    for bbox_info in bboxes:
        x_min, y_min, x_max, y_max = bbox_info  # Use the values directly from bbox_info
        mask = np.zeros((height, width), dtype=np.uint8)
        mask[y_min:y_max, x_min:x_max] = 1
        masks.append(mask)
    return masks

def __getitem__(self, idx):
    image_file = os.path.join(self.image_folder, self.image_files[idx])
    json_file = os.path.join(self.json_folder, self.json_files[idx])

    # Load the image as a PIL image
    image = Image.open(image_file).convert('RGB')

    # Load the JSON file and extract bounding boxes
    with open(json_file, 'r') as file:
        json_data = json.load(file)
    bboxes = json_data['bounding_boxes']
    
    # Extract labels from bounding boxes and convert them to integers
    labels = [int(bbox['label']) for bbox in bboxes]

    # Convert bounding boxes to the expected format (list of lists)
    bboxes = [[bbox['bbox'][0], bbox['bbox'][1], bbox['bbox'][2], bbox['bbox'][3]] for bbox in bboxes]
    
    # Convert bounding boxes to masks
    image_width = json_data['imageWidth']
    image_height = json_data['imageHeight']
    masks = self.bbox_to_mask(bboxes, image_width, image_height) 

    targets = {
        'image': image,
        'labels': labels,
        'boxes': bboxes,  # Modify this to be a list of bounding boxes [x_min, y_min, x_max, y_max]
        'masks': masks,
    }

    if self.transform:
        image = self.transform(image)
    
    return image.permute(2, 0, 1), targets
</code></pre>
<p>def collate_fn(batch):<br>
images = [item[0] for item in batch]  # Extract the image from the tuple<br>
targets = [item[1] for item in batch]  # Extract the target dictionary</p>
<pre><code>all_labels = [target['labels'] for target in targets]
all_bboxes = [target['boxes'] for target in targets]
all_masks = [target['masks'] for target in targets]

# Convert the extracted bounding boxes to tensors
bbox_tensors = [torch.tensor(bbox, dtype=torch.float32) for bbox in all_bboxes]

# Pad bounding boxes
padded_bboxes = pad_sequence(bbox_tensors, batch_first=True)

# Convert list of masks to a single NumPy array and then to a tensor
#padded_masks = pad_sequence([torch.tensor(np.array(mask)) for mask in all_masks], batch_first=True)
mask_tensors = [torch.tensor(mask, dtype=torch.float32) for mask in all_masks]

# Pad masks
padded_masks = pad_sequence(mask_tensors, batch_first=True)

# Convert labels to a tensor with padding
max_num_labels = max(len(labels) for labels in all_labels)
common_padding_value = -1
padded_labels = [labels + [common_padding_value] * (max_num_labels - len(labels)) for labels in all_labels]
padded_labels = torch.tensor(padded_labels, dtype=torch.long)

targets = {
        'labels': padded_labels,
        'boxes': padded_bboxes,  
        'masks': padded_masks}

return images, targets
</code></pre>
<p>def calculate_mean_std(image_folder):<br>
image_files = [file for file in os.listdir(image_folder) if file.endswith(‘.png’)]<br>
num_images = len(image_files)<br>
pixel_sum = np.zeros(3)<br>
pixel_squared_sum = np.zeros(3)</p>
<pre><code>for image_file in image_files:
    image_path = os.path.join(image_folder, image_file)
    image = Image.open(image_path).convert('RGB')
    pixel_data = np.array(image, dtype=np.float32) / 255.0  # Normalize pixel values to [0, 1]

    # Accumulate pixel values and squared pixel values for each channel (R, G, B)
    pixel_sum += np.sum(pixel_data, axis=(0, 1))
    pixel_squared_sum += np.sum(pixel_data ** 2, axis=(0, 1))

# Calculate mean and standard deviation for each channel
pixel_mean = pixel_sum / (num_images * image.size[0] * image.size[1])
pixel_std = np.sqrt((pixel_squared_sum / (num_images * image.size[0] * image.size[1])) - pixel_mean ** 2)

return pixel_mean, pixel_std
</code></pre>
<h1><a name="calculate-mean-and-std-1" class="anchor" href="#calculate-mean-and-std-1"></a>Calculate mean and std</h1>
<p>mean, std = calculate_mean_std(rescaled_images_folder)<br>
print(“Mean:”, mean)<br>
print(“Standard Deviation:”, std)</p>
<h1><a name="define-transformations-modify-as-needed-2" class="anchor" href="#define-transformations-modify-as-needed-2"></a>Define transformations (modify as needed)</h1>
<p>transform = transforms.Compose([<br>
transforms.ToTensor(),<br>
transforms.Normalize(mean, std)<br>
])</p>
<h1><a name="create-the-dataset-3" class="anchor" href="#create-the-dataset-3"></a>Create the dataset</h1>
<p>dataset = ObjectDetectionDataset(image_folder=rescaled_images_folder, json_folder=rescaled_json_folder, transform=transform)</p>
<h1><a name="create-the-dataloader-4" class="anchor" href="#create-the-dataloader-4"></a>Create the DataLoader</h1>
<p>batch_size = 5<br>
train_dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True, collate_fn=collate_fn)</p>
<p>Then I am trying the simplest training/validation:</p>
<h1><a name="define-devices-5" class="anchor" href="#define-devices-5"></a>Define devices</h1>
<p>device = torch.device(‘cuda’) if torch.cuda.is_available() else torch.device(‘cpu’)</p>
<h1><a name="define-the-model-6" class="anchor" href="#define-the-model-6"></a>Define the model</h1>
<p>model = maskrcnn_resnet50_fpn(weights=MaskRCNN_ResNet50_FPN_Weights.DEFAULT)</p>
<h1><a name="move-model-to-gpu-7" class="anchor" href="#move-model-to-gpu-7"></a>Move model to GPU</h1>
<p>model.to(device)</p>
<h1><a name="define-optimizer-8" class="anchor" href="#define-optimizer-8"></a>Define optimizer</h1>
<p>optimizer = optim.Adam(model.parameters(), lr=0.001)</p>
<p>lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.1)</p>
<h1><a name="define-loss-functions-9" class="anchor" href="#define-loss-functions-9"></a>Define loss functions</h1>
<p>classification_loss = nn.CrossEntropyLoss()</p>
<p>regression_loss = nn.SmoothL1Loss()</p>
<p>mask_loss = nn.BCEWithLogitsLoss() # Dice + CrossEntropy / IoU</p>
<p>num_epochs = 2<br>
for epoch in range(num_epochs):<br>
model.train()<br>
total_loss = 0.0</p>
<pre><code>for images, targets in train_dataloader:
    images = [image.to(device) for image in images]
    targets = {k: v.to(device) for k, v in targets.items()}

    optimizer.zero_grad()

    # Forward pass
    loss_dict = model(images, targets)

    # Compute the total loss (classification loss + regression loss + mask loss)
    loss = sum(loss for loss in loss_dict.values())

    # Backward pass and optimization
    loss.backward()
    optimizer.step()

    total_loss += loss.item()

# Print training statistics
print(f"Epoch [{epoch + 1}/{num_epochs}] Loss: {total_loss / len(train_dataloader)}")

# Update the learning rate scheduler
lr_scheduler.step()

model.eval()
validation_loss = 0.0

with torch.no_grad():
    for images, labels, bboxes, masks, num_teeth in validation_dataloader:
        images = [image.to(device) for image in images]
        targets = [{'labels': labels[idx], 'boxes': bboxes[idx], 'masks': masks[idx]} for idx in range(len(labels))]
    
        loss_dict = model(images, targets)
        loss = sum(loss for loss in loss_dict.values())
    
        validation_loss += loss.item()

# Print validation loss
print(f"Validation Loss: {validation_loss / len(validation_dataloader)}")
</code></pre>
<p>However, I keep getting the error:</p>
<p>loss_dict = model(images, targets)<br>
…\Anaconda\lib\site-packages\torchvision\models\detection\generalized_rcnn.py", line 65, in forward<br>
boxes = target[“boxes”]<br>
TypeError: string indices must be integers</p>
<p>Could someone help me with this?</p>