日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

KBQA_多轮对话——模型源码解析(一)Pickle模块功能详解

發布時間:2024/3/24 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 KBQA_多轮对话——模型源码解析(一)Pickle模块功能详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

KBQA_多輪對話——模型源碼解析(一)Pickle模塊功能詳解

  • pickle --- Python 對象序列化的基本功能
    • 1、pickle基本概念
    • 2、pickle 與 json 模塊的比較
    • 3、pickle應用實例
    • 4、pickle模塊解析CIFAR-10數據集
    • 5、【對象持久性】的理解

pickle — Python 對象序列化的基本功能

1、pickle基本概念

模塊pickle實現了對一個Python對象結構的二進制序列化 “封存 (pickling)” 反序列化 “解封 (unpickling)”

  • pickling是將Python對象及其所擁有的層次結構轉化為一個字節流的過程;
  • unpickling是相反的操作,會將(來自一個binary file 或者 bytes-like object)的字節流轉化回一個對象層次結構。

參考鏈接:pickle的官方開發文檔——pickle — Python 對象序列化

  • pickle模塊對于錯誤或惡意構造的數據是不安全的。

數據流格式: pickle 所使用的數據格式僅可用于 Python。

這樣做的好處是沒有外部標準給該格式強加限制,比如 JSON 或 XDR(不能表示共享指針)標準;但這也意味著 非 Python 程序可能無法重新讀取 pickle 封存的 Python 對象

默認情況下,pickle 格式使用相對緊湊的二進制來存儲。如果需要讓文件更小,可以高效地 壓縮 由 pickle 封存的數據。

注解:序列化是一種比持久化更底層的概念,雖然 pickle 讀取和寫入的是文件對象,但它不處理持久對象的命名問題,也不處理對持久對象的并發訪問(甚至更復雜)的問題。pickle 模塊可以將復雜對象轉換為字節流,也可以將字節流轉換為具有相同內部結構的對象。處理這些字節流最常見的做法是將它們寫入文件,但它們也可以通過網絡發送或存儲在數據庫中。shelve 模塊提供了一個簡單的接口,用于在 DBM 類型的數據庫文件上封存和解封對象。

模塊接口:

要序列化某個包含層次結構的對象,只需調用 dumps() 函數即可。同樣,要反序列化數據流,可以調用 loads() 函數。但是,如果要對序列化和反序列化加以更多的控制,可以分別創建 Pickler 或 Unpickler 對象。

pickle 模塊的常用方法:

