2010-09-28 19 views
11

Tôi đang chạy Python 2.6.5 trên Mac OS X 10.6.4 (đây không phải là phiên bản gốc, tôi đã tự cài đặt) với Scipy 0.8.0. Nếu tôi làm như sau:Một số người có thể giải thích hành vi kỳ lạ này của sự phân bố hypergeometric trong scipy?

>>> from scipy.stats import hypergeom 
>>> hypergeom.sf(5,10,2,5) 

Tôi nhận được IndexError. Sau đó, tôi làm:

>>> hypergeom.sf(2,10,2,2) 
-4.44.... 

Tôi nghi ngờ giá trị âm là do độ chính xác của dấu phẩy động xấu. Sau đó, tôi làm lại cái đầu tiên:

>>> hypergeom.sf(5,10,2,5) 
0.0 

Bây giờ nó hoạt động! Ai đó có thể giải thích điều này? Bạn có thấy hành vi này không?

+2

Nó cũng làm như vậy trên Python 2.6.6 trên Debian. – eumiro

+2

Đối với bất cứ điều gì nó có giá trị, điều này nghe có vẻ như nó có thể là một lỗi, và do đó có thể được yêu cầu tốt hơn trên danh sách người dùng scipy: http://mail.scipy.org/mailman/listinfo/scipy-user Nó có nhiều khả năng để có được sự chú ý của các nhà phát triển ở đó ... –

+5

Tôi đã mở một vé cho việc này: http://projects.scipy.org/scipy/ticket/1291. Như Joe Kington đã đề cập, sẽ hữu ích khi báo cáo lỗi hoặc hành vi bất ngờ đến danh sách gửi thư hoặc trình theo dõi lỗi của gói. – user333700

Trả lời

3

Vấn đề có vẻ phát sinh nếu cuộc gọi đầu tiên đến hàm sinh tồn nằm trong phạm vi rõ ràng là bằng không (xem nhận xét của tôi về câu trả lời trước). Ví dụ, đối với các cuộc gọi đến hypergeom.sf (x, M, n, N) nó sẽ thất bại nếu lệnh gọi hàm hypergeometric đầu tiên đến hàm là một tình huống trong đó x> n, trong đó hàm sống sẽ luôn bằng không.

Bạn trivially có thể sửa lỗi này tạm thời bởi:

def new_hypergeom_sf(k, *args, **kwds): 
    from scipy.stats import hypergeom 
    (M, n, N) = args[0:3] 
    try: 
     return hypergeom.sf(k, *args, **kwds) 
    except Exception as inst: 
     if k >= n and type(inst) == IndexError: 
      return 0 ## or conversely 1 - hypergeom.cdf(k, *args, **kwds) 
     else: 
      raise inst 

Bây giờ nếu bạn không có vấn đề chỉnh sửa /usr/share/pyshared/scipy/stats/distributions.py (hoặc tập tin tương đương), sửa chữa có khả năng trên đường dây 3966 nơi ngay bây giờ nó đọc:

place(output,cond,self._sf(*goodargs)) 
    if output.ndim == 0: 
     return output[()] 
    return output 

Nhưng nếu bạn thay đổi nó thành:

if output.ndim == 0: 
     return output[()] 
    place(output,cond,self._sf(*goodargs)) 
    if output.ndim == 0: 
     return output[()] 
    return output 

Nó bây giờ hoạt động mà không có IndexError. Về cơ bản, nếu đầu ra là không chiều bởi vì nó không kiểm tra, nó cố gắng gọi địa điểm, không thành công và không tạo ra phân phối. (Điều này không xảy ra nếu một phân phối trước đó đã được tạo ra có khả năng là lý do tại sao điều này không bị bắt gặp trong các bài kiểm tra trước đó.) Lưu ý rằng địa điểm (được định nghĩa trong function_base.py của numpy) sẽ thay đổi các phần tử của mảng (mặc dù tôi không chắc chắn nếu nó thay đổi kích thước) vì vậy nó có thể là tốt nhất để vẫn có nó để lại 0 dim kiểm tra sau khi diễn ra quá. Tôi đã không kiểm tra đầy đủ điều này để xem sự thay đổi này có phá vỡ bất kỳ thứ gì khác không (và nó áp dụng cho tất cả các bản phân phối biến ngẫu nhiên rời rạc), vì vậy nó có thể là tốt nhất để sửa lỗi đầu tiên.

Nó phá vỡ nó; ví dụ: stats.hypergeom.sf (1,10,2,5) trả về 0 (thay vì 2/9).

sửa chữa Điều này dường như làm việc tốt hơn nhiều, trong phần giống nhau:

class rv_discrete(rv_generic): 
... 
    def sf(self, k, *args, **kwds): 
    ... 
     if any(cond): 
      place(output,cond,self._sf(*goodargs)) 
     if output.ndim == 0: 
      return output[()] 
     return output 
1

Tôi không biết trăn, nhưng chức năng được định nghĩa như thế này: hypergeom.sf (x, M, n, N, loc = 0)

M là số các đối tượng thú vị, N là tổng số đối tượng và n là tần suất bạn "chọn một" (Xin lỗi, nhà thống kê Đức).

Nếu bạn đã có một bát với 20 quả bóng, 7 của những màu vàng (một màu vàng hấp dẫn), sau đó N là 20 và M là 7.

Có lẽ chức năng xử undefined cho (vô nghĩa) trường hợp khi M> N?

+0

Hàm được định nghĩa trong python được xác định rõ ràng cho các giá trị của M, n, N được sử dụng. Từ docstring trong python cho scipy.stats.hypergeom, M là tổng số đối tượng, n là số đối tượng kiểu 1, và N được vẽ mà không cần thay thế. Vì vậy, probs là hypergeom (x = 0,10,2,5) = 2/9, hypergeom (x = 1,10,2,5) = 5/9, hypergeom (x = 2,10,2,5) = 2/9; do đó hàm sống cho x <0 là 0, 7/9 cho 0 <= x <1, 2/9 cho 1 <= x <2 và 0 cho 2 <= x. Đối với sf (chức năng sống sót, được đọc dưới dạng 1-cdf, hàm phân phối lũy tích) của phân phối hypergeometric, chúng ta biết câu trả lời phải là 0. –

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