Loading and Saving C++ torch model in Python and another OS

Viewed 2033

I have a custom LSTM pytorch model in C++. After training I save the model using

torch::save(lstmNetwork, 'model.pt'); 

where lstmNetwork is std::shared_ptr<LSTMNetwork>;

class LSTMNetwork : public torch::nn::Module {
public:
  LSTMNetwork(const torch::nn::LSTMOptions &lstmOpts1,
            const torch::nn::LSTMOptions &lstmOpts2,
            const torch::nn::LinearOptions &linearOpts);
  ~LSTMNetwork();

  torch::Tensor forward(const torch::Tensor &x);

private:
  torch::nn::LSTM lstm1;
  torch::nn::LSTM lstm2;
  torch::nn::Linear linear;
};

LSTMNetwork::LSTMNetwork(const torch::nn::LSTMOptions &lstmOpts1,
                     const torch::nn::LSTMOptions &lstmOpts2,
                     const torch::nn::LinearOptions &linearOpts)
    : torch::nn::Module(),
      lstm1(register_module("lstm1", torch::nn::LSTM(lstmOpts1))),
      lstm2(register_module("lstm2", torch::nn::LSTM(lstmOpts2))),
      linear(register_module("linear", torch::nn::Linear(linearOpts))) {}

LSTMNetwork::~LSTMNetwork() {}

torch::Tensor LSTMNetwork::forward(const torch::Tensor &input) {
  torch::nn::RNNOutput lstm_out = this->lstm1->forward(input);
  lstm_out = this->lstm2->forward(lstm_out.output);
  torch::Tensor y_pred = this->linear(lstm_out.output[-1]);
  return y_pred.view({-1});
}

// .....
  torch::nn::LSTMOptions lstmOpts1(input, hidden);
  torch::nn::LSTMOptions lstmOpts2(hidden, hidden);
  lstmOpts1.layers(numLayers)
      .dropout(NetworkConstants::klsmt1DropOut)
      .with_bias(NetworkConstants::kIncludeBias);
  lstmOpts2.layers(numLayers)
      .dropout(NetworkConstants::klsmt2DropOut)
      .with_bias(NetworkConstants::kIncludeBias);

  torch::nn::LinearOptions linearOpts(hidden, output);
  linearOpts.with_bias(false);
  lstmNetwork = std::make_shared<LSTMNetwork>(lstmOpts1, lstmOpts2, linearOpts);

  torch::optim::AdamOptions opts(learningRate);
  optimizer = std::make_shared<torch::optim::Adam>(
      torch::optim::Adam(lstmNetwork->parameters(), opts));

  if (gpuAvailable) {
    lstmNetwork->to(torch::kCUDA);
  }
//....

I can reload the trained model in C++ without issue, using:

 torch::load(lstmNetwork, 'model.pt');

I have two questions related to the above snippets:

a) Is the trained model OS independent? Can I save the model on Windows 10 and reload it on Ubuntu 18.04 LTS? (The application is complied on both the platforms)

b) How do I open the saved pytorch model ('model.pt') in python?

Following gives an error:

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

Error : (showing the exact model name)

lstmModel = torch.load('stockData\BOM500570.pt') Traceback (most recent call last): File "C:\Python37\lib\tarfile.py", line 187, in nti n = int(s.strip() or "0", 8) ValueError: invalid literal for int() with base 8: 'ZZZZZZZZ'

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "C:\Python37\lib\tarfile.py", line 2289, in next tarinfo = self.tarinfo.fromtarfile(self) File "C:\Python37\lib\tarfile.py", line 1095, in fromtarfile obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) File "C:\Python37\lib\tarfile.py", line 1037, in frombuf chksum = nti(buf[148:156]) File "C:\Python37\lib\tarfile.py", line 189, in nti raise InvalidHeaderError("invalid header") tarfile.InvalidHeaderError: invalid header

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "C:\Python37\lib\site-packages\torch\serialization.py", line 591, in _load return legacy_load(f) File "C:\Python37\lib\site-packages\torch\serialization.py", line 502, in legacy_load with closing(tarfile.open(fileobj=f, mode='r:', format=tarfile.PAX_FORMAT)) as tar, \ File "C:\Python37\lib\tarfile.py", line 1591, in open return func(name, filemode, fileobj, **kwargs) File "C:\Python37\lib\tarfile.py", line 1621, in taropen return cls(name, mode, fileobj, **kwargs) File "C:\Python37\lib\tarfile.py", line 1484, in init self.firstmember = self.next() File "C:\Python37\lib\tarfile.py", line 2301, in next raise ReadError(str(e)) tarfile.ReadError: invalid header

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "", line 1, in File "C:\Python37\lib\site-packages\torch\serialization.py", line 422, in load return _load(f, map_location, pickle_module, **pickle_load_args) File "C:\Python37\lib\site-packages\torch\serialization.py", line 595, in _load raise RuntimeError("{} is a zip archive (did you mean to use torch.jit.load()?)".format(f.name)) RuntimeError: stockData\BOM500570.pt is a zip archive (did you mean to use torch.jit.load()?)

However following executes correctly:

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

For the latter case, I cannot use python's forward()/ overloaded () function, and I'm not sure how to use the loaded model.

>>> lstmModel = torch.jit.load('stockData\BOM500570.pt')
>>> input = torch.arange(5)
>>> lstmModel.forward(input)

Traceback (most recent call last): File "", line 1, in File "C:\Python37\lib\site-packages\torch\jit__init__.py", line 1585, in getattr return super(ScriptModule, self).getattr(attr) File "C:\Python37\lib\site-packages\torch\nn\modules\module.py", line 585, in getattr type(self).name, name)) AttributeError: 'ScriptModule' object has no attribute 'forward'

>>> lstmModel(input)

Traceback (most recent call last): File "", line 1, in File "C:\Python37\lib\site-packages\torch\nn\modules\module.py", line 541, in call result = self.forward(*input, **kwargs) File "C:\Python37\lib\site-packages\torch\jit__init__.py", line 1585, in getattr return super(ScriptModule, self).getattr(attr) File "C:\Python37\lib\site-packages\torch\nn\modules\module.py", line 585, in getattr type(self).name, name)) AttributeError: 'ScriptModule' object has no attribute 'forward'

>>> lstmModel

ScriptModule(
      original_name=Module
      (lstm1): ScriptModule(original_name=Module)
      (lstm2): ScriptModule(original_name=Module)
      (linear): ScriptModule(original_name=Module)
    )
0 Answers
Related