Como corrigir 'Arrays de objetos não podem ser carregados quando allow_pickle = False' para a função imdb.load_data ()?


113

Estou tentando implementar o exemplo de classificação binária usando o conjunto de dados IMDb no Google Colab . Eu implementei esse modelo antes. Mas quando tentei fazer isso novamente após alguns dias, ele retornou um erro de valor: 'Matrizes de objetos não podem ser carregadas quando allow_pickle = False' para a função load_data ().

Já tentei resolver isso, referindo-se a uma resposta existente para um problema semelhante: Como corrigir 'Arrays de objetos não podem ser carregados quando allow_pickle = False' no algoritmo sketch_rnn Mas descobri que apenas adicionar um argumento allow_pickle não é suficiente.

Meu código:

from keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

O erro:

ValueError                                Traceback (most recent call last)
<ipython-input-1-2ab3902db485> in <module>()
      1 from keras.datasets import imdb
----> 2 (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

2 frames
/usr/local/lib/python3.6/dist-packages/keras/datasets/imdb.py in load_data(path, num_words, skip_top, maxlen, seed, start_char, oov_char, index_from, **kwargs)
     57                     file_hash='599dadb1135973df5b59232a0e9a887c')
     58     with np.load(path) as f:
---> 59         x_train, labels_train = f['x_train'], f['y_train']
     60         x_test, labels_test = f['x_test'], f['y_test']
     61 

/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py in __getitem__(self, key)
    260                 return format.read_array(bytes,
    261                                          allow_pickle=self.allow_pickle,
--> 262                                          pickle_kwargs=self.pickle_kwargs)
    263             else:
    264                 return self.zip.read(key)

/usr/local/lib/python3.6/dist-packages/numpy/lib/format.py in read_array(fp, allow_pickle, pickle_kwargs)
    690         # The array contained Python objects. We need to unpickle the data.
    691         if not allow_pickle:
--> 692             raise ValueError("Object arrays cannot be loaded when "
    693                              "allow_pickle=False")
    694         if pickle_kwargs is None:

ValueError: Object arrays cannot be loaded when allow_pickle=False

1
O que esse erro significa?
Charlie Parker

3
@CharlieParker Aparentemente, foi adicionado um parâmetro na função numpy.load (). Anteriormente era np.load(path), agora é np.load(path, boolean)Por padrão, o booleano (allow_pickle) é falso
Kanad

obrigado! mas isso significa que agora entorpecido picles coisas para mim sem minha permissão ao salvar ?! esquisito! Eu olhei os np.savezdocumentos, mas não havia nenhuma referência a decapagem, então não tenho ideia de como ele sabia em primeiro lugar que as coisas que eu estava salvando eram coisas do Pytorch e não apenas entorpecidas ... estranho! Se você sabe o que está acontecendo, compartilhe conosco :)
Charlie Parker

Minha convicção, depois de encontrar o mesmo problema, é que depende totalmente do que você está salvando em um arquivo .npz. Se você estiver salvando tipos integrados, nada de decapagem. No entanto, se você escrever um objeto, python / numpy irá selecioná-lo (isto é, serializá-lo). Isso, eu imagino, abre um risco de segurança, então versões posteriores do numpy pararam de permitir que fosse o padrão ... só um palpite.
Robert Lugg

Respostas:


123

Aqui está um truque para forçar imdb.load_datapara permitir picles, em seu caderno, substituindo esta linha:

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

por este:

import numpy as np
# save np.load
np_load_old = np.load

# modify the default parameters of np.load
np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)

# call load_data with allow_pickle implicitly set to true
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

# restore np.load for future normal usage
np.load = np_load_old

Eu sugiro adicionar "import numpy as np" no começo. Numpy pode ser importado com um nome diferente, ou não ser importado ...
Kristóf

Isso me ajuda muito
estática ou

7
Obtendo erroTypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat

1
O problema de vários valores para o argumento de palavra-chave foi abordado em stackoverflow.com/a/58586450/5214998
Sajad Norouzi

91

Este problema ainda está em jogo no keras git. Espero que seja resolvido o mais rápido possível. Até então, tente fazer o downgrade de sua versão numpy para 1.16.2. Parece resolver o problema.

!pip install numpy==1.16.1
import numpy as np

Esta versão do numpy tem o valor padrão de allow_pickle as True.


