Logistic regression for Pytorch
在此之前回顾一下当前的一些可能涉及到的细节问题。在反向传播时需要通过链式法则对损失函数进行对参数求导更新,通过使用梯度下降设置学习率进行参数更新.
1-自定义数据集
import torch
# 生成 1000 个 3 维的随机数作为特征
X = torch.randn((1000, 3))
# 设定真实的权重和偏置,作为生成标签的依据
true_w = torch.tensor([2, -3, 4], dtype=torch.float32)
true_b = torch.tensor([4.2], dtype=torch.float32)
# 生成标签,使用 sigmoid 函数将标签转化为 0 或 1
h = torch.mm(X, true_w.reshape(-1, 1)) + true_b
Y = 1 / (1 + torch.exp(-h))
labels = torch.where(Y > 0.5, torch.tensor([1], dtype=torch.float32), torch.tensor([0], dtype=torch.float32))
#labels = (Y > 0.5).float()# 简化代码
2-模型函数和损失函数
# 定义自定义 sigmoid 函数
#torch.sigmoid(logits)
def sigmoid(x):
return 1 / (1 + torch.exp(-x))
# 定义自定义损失函数 交叉熵
#torch.nn.functional.binary_cross_entropy(Y_pred, labels.float())
def binary_cross_entropy_loss(Y_pred, Y_true):
loss = -torch.mean(Y_true * torch.log(Y_pred) + (1 - Y_true) * torch.log(1 - Y_pred))
return loss
3-优化算法梯度下降
requires_grad 属性设为 True,表示需要计算梯度
loss.backward():计算当前梯度。
with torch.no_grad()::开启一个上下文管理器,表示后面的操作不需要计算梯度。
# 定义自定义梯度下降函数 learning_rate 学习率 num_iterations 迭代次数
def gradient_descent(X, Y_true, learning_rate, num_iterations):
# 初始化参数 w 和 b
w = torch.randn((X.shape[1], 1), dtype=torch.float32, requires_grad=True)
b = torch.randn((1, 1), dtype=torch.float32, requires_grad=True)
#训练迭代
for i in range(num_iterations):
# 计算预测值 Y_pred 和损失函数
Y_pred = sigmoid(torch.mm(X, w) + b)
loss = binary_cross_entropy_loss(Y_pred, Y_true)
#反向传播
# 计算损失函数对参数的梯度,并更新参数
loss.backward()#
with torch.no_grad():
w -= learning_rate * w.grad#更新参数
b -= learning_rate * b.grad
# 清空梯度 缓存,避免梯度累积
w.grad.zero_()
b.grad.zero_()
# 每 100 次迭代打印一次损失函数的值
if (i + 1) % 100 == 0:
print("Iteration [{}/{}], Loss: {:.4f}".format(i + 1, num_iterations, loss.item()))
return w, b
4-调用梯度下降函数进行模型训练
# 调用梯度下降函数进行模型训练
learning_rate = 0.01
num_iterations = 1000
w, b = gradient_descent(X, labels, learning_rate, num_iterations)
# 打印训练得到的权重和偏置
print("Weight:", w.reshape(-1).detach().numpy())
print("Bias:", b.reshape(-1).detach().numpy())
#detach() 方法用于将张量从计算图中分离出来 将其转化为CPU上的NumPy数组