libtorch

spring·2020년 11월 9일
0

설치

python은 1.4.0 stable을 받아서 사용한다. Preview(Nightly) 1.5.0은 DLL Load Failed 에러가 있다.

pip install torch===1.4.0 torchvision===0.5.0 -f https://download.pytorch.org/whl/torch_stable.html

C++은 Preview(Nightly) 1.5.0를 사용한다. 1.4.0은 Release에서 에러가 있다.
(torch::tensor 함수를 사용하지 못함)

libtorch 1.5.0 dev 설정 을 참고하거나 cip를 통해 설치한다.

datasets

python은 길게 설명하지 않겠다. python에서는 Normalizer를 하려면 반드시 ToTensor를 먼저 사용해야 한다.

transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])])

train_data = torchvision.datasets.CIFAR10(root='D:/data',train=True,transform=transform,download=False)
test_data = torchvision.datasets.CIFAR10(root='D:/data',train=False,transform=transform,download=False)

C++에서는 ToTensor대신 Stack을 사용한다. Stack은 images와 targets를 붙여서 하나의 텐서로 만드는 작업이다. C++에서는 애초부터 텐서이기 때문에 ToTensor가 필요없다. 또한 애초부터 텐서이기 때문에 transform의 순서가 중요하지 않다.

아래 예제에서 사용한 CIFAR10은 여기에서 다운받을 수 있다.

auto test_data = CIFAR10("D:/datac", CIFAR10::Mode::kTest)
    .map(torch::data::transforms::Normalize<>(0.5, 0.5))
    .map(torch::data::transforms::Stack<>());
auto train_data = CIFAR10("D:/datac",CIFAR10::Mode::kTrain)
    .map(torch::data::transforms::Normalize<>(0.5, 0.5))
    .map(torch::data::transforms::Stack<>());

DataLoader

python이 편하다. 인정한다.

train_loader = torch.utils.data.DataLoader(train_data,batch_size=64,shuffle=True,num_workers=4)
test_loader = torch.utils.data.DataLoader(test_data,batch_size=1,shuffle=False,num_workers=1)

C++에서는 DataLoaderOptions을 통해 옵션을 설정할 수 있고 make_data_loader의 템플릿 인자로 shuffle을 지정할 수 있다. 기본 템플릿 값은 RandomSampler이다.

torch::data::DataLoaderOptions train_options;
train_options.batch_size(64);
train_options.workers(4);
auto train_loader = torch::data::make_data_loader<torch::data::samplers::RandomSampler>(train_data, train_options);
torch::data::DataLoaderOptions test_options;
test_options.batch_size(1);
test_options.workers(1);
auto test_loader = torch::data::make_data_loader<torch::data::samplers::SequentialSampler>(test_data, test_options);

iterate DataLoader & Tensor to Primitive scalar

python은 기본 문법을 벗어나질 않는다. 돌고, 형변환 하면 된다.

for i,data in enumerate(test_loader):
    input = data[0][0]
    print(input.shape)
    for y in range(32):
        for x in range(32):
            print(float(input[0][y][x]),float(input[1][y][x]),float(input[2][y][x]),sep=',')
        break

C++은 data_ptr을 통해 포인터를 가져올 수 있다.

for (auto&data : *test_loader) {
    auto input = data.data[0];
    for (int y = 0; y < 32; y++) {
        for (int x = 0; x < 32; x++) {
            std::cout << *input[0][y][x].data_ptr<float>() << ","
                << *input[1][y][x].data_ptr<float>() << ","
                << *input[2][y][x].data_ptr<float>() << std::endl;
        }
    }
    break;
}
profile
Researcher & Developer @ NAVER Corp | Designer @ HONGIK Univ.

1개의 댓글

comment-user-thumbnail
2021년 10월 19일

libtorch 1.5.0 dev 설정 링크가 안되네요.. 예전버전 libtorch를 설치하고파서 그런데..

답글 달기