ML入门4.0 手写逻辑斯蒂回归 (Logistic Regression)
- 逻辑斯蒂回归简介
- 原理简介
- 决策边界
- 线性分割面的表达
- 学习与分类
- 损失函数
- 第一种损失函数
- 第二种损失函数
- 第三种损失函数
- 梯度下降法
- 代码实现
- 运行结果
- GitHub地址
- 优缺点
逻辑斯蒂回归简介
Logistic Regression 即对数概率回归,是一种广义的线性回归分析模型,是一种应用于二分类问题的分类算法。
常用于数据挖掘,疾病自动诊断,经济预测等领域。例如,探讨引发疾病的危险因素,并根据危险因素预测疾病发生的概率等。以胃癌病情分析为例,选择两组人群,一组是胃癌组,一组是非胃癌组,两组人群必定具有不同的体征与生活方式等。因此因变量就为是否胃癌,值为“是”或“否”,自变量就可以包括很多了,如年龄、性别、饮食习惯、幽门螺杆菌感染等。自变量既可以是连续的,也可以是分类的。然后通过logistic回归分析,可以得到自变量的权重,从而可以大致了解到底哪些因素是胃癌的危险因素。同时根据该权值可以根据危险因素预测一个人患癌症的可能性。百度百科
原理简介
逻辑回归解决二分类问题,所谓分类就是分割数据,那么逻辑回归的本质就是通过在数据集中学习,拟合出分类的决策边界(决策函数)。
决策边界
两个条件属性(二维平面直角坐标系中):决策边界为直线;
三个条件属性(三维空间直角坐标系中):决策边界为平面;
四个条件属性(四维坐标系中):决策边界为超平面;
线性分割面的表达
二维: w 0 x 0 + w 1 x 1 + w 2 x 2 = 0 w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} = 0 w0x0+w1x1+w2x2=0 (PS: x 0 ≡ 1 x_{0} \equiv 1 x0≡1)
三维: w 0 x 0 + w 1 x 1 + w 2 x 2 + w 3 x 3 = 0 w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} + w_{3}x_{3} = 0 w0x0+w1x1+w2x2+w3x3=0
四维: w 0 x 0 + w 1 x 1 + w 2 x 2 + w 3 x 3 + w 4 x 4 = 0 w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} + w_{3}x_{3} + w_{4}x_{4} = 0 w0x0+w1x1+w2x2+w3x3+w4x4=0
向量表达:
n维: X W \boldsymbol X \boldsymbol W XW (X为行向量,W为列向量)
学习与分类
Logistic Regression 的回归任务就是计算向量W
二分类:对于新的对象X’,计算X’W:结果小于0则为0类,否则为1类
损失函数
定义:度量预测结果和实际结果之间的差别
第一种损失函数
令 X = { x 1 , . . . , x m } X=\{x_{1},...,x_{m}\} X={x1,...,xm} ,
MSE = 1 m ∑ i = 1 m ∣ H ( x i w ) − y i ∣ \frac{1}{m}\sum_{i=1}^{m}|H(x_{i}w)-y{i}| m1∑i=1m∣H(xiw)−yi∣
其中 H ( z ) = { 0 if z<0 1 2 if z=0 1 otherwise H(z)= \begin{cases} 0& \text{if z<0}\\ \frac{1}{2}& \text{if z=0}\\ 1& \text{otherwise} \end{cases} H(z)=⎩⎪⎨⎪⎧0211if z<0if z=0otherwise
H ( x i w ) H(x_{i}w) H(xiw)就是分类函数给出的标签, y i y_{i} yi是真实标签
优点:表达了错误率
缺点:函数H不连续,无法使用优化理论
第二种损失函数
MSE = 1 m ∑ i = 1 m 1 2 ( y i ^ − y i ) 2 \frac{1}{m}\sum_{i=1}^{m}\frac{1}{2}(\widehat{y_{i}}-y_{i})^2 m1∑i=1m21(yi −yi)2
其中 y i ^ = σ ( x i w ) \widehat{y_{i}}=\sigma(x_{i}w) yi =σ(xiw),
σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1+e^{-z}} σ(z)=1+e−z1 ;
σ ( z ) ′ = σ ( z ) ( 1 − σ ( z ) ) \sigma(z)' = \sigma(z)(1-\sigma(z)) σ(z)′=σ(z)(1−σ(z))
缺点:非凸优化,多个局部最优解
第三种损失函数
因为 0 < σ ( z ) < 1 0 < \sigma(z) < 1 0<σ(z)<1, 所以将分类函数强行看作概率。
假设:
P ( y i = 1 ∣ x i ; w ) = σ ( x i w ) P (y_{i} = 1|x_{i}; w) = σ(x_{i}w) P(yi=1∣xi;w)=σ(xiw)
$P (y_{i} = 0|x_{i}; w) = 1 - σ(x_{i}w)
综合两式可得
P ( y i ∣ x i ; w ) = ( σ ( x i w ) ) y i ( 1 − σ ( x i w ) ) 1 − y i P (y_{i}|x_{i}; w) = (σ(x_{i}w))^{y_{i}} (1 − σ(x_{i}w))^{1−y_{i}} P(yi∣xi;w)=(σ(xiw))yi(1−σ(xiw))1−yi
由此获得似然函数:
L ( w ) = P ( Y ∣ X ; w ) = ∏ i = 1 m ( σ ( x i w ) ) y i ( 1 − σ ( x i w ) ) 1 − y i L(w) = P (Y|X; w)=\prod_{i=1}^{m}(σ(x_{i}w))^{y_{i}} (1 − σ(x_{i}w))^{1−y_{i}} L(w)=P(Y∣X;w)=∏i=1m(σ(xiw))yi(1−σ(xiw))1−yi
因为log具有单调性
l ( w ) = l o g L ( w ) l(w) = log L(w) l(w)=logL(w)
优化目标为 :
m i n w 1 m ∑ i = 1 m − y i l o g σ ( x i w ) − ( 1 − y i ) l o g ( 1 − σ ( x i w ) ) min_{w}\frac{1}{m}\sum_{i=1}^{m} −y_{i}logσ(x_{i}w) − (1 − y_{i}) log(1 − σ(x_{i}w)) minwm1∑i=1m−yilogσ(xiw)−(1−yi)log(1−σ(xiw))
梯度下降法
∂ l ( w ) ∂ w j = ∑ i = 1 m ( y i − σ ( x i w ) ) x i j \frac{∂l(w)} {∂wj}=\sum_{i=1}^{m}(y_{i} − σ(x_{i}w))x_{ij} ∂wj∂l(w)=∑i=1m(yi−σ(xiw))xij
通过求得优化目标的方向导数(梯度),来确定函数下降的最快方向,由此来更新W以获得最佳W
代码实现
Func1: LoadDataSet(paraFileName)加载数据集
def LoadDataSet(paraFileName):
''' LoadDataSet :param paraFileName: :return: 特征&标签 '''
dataMat = []
labelMat = []
txt = open(paraFileName)
for line in txt.readlines():
tempValuesStringArray = np.array(line.replace("\n", "").split(','))
tempValues = [float(tempValue) for tempValue in tempValuesStringArray]
tempArray = [1.0] + [tempValue for tempValue in tempValues] # 相当于w0对应的x0
tempX = tempArray[:-1]
tempY = tempArray[-1]
dataMat.append(tempX)
labelMat.append(tempY)
return dataMat, labelMat
Func2: sigmoid(paraX)分类函数实现
def sigmoid(paraX):
''' sigmoid函数实现 :param paraX:参数 :return: 计算结果 '''
return 1.0/(1 + np.exp(-paraX))
Func3: gradAscent(dataMat, labelMat)梯度上升法(因为取了优化目标的相反数,所以要求上升最快的方向)求W
def gradAscent(dataMat, labelMat):
''' 用梯度上升法求得最优权重 :param dataMat: :param labelMat: :return: '''
X = np.mat(dataMat)
Y = np.mat(labelMat) #transfer the input to matrix
Y = Y.transpose()
m, n = np.shape(X)
alpha = 0.001 # 学习步长
maxCycles = 1000
W = np.ones( (n,1))
for i in range(maxCycles):
y = sigmoid(X * W)
error = Y - y
W = W + alpha * X.transpose() * error
return W
Func4: STLogisticClassifierTest ()手写分类器
def STLogisticClassifierTest():
''' Logistic 分类器 '''
X, Y = LoadDataSet('iris2condition2class.csv')
tempStartTime = time.time()
tempScore = 0
numInstances = len(Y)
weights = gradAscent(X, Y)
tempPredicts = np.zeros((numInstances))
for i in range(numInstances):
tempPrediction = X[i] * weights
if tempPrediction > 0:
tempPredicts[i] = 1
else:
tempPredicts[i] = 0
tempCorrect = 0
for i in range(numInstances):
if tempPredicts[i] == Y[i]:
tempCorrect += 1
tempScore = tempCorrect / numInstances
tempEndTime = time.time()
tempRunTime = tempEndTime - tempStartTime
print('STLogistic Score: {}, runtime = {}'.format(tempScore, tempRunTime))
rowWeights = np.transpose(weights).A[0]
plotBestFit(rowWeights)
运行结果
GitHub地址
完整代码和数据集见github.
优缺点
优点:
1.适合需要得到一个分类概率的场景。2.计算代价不高,容易理解实现。LR在时间和内存需求上相当高效。它可以应用于分布式数据,并且还有在线算法实现,用较少的资源处理大型数据。3.LR对于数据中小噪声的鲁棒性很好,并且不会受到轻微的多重共线性的特别影响。
缺点:
1.容易欠拟合,分类精度不高。2.数据特征有缺失或者特征空间很大时表现效果并不好。