UndefinedMetricWarning: Điểm F không được xác định rõ và được đặt thành 0,0 trong các nhãn không có mẫu dự đoán


78

Tôi gặp lỗi kỳ lạ này:

classification.py:1113: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 in labels with no predicted samples.
'precision', 'predicted', average, warn_for)`

nhưng sau đó nó cũng in điểm f trong lần đầu tiên tôi chạy:

metrics.f1_score(y_test, y_pred, average='weighted')

Lần thứ hai tôi chạy, nó cung cấp điểm số mà không có lỗi. Tại sao vậy?

>>> y_pred = test.predict(X_test)
>>> y_test
array([ 1, 10, 35,  9,  7, 29, 26,  3,  8, 23, 39, 11, 20,  2,  5, 23, 28,
       30, 32, 18,  5, 34,  4, 25, 12, 24, 13, 21, 38, 19, 33, 33, 16, 20,
       18, 27, 39, 20, 37, 17, 31, 29, 36,  7,  6, 24, 37, 22, 30,  0, 22,
       11, 35, 30, 31, 14, 32, 21, 34, 38,  5, 11, 10,  6,  1, 14, 12, 36,
       25,  8, 30,  3, 12,  7,  4, 10, 15, 12, 34, 25, 26, 29, 14, 37, 23,
       12, 19, 19,  3,  2, 31, 30, 11,  2, 24, 19, 27, 22, 13,  6, 18, 20,
        6, 34, 33,  2, 37, 17, 30, 24,  2, 36,  9, 36, 19, 33, 35,  0,  4,
        1])
>>> y_pred
array([ 1, 10, 35,  7,  7, 29, 26,  3,  8, 23, 39, 11, 20,  4,  5, 23, 28,
       30, 32, 18,  5, 39,  4, 25,  0, 24, 13, 21, 38, 19, 33, 33, 16, 20,
       18, 27, 39, 20, 37, 17, 31, 29, 36,  7,  6, 24, 37, 22, 30,  0, 22,
       11, 35, 30, 31, 14, 32, 21, 34, 38,  5, 11, 10,  6,  1, 14, 30, 36,
       25,  8, 30,  3, 12,  7,  4, 10, 15, 12,  4, 22, 26, 29, 14, 37, 23,
       12, 19, 19,  3, 25, 31, 30, 11, 25, 24, 19, 27, 22, 13,  6, 18, 20,
        6, 39, 33,  9, 37, 17, 30, 24,  9, 36, 39, 36, 19, 33, 35,  0,  4,
        1])
>>> metrics.f1_score(y_test, y_pred, average='weighted')
C:\Users\Michael\Miniconda3\envs\snowflakes\lib\site-packages\sklearn\metrics\classification.py:1113: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 in labels with no predicted samples.
  'precision', 'predicted', average, warn_for)
0.87282051282051276
>>> metrics.f1_score(y_test, y_pred, average='weighted')
0.87282051282051276
>>> metrics.f1_score(y_test, y_pred, average='weighted')
0.87282051282051276

Ngoài ra, tại sao có 'precision', 'predicted', average, warn_for)thông báo lỗi theo sau ? Không có dấu ngoặc mở, vậy tại sao nó lại kết thúc bằng dấu ngoặc đóng? Tôi đang chạy sklearn 0.18.1 bằng Python 3.6.0 trong môi trường chung cư trên Windows 10.

Tôi cũng đã xem ở đây và tôi không biết có phải cùng một lỗi hay không. Bài SO này cũng không có giải pháp.


9
Có một số nhãn trong y_true, không xuất hiện trong y_pred và do đó nó không được xác định rõ ràng
Vivek Kumar

3
@VivekKumar Tôi cũng nhận được cảnh báo tương tự. Tôi có tập dữ liệu cân bằng (500 + 500) và cảnh báo này dường như xuất hiện trong clf = GridSearchCV(SVC(C=2), tuned_parameters, cv=cv, scoring='f1') clf.fit(X_train, y_train)giai đoạn này. Sẽ thật tuyệt khi xem điều gì đang gây ra cảnh báo hoặc cách khắc phục nó.
salvu

Câu trả lời:


111

Như đã đề cập trong các nhận xét, một số nhãn trong y_true không xuất hiện trong y_pred. Cụ thể trong trường hợp này, nhãn '2' không bao giờ được dự đoán:

>>> set(y_test) - set(y_pred)
{2}

Điều này có nghĩa là không có điểm F để tính cho nhãn này, và do đó điểm F cho trường hợp này được coi là 0,0. Vì bạn yêu cầu điểm trung bình, bạn phải tính đến điểm 0 đã được đưa vào phép tính và đây là lý do tại sao scikit-learning hiển thị cho bạn cảnh báo đó.

Điều này đưa tôi đến việc bạn không gặp lỗi lần thứ hai. Như tôi đã đề cập, đây là một cảnh báo , được xử lý khác với lỗi trong python. Hành vi mặc định trong hầu hết các môi trường là chỉ hiển thị cảnh báo cụ thể một lần. Hành vi này có thể được thay đổi:

import warnings
warnings.filterwarnings('always')  # "error", "ignore", "always", "default", "module" or "once"

Nếu bạn đặt điều này trước khi nhập các mô-đun khác, bạn sẽ thấy cảnh báo mỗi khi chạy mã.

Không có cách nào để tránh nhìn thấy cảnh báo này lần đầu tiên, ngoài việc thiết lập warnings.filterwarnings('ignore'). Những gì bạn có thể làm, là quyết định rằng bạn không quan tâm đến điểm số của nhãn mà không được dự đoán, và sau đó xác định rõ ràng các nhãn bạn đang quan tâm (trong đó có nhãn đã được dự đoán ít nhất một lần):

>>> metrics.f1_score(y_test, y_pred, average='weighted', labels=np.unique(y_pred))
0.91076923076923078

Cảnh báo không được hiển thị trong trường hợp này.


2
Đây là một câu trả lời tuyệt vời nhưng tôi sẽ thận trọng không nên chọn tính điểm f1 bằng cách sử dụng unique(y_pred)vì điều này có thể dẫn đến điểm sai lệch.
Robert Sim,

@RobertSim, bạn có thể vui lòng giải thích một chút về điều này được không? Cảm ơn bạn.
Akash Kandpal

4
@ harrypotter0, tôi nghĩ ý của anh ấy là việc sử dụng unique(y_pred)như một phương pháp tiêu chuẩn, mà không hiểu bạn đang làm gì, có thể gây ra những hậu quả không mong muốn. Điều xảy ra ở đây là các nhãn không được dự đoán trước chỉ đơn giản là bị bỏ qua. Miễn là bạn chủ động quyết định rằng đó là điều bạn quan tâm, đó là ok. Khi sử dụng phương pháp này, cá nhân tôi sẽ luôn in ra các nhãn không được dự đoán (sử dụng các phép toán đặt ở đầu câu trả lời), để đảm bảo rằng tôi không bỏ lỡ thực tế đó.
Shovalt

Tôi đang đề cập đến câu hỏi này vì tôi đang gặp vấn đề tương tự. Trong trường hợp của tôi, khi tôi kiểm tra độ dài của y_testy_prednhững cái có cùng độ dài. Vậy làm sao nó có thể được xác định sai khi mọi nhãn thật đều có nhãn dự đoán?
akalanka

3
@akalanka, hãy thử sử dụng np.unique(y_pred)np.unique(y_test). Chúng có thể có độ dài khác nhau. Tất cả các y của bạn đều có nhãn được dự đoán, nhưng không phải tất cả các nhãn đều được dự đoán ít nhất một lần.
Shovalt

4

Theo câu trả lời của @ Shovalt, nhưng trong ngắn hạn:

Ngoài ra, bạn có thể sử dụng các dòng mã sau

    from sklearn.metrics import f1_score
    metrics.f1_score(y_test, y_pred, labels=np.unique(y_pred))

Điều này sẽ loại bỏ cảnh báo của bạn và cung cấp cho bạn kết quả bạn muốn, vì nó không còn xem xét sự khác biệt giữa các tập hợp, bằng cách sử dụng chế độ duy nhất.


4
Đây là một bản sao của câu trả lời của Shovalt.
normanius

3

Câu trả lời được chấp nhận đã giải thích rõ lý do tại sao cảnh báo xảy ra. Nếu bạn chỉ muốn kiểm soát các cảnh báo, người ta có thể sử dụng precision_recall_fscore_support. Nó đưa ra một đối số (bán chính thức) warn_forcó thể được sử dụng để tắt tiếng cảnh báo.

(_, _, f1, _) = metrics.precision_recall_fscore_support(y_test, y_pred,
                                                        average='weighted', 
                                                        warn_for=tuple())

Như đã đề cập trong một số nhận xét, hãy sử dụng nó một cách cẩn thận.


1
Không, tìm kiếm nguồn sklearn, tôi chỉ tìm thấy tùy chọn này cho precision_recall_fscore_support().
normanius

3

vấn đề tương tự cũng xảy ra với tôi khi tôi đào tạo mô hình phân loại của mình. lý do gây ra vấn đề này là như những gì thông báo cảnh báo cho biết "trong nhãn không có mẫu dự đoán", nó sẽ gây ra phép chia 0 khi tính điểm f1. Tôi đã tìm thấy một giải pháp khác khi tôi đọc tài liệu sklearn.metrics.f1_score , có một lưu ý như sau:

Khi true positive + false positive == 0, độ chính xác là không xác định; Khi true dương tính + false âm tính == 0, gọi lại là không xác định. Trong những trường hợp như vậy, theo mặc định, số liệu sẽ được đặt thành 0, cũng như điểm f và UndefinedMetricWarning sẽ được tăng lên. Hành vi này có thể được sửa đổi với zero_division

các zero_divisiongiá trị mặc định là "warn", bạn có thể đặt nó vào 0hoặc 1để tránh UndefinedMetricWarning. nó hoạt động với tôi;) ồ chờ đã, có một vấn đề khác khi tôi sử dụng zero_division, báo cáo sklearn của tôi rằng không có đối số từ khóa nào như vậy bằng cách sử dụng scikit-learning 0.21.3. Chỉ cần cập nhật sklearn của bạn lên phiên bản mới nhất bằng cách chạypip install scikit-learn -U


1

Như tôi đã nhận thấy lỗi này xảy ra trong hai trường hợp,

  1. Nếu bạn đã sử dụng train_test_split () để chia nhỏ dữ liệu của mình, bạn phải đảm bảo rằng bạn đặt lại chỉ mục của dữ liệu (đặc biệt khi được thực hiện bằng đối tượng chuỗi gấu trúc): y_train, chỉ số y_test phải được đặt lại. Vấn đề là khi bạn cố gắng sử dụng một trong những điểm số từ sklearn.metrics như; precision_score, điều này sẽ cố gắng khớp với các chỉ số xáo trộn của y_test mà bạn nhận được từ train_test_split ().

vì vậy hãy sử dụng np.array (y_test) cho y_true về điểm số hoặc y_test.reset_index (drop = True)

  1. Sau đó, một lần nữa, bạn vẫn có thể gặp lỗi này nếu 'Số khẳng định đúng' được dự đoán là 0, được sử dụng cho độ chính xác, thu hồi và f1_scores. Bạn có thể hình dung điều này bằng cách sử dụng một sự cố_matrix. Nếu phân loại là đa nhãn và bạn đặt param: average = 'weighted' / micro / macro, bạn sẽ nhận được câu trả lời miễn là đường chéo trong ma trận không phải là 0

Hi vọng điêu nay co ich.


-1

Như thông báo lỗi nêu rõ, phương pháp được sử dụng để lấy điểm F là từ phần "Phân loại" của sklearn - do đó nói về "nhãn".

Bạn có một vấn đề hồi quy? Sklearn cung cấp phương pháp "điểm F" để hồi quy trong nhóm "lựa chọn tính năng": http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.f_regression.html

Trong trường hợp bạn gặp vấn đề về phân loại, câu trả lời của @ Shovalt có vẻ đúng với tôi.


Bạn đúng khi chỉ ra sự khác biệt giữa hồi quy và phân loại, nhưng tôi kết luận rằng đây là một vấn đề phân loại từ bản chất rời rạc của y_testy_predtrong câu hỏi.
Shovalt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.