c++調用pytorch模型踩坑記錄


博主曾經在試過用C++調用tensorflow模型失敗后棄坑,選擇了C++調用Pytorch模型,雖然也是一路踩坑,但是最終結果還是成功了,固在此記錄一下。

step1:

下載pytorch:可以根據官網自行選擇符合自己電腦和環境的pytorch版本

下載libtorch(一個讓pytorch模型能被C++調用的庫):最好選擇和pytorch版本一樣的libtorch,否則好像也會也版本兼容問題(但是博主torch版本1.0.0,libtorch1.7.1也能用= = )

step2:

訓練pytorch模型,博主這兒訓練了一個簡單的二分類模型,輸入是一個float類型的一維數據,輸出是一個二維的tensor張量,分別代表該數據為類型0/1的概率

導出對應的torch script:

traced_script_module = torch.jit.trace(net, text)
# 保存模型
traced_script_module.save("D:/***/torch_script_eval.pt")

step3:

在clion中,調用torch_script_eval.pt,這兒來了第一個坑

在使用如下語句調用模型時報錯找不到路徑:

string path ="D:/***/torch_script_eval.pt";
torch::jit::Module module = torch::jit::load(path);

博主的代碼和模型都是放在D盤中,但是我通過Clion的wsl功能,鏈接到了windows的Ubuntu子系統下,用了子系統的環境,包括libtorch都是放在子系統中的,

所以這里的訪問路徑並不能直接從D盤訪問,而是應該站在子系統的角度去訪問,改為如下就能成功找到模型了:

string path ="/mnt/d/***/torch_script_eval.pt";
torch::jit::Module module = torch::jit::load(path);

step4:

博主想使用我訓練時候的數據,進行測試,看看在c++中調用和python調用結果是否一樣,於是我從csv文件中訪問我的數據,並且進行測試

 // 加載數據
    string pos_path="/mnt/d/***/data/pos_test1.csv";
    string neg_path="/mnt/d/***/data/neg_test1.csv";
    ifstream fin(neg_path); //打開文件流操作
    string line = "";
    vector<torch::jit::IValue> inputs;
    while (getline(fin, line))   //整行讀取,換行符“\n”區分,遇到文件尾標志eof終止讀取
    {
        // line 中格式為string,且末尾帶一個'\r'
        istringstream sin(line); //將整行字符串line讀入到字符串流istringstream中
        getline(sin,line,'\r');
        //第一行是id,跳過
        if( strcmp(line.c_str(),"id") == 0)
            continue;
        float tmp;
        tmp = atof(line.c_str());
        torch::Tensor test = torch::ones({1, 1});
        at::Tensor t =  test.variable_data();
        t[0][0] = tmp; //將一個數字改為一個1*1的tensor矩陣
        inputs.clear();
        inputs.push_back(test);
        at::Tensor output = module.forward(inputs).toTensor();//輸出兩個數字,分別對應類別0/1的分數
        cout << output<<endl;
    }

  這是最終成功的代碼,其中的重點在於,我需要向module.forward()方法中輸入一個vector,且vector中的數據結構應該是一個1*1的tensor張量(沒錯,坑在這兒,要如何將自己的一個一維float數據轉換為1*1的tensor張量,博主在坑里躺了很久)

  最終采用的方法如下:

float tmp;
tmp = atof(line.c_str());
torch::Tensor test = torch::ones({1, 1});
at::Tensor t =  test.variable_data();
t[0][0] = tmp; //將一個數字改為一個1*1的tensor矩陣

  這個方法可能不是最優的,但是確實是有效地

  先用torch::ones({1,1})方法,生成一個1*1的tensor張量,當然,里面的數據是1

  然后將test.variable_data()賦值給一個at::Tensor類,據說at::Tensor類才可以修改里面的數據,torch::Tensor不可以

  然后at::Tensor支持隨機訪問,此時用t[0][0]=tmp,就成功構造了一個1*1的一維張量,且里面包含的數據是自己定義的數據啦


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM