शिकवा-सीखें में क्लास_वेट पैरामीटर कैसे काम करता है?


115

मुझे यह समझने में बहुत परेशानी हो रही है कि class_weightscitit-learn के लॉजिस्टिक रिग्रेशन में पैरामीटर कैसे संचालित होता है।

स्थिति

मैं बहुत असंतुलित डेटा सेट पर द्विआधारी वर्गीकरण करने के लिए लॉजिस्टिक प्रतिगमन का उपयोग करना चाहता हूं। वर्गों को 0 (ऋणात्मक) और 1 (पॉजिटिव) लेबल किया जाता है और मनाया गया डेटा लगभग 19: 1 के अनुपात में होता है, जिसमें अधिकांश नमूने नकारात्मक परिणाम वाले होते हैं।

पहला प्रयास: मैन्युअल रूप से प्रशिक्षण डेटा तैयार करना

मैंने प्रशिक्षण और परीक्षण (लगभग 80/20) के लिए मेरे पास मौजूद डेटा को विभाजित कर दिया था। फिर मैंने 19: 1 की तुलना में अलग-अलग अनुपात में प्रशिक्षण डेटा प्राप्त करने के लिए हाथ से प्रशिक्षण डेटा को बेतरतीब ढंग से नमूना लिया; 2: 1 -> 16: 1 से।

मैंने तब इन विभिन्न प्रशिक्षण डेटा उप-समूहों पर लॉजिस्टिक प्रतिगमन को प्रशिक्षित किया और विभिन्न प्रशिक्षण अनुपातों के एक फ़ंक्शन के रूप में (= टीपी / (टीपी + एफएन)) को वापस बुलाया। बेशक, रिकॉल की गणना असंतुष्ट टेस्ट नमूनों पर की गई थी, जिसमें 19: 1 का अनुपात देखा गया था। ध्यान दें, हालांकि मैंने अलग-अलग प्रशिक्षण डेटा पर विभिन्न मॉडलों को प्रशिक्षित किया है, फिर भी मैंने उन सभी के लिए एक ही (असंतुष्ट) परीक्षण डेटा पर रिकॉल किया।

परिणाम उम्मीद के मुताबिक थे: रीकॉल 2: 1 प्रशिक्षण अनुपात के बारे में 60% था और जब तक यह 16, 1 तक पहुंच गया, तब तक तेजी से गिर गया। कई अनुपात 2: 1 -> 6: 1 थे, जहां रिकॉल 5% से अधिक था।

दूसरा प्रयास: ग्रिड खोज

अगला, मैं विभिन्न नियमितीकरण मापदंडों का परीक्षण करना चाहता था और इसलिए मैंने ग्रिडसर्च सीवी का उपयोग किया और Cपैरामीटर के साथ-साथ पैरामीटर के कई मूल्यों का ग्रिड बनाया class_weight। मेरे n: m के अनुपात का नकारात्मक अनुवाद करने के लिए: सकारात्मक प्रशिक्षण के नमूने में class_weightमैंने सोचा था कि मैं इस प्रकार कई शब्दकोश निर्दिष्ट करता हूं:

{ 0:0.67, 1:0.33 } #expected 2:1
{ 0:0.75, 1:0.25 } #expected 3:1
{ 0:0.8, 1:0.2 }   #expected 4:1

और मैं भी शामिल किए गए Noneऔर auto

इस बार परिणाम पूरी तरह से निराकृत थे। मेरे सभी रिकॉल छोटे (<0.05) को class_weightछोड़कर हर मूल्य के लिए आए auto। इसलिए मैं केवल यह मान सकता हूं कि class_weightशब्दकोश को सेट करने के बारे में मेरी समझ गलत है। दिलचस्प है, class_weightग्रिड खोज में 'ऑटो' का मूल्य सभी मूल्यों के लिए लगभग 59% था C, और मैंने अनुमान लगाया कि यह 1 से 1 तक संतुलित है?

