2016-05-25 6 views
1

Я пытаюсь сериализовать spacy.io документов в байтовые строки и сохранять их в массиве numpy.numpy trimming завершающие нули в байтовых строках

spacy имеет функцию to_bytes, которая производит bytearray. Я вызываю str на этом bytearray и вставляю этот строковый объект в массив numpy. Это работает для большинства документов, кроме тех, которые заканчиваются конечным нулевым байтом.

Для воспроизведения:

>>> 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') 

numpy Строка отсекает любые конечные нули, то DTYPE для строки фиксированной длины имеет ту же длину, что и входной текст однако.

Вы можете увидеть это даже от создания каких-либо байтовой строки с задней нулевых байтов в массиве:

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

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

numpy Я полагаю, посчитает завершающие нули несущественным? Однако я не могу десериализовать эти байты обратно на объект документа spacy.

Есть ли способ получить numpy, чтобы не обрезать конечные нули или мне нужно придерживаться списков Python для этого сценария?

+1

Append фиктивных ненулевых байт перед хранением и удалить его после извлечения? – nekomatic

+0

@nekomatic спасибо за предложение, я мог бы определенно сделать это, и это сработает. В идеале я хотел бы знать, почему «numpy» делает это, особенно любопытно о несоответствии между длиной строки dtype и размером обрезанной строки. – dsimmie

ответ

3

Это нормальное поведение. После b_arr_np.tostring() вы можете видеть, что все конечные нули в порядке.

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' 

Отметить сообщение information loss with bytes type от github. Вопросы, либо использовать trailng ненулевых байты или использовать dtype=uint8 с b_arr:

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

Спасибо за это @ vadim-shkaberda. Это сообщение объясняет все, о чем мне было интересно. К сожалению, ваше предложение использовать 'np.uint8' для меня не работает, поскольку у меня смешанные формы bytearrays: ' np.asarray ([bytearray (b '\ xca \ x00 \ x00 \ x00')), bytearray (b '\ XCA \ x00 \ x00')], DTYPE = np.uint8) ' выдает ошибку значение: ' ValueError: установка элемента массива с sequence.' в пост наводит на мысль я могу использовать объект 'DTYPE ', но это теряет преимущество использования' numpy' над списками Python. Я думаю, что я буду придерживаться использования обходного пути, предложенного @nekomatic, и добавьте фиктивный байт и удаляем его после. – dsimmie