书中重要定义及一些理解
- 先通过介绍逻辑史蒂的分布来引出logist模型
- 而通过极大似然法来推导模型的参数估计问题
- 通过对模型参数的似然函数通过求导来得到递归方程
- 通过公式可以看出logist是对前面的感知机的升级版,感知机的判断方式过于简单。而其梯度下降的时候也将sign的去掉了,否则无法微分。
- 后通过方程来写出公式,代码如下
import numpy as np
from read_data import get_2_kind_data
def logistic_Regression(tra_x, tra_y, lambdas=0.01, iter=200):
'''
逻辑斯蒂回归训练过程
:param trainDataList:训练集
:param trainLabelList: 标签集
:param iter: 迭代次数
:return: 习得的w
'''
# 按照书本“6.1.2 二项逻辑斯蒂回归模型”中式6.5的规则,将w与b合在一起,
# 此时x也需要添加一维,数值为1
tra_x = np.insert(tra_x, len(tra_x[0]), 1, 1)
w = np.random.rand(len(tra_x[0]))
for i in range(iter): # 每次迭代冲遍历一次所有样本,进行随机梯度下降
for j in range(len(tra_x)):
# 随机梯度上升部分
# 在“6.1.3 模型参数估计”一章中给出了似然函数,我们需要极大化似然函数
# 但是似然函数由于有求和项,并不能直接对w求导得出最优w,所以针对似然函数求和
# 部分中每一项进行单独地求导w,得到针对该样本的梯度,并进行梯度上升(因为是
# 要求似然函数的极大值,所以是梯度上升,如果是极小值就梯度下降。梯度上升是
# 加号,下降是减号)
# 求和式中每一项单独对w求导结果为:xi * yi - (exp(w * xi) * xi) / (1 + exp(w * xi))
# 如果对于该求导式有疑问可查看我的博客 www.pkudodo.com
# 计算w * xi,因为后式中要计算两次该值,为了节约时间这里提前算出
# 其实也可直接算出exp(wx),为了读者能看得方便一点就这么写了,包括yi和xi都提前列出了
wx = np.dot(w, tra_x[j].T)
yi = tra_y[j]
xi = tra_x[j]
w += lambdas * (xi * yi - (np.exp(wx) * xi) / (1 + np.exp(wx)))
return w
def predict(w, x):
'''
预测标签
:param w:训练过程中学到的w
:param x: 要预测的样本
:return: 预测结果
'''
#dot为两个向量的点积操作,计算得到w * x
wx = np.dot(w, x)
#计算标签为1的概率
#该公式参考“6.1.2 二项逻辑斯蒂回归模型”中的式6.5
P1 = np.exp(wx) / (1 + np.exp(wx))
#如果为1的概率大于0.5,返回1
if P1 >= 0.5:
return 1
#否则返回0
return 0
def test(testDataList, testLabelList, w):
'''
验证
:param testDataList:测试集
:param testLabelList: 测试集标签
:param w: 训练过程中学到的w
:return: 正确率
'''
#与训练过程一致,先将所有的样本添加一维,值为1,理由请查看训练函数
testDataList=np.insert(testDataList,len(testDataList[0]),1,1)
#错误值计数
errorCnt = 0
#对于测试集中每一个测试样本进行验证
for i in range(len(testDataList)):
#如果标记与预测不一致,错误值加1
if testLabelList[i] != predict(w, testDataList[i]):
errorCnt += 1
#返回准确率
return 1 - errorCnt / len(testDataList)
if __name__ == '__main__':
tra_x, test_x, tra_y, test_y = get_2_kind_data('data/Mnist/mnist_train.csv')
tra_x, test_x = tra_x / 255, test_x / 255
w=logistic_Regression(tra_x, tra_y)
acc=test(test_x,test_y,w)
print(acc)