How do I copy the parameters of a model learned in c ++?

I want to use it in c ++.
I want to learn new network by reusing previously learned data, but I do not know what to do.

Do you have the network defined in C++ frontend?

Yes. I Have a network

I saw your other post in How to load the prebuilt Resnet models weight ?(or any other prebuilt models), did you resolve this problem?

Yes. this problem Resolve

Can you tell me how you solved this problem?
I built the resnet50 network in C++, and I have the pre-training weight of resnet50 under Python. How can I load this weight into resnet50 in C++ and continue training?

This is one way to share pre-trained weights from Python to C++:

  1. Convert Python model to TorchScript, and save the model to file using model.save(filename).
  2. Create a C++ frontend model with the exact same model structure.
  3. Load the parameters and buffers from TorchScript model to C++ frontend model using torch::load(cpp_module, file_path_to_torchscript_model)

This is a minimal example:
JIT model:

import torch
class Model(torch.jit.ScriptModule):
    def __init__(self):
        super(Model, self).__init__()
        self.linear = torch.nn.Linear(2, 2)

model = Model()
print(model.linear.weight)  # For comparison
model.save('model1.pt')

C++ frontend model:

struct Net : torch::nn::Module {
  Net() {
    linear = register_module("linear", torch::nn::Linear(2, 2));  // Exactly match the Python model
  }
  torch::nn::Linear linear{nullptr};
};

Load parameters of JIT model into C++ frontend model:

int main(int argc, const char* argv[]) {
    auto module = std::make_shared<Net>();
    std::cout << module->linear->named_parameters()["weight"] << "\n";  // before loading pre-trained params
    torch::load(module, argv[1]);
    std::cout << module->linear->named_parameters()["weight"] << "\n";  // after loading pre-trained params

    return 0;
}

For converting your existing Python model to TorchScript (i.e. step 1), you can also use tracing (https://pytorch.org/tutorials/advanced/cpp_export.html#converting-to-torch-script-via-tracing). However you still need to manually define the same model structure in C++ API before loading the parameters in C++.

5 Likes

This example is very simple, but it works well. If you want more information. Check this Repository.

There is also a way to not use JIT.
If it does not work, talk to me. I’ll tell you another way.

:blush:

I hope you can share another method with me, thank you.:blush:

I hope you can share another method with me, thank you.:blush:

you See here.

The method is as

  1. Python Model State JSON File Dump
  2. Load libtorch JSON to parameter

JSON file Dump Like that

import torch
import torchvision
import torch.nn as nn
import torchvision.models as models
import json

resnet18 = torchvision.models.resnet18(True)

raw_state_dict = {}
for k, v in resnet18.state_dict().items():
	if isinstance(v, torch.Tensor):
		raw_state_dict[k] = (list(v.size()), v.numpy().tolist())
	else:
		print("State parameter type error : {}".format(k))
		exit(-1)


with open('resnet18.json', 'w') as outfile:
	json.dump(raw_state_dict, outfile,indent= "\t")

Load JSON model c++

//you defined model
Network model;

LoadStateDictJson(model, "JSON File Path");

torch::save(model, "File path");

Caution you doing for Define Network.
All networks should be in Impl so that torch :: save works normally.

use to TORCH_MODULE

In a similar way to

#ifndef ALEXNET_H
#define ALEXNET_H

#include <torch/torch.h>

namespace vision {
namespace models {
// AlexNet model architecture from the
// "One weird trick..." <https://arxiv.org/abs/1404.5997> paper.
struct AlexNetImpl : torch::nn::Module {
  torch::nn::Sequential features{nullptr}, classifier{nullptr};

  AlexNetImpl(int64_t num_classes = 1000);

  torch::Tensor forward(torch::Tensor x);
};

TORCH_MODULE(AlexNet);

} // namespace models
} // namespace vision

#endif // ALEXNET_H
1 Like