pickle 模塊提供了以下方法,讓封存過程更加方便:

  • pickle.dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None)
    將對象 obj 封存以后的對象寫入已打開的 file object file。它等同于 Pickler(file, protocol).dump(obj)。
  • 備注:參數 file、protocol、fix_imports 和 buffer_callback 的含義與它們在 Pickler 的構造函數中的含義相同。

  • pickle.dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None)
    將 obj 封存以后的對象作為 bytes 類型直接返回,而不是將其寫入到文件
  • 備注:參數 protocol、fix_imports 和 buffer_callback 的含義與它們在 Pickler 的構造函數中的含義相同。

  • pickle.load(file, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)
    從已打開的 file object 文件 中讀取封存后的對象,重建其中特定對象的層次結構并返回。它相當于 Unpickler(file).load()。
  • Pickle 協議版本是自動檢測出來的,所以不需要參數來指定協議。封存對象以外的其他字節將被忽略。

    備注:參數 file、fix_imports、encoding、errors、strict 和 buffers 的含義與它們在 Unpickler 的構造函數中的含義相同。

  • pickle.loads(data, /, *, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
    重建并返回一個對象的封存表示形式 data 的對象層級結構。 data 必須為 bytes-like object。
  • Pickle 協議版本是自動檢測出來的,所以不需要參數來指定協議。封存對象以外的其他字節將被忽略。

    備注:參數 file、fix_imports、encoding、errors、strict 和 buffers 的含義與它們在 Unpickler 的構造函數中的含義相同。

    pickle 模塊包含了 3 個類,Pickler、Unpickler 和 PickleBuffer:

  • class pickle.Pickler(file, protocol=None, *, fix_imports=True, buffer_callback=None)
    它接受一個二進制文件用于寫入 pickle 數據流。

  • class pickle.Unpickler(file, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)
    它接受一個二進制文件用于讀取 pickle 數據流。

  • class pickle.PickleBuffer(buffer)
    緩沖區的包裝器 (wrapper),緩沖區中包含著可封存的數據。buffer 必須是一個 buffer-providing 對象,比如 bytes-like object 或多維數組。

  • 2、pickle 與 json 模塊的比較

    json 模塊:是一個允許JSON序列化反序列化的標準庫模塊。

    Pickle 協議和 JSON (JavaScript Object Notation) 間有著本質的不同:
    \quad

  • JSON 是一個文本序列化格式(它輸出 unicode 文本,盡管在大多數時候它會接著以 utf-8 編碼),而 pickle 是一個二進制序列化格式;
  • JSON 是我們可以直觀閱讀的,而 pickle 不是;
  • JSON是可互操作的,在Python系統之外廣泛使用,而pickle則是Python專用的;
  • 默認情況下,JSON 只能表示 Python 內置類型的子集,不能表示自定義的類;但 pickle 可以表示大量的 Python 數據類型(可以合理使用 Python 的對象內省功能自動地表示大多數類型,復雜情況可以通過實現 specific object APIs 來解決)。
  • 不像pickle,對一個不信任的JSON進行反序列化的操作本身不會造成任意代碼執行漏洞。
  • 3、pickle應用實例

    示例1:創建一個文件,通過pickle模塊編碼為二進制流,再unpickle解碼為可讀數據。

    import numpy as np import pickle import osif __name__=='__main__':path = r'/Users/zhang/Documents/my_daily/KBQA_for_Diagnosis_yangyang/nlu/bert_intent_recognition/test_picklefile'file = open(path, 'wb')data = {'a':123, 'b':'ads', 'c':[[1,2],[3,4]]}pickle.dump(data, file)print("file:", file)file.close()f1 = open(path, 'rb')print("file1:", f1)data1 = pickle.load(f1)print(data1)打印輸出: >>> file: <_io.BufferedWriter name='/Users/yangyang/Documents/my_daily/KBQA_for_Diagnosis_yangyang/nlu/bert_intent_recognition/test_picklefile'> file1: <_io.BufferedReader name='/Users/yangyang/Documents/my_daily/KBQA_for_Diagnosis_yangyang/nlu/bert_intent_recognition/test_picklefile'> {'a': 123, 'b': 'ads', 'c': [[1, 2], [3, 4]]}

    示例2:創建一個文件,通過pickle模塊編碼為二進制流,再unpickle解碼為可讀數據。

    import numpy as np import pickle import os import random import matplotlib.pyplot as plt from PIL import Imagepath1 = r'/Users/yangyang/Documents/學習資料/d2l-zh/data/cifar_10數據集/cifar-10-batches-py/data_batch_1'if __name__ == '__main__':with open(path1, 'rb') as fo:data_dict = pickle.load(fo, encoding='bytes')print("data_dict:", data_dict)print("data_dict包含的鍵:",data_dict.keys())print("data_dict[b'batch_label']:",data_dict[b'batch_label'])print("data_dict[b'labels']:",data_dict[b'labels'])print("data_dict[b'filenames']:",data_dict[b'filenames'])print("data_dict[b'data'].shape:",data_dict[b'data'].shape)images_batch = np.array(data_dict[b'data'])images = images_batch.reshape([-1, 3, 32, 32])print("images.shape:",images.shape)imgs = images[5,:,:,:].reshape([3,32,32]) # images的四個維度分別為[第N張圖像, 圖像channel, 圖像width, 圖像length]img = np.stack((imgs[0,:,:], imgs[1,:,:], imgs[2,:,:]), 2)print("img.shape:",img.shape)plt.imshow(img)plt.axis('off')plt.show()輸出結果: >>> data_dict: {b'batch_label': b'training batch 1 of 5', b'labels': [6, 9, 9, 4, 1,...,],b'data': array([[ 59, 43, 50, ..., 140, 84, 72],[154, 126, 105, ..., 139, 142, 144],[255, 253, 253, ..., 83, 83, 84],...,[ 71, 60, 74, ..., 68, 69, 68],[250, 254, 211, ..., 215, 255, 254],[ 62, 61, 60, ..., 130, 130, 131]], dtype=uint8), b'filenames': [b'leptodactylus_pentadactylus_s_000004.png', b'camion_s_000148.png', b'tipper_truck_s_001250.png',...]>>> data_dict包含的鍵: dict_keys([b'batch_label', b'labels', b'data', b'filenames']) >>> data_dict[b'batch_label']: b'training batch 1 of 5' >>> data_dict[b'labels']: [6, 9, 9, 4, 1, 1, 2, 7, 8, 3, 4, 7, 7, 2,...] >>> data_dict[b'filenames']: [b'leptodactylus_pentadactylus_s_000004.png', b'camion_s_000148.png',...] >>> data_dict[b'data'].shape: (10000, 3072) >>> images.shape: (10000, 3, 32, 32) >>> "img.shape:"(32, 32, 3)

    4、pickle模塊解析CIFAR-10數據集

    CIFAR-10和CIFAR-100是來自于80 million張小型圖片的數據集,圖片收集者是Alex Krizhevsky, Vinod Nair, and Geoffrey Hinton。

    官網 http://www.cs.toronto.edu/~kriz/cifar.html

    cifar-10 數據集說明及下載:

  • 數據集組成:本數據及包含了6萬張分辨率為32x32的圖片,一共分為了10類,分別為:
    飛機、汽車、鳥、貓、鹿、狗、青蛙、馬、船、貨車。其中,5萬張作為訓練集,1萬張作為測試機。訓練集被分為了5批訓練和1批測試。每一批都是1萬張。測試集是從每一種分類中隨機抽取出來1000張組成。訓練集從10個分類中各自隨機抽取5000張,一共5萬張。
  • 數據結構:數據集解壓之后的樣子如下圖所示:
  • 說明:

    • 沒有后綴名的文件,如:data_batch_1,其實都是用python的cpickle庫打包好的,這個庫就是用來將python中的變量原封不動地存到本地使用的,當再次使用的時候,可以讀取出來。

    備注:有經驗的朋友會自動和json.dumps聯系起來,其實json模塊只能保存一個字典到本地的json文件,而pickle模塊(或者cpickle)卻可以打包任何對象。

    通過pickle在python3環境下讀取CIFAR-10數據:

    def unpickle(file):import picklewith open(file, 'rb') as fo:dict = pickle.load(fo, encoding='bytes')return dictdata = unpickle('test_batch') data.keys() # dict_keys([b'batch_label', b'labels', b'data', b'filenames']) data[b'data'][0] # array([158, 159, 165, ..., 124, 129, 110], dtype=uint8)

    每個字典如下表所示,每個batch文件轉換為dictonary,其中的內容是:

    鍵值
    dataa 10000×3072 array(uint85),array的每行是一張32×32的彩色圖片,前1024是red channel的值,后面1024是green channel的值,最后1024是blue channel的值。圖片是以行主順序存儲,所以,前數組中前32個數表示的是一張圖片第一行的red channel values。
    labels標簽,長度是10000,每個都是0-9的數字,是一個列表。其索引和data里面的索引相互對應。
    batch_labelbatch的名稱
    filenames數據集中data對應的圖片名稱數組
    • 含后綴的文件batches.meta,這個文件保存的就是索引與名字之間的對應。如:label_names[0] == “airplane”, label_names[1] == “automobile”,batches.meta文件包含了[b’num_cases_per_batch’, b’label_names’, b’num_vis’]。其中,label_names 對應 十個類別的英文名,cifar-10劃分為5個training batches。圖像也是彩色的,所以要給圖像的三個通道進行管理。

    參考鏈接:
    讀取代碼參考:https://blog.csdn.net/DarrenXf/article/details/85471718,
    cifar10數據格式以及讀取方式:https://blog.csdn.net/u014281392/article/details/74881967,
    TensorFlow進階:CNN對CIFAR10圖像分類和python讀取,https://www.cnblogs.com/jimobuwu/p/9161531.html

    將cifar的3個單通道數據,轉化為三通道數據,并保存:

    p = './data/cifar-10-batches/data_batch_1' d = unpickle(p) #print(d) #print(d.keys()) #print(d[b'batch_label']) #print(d[b'labels']) #print(d[b'filenames'])e = d[b'data'] for i in range(100):image = e[i]red_image = image[:1024].reshape(32,32)green_image = image[1024:2048].reshape(32,32)blue_image = image[2048:].reshape(32,32)result_img = np.ones((32, 32, 3), dtype=np.uint8)result_img[:,:,0] = red_imageresult_img[:,:,1] = green_imageresult_img[:,:,2] = blue_imagecv2.imwrite('a\\'+str(i)+'.jpg',result_img)


    參考鏈接:深度學習:CIFAR-10數據集讀取實操

    5、【對象持久性】的理解

    什么是持久性?

    持久性的基本思想很簡單。假定有一個 Python 程序,它可能是一個管理日常待辦事項的程序,您希望在多次執行這個程序之間可以保存應用程序對象(待辦事項)。換句話說,您希望將對象存儲在磁盤上,便于以后檢索。這就是持久性。要達到這個目的,有幾種方法,每一種方法都有其優缺點。
    例如,可以將對象數據存儲在某種格式的文本文件中,譬如 CSV 文件。或者可以用關系數據庫,譬如 Gadfly、MySQL、PostgreSQL 或者 DB2。這些文件格式和數據庫都非常優秀,對于所有這些存儲機制,Python 都有健壯的接口。

    這些存儲機制都有一個共同點: 存儲的數據是獨立于對這些數據進行操作的對象和程序。這樣做的好處是,數據可以作為共享的資源,供其它應用程序使用。缺點是,用這種方式,可以允許其它程序訪問對象的數據,這違背了面向對象的封裝性原則 — 即對象的數據只能通過這個對象自身的公共(public)接口來訪問。
    另外,對于某些應用程序,關系數據庫方法可能不是很理想。尤其是,關系數據庫不理解對象。相反,關系數據庫會強行使用自己的類型系統和關系數據模型(表),每張表包含一組元組(行),每行包含具有固定數目的靜態類型字段(列)。如果應用程序的對象模型不能夠方便地轉換到關系模型,那么在將對象映射到元組以及將元組映射回對象方面,會碰到一定難度。這種困難常被稱為阻礙性不匹配(impedence-mismatch)問題。

    對象持久性

    如果希望透明地存儲 Python 對象,而不丟失其身份和類型等信息,則需要某種形式的對象序列化:它是一個將任意復雜的對象轉成對象的文本或二進制表示的過程。同樣,必須能夠將對象經過序列化后的形式恢復到原有的對象。在 Python 中,這種序列化過程稱為 pickle,可以將對象 pickle 成字符串、磁盤上的文件或者任何類似于文件的對象,也可以將這些字符串、文件或任何類似于文件的對象 unpickle 成原來的對象。我們將在本文后面詳細討論 pickle。

    假定您喜歡將任何事物都保存成對象,而且希望避免將對象轉換成某種基于非對象存儲的開銷;那么 pickle 文件可以提供這些好處,但有時可能需要比這種簡單的 pickle 文件更健壯以及更具有可伸縮性的事物。例如,只用 pickle 不能解決命名和查找 pickle 文件這樣的問題,另外,它也不能支持并發地訪問持久性對象。如果需要這些方面的功能,則要求助類似于 ZODB(針對 Python 的 Z 對象數據庫)這類數據庫。ZODB 是一個健壯的、多用戶的和面向對象的數據庫系統,它能夠存儲和管理任意復雜的 Python 對象,并支持事務操作和并發控制。(請參閱 參考資料,以下載 ZODB。)令人足夠感興趣的是,甚至 ZODB 也依靠 Python 的本機序列化能力,而且要有效地使用 ZODB,必須充分了解 pickle。

    另一種令人感興趣的解決持久性問題的方法是 Prevayler,它最初是用 Java 實現的(有關 Prevaylor 方面的developerWorks 文章,請參閱 參考資料)。最近,一群 Python 程序員將 Prevayler 移植到了 Python 上,另起名為 PyPerSyst,由 SourceForge 托管(有關至 PyPerSyst 項目的鏈接,請參閱 參考資料)。Prevayler/PyPerSyst 概念也是建立在 Java 和 Python 語言的本機序列化能力之上。PyPerSyst 將整個對象系統保存在內存中,并通過不時地將系統快照 pickle 到磁盤以及維護一個命令日志(通過此日志可以重新應用最新的快照)來提供災難恢復。所以,盡管使用 PyPerSyst 的應用程序受到可用內存的限制,但好處是本機對象系統可以完全裝入到內存中,因而速度極快,而且實現起來要比如 ZODB 這樣的數據庫簡單,ZODB 允許對象的數目比同時在能內存中所保持的對象要多。

    既然我們已經簡要討論了存儲持久對象的各種方法,那么現在該詳細探討 pickle 過程了。雖然我們主要感興趣的是探索以各種方式來保存 Python 對象,而不必將其轉換成某種其它格式,但我們仍然還有一些需要關注的地方,譬如:如何有效地 pickle 和 unpickle 簡單對象以及復雜對象,包括定制類的實例;如何維護對象的引用,包括循環引用和遞歸引用;以及如何處理類定義發生的變化,從而使用以前經過 pickle 的實例時不會發生問題。我們將在隨后關于 Python 的 pickle 能力探討中涉及所有這些問題。
    一些經過 pickle 的 Python

    pickle 模塊及其同類模塊 cPickle 向 Python 提供了 pickle 支持。后者是用 C 編碼的,它具有更好的性能,對于大多數應用程序,推薦使用該模塊。我們將繼續討論 pickle ,但本文的示例實際是利用了 cPickle 。由于其中大多數示例要用 Python shell 來顯示,所以先展示一下如何導入 cPickle ,并可以作為 pickle 來引用它:

    參考鏈接:Python pickle模塊學習(超級詳細)

    總結

    以上是生活随笔為你收集整理的KBQA_多轮对话——模型源码解析(一)Pickle模块功能详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。