मेरे सवाल

  1. class_weightआप वास्तव में इसे क्या देते हैं, उससे प्रशिक्षण डेटा में विभिन्न संतुलन हासिल करने के लिए आप कैसे ठीक से उपयोग करते हैं ? विशेष रूप से, class_weightनकारात्मक: सकारात्मक प्रशिक्षण नमूनों के n: m अनुपात का उपयोग करने के लिए मैं किस शब्दकोश से गुजरता हूं ?

  2. यदि आप class_weightGridSearchCV के लिए विभिन्न शब्दकोशों को पास करते हैं , तो क्रॉस-वैलिडेशन के दौरान यह शब्दकोश के अनुसार प्रशिक्षण गुना डेटा को फिर से संतुलित करेगा, लेकिन परीक्षण तह पर मेरे स्कोरिंग फ़ंक्शन की गणना के लिए सही दिए गए नमूना अनुपात का उपयोग करें? यह महत्वपूर्ण है क्योंकि किसी भी मीट्रिक मेरे लिए केवल तभी उपयोगी है जब यह देखे गए अनुपात में डेटा से आता है।

  3. जहाँ तक आनुपातिकता है, उसका क्या autoमूल्य है class_weight? मैंने दस्तावेज़ीकरण पढ़ा और मुझे लगता है "डेटा को उनकी आवृत्ति के विपरीत आनुपातिक संतुलित करता है" बस इसका मतलब है कि यह 1: 1 बनाता है। क्या ये सही है? यदि नहीं, तो क्या कोई स्पष्ट कर सकता है?


जब कोई क्लास_वेट का उपयोग करता है, तो नुकसान फ़ंक्शन संशोधित हो जाता है। उदाहरण के लिए, क्रॉस एन्ट्रापी के बजाय, यह वीज़्ड क्रॉस एंट्रोपी बन जाता है। towardsdatascience.com/...
प्रशांत

जवाबों:


123

सबसे पहले, यह सिर्फ अकेले याद करके जाना अच्छा नहीं हो सकता है। आप बस सकारात्मक वर्ग के रूप में सब कुछ वर्गीकृत करके 100% की याद को प्राप्त कर सकते हैं। मैं आमतौर पर मापदंडों का चयन करने के लिए एयूसी का उपयोग करने का सुझाव देता हूं, और फिर ऑपरेटिंग बिंदु (किसी दिए गए सटीक स्तर कहते हैं) के लिए दहलीज ढूंढता हूं जिसमें आप रुचि रखते हैं।

के लिए कैसे class_weightकाम करता है: यह के नमूने में गलतियों penalizes class[i]साथ class_weight[i]बजाय 1. उच्च वर्ग वजन साधन तो तुम एक वर्ग पर अधिक जोर डाल करना चाहते हैं। आप जो कहते हैं उससे यह लगता है कि कक्षा 1 कक्षा की तुलना में 19 गुना अधिक है। इसलिए आपको class_weightकक्षा 0 के सापेक्ष कक्षा 1 की संख्या बढ़ानी चाहिए , {0: .1, 1: .9}। यदि class_weight1 का योग नहीं है, तो यह मूल रूप से नियमितीकरण पैरामीटर को बदल देगा।

कैसे class_weight="auto"काम करता है, आप इस चर्चा पर एक नज़र डाल सकते हैं । देव संस्करण में आप उपयोग कर सकते हैं class_weight="balanced", जो समझना आसान है: मूल रूप से इसका मतलब है कि छोटे वर्ग की नकल करना जब तक कि आपके पास बड़े एक के रूप में कई नमूने नहीं हैं, लेकिन एक अंतर्निहित तरीके से।


