c++序列化方法


  1. 暫時使用boost 序列化, 目前我的測試基本都ok 只是對於c++11 shared ptr 沒有測試成功,只能手工寫下shared ptr 部分的序列化,也就是目前我對指針都不直接序列化,自己管理,例如下面樣子

    Load_(modelFile); //model直接序列化

    string normalizerName = read_file(OBJ_NAME_PATH(_normalizer));

    if (!normalizerName.empty())

    { //由於沒有利用shared ptr直接序列化,不知道具體信息,所以我save的時候寫了normalzier類型名字到文本,load時候通過這個確定類型

    _normalizer = NormalizerFactory::CreateNormalizer(normalizerName, OBJ_PATH(_normalizer));

    }

    string calibratorName = read_file(OBJ_NAME_PATH(_calibrator));

    if (!calibratorName.empty())

    {

    _calibrator = CalibratorFactory::CreateCalibrator(calibratorName, OBJ_PATH(_calibrator));

    }

    static NormalizerPtr CreateNormalizer(string name)

    {

    boost::to_lower(name);

    if (name == "minmax" || name == "minmaxnormalizer")

    {

    return make_shared<MinMaxNormalizer>();

    }

    if (name == "gaussian" || name == "gaussiannormalizer")

    {

    return make_shared<GaussianNormalizer>();

    }

    if (name == "bin" || name == "binnormalizer")

    {

    return make_shared<BinNormalizer>();

    }

    LOG(WARNING) << name << " is not supported now, do not use normalzier, return nullptr";

    return nullptr;

    }

       

    static NormalizerPtr CreateNormalizer(string name, string path)

    {

    NormalizerPtr normalizer = CreateNormalizer(name);

    if (normalizer != nullptr)

    {

    normalizer->Load(path); //normalzier直接序列化

    }

    return normalizer;

    }

       

    @TODO 確認下是否沒有辦法直接序列化shared ptr,

    另外可以嘗試下開源的專門序列化庫creal,creal仿照boost 序列化 同時boost序列化只支持binary,文本,xml三種序列化,文本序列化可讀性不強,binary速度最快,xml可讀性最高速度慢一些。我一般只用binary和xml格式。而creal 支持json格式的輸出,號稱支持shared ptr

       

    同一個模型boost序列化速度

  

Binary

Text

Save

1.8

2.29

Load

1.9

2.67

   

   

  1. 如果需要xml輸出,boost的序列化寫法和只需要binary輸出不一樣,建議采用支持xml輸出的寫法這樣互相都兼容。

       

    friend class boost::serialization::access;

    template<class Archive>

    void serialize(Archive &ar, const unsigned int version)

    {

    /*        ar & boost::serialization::base_object<Predictor>(*this);

    ar & _weights;

    ar & _bias;*/ //這種寫法只支持binary

    ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Predictor);

    ar & BOOST_SERIALIZATION_NVP(_weights); //這樣宏比較方便 如果需要改名字比如_weights->weights可以使用原函數

    ar & BOOST_SERIALIZATION_NVP(_bias);

    }

       

       

  2. 采用python腳本自動生成序列化部分的代碼。因為和c#不一樣 c#是默認都可以序列化,如果不需要序列化,你可以類似#define指定,而boost默認都不序列化,需要序列化的地方需要顯示都寫上

    Predictors]$ get-lines.py LinearPredictor.h 98 99 | gen-boost-seralize-xml.py

       

    friend class boost::serialization::access;

    template<class Archive>

    void serialize(Archive &ar, const unsigned int version)

    {

    ar & BOOST_SERIALIZATION_NVP(_weights);

    ar & BOOST_SERIALIZATION_NVP(_bias);

    }

       

4. 對於Predictor 默認是Save二進制,可選的SaveXml方式這個自動支持,可選的SaveText這個是特定的Precitor子類型如果有需要手動寫的文本輸出格式。

xml輸出類似這樣

   

轉換為json

