如何解码(从 base64)python np 数组并将其作为浮点向量重新加载到 C++ 中?

How to decode (from base64) a python np-array and reload it in c++ as a vector of floats?

在我的项目中,我使用词向量作为 300 维的 numpy 数组。我想将处理后的数组存储在 mongo 数据库中,base64 编码,因为这样可以节省大量存储空间 space.

Python代码

import base64
import numpy as np

vector = np.zeros(300, dtype=np.float32) # represents some word-vector
vector = base64.b64encode(vector) # base64 encoding
# Saving vector to MongoDB...

在MongoDB中,它像this一样以二进制形式保存。在 C++ 中,我想将此二进制数据加载为 std::vector。因此我必须先解码数据然后正确加载它。我能够使用 mongocxx 将二进制数据放入 c++ 程序并将其作为 uint8_t* 大小为 1600 - 但现在我不知道该怎么做并且会很高兴如果有人可以帮助我。谢谢 (:

C++ 代码

const bsoncxx::document::element elem_vectors = doc["vectors"];
const bsoncxx::types::b_binary vectors = elemVectors.get_binary();

const uint32_t b_size = vectors.size; // == 1600
const uint8_t* first = vectors.bytes;

// How To parse this as a std::vector<float> with a size of 300?

解决方案

我将这些行添加到我的 C++ 代码中,并且能够加载包含 300 个元素和所有正确值的向量。

    const std::string encoded(reinterpret_cast<const char*>(first), b_size);
    std::string decoded = decodeBase64(encoded);
    std::vector<float> vec(300);
    for (size_t i = 0; i < decoded.size() / sizeof(float); ++i) {
        vec[i] = *(reinterpret_cast<const float*>(decoded.c_str() + i * sizeof(float)));
    }

提一下:感谢@Holt 的信息,对 Numpy 数组进行 base64 编码然后将其存储为二进制是不明智的。在 numpy 数组上调用“.to_bytes()”然后将其存储在 MongoDB 中要好得多,因为它将文档大小从 1.7kb (base64) 减小到 1.2kb (to_bytes ()) 然后节省计算时间,因为不必计算编码(和解码!)!

感谢@Holt 指出我的错误

首先,使用base64编码无法节省存储空间space。相反,它会浪费你的存储空间。 一个有300个浮点数的数组,存储空间只有300 * 4 = 1200bytes。而编码后,存储空间为1600字节!查看更多关于 base64 here.

其次,您想将字节解析为 vector<float>。如果您仍然使用 base64 编码,则需要对字节进行解码。我建议你使用一些第三方库或尝试 this question。假设你已经有了decode函数。

std::string base64_decode(std::string const& encoded_string); // or something like that.

您需要使用 reinterpret_cast 来获取值。

const std::string encoded(first, b_size);
std::string decoded = base64_decode(encoded);
std::vector<float> vec(300);
for (size_t i = 0; i < decode.size() / sizeof(float); ++i) {
    vec[i] = *(reinterpret_cast<const double*>(decoded.c_str()) + i);
}