4
Eu usaria a solução do MappaGnosis em vez de rebaixar a versão numpy: para mim brincar com a versão, dançar é o último recurso!
Eric

2
1.16.4 também tem o problema
kensai

Obrigado @kensai. Alguém sabe se isso foi resolvido no numpy 1,17?
nsheff de

No numpy 1.18, esse problema ainda está presente. Tive que mudar para o numpy 1.16.1 e agora está resolvido. obrigado.
BC Smith

55

Seguindo esse problema no GitHub, a solução oficial é editar o arquivo imdb.py. Essa correção funcionou bem para mim sem a necessidade de fazer o downgrade do numpy. Encontre o arquivo imdb.py em tensorflow/python/keras/datasets/imdb.py(o caminho completo para mim era: C:\Anaconda\Lib\site-packages\tensorflow\python\keras\datasets\imdb.py- outras instalações serão diferentes) e altere a linha 85 de acordo com o diff:

-  with np.load(path) as f:
+  with np.load(path, allow_pickle=True) as f:

O motivo da mudança é a segurança para evitar o equivalente em Python de uma injeção de SQL em um arquivo em conserva. A mudança acima SOMENTE afetará os dados imdb e, portanto, você manterá a segurança em outro lugar (sem rebaixar o numpy).


1
Como disse, estou usando o Colab, como posso fazer alterações no arquivo imdb.py?
Kanad

Este não é um problema do Colab, pois o IMDB é baixado localmente na primeira vez que você o consulta. Portanto, haverá uma cópia local em algum lugar do seu computador (tente os caminhos sugeridos acima - ou, se você definir um diretório para Colab, tente lá primeiro) e simplesmente abra o arquivo imdb.py em qualquer IDE ou mesmo em um editor de texto para faça a alteração (usei o Notepad ++ para editar o arquivo imdb.py que foi baixado enquanto trabalhava no Jupyter - um ambiente muito semelhante ao Colab!).
MappaGnosis de

a solução que funciona para mim é> np.load (data_path, encoding = 'latin1', allow_pickle = True)
Jorge Santos Neill

Esta é a solução que utilizo, pois mexer nas versões (principalmente do numpy), como na resposta aceita, é algo que procuro evitar. Isso também é mais pitônico, pois apenas corrige explicitamente o problema. (Observe também que as versões mais recentes do Keras, no github, realmente incorporam essa correção)
Eric

35

Acabei de usar allow_pickle = True como um argumento para np.load () e funcionou para mim.


Estou observando que permitir picles muda a matriz. A matriz .npy antes de salvar e depois de carregar gera uma exceção ao tentar afirmar a igualdade usando np.array_equal
yasht

18

No meu caso trabalhei com:

np.load(path, allow_pickle=True)

12

Acho que a resposta de cheez ( https://stackoverflow.com/users/122933/cheez ) é a mais fácil e eficaz. Eu elaboraria um pouco sobre isso para não modificar uma função numpy durante todo o período da sessão.

Minha sugestão está abaixo. Estou usando para baixar o conjunto de dados reuters do keras, que está apresentando o mesmo tipo de erro:

old = np.load
np.load = lambda *a,**k: old(*a,**k,allow_pickle=True)

from keras.datasets import reuters
(train_data, train_labels), (test_data, test_labels) = reuters.load_data(num_words=10000)

np.load = old
del(old)

Você pode explicar mais sobre o que está acontecendo aqui?
Kanad

1
Não consegui carregar os conjuntos de dados Keras. Pesquisei na internet e encontrei uma solução que dizia que eu deveria editar o arquivo imdb.py, outros apontavam para mudanças na instalação numpy (como aqui) ou mudança do Tensorflow para uma versão de desenvolvimento. Me deparei com a solução cheez. IMHO esse foi o mais fácil e eficaz.
Gustavo Mirapalheta

1
@Kanad - lambda é uma função anônima. Gustavo criou um aumento de função para o np.load, usou a versão aumentada e, em seguida, voltou ao valor padrão.
EngrStudent


4

nenhuma das soluções listadas acima funcionou para mim: eu executo o anaconda com o python 3.7.3. O que funcionou para mim foi

  • execute "conda install numpy == 1.16.1" do Anaconda PowerShell

  • feche e reabra o bloco de notas


Obrigado, foi isso que eu procurei. A propósito, parece que 1.16.2 é a versão mais recente, onde allow_pickle=Trueé o valor padrão.
Matěj Račinský

3

no notebook jupyter usando

np_load_old = np.load

# modify the default parameters of np.load
np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)

