imdb.load_data()関数の「allow_pickle = False」のときに「オブジェクト配列をロードできない」を修正するにはどうすればよいですか?


113

Google Colabの IMDbデータセットを使用してバイナリ分類の例を実装しようとしています。このモデルは以前に実装しました。しかし、数日後にもう一度実行しようとすると、値エラーが返されました。

私はすでにこれを解決しようとしましたが、同様の問題の既存の回答を参照しています:sketch_rnnアルゴリズムで「allow_pickle = False」のときにオブジェクト配列をロードできない方法 しかし、allow_pickle引数を追加するだけでは不十分であることがわかります。

私のコード:

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

エラー:

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
このエラーはどういう意味ですか?
チャーリーパーカー、

3
@CharlieParkerどうやら、numpy.load()関数にパラメーターが追加されています。以前はでしたがnp.load(path)、現在はnp.load(path, boolean)です。デフォルトでは、ブール値(allow_pickle)はfalseです
Kanad

ありがとう!しかし、それは今、numpyが保存時に私の許可なしに私のために物事を漬けることを意味しますか?!変!私はnp.savezドキュメントを調べましたが、ピクルスへの参照がなかったので、最初に保存していたものがPytorchのものであり、numpy ... weirdだけではないことを最初から知っていたのかわかりません。あなたが私たちと共有していることを知っているなら:)
チャーリー・パーカー

同じ問題が発生した後の私の信念は、.npzに保存する内容に完全に依存しているということです。組み込みタイプを保存する場合、酸洗いはありません。ただし、オブジェクトを記述した場合、python / numpyはそれをピクルします(つまり、シリアル化します)。これは私が想像するセキュリティリスクを開くので、numpyの新しいバージョンはデフォルトにすることを止めました...
Robert Lugg

回答:


123

imdb.load_dataノートブックでこの行を置き換えて、ピクルスを許可するように強制するトリックを次に示します。

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

これで:

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

最初に「import numpy as np」を追加することをお勧めします。numpyのは...別の名前でインポート、またはまったくインポートされませんすることができる
クリストフ

それは私を大いに助けます
静的または

7
エラーの発生TypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat、

1
キーワード引数の複数の値の問題は、stackoverflow.com
a / 58586450/5214998で

91

この問題はまだkeras gitで発生しています。それができるだけ早く解決されることを願っています。それまでは、numpyバージョンを1.16.2にダウングレードしてみてください。問題は解決したようです。

!pip install numpy==1.16.1
import numpy as np

このバージョンのnumpyのデフォルト値はallow_pickleas Trueです。


4
numpyバージョンをダウングレードするのではなく、MappaGnosisのソリューションを使用します。私にとって、バージョンダンスをいじくりまわすのは最後の手段です。
エリック

2
1.16.4にも問題があります
ケンサイ

@kensaiに感謝します。これがnumpy 1.17で解決されたかどうか誰かが知っていますか?
nsheff

numpy 1.18ではまだこの問題が存在しています。私はnumpy 1.16.1に切り替える必要があり、それは今解決しました。ありがとうございました。
BC Smith

55

GitHubでこの問題が発生した後の正式な解決策は、imdb.pyファイルを編集することです。この修正は、numpyをダウングレードする必要なく、私にとってはうまくいきました。imdb.pyファイルをtensorflow/python/keras/datasets/imdb.py(私のフルパスは:C:\Anaconda\Lib\site-packages\tensorflow\python\keras\datasets\imdb.py-他のインストールは異なるでしょう)で見つけ、85行目を差分に従って変更します。

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

変更の理由は、ピクル化されたファイルでのSQLインジェクションに相当するPythonを防ぐためのセキュリティです。上記の変更はimdbデータにのみ影響するため、他の場所でセキュリティを保持します(numpyをダウングレードしないことにより)。


1
先ほど言ったように、私はColabを使用していますが、imdb.pyファイルを変更するにはどうすればよいですか?
カナド

IMDBは初めて参照するときにローカルにダウンロードされるため、これはColabの問題ではありません。したがって、コンピュータのどこかにローカルコピーが存在し(上記の推奨パスを試してください-または、Colabのディレクトリを設定する場合は、まずそこに試してください)、任意のIDEまたはテキストエディタでimdb.pyファイルを開くだけで、変更を加えます(Jupyterでの作業時にダウンロードされたimdb.pyファイルを編集するためにNotepad ++を使用しました-Colabに非常に似た環境です!)。
MappaGnosis、

私にとって有効なソリューションは> np.load(data_path、encoding = 'latin1'、allow_pickle = True)
ホルヘサントスニール

これは私が使用する解決策です。受け入れられた回答のように、バージョン(特にnumpy)をいじるのは避けたいものです。これは明示的に問題を修正するだけなので、よりpythonicです。(githubにあるKerasの最新バージョンにも実際にこの修正が組み込まれていることに注意してください)
eric

