二分类逻辑回归(Logistic Regression)是一种广泛应用于二分类问题的统计模型。尽管名字中带有“回归”二字,但它实际上是一种分类算法。逻辑回归通过拟合一个 S 形曲线(Sigmoid 函数)来预测样本属于某一类别的概率。
逻辑回归(Logistic Regression)是一种广泛应用于二分类问题的统计模型。尽管名字中带有“回归”二字,但它实际上是一种分类算法。逻辑回归通过拟合一个 S 形曲线(Sigmoid 函数)来预测样本属于某一类别的概率。
逻辑回归的基本原理
-
线性组合:
逻辑回归首先计算输入特征的线性组合。假设输入特征向量为x=[x1,x2,…,xn]\mathbf{x} = [x_1, x_2, \ldots, x_n]x=[x1,x2,…,xn],权重向量为w=[w1,w2,…,wn\mathbf{w} = [w_1, w_2, \ldots, w_nw=[w1,w2,…,wn],偏置为bbb,则线性组合可以表示为:
z=w⊤x+b z = \mathbf{w}^\top \mathbf{x} + b z=w⊤x+b
-
Sigmoid 函数:
线性组合zzz 通过 Sigmoid 函数(也称为 Logistic 函数)转换为一个概率值。Sigmoid 函数的公式为:
σ(z)=11+e−z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e−z1
Sigmoid 函数将任意实数映射到 (0, 1) 区间内,表示样本属于某一类别的概率。
-
预测:
模型的预测输出为:
y^=σ(w⊤x+b) \hat{y} = \sigma(\mathbf{w}^\top \mathbf{x} + b) y^=σ(w⊤x+b)
通常,如果y^>0.5\hat{y} > 0.5y^>0.5,则预测样本属于正类(1);否则,预测样本属于负类(0)。
损失函数
逻辑回归通常使用二元交叉熵损失函数(Binary Cross Entropy Loss)来衡量模型预测值与真实标签之间的差异。二元交叉熵损失函数的公式为:
其中,(y 是真实标签(0 或 1),(y^\hat{y}y^ 是模型的预测概率。
BCE(y,y^)=−[ylog(y^)+(1−y)log(1−y^)]
\text{BCE}(y, \hat{y}) = -\left[ y \log(\hat{y}) + (1 - y) \log(1 - \hat{y}) \right]
BCE(y,y^)=−[ylog(y^)+(1−y)log(1−y^)]
其中,(y 是真实标签(0 或 1),(y^\hat{y}y^ 是模型的预测概率。
优化
逻辑回归模型的训练过程通常使用梯度下降法(或其变种,如随机梯度下降、小批量梯度下降等)来最小化损失函数。具体步骤如下:
-
前向传播:
- 计算线性组合z=w⊤x+bz = \mathbf{w}^\top \mathbf{x} + bz=w⊤x+b。
- 通过 Sigmoid 函数计算预测概率\hat{y} = \sigma(z)。
-
计算损失:
- 使用二元交叉熵损失函数计算损失值。
-
反向传播:
- 计算损失对模型参数的梯度。
- 更新模型参数,通常使用优化器(如 SGD、Adam 等)。
代码
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# 生成模拟数据
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
X_train = torch.tensor(X_train, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.float32).view(-1, 1)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_test = torch.tensor(y_test, dtype=torch.float32).view(-1, 1)
# 定义逻辑回归模型
class LogisticRegression(nn.Module):
def __init__(self, input_dim):
super(LogisticRegression, self).__init__()
self.linear = nn.Linear(input_dim, 1)
def forward(self, x):
return torch.sigmoid(self.linear(x))
input_dim = X_train.shape[1]
model = LogisticRegression(input_dim)
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 训练模型
num_epochs = 100
for epoch in range(num_epochs):
model.train()
optimizer.zero_grad()
outputs = model(X_train)
loss = criterion(outputs, y_train)
loss.backward()
optimizer.step()
if (epoch+1) % 10 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
# 评估模型
model.eval()
with torch.no_grad():
y_pred = model(X_test)
y_pred_class = (y_pred > 0.5).float()
accuracy = (y_pred_class == y_test).float().mean()
print(f'Test Accuracy: {accuracy:.4f}')
对代码的解释
数据生成:
- 这段代码中使用了哪些库来生成和处理数据?
- 主要使用的库有
sklearn和torch。sklearn用于生成和处理数据,torch用于构建和训练模型。
- 主要使用的库有
make_classification函数的作用是什么?它的主要参数有哪些?make_classification是sklearn.datasets模块中的一个函数,用于生成模拟的分类数据集。主要参数包括:n_samples:生成的样本数。n_features:每个样本的特征数。n_classes:类别数。random_state:随机种子,确保每次生成的数据相同。
数据预处理:
train_test_split函数的作用是什么?它的主要参数有哪些?train_test_split是sklearn.model_selection模块中的一个函数,用于将数据集划分为训练集和测试集。主要参数包括:test_size:测试集的比例。random_state:随机种子,确保每次划分的结果相同。
StandardScaler的作用是什么?为什么需要对数据进行标准化处理?StandardScaler是sklearn.preprocessing模块中的一个类,用于对数据进行标准化处理,即将数据缩放到零均值和单位方差。标准化处理可以加速模型的收敛速度,提高模型的性能,特别是对于基于梯度的优化算法。- 之所以只对训练数据标准化是因为,实际生活中,未来应用在模型上的数据一般是不可见的,这些数据不应该贸然标准化,所以在测试模型时,也不应该标准化测试数据集。
数据转换:
- 为什么需要将数据从NumPy数组转换为PyTorch张量?
- PyTorch 是一个深度学习框架,它使用张量(Tensor)作为其主要数据结构。将数据从NumPy数组转换为PyTorch张量是为了能够在PyTorch的模型中直接使用这些数据。
dtype=torch.float32和.view(-1, 1)的作用分别是什么?dtype=torch.float32:指定张量的数据类型为32位浮点数,这是大多数深度学习模型的标准数据类型。.view(-1, 1):改变张量的形状。-1表示自动计算该维度的大小,1表示将张量的第二个维度设置为1。y_train和y_test都是通过torch.tensor创建的张量,初始形状是一维的。原因是因为y_train与模型的输出形状匹配,通常需要将它 reshape 成二维张量,而y_test因为在BECloss函数中需要模型输出和标签真实值进行匹配的计算,所以y_test也得变成更y_train一样的形状。而模型之所以输出的形状是二维的是因为nn.Linear`的输出是二维的。
模型定义:
LogisticRegression类继承自哪个基类?为什么需要继承这个基类?
LogisticRegression类继承自nn.Module。nn.Module是 PyTorch 中所有神经网络模块的基类,继承自nn.Module可以方便地定义和管理模型的参数、前向传播过程等。
nn.Linear和torch.sigmoid的作用分别是什么?
nn.Linear:定义一个全连接层,用于线性变换。参数input_dim和1分别表示输入特征的维度和输出特征的维度。此全连接层的目的是将一个矩阵线性变化变成y = XW + b,其中W是权重矩阵,b是偏置矩阵,权重矩阵W和偏置向量b就是模型训练中的参数torch.sigmoid:激活函数,将线性变换的结果映射到 (0, 1) 区间,常用于二分类问题。sigmoid(z)=1/(1+exp(−z))sigmoid(z) = 1 / (1 + exp(-z))sigmoid(z)=1/(1+exp(−z))

损失函数和优化器:
-
model.parameters():需要优化的模型参数。- 深度学习的参数是指模型在训练过程中需要学习和优化的变量。这些参数通常包括线性层的权重和偏置、卷积层的滤波器权重等。通过优化这些参数,模型可以逐渐拟合训练数据,从而在测试数据上表现更好。,通过保留这些参数可以简易的保存模型。
model.parameters()返回一个生成器,生成器可以迭代访问模型中所有需要优化的参数。而这些参数通常是以torch.Tensor对象的形式存在,每个张量包含一组参数值。- 使用场景
- 优化器:在定义优化器时,需要传入模型的参数,以便优化器知道哪些参数需要更新。
- 梯度计算:在反向传播过程中,计算梯度时需要访问这些参数。
- 参数初始化:在模型初始化时,可以对这些参数进行初始化。
-
nn.BCELoss是什么?它适用于哪种类型的任务?nn.BCELoss是二元交叉熵损失函数,适用于二分类问题。它计算预测值和真实值之间的平均二元交叉熵损失。
-
optim.SGD是什么?它的主要参数有哪些?-
optim.SGD是随机梯度下降优化器,用于更新模型参数以最小化损失函数。主要参数包括:-
model.parameters():需要优化的模型参数。 -
lr:学习率,控制参数更新的步长。-
学习率的基本概念
-
学习率是一个正数,通常表示为
lr。在每次参数更新时,学习率决定了参数调整的幅度。 -
更新规则通常如下:
θnew=θold−lr×∂L∂θ \theta_{\text{new}} = \theta_{\text{old}} - \text{lr} \times \frac{\partial L}{\partial \theta} θnew=θold−lr×∂θ∂L∂L∂θ\frac{\partial L}{\partial \theta}∂θ∂L 是损失函数对参数的梯度。
-
作用:控制更新步长:学习率越大,参数更新的步长越大,模型可能更快地收敛,但也可能跳过最优解。影响收敛速度:学习率适中时,模型可以稳定地收敛到最优解;学习率太小时,模型收敛速度慢;学习率太大时,模型可能无法收敛,甚至发散。
-
学习率可以甚至为固定的值,也可以动态变化。固定值的设置可以通过多次实验的结果进行设置
-
-
-
-
模型训练:
model.train()和model.eval()的区别是什么?model.train():将模型设置为训练模式,启用如Dropout和BatchNorm等在训练过程中需要的行为。model.eval():将模型设置为评估模式,禁用如Dropout和BatchNorm等在训练过程中需要的行为。
optimizer.zero_grad()和optimizer.step()的作用分别是什么?optimizer.zero_grad():清零梯度,防止梯度累积。梯度清零的原因是因为每个批次的梯度应该独立计算,反映当前批次数据对模型参数的贡献。不清零梯度会导致不同批次之间的梯度相互影响,破坏每个批次的独立性。而且不清零梯度会导致梯度值不断累积,存在梯度爆炸的风险,占用越来越多的内存。optimizer.step():根据计算出的梯度更新模型参数。
前向传播和反向传播:
outputs = model(X_train)这行代码做了什么?- 调用模型的
forward方法,计算输入X_train的前向传播结果,即模型的预测输出。
- 调用模型的
loss.backward()的作用是什么?- 计算损失函数相对于模型参数的梯度,并将梯度存储在参数的
grad属性中。
- 计算损失函数相对于模型参数的梯度,并将梯度存储在参数的
训练过程中的输出:
if (epoch+1) % 10 == 0:这行代码的作用是什么?- 每10个epoch输出一次当前的损失值,用于监控训练过程。
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')这行代码的格式化字符串中,{loss.item():.4f}表示什么?{loss.item():.4f}:将loss张量转换为标量,并保留四位小数,用于输出当前的损失值。
模型评估:
-
with torch.no_grad():的作用是什么?with torch.no_grad():临时禁用梯度计算,用于评估模型时节省内存和计算资源。
-
(y_pred > 0.5).float()这行代码做了什么?- 比较操作:
y_pred > 0.5y_pred:这是模型的预测输出,通常是一个包含概率值的张量,每个元素的值在 0 到 1 之间。y_pred > 0.5:这是一个布尔操作,将y_pred中的每个元素与 0.5 进行比较。如果某个元素大于 0.5,则返回True;否则返回False。
- 类型转换:
.float()True和False的结果是一个布尔张量,.float()方法将布尔张量转换为浮点张量。在 PyTorch 中,布尔值True被转换为1.0,布尔值False被转换为0.0。
- 比较操作:
-
accuracy = (y_pred_class == y_test).float().mean()这行代码计算的是什么?- 计算模型在测试集上的准确率。
(y_pred_class == y_test).float()生成一个布尔张量,表示预测结果与真实标签是否一致,将其转换为浮点数(True为1,False为0),然后计算平均值,得到准确率。
- 计算模型在测试集上的准确率。
-
为什么使用
mean()来计算准确率?mean()计算张量中所有元素的平均值。在这里,张量中的每个元素表示一个样本的预测是否正确,因此平均值就是正确预测的样本比例,即准确率。
1854

被折叠的 条评论
为什么被折叠?