1
धन्यवाद! त्वरित प्रश्न: मैंने स्पष्टता के लिए रिकॉल का उल्लेख किया है और वास्तव में मैं यह तय करने की कोशिश कर रहा हूं कि मेरे उपाय के रूप में किस एयूसी का उपयोग करना है। मेरी समझ यह है कि मुझे पैरामीटर खोजने के लिए रिको बनाम सटीक वक्र के तहत आरओसी वक्र या क्षेत्र के तहत अधिकतम क्षेत्र होना चाहिए। इस तरह से मापदंडों को चुनने के बाद, मेरा मानना ​​है कि मैं वक्र के साथ फिसलने से वर्गीकरण के लिए सीमा का चयन करता हूं। क्या यही आपका मतलब है? यदि हां, तो दो में से कौन सा वक्र सबसे अधिक समझ में आता है कि क्या मेरा लक्ष्य कई टीपी के रूप में संभव है? इसके अलावा, अपने काम के लिए धन्यवाद और शिक्षा-योगदान के लिए धन्यवाद !!!
किग्रागेट्राउट

1
मुझे लगता है कि आरओसी का उपयोग करना अधिक मानक तरीका होगा, लेकिन मुझे नहीं लगता कि इसमें कोई बड़ा अंतर होगा। हालांकि, वक्र पर बिंदु को चुनने के लिए आपको कुछ मानदंड की आवश्यकता होती है।
एंड्रियास म्यूलर

3
@MiNdFrEaK मुझे लगता है कि एंड्रयू का अर्थ क्या है कि अनुमानक अल्पसंख्यक वर्ग में नमूनों की नकल करता है, ताकि विभिन्न वर्गों के नमूने संतुलित हों। यह सिर्फ एक अंतर्निहित तरीके से निरीक्षण कर रहा है।
शॉन तियान

8
@MiNdFrEaK और Shawn Tian: SV- आधारित क्लासिफायर 'संतुलित' का उपयोग करते समय छोटे वर्गों के अधिक नमूनों का उत्पादन नहीं करते हैं। यह वस्तुतः छोटी कक्षाओं पर की गई गलतियों को दंडित करता है। अन्यथा कहना एक भूल है और भ्रामक है, विशेष रूप से बड़े डेटासेट में जब आप अधिक नमूने नहीं बना सकते। यह उत्तर संपादित करना होगा।
पाब्लो रिवास

4
scikit-learn.org/dev/glossary.html#term-class-weight क्लास वज़न को एल्गोरिथम के आधार पर अलग-अलग तरीके से इस्तेमाल किया जाएगा: रैखिक मॉडल (जैसे रैखिक एसवीएम या लॉजिस्टिक रिग्रेशन) के लिए, क्लास वेट से नुकसान फ़ंक्शन को बदल देगा। प्रत्येक नमूना के नुकसान को उसके वर्ग के वजन से घटाकर। ट्री-आधारित एल्गोरिदम के लिए, विभाजन मानदंड को फिर से तैयार करने के लिए वर्ग वजन का उपयोग किया जाएगा। हालांकि ध्यान दें कि यह पुनर्संतुलन प्रत्येक वर्ग में नमूनों के वजन को ध्यान में नहीं रखता है।
प्रशस्त

2

पहला जवाब यह समझने के लिए अच्छा है कि यह कैसे काम करता है। लेकिन मैं यह समझना चाहता था कि मुझे अभ्यास में इसका उपयोग कैसे करना चाहिए।

सारांश

  • शोर के बिना मामूली असंतुलित डेटा के लिए, क्लास वेट लगाने में बहुत अंतर नहीं है
  • शोर के साथ मध्यम रूप से असंतुलित डेटा और दृढ़ता से असंतुलित होने के लिए, वर्ग भार लागू करना बेहतर है
  • class_weight="balanced"आप मैन्युअल रूप से अनुकूलन करने के लिए चाहते हैं की अनुपस्थिति में परम अच्छा काम करता है
  • आपके साथ class_weight="balanced"और अधिक सच्ची घटनाओं को कैप्चर किया जाता है (उच्च TRUE रिकॉल) लेकिन साथ ही आपको झूठी अलर्ट (कम TRUE परिशुद्धता) प्राप्त होने की अधिक संभावना है
    • परिणामस्वरूप, सभी झूठी सकारात्मकता के कारण कुल% TRUE वास्तविक से अधिक हो सकता है
    • यदि गलत अलार्म एक मुद्दा है तो एयूसी आपको यहां गुमराह कर सकता है
  • असंतुलन% के लिए निर्णय की सीमा को बदलने की आवश्यकता नहीं है, यहां तक ​​कि मजबूत असंतुलन के लिए, ठीक रखने के लिए 0.5 (या कहीं और जो आपके लिए आवश्यक है, उसके आधार पर)

