20.03.2021 Views

Deep-Learning-with-PyTorch

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

466 CHAPTER 15 Deploying to production

}

image = image.resize(227, 227);

Resizes to a smaller size

// ...here we need to produce an output tensor from input

CImg<float> out_img(output.data_ptr<float>(), output.size(2),

output.size(3), 1, output.size(1));

out_img.save(argv[3]);

The method data_ptr<float>() gives us a pointer

return 0;

to the tensor storage. With it and the shape

Saves the image

information, we can construct the output image.

For the PyTorch side, we include a C++ header torch/script.h. Then we need to set up

and include the CImg library. In the main function, we load an image from a file given

on the command line and resize it (in CImg). So we now have a 227 × 227 image in

the CImg<float> variable image. At the end of the program, we’ll create an out_img of

the same type from our (1, 3, 277, 277)-shaped tensor and save it.

Don’t worry about these bits. They are not the PyTorch C++ we want to learn, so we

can just take them as is.

The actual computation is straightforward, too. We need to make an input tensor

from the image, load our model, and run the input tensor through it.

Listing 15.11

cyclegan_jit.cpp

Puts the image data into a tensor

auto input_ = torch::tensor(

torch::ArrayRef<float>(image.data(), image.size()));

auto input = input_.reshape({1, 3, image.height(),

image.width()}).div_(255);

Reshapes and rescales

to move from CImg

conventions to

PyTorch’s

auto module = torch::jit::load(argv[1]);

std::vector<torch::jit::IValue> inputs;

inputs.push_back(input);

auto output_ = module.forward(inputs).toTensor();

auto output = output_.contiguous().mul_(255);

Calls the module and extracts the result tensor. For

efficiency, the ownership is moved, so if we held on

to the IValue, it would be empty afterward.

Loads the JITed model

or function from a file

Packs the input into a (oneelement)

vector of IValues

Makes sure our result

is contiguous

Recall from chapter 3 that PyTorch keeps the values of a tensor in a large chunk of

memory in a particular order. So does CImg, and we can get a pointer to this memory

chunk (as a float array) using image.data() and the number of elements using

image.size(). With these two, we can create a somewhat smarter reference: a

torch::ArrayRef (which is just shorthand for pointer plus size; PyTorch uses those at

the C++ level for data but also for returning sizes without copying). Then we can just

parse that into the torch::tensor constructor, just as we would with a list.

TIP Sometimes you might want to use the similar-working torch::from_blob

instead of torch::tensor. The difference is that tensor will copy the data. If

you do not want copying, you can use from_blob, but then you need to take care

that the underpinning memory is available during the lifetime of the tensor.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!