วิธีแก้ไข 'Object arrays ไม่สามารถโหลดได้เมื่อ allow_pickle = False' สำหรับฟังก์ชัน imdb.load_data ()


114

ฉันพยายามที่จะดำเนินการเช่นการจัดหมวดหมู่ไบนารีโดยใช้ชุดข้อมูลที่ไอเอ็มในGoogle Colab ฉันเคยใช้โมเดลนี้มาก่อน แต่เมื่อฉันพยายามทำอีกครั้งหลังจากผ่านไปสองสามวันมันกลับมีข้อผิดพลาดค่า: 'Object arrays ไม่สามารถโหลดได้เมื่อ allow_pickle = False' สำหรับฟังก์ชัน load_data ()

ฉันได้ลองแก้ปัญหานี้แล้วโดยอ้างถึงคำตอบที่มีอยู่สำหรับปัญหาที่คล้ายกัน: วิธีแก้ไข 'Object arrays ไม่สามารถโหลดได้เมื่อ allow_pickle = False' ในอัลกอริทึม sketch_rnn แต่ปรากฎว่าการเพิ่มอาร์กิวเมนต์ 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
ข้อผิดพลาดนี้หมายความว่าอย่างไร
Charlie Parker

3
@CharlieParker เห็นได้ชัดว่ามีการเพิ่มพารามิเตอร์ในฟังก์ชัน numpy.load () ก่อนหน้าnp.load(path)นี้ตอนนี้เป็นnp.load(path, boolean)ค่าเริ่มต้นบูลีน (allow_pickle) เป็นเท็จ
Kanad

ขอบคุณ! แต่นั่นหมายความว่าตอนนี้นัมปี้ดองของให้ฉันโดยไม่ได้รับอนุญาตเมื่อทำการบันทึก?! แปลก! ฉันดูnp.savezเอกสาร แต่ไม่มีการอ้างอิงถึงการดองดังนั้นฉันจึงไม่รู้ว่ามันรู้ได้อย่างไรตั้งแต่แรกว่าสิ่งที่ฉันประหยัดนั้นเป็นของ Pytorch และไม่เพียง แต่น่าเบื่อ ... แปลก! ถ้าคุณรู้ว่าจะมีอะไรมาแบ่งปันกับเรา :)
Charlie Parker

ความเชื่อของฉันหลังจากพบปัญหาเดียวกันก็คือทั้งหมดขึ้นอยู่กับสิ่งที่คุณบันทึกลงใน. npz หากคุณกำลังบันทึกประเภทบิวท์อินก็ไม่มีการดอง อย่างไรก็ตามหากคุณเขียนออบเจ็กต์ python / numpy จะทำให้มันดอง (เช่นทำให้เป็นอนุกรม) สิ่งนี้ฉันคิดว่าเป็นการเปิดความเสี่ยงด้านความปลอดภัยดังนั้น numpy เวอร์ชันที่ใหม่กว่าจึงหยุดปล่อยให้เป็นค่าเริ่มต้น ...
Robert Lugg

คำตอบ:


124

ต่อไปนี้เป็นเคล็ดลับในการบังคับ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 เป็น np" ในตอนต้น Numpy อาจนำเข้าโดยใช้ชื่ออื่นหรือไม่นำเข้าเลย ...
Kristóf

มันช่วยฉันได้มาก
staticor

7
รับข้อผิดพลาดTypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat

1
ปัญหาของหลายค่าสำหรับอาร์กิวเมนต์คำหลักได้รับการแก้ไขแล้วในstackoverflow.com/a/58586450/5214998
Sajad

91

ปัญหานี้ยังคงขึ้นอยู่กับ keras git ฉันหวังว่ามันจะได้รับการแก้ไขโดยเร็วที่สุด ในระหว่างนี้ให้ลองปรับลดรุ่นของคุณเป็น 1.16.2 ดูเหมือนว่าจะแก้ปัญหาได้

!pip install numpy==1.16.1
import numpy as np

รุ่นของ numpy นี้มีค่าเริ่มต้นของการเป็นallow_pickleTrue


4
ฉันจะใช้วิธีแก้ปัญหาจาก MappaGnosis แทนการดาวน์เกรดเวอร์ชัน numpy: สำหรับฉันแล้วการเต้นเวอร์ชั่นเป็นทางเลือกสุดท้าย!
eric

2
1.16.4 มีปัญหาเช่นกัน
kensai

ขอบคุณ @kensai. ไม่มีใครรู้ว่าสิ่งนี้ได้รับการแก้ไขในจำนวน 1.17 หรือไม่
nsheff

ในจำนวน 1.18 ยังคงมีปัญหานี้อยู่ ฉันต้องเปลี่ยนเป็น numpy 1.16.1 และแก้ไขได้แล้ว ขอบคุณ.
BC Smith

55

หลังจากปัญหานี้ใน GitHub วิธีแก้ปัญหาอย่างเป็นทางการคือการแก้ไขไฟล์ imdb.py การแก้ไขนี้ทำงานได้ดีสำหรับฉันโดยไม่จำเป็นต้องดาวน์เกรดจำนวนนับ ค้นหาไฟล์ 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:

เหตุผลของการเปลี่ยนแปลงคือความปลอดภัยเพื่อป้องกันไม่ให้ Python เทียบเท่ากับการแทรก SQL ในไฟล์ดอง การเปลี่ยนแปลงข้างต้นจะมีผลกับข้อมูล imdb เท่านั้นดังนั้นคุณจึงยังคงรักษาความปลอดภัยไว้ที่อื่น (โดยไม่ดาวน์เกรดจำนวนนับ)


1
อย่างที่บอกว่าฉันใช้ Colab ฉันจะทำการเปลี่ยนแปลงในไฟล์ imdb.py ได้อย่างไร
Kanad

นี่ไม่ใช่ปัญหา Colab เนื่องจาก IMDB ถูกดาวน์โหลดภายในครั้งแรกที่คุณอ้างอิง ดังนั้นจะมีสำเนาในเครื่องอยู่ที่ไหนสักแห่งในคอมพิวเตอร์ของคุณ (ลองใช้เส้นทางที่แนะนำด้านบน - หรือหากคุณตั้งค่าไดเรกทอรีสำหรับ Colab ให้ลองที่นั่นก่อน) และเพียงเปิดไฟล์ imdb.py ใน IDE ใด ๆ หรือแม้แต่โปรแกรมแก้ไขข้อความเพื่อ ทำการเปลี่ยนแปลง (ฉันใช้ Notepad ++ เพื่อแก้ไขไฟล์ imdb.py ซึ่งดาวน์โหลดเมื่อทำงานใน Jupyter - ดังนั้นสภาพแวดล้อมที่คล้ายกันมากกับ Colab!)
MappaGnosis

วิธีแก้ปัญหาที่เหมาะกับฉันคือ> np.load (data_path, encoding = 'latin1', allow_pickle = True)
Jorge Santos Neill

นี่เป็นวิธีแก้ปัญหาที่ฉันใช้ในขณะที่ยุ่งกับเวอร์ชัน (โดยเฉพาะอย่างยิ่งของ numpy) เช่นเดียวกับในคำตอบที่ยอมรับเป็นสิ่งที่ฉันพยายามหลีกเลี่ยง นอกจากนี้ยังมี pythonic มากขึ้นเนื่องจากเป็นการแก้ไขปัญหาอย่างชัดเจน (โปรดทราบว่า Keras เวอร์ชันใหม่ล่าสุดที่ github รวมการแก้ไขนี้ไว้แล้ว)
eric

35

ฉันเพิ่งใช้ allow_pickle = True เป็นอาร์กิวเมนต์สำหรับ np.load () และมันก็ใช้ได้สำหรับฉัน