एनबी

RF या GBM का उपयोग करते समय परिणाम भिन्न हो सकता है। sklearn में class_weight="balanced" GBM नहीं है , लेकिन lightgbm हैLGBMClassifier(is_unbalance=False)

कोड

# scikit-learn==0.21.3
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, classification_report
import numpy as np
import pandas as pd

# case: moderate imbalance
X, y = datasets.make_classification(n_samples=50*15, n_features=5, n_informative=2, n_redundant=0, random_state=1, weights=[0.8]) #,flip_y=0.1,class_sep=0.5)
np.mean(y) # 0.2

LogisticRegression(C=1e9).fit(X,y).predict(X).mean() # 0.184
(LogisticRegression(C=1e9).fit(X,y).predict_proba(X)[:,1]>0.5).mean() # 0.184 => same as first
LogisticRegression(C=1e9,class_weight={0:0.5,1:0.5}).fit(X,y).predict(X).mean() # 0.184 => same as first
LogisticRegression(C=1e9,class_weight={0:2,1:8}).fit(X,y).predict(X).mean() # 0.296 => seems to make things worse?
LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict(X).mean() # 0.292 => seems to make things worse?

roc_auc_score(y,LogisticRegression(C=1e9).fit(X,y).predict(X)) # 0.83
roc_auc_score(y,LogisticRegression(C=1e9,class_weight={0:2,1:8}).fit(X,y).predict(X)) # 0.86 => about the same
roc_auc_score(y,LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict(X)) # 0.86 => about the same

# case: strong imbalance
X, y = datasets.make_classification(n_samples=50*15, n_features=5, n_informative=2, n_redundant=0, random_state=1, weights=[0.95])
np.mean(y) # 0.06

LogisticRegression(C=1e9).fit(X,y).predict(X).mean() # 0.02
(LogisticRegression(C=1e9).fit(X,y).predict_proba(X)[:,1]>0.5).mean() # 0.02 => same as first
LogisticRegression(C=1e9,class_weight={0:0.5,1:0.5}).fit(X,y).predict(X).mean() # 0.02 => same as first
LogisticRegression(C=1e9,class_weight={0:1,1:20}).fit(X,y).predict(X).mean() # 0.25 => huh??
LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict(X).mean() # 0.22 => huh??
(LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict_proba(X)[:,1]>0.5).mean() # same as last

roc_auc_score(y,LogisticRegression(C=1e9).fit(X,y).predict(X)) # 0.64
roc_auc_score(y,LogisticRegression(C=1e9,class_weight={0:1,1:20}).fit(X,y).predict(X)) # 0.84 => much better
roc_auc_score(y,LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict(X)) # 0.85 => similar to manual
roc_auc_score(y,(LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict_proba(X)[:,1]>0.5).astype(int)) # same as last

print(classification_report(y,LogisticRegression(C=1e9).fit(X,y).predict(X)))
pd.crosstab(y,LogisticRegression(C=1e9).fit(X,y).predict(X),margins=True)
pd.crosstab(y,LogisticRegression(C=1e9).fit(X,y).predict(X),margins=True,normalize='index') # few prediced TRUE with only 28% TRUE recall and 86% TRUE precision so 6%*28%~=2%

print(classification_report(y,LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict(X)))
pd.crosstab(y,LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict(X),margins=True)
pd.crosstab(y,LogisticRegression(C=1e9,class_weight="balanced").fit(X,y).predict(X),margins=True,normalize='index') # 88% TRUE recall but also lot of false positives with only 23% TRUE precision, making total predicted % TRUE > actual % TRUE
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.