Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anchors #503

Closed
JiaLim98 opened this issue Jul 24, 2020 · 34 comments
Closed

Anchors #503

JiaLim98 opened this issue Jul 24, 2020 · 34 comments
Labels
question Further information is requested

Comments

@JiaLim98
Copy link

Hi Ultralytics,

First of all, thank you so much for the interesting work and sharing.

❔Question

I mainly have three questions to ask:

  1. Size of anchors
    image
    May I know why the anchors are much bigger than the scale of the Feature Pyramid Network?

  2. bpr of computed anchors
    image
    I wanted to know what my anchors are so I computed them using kmean_anchors in utils.py. May I know why both anchors can reach a bpr of 1.0000? This is because there are quite a big difference between them and I wanted to know whether the default anchors or kmean anchors works better for my data.

  3. Source of anchors
    Where does the model take anchors from? Is it from the configuration files shown above or they are calculated everytime? This is because from Q2 above, both anchors achieved bpr of 1. That makes me question does the model use that anchors.

Best regards,
JiaLim98

@JiaLim98 JiaLim98 added the question Further information is requested label Jul 24, 2020
@maxjcohen
Copy link

I have a similar problem when computing anchors using kmean_anchors: even if I force-replace default anchors with the newly computed ones, I don't know how to save them to the .yml. Simply coping the values printed doesn't give the same bpr when loading anchors from the .yml.

In particular, there is one line executed after computing anchors with kmean_anchors that seems to be re-iterated at each model loading.

I am currently using the modification from #462 .

@glenn-jocher
Copy link
Member

@maxjcohen @JiaLim98 anchors may be supplied in your model.yaml file as you have shown above. AutoAnchor runs before training to ensure your anchors are a good fit for your data. If they are not, then new anchors are computed and evolved and attached to your model automatically. No action is needed on your part. You can disable autoanchor with python train.py --noautoanchor.

Strongly advise to git clone the latest repo (often), there have been many recent updates and bug fixes.

@JiaLim98
Copy link
Author

@maxjcohen Thank you for the information
@glenn-jocher The anchors are there because I calculated using kmean_anchors and typed them in myself. Anyway, are you saying that the code will auto compute the anchors and type them inside the .yaml file? This is because I want to know the anchors used.

@glenn-jocher
Copy link
Member

@JiaLim98 your yaml is never modified. AutoAnchor will attach anchors automatically to your model.pt file (i.e. last.pt or best.pt). If AutoAnchor computes anchors it will be obvious, it displays them to you and even advises you to update your yaml if you'd like to reuse them in the future.

@JiaLim98
Copy link
Author

@glenn-jocher I see. Which way do you advise to open the .pt files?

@glenn-jocher
Copy link
Member

model = torch.load('model.pt')

You can visualize with Netron also.

@JiaLim98
Copy link
Author

@glenn-jocher Thank you very much. Sorry for inconvenience caused as I'm new to object detection.

@JiaLim98
Copy link
Author

@glenn-jocher Another question. I can't seem to find the best weights saved in the weights folder or the runs folder. I have tried both --nosave of value true and false. Can you point it out to me?

@glenn-jocher
Copy link
Member

@JiaLim98 don't use nosave. Just start from the colab notebook and follow the examples there. The code displays to you where your models are saved after training completes.

Screen Shot 2020-07-24 at 9 56 07 PM

@JiaLim98
Copy link
Author

@glenn-jocher Yes, I know about the weights for last epoch. Previously, there is best and last weights right? Or is the last.pt shown here is the best weights?

@glenn-jocher
Copy link
Member

@JiaLim98 last.pt is the last weights. best.pt is the best weights.

Just use the notebook and run the tutorial.

@china56321
Copy link

@JiaLim98 your yaml is never modified. AutoAnchor will attach anchors automatically to your model.pt file (i.e. last.pt or best.pt). If AutoAnchor computes anchors it will be obvious, it displays them to you and even advises you to update your yaml if you'd like to reuse them in the future.

Hi,I want to extract the anchors and use it in the future .According to your idea. you mean AutoAnchor will save anchors automatically to the best.pt file , I use netron to open best.pt file ,but i do not know where the anchors be saved ? just found Detect layer has some parameters , Could you tell me where the anchors be saved or how to extract the anchors ? Thanks !

@glenn-jocher
Copy link
Member

@china56321 AutoAnchor displays the computed anchors on screen and advises you to update your yaml if you'd like to use them in the future.

@china56321
Copy link

china56321 commented Aug 5, 2020

@china56321 AutoAnchor displays the computed anchors on screen and advises you to update your yaml if you'd like to use them in the future.
Does it display the computed anchors on screen when training ? or when it finished training ?
2020-08-05 10-03-43屏幕截图
The former part is same with .yaml file ?

@glenn-jocher
Copy link
Member

No. After that, it will say analyzing anchors...

@glenn-jocher
Copy link
Member

@china56321 it's very obvious, it prints everything out for you.

@china56321
Copy link

@china56321 it's very obvious, it prints everything out for you.

OK, thank you!

@china56321
Copy link

No. After that, it will say analyzing anchors...
2020-08-07 18-40-29屏幕截图

I see analyzing anchors.. , but it did't show the anchors .
my purpose is to save or extract the anchors ,Could you tell me how should i do ? or post a screenshot ? thank you

@glenn-jocher
Copy link
Member

@china56321 right. Your anchors were analyzed against your dataset and a best possible recall was computed. This BPR is high enough not to warrant anchor recomputation. No new anchors were calculated for you.

@edwardnguyen1705
Copy link

Dear @glenn-jocher ,
If a model is trained with an image size, say 640, but when testing a 320-size image is fed to the model. Do I need to change the anchors?

@glenn-jocher
Copy link
Member

@edwardnguyen1705 anchors are never changed on a trained model. Also, you should train at the same size you intend to run inference at for best results.

@edwardnguyen1705
Copy link

@glenn-jocher thank you for your information.

@abhiagwl4262
Copy link

@glenn-jocher Can you explain the evolution of anchors after kmean based anchor computation?

@glenn-jocher
Copy link
Member

@abhiagwl4262 a genetic evolution optimizer runs on the anchors following a kmeans scan. Fitness function is the same as the regression loss used in loss.py. Code is below.

def check_anchors(dataset, model, thr=4.0, imgsz=640):
# Check anchor fit to data, recompute if necessary
prefix = colorstr('autoanchor: ')
print(f'\n{prefix}Analyzing anchors... ', end='')
m = model.module.model[-1] if hasattr(model, 'module') else model.model[-1] # Detect()
shapes = imgsz * dataset.shapes / dataset.shapes.max(1, keepdims=True)
scale = np.random.uniform(0.9, 1.1, size=(shapes.shape[0], 1)) # augment scale
wh = torch.tensor(np.concatenate([l[:, 3:5] * s for s, l in zip(shapes * scale, dataset.labels)])).float() # wh
def metric(k): # compute metric
r = wh[:, None] / k[None]
x = torch.min(r, 1. / r).min(2)[0] # ratio metric
best = x.max(1)[0] # best_x
aat = (x > 1. / thr).float().sum(1).mean() # anchors above threshold
bpr = (best > 1. / thr).float().mean() # best possible recall
return bpr, aat
bpr, aat = metric(m.anchor_grid.clone().cpu().view(-1, 2))
print(f'anchors/target = {aat:.2f}, Best Possible Recall (BPR) = {bpr:.4f}', end='')
if bpr < 0.98: # threshold to recompute
print('. Attempting to improve anchors, please wait...')
na = m.anchor_grid.numel() // 2 # number of anchors
new_anchors = kmean_anchors(dataset, n=na, img_size=imgsz, thr=thr, gen=1000, verbose=False)
new_bpr = metric(new_anchors.reshape(-1, 2))[0]
if new_bpr > bpr: # replace anchors
new_anchors = torch.tensor(new_anchors, device=m.anchors.device).type_as(m.anchors)
m.anchor_grid[:] = new_anchors.clone().view_as(m.anchor_grid) # for inference
m.anchors[:] = new_anchors.clone().view_as(m.anchors) / m.stride.to(m.anchors.device).view(-1, 1, 1) # loss
check_anchor_order(m)
print(f'{prefix}New anchors saved to model. Update model *.yaml to use these anchors in the future.')
else:
print(f'{prefix}Original anchors better than new anchors. Proceeding with original anchors.')
print('') # newline

@Yashar78
Copy link

Yashar78 commented Apr 3, 2021

Can somebody explain to me or point to me to a documents that explains what the lines
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple

anchors:

  • [10,13, 16,30, 33,23] # P3/8
  • [30,61, 62,45, 59,119] # P4/16
  • [116,90, 156,198, 373,326] # P5/32
    means in the yolov5x.yaml file.

@glenn-jocher
Copy link
Member

@Yashar78 depth and width multiple are YOLOv5 compound scaling constants inspired by EfficientDet:
https://arxiv.org/abs/1911.09070

Anchors are model anchors, all YOLO models use these to normalize outputs.

@abhiagwl4262
Copy link

@glenn-jocher

anchors:

[10,13, 16,30, 33,23] # P3/8
[30,61, 62,45, 59,119] # P4/16
[116,90, 156,198, 373,326] # P5/32

How can I reproduce these anchors ?

@glenn-jocher
Copy link
Member

@abhiagwl4262 I'm sorry I don't understand the question. You can manually specify anchors in your model.yaml file:

# parameters
nc: 80 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
# anchors
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32

@abhiagwl4262
Copy link

@glenn-jocher What I am trying to say is... we have algorithm that can generate custom anchors for any data. The anchors defined in yolov5/models/yolov5s.yaml are used for training on COCO data. Are the following anchors being calculated using the same algorithm?

  • [10,13, 16,30, 33,23] # P3/8
  • [30,61, 62,45, 59,119] # P4/16
  • [116,90, 156,198, 373,326]

@glenn-jocher
Copy link
Member

@abhiagwl4262 hey buddy. I think these anchors are simply adopted from the original YOLOv3 anchors by Josheph Redmon at https://github.com/pjreddie/darknet, or if not then they are generated by YOLOv5 autoanchor.

@abhiagwl4262
Copy link

@glenn-jocher Yeah, They have been taken from YOLOv3 directly. The anchors being calculated by autoanchor algorithm are not matching with the once taken from YOLOv3. Didn't you guys think of using custom ones ?

@glenn-jocher
Copy link
Member

glenn-jocher commented Apr 20, 2021

@abhiagwl4262 if the anchors are unmodified then auto-anchor has determined that they are suitable for training as-is.

Our YOLOv5-P6 models use auto-anchor evolved anchors for example (for training at --img 1280):

# anchors
anchors:
- [ 19,27, 44,40, 38,94 ] # P3/8
- [ 96,68, 86,152, 180,137 ] # P4/16
- [ 140,301, 303,264, 238,542 ] # P5/32
- [ 436,615, 739,380, 925,792 ] # P6/64

@abhiagwl4262
Copy link

@glenn-jocher Btw, I did run training for multiple datasets and custom anchors always improve the results irrespective of the good BPR value from the anchors given for COCO.

@glenn-jocher
Copy link
Member

@abhiagwl4262 oh interesting, thanks for the feedback! It looks like autoanchor is working well for your use case then :)

One trick to force autoanchor to create new anchors in all cases is to raise the BPR threshold from 0.98 to 1.0 here on L43 of autoanchor.py:

anchors = m.anchor_grid.clone().cpu().view(-1, 2) # current anchors
bpr, aat = metric(anchors)
print(f'anchors/target = {aat:.2f}, Best Possible Recall (BPR) = {bpr:.4f}', end='')
if bpr < 0.98: # threshold to recompute
print('. Attempting to improve anchors, please wait...')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

7 participants