Logistic回归(逻辑回归)及python代码实现
后台-插件-广告管理-内容页头部广告(手机) |
文章目录
- Logistic(Logistic Regression,LR)回归
- 原理讲解
- 参数计算
- python代码实现
- 生成数据集
- 不使用其他库实现
- 定义激活函数(标准Logistic函数即Sigmoid函数)
- 定义LogisticRegression类
- 调用LogisticRegression类解决分类问题
- 使用sklearn库
- 拓展
Logistic(Logistic Regression,LR)回归
原理讲解
在模式识别问题中,所关心的量是分类,比如是否会患有某种疾病,这时就不能用简单的线性回归来完成这个问题了。为了解决次问题,我们引入了非线性激活函数
g
:
R
D
→
(
0
,
1
)
g:{\mathbb R}^D\to(0,1)
g:RD→(0,1)来预测类别标签的后验概率
p
(
y
=
1
∣
x
)
p(y=1|\bf x)
p(y=1∣x),其中
y
∈
{
0
,
1
}
y\in\{0,1\}
y∈{0,1},函数
g
g
g的作用是把线性函数的值域从实数区间挤压到0和1之间
在Logistic回归中,激活函数的表达式为:
σ
(
x
)
=
1
1
+
e
−
x
\sigma(x)=\frac{1}{1+e^{-x}}
σ(x)=1+e−x1
标签
y
=
1
y=1
y=1的后验概率为
p
(
y
=
1
∣
x
)
=
σ
(
w
T
x
)
=
1
1
+
e
−
w
T
x
⋯
(
1
)
p(y=1|{\bf x})=\sigma({\bf w}^{\rm T}{\bf {x}})=\frac{1}{1+e^{-{\bf w}^{\rm T}{\bf {x}}}}\cdots(1)
p(y=1∣x)=σ(wTx)=1+e−wTx1⋯(1)
这里,
x
=
[
x
1
,
⋯
,
x
D
,
1
]
T
{\bf x}=[x_1,\cdots,x_D,1]^{\rm T}
x=[x1,⋯,xD,1]T和
w
=
[
w
1
,
⋯
,
w
D
,
b
]
T
{\bf w}=[w_1,\cdots,w_D,b]^{\rm T}
w=[w1,⋯,wD,b]T分别为D+1维的增广特征向量与增广权重向量
标签
y
=
0
y=0
y=0的后验概率为
p
(
y
=
0
∣
x
)
=
1
−
p
(
y
=
1
∣
x
)
=
e
−
w
T
x
1
+
e
−
w
T
x
p(y=0|{\bf x})=1-p(y=1|{\bf x})=\frac{e^{-{\bf w}^{\rm T}{\bf {x}}}}{1+e^{-{\bf w}^{\rm T}{\bf {x}}}}
p(y=0∣x)=1−p(y=1∣x)=1+e−wTxe−wTx
对式(1)进行变换后得到
w
T
x
=
log
p
(
y
=
1
∣
x
)
1
−
p
(
y
=
1
∣
x
)
=
log
p
(
y
=
1
∣
x
)
p
(
y
=
0
∣
x
)
{\bf w}^{\rm T}{\bf {x}}=\log \frac{p(y=1|{\bf x})}{1-p(y=1|{\bf x})}=\log \frac{p(y=1|{\bf x})}{p(y=0|{\bf x})}
wTx=log1−p(y=1∣x)p(y=1∣x)=logp(y=0∣x)p(y=1∣x)上式左边为线性函数,右边为正反后验概率比值(几率)取对数,因此Logistic回归也称为对数几率回归
参数计算
LR采用交叉熵作为损失函数,使用梯度下降进行优化
假设存在N个训练样本
{
(
x
(
n
)
,
y
(
n
)
)
}
n
=
1
N
\{({\bf x}^{(n)},y^{(n)})\}_{n=1}^N
{(x(n),y(n))}n=1N,采用LR回归模型对每个样本
x
(
n
)
{\bf x}^{(n)}
x(n)进行预测,输出其标签为1的后验概率,记为
y
^
(
n
)
{\hat y}^{(n)}
y^(n),即
y
^
(
n
)
=
σ
(
w
T
x
(
n
)
)
,
1
≤
n
≤
N
{\hat y}^{(n)}=\sigma({\bf w}^{\rm T}{\bf {x}}^{(n)}),1\leq n\leq N
y^(n)=σ(wTx(n)),1≤n≤N
由于
y
(
n
)
∈
{
0
,
1
}
y^{(n)}\in\{0,1\}
y(n)∈{0,1},样本
(
x
(
n
)
,
y
(
n
)
)
({\bf x}^{(n)},y^{(n)})
(x(n),y(n))的真实条件概率可以表示为
p
r
(
y
(
n
)
=
1
∣
x
(
n
)
)
=
y
(
n
)
,
p_r(y^{(n)}=1|{\bf x}^{(n)})=y^{(n)},
pr(y(n)=1∣x(n))=y(n),
p
r
(
y
(
n
)
=
0
∣
x
(
n
)
)
=
1
−
y
(
n
)
p_r(y^{(n)}=0|{\bf x}^{(n)})=1-y^{(n)}
pr(y(n)=0∣x(n))=1−y(n)
采用交叉熵损失函数,其风险函数为
R
(
w
)
=
−
1
N
∑
n
=
1
N
(
p
r
(
y
(
n
)
=
1
∣
x
(
n
)
)
log
y
^
(
n
)
+
p
r
(
y
(
n
)
=
0
∣
x
(
n
)
)
log
(
1
−
y
^
(
n
)
)
)
=
−
1
N
∑
n
=
1
N
(
y
(
n
)
log
y
^
(
n
)
+
(
1
−
y
(
n
)
)
log
(
1
−
y
^
(
n
)
)
)
{\mathcal R}({\bf w})=-\frac{1}{N}\sum_{n=1}^N \left(p_r(y^{(n)}=1|{\bf x}^{(n)})\log {\hat y}^{(n)}+p_r(y^{(n)}=0|{\bf x}^{(n)})\log (1-{\hat y}^{(n)})\right) \\ =-\frac{1}{N}\sum_{n=1}^N\left(y^{(n)}\log {\hat y}^{(n)}+(1-y^{(n)})\log (1-{\hat y}^{(n)}) \right)
R(w)=−N1n=1∑N(pr(y(n)=1∣x(n))logy^(n)+pr(y(n)=0∣x(n))log(1−y^(n)))=−N1n=1∑N(y(n)logy^(n)+(1−y(n))log(1−y^(n)))
风险函数关于参数
w
\bf w
w的偏导数为
∂
R
(
w
)
∂
w
=
−
1
N
∑
n
=
1
N
(
y
(
n
)
y
^
(
n
)
(
1
−
y
^
(
n
)
)
y
^
(
n
)
x
(
n
)
−
(
1
−
y
(
n
)
)
y
^
(
n
)
(
1
−
y
^
(
n
)
)
1
−
y
^
(
n
)
x
(
n
)
)
=
−
1
N
∑
n
=
1
N
(
y
(
n
)
(
1
−
y
^
(
n
)
)
x
(
n
)
−
(
1
−
y
(
n
)
)
y
^
(
n
)
x
(
n
)
)
=
−
1
N
∑
n
=
1
N
x
(
n
)
(
y
(
n
)
−
y
^
(
n
)
)
\frac{\partial {\mathcal R}({\bf w})}{\partial {\bf w}}=-\frac{1}{N}\sum_{n=1}^N\left(y^{(n)}\frac{{\hat y}^{(n)}(1-{\hat y}^{(n)})}{{\hat y}^{(n)}}{\bf x}^{(n)}-(1-y^{(n)})\frac{{\hat y}^{(n)}(1-{\hat y}^{(n)})}{1-{\hat y}^{(n)}}{\bf x}^{(n)} \right) \\ =-\frac{1}{N}\sum_{n=1}^N\left(y^{(n)}(1-{\hat y}^{(n)}){\bf x}^{(n)}-(1-y^{(n)}){\hat y}^{(n)}{\bf x}^{(n)} \right) \\ =-\frac{1}{N}\sum_{n=1}^N{\bf x}^{(n)}(y^{(n)}-{\hat y}^{(n)})
∂w∂R(w)=−N1n=1∑N(y(n)y^(n)y^(n)(1−y^(n))x(n)−(1−y(n))1−y^(n)y^(n)(1−y^(n))x(n))=−N1n=1∑N(y(n)(1−y^(n))x(n)−(1−y(n))y^(n)x(n))=−N1n=1∑Nx(n)(y(n)−y^(n))
由此我们可以采用梯度下降法更新参数最终得到合适的参数
w
\bf w
w
python代码实现
生成数据集
我们通过下面的代码自行生成一个样本数量为100的数据集
import numpy as np import matplotlib.pyplot as plt # 设置随机种子,以便结果可复现 np.random.seed(42) # 生成随机数据 # 两个特征的均值和方差 mean_1 = [2, 2] cov_1 = [[2, 0], [0, 2]] mean_2 = [-2, -2] cov_2 = [[1, 0], [0, 1]] # 生成类别1的样本 X1 = np.random.multivariate_normal(mean_1, cov_1, 50) y1 = np.zeros(50) # 生成类别2的样本 X2 = np.random.multivariate_normal(mean_2, cov_2, 50) y2 = np.ones(50) # 合并样本和标签 X = np.concatenate((X1, X2), axis=0) y = np.concatenate((y1, y2)) # 绘制散点图 plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1, edgecolor='k') plt.xlabel('Feature 1') plt.ylabel('Feature 2') plt.title('Logistic Regression Dataset') plt.show()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
运行结果如下图所示
图中,类别1为右上部分,标签为0;类别2为左下部分,标签为1
不使用其他库实现
定义激活函数(标准Logistic函数即Sigmoid函数)
def sigmoid(x): if x>0: return 1.0/(1.0+np.exp(-x)) else: return np.exp(x)/(1.0+np.exp(x))- 1
- 2
- 3
- 4
- 5
定义LogisticRegression类
class LogisticRegression: def __init__(self, learning_rate=0.01, num_iterations=1000): self.learning_rate = learning_rate self.num_iterations = num_iterations self.weights = None self.bias = None def fit(self, X, y): num_samples, num_features = X.shape # 初始化权重和偏置 self.weights = np.zeros(num_features) self.bias = 0 # 梯度下降 for _ in range(self.num_iterations): linear_model = np.dot(X, self.weights) + self.bias y_pred = sigmoid(linear_model) dw = (1 / num_samples) * np.dot(X.T, (y_pred - y)) db = (1 / num_samples) * np.sum(y_pred - y) self.weights -= self.learning_rate * dw self.bias -= self.learning_rate * db def predict_prob(self, X): linear_model = np.dot(X, self.weights) + self.bias y_pred = sigmoid(linear_model) return y_pred def predict(self, X, threshold=0.5): y_pred_prob = self.predict_prob(X) y_pred = np.zeros_like(y_pred_prob) y_pred[y_pred_prob >= threshold] = 1 return y_pred- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
调用LogisticRegression类解决分类问题
# 创建 Logistic 回归模型 logreg = LogisticRegression() # 训练模型 logreg.fit(X, y) # 预测样本 X_new = np.array([[2.5, 2.5], [-6.0, -4.0]]) y_pred_prob = logreg.predict_prob(X_new) y_pred = logreg.predict(X_new) print("Predicted Probabilities:", y_pred_prob) print("Predicted Labels:", y_pred)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
输出结果为
预测样本1(2.5,2.5)位于右上部分属于类别1,真实标签为0;预测样本2(-6,-4)位于左下部分属于类别2,真实标签为1,对比输出结果可知,该分类器已训练得合适参数,可完成分类任务
使用sklearn库
我们可以通过使用sklearn库来简洁地实现LR
import numpy as np from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score #所使用数据集同上X,y # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 创建Logistic回归模型 logreg = LogisticRegression() # 训练模型 logreg.fit(X_train, y_train) # 预测测试集 y_pred = logreg.predict(X_test) # 计算预测准确率 accuracy = accuracy_score(y_test, y_pred) print("Accuracy:", accuracy)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
最终测试集上计算得到的准确率accuracy为1,可见该分类器的效果非常好
拓展
logistic回归可以用于分类非线性可分的数据。尽管logistic回归本身是一个线性分类器,但可以通过引入多项式特征、交互特征、组合特征等方法来扩展其能力,从而处理非线性的分类问题。
具体来说,可以通过特征工程的方式将原始特征进行变换,以引入非线性关系。例如,可以通过添加多项式特征,将原始特征的高阶项加入到模型中,例如原始特征的平方项、立方项等。还可以引入交互特征,将不同特征之间的乘积或分割点(例如,做差或做除)作为新的特征。
通过引入这些非线性特征,logistic回归可以更好地捕捉到数据中的非线性关系,从而能够更好地分类非线性可分的数据。需要注意的是,在引入非线性特征时,可能需要进行正则化或其他模型调优技巧,以避免过拟合问题。
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。
在线投稿:投稿 站长QQ:1888636
后台-插件-广告管理-内容页尾部广告(手机) |