Logistic Regression(邏輯迴歸)模型實現二分類和多分類

原文鏈接:https://blog.csdn.net/u011734144/article/details/79717470

一、邏輯迴歸

二、判定邊界

當將訓練集的樣本以其各個特徵爲座標軸在圖中進行繪製時,通常可以找到某一個 判定邊界 去將樣本點進行分類。例如:

線性判定邊界:

 


這裏寫圖片描述

 

非線性判定邊界:

 


這裏寫圖片描述

 

三、二分類和sigmoid函數


 

sigmoid函數圖像如下:

 

這裏寫圖片描述

 

四、損失函數

1. 定義

2. 極大似然估計

上面是一種求損失函數的方式,我們也可以換一種方式來求損失函數,即極大似然估計。用極大似然估計來作爲損失函數

3. 正則化

五、最小化損失函數

這裏寫圖片描述

同樣,上式中的a爲學習率(下山步長)。將上式的偏導展開,可得:

非正則化的損失函數的偏導:

這裏寫圖片描述

含正則化項的損失函數的偏導:

這裏寫圖片描述

其中 λ 爲正則化的強度。

同線性迴歸般,可以通過學習率a對特徵係數向量中的元素不斷進行迭代,直到元素值收斂到某一值即可,這時可以得到損失函數較小時的特徵向量係數Θ。

六、從二分類過渡到多分類

在上面,我們主要使用邏輯迴歸解決二分類的問題,那對於多分類的問題,也可以用邏輯迴歸來解決?

1. one vs rest

由於概率函數 hΘ(X) 所表示的是樣本標記爲某一類型的概率,但可以將一對一(二分類)擴展爲一對多(one vs rest):

  1. 將類型class1看作正樣本,其他類型全部看作負樣本,然後我們就可以得到樣本標記類型爲該類型的概率p1;

  2. 然後再將另外類型class2看作正樣本,其他類型全部看作負樣本,同理得到p2;

  3. 以此循環,我們可以得到該待預測樣本的標記類型分別爲類型class i時的概率pi,最後我們取pi中最大的那個概率對應的樣本標記類型作爲我們的待預測樣本類型。

2. softmax函數

使用softmax函數構造模型解決多分類問題。

