2016-05-25 23 views
1

Ich versuche, spacy.io Dokumente in Byte-Strings zu serialisieren und sie in einem numpy Array zu speichern.numpy trimmen nachgestellte Nullen in Byte-Strings

spacy hat eine to_bytes Funktion, die eine bytearray erzeugt. Ich rufe str auf diesem bytearray an und füge dieses Zeichenfolgenobjekt in ein numpy Array ein. Dies funktioniert für die meisten Dokumente mit Ausnahme derer, die mit einem abschließenden Nullbyte enden.

zu reproduzieren:

>>> import numpy as np 
>>> b_arr = bytearray(b'\xca\x00\x00\x00n\xff\xff\xff\x19C\x98\xc9\x06\xb18{\xa5\xe0\xaf6\xe3\x9f\xa7\xad\x86\xd6\x8d\xc0\xe6Mo;{\x96xm\x80\xe5\x8c\x9f<!\xc33\x9dg\xd3\xb3D\xf6\xac\x03P\x8do\x07m$r)\x06XBI\xc87\xcao\x83\x1d\xe4\r]\x86\xda\xeb\xb8\x1f\xd5\xcb\xde\xaa\x85r\x0f\xf1=p\xd6\x01\xdc\x83Z|&\xeb\xce|\xf9o\xa0\xe99x\x87\x87\xac\x1b\x17\x08\x000\x92\x10A\x98\x10\x13\x89(0\x88 "!*N\xf8\xe6\xf4\r\xb1e\xf0\x9d\xfd\x80\xa2G2\x18\xdesv\xec\x85\xf7\xb1\xb3\xb3\xa68\xa7n\xe8BF\xa6\xe0\xb1\x8d\x8d\x9c\xe5\x99\x9bV\xfcE`\x1cI\x92$I\x92$I\x92$%I\x92\xe4\xff\xff\x7f\xd1\xff\xf0T\xa6\xe8\n\x9a\xd3\xffMe0\xa9\x15\xf1|\x00') 
>>> b_arr_text = str(b_arr) 
>>> b_arr_np = np.asarray([b_arr_text], dtype=np.str) 
>>> b_arr_text == b_arr_np[0] 
Out[229]: False 
>>> len(b_arr_text) 
Out[230]: 206 
>>> len(b_arr_np[0]) 
Out[231]: 205 
>>> b_arr_np.dtype 
Out[232]: dtype('S206') 

Die numpy Zeichenfolge trimmt irgendwelche nachgestellten Nullen ist die dtype für die feste Länge Zeichenfolge die gleiche Länge wie der Eingabetext jedoch.

Sie können dies sehen auch aus beliebigem bytestring zu schaffen mit Hinter Null-Bytes in einem Array:

>>> np.asarray(['\xca\x00\x00\x00'], dtype=np.str) 

Out: array(['\xca'], dtype='|S4') 

Ich nehme an numpy davon ausgeht, nachfolgende Nullen unbedeutend zu sein? Allerdings kann ich diese Bytestrings nicht zu einem spacy Dokumentobjekt deserialisieren.

Gibt es eine Möglichkeit, numpy zu erhalten, die abschließenden Nullen nicht zu trimmen, oder muss ich Python-Listen für dieses Szenario beibehalten?

+1

Anfügen einen Dummy-nicht-Null-Byte vor dem Speichern und entfernt sie nach dem Abrufen? – nekomatic

+0

@nekomatic danke für den Vorschlag, ich könnte definitiv tun, und es würde funktionieren. Idealerweise würde ich gerne wissen, warum 'numpy' das macht, besonders neugierig auf die Diskrepanz zwischen der 'dtype'-Saitenlänge und der Größe der getrimmten Saite. – dsimmie

Antwort

3

Es ist normales Verhalten. Nach b_arr_np.tostring() können Sie sehen, dass alle abschließenden Nullen in Ordnung sind.

b_arr = bytearray(b'\xca\x00\x00\x00') 

b_arr_text = str(b_arr) 

b_arr_np = np.asarray([b_arr_text], dtype=np.str) 

b_arr_np 
Out[303]: 
array(['\xca'], 
     dtype='|S4') 

b_arr_np.tostring() 
Out[304]: '\xca\x00\x00\x00' 

Überprüfen Sie Beitrag information loss with bytes type von Github. Probleme werden entweder trailng Nicht-Null-Bytes verwenden oder mit dtype=uint8b_arr verwenden:

b_arr_np = np.asarray([b_arr], dtype=np.uint8) 

b_arr_np 
Out[319]: array([[202, 0, 0, 0]], dtype=uint8) 

b_arr_np.tostring() 

Out[320]: '\xca\x00\x00\x00' 
+0

Danke für diese @ vadim-shkaberda .. dieser Beitrag erklärt alles, worüber ich mich wundere. Leider funktioniert Ihr Vorschlag, 'np.uint8' zu verwenden, nicht, da ich Formbytearrays gemischt habe: ' np.asarray ([Bytearray (b '\ xca \ x00 \ x00 \ x00'), Bytearray (b '\ XCA \ x00 \ x00')], dtype = np.uint8) ' erzeugt einen Wert Fehler: ' Valueerror: ein Array-Element mit einem sequence.' Als Beitrag schlägt Einstellung ich das Objekt verwenden kann 'dtype 'aber das verliert den Vorteil,' numpy' über Python-Listen zu verwenden. Ich denke, ich werde bei der von @nekomatic vorgeschlagenen Lösung bleiben und ein Dummy-Byte anhängen und danach entfernen. – dsimmie