2017-09-28 3 views
2

Ich arbeite mit Bildern in numply Array-Form. Ich muss sie zu/von JSON serialisieren/deserialisieren (ich verwende MongoDB)Warum ist ein BSON serialisiertes numpy Array viel größer als das Original?

numpy Felder können nicht mit json.dump serialisiert werden; Ich bin mir bewusst, this aber ich frage mich, ob es einen besseren Weg, da die Umwandlung eines Bytes numpy Array BSON die Anzahl von Bytes multipliziert um fast 12 (Ich verstehe nicht, warum):

import numpy as np 
import bson 
from io import StringIO as sio 
RC = 500 
npdata = np.zeros(shape=(RC,RC,3), dtype='B') 
rows, cols, depth = npdata.shape 
npsize = rows*cols*depth 
npdata=npdata.reshape((npsize,)) 
listdata = npdata.tolist() 
bsondata = bson.BSON.encode({"rows": rows, "cols": cols, "data": listdata}) 
lb = len(bsondata) 
print(lb, npsize, lb/npsize) 

> 8888926 750000 11.851901333333334 
+1

Die Frage besagt, dass Sie zu/von JSON serialisieren müssen, aber dann verwenden Sie BSON. Welchen brauchst du wirklich? Oder suchen Sie nach einer * Möglichkeit, Arrays effizient zu serialisieren? Bitte klären Sie. – kazemakase

+0

Sie kommunizieren mit MongoDB in JSON, aber MongoDB verwendet BSON hinter den Kulissen. Was ich suche, ist eine vernünftige BSON-Größe. – Eduardo

Antwort

1

Die Grund für diese erhöhte Anzahl an Bytes ist, wie BSON die Daten speichert. Sie können diese Informationen in der BSON specification finden, aber schauen wir uns ein konkretes Beispiel aussehen:

import numpy as np 
import bson 

npdata = np.arange(5, dtype='B') * 11 
listdata = npdata.tolist() 
bsondata = bson.BSON.encode({"rows": rows, "cols": cols, "data": listdata}) 

print([hex(b) for b in bsondata]) 

Hier speichern wir ein Array mit Werten [0, 11, 22, 33, 44, 55] als BSON und die resultierenden Binärdaten drucken. Im Folgenden werde ich das Ergebnis mit Anmerkungen versehen haben, zu erklären, was los ist:

['0x47', '0x0', '0x0', '0x0', # total number of bytes in the document 
# First element in document 
    '0x4', # Array 
    '0x64', '0x61', '0x74', '0x61', '0x0', # key: "data" 
    # subdocument (data array) 
     '0x4b', '0x0', '0x0', '0x0', # total number of bytes 
     # first element in data array 
      '0x10',      # 32 bit integer 
      '0x30', '0x0',     # key: "0" 
      '0x0', '0x0', '0x0', '0x0', # value: 0 
     # second element in data array 
      '0x10',      # 32 bit integer 
      '0x31', '0x0',     # key: "1" 
      '0xb', '0x0', '0x0', '0x0', # value: 11 
     # third element in data array 
      '0x10',      # 32 bit integer 
      '0x32', '0x0',     # key: "2" 
      '0x16', '0x0', '0x0', '0x0', # value: 22    
# ... 
] 

Neben einigen Format Overhead wird jeder Wert des Arrays eher verschwenderisch mit 7 Byte codiert: 1 Byte den Datentyp angeben, 2 Byte für eine Zeichenkette, die den Index enthält (drei Bytes für Indizes> = 10, vier Bytes für Indizes> = 100, ...) und vier Bytes für den 32-Bit-Integer-Wert.

Dies erklärt zumindest, warum die BSON-Daten so viel größer sind als das ursprüngliche Array.

Ich fand zwei Bibliotheken GitHub - mongodb/bson-numpy und GitHub - ajdavis/bson-numpy, die eine bessere Arbeit der Codierung von NUMBY-Arrays in BSON tun können. Ich habe sie jedoch nicht getestet, daher kann ich nicht sagen, ob das der Fall ist oder ob sie überhaupt richtig funktionieren.

Verwandte Themen