35

np.load()への引数としてallow_pickle = Trueを使用したところ、うまくいきました。


pickleを許可すると配列が変わることを観察しています。保存前とロード後の.npy配列は、np.array_equalを使用して等しいかどうかをアサートしようとすると例外が発生します
yasht

18

私の場合、以下で動作しました:

np.load(path, allow_pickle=True)

12

cheez(https://stackoverflow.com/users/122933/cheez)からの答えが最も簡単で効果的なものだと思います。セッション期間全体でnumpy関数を変更しないように、少し詳しく説明します。

私の提案は以下です。私はそれを使用して、同じ種類のエラーを示しているkerasからロイターデータセットをダウンロードしています。

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)

ここで何が起こっているのか詳しく説明できますか?
カナド

1
Kerasデータセットをロードできませんでした。私はインターネットを検索し、de imdb.pyファイルを編集する必要があるという解決策を見つけました。他の人はnumpyインストールの変更(ここなど)またはTensorflowを開発バージョンに変更することを指摘しました。私はcheezソリューションに出会いました。最も簡単で効果的な私見です。
Gustavo Mirapalheta

1
@Kanad-ラムダは匿名関数です。Gustavoはnp.loadに関数拡張を作成し、拡張バージョンを使用してから、デフォルト値に戻しました。
EngrStudent


4

上記の解決策のどれも私にとってうまくいきませんでした:私はpython 3.7.3でanacondaを実行します。私のために働いたのは

  • Anaconda powershellから「conda install numpy == 1.16.1」を実行します

  • ノートブックを閉じて再度開く


ありがとう、それが私が検索したものです。ちなみに、allow_pickle=Trueデフォルト値は1.16.2が最新バージョンのようです。
マテイRačinský

3

使用してjupyterノートに

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)

正常に動作しましたが、spyderでこのメソッドを使用すると問題が発生します(毎回カーネルを再起動する必要があります。そうしないと、次のようなエラーが発生します:

TypeError:()キーワード引数 'allow_pickle'に複数の値を取得しました

私はここの解決策を使用してこの問題を解決しました


3

私はここに上陸し、あなたの方法を試してみましたが、理解できませんでした。

私は実際に所定のコードに取り組んでいました

pickle.load(path)

使用したので交換しました

np.load(path, allow_pickle=True)

2

はい、以前のバージョンのnumpyをインストールすると問題が解決しました。

PyCharm IDEを使用する人のために:

私のIDE(Pycharm)で、File-> Settings-> Project Interpreter:numpyが1.16.3であることがわかったので、1.16.1に戻します。+をクリックして検索でnumpyと入力し、「バージョンを指定」にチェックマークを付けて、1.16.1を選択し、->パッケージをインストールします。


2

imdb.pyへのパスを見つけて、フラグをnp.load(path、... flag ...)に追加するだけです

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

1

私の仕事

        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
また、ソリューションが機能する理由を説明するコンテキストもあります。(レビューより)。
ZF007

1

私が見つけたのは、TensorFlow 2.0(私は2.0.0-alpha0を使用しています)がNumpyの最新バージョン、つまりv1.17.0(および場合によってはv1.16.5 +)と互換性がないことです。TF2がインポートされるとすぐに、次のようなFutureWarningの膨大なリストがスローされます。

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

これにより、kerasからimdbデータセットをロードしようとすると、allow_pickleエラーが発生しました。

うまく機能する次のソリューションを使用しようとしましたが、TF2またはtf.kerasをインポートするすべてのプロジェクトでそれを実行する必要がありました。

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

私が見つけた最も簡単な解決策は、numpy 1.16.1をグローバルにインストールするか、仮想環境で互換性のあるバージョンのtensorflowとnumpyを使用することでした。

この回答の私の目標は、それがimdb.load_dataの問題だけでなく、TF2とNumpyのバージョンの非互換性によって引き起こされるより大きな問題であり、他の多くの隠れたバグや問題を引き起こす可能性があることを指摘することです。


0

Tensorflowはtf-nightlyバージョンで修正されています。

!pip install tf-nightly

現在のバージョンは「2.0.0-dev20190511」です。


0

@cheez答えがうまくいかず、関数を何度も再帰的に呼び出す場合があります。この問題を解決するには、関数を深くコピーする必要があります。関数を使用してこれを行うことができるpartialため、最終的なコードは次のようになります。

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

私は通常これらのものに投稿しませんが、これは非常に迷惑でした。混乱は、いくつかのKeras imdb.pyファイルがすでに更新されているという事実から生じます:

with np.load(path) as f:

のバージョンにallow_pickle=True。imdb.pyファイルをチェックして、この変更がすでに実装されているかどうかを確認してください。調整されている場合、以下は正常に機能します。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.