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
Kanad
fonte
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
cheez
fonte
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.

Tirth Patel
fonte
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).

MappaGnosis
fonte
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.

Madhuparna Bhowmik
fonte
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)
travs15
fonte
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)
Gustavo Mirapalheta
fonte
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
9

Você pode tentar alterar o valor do sinalizador

np.load(training_image_names_array,allow_pickle=True)
Brayan Armando Yaquian Gonzale
fonte
Ótimo. Está funcionando. Esta deve ser a resposta aceita.
Biranchi
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

farid khafizov
fonte
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 :

Yasser Albarbay
fonte
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)
Shristi Gupta
fonte
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.

Wissam
fonte
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:
Leonhard Rathnak
fonte
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
ReimuChan
fonte
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.

sidk
fonte
0

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

!pip install tf-nightly

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

Joocheol Kim
fonte
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
Sajad Norouzi
fonte
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)
James
fonte
0

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

Nasif Imtiaz Ohi
fonte