Cómo decodificar (desde base64) un np-array de python y recargarlo en c++ como un vector de floats?
Para decodificar un np-array desde base64 en python y luego recargarlo en c++ como un vector de floats, debes seguir los siguientes pasos:
1. En python, importa los módulos necesarios:
“`python
import numpy as np
import base64
“`
2. Codifica el np-array en base64:
“`python
np_array = np.array([1.0, 2.0, 3.0, 4.0]) # Ejemplo de un np-array en python
encoded_data = base64.b64encode(np_array.astype(np.float32).tobytes())
“`
3. Transfiere el resultado a c++ y decodifica desde base64:
Para decodificar en c++, necesitarás una biblioteca de base64. Puedes utilizar una biblioteca como ‘Boost’ o implementar tus propias funciones.
Aquí hay un ejemplo utilizando la biblioteca ‘Boost’:
“`cpp
#include
#include
#include
#include
int main() {
std::string encoded_data = “aW5jbHVkaW5nIHRvIGEgYmFzZTY0IGVuY29kaW5n”; // Resultado codificado en base64
// Decodifica desde base64 a una cadena de bytes
std::string decoded_string = boost::algorithm::b64decode(encoded_data);
// Convierte la cadena de bytes en un vector de floats
const float* float_ptr = reinterpret_cast(decoded_string.c_str());
std::vector float_vector(float_ptr, float_ptr + (decoded_string.length() / sizeof(float)));
// Imprime los elementos del vector
for (const auto& element : float_vector) {
std::cout << element << " ";
}
return 0;
}
```
Asegúrate de incluir y vincular correctamente la biblioteca 'Boost' en tu proyecto. Este es solo un ejemplo básico y podrías necesitar hacer ajustes adicionales según tu entorno y requerimientos específicos.
En mi proyecto trabajo con vectores de palabras como matrices de numpy con una dimensión de 300. Quiero almacenar las matrices procesadas en una base de datos de mongo, codificadas en base64, porque esto ahorra mucho espacio de almacenamiento.
Código en Python
import base64
import numpy as np
vector = np.zeros(300, dtype=np.float32) # representa algún vector de palabras
vector = base64.b64encode(vector) # codificación en base64
# Guardando el vector en MongoDB...
En MongoDB se guarda como binario como se muestra en este enlace. En C++, me gustaría cargar estos datos binarios como un std::vector
Código en 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;
// ¿Cómo analizar esto como un std::vector<float> con un tamaño de 300?
Solución
Añadí estas líneas a mi código de C++ y pude cargar un vector con 300 elementos y todos los valores correctos.
c++
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)));
}
Mencionar: Gracias a la información de @Holt, no es sabio codificar una matriz de Numpy en base64 y luego almacenarla como binario. Es mucho mejor llamar “.tobytes()” en la matriz de numpy y luego almacenar eso en MongoDB, porque reduce el tamaño del documento de 1.7kb (base64) a 1.2kb (tobytes()) y luego ahorra tiempo de computación porque ¡no es necesario calcular la codificación (¡y decodificación!)!
davy.ai
Para cargar los datos binarios como un
std::vector<float>
en C++, primero necesitas decodificar los datos base64. Esto se puede hacer utilizando una función de decodificación base64, comodecodeBase64()
.Una vez que tienes los datos decodificados como un std::string, puedes crear un std::vector con un tamaño de 300 e iterar sobre el string decodificado para llenar cada elemento del vector.
Aquí tienes un ejemplo de código en C++ que ilustra esto:
“`c++
#include
#include
#include
std::string decodeBase64(const std::string& encoded); // función de decodificación base64
// …
const bsoncxx::document::element elem_vectors = doc[“vectors”];
const bsoncxx::types::b_binary vectors = elem_vectors.get_binary();
const uint32_t b_size = vectors.size;
const uint8_t* first = vectors.bytes;
// decodificar los datos base64(first), b_size);
const std::string encoded(reinterpret_cast
std::string decoded = decodeBase64(encoded);
// crear un std::vector con un tamaño de 300 y llenar cada elemento vec(300);(decoded.c_str() + i * sizeof(float)));
std::vector
for (size_t i = 0; i < decoded.size() / sizeof(float); ++i) {
vec[i] = *(reinterpret_cast
}
“`
Vale la pena señalar que codificar una matriz de numpy como base64 y luego almacenarla como binario puede que no sea el enfoque más eficiente. En su lugar, podrías llamar a
.to_bytes()
en la matriz de numpy y almacenar los bytes resultantes en MongoDB. Esto reduciría el tamaño del documento y ahorraría tiempo de computación, ya que no habría necesidad de codificar y decodificar los datos.