crnn pytorch轉libtorch轉trt問題記錄--------libtorch的data_ptr()方法不同版本變化了


大坑!!!
首先發現這個問題的時候是在libtorch1.1版本上面沒有問題的代碼,移植到高版本libtorch1.7,發現同樣的代碼在高版本上面精度不一樣。然后查找原因的時候發現的。
運行代碼發現沒有顯存累加情況但是精度不對,不能出效果圖。之前的環境雖然存在顯存累加問題但是精度是對的可以出效果圖。查找問題,先查找trt推理出來的結果發現對不上,再查找輸入發現對的上。這里我都是對比的libtorch的tensor里面數值。
然后我再對比之前一開始寫的測試代碼,沒有用libtorch的,就只用全1的矩陣輸入作為輸入給trt推理,對比pytorch和trt結果,發現是可以對的上的。說明trt只要輸入和pytorch一致輸出就一致,在這個配置環境下是沒有問題的。但是為啥加了libtorch就不一樣了。然后再去libtorch代碼找原因。
在數據預處理之后是
void* input = tensor_image.data_ptr();
用libtorch的tensor類型的提供的數據指針data_ptr()給trt的。然后我對這個指針取出前100個,和之前libtorch1.1,cuda10.0上面的工程對比,發現取出來的前100個數據居然不一樣。但是tensor_image這個里面的數值兩者是一樣的。
就是打印tensor_image兩邊發現是一樣的數據。但是用指針方式訪問發現是不一樣的!!
本能的認為可能是數據類型的問題。tensor_image = tensor_image.to(torch::kFloat16);這么試float16,32,64都試了還是不一致。
在jiamin提醒下是不是高版本通道變化了,我發現打印出來的前100個數有些數值確實是和之前低版本打印的是一樣的。然后在低版本的代碼如下打印:
tensor_image[0][0][0],tensor_image[1][0][0],tensor_image[2][0][0]
發現這樣的打印,低版本的這么打印是和高版本的用data_ptr打印的是一致的。說明高版本的data_ptr確實是有改動了。然后就是
tensor_image = tensor_image.permute({2, 0, 1});把6種可能的順序都顛倒試了一下還是沒有和之前低版本打印的一樣。
最后沒有辦法,tensor_image = tensor_image.reshape({-1});用這句話把數據壓成一維度,在調用data_ptr打印,這回發現數據一致了。然后跑整個工程可以出效果圖。
然后的然后,我又用libtorch來轉trt的crnn,本來已經寫好的代碼調試可以出效果。然后整理代碼,把申請顯存釋放顯存的操作放在循環外面,然后一波修改。改完之后發現出來的結果都是亂七八糟的。
氣死,本來都弄好的,咋就不一樣了呢,可是代碼都被我保存,不好回退了。哎。。。
搞了一個晚上,實在是不想從頭再搞。。。。查找了好久還是找不出問題,甚至從頭開始就對不第一層卷積出來的效果發現結果是不一樣的。然而我還是不知道哪里問題。我對比了輸入給網絡的輸入是一樣的。!!!
這里注意,用的是libtorch tensor和pytorch的tensor是一樣的!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~分割線~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

隔了好久,沒有辦法,我找了個一開始的版本,然后重新來,弄着弄着的時候發現漏了一句話,然后我恍然大悟!原來又是之前的坑啊!!
整理代碼的時候把這句話給刪了

input = input.reshape({-1});///import for torch1.7//////////////////////////////

一開始查找輸入的時候發現tensor一致,是因為tensor本來就是一致的,只是用指針訪問才不一致!!!

這里還得吐槽一下,一個巨坑!
就是就是我一開始把crnn轉trt的時候,先搭好了基網絡,然后驗證精度。發現精度對不上,按照我之前的經驗torch和trt應該轉出來是一摸一樣的。然后找原因,然后找到layer2發現精度也不一樣,然后找第一個pool發現也不一樣,然后第一個卷積層,發現也不一樣!!!然后我迷茫了。這種情況就是兩種可能,第一種可能就是輸入不一樣,還有就是提取的權重有問題。
打印出輸入的前幾個數值發現是一樣的,那么輸入就是沒有問題了,難不成還是權重提取的有問題的嗎?
我看了代碼不就是那幾行代碼,之前也是這么整的,這能有什么問題!!?
我又陷入迷茫加無助!!放棄的邊緣。。。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~分割線~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

然后,痛定思痛。
轉libtorch驗證精度小程序 https://www.cnblogs.com/yanghailin/p/13669046.html
耐心核查每一步。不偷懶了,雖然前面幾個數值一樣,還是把tensor都保存在本地txt,兩個txt用腳本統計精度。
驚奇的發現輸入誤差很大!!!雖然前幾個數值是一樣的,但是中間有數值是不一樣的,而且很多!!!
然后我就去找原因。定位問題在如下:
python代碼

def LstmImgStandardization(img, ratio, stand_w, stand_h):
    img_h, img_w, _ = img.shape
    if img_h < 2 or img_w < 2:
        return
    if 32 == img_h and 320 == img_w:
        return img

    ratio_now = img_w * 1.0 / img_h
    if ratio_now <= ratio:
        mask = np.ones((img_h, int(img_h * ratio), 3), dtype=np.uint8) * 255
        mask[0:img_h,0:img_w,:] = img
    else:
        mask = np.ones((int(img_w*1.0/ratio), img_w, 3), dtype=np.uint8) * 255
        mask[0:img_h, 0:img_w, :] = img

    mask_stand = cv2.resize(mask,(stand_w, stand_h),interpolation=cv2.INTER_AREA)

    return mask_stand

c++代碼

bool LstmImgStandardization(const cv::Mat &src, const float &ratio, int standard_w, int standard_h, cv::Mat &dst)
{
    if(src.empty()) {return false;}
    if(src.cols<2 || src.rows<2) { return false;}
    if(32 == src.rows && 320 == src.rows) { dst = src.clone(); return true;}

    float width=src.cols;
    float height=src.rows;
    float  a=width/ height;

    if(a <=ratio)
    {
        cv::Mat mask(height, ratio*height, CV_8UC3, cv::Scalar(255, 255, 255));
        cv::Mat imageROI = mask(cv::Rect(0, 0, width, height));
        src.copyTo(imageROI);
        dst=mask.clone();
    }
    else
    {
        cv::Mat mask(width/ratio, width, CV_8UC3, cv::Scalar(255, 255, 255));
        cv::Mat imageROI = mask(cv::Rect(0, 0, width, height));
        src.copyTo(imageROI);
        dst=mask.clone();
    }

    cv::resize(dst, dst, cv::Size(standard_w,standard_h));
    return true;
}

兩者功能是一樣的。但是細心的同學會發現最后的resize不一樣!!!!

cv::resize(dst, dst, cv::Size(standard_w,standard_h),0,0,cv::INTER_AREA);

c++代碼應該這么寫!!!!保持一致啊!!

本來計划半天的工作量,硬是搞了兩天。還是要細心耐心啊,不能偷懶,保持嚴謹!要不然得不償失!


免責聲明!

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



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