1.邏輯斯蒂迴歸、邏輯斯蒂分佈、對數機率
首先,邏輯斯蒂迴歸的公式爲:
對於輸入x,代入上述公式,我們可求出P(Y=1|x)的概率,。
而的公式來源於邏輯斯蒂分佈:
由此分佈可以看出,的公式來與此分佈相同,因此其對應的圖像與F(x)圖像相同。
同時對應的對數機率爲,對應的爲整個實數域,即通過logit變換可將p對應於整個實數域,即將【0,1】與一一對應起來,取上述logit的反函數即爲。
2.參數求解
而此時的我們可利用極大似然估計對上述參數進行求解,首先似然函數如下圖所示
然後我們需要做的就是極大化上述的,具體的求解方法可以用梯度下降法、牛頓法等。(疑問:而此時logistics迴歸爲什麼不直接採用梯度爲0求解?)——link 雖然有時候能夠通過直接令梯度爲0求得,但通過梯度上升也能夠得到差不多最優的結果。最重要的是有的時候不能通過直接令梯度等0直接求出結果,但總能通過梯度上升求出。(極大化——梯度上升/極小化——梯度下降)
具體的對梯度爲:
然後梯度上升的公式爲:
對應到向量的運算爲:
上述爲批量梯度下降的公式,具體到隨機梯度下降上:
總結:
以上,就是這次對邏輯斯蒂迴歸的大致介紹,我們首先介紹了邏輯斯蒂迴歸對應的公式,然後介紹了他與邏輯斯蒂分佈以及對數機率之間的關係;然後介紹模型的參數求解,使用極大似然估計方法求解,先寫出似然函數,然後可以利用梯度下降/牛頓法等用於求解無約束優化問題的這類方法來對參數進行求解。最後,將會附上一個minist數據集對應的手寫邏輯斯蒂迴歸方法實現的分類。
附:邏輯斯蒂迴歸實現(minist數據集)
參考:https://www.pkudodo.com/2018/12/03/1-6/#comment-454
import numpy as np
import datetime
'''
minist 數據集
50000 訓練集
10000 測試集(實際使用200)
訓練結果:
time_cost 295
currencies 0.902
'''
def load_data(fileName):#加載數據
'''
:param fileName:minist訓練集/測試集文件
:return: 對應的特徵值X和標籤值Y
'''
fr = open(fileName, 'r')
dataX = [];dataY = []
for line in fr.readlines():
lineArr = []
curline = line.strip().split(',')
if(curline[0]=='0'):# 二分類問題 轉換爲區分0和非0數字
dataY.append(1) # 標籤
else:
dataY.append(0)
#dataX.append([int(num) for num in curline[1:]]) # 特徵
dataX.append([int(num)/255 for num in curline[1:]]) # 特徵
'''
/255是進行歸一化
如果不進行歸一化 則將如下代碼
if(curline[0]=='0'):# 二分類問題 轉換爲區分0和非0數字
dataY.append(1) # 標籤
else:
dataY.append(0)
改爲:
if(curline[0]=='0'):# 二分類問題 轉換爲區分0和非0數字
dataY.append(0) # 標籤
else:
dataY.append(1)
則正確率會很低
但進行歸一化之後,就不會有上述問題
'''
# print(dataX)
return dataX, dataY
def logistics_Regression(trainX,trainY,iter=200):
'''
對模型進行訓練
:param trainX: 訓練集特徵x
:param trainY:訓練集標籤y
:param iter:迭代次數
:return:返回學習到的參數w
'''
# 將w·x+b變爲w·x
for i in range(len(trainX)):
trainX[i].append(1)
#將列表轉換爲數組 便於運算
trainX = np.array(trainX)
# 權值數組大小
w = np.zeros(trainX.shape[1])
#步長
h = 0.001
for i in range(iter):#迭代次數
for j in range(trainX.shape[0]):
# np.dot 點乘 矩陣相乘 a × b 、b×c ==> a × c
# * np.multiply() 對應元素相乘
wx = np.dot(w,trainX[j])
w += h*(trainY[j]*trainX[j] - trainX[j]*np.exp(wx)/(1+np.exp(wx)))
if i%20==0:
print('{:.2%}...'.format(i/200))
return w
def predict(w,X):
'''
進行結果預測
:param w: 訓練好的參數
:param X: 待預測的樣本特徵
:return: 預測結果
'''
p = np.exp(np.dot(w,X))/(1+np.exp(np.dot(w,X)))
if(p>=0.5):
return 1
else:
return 0
def test(testX,testY,w):
'''
進行測試集的相關測試
:param testX:測試集特徵
:param testY: 測試集標籤
:param w: 參數
:return: 正確率
'''
for i in range(len(testX)):
testX[i].append(1)
count = 0
for i in range(len(testX)):
if testY[i] == predict(w,testX[i]):#進行測試
count+=1
return float(count/len(testX))
if __name__ == "__main__":
print("start read data...")
trainX, trainY = load_data("./mnist_train/mnist_train.csv")
testX, testY = load_data("./mnist_test/mnist_test.csv") # 進行測試
# (60000,784) (60000,1)
# testX = np.mat(testX)
start = datetime.datetime.now()
print("start train the model...")
w = logistics_Regression(trainX, trainY)
print("start test...")
acc = test(testX,testY,w)
end = datetime.datetime.now()
print("time_cost", (end - start).seconds)
print("currencies ", acc)