如何解码(从 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);
}
在我的项目中,我使用词向量作为 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);
}