導(dǎo)讀
當(dāng)你只有幾個正樣本的時候,如何分類未標注的數(shù)據(jù)假設(shè)您有一個支付事務(wù)數(shù)據(jù)集。其中一些交易被標記為欺詐,其余的被標記為真實交易,你需要設(shè)計一個模型來區(qū)分欺詐交易和真實交易。假設(shè)你有足夠的數(shù)據(jù)和良好的特征,這似乎是一個簡單的分類任務(wù)。但是,假設(shè)只有15%的數(shù)據(jù)有標注,并且標注的樣本只屬于一個類,因此你的訓(xùn)練集由15%標記為真實的樣本組成,而其余的沒有標記,可能是真實的,也可能是虛假的。你如何對它們進行分類?這樣的需求是否只是將這個任務(wù)變成了一個無監(jiān)督的學(xué)習(xí)問題?好吧,不一定。 這個問題 —— 通常被稱為PU(正樣本的和未標記的樣本)的分類問題 —— 應(yīng)該首先從兩個相似且常見的“標注問題”中區(qū)分出來,這兩個問題使許多分類任務(wù)復(fù)雜化。第一個也是最常見的標簽問題是“小訓(xùn)練集”的問題。當(dāng)你有相當(dāng)數(shù)量的數(shù)據(jù),但只有一小部分被標記時,它就會出現(xiàn)。這個問題有許多種類和相當(dāng)多的具體訓(xùn)練方法。另一個常見的標記問題(通常與PU問題合并在一起)涉及的情況是,我們的訓(xùn)練數(shù)據(jù)集全都有標記,但它只包含一個類。例如,假設(shè)我們只有一個非欺詐事務(wù)的數(shù)據(jù)集,并且我們需要使用這個數(shù)據(jù)集來訓(xùn)練一個模型來區(qū)分(類似的)非欺詐事務(wù)和欺詐事務(wù)。這也是一個常見的問題,通常被視為無監(jiān)督的離群點檢測問題,盡管在ML領(lǐng)域中也有相當(dāng)多的工具是專門設(shè)計來處理這些場景的(OneClassSVM可能是最著名的)。 相比之下,PU分類問題涉及到一個訓(xùn)練集,其中只有部分數(shù)據(jù)被標記為正,而其余數(shù)據(jù)未被標記,可能是正的,也可能是負的。例如,假設(shè)你的雇主是一家銀行,它可以為你提供大量的事務(wù)性數(shù)據(jù),但只能確認其中的一部分是100%真實的。我在這里使用的例子涉及到關(guān)于偽鈔的類似場景。它包括了1200張紙幣的數(shù)據(jù)集,其中大部分沒有標記,只有一部分被確認為真實的。雖然PU問題也很常見,但是與前面提到的兩個分類問題相比,它們的討論要少得多,而且很少有實踐的例子或庫可以廣泛使用。 本文的目的是提供一種可能的方法來解決PU問題,我最近在一個分類項目中使用了這種方法。它是基于Charles Elkan和Keith Noto寫的論文“Learning classifiers from only positive and unlabeled data”(2008),以及由Alexandre Drouin寫的一些代碼。盡管在文章中有更多的PU學(xué)習(xí)方法(我打算在以后的文章中討論另一種相當(dāng)流行的方法),Elkan和Noto的(E&N)方法非常簡單,可以很容易地在Python中實現(xiàn)。 一點點理論(請原諒)E&N本質(zhì)上聲稱,給定一個數(shù)據(jù)集,我們有正的和未標記的數(shù)據(jù),某個樣本標記為正的概率是 [ P(y=1|x)] 的概率等于樣本被標記的概率 [P(s=1|x)] 除以我們的數(shù)據(jù)集中正樣本被標記的概率[P(s=1|y=1)]。 如果這個斷言是正確的,那么實現(xiàn)起來就相對容易了。這是因為雖然我們沒有足夠的數(shù)據(jù)來訓(xùn)練分類器來告訴我們樣本是正的還是負的,在PU場景中我們確實有足夠的標簽數(shù)據(jù)告訴我們正樣本是否可能被標記,根據(jù)E&N,這足以估計有多可能是正的。 更正式地說,給定一個未標記的數(shù)據(jù)集,其中只有一組標記為正的樣本,如果我們估計P(s=1|x) / P(s=1|y=1),我們就可以估計未標記的樣本x為正的概率。幸運的是,我們幾乎可以使用任何基于sklearn的分類器,按照以下步驟來估計: (1)在包含已標記和未標記數(shù)據(jù)的數(shù)據(jù)集上擬合一個分類器,同時使用isLabeled作為目標y。以這種方式擬合分類器,訓(xùn)練它預(yù)測給定樣本x被標記的概率P(s=1|x)。 (2)使用分類器預(yù)測數(shù)據(jù)集中已知正樣本被標記的概率,預(yù)測結(jié)果可以表示為正樣本被標記的概率 P(s=1|y=1|x),計算這些預(yù)測概率的平均值,這就是我們的P(s=1|y=1)。有了P(s=1|y=1)的估計值,為了預(yù)測數(shù)據(jù)點k為正的概率,根據(jù)E&N,我們需要做的就是估計P(s=1|k)或它被標記的概率,這正是我們訓(xùn)練的分類器(1)知道如何做的。 (3)使用我們在(1)上訓(xùn)練的分類器來估計k被標記或P(s=1|k)的概率。 (4)一旦我們估算出P(s=1|k),我們就可以將這個概率除以P(s=1|y=1) ,這是在步驟(2)上估算出來的,這樣就可以得到它屬于這兩類的實際概率。 我們現(xiàn)在寫代碼并進行測試以上步驟1-4可按如下方式實施: # prepare datax_data = the training sety_data = target var (1 for the positives and not-1 for the rest)# fit the classifier and estimate P(s=1|y=1)classifier, ps1y1 = fit_PU_estimator(x_data, y_data, 0.2, Estimator())# estimate the prob that x_data is labeled P(s=1|X)predicted_s = classifier.predict_proba(x_data)# estimate the actual probabilities that X is positive# by calculating P(s=1|X) / P(s=1|y=1)predicted_y = estimated_s / ps1y1讓我們從這里開始:fit_PU_estimator()方法。 fit_PU_estimator()方法完成了兩個主要任務(wù):它擬合一個分類器,你選擇一個具有正樣本和未標記樣本的訓(xùn)練集,然后估計一個正樣本被標記的概率。相應(yīng)地,它返回擬合的分類器(學(xué)會估計給定樣本被標記的概率)和估計的概率P(s=1|y=1)。之后,我們需要做的就是找到P(s=1|x)或者標記為x的概率。因為這就是我們訓(xùn)練的分類器要做的,我們只需要調(diào)用它的predict_proba()方法。最后,為了實際對樣本x進行分類,我們只需要將結(jié)果除以我們已經(jīng)找到的P(s=1|y=1)。這可以用代碼表示為: 實現(xiàn)fit_PU_estimator()方法本身非常簡單: def fit_PU_estimator(X,y, hold_out_ratio, estimator): # The training set will be divided into a fitting-set that will be used # to fit the estimator in order to estimate P(s=1|X) and a held-out set of positive samples # that will be used to estimate P(s=1|y=1) # -------- # find the indices of the positive/labeled elements assert (type(y) == np.ndarray), 'Must pass np.ndarray rather than list as y' positives = np.where(y == 1.)[0] # hold_out_size = the *number* of positives/labeled samples # that we will use later to estimate P(s=1|y=1) hold_out_size = int(np.ceil(len(positives) * hold_out_ratio)) np.random.shuffle(positives) # hold_out = the *indices* of the positive elements # that we will later use to estimate P(s=1|y=1) hold_out = positives[:hold_out_size] # the actual positive *elements* that we will keep aside X_hold_out = X[hold_out] # remove the held out elements from X and y X = np.delete(X, hold_out,0) y = np.delete(y, hold_out) # We fit the estimator on the unlabeled samples + (part of the) positive and labeled ones. # In order to estimate P(s=1|X) or what is the probablity that an element is *labeled* estimator.fit(X, y) # We then use the estimator for prediction of the positive held-out set # in order to estimate P(s=1|y=1) hold_out_predictions = estimator.predict_proba(X_hold_out) #take the probability that it is 1 hold_out_predictions = hold_out_predictions[:,1] # save the mean probability c = np.mean(hold_out_predictions) return estimator, cdef predict_PU_prob(X, estimator, prob_s1y1): prob_pred = estimator.predict_proba(X) prob_pred = prob_pred[:,1] return prob_pred / prob_s1y1為了測試這一點,我使用了[Bank Note Authentication dataset]( 一些重點。首先,這種方法的性能在很大程度上取決于數(shù)據(jù)集的大小。在本例中,我使用了大約150個正樣本和1200個未標記樣本。這遠不是這種方法的理想數(shù)據(jù)集。例如,如果我們只有100個樣本,我們的分類器就會表現(xiàn)得很差。其次,正如所附的notebook所示,有一些變量需要調(diào)優(yōu)(例如要設(shè)置的樣本大小、用于分類的概率閾值等),但最重要的可能是所選的分類器及其參數(shù)。我選擇使用XGBoost是因為它在具有很少特征的小型數(shù)據(jù)集上執(zhí)行得相對較好,但需要注意的是,它并不是在所有場景中都執(zhí)行得最好,測試正確的分類器非常重要。 代碼在這里: 英文原文: |
|
|
來自: taotao_2016 > 《AI》