1. LR模型定义
线性二分类模型:
其中,
是决策平面。
逻辑回归决策函数是将此线性二分类嵌套一个sigmoid函数:
该式子取值在0~1,它的含义是,二分类中,类别y 为正类(即1)的概率。
因此,在二分类中,
其中,
此外, 如果取Y的取值为{+1, -1 }; 最终梯度计算会不一样。
最大似然函数:
(这里也体现了LR满足伯努利分布。)
令损失函数为负对数似然函数:
化简得到:
对
求极小值。
这也是梯度下降法计算的参数梯度。
参数更新:
沿着负梯度方向进行更新。
2. 多分类LR
假如有y 有K类。
损失函数:
或者采用 one-vs-rest 方法,构建 K-1 个逻辑斯蒂回归模型。
3. 防止过拟合方法
1.减少特征数量;
2.正则化
损失函数:
为正则化系数。
4. 实践
LogisticRegression二分类的python实现,由于LogisticRegression没有解释解,使用梯度下降法进行求解。
import sklearn.datasets as datasets
import numpy as np
from sklearn.linear_model import LogisticRegression as LR
class LogisticRegression():
def __init__(self,alpha=0.01,epochs=3):
self.W = None
self.b = None
self.alpha = alpha
self.epochs = epochs
def fit(self,X,y):
# 设定种子
np.random.seed(10)
self.W = np.random.normal(size=(X.shape[1]))
self.b = 0
for epoch in range(self.epochs):
if epoch%50 == 0:
print("epoch",epoch)
w_derivate = np.zeros_like(self.W)
b_derivate = 0
for i in range(len(y)):
# 这里是加上负梯度
w_derivate += (y[i] - 1/(1+np.exp(-np.dot(X[i],self.W.T)-self.b)))*X[i]
b_derivate += (y[i] - 1/(1+np.exp(-np.dot(X[i],self.W.T)-self.b)))
self.W = self.W + self.alpha*np.mean(w_derivate,axis=0)
self.b = self.b + self.alpha*np.mean(b_derivate)
return self
def predict(self,X):
p_1 = 1/(1 + np.exp(-np.dot(X,self.W) - self.b))
return np.where(p_1>0.5, 1, 0)
def accuracy(pred, true):
count = 0
for i in range(len(pred)):
if(pred[i] == true[i]):
count += 1
return count/len(pred)
def normalize(x):
return (x - np.min(x))/(np.max(x) - np.min(x))
if __name__ == "__main__":
# input datasets
digits = datasets.load_breast_cancer()
X = digits.data
y = digits.target
# 归一化
X_norm = normalize(X)
X_train = X_norm[:int(len(X_norm)*0.8)]
X_test = X_norm[int(len(X_norm)*0.8):]
y_train = y[:int(len(X_norm)*0.8)]
y_test = y[int(len(X_norm)*0.8):]
# model 1
lr = LogisticRegression(epochs=500,alpha=0.03)
lr.fit(X_train,y_train)
y_pred = lr.predict(X_test)
# 评估准确率
acc = accuracy(y_pred, y_test)
print("acc", acc)
# model 2
clf_lr = LR()
clf_lr.fit(X_train, y_train)
y_pred2 = clf_lr.predict(X_test)
print("acc2", accuracy(y_pred2, y_test))
运行结果:
acc 0.9473684210526315
acc2 0.9298245614035088
可以看到自己写的LR模型比sklearn里边实现的效果更好,原因,可能是我们设定的超参数(如alpha,epoch)更加适合这个小数据集吧。
参考: