Chris-hughes10 / Yolov7-training

A clean, modular implementation of the Yolov7 model family, which uses the official pretrained weights, with utilities for training the model on custom (non-COCO) tasks.
GNU General Public License v3.0
116 stars 35 forks source link

Request for yolov7-tiny weights #12

Closed varshanth closed 1 year ago

varshanth commented 1 year ago

Hi, I do not see the release file for yolov7-tiny. Just wanted to know if you plan to release it? It is available from the official repo from here: https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-tiny.pt

When I tried to load this ckpt myself, I encountered the following error:

(Pdb) torch.load('yolov7-tiny.pt', map_location="cpu")
*** AttributeError: Can't get attribute 'Model' on <module 'models.yolo' (namespace)>

Is there something special to be done to convert the official weights to the ones compatible with your repo?

Thanks in advance!

Daraan commented 1 year ago

While it would be amazing I think they do not provide the weights. There are two kinds provided: the [model].pt weights and the [model]-training.pt weights. What we are using and want are the training weights for transfer learning. The other weights are for prediction

See also here: https://github.com/WongKinYiu/yolov7/issues/648


Btw. you can load these training weights if you clone the original yolov7 github, add your folder to sys.path then torch.load works. Looking at the loaded model (while I'm not 100% sure) looks differently structured.

Chris-hughes10 commented 1 year ago

Hi,

Hopefully I can provide some clarity on this.

The original repo provides serialised versions of the whole model. These are large and sensitive to the code and file structure of the codebase where they are used. For these reasons, PyTorch recommends that state dicts are used instead; which offer much more flexibility.

When we were creating this repo, we ran the script located here in the root of the original repo to extract the state dicts from their saved checkpoints (the *-training versions) and attached those to a release; which is used by our models. Therefore, our models use exactly the same weights, even though our implementations have been restructured slightly (for clarity and interpretability).

At the time, I believe that the weights for the tiny version was not available, which is why these were not included. It should be relatively simple to repeat this process to add the tiny weights. Unfortunately, I don't have much bandwidth to do this at the moment, but would welcome a PR and happy to advise if you would be willing to contribute this!

varshanth commented 1 year ago

While it would be amazing I think they do not provide the weights. There are two kinds provided: the [model].pt weights and the [model]-training.pt weights. What we are using and want are the training weights for transfer learning. The other weights are for prediction

See also here: WongKinYiu/yolov7#648

Btw. you can load these training weights if you clone the original yolov7 github, add your folder to sys.path then torch.load works. Looking at the loaded model (while I'm not 100% sure) looks differently structured.

Hey, thanks for your reply. Yes, I have loaded and observed the weights. It's fine. For the YOLOv7 models which don't have RepConv, the only difference between the training and inference versions is that the implicit add and multiply modules are merged with the last Conv weights and biases. Theoretically, the inference versions can still be trained with the training code since Conv weights and bias are present in both versions. Mathematically, during training (by loading the inference version weights), the implicit modules would be extra modules and will be randomly init'd and would/should learn to do the inverse operation (implicit multiply will learn implicit divide and implicit add will learn implicit subtract) to achieve convergence. Optionally, you can remove the implicit modules during training so that both the versions match and you wouldn't experience a significant performance drop. I have done both of these and confirm that both work.

varshanth commented 1 year ago

Hi,

Hopefully I can provide some clarity on this.

The original repo provides serialised versions of the whole model. These are large and sensitive to the code and file structure of the codebase where they are used. For these reasons, PyTorch recommends that state dicts are used instead; which offer much more flexibility.

When we were creating this repo, we ran the script located here in the root of the original repo to extract the state dicts from their saved checkpoints (the *-training versions) and attached those to a release; which is used by our models. Therefore, our models use exactly the same weights, even though our implementations have been restructured slightly (for clarity and interpretability).

At the time, I believe that the weights for the tiny version was not available, which is why these were not included. It should be relatively simple to repeat this process to add the tiny weights. Unfortunately, I don't have much bandwidth to do this at the moment, but would welcome a PR and happy to advise if you would be willing to contribute this!

Hi, thanks for your explanation. The process was very quick and simple. I can confirm that the yolov7-tiny weights from the original repo are compatible with your repo and work fine for fine-tuning and also transfer learning. Just a small caveat as mentioned above, the provided weights were meant for inference, and so they have the implicit operations encoded in the last conv, i.e., they aren't available as explicit modules. Please note my above comment for alternate usages for fine-tuning/transfer-learning. I will send over a PR for the weights as soon as I get some free time (latest by next week). Thanks!

tkupek commented 1 year ago

@varshanth thanks for doing this process. We would also benefit from the weights. If you could send me the files, I can also support with the PR.

varshanth commented 1 year ago

Hey, here's the link to the weights. I would appreciate it if you could help with the PR and let me know once it's done so I can remove the file from my Drive. Thanks!

tkupek commented 1 year ago

Awesome. Thanks a lot. I have created a quick PR https://github.com/Chris-hughes10/Yolov7-training/pull/14, but the weights have to be added to the release and I can't to that without access to the repo. @Chris-hughes10 would you mind uploading the file to releases?

tkupek commented 1 year ago

@varshanth before we merge, could you please double check if the state dict you uploaded is correct? In comparison to the default yolov7 weights I'm gettting pretty much garbage detections with the tiny version.

import numpy as np
import torch
from PIL import Image
from yolov7 import create_yolov7_model
from yolov7.plotting import show_image
from yolov7.trainer import filter_eval_predictions

model = create_yolov7_model(architecture="yolov7-tiny")
model.eval()

image = Image.open("test.jpg").convert("RGB")
image = np.array(image)
image = image / 255.
image = np.transpose(image, (2, 0, 1))
image = torch.tensor(image).float()
image = image.unsqueeze(dim=0)

outputs = model(image)
preds = model.postprocess(outputs)
preds = filter_eval_predictions(preds, confidence_threshold=0.35)

boxes = preds[0][:, :4]
class_ids = preds[0][:, -1]
show_image(image[0].permute(1, 2, 0), boxes.tolist(), class_ids.tolist())

image image

varshanth commented 1 year ago

Hey @tkupek , as I mentioned in my comments here and here, the weights are for inference only. What this means is that the implicit modules are merged with the last conv layers. If you wish to perform inference using the uploaded weights, then please remove/comment this block, and replace the code here

x[layer_idx] = self.m[layer_idx](self.ia[layer_idx](x[layer_idx]))
x[layer_idx] = self.im[layer_idx](x[layer_idx])

with

x[layer_idx] = self.m[layer_idx](x[layer_idx])

So a junk output like this: test_pred_with_implicit_modules

becomes this:

test_pred

That being said, I want to reiterate that if you wish to train:

  1. Without the implicit modules, as I suggested above, without a practically significant difference in performance.
  2. With the implicit modules, you can still get a performance small boost, but you'll have to either a. Merge the implicit modules with the last conv yourself to get a slight speed boost up, or b. Be alright with the implicit modules in your model, which may induce a slight lag in speed.

Hope this helps!

tkupek commented 1 year ago

@varshanth thanks for the detailed description. Don't know why I missed the inference description but the adjusted code works!

varshanth commented 1 year ago

Cool. I'm closing this issue. @Chris-hughes10 , I think it might be worth it to add a note to the README pointing to this issue for how to use yolov7-tiny weights. Thanks!