2012-04-09 35 views
11

câu hỏi đầu tiên tại đây. Tôi sẽ cố gắng súc tích.Cách lưu các từ điển và mảng trong cùng một kho lưu trữ (với numpy.savez)

Tôi đang tạo nhiều mảng chứa thông tin tính năng cho ứng dụng học máy. Khi các mảng không có kích thước bằng nhau, tôi lưu trữ chúng trong một từ điển chứ không phải trong một mảng. Có hai loại tính năng khác nhau, vì vậy tôi đang sử dụng hai từ điển khác nhau.

Tôi cũng tạo nhãn để đi kèm với các tính năng. Các nhãn này được lưu trữ trong mảng. Ngoài ra, có các chuỗi chứa các tham số chính xác được sử dụng để chạy tập lệnh và dấu thời gian.

Tất cả trong tất cả nó trông như thế này:

import numpy as np  

feature1 = {} 
feature2 = {} 
label1 = np.array([]) 
label2 = np.array([]) 
docString = 'Commands passed to the script were...' 

# features look like this: 
feature1 = {'case 1': np.array([1, 2, 3, ...]), 
      'case 2': np.array([2, 1, 3, ...]), 
      'case 3': np.array([2, 3, 1, ...]), 
      and so on... } 

Bây giờ mục tiêu của tôi sẽ là để làm điều này:

np.savez(outputFile, 
     saveFeature1 = feature1, 
     saveFeature2 = feature2, 
     saveLabel1 = label1, 
     saveLabel2 = label2, 
     saveString = docString) 

này dường như làm việc (ví dụ như một tập tin được lưu với không có lỗi ném và có thể được tải lại). Tuy nhiên, khi tôi cố gắng tải ví dụ như tính năng từ tệp một lần nữa:

loadedArchive = np.load(outFile) 
loadedFeature1 = loadedArchive['saveFeature1'] 
loadedString = loadedArchive['saveString'] 

Sau đó thay vì nhận lại từ điển, tôi nhận được một mảng hình khối (0) mà tôi không biết cách truy cập các nội dung:

In []: loadedFeature1 
Out[]: 
     array({'case 1': array([1, 2, 3, ...]), 
       'case 2': array([2, 3, 1, ...]), 
       ..., }, dtype=object) 

Cũng chuỗi trở thành mảng và có được một datatype lạ:

In []: loadedString.dtype 
Out[]: dtype('|S20') 

Vì vậy, trong ngắn hạn, tôi giả định này không phải là cách nó được thực hiện một cách chính xác. Tuy nhiên tôi không muốn đặt tất cả các biến vào một từ điển lớn vì tôi sẽ lấy chúng trong một tiến trình khác và muốn lặp lại từ điển dictionary.keys() mà không phải lo lắng về so sánh chuỗi.

Bất kỳ ý tưởng nào được đánh giá cao. Cảm ơn

Trả lời

15

Như @fraxel đã đề xuất, sử dụng dưa chuột là một lựa chọn tốt hơn nhiều trong trường hợp này. Chỉ cần lưu dict cùng với các mục trong đó.

Tuy nhiên, hãy chắc chắn sử dụng dưa với giao thức nhị phân. Theo mặc định, định dạng kém hiệu quả hơn, điều này sẽ dẫn đến việc sử dụng bộ nhớ quá mức và các tệp lớn nếu mảng của bạn lớn.

saved_data = dict(outputFile, 
        saveFeature1 = feature1, 
        saveFeature2 = feature2, 
        saveLabel1 = label1, 
        saveLabel2 = label2, 
        saveString = docString) 

with open('test.dat', 'wb') as outfile: 
    pickle.dump(saved_data, outfile, protocol=pickle.HIGHEST_PROTOCOL) 

Điều đó đã được nói, chúng ta hãy xem điều gì đang diễn ra chi tiết hơn cho mục đích minh họa.

numpy.savez hy vọng mỗi mục là một mảng. Trên thực tế, nó gọi số np.asarray trên mọi thứ bạn vượt qua.

Nếu bạn biến một dict thành một mảng, bạn sẽ nhận được một mảng đối tượng. Ví dụ.

import numpy as np 

test = {'a':np.arange(10), 'b':np.arange(20)} 
testarr = np.asarray(test) 

Tương tự như vậy, nếu bạn thực hiện một mảng ra khỏi một chuỗi, bạn sẽ nhận được một mảng chuỗi:

In [1]: np.asarray('abc') 
Out[1]: 
array('abc', 
     dtype='|S3') 

Tuy nhiên, vì một điều không minh bạch trong cách các mảng đối tượng được xử lý, nếu bạn vượt qua trong một đối tượng duy nhất (trong trường hợp của bạn, dict) của bạn không phải là một tuple, danh sách hoặc mảng, bạn sẽ nhận được một mảng đối tượng 0 chiều.