softmax迴歸分類器需要學習的函數爲 : (這裏下面的公式有問題,括號中的每一項應該都是以e爲底的

這裏寫圖片描述

其中 k 個 類別的個數 ,這裏寫圖片描述 和 這裏寫圖片描述 爲 第 i 個 類別對應的 權重向量 和 偏移標量。

其中 這裏寫圖片描述 可看作樣本 X 的標籤 爲 第 j 個 類別的概率,且有 這裏寫圖片描述 。

與 logistic迴歸 不同的是,softmax迴歸分類模型會有多個的輸出,且輸出個數 與 類別個數 相等,輸出爲樣本 X 爲各個類別的概率 ,最後對樣本進行預測的類型爲 概率最高 的那個類別。

我們需要通過學習得到 這裏寫圖片描述 和 這裏寫圖片描述 ,因此建立目標損失函數爲:

這裏寫圖片描述

上式的代價函數也稱作:對數似然代價函數。

在二分類的情況下,對數似然代價函數 可以轉化爲 交叉熵代價函數。

其中 m 爲訓練集樣本的個數,k 爲 類別的個數,這裏寫圖片描述 爲示性函數,當 這裏寫圖片描述 爲真時,函數值爲 1 ,否則爲 0 ,即 樣本類別正確時,函數值才爲 1 。

這裏寫圖片描述

繼續展開:

這裏寫圖片描述

通過 梯度下降法 最小化損失函數 和 鏈式偏導,使用 這裏寫圖片描述 對 這裏寫圖片描述 求偏導:

這裏寫圖片描述

化簡可得:

這裏寫圖片描述

再次化簡可有:

這裏寫圖片描述

因此由 梯度下降法 進行迭代:

這裏寫圖片描述

同理 通過梯度下降法最小化損失函數也可以得到 這裏寫圖片描述 的最優值。

同邏輯迴歸一樣,可以給損失函數加上正則化項。

3. 選擇的方案

當標籤類別之間是互斥時,適合選擇softmax迴歸分類器 ;當標籤類別之間不完全互斥時,適合選擇建立多個獨立的logistic迴歸分類器。

4. tensorflow代碼示例:

  • 使用softmax迴歸對sklearn中的digit手寫數據進行分類
import tensorflow as tf

 
  1. from sklearn.datasets import load_digits

  2. import numpy as np


 
  1. digits = load_digits()

  2. X_data = digits.data.astype(np.float32)

  3. Y_data = digits.target.reshape(-1,1).astype(np.float32)

  4. print X_data.shape

  5. print Y_data.shape


 
  1. (1797, 64)

  2. (1797, 1)

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_data = scaler.fit_transform(X_data)
from sklearn.preprocessing import OneHotEncoder
Y = OneHotEncoder().fit_transform(Y_data).todense() #one-hot編碼
Y

 
  1. matrix([[ 1., 0., 0., ..., 0., 0., 0.],

  2. [ 0., 1., 0., ..., 0., 0., 0.],

  3. [ 0., 0., 1., ..., 0., 0., 0.],

  4. ...,

  5. [ 0., 0., 0., ..., 0., 1., 0.],

  6. [ 0., 0., 0., ..., 0., 0., 1.],

  7. [ 0., 0., 0., ..., 0., 1., 0.]])

print Y.shape

 
  1. (1797, 10)

  2. 1797

batch_size = 10 # 使用MBGD算法,設定batch_size爲10

 
  1. def generatebatch(X,Y,n_examples, batch_size):

  2. for batch_i in range(n_examples // batch_size):

  3. start = batch_i*batch_size

  4. end = start + batch_size

  5. batch_xs = X[start:end, :]

  6. batch_ys = Y[start:end]

  7. yield batch_xs, batch_ys # 生成每一個batch


 
  1. tf.reset_default_graph()

  2. tf_X = tf.placeholder(tf.float32,[None,64])

  3. tf_Y = tf.placeholder(tf.float32,[None,10])


 
  1. tf_W_L1 = tf.Variable(tf.zeros([64,10]))

  2. tf_b_L1 = tf.Variable(tf.zeros([1,10]))

pred = tf.nn.softmax(tf.matmul(tf_X,tf_W_L1)+tf_b_L1)

 
  1. loss = -tf.reduce_mean(tf_Y*tf.log(tf.clip_by_value(pred,1e-11,1.0)))

  2. # 也可以直接使用tensorflow的版本:

  3. # loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=tf_Y,logits=pred))

train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss)

 
  1. y_pred = tf.arg_max(pred,1)

  2. bool_pred = tf.equal(tf.arg_max(tf_Y,1),y_pred)

accuracy = tf.reduce_mean(tf.cast(bool_pred,tf.float32)) # 準確率

 
  1. with tf.Session() as sess:

  2. sess.run(tf.global_variables_initializer())

  3. for epoch in range(2001): # 迭代2001個週期

  4. for batch_xs,batch_ys in generatebatch(X_data,Y,Y.shape[0],batch_size): # 每個週期進行MBGD算法

  5. sess.run(train_step,feed_dict={tf_X:batch_xs,tf_Y:batch_ys})

  6. if(epoch%1000==0):

  7. res = sess.run(accuracy,feed_dict={tf_X:X_data,tf_Y:Y})

  8. print (epoch,res)

  9. res_ypred = y_pred.eval(feed_dict={tf_X:X_data,tf_Y:Y}).flatten()

  10. print res_ypred


 
  1. (0, 0.86866999)

  2. (1000, 0.99332219)

  3. (2000, 0.99833053)

  4. [0 1 2 ..., 8 9 8]

from sklearn.metrics import  accuracy_score
print accuracy_score(Y_data,res_ypred.reshape(-1,1))
0.998330550918

八、Logistic Loss的另一種表達

在上面的邏輯迴歸的二分類問題中,我們令正樣本的標籤 y = 1 ,負樣本的標籤 y = 0。對於單個樣本來說,其損失函數Cost(hΘ(X),y)可以表示爲:(hΘ(X)的值表示正樣本的概率)

這裏寫圖片描述

若我們 令正樣本的標籤 y = 1 ,負樣本的標籤 y = -1,則有:

其中(待續)

七、代碼示例

  • 使用ovr多分類的邏輯迴歸判斷鳶尾屬植物的類型

 
  1. from sklearn import datasets

  2.  
  3. iris = datasets.load_iris() # 加載數據

  4. X = iris.data

  5. y = iris.target

  6. print X.shape

  7. print y.shape


 
  1. (150L, 4L)

  2. (150L,)


 
  1. from sklearn.model_selection import train_test_split

  2.  
  3. #分隔訓練集和測試集

  4. X_train, X_test, y_train, y_test = train_test_split(X, y ,test_size = 1/3.,random_state = 8)


 
  1. from sklearn.preprocessing import PolynomialFeatures

  2.  
  3. featurizer = PolynomialFeatures(degree=2) # 特徵多項式化

  4. X_train = featurizer.fit_transform(X_train)

  5. X_test = featurizer.transform(X_test)


 
  1. from sklearn.preprocessing import StandardScaler # 對數據歸一化

  2.  
  3. scaler = StandardScaler()

  4. X_std_train = scaler.fit_transform(X_train)

  5. X_std_test = scaler.transform(X_test)


 
  1. from sklearn.linear_model import LogisticRegression

  2. from sklearn.linear_model import SGDClassifier

  3.  
  4. # penalty:正則化 l2/l1

  5. # C :正則化強度

  6. # multi_class:多分類時使用 ovr: one vs rest

  7. lor = LogisticRegression(penalty='l1',C=100,multi_class='ovr')

  8. lor.fit(X_std_train,y_train)

  9. print lor.score(X_std_test,y_test)

  10.  
  11. sgdv = SGDClassifier(penalty='l1')

  12. sgdv.fit(X_std_train,y_train)

  13. print sgdv.score(X_std_test,y_test)


 
  1. 0.94

  2. 0.92

  3.  
  4.  
  5. LogisticRegression對參數的計算採用精確解析的方式,計算時間長但模型的性能高;SGDClassifier採用隨機梯度下降/上升算法估計模型的參數,計算時間短但模型的性能較低。

  • 使用Tensorflow實現線性邏輯迴歸:

 
  1. from sklearn.datasets import make_classification

  2. import matplotlib.pyplot as plt

  3. import numpy as np


 
  1. X, y = make_classification(n_features=2, n_redundant=0, n_informative=2,

  2. n_clusters_per_class=1,random_state=78,n_samples=200)

  3. X = X.astype(np.float32)

  4. y = y.astype(np.float32)


 
  1. plt.scatter(X[:,0],X[:,1],c=y)

  2. plt.show()

這裏寫圖片描述


 
  1. from sklearn import preprocessing

  2. scaler = preprocessing.StandardScaler().fit(X)

  3. X = scaler.transform(X)

  4. print X.shape

(200, 2)

 
  1. b = tf.Variable(tf.zeros([1,1]))

  2. W = tf.Variable(tf.zeros([2,1]))

  3. X_DATA = tf.placeholder(tf.float32,[None,2])

  4. Y = tf.placeholder(tf.float32,[None,1])


 
  1. H = 1 / (1 + tf.exp(-(tf.matmul(X_DATA, W) + b)))

  2. loss = tf.reduce_mean(- Y* tf.log(tf.clip_by_value(H,1e-11,1.0)) - (1 - Y) * tf.log(1 - tf.clip_by_value(H,1e-11,1.0)))

  3. # 也可以使用tensorflow的版本:

  4. #loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=tf_Y,logits=pred))

optimizer = tf.train.GradientDescentOptimizer(0.1)
train = optimizer.minimize(loss)

 
  1. init_vals = tf.global_variables_initializer()

  2. with tf.Session() as sess:

  3. sess.run(init_vals)

  4. for step in range(15501):

  5. sess.run(train,feed_dict={X_DATA:X,Y:y.reshape(-1,1)})

  6. if(step%5000==0):

  7. print(step,sess.run(W).flatten(),sess.run(b).flatten())

  8. w1 = sess.run(W).flatten()

  9. b1 = sess.run(b).flatten()


 
  1. (0, array([ 0.04289575, 0.04343094], dtype=float32), array([-0.0005], dtype=float32))

  2. (5000, array([ 3.44468737, 3.617342 ], dtype=float32), array([-1.10549724], dtype=float32))

  3. (10000, array([ 3.46032 , 4.07498837], dtype=float32), array([-1.60735476], dtype=float32))

  4. (15000, array([ 3.45384622, 4.39454508], dtype=float32), array([-1.95797122], dtype=float32))

print (w1,b1)
(array([ 3.45412397,  4.42197132], dtype=float32), array([-1.9879719], dtype=float32))

 
  1. x1_min, x1_max = X[:,0].min(), X[:,0].max(),

  2. x2_min, x2_max = X[:,1].min(), X[:,1].max(),

  3. xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max))

  4. f = w1[0]*xx1+w1[1]*xx2+b1[0]

  5. plt.contour(xx1, xx2, f, [0], colors = 'r') # 繪製分隔超平面

  6. plt.scatter(X[:,0],X[:,1],c=y)

  7. plt.show()

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章