xml2json.py model.xml > model.json

more model.json

采用json pretty print來查看json文件

jpp.py model.json | more

   

Xml2tojson.py 利用xmltodict 進行向json的轉換

   

import sys,os

import xmltodict, json

doc = xmltodict.parse(open(sys.argv[1]), process_namespaces=True)

print json.dumps(doc)

   

Jpp.py

import sys,os

import json

s = open(sys.argv[1]).readline().decode('gbk')

print json.dumps(json.loads(s),sort_keys=True, indent=4, ensure_ascii=False).encode('gbk')

   

  1. 如何更方便的查看輸出的模型?

    小的模型輸出直接看xml文本就好,如果數據比較多處理xml不是很方便,json好一些 用python,

    但是如果轉換為json的map也不是很方便因為你要按照key去訪問string類型是沒有自動提示的

       

    In [6]: import json

       

    In [7]: m = json.loads(open('./model.json').readline())

       

    In [8]: m.keys()

    Out[8]: [u'boost_serialization']

       

    In [9]: m['boost_serialization'].keys()

    Out[9]: [u'@version', u'@signature', u'data']

       

    In [18]: m['boost_serialization']['data']['_trees']['item'][0].keys()

    Out[18]:

    [u'_gainPValue',

    u'@tracking_level',

    u'@class_id',

    u'_lteChild',

    u'_gtChild',

    u'_maxOutput',

    u'_leafValue',

    u'NumLeaves',

    u'_splitGain',

    u'_splitFeature',

    u'_previousLeafValue',

    u'_threshold',

    u'@version',

    u'_weight']

       

    In [19]: m['boost_serialization']['data']['_trees']['item'][0]['_splitGain']['item'][10]

    Out[19]: u'3.89894126598927926e+00'

       

    由於python提示的時候_開頭的作為private默認是不提示的,因此做了修改

    #include "conf_util.h"

    #include <boost/serialization/nvp.hpp>

    #define GEZI_SERIALIZATION_NVP(name)\

    boost::serialization::make_nvp(gezi::conf_trim(#name).c_str(), name)

       

    這樣展示的就是gainPvalue這樣沒有_開頭了

       

    利用python的自省功能可以把json解析得到的dict數據,string作為key的轉為一個python object方便訪問如下

    def h2o(x):

    if isinstance(x, dict):

    return type('jo', (), {k: h2o(v) for k, v in x.iteritems()})

    elif isinstance(x, list):

    l = [h2o(item) for item in x]

    return l

    else:

    return x

       

    def h2o2(x):

    if isinstance(x, dict):

    return type('jo', (), {k: h2o2(v) for k, v in x.iteritems()})

    elif isinstance(x, list):

    return type('jo', (), {"i" + str(idx): h2o2(val) for idx, val in enumerate(x)})

    return l

    else:

    return x

       

    def xmlfile2obj(path):

    import xmltodict

    doc = xmltodict.parse(open(path), process_namespaces=True)

    return h2o(doc)

       

    def xmlfile2obj2(path):

    import xmltodict

    doc = xmltodict.parse(open(path), process_namespaces=True)

    return h2o2(doc)

       

    這樣對於序列化之后的xml文件可以直接使用 m = xmlfile2obj('*.xml') 或者 m = xml2obj2('*.xml')

    建議是用第一種,是標准轉換,提供第二個接口主要是python的自動提示對於list的item就沒有了,只能dir()查看。。

    第二種將[3]這樣轉為了.i3也就是去掉了所有list都用dict表示。

       

    m = xmlfile2obj('./model.xml')

    In [14]: m.boost_serialization.data.trees.item[0].splitGain.item[13]

    Out[14]: u'3.26213753939964946e+00'

       

    m = xmlfile2obj2('./model.xml')

    In [16]: m.boost_serialization.data.trees.item.i0.splitGain.item.i13

    Out[16]: u'3.26213753939964946e+00'

       

       

       

       

       

   


免責聲明!

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



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