Điều này có nghĩa là bạn không thể lập chỉ mục trực tiếp. Thực tế, việc thực hiện testarr[0] sẽ tăng số IndexError. Dữ liệu vẫn còn ở đó, nhưng trước tiên bạn cần phải thêm thứ nguyên, vì vậy bạn phải làm yourdictionary = testarr.reshape(-1)[0].

Nếu tất cả điều này có vẻ khó khăn, đó là vì nó là. Đối tượng mảng về cơ bản luôn luôn là câu trả lời sai. (Mặc dù asarray cho là cần vượt qua trong ndmin=1 để array, trong đó sẽ giải quyết vấn đề này cụ thể, nhưng có khả năng phá vỡ những thứ khác.)

savez được thiết kế để lưu trữ mảng, chứ không phải là đối tượng tùy ý. Vì cách hoạt động, nó có thể lưu trữ các đối tượng hoàn toàn tùy ý, nhưng không nên sử dụng theo cách đó.

Nếu bạn muốn sử dụng nó, tuy nhiên, một cách giải quyết nhanh chóng sẽ làm:

np.savez(outputFile, 
     saveFeature1 = [feature1], 
     saveFeature2 = [feature2], 
     saveLabel1 = [label1], 
     saveLabel2 = [label2], 
     saveString = docString) 

Và sau đó bạn muốn truy cập vào mọi thứ với

loadedArchive = np.load(outFile) 
loadedFeature1 = loadedArchive['saveFeature1'][0] 
loadedString = str(loadedArchive['saveString']) 

Tuy nhiên, điều này rõ ràng là nhiều khó khăn hơn là chỉ sử dụng dưa chua. Sử dụng numpy.savez khi bạn chỉ lưu mảng. Trong trường hợp này, bạn đang lưu cấu trúc dữ liệu lồng nhau, không phải mảng.

+0

tuyệt vời! cảm ơn bạn! – surchs

+2

Tôi thích truy cập vào phần tử trong mảng '()' bằng 'testarr.flat [0]'. Đối với người đọc tò mò, nó cũng có thể sử dụng một tuple trống như trong 'testarr [()]', nhưng điều này làm tổn thương khả năng đọc. –

0

Đặt tất cả các biến của bạn vào một đối tượng và sau đó sử dụng Pickle. Đó là cách tốt hơn để lưu trữ thông tin tiểu bang.

+0

Cảm ơn. Nhưng điều này không có nghĩa là, tôi sẽ phải sử dụng cùng một số biến số mỗi lần? Nếu, vì một lý do nào đó, tôi sẽ chỉ lưu một từ điển sau đó mọi tập lệnh tải tập tin này với dưa chua sẽ làm rối trật tự của các biến được lưu trữ. – surchs

+0

Pickle không hoạt động cho điều này trong 2.x; không hỗ trợ 64bit. – Will

10

Nếu bạn cần lưu dữ liệu của mình theo cách có cấu trúc, bạn nên cân nhắc sử dụng định dạng tệp HDF5 (http://www.hdfgroup.org/HDF5/). Nó rất linh hoạt, dễ sử dụng, hiệu quả và các phần mềm khác có thể đã hỗ trợ nó (HDFView, Mathematica, Matlab, Origin ..). Có một ràng buộc trăn đơn giản gọi là h5py.

Bạn có thể lưu trữ bộ dữ liệu trong hệ thống tệp như cấu trúc và xác định thuộc tính cho từng tập dữ liệu, như từ điển. Ví dụ:

import numpy as np 
import h5py 

# some data 
table1 = np.array([(1,1), (2,2), (3,3)], dtype=[('x', float), ('y', float)]) 
table2 = np.ones(shape=(3,3)) 

# save to data to file 
h5file = h5py.File("test.h5", "w") 
h5file.create_dataset("Table1", data=table1) 
h5file.create_dataset("Table2", data=table2, compression=True) 
# add attributes 
h5file["Table2"].attrs["attribute1"] = "some info" 
h5file["Table2"].attrs["attribute2"] = 42 
h5file.close() 

Đọc dữ liệu cũng rất đơn giản, thậm chí bạn có thể tải chỉ là một vài yếu tố ra khỏi một tập tin lớn nếu bạn muốn:

h5file = h5py.File("test.h5", "r") 
# read from file (numpy-like behavior) 
print h5file["Table1"]["x"][:2] 
# read everything into memory (real numpy array) 
print np.array(h5file["Table2"]) 
# read attributes 
print h5file["Table2"].attrs["attribute1"] 

Thêm nhiều tính năng và khả năng được tìm thấy trong tài liệu và trên các trang web (số Quick Start Guide có thể được quan tâm).

Các vấn đề liên quan