ฉันสังเกตว่าการอนุญาตให้ดองเปลี่ยนอาร์เรย์ อาร์เรย์. npy ก่อนบันทึกและหลังการโหลดจะมีข้อยกเว้นเมื่อพยายามยืนยันความเท่าเทียมโดยใช้ np.array_equal
yasht


12

ฉันคิดว่าคำตอบจาก cheez ( https://stackoverflow.com/users/122933/cheez ) เป็นคำตอบที่ง่ายและมีประสิทธิภาพมากที่สุด ฉันจะอธิบายเพิ่มเติมเล็กน้อยเพื่อที่จะไม่แก้ไขฟังก์ชัน numpy ตลอดช่วงเซสชันทั้งหมด

คำแนะนำของฉันอยู่ด้านล่าง ฉันใช้มันเพื่อดาวน์โหลดชุดข้อมูล reuters จาก 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)

คุณช่วยอธิบายเพิ่มเติมเกี่ยวกับสิ่งที่เกิดขึ้นที่นี่ได้ไหม
Kanad

1
ฉันไม่สามารถโหลดชุดข้อมูล Keras ได้ ฉันค้นหาอินเทอร์เน็ตและพบวิธีแก้ปัญหาที่บอกว่าฉันควรแก้ไขไฟล์ de imdb.py คนอื่น ๆ ชี้ให้เห็นถึงการเปลี่ยนแปลงในการติดตั้ง numpy (เช่นที่นี่) หรือเปลี่ยน Tensorflow เป็นเวอร์ชันระหว่างการพัฒนา ฉันเจอโซลูชัน Cheez IMHO เป็นวิธีที่ง่ายและมีประสิทธิภาพมากที่สุด
Gustavo Mirapalheta

1
@Kanad - lambda เป็นฟังก์ชันที่ไม่ระบุตัวตน Gustavo สร้างฟังก์ชันเพิ่มให้กับ np.load โดยใช้เวอร์ชันเสริมจากนั้นตั้งค่ากลับเป็นค่าเริ่มต้น
EngrStudent

9

คุณสามารถลองเปลี่ยนค่าของแฟล็ก

np.load(training_image_names_array,allow_pickle=True)

เยี่ยมมาก มันใช้งานได้ นี่ควรเป็นคำตอบที่ได้รับการยอมรับ
Biranchi

4

วิธีแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉัน: ฉันใช้งาน anaconda ด้วย python 3.7.3 สิ่งที่ได้ผลสำหรับฉันคือ

  • เรียกใช้ "conda install numpy == 1.16.1" จาก Anaconda powershell

  • ปิดและเปิดโน้ตบุ๊กอีกครั้ง


ขอบคุณนั่นคือสิ่งที่ฉันค้นหา อย่างไรก็ตามดูเหมือนว่า 1.16.2 จะเป็นเวอร์ชันใหม่ล่าสุดซึ่งallow_pickle=Trueเป็นค่าเริ่มต้น
MatějRač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'.

นอกจากนี้ยังส่งผลให้เกิดข้อผิดพลาด allow_pickle เมื่อพยายามโหลดชุดข้อมูล imdb จาก keras

ฉันพยายามใช้โซลูชันต่อไปนี้ซึ่งใช้งานได้ดี แต่ฉันต้องทำทุกโครงการที่ฉันนำเข้า 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

ฉันมักจะไม่โพสต์สิ่งเหล่านี้ แต่มันน่ารำคาญมาก ความสับสนมาจากข้อเท็จจริงที่ว่าimdb.pyไฟล์Keras บางไฟล์ได้อัปเดตแล้ว:

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)

0

วิธีที่ง่ายที่สุดคือเปลี่ยนimdb.pyการตั้งค่าallow_pickle=Trueไปnp.loadที่เส้นที่แสดงimdb.pyข้อผิดพลาด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.