Why OrderDict here

taotaotao: <p>Hey, I am learning Faster-rcnn by reading the source code,<br>
i don’t know why here using Order Dict</p>
<aside class="onebox githubblob">
  <header class="source">
      <a href="https://github.com/pytorch/vision/blob/master/torchvision/models/detection/generalized_rcnn.py#L96" target="_blank" rel="nofollow noopener">github.com</a>
  </header>
  <article class="onebox-body">
    <h4><a href="https://github.com/pytorch/vision/blob/master/torchvision/models/detection/generalized_rcnn.py#L96" target="_blank" rel="nofollow noopener">pytorch/vision/blob/master/torchvision/models/detection/generalized_rcnn.py#L96</a></h4>
<pre class="onebox"><code class="lang-py"><ol class="start lines" start="86" style="counter-reset: li-counter 85 ;">
<li>        degenerate_boxes = boxes[:, 2:] &lt;= boxes[:, :2]</li>
<li>        if degenerate_boxes.any():</li>
<li>            # print the first degenrate box</li>
<li>            bb_idx = degenerate_boxes.any(dim=1).nonzero().view(-1)[0]</li>
<li>            degen_bb: List[float] = boxes[bb_idx].tolist()</li>
<li>            raise ValueError("All bounding boxes should have positive height and width."</li>
<li>                             " Found invaid box {} for target at index {}."</li>
<li>                             .format(degen_bb, target_idx))</li>
<li>
</li><li>features = self.backbone(images.tensors)</li>
<li class="selected">if isinstance(features, torch.Tensor):</li>
<li>    features = OrderedDict([('0', features)])</li>
<li>proposals, proposal_losses = self.rpn(images, features, targets)</li>
<li>detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)</li>
<li>detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes)</li>
<li>
</li><li>losses = {}</li>
<li>losses.update(detector_losses)</li>
<li>losses.update(proposal_losses)</li>
<li>
</li><li>if torch.jit.is_scripting():</li>
</ol></code></pre>


  </article>
  <div class="onebox-metadata">
    
    
  </div>
  <div style="clear: both"></div>
</aside>

<p>This is passed as a parameter to the self.rpn function on the next line.</p>
<p>and In rpn turn the Order dict  into an array</p>
<aside class="onebox githubblob">
  <header class="source">
      <a href="https://github.com/pytorch/vision/blob/master/torchvision/models/detection/rpn.py#L479" target="_blank" rel="nofollow noopener">github.com</a>
  </header>
  <article class="onebox-body">
    <h4><a href="https://github.com/pytorch/vision/blob/master/torchvision/models/detection/rpn.py#L479" target="_blank" rel="nofollow noopener">pytorch/vision/blob/master/torchvision/models/detection/rpn.py#L479</a></h4>
<pre class="onebox"><code class="lang-py"><ol class="start lines" start="469" style="counter-reset: li-counter 468 ;">
<li>        If provided, each element in the dict should contain a field `boxes`,</li>
<li>        with the locations of the ground-truth boxes.</li>
<li>
</li><li>Returns:</li>
<li>    boxes (List[Tensor]): the predicted boxes from the RPN, one Tensor per</li>
<li>        image.</li>
<li>    losses (Dict[Tensor]): the losses for the model during training. During</li>
<li>        testing, it is an empty dict.</li>
<li>"""</li>
<li># RPN uses all feature maps that are available</li>
<li class="selected">features = list(features.values())</li>
<li>objectness, pred_bbox_deltas = self.head(features)</li>
<li>anchors = self.anchor_generator(images, features)</li>
<li>
</li><li>num_images = len(anchors)</li>
<li>num_anchors_per_level_shape_tensors = [o[0].shape for o in objectness]</li>
<li>num_anchors_per_level = [s[0] * s[1] * s[2] for s in num_anchors_per_level_shape_tensors]</li>
<li>objectness, pred_bbox_deltas = \</li>
<li>    concat_box_prediction_layers(objectness, pred_bbox_deltas)</li>
<li># apply pred_bbox_deltas to anchors to obtain the decoded proposals</li>
<li># note that we detach the deltas because Faster R-CNN do not backprop through</li>
</ol></code></pre>


  </article>
  <div class="onebox-metadata">
    
    
  </div>
  <div style="clear: both"></div>
</aside>

<p>I think here is a reason, can someone help me ?</p>

ptrblck: <p>I assume the <code>OrderedDict</code> is used to guarantee that the passed features are in the right order.<br>
Depending on the Python version <code>features.values()</code> might reorder the values, which would yield a wrong behavior.</p>
<p>From the <a href="https://docs.python.org/2/library/stdtypes.html#dict.items">Python2 docs</a>:</p>
<blockquote>
<p><strong>CPython implementation detail:</strong>  Keys and values are listed in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions.</p>
</blockquote>
<p><a href="https://docs.python.org/3/library/stdtypes.html#dictionary-view-objects">Python 3 docs</a>:</p>
<blockquote>
<p>Dictionaries preserve insertion order. Note that updating a key does not affect the order. Keys added after deletion are inserted at the end.<br>
Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was an implementation detail of CPython from 3.6.</p>
</blockquote>