logistic回归详解
1 原理讲解
算法结构如下图所示:
1.1 前向传播过程
1.2 反向传播过程
2 向量化实现方法
3 代码实现
为了便于理解,首先采用循环的形式实现。正向传播计算损失函数,梯度下降法反向传播更新参数。代码实现如下:
# -*- coding: utf-8 -*-
"""
Created on Thu Oct 24 21:27:14 2019
@author: Iseno_V
"""
import math
import random
#模型参数 y=w1*x1+w2*x2+b
w1=random.random()
w2=random.random()
b=random.random()
#生成训练集样本,本例子中训练集分为y轴以上和y轴以下两种不同类型的点
X=[]#训练集样本
Y=[]#训练集标签
for i in range(1000):
X.append([random.random()*10.0,-random.random()*10.0])
Y.append(0)
for i in range(1000):
X.append([random.random()*10.0,random.random()*10.0])
Y.append(1)
I = 1000#迭代步数
alpha=0.1#学习率
m=len(X)#训练样本集大小
#迭代训练过程
for i in range(I):
#正向传播
J = 0
dw1=0
dw2=0
db=0
for j in range(m):
z=w1*X[j][0]+w2*X[j][1]+b#计算logistic模型输出
a=1.0/(1+math.exp(-z))#激活函数采用sigmoid函数
J=J-(Y[j]*math.log(a)+((1-Y[j])*math.log(1-a)))#迭代求解损失函数
dz=a-Y[j]#迭代求解dJ/dz
dw1=dw1+X[j][0]*dz#迭代求解dJ/dw1
dw2=dw2+X[j][1]*dz#迭代求解dJ/dw2
db=db+dz#迭代求解dJ/db
J=J/m
#计算当前的损失函数并打印出来
print('cross function = {0}'.format(J))
#反向传播(梯度下降法)
dw1=dw1/m
dw2=dw2/m
db=db/m
w1=w1-alpha*dw1#更新参数w1
w2=w2-alpha*dw2#更新参数w2
b=b-alpha*db#更新参数b
#生成测试集
X_test=[]
Y_test=[]
for i in range(100):
X_test.append([random.random()*10.0,-random.random()*10.0])
Y_test.append(0)
for i in range(100):
X_test.append([random.random()*10.0,random.random()*10.0])
Y_test.append(1)
#计算准确率
ans = 0
for i in range(200):
label = 0
if w1*X_test[i][0]+w2*X_test[i][1]+b>0.5:
label=1
if label is Y_test[i]:
ans=ans+1
print('accuracy={0}'.format(ans/200))
由于循环实现效率较低,可以考虑采用向量化方法来实现。python编程中,在可以采用向量化方法的时候尽量不要使用for循环,两种编码方式的效率相差高达几十倍。代码如下所示:
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 25 13:54:19 2019
@author: Iseno_V
"""
import numpy as np
m = 1000#x训练集大小
n = 6#logistic回归模型参数的维数
alpha=0.001#学习率
#生成样本集
X=np.hstack((np.random.rand(n,m/2),-np.random.rand(n,m/2)))
Y=np.hstack((np.zeros((1,m/2)),np.ones((1,m/2))))
#生成测试集
X_test=np.hstack((-np.random.rand(n,m/2),np.random.rand(n,m/2)))
Y_test=np.hstack((np.ones((1,m/2)),np.zeros((1,m/2))))
I = 20000#迭代步数
w = np.random.rand(n,1)#初始化参数w
b = np.random.rand(1,1)#初始化参数b
for i in range(I):
#正向传播过程
z = np.dot(w.T,X)+b
a = 1.0/(1+np.exp(-z))
#计算损失函数
J = - (np.dot(Y,np.log(a).T)+(np.dot((1-Y),np.log(1-a).T)))/m
print('cost function={0}'.format(J))
#反向传播过程
dz = a-Y#计算梯度dJ/dz
dw = np.dot(X,dz.T)/m#计算梯度dJ/dw
db = np.sum(dz)/m#计算梯度dJ/db
w=w-alpha*dw#更新w
b=b-alpha*db#更新b
#采用逻辑运算的方式获取准确率
pre = np.dot(w.T,X_test)+b>0.5
rate = 1-np.sum(np.abs(Y_test - pre.astype(np.int16)))/m
print('accuracy={0}'.format(rate))