funcionou bem, mas o problema aparece quando você usa esse método no spyder (você precisa reiniciar o kernel todas as vezes ou obterá um erro como:

TypeError: () obteve vários valores para o argumento de palavra-chave 'allow_pickle'

Resolvi esse problema usando a solução aqui :


3

Aterrissei aqui, tentei seus caminhos e não consegui descobrir.

Na verdade, eu estava trabalhando em um código pré-determinado onde

pickle.load(path)

foi usado, então eu o substituí por

np.load(path, allow_pickle=True)

2

Sim, instalar uma versão anterior do numpy resolveu o problema.

Para quem usa PyCharm IDE:

em meu IDE (Pycharm), Arquivo-> Configurações-> Intérprete do projeto: Eu descobri que meu numpy era 1.16.3, então volto para 1.16.1. Clique em + e digite numpy na pesquisa, marque "especificar versão": 1.16.1 e escolha -> instalar pacote.


2

encontre o caminho para imdb.py e, em seguida, adicione o sinalizador a np.load (caminho, ... sinalizador ...)

    def load_data(.......):
    .......................................
    .......................................
    - with np.load(path) as f:
    + with np.load(path,allow_pickle=True) as f:

1

É trabalho para mim

        np_load_old = np.load
        np.load = lambda *a: np_load_old(*a, allow_pickle=True)
        (x_train, y_train), (x_test, y_test) = reuters.load_data(num_words=None, test_split=0.2)
        np.load = np_load_old

4
E algum contexto explicando por que sua solução funciona. (Da avaliação).
ZF007

1

O que descobri é que o TensorFlow 2.0 (estou usando 2.0.0-alpha0) não é compatível com a versão mais recente do Numpy, ou seja, v1.17.0 (e possivelmente v1.16.5 +). Assim que o TF2 é importado, ele lança uma lista enorme de FutureWarning, que se parece com isto:

FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_qint8 = np.dtype([("qint8", np.int8, 1)])
/anaconda3/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_qint8 = np.dtype([("qint8", np.int8, 1)])
/anaconda3/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_quint8 = np.dtype([("quint8", np.uint8, 1)])
/anaconda3/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.

Isso também resultou no erro allow_pickle ao tentar carregar o conjunto de dados imdb do keras

Tentei usar a solução a seguir que funcionou bem, mas tive que fazer isso em todos os projetos em que importava TF2 ou tf.keras.

np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)

A solução mais fácil que encontrei foi instalar o numpy 1.16.1 globalmente ou usar versões compatíveis do tensorflow e do numpy em um ambiente virtual.

Meu objetivo com esta resposta é apontar que não é apenas um problema com imdb.load_data, mas um problema maior gerado pela incompatibilidade das versões do TF2 e Numpy e pode resultar em muitos outros bugs ou problemas ocultos.


0

Tensorflow tem uma correção na versão tf-nightly.

!pip install tf-nightly

A versão atual é '2.0.0-dev20190511'.


0

A resposta de @cheez às vezes não funciona e chama a função recursivamente novamente e novamente. Para resolver este problema, você deve copiar a função profundamente. Você pode fazer isso usando a função partial, então o código final é:

import numpy as np
from functools import partial

# save np.load
np_load_old = partial(np.load)

# modify the default parameters of np.load
np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)

# call load_data with allow_pickle implicitly set to true
(train_data, train_labels), (test_data, test_labels) = 
imdb.load_data(num_words=10000)

# restore np.load for future normal usage
np.load = np_load_old

0

Eu não costumo postar nessas coisas, mas isso era super irritante. A confusão vem do fato de que alguns dos imdb.pyarquivos Keras já foram atualizados:

with np.load(path) as f:

para a versão com allow_pickle=True. Certifique-se de verificar o arquivo imdb.py para ver se essa alteração já foi implementada. Se tiver sido ajustado, o seguinte funciona bem:

from keras.datasets import imdb
(train_text, train_labels), (test_text, test_labels) = imdb.load_data(num_words=10000)

0

A maneira mais fácil é alterar a imdb.pyconfiguração allow_pickle=Truepara np.loada linha em que imdb.pylança o erro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.