什么是逻辑回归
逻辑回归(Logistic Regression)是⼀种⽤于解决分类问题的统计学习⽅法。 尽管它的名称中包含"回归"⼀词,但它实际上是⼀种分类算法,⽤于将输⼊数据分 为两个或多个类别。逻辑回归通常⽤于⼆元分类问题,其中要将输⼊数据分为两个 类别,但它也可以扩展到多类别分类。
逻辑回归的基本思想是,通过将输⼊特征与权重进⾏线性组合,然后将线性组 合的结果通过⼀个称为逻辑函数(Logistic function)或 Sigmoid 函数的⾮线性 函数进⾏转换,将其映射到⼀个介于0和1之间的概率值。这个概率值表示属于某⼀ 类别的概率。
sepal_length | sepal_width | petal_length | petal_width | species |
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5 | 3.6 | 1.4 | 0.2 | ? |
我们就可以基于已知的数据集,建⽴模型,从⽽可以对未知的样本数据进⾏分类预测。
算法模型
对于逻辑回归,模型的前⾯与线性回归类似:
不过, z的值是⼀个连续的值,取值范围为 (-∞,∞),我们可以将阈值设置为中 间的位置,也就是 0,当 z>0时,模型将样本判定为⼀个类别(正例),当 z<=0 时,模型将样本判定为另外⼀个类别(负例)。这样,模型就实现了⼆分类的任务。
假设真实的分类 的值为1与0,则模型的预测结果为:
sigmoid函数
Sigmoid 函数(也称为 Logistic 函数)是⼀种常⻅的⾮线性激活函数,通常⽤于 将实数值映射到介于 0 和 1 之间的范围。它的数学形式如下:
其中:
- sigmoid(z) 是 Sigmoid 函数的输出,它表示在输⼊ z的情况下,输出为 1 的概率。
Sigmoid 函数具有以下特性:
- 输出范围在 0 到 1 之间,因此它常被⽤于⼆元分类问题,其中输出可以被解释 为某个事件发⽣的概率。
- 当 z 接近正⽆穷⼤时,sigmoid(z)接近 1,当 z接近负⽆穷⼤时,sigmoid(z)接 近 0。
- Sigmoid 函数是单调递增的,这意味着输⼊值增加时,输出值也增加。
sigmoid函数图像
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['font.size'] = 12
plt.figure(figsize=(10,5))
z = np.linspace(-10,10,200)
sig = 1/(1+np.exp(-z))
plt.plot(z,sig, 'g', linewidth=2, label=r'$\sigma(x)=\frac{1}{1+e^{-z}}$')
plt.legend(fontsize=20)
plt.axhline(y=1,ls='--',c='k')
plt.axhline(y=0,ls='--',c='k')
运行结果:
损失函数
损失函数是⽤于评估模型预测结果与实际结果之间差异的函数。
对数损失函数
在逻辑回归中,损失函数通常是对数损失函数(log loss),它根据模型的预测概 率和真实标签来计算损失。
为了⽅便求解,我们取对数似然函数,让累积乘积变成累积求和:
我们可以将上式的相反数作为逻辑回归的损失函数(对数损失函数):
损失函数与sigmoid
import matplotlib.pyplot as plt
s =np.linspace(0.01,0.99,200)
for y in [0,1]:
loss = -(y*np.log(s)+(1-y)*np.log(1-s))
plt.plot(s,loss,label=f"y={y}")
plt.legend()
plt.xlabel('s(z)')
plt.ylabel('J(w)')
运行结果
模型训练与预测
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import warnings
warnings.filterwarnings("ignore")
iris = load_iris()
x,y = iris.data,iris.target
x = x[y!=0,2:]
y=y[y!=0]
y[y==1] = 0
y[y==2] = 1
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25,random
_state=20)
lr = LogisticRegression()
lr.fit(x_train,y_train)
y_hat = lr.predict(x_test)
print("权重:", lr.coef_)
print("偏置:", lr.intercept_)
print("真实值:", y_test)
print("预测值:", y_hat)
运行结果
权重: [[2.77710497 1.82744851]]
偏置: [-16.80892093]
真实值: [1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0]
预测值: [1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 1 0 0 1 0 1 0]
可视化
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'SimHei'
c1 = x[y == 0]
c2 = x[y == 1]
plt.scatter(x=c1[:, 0], y=c1[:, 1], c="g", label="类别0")
plt.scatter(x=c2[:, 0], y=c2[:, 1], c="r", label="类别1")
plt.xlabel("花瓣⻓度")
plt.ylabel("花瓣宽度")
plt.title("鸢尾花样本分布")
plt.legend()
运行结果
接下来,我们来绘制在测试集中,样本的真实类别与预测类别。
plt.figure(figsize=(15,5))
plt.plot(y_test,marker="o",ls="",ms=15,c="r",label="真实类别")
plt.plot(y_hat,marker="X",ls="",ms=15,c="g",label="预测类别")
plt.legend()
plt.title("逻辑回归分类预测结果")
plt.show()
运行结果
逻辑回归实现二分类
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import warnings
warnings.filterwarnings('ignore')
iris = load_iris()
x,y = iris.data,iris.target
# 只取1和2这两个类别
x = x[y!=0,2:] # 取类别不为0,然后取2列和3列
y = y[y!=0] # 取y != 0 的类别
# print(y)
y[y==1] = 0 # 把原来为1的类别改为0
y[y==2] = 1
# 数据集划分
x_train, x_test,y_train,y_test = train_test_split(x,y,test_size=0.25,random_state=2)
lr = LogisticRegression()
# 训练数据
lr.fit(x_train,y_train)
# 预测
y_hat = lr.predict(x_test)
print("真实值", y_test)
print("预测值", y_hat)
运行结果
真实值 [1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 1 0 1] 预测值 [1 0 0 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 1 1 0 0 1 0 1]
绘制决策边界
# np.meshgrid
x = np.arange(0,5,2)
y = np.arange(1,10,3)
print(x)
print(y)
plt.plot(x,y, color='red', marker='.',linestyle='',markersize='10')
plt.grid()
运行结果
x = np.arange(0,5,2)
y = np.arange(1,10,3)
X,Y = np.meshgrid(x,y)
plt.plot(X,Y, color='red', marker='.',linestyle='',markersize='10')
plt.grid()
运行结果
from matplotlib.colors import ListedColormap
def plot_decision_boundary(model,X,y):
# 设置三个分类
color = ['r','g','b']
marker = ['o','v','x']
# 获取标签
class_label = np.unique(y)
# 定义颜色图
cmap = ListedColormap(color[:len(class_label)])
# 获取最小值和最大值
x1_min,x2_min = np.min(X,axis=0)
x1_max,x2_max = np.max(X,axis=0)
print(X.shape)
# 在原范围内取更多值
x1 = np.arange(x1_min-1,x1_max+1,0.02)
x2 = np.arange(x2_min-1,x2_max+1,0.02)
#笛卡尔积
X1,X2 = np.meshgrid(x1,x2)
# print(X1.shape) # (175,295)
# print(X2.shape) # (175,295)
Z = model.predict(np.array([X1.ravel(), X2.ravel()]).T).reshape(X1.shape)
# 绘制等高线
plt.contourf(X1,X2,Z,cmap=cmap,alpha=0.5)
#绘制
for i,class_ in enumerate(class_label):
plt.scatter(x=X[y==class_,0], y=X[y==class_,1],c=cmap.colors[i],label=class_,marker=marker[i])
plt.legend()
plt.figure(figsize=(10,6))
plot_decision_boundary(lr,x_train,y_train)
运行结果
plot_decision_boundary(lr,x_test,y_test)
运行结果
总结
逻辑回归(Logistic Regression)是⼀种⽤于⼆分类问题的监督学习算法。尽 管它带有“回归”⼀词,但实际上它⽤于分类问题。逻辑回归通过将线性组合的结果 通过⼀个sigmoid函数映射到[0, 1]的范围来进⾏分类。以下是逻辑回归算法的基本 实现步骤:
1. 导⼊必要的库:
import numpy as np
import matplotlib.pyplot as plt
2. 定义sigmoid函数:
def sigmoid(z):
return 1 / (1 + np.exp(-z))
3.定义损失函数:
逻辑回归的损失函数通常使⽤交叉熵损失函数(cross-entropy loss):
def compute_loss(y, y_pred):
m = len(y)
loss = -1/m * np.sum(y * np.log(y_pred) + (1 - y) * np.log(1 - y_pred))
return loss
4. 定义梯度下降函数:
def gradient_descent(X, y, y_pred, learning_rate):
m = len(y)
gradient = np.dot(X.T, (y_pred - y)) / m
return learning_rate * gradient
5. 训练模型:
def train(X, y, epochs, learning_rate):
m, n = X.shape
# 初始化权重和偏置
weights = np.zeros((n, 1))
bias = 0
for epoch in range(epochs):
# 计算预测值
z = np.dot(X, weights) + bias
y_pred = sigmoid(z)
# 计算损失
loss = compute_loss(y, y_pred)
# 计算梯度并更新参数
gradient = gradient_descent(X, y, y_pred, learning_rate)
weights -= gradient.reshape((n, 1))
bias -= learning_rate * np.sum(y_pred - y) / m
# 每迭代100次输出⼀次损失
if epoch % 100 == 0:
print(f'Epoch {epoch}, Loss: {loss}')
return weights, bias
6. 测试模型:
def predict(X, weights, bias):
z = np.dot(X, weights) + bias
y_pred = sigmoid(z)
return (y_pred >= 0.5).astype(int))