逻辑回归(logistic regression)被广泛用于分类预测,例如:银行通过客户的用户行为判断客户是否会流失,医院通过病人肿瘤的形态特征判断肿瘤是否为良性,电子邮箱通过对邮件信息的识别判断是否为垃圾邮件等等。作为目前最流行使用的一种学习算法,逻辑回归能非常有效地对数据进行分类。
1. 回归假设
h
θ
(
x
)
=
g
(
θ
T
X
)
h_θ (x)=g(θ^T X)
hθ(x)=g(θTX),其中:
X
X
X代表特征向量(即影响因子向量),
θ
T
θ^T
θT代表参数的转置矩阵,
g
g
g 代表一个常用的逻辑函数,为S形函数(Sigmoid function),公式为:
g
(
z
)
=
1
/
(
1
+
e
(
−
z
)
)
g(z)=1/(1+e^{(-z)} )
g(z)=1/(1+e(−z))。合起来,我们可以得到逻辑回归的假设函数为:
h
θ
(
x
)
=
1
/
(
1
+
e
(
−
θ
T
X
)
)
h_θ (x)=1/(1+e^{(-θ^T X)} )
hθ(x)=1/(1+e(−θTX))
其中,
θ
T
X
θ^T X
θTX是参数
θ
θ
θ和特征
X
X
X的向量运算,展开就是:
θ
T
X
=
θ
0
+
θ
1
x
1
+
θ
2
x
2
+
.
.
.
+
θ
n
x
n
(
n
代
表
特
征
的
数
量
)
θ^T X=θ_0+θ_1 x_1+θ_2 x_2+...+θ_n x_n(n代表特征的数量)
θTX=θ0+θ1x1+θ2x2+...+θnxn(n代表特征的数量)
1)S形函数
- 实际上,我们套用了S形函数进行逻辑回归的计算。这是个非常经典的分类函数,是机器学习入门必须掌握的基础知识。
- 函数是一个分数,取值在0-1之间。
- 当
z
<
0
z<0
z<0时,
g
(
z
)
<
0.5
g(z)<0.5
g(z)<0.5;当
z
=
0
z=0
z=0时,
g
(
z
)
=
0.5
g(z)=0.5
g(z)=0.5;当
z
>
0
z>0
z>0时,
g
(
z
)
>
0.5
g(z)>0.5
g(z)>0.5。
- S函数用python代码实现为:
import numpy as np
def sigmoid(z):
return 1 / (1 + np.exp(-z))
2)假设判断
- h θ ( x ) h_θ (x) hθ(x)表示的是:根据参数得出因变量y为1的概率/可能性(estimated probablity),即 h θ ( x ) = P ( y = 1 ∣ x ; θ ) h_θ (x)=P(y=1|x;θ) hθ(x)=P(y=1∣x;θ)
- 一般地,我们判断:
- h θ ( x ) < = 0.5 h_θ (x)<=0.5 hθ(x)<=0.5,则分类为 y = 0 y=0 y=0; h θ ( x ) > 0.5 h_θ (x)>0.5 hθ(x)>0.5,则分类为 y = 1 y=1 y=1。
举个栗子:
假设病人患恶性肿瘤为 y = 1 y=1 y=1,未患恶性肿瘤为 y = 0 y=0 y=0。现根据肿瘤大小( x 1 x_1 x1)和肿瘤颜色( x 2 x_2 x2)两个特征可以得到逻辑回归模型为: h θ ( x ) = g ( θ T X ) = g ( θ 0 + θ 1 x 1 + θ 2 x 2 ) = 1 / ( 1 + e − ( θ 0 + θ 1 x 1 + θ 2 x 2 ) ) h_θ (x)=g(θ^T X)=g(θ_0+θ_1 x_1+θ_2 x_2)=1/(1+e^{-(θ_0+θ_1 x_1+θ_2 x_2)}) hθ(x)=g(θTX)=g(θ0+θ1x1+θ2x2)=1/(1+e−(θ0+θ1x1+θ2x2))
其中,参数 θ 0 = − 0.8 , θ 1 = 0.01 , θ 2 = − 0.05 θ_0=-0.8,θ_1=0.01,θ_2=-0.05 θ0=−0.8,θ1=0.01,θ2=−0.05,则模型为:
h θ ( x ) = 1 / ( 1 + e − ( − 0.8 + 0.01 x 1 − 0.05 x 2 ) ) h_θ (x)=1/(1+e^{-(-0.8+0.01 x_1-0.05 x_2)}) hθ(x)=1/(1+e−(−0.8+0.01x1−0.05x2))
已知一名病人的肿瘤大小为1cm,肿瘤颜色分类为5,则代入模型计算得到 h θ ( x ) = 0.26 h_θ (x)=0.26 hθ(x)=0.26,说明病人患恶性肿瘤的概率为0.26,概率低于0.5,由此我们将病人分类为“未患肿瘤( y = 0 y=0 y=0)”。
3)决策边界
- 决策边界是对分类预测的可视化。如上文所说,一般以
h
θ
(
x
)
=
0.5
h_θ (x)=0.5
hθ(x)=0.5进行分类,而此时
z
=
θ
T
X
=
0
z=θ^T X=0
z=θTX=0。
- 当特征变量 X X X只有1-3个时,我们可以通过散点图画出 θ T X = 0 θ^T X=0 θTX=0的决策边界,帮助我们更好地理解分类正确率,但画出决策边界不是必须的。因为大部分时候,特征变量都会多于3个,这时,我们就很难画出决策边界,一般通过混淆矩阵判断预测的准确度。
2.特征缩放
- 特征缩放(feature scaling)其实就是将所有的特征变量缩放到相近的尺度,以便减少计算量,更快地构建模型,最常用的方法是通过均值归一化(mean normalization)将所有特征的尺度都尽量缩放到-1到1之间。即:
x n = ( x n − μ n ) / s n , ( μ n 是 平 均 值 , s n 为 标 准 差 ) x_n=(x_n-μ_n)/s_n ,(μ_n是平均值,s_n为标准差) xn=(xn−μn)/sn,(μn是平均值,sn为标准差) - 这是模型构建前必做的数据预处理动作,能有效减少计算量。
- 特征缩放用Python代码实现为:
import numpy as np
def featurescaling(X):
X=(X-np.average(X))/np.std(X)
return X
3. 损失函数
- 构建预测模型就需要定义损失函数。损失函数也叫代价函数(loss function),简单理解,就是计算预测值与实际值之间的误差。通过计算损失(loss),我们才能判断模型的准确度。通用公式如下:
J
(
θ
)
=
1
/
m
∑
(
i
=
1
)
m
C
o
s
t
(
h
θ
(
x
(
i
)
)
,
y
(
i
)
)
(
m
表
示
样
本
数
量
)
J(θ)=1/m ∑_{(i=1)}^mCost(h_θ (x^{(i)} ),y^{(i)})(m表示样本数量)
J(θ)=1/m(i=1)∑mCost(hθ(x(i)),y(i))(m表示样本数量)
对于逻辑回归,我们采用对数计算损失,其中:
简化可以得到:
C
o
s
t
(
h
θ
(
x
)
,
y
)
=
−
y
×
l
o
g
(
h
θ
(
x
)
)
−
(
1
−
y
)
×
l
o
g
(
1
−
h
θ
(
x
)
)
Cost(h_θ (x),y)=-y×log(h_θ (x))-(1-y)×log(1-h_θ (x))
Cost(hθ(x),y)=−y×log(hθ(x))−(1−y)×log(1−hθ(x))
最终可以得到逻辑回归的代价函数为:
J
(
θ
)
=
1
/
m
∑
(
i
=
1
)
m
[
−
y
×
l
o
g
(
h
θ
(
x
)
)
−
(
1
−
y
)
×
l
o
g
(
1
−
h
θ
(
x
)
)
]
J(θ)=1/m ∑_{(i=1)}^m[-y×log(h_θ (x))-(1-y)×log(1-h_θ (x)) ]
J(θ)=1/m(i=1)∑m[−y×log(hθ(x))−(1−y)×log(1−hθ(x))]
- 损失函数用Python代码实现为:
import numpy as np
def costfunction(theta, X, y):
theta = np.matrix(theta)
X = np.matrix(X)
y = np.matrix(y)
part_1 = np.multiply(-y, np.log(sigmoid(X @ theta.T)))# 引用了sigmoid函数
part_2 = np.multiply((1 - y), np.log(1 - sigmoid(X @ theta.T)))
return np.sum(part_1 - part_2) / (len(X))
4.优化算法:梯度下降
- 既然我们通过损失函数计算了损失,那么为了减少损失,我们就需要对参数进行不断的优化。
- 梯度下降(gradient descent)是一个用来求函数最小值的算法,非常强大可靠,主要是通过代价函数的导数更新优化参数,直至达到代价函数的局部最小值,通用公式为:
R e p e a t θ j : = θ j − α ∂ / ∂ θ j J ( θ ) ( 同 时 更 新 所 有 的 θ j ) Repeat { θ_j:=θ_j-α ∂/∂θ_j J(θ) (同时更新所有的θ_j ) } Repeatθj:=θj−α∂/∂θjJ(θ)(同时更新所有的θj)
根据微积分知识,简化后可以得到 θ j : = θ j − α / m ∑ ( i = 1 ) m [ ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) ] , ( α 为 学 习 速 度 ( l e a r n i n g r a t e ) , m 为 样 本 数 量 ) θ_j:=θ_j-α /m ∑_{(i=1)}^m[(h_θ (x^{(i)})-y^{(i)})x_j^{(i)} ], (α为学习速度(learning rate),m为样本数量) θj:=θj−α/m(i=1)∑m[(hθ(x(i))−y(i))xj(i)],(α为学习速度(learningrate),m为样本数量) - α α α控制我们按多大的幅度去更新参数。如果a太小,梯度下降计算慢;如果a太大,那么梯度下降可能会越过最低点,导致无法收敛,甚至发散。
- 梯度下降用Python代码实现为:
def gradientDescent(X, y, theta, alpha, iters):#iters表示更新迭代次数
theta = np.matrix(theta)
X = np.matrix(X)
y = np.matrix(y)
temp = np.matrix(np.zeros(theta.shape))# 设置temp作为theta的转换
parameters = int(theta.ravel().shape[1]) # 计算参数的数量
cost = np.zeros(iters)
# 设置迭代循环
for i in range(iters):
error = sigmoid(X @ theta.T) - y # 引用sigmoid函数
for j in range(parameters):
term = np.multiply(error, X[:,j])
temp[0,j] = theta[0,j] - ((alpha / len(X)) * np.sum(term))
theta = temp
cost[i] = costfunction(theta, X, y) # 引用costfunction函数
return theta, cost
- 除了梯度下降算法以外,还有很多其他更高级的优化算法,本文就不多赘述了。
4. 模板代码
- 了解了逻辑回归的数学知识之后,实际工作中,我们不需要自己定义损失函数和优化算法,有成熟的机器学习库可供我们直接调用。比如,sklearn中逻辑回归函数可调用的优化算法就有:liblinear, newton-cg, lbfgs, sag 和 saga,默认使用lbfgs。
- 下面是调用sklearn库的模板代码:
# 1.创建X和y
X = df.iloc[:,:-1].values # 需根据实际情况更改
y = df.iloc[:,-1].values # 需根据实际情况更改
# 2.将数据分成训练集和测试集
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=0)
# 3.特征缩放(Feature Scaling)
from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)#转换变量
X_test = sc_X.fit_transform(X_test)#转换变量
# 4.利用逻辑回归进行分类
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression(random_state=0)
classifier.fit(X_train,y_train)
# 5.预测测试集中的y值
y_pred = classifier.predict(X_test)
# 6.用混淆矩阵检测准确率
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test,y_pred)