-
Notifications
You must be signed in to change notification settings - Fork 8k
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
Worse performance in this repo than in a yolov3 pytorch implementation #2914
Comments
|
Did you train 2 different models, one by using https://github.com/AlexeyAB/darknet and antoher by using https://github.com/ultralytics/yolov3 ? How many Training and Validation images did you use? What GPU did you use for training using Darknet? Did you set CUDNN_HALF=1? As claimed, there can be achived There are several assumptions here:
|
Yes, I trained two different models starting from darknet53.conv.74 and yolov3-spp.cfg adapted for 4 classes. I kept the rest of the hyperparameters equal in both frameworks. I have 4000 images in the train set and 1000 in the valid set. I used an RTX 2060 so I trained with CUDNN_HALF=1, but I also added mixed precison training to the pytorch version through nvidia apex.amp. I believe it's related with the presence of very small objects (smaller than 10x10 when img size=256). This objects are present as class 1, the class that improves the most its mAP in this pytorch implementation and also the class with more number of examples. |
You can try to convert your Darknet
Also if you try to retrain the model with CUDNN_HALF=0 and get better accuracy, I will try to find an bug if is there in the Darknet. I just don't use Loss-scale, because I don't apply FP16 to activations, but may be it is required in any cases: https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/index.html |
It seems that you can run the pytorch inplementation with the darknet weights. I got this results by using the same weigths, cfg file and validation set
|
I already tried that some weeks ago and there was no performance difference, it was even slightly better with CUDNN_HALF=1 |
In addition to: #2914 (comment) |
@AlexeyAB @drapado yes https://github.com/ultralytics/yolov3 accepts weights in either darknet or pytorch format in A couple points on training though:
|
@glenn-jocher Hi, Can you provide short manual how to convert
Do you mean it is better to calculate many F1-scores for each threshold from 0.0 to 1.0 (for example) with step=0.01 and get the highest value? |
@AlexeyAB yes I will create a short conversion function. There is already a nice pathway to convert weights/cfg to *.pt, but we don't have an easy way to convert back to *.weights/cfg yet though!! About the mAP, it seems I get the best mAP@0.5 on COCO by testing at extremely low confidence thresholds, about This is an example using yolov3-tiny, from ultralytics/yolov3#188. The top pictures, run at
|
mAP is calculated for all possible thresholds. So when you set the Why should we take into account detections with very low and very high thresholds:
So to create the single rating of models we should use mAP that includes Precision and Recall for all possible thresholds. That is why mAP is used in the most detection ratings/competitions: Pascal VOC, MS COCO, ImageNet... Actually for MS COCO the mAP is calculated for 101 different thresholds, URLs at the bottom of the first message: #2746 We get 101 points on Precision-Recall curve, for Recall = Lines 982 to 1002 in 099b71d
|
@AlexeyAB thanks for the excellent summary of mAP and why it's important across different applications! Very educational for everyone. It is true that you can tune your P/R ratio to suit your needs as move up the I've added a simple conversion function to export from both pytorch to darknet format and vice versa now. The process is very simple: git clone https://github.com/ultralytics/yolov3 && cd yolov3
# darknet to pytorch
python3 -c "from models import *; convert('cfg/yolov3-spp.cfg', 'weights/yolov3-spp.weights')"
Success: converted 'weights/yolov3-spp.weights' to 'converted.pt'
# pytorch to darknet
python3 -c "from models import *; convert('cfg/yolov3-spp.cfg', 'weights/yolov3-spp.pt')"
Success: converted 'weights/yolov3-spp.pt' to 'converted.weights' |
@glenn-jocher Thank you! I will add URL to Readme. |
@AlexeyAB Great! You could link to our iDetection iOS app also if you want, it runs YOLOv3-SPP 320 realtime (about 15-20 FPS) on devices with the newest Apple A12 processor (iPhone Xs, Xr, etc.) It has a 5 star rating and over 700 downloads in the last two months. The screenshots below are from a previous release at 416 inference, which reduces the framerate to about 11 FPS. We are working on introducing rectangular inference as well, which could theoretically boost the FPS by 40% on HD (16:9) aspect ratios vs square inference, adding pinch to zoom functionality like the native camera app, and a few other updates. Older devices can run the app as well, but will suffer as the model year goes back. An iPhone 6s for example will run about 0.3 FPS. Apple has really been making leaps with their Neural Engine, which is at 5 TOPS now. |
Hello @glenn-jocher & @AlexeyAB , I was trying to reproduce training & evaluation results on my custom dataset from Darknet C implementation from alexeyAB repo. I get worse performance results on ultralytics/yolov3 implementation. Training dataset: ~7800 images Command which I ran to compute the metrics: Darknet C implementation: Converted the .weights file from Darknet to .pt : ultralytics/yolov3 Pytorch trained model implementation:
Thanks |
Also, when I tried to convert the Pytorch model to darknet .weights format , I get no detections in Darknet. python3 -c "from models import *; convert('cfg/yolov3-tiny_3l.cfg', 'weights/best.pt')" **calculation mAP (mean average precision)... for thresh = 0.25, precision = -nan, recall = 0.00, F1-score = -nan IoU threshold = 50 %, used Area-Under-Curve for each unique Recall Set -points flag: |
@aditbhrgv generally testing for mAP computation (to get the results shown in https://github.com/ultralytics/yolov3#map) should be done at extremely low We've not actually tried using converted models, so this is an interesting finding. What happens if you convert the official yolov3.pt model from https://drive.google.com/drive/folders/1uxgUBemJVw9wZsdpboYbzUN4bcRhsuAI to .weights format and test that? |
Actually, I am not interested in mAP, I just care about comparable P, R and F1 scores in both the implementations for a particular threshold. (0.25 in above example.). I wonder what could be implementation differences on my custom dataset which lead to the above results. |
Hello @AlexeyAB , There's definitely some problem in converting from Pytorch to Darknet weights. THanks |
@aditbhrgv ah buddy I think you are confusing the extensions and repositories a bit:
With the ultralytics/yolov3 repo the commands to detect the default images (using rectangular inference at 416 pixels :) with 1) original darknet # 1) original darknet weights ------------------------------------------------------------------
python3 detect.py --weights weights/yolov3-spp.weights # original darknet weights
Namespace(cfg='cfg/yolov3-spp.cfg', conf_thres=0.5, data_cfg='data/coco.data', images='data/samples', img_size=416, nms_thres=0.5, weights='weights/yolov3-spp.weights')
Using CPU
image 1/2 data/samples/bus.jpg: 416x320 1 handbags, 3 persons, 1 buss, Done. (0.755s)
image 2/2 data/samples/zidane.jpg: 256x416 1 ties, 2 persons, Done. (0.607s)
# 2) converted to pytorch ---------------------------------------------------------------------
python3 -c "from models import *; convert('cfg/yolov3-spp.cfg', 'weights/yolov3-spp.weights')"
Success: converted 'weights/yolov3-spp.weights' to 'converted.pt'
python3 detect.py --weights converted.pt # converted to pytorch
Namespace(cfg='cfg/yolov3-spp.cfg', conf_thres=0.5, data_cfg='data/coco.data', images='data/samples', img_size=416, nms_thres=0.5, weights='converted.pt')
Using CPU
image 1/2 data/samples/bus.jpg: 416x320 1 handbags, 3 persons, 1 buss, Done. (0.749s)
image 2/2 data/samples/zidane.jpg: 256x416 1 ties, 2 persons, Done. (0.588s)
# 3) converted back to darknet ---------------------------------------------------------------
python3 -c "from models import *; convert('cfg/yolov3-spp.cfg', 'converted.pt')"
Success: converted 'converted.pt' to 'converted.weights'
python3 detect.py --weights converted.weights # converted back to darknet
Namespace(cfg='cfg/yolov3-spp.cfg', conf_thres=0.5, data_cfg='data/coco.data', images='data/samples', img_size=416, nms_thres=0.5, weights='converted.weights')
Using CPU
image 1/2 data/samples/bus.jpg: 416x320 1 handbags, 3 persons, 1 buss, Done. (0.749s)
image 2/2 data/samples/zidane.jpg: 256x416 1 ties, 2 persons, Done. (0.594s)
|
@glenn-jocher THanks for the clarification. I was thinking I could use the "converted.weights" from Pytorch in Darknet C implementation. Just a last quick question, how can I reproduce the results on my custom dataset as Darknet C Implementation in Pytorch implementation ? (see table here #2914 (comment)) . I didn't use multi-scale training, neither in Darknet C nor in Pytorch implementation.
|
@aditbhrgv Hi,
Can you attach Try to test official yolov3.pt on https://github.com/pjreddie/darknet instead of https://github.com/AlexeyAB/darknet does it work?
|
@glenn-jocher Hi, That's great! I will add URL.
Do you mean that you currently uses square network size (320x320) and uses And you will add ability for rectangle network size 16:9 (320x192 or 576x320) and will use simple resize without padding? Did you try to implement XNOR-net on ARM/ Apple A12 processor? #2365 (comment) |
@AlexeyAB we just got it done today!!! See ultralytics/yolov3#232 (comment). To answer your question yes, previously our app was running at 416x416 with letterboxing vertical 4k iPhone Xs video (the 4k video was resized to 234x416 and then padded/letterboxed to 416x416). This ran about 11 FPS. We reduced this to 320x320 to improve performance, and this ran at about 18 FPS. This is the current v4 app available for download today on the app store. After our rectangular inference builds the app can now run YOLOv3-SPP at 30FPS 192x320, or 20FPS 256x416. We still letterbox/pad the short dimension to the nearest 32 multiple though. So for example the 4k video is resized to 234x416 (width x height), and then padded with 11 pixels on the left + 11 on the right to round out a multiple of 32: 256x416. I don't know what XNOR-net is though. Here is an actual screenshot from today in Madrid, with a 1.15X zoom factor also (we enabled pinch-to-zoom functionality as well!! :) |
Hello @AlexeyAB |
Hi @glenn-jocher, After the conversion nothing is detected. I figured out that after changing the header information in the weights file using a tool like But when converting a custom model I suffer a big accuracy loss (scores are reduced almost by 0.5). The weird thing is that, when using my custom model or default tiny yolov3 after conversion on the pjreddie version of darknet, @AlexeyAB is there a difference, that you are aware of, between the pjreddie reposiotry and yours that could cause such a mismatch? @glenn-jocher Is there some reason why you don't preserve the header information after conversion? Thank you very much, this would clear up a lot for me |
@gwestner94 we can test out the conversion mAPs. The commands (and saved outputs) are here. All 3 results are identical, performing the mAP calculation using ultralytics/yolov3. The original yolov3-spp.weights was downloaded from https://pjreddie.com/media/files/yolov3-spp.weights. This mAP round-trip should be reproducible in our Google Colab Notebook. If the headers are different, perhaps the header may play a role when using this repo. Feel free to submit a PR for header inclusion over at ultralytics/yolov3 if you'd like. git clone https://github.com/ultralytics/yolov3
cd yolov3
# 1) original darknet weights ------------------------------------------------------------------
python3 test.py --weights weights/yolov3-spp.weights --save-json
# Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.566
# 2) converted to pytorch ---------------------------------------------------------------------
python3 -c "from models import *; convert('cfg/yolov3-spp.cfg', 'weights/yolov3-spp.weights')"
# Success: converted 'weights/yolov3-spp.weights' to 'converted.pt'
python3 test.py --weights converted.pt --save-json
# Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.566
# 3) converted back to darknet ---------------------------------------------------------------
python3 -c "from models import *; convert('cfg/yolov3-spp.cfg', 'converted.pt')"
# Success: converted 'converted.pt' to 'converted.weights'
python3 test.py --weights converted.weights --save-json
# Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.566 EDIT 1: @gwestner94 after re-reading your question a second test would be to perform the same round trip using an AlexeyAB/darknet trained network. I just so happen to have one of these. I can try the round trip again with it later. EDIT 2: Round trip successfully performed on custom dataset trained on AlexeyAB/darknet. # 1) original darknet weights ------------------------------------------------------------------
python3 test.py --weights ../darknet/backup/yolov3-spp-sm2-1cls_5000.weights --cfg cfg/yolov3-spp-sm2-1cls.cfg --data ../supermarket2/supermarket2.data
# Class Images Targets P R mAP F1
# Computing mAP: 100%|██████████████████████████████████| 2/2 [00:02<00:00, 1.72s/it]
# all 25 479 0.486 0.971 0.868 0.648
# 2) converted to pytorch ---------------------------------------------------------------------
python3 -c "from models import *; convert('cfg/yolov3-spp-sm2-1cls.cfg', '../darknet/backup/yolov3-spp-sm2-1cls_5000.weights')"
# Success: converted '../darknet/backup/yolov3-spp-sm2-1cls_5000.weights' to 'converted.pt'
python3 test.py --weights converted.pt --cfg cfg/yolov3-spp-sm2-1cls.cfg --data ../supermarket2/supermarket2.data
# Class Images Targets P R mAP F1
# Computing mAP: 100%|██████████████████████████████████| 2/2 [00:02<00:00, 1.72s/it]
# all 25 479 0.486 0.971 0.868 0.648
# 3) converted back to darknet ---------------------------------------------------------------
python3 -c "from models import *; convert('cfg/yolov3-spp-sm2-1cls.cfg', 'converted.pt')"
# Success: converted 'converted.pt' to 'converted.weights'
python3 test.py --weights converted.weights --cfg cfg/yolov3-spp-sm2-1cls.cfg --data ../supermarket2/supermarket2.data
# Class Images Targets P R mAP F1
# Computing mAP: 100%|██████████████████████████████████| 2/2 [00:02<00:00, 1.65s/it]
# all 25 479 0.486 0.971 0.868 0.648 |
Thank you for your feedback! |
I tested the yolo-v3 model using COCO-Val data in both darknet and pytorch(ultralytics). In Pytorch framework: 1.Yolo-v3.weights (original from darknet) -- 54.2 % mAP In Darknet framework: Yolo-v3.weights (original) -- 54.37 % save_weights method from ultralytics_code: `def save_weights(self, path='model.weights', cutoff=-1):
It uses the header info to store it in the weights file. Can you please tell us that what went wrong in the .weights file conversion? @glenn-jocher what do u mean "correct header information"? @gwestner94 |
@Sudhakar17 I don't believe anything went wrong with the weights conversion, as you can see from your own pytorch framework experiment. I myself don't have knowledge of how the headers are used in this AlexeyAB/darknet repository, that would be a question for @AlexeyAB. We do not use them at all in https://github.com/ultralytics/yolov3. |
@Sudhakar17 Hi, Can you share (f.e. via Google-disk) 4 files - I will check the difference:
|
@AlexeyAB thanks! We presently create a header 5 values long of int32s, and then write the number of images # Needed to write header when saving *.weights
self.header_info = np.zeros(5, dtype=np.int32) # First five are header values
self.header_info[3] = seen # number of images seen during training |
You should use these values |
@AlexeyAB I am traveling at the moment. I used original yolo-v3 model and the same cfg file. mAP values will be the different one since I didn't update my local darknet repository. I update my repository and rerun the converted model later. Is this header info used anywhere for calculating mAP? @glenn-jocher |
I updated the darknet repository and run the yolo-v3_converted.weight. It's not working. Any new updates? |
@glenn-jocher Hi, did you fix header (version) in your conversion script? #2914 (comment) |
@AlexeyAB @Sudhakar17 I just fixed this now in ultralytics/yolov3@d7a28bd @Sudhakar17 you should now be able to run pytorch exported models in darknet. |
I've tested this yolov3 implementation in pytorch https://github.com/ultralytics/yolov3. I used the same dataset and same yolov3-spp.cfg file (same of everything) for the tests. I achieved these results (consistent over several attempts):
The text was updated successfully, but these errors were encountered: