2013-09-16 36 views
7

Tôi đang viết mã Python để tạo ra và âm mưu chức năng 'siêu Gauss', như:AttributeError trong python/NumPy khi xây dựng chức năng cho các giá trị nhất định

def supergaussian(x, A, mu, sigma, offset, N=8): 
    """Supergaussian function, amplitude A, centroid mu, st dev sigma, exponent N, with constant offset""" 
    return A * (1/(2**(1+1/N)*sigma*2*scipy.special.gamma(1+1/N))) * numpy.exp(-numpy.absolute(numpy.power(x-mu,N))/(2*sigma**N)) + offset 

init_x = numpy.arange(-100,100,1.0) 
init_y = supergaussian(init_x, 1, 0, 25, 0, N=12) 

mã sau chỉ làm cho một âm mưu của nó. Đối với một lý do tôi không thể hiểu được, mã này hoạt động tốt khi sử dụng giá trị mặc định là 8 cho N, hoặc cho các giá trị của N lên đến 13. Khi N là 14 hoặc cao hơn, chức năng treo với một thông báo lỗi:

AttributeError: 'float' object has no attribute 'exp' 

Tại dòng trả về trong định nghĩa hàm. Ý tưởng nào? Vì điều duy nhất trong dòng đó sử dụng .exp là numpy.exp thông báo lỗi dường như ngụ ý rằng numpy đang được hiểu là phao, nhưng chỉ cho các giá trị lớn của N ...

Tôi đang chạy python 3.3. 2 với numpy 1.7.1 và scipy 0.12.0

Trả lời

14

Lỗi là do một số kỳ quặc dtype ntyty. Tôi không chắc chắn chính xác như thế nào nó hoạt động trong nội bộ, nhưng vì một lý do 2*25**14 gây nên một sự thay đổi trong cách NumPy xử lý các kiểu dữ liệu:

>>> type(np.max(-numpy.absolute(numpy.power(init_x-0,13)))/(2*25**13)) 
<type 'numpy.float64'> 
>>> type(np.max(-numpy.absolute(numpy.power(init_x-0,14)))/(2*25**14)) 
<type 'float'> 

Với 13, nó vẫn sử dụng loại float64 NumPy, nhưng với 14 nó bằng cách nào đó quay ngược lại thường xuyên nổi. Đây là lý do tại sao bạn nhận được AttributeError: một float Python bình thường không có phương thức exp, đó là một phương thức ufunc numpy. (Lỗi này không phải do tên numpy được hiểu là phao. Đôi khi các lỗi nội bộ này không hữu ích ở chỗ chúng không cho bạn biết đối tượng là gì không có thuộc tính.)

Tuy nhiên , điều này chỉ xảy ra bởi vì số 2*25**N là một Python dài thường xuyên, không phải là giá trị của một kiểu dữ liệu có khối u. Bạn có thể sửa chữa nó bằng cách bao bọc trước giá trị đó trong một kiểu dumppe numpy, như thế này:

def supergaussian(x, A, mu, sigma, offset, N=8): 
    """Supergaussian function, amplitude A, centroid mu, st dev sigma, exponent N, with constant offset""" 
    denom = np.float64(2*sigma**N) 
    return A * (1/(2**(1+1/N)*sigma*2*scipy.special.gamma(1+1/N))) * numpy.exp(-numpy.absolute(numpy.power(x-mu,N))/denom) + offset 

Bây giờ nó hoạt động tốt cho các giá trị lớn.

Lỗi chuyển đổi có vẻ là do thực tế là 2*25**14 quá lớn để vừa với một int64 gọn gàng. Điều này trông giống như một lỗi cho tôi: nếu nó quá lớn cho int64, nó sẽ rơi trở lại float64 hoặc tăng một lỗi, không âm thầm rơi trở lại đồng bằng float. Có vẻ như có lỗi liên quan trên numpy tracker, nhưng trông hơi khác một chút. Bạn có thể muốn nêu vấn đề trên trình theo dõi và/hoặc danh sách gửi thư.

+0

Cảm ơn, đây chính là điều đang xảy ra. Tôi sẽ gửi đến bộ theo dõi. –

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