【调参07】不平衡分类问题中分类权重计算与设置
文章目錄
- 前言
- 1. 類(lèi)別權(quán)重如何計(jì)算
- 2. tensorflow.keras.model.fit API 配置
- 3. 實(shí)現(xiàn)方法
- 3.1 數(shù)據(jù)集介紹
- 3.2 代碼實(shí)現(xiàn)
- 3.3 完整代碼
- 相關(guān)API 官方文檔
代碼環(huán)境:
- python-3.7.6
- tensorflow-2.1.0
前言
最近幾個(gè)月一直在做時(shí)間序列分類(lèi)相關(guān)的工作,在實(shí)際應(yīng)用工作中,調(diào)整模型參數(shù)對(duì)模型的性能表現(xiàn)的影響比較大。通過(guò)設(shè)置分類(lèi)權(quán)重平衡原來(lái)數(shù)據(jù)集中樣本分布不均衡的情況,同時(shí)配合Adam優(yōu)化算法和BatchNormalization,準(zhǔn)確率有比較大的提升。
本文重點(diǎn)介紹【時(shí)間序列分類(lèi)任務(wù)】中【不平衡分類(lèi)】問(wèn)題,如何配置 tensorflow.keras.model.fit() API 中的 class_weight 參數(shù),以平衡分類(lèi)。其實(shí)在時(shí)間序列分類(lèi)任務(wù)中,也可以通過(guò)插值的方式擴(kuò)充數(shù)據(jù)樣本,使各類(lèi)樣本數(shù)量相同,來(lái)平衡各類(lèi)別。
不平衡分類(lèi)是個(gè)比較大的問(wèn)題,以后再寫(xiě)吧。本文先介紹如何在時(shí)間序列分類(lèi)任務(wù)中的應(yīng)用。
1. 類(lèi)別權(quán)重如何計(jì)算
一開(kāi)始看到分類(lèi)平衡中的分類(lèi)權(quán)重參數(shù)(tensorflow.keras.model.fit中的參數(shù)為 class_weight)的計(jì)算時(shí)比較懵,不知道如何計(jì)算的,大部分文章基本都沒(méi)有提及計(jì)算過(guò)程,不適合我這樣的小白。于是,動(dòng)手算了算,發(fā)現(xiàn)其實(shí)很簡(jiǎn)單。
class_weight 參數(shù)需要傳入一個(gè)各類(lèi)別權(quán)重字典,通過(guò)分類(lèi)數(shù)量計(jì)算得到,其的意義是模型對(duì)各類(lèi)別的關(guān)注程度。 注意與 sample_weight 區(qū)分。
如果要平衡分類(lèi),一種簡(jiǎn)單的方式是通過(guò)設(shè)置該參數(shù),讓模型重點(diǎn)關(guān)注樣本數(shù)目較少的類(lèi)別,即乘以不同的權(quán)重,達(dá)到類(lèi)似各類(lèi)樣本數(shù)目都相同的目的。
計(jì)算的方式有很多種,舉個(gè)例子說(shuō)明如何計(jì)算分類(lèi)權(quán)重。
假設(shè)有A,B,C,D四類(lèi)樣本,各類(lèi)樣本數(shù)量如下:
分類(lèi):A B C D total 數(shù)量:10 20 30 40 100 比例:1/10 2/10 3/10 4/10 10/10假設(shè)平衡后模型對(duì)各類(lèi)別的關(guān)注度相同,即每類(lèi)樣本應(yīng)該受到相同的關(guān)注,取個(gè)名字,稱(chēng)它為平均關(guān)注度吧(隨便起的,方便表示)即 :
平均關(guān)注度=1分類(lèi)數(shù)=14(本例中)平均關(guān)注度=\frac{1}{分類(lèi)數(shù)} =\frac{1}{4}(本例中)平均關(guān)注度=分類(lèi)數(shù)1?=41?(本例中)
那么,每類(lèi)樣本的比例乘以各自的權(quán)重,應(yīng)該等于平均關(guān)注度。easy!則有:
某類(lèi)樣本的權(quán)重?樣本所占數(shù)據(jù)集比例=平均關(guān)注度某類(lèi)樣本的權(quán)重 * 樣本所占數(shù)據(jù)集比例 = 平均關(guān)注度某類(lèi)樣本的權(quán)重?樣本所占數(shù)據(jù)集比例=平均關(guān)注度
如此可以求出某類(lèi)樣本平衡后應(yīng)該乘以的權(quán)重:
某類(lèi)樣本的權(quán)重=平均關(guān)注度樣本所占數(shù)據(jù)集比例=1分類(lèi)數(shù)?樣本總數(shù)某類(lèi)樣本數(shù)量某類(lèi)樣本的權(quán)重 = \frac{平均關(guān)注度}{樣本所占數(shù)據(jù)集比例}=\frac{1}{分類(lèi)數(shù)}*\frac{樣本總數(shù)}{某類(lèi)樣本數(shù)量}某類(lèi)樣本的權(quán)重=樣本所占數(shù)據(jù)集比例平均關(guān)注度?=分類(lèi)數(shù)1??某類(lèi)樣本數(shù)量樣本總數(shù)?
簡(jiǎn)單的推導(dǎo)。。。想明白轉(zhuǎn)化關(guān)系其實(shí)很簡(jiǎn)單。清楚了計(jì)算公式,下面講一下如何實(shí)現(xiàn)。
2. tensorflow.keras.model.fit API 配置
fit(x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None,...class_weight=None,sample_weight=None, ... )關(guān)鍵參數(shù)說(shuō)明:
- class_weight:可選參數(shù)。樣本標(biāo)簽(整型,已經(jīng)編碼)到權(quán)重值(float類(lèi)型)的映射,用來(lái)加權(quán)損失函數(shù)(僅在訓(xùn)練期間加權(quán))。這可以有效地告訴模型需要更關(guān)注哪些樣本。
- sample_weight:可選參數(shù)。訓(xùn)練樣本權(quán)重?cái)?shù)組,用來(lái)加權(quán)損失函數(shù)(僅在訓(xùn)練期間加權(quán))。
本文僅介紹如何配置 class_weight 參數(shù)。
3. 實(shí)現(xiàn)方法
3.1 數(shù)據(jù)集介紹
本文使用的數(shù)據(jù)集是在個(gè)人創(chuàng)建的適合業(yè)務(wù)場(chǎng)景的數(shù)據(jù)集。包含十個(gè)類(lèi)別,以7:3劃分訓(xùn)練集和驗(yàn)證集。訓(xùn)練集中各樣本數(shù)量如下:
類(lèi)別 數(shù)量 1 582 2 580 3 1688 4 1152 5 580 6 580 7 2470 8 571 9 534 10 578 total 9315在本文的數(shù)據(jù)集中,原數(shù)據(jù)存儲(chǔ)在csv文件中,各類(lèi)標(biāo)簽已經(jīng)編碼為單個(gè)整型數(shù)字。
首先,以 pandas.DataFrame 格式讀取,滑動(dòng)窗口切分完成后,提取各樣本已經(jīng)編碼的標(biāo)簽。其實(shí)直接從原始數(shù)據(jù)集(還未使用滑動(dòng)窗口)提取標(biāo)簽計(jì)算是一樣的,相差不會(huì)太多,無(wú)非是滑動(dòng)窗口可能丟棄了不完整的數(shù)據(jù),實(shí)際影響不大,這也是設(shè)置分類(lèi)權(quán)重而不設(shè)置樣本權(quán)重的好處,一勞永逸~。如果在滑動(dòng)窗口處理數(shù)據(jù)的過(guò)程中,標(biāo)簽已經(jīng)轉(zhuǎn)換成 one-hot 編碼,使用 np.argmax(trainy,axis=1) 轉(zhuǎn)換成單個(gè)整型數(shù)字編碼即可。
下面看一下代碼實(shí)現(xiàn)。
3.2 代碼實(shí)現(xiàn)
有了以上準(zhǔn)備,現(xiàn)在應(yīng)該有:單個(gè)整型數(shù)字組成的標(biāo)簽序列。比如:
y_train -> array([6, 6, 6, ..., 3, 3, 3], dtype=int64) len(y_train) -> 9315現(xiàn)在進(jìn)一步處理:
這里說(shuō)明一下,跟np.unique() 輸出相同,np.unique() 是取出數(shù)組中的唯一元素,并返回包含這些元素的數(shù)組。le.transform() 標(biāo)準(zhǔn)化編碼,這一步是保證輸入數(shù)據(jù)是真標(biāo)簽的情況下,轉(zhuǎn)換為數(shù)字編碼。
3.3 完整代碼
如果訓(xùn)練標(biāo)簽已經(jīng)轉(zhuǎn)化為one-hot編碼:
y_train = np.argmax(trainy, axis=1)如果使用原始數(shù)據(jù)集處理:
y_train = train_loaded['state_encode'] # pd.series完整代碼:
from sklearn.preprocessing import LabelEncoder le = LabelEncoder()y_index = le.fit_transform(y_train.ravel()) recip_freq = len(y_train) / (len(classes) * np.bincount(y_index).astype(np.float64)) class_weight = recip_freq[le.transform(classes)] print("Class weights : ", class_weight)# 將訓(xùn)練標(biāo)簽變?yōu)閛ne-hot編碼;這里使用keras API 實(shí)現(xiàn),使用pd.get_dummies也可以。 y_train = tf.keras.utils.to_categorical(y_train, len(np.unique(y_train)))y_train:
array([[0., 0., 0., ..., 0., 0., 0.],[0., 0., 0., ..., 0., 0., 0.],[0., 0., 0., ..., 0., 0., 0.],...,[0., 0., 0., ..., 0., 0., 0.],[0., 0., 0., ..., 0., 0., 0.],[0., 0., 0., ..., 0., 0., 0.]], dtype=float32)相關(guān)API 官方文檔
- sklearn.preprocessing.LabelEncoder
- numpy.bincount
- numpy.ravel
- numpy.unique
- tensorflow.keras.model.fit()
- pandas.get_dummies
總結(jié)
以上是生活随笔為你收集整理的【调参07】不平衡分类问题中分类权重计算与设置的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 新年新气象,牛年更牛,开始新的征程
- 下一篇: s60按键处理模型