1. 程式人生 > >keras解決多標籤分類問題

keras解決多標籤分類問題

multi-class classification problem: 多分類問題是相對於二分類問題(典型的0-1分類)來說的,意思是類別總數超過兩個的分類問題,比如手寫數字識別mnist的label總數有10個,每一個樣本的標籤在這10箇中取一個。

multi-label classification problem:多標籤分類(或者叫多標記分類),是指一個樣本的標籤數量不止一個,即一個樣本對應多個標籤。

一般問題定義

一般情況下,假設我們的分類問題有5個標籤,樣本數量為n,數學表示為:

X={x1,x2,...,xn}Y={y1,y2,y3,y4,y5},yi{1,2,3,4,5}
我們用神經網路模型對樣本建模,計算P(cj|xi) :樣本xi 的標籤為cj的概率。模型的輸出為:
y^i=argmaxj{1,2,3,4,5}P(cj|xi)
現在我們用keras的Sequential 模型建立一個簡單的模型:
from keras.layers import Input,Dense
from keras.models import Sequential

model = Sequential()
model.add(Dense(10
, activation="relu", input_shape=(10,))) model.add(Dense(5))

multi-class classification

對於多分類問題,接下來要做的是輸出層的設計。在多分類中,最常用的就是softmax層。

softmax層中的softmax 函式是logistic函式在多分類問題上的推廣,它將一個N維的實數向量壓縮成一個滿足特定條件的N維實數向。壓縮後的向量滿足兩個條件:

  • 像兩種的每個元素的大小都在[0,1]
  • 所有向量元素的和為1

因此,softmax適用於多分類問題中對每一個類別的概率判斷,softmax計算公式:

Softmax(xi)=exiinexi
python 程式碼示例:
import numpy as np

def Softmax_sim(x):
    y = np.exp(x)
    return y/np.sum(y)

x = np.array([1.0,2.0,3.0,4.0,1.0])
print(Softmax_sim(x))
#輸出:[ 0.03106277  0.08443737  0.22952458  0.6239125   0.03106277]

假設隱藏層的輸出為[1.0,2.0,3.0,4.0,1.0],我們可以根據softmax函式判斷屬於標籤4

所以,利用keras的函式式定義多分類的模型:

from keras.layers import Input,Dense
from keras.models import Model

inputs = Input(shape=(10,))
hidden = Dense(units=10,activation='relu')(inputs)
output = Dense(units=5,activation='softmax')(hidden)

mulit-label classification

在預測多標籤分類問題時,假設隱藏層的輸出是[-1.0, 5.0, -0.5, 5.0, -0.5 ],如果用softmax函式的話,那麼輸出為:

z = np.array([-1.0, 5.0, -0.5, 5.0, -0.5 ])
print(Softmax_sim(z))
# 輸出為[ 0.00123281  0.49735104  0.00203256  0.49735104  0.00203256]

通過使用softmax,我們可以清楚地選擇標籤2和標籤4。但我們必須知道每個樣本需要多少個標籤,或者為概率選擇一個閾值。這顯然不是我們想要的,因為樣本屬於每個標籤的概率應該是獨立的。

對於一個二分類問題,常用的啟用函式是sigmoid函式:

σ(x)=11+ex
ps: sigmoid函式之所以在之前很長一段時間作為神經網路啟用函式(現在大家基本都用Relu了),一個很重要的原因是sigmoid函式的導數很容易計算,可以用自身表示:
σ(x)=σ(x)(1σ(x))
python 程式碼為:
import numpy as np

def Sigmoid_sim(x):
    return  1 /(1+np.exp(-x))

a = np.array([-1.0, 5.0, -0.5, 5.0, -0.5])
print(Sigmoid_sim(a))
#輸出為: [ 0.26894142  0.99330715  0.37754067  0.99330715  0.37754067]

此時,每個標籤的概率即是獨立的。完整整個模型構建之後,最後一步中最重要的是為模型的編譯選擇損失函式。在多標籤分類中,大多使用binary_crossentropy損失而不是通常在多類分類中使用的categorical_crossentropy損失函式。這可能看起來不合理,但因為每個輸出節點都是獨立的,選擇二元損失,並將網路輸出建模為每個標籤獨立的bernoulli分佈。整個多標籤分類的模型為:

from keras.models import Model
from keras.layers import Input,Dense

inputs = Input(shape=(10,))
hidden = Dense(units=10,activation='relu')(inputs)
output = Dense(units=5,activation='sigmoid')(hidden)
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

參考