【机器学习】自定义数据集 使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数

一、使用pytorch框架实现逻辑回归

1. 数据部分

  • 首先自定义了一个简单的数据集,特征 X 是 100 个随机样本,每个样本一个特征,目标值 y 基于线性关系并添加了噪声。
  • 将 numpy 数组转换为 PyTorch 张量,方便后续在模型中使用。

2. 模型定义部分

方案 1:使用 nn.Sequential 直接按顺序定义了一个线性层,简洁直观。

import torch
import torch.nn as nn
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score# 自定义数据集
X = np.random.rand(100, 1).astype(np.float32)
y = 2 * X + 1 + 0.3 * np.random.randn(100, 1).astype(np.float32)# 转换为 PyTorch 张量
X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义线性回归模型
model = nn.Sequential(nn.Linear(1, 1)
)# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):# 前向传播outputs = model(X_tensor)loss = criterion(outputs, y_tensor)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 模型评估
with torch.no_grad():y_pred = model(X_tensor).numpy()mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")# 输出模型的系数和截距
print("模型系数:", model[0].weight.item())
print("模型截距:", model[0].bias.item())

方案 2:使用 nn.ModuleList 存储线性层,在 forward 方法中依次调用层进行前向传播,适合动态构建层序列。

import torch
import torch.nn as nn
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score# 自定义数据集
X = np.random.rand(100, 1).astype(np.float32)
y = 2 * X + 1 + 0.3 * np.random.randn(100, 1).astype(np.float32)# 转换为 PyTorch 张量
X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义线性回归模型
class LinearRegression(nn.Module):def __init__(self):super(LinearRegression, self).__init__()self.layers = nn.ModuleList([nn.Linear(1, 1)])def forward(self, x):for layer in self.layers:x = layer(x)return xmodel = LinearRegression()# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):# 前向传播outputs = model(X_tensor)loss = criterion(outputs, y_tensor)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 模型评估
with torch.no_grad():y_pred = model(X_tensor).numpy()mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")# 输出模型的系数和截距
print("模型系数:", model.layers[0].weight.item())
print("模型截距:", model.layers[0].bias.item())

方案 3:使用 nn.ModuleDict 以字典形式存储层,通过键名调用层,适合需要对层进行命名和灵活访问的场景。

import torch
import torch.nn as nn
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score# 自定义数据集
X = np.random.rand(100, 1).astype(np.float32)
y = 2 * X + 1 + 0.3 * np.random.randn(100, 1).astype(np.float32)# 转换为 PyTorch 张量
X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义线性回归模型
class LinearRegression(nn.Module):def __init__(self):super(LinearRegression, self).__init__()self.layers = nn.ModuleDict({'linear': nn.Linear(1, 1)})def forward(self, x):x = self.layers['linear'](x)return xmodel = LinearRegression()# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):# 前向传播outputs = model(X_tensor)loss = criterion(outputs, y_tensor)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 模型评估
with torch.no_grad():y_pred = model(X_tensor).numpy()mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")# 输出模型的系数和截距
print("模型系数:", model.layers['linear'].weight.item())
print("模型截距:", model.layers['linear'].bias.item())

方案 4:直接继承 nn.Module,在 __init__ 方法中定义线性层,在 forward 方法中实现前向传播逻辑,是最常见和基础的定义模型方式。

import torch
import torch.nn as nn
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score# 自定义数据集
X = np.random.rand(100, 1).astype(np.float32)
y = 2 * X + 1 + 0.3 * np.random.randn(100, 1).astype(np.float32)# 转换为 PyTorch 张量
X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义线性回归模型
class LinearRegression(nn.Module):def __init__(self):super(LinearRegression, self).__init__()self.linear = nn.Linear(1, 1)def forward(self, x):return self.linear(x)model = LinearRegression()# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):# 前向传播outputs = model(X_tensor)loss = criterion(outputs, y_tensor)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 模型评估
with torch.no_grad():y_pred = model(X_tensor).numpy()mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")# 输出模型的系数和截距
print("模型系数:", model.linear.weight.item())
print("模型截距:", model.linear.bias.item())

3. 训练和评估部分

  • 定义了均方误差损失函数 nn.MSELoss 和随机梯度下降优化器 torch.optim.SGD
  • 通过多个 epoch 进行训练,每个 epoch 包含前向传播、损失计算、反向传播和参数更新。
  • 训练结束后,在无梯度计算模式下进行预测,并使用 scikit-learn 的指标计算均方误差和决定系数评估模型性能,最后输出模型的系数和截距。

二、保存pytorch框架逻辑回归模型

在 PyTorch 中,有两种常见的保存模型的方式:保存模型的权重和其他参数,以及保存整个模型。下面将结合一个简单的逻辑回归模型示例,详细介绍这两种保存方式及对应的加载方法。

方式 1:保存模型的权重和其他参数

这种方式只保存模型的状态字典(state_dict),它包含了模型的所有可学习参数(如权重和偏置)。这种方法的优点是文件体积小,便于共享和迁移,缺点是加载时需要先定义模型结构。

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np# 自定义数据集
X = np.random.randn(100, 2).astype(np.float32)
y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1)X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义逻辑回归模型
class LogisticRegression(nn.Module):def __init__(self, input_size):super(LogisticRegression, self).__init__()self.linear = nn.Linear(input_size, 1)self.sigmoid = nn.Sigmoid()def forward(self, x):out = self.linear(x)out = self.sigmoid(out)return out# 初始化模型
input_size = 2
model = LogisticRegression(input_size)# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):outputs = model(X_tensor)loss = criterion(outputs, y_tensor)optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 保存模型的权重和其他参数
torch.save(model.state_dict(), 'model_weights.pth')# 加载模型的权重和其他参数
loaded_model = LogisticRegression(input_size)
loaded_model.load_state_dict(torch.load('model_weights.pth'))
loaded_model.eval()# 生成新数据进行预测
new_X = np.random.randn(10, 2).astype(np.float32)
new_X_tensor = torch.from_numpy(new_X)with torch.no_grad():predictions = loaded_model(new_X_tensor)predicted_labels = (predictions >= 0.5).float()print("预测概率:")
print(predictions.numpy())
print("预测标签:")
print(predicted_labels.numpy())

代码解释

  1. 模型训练:首先定义并训练一个逻辑回归模型。
  2. 保存模型:使用 torch.save(model.state_dict(), 'model_weights.pth') 保存模型的状态字典到文件 model_weights.pth
  3. 加载模型:先创建一个新的模型实例 loaded_model,然后使用 loaded_model.load_state_dict(torch.load('model_weights.pth')) 加载保存的状态字典。
  4. 预测:将模型设置为评估模式,生成新数据进行预测。

方式 2:保存整个模型

这种方式会保存整个模型对象,包括模型的结构和状态字典。优点是加载时不需要重新定义模型结构,缺点是文件体积较大,并且可能会受到 Python 版本和库版本的限制。

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np# 自定义数据集
X = np.random.randn(100, 2).astype(np.float32)
y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1)X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义逻辑回归模型
class LogisticRegression(nn.Module):def __init__(self, input_size):super(LogisticRegression, self).__init__()self.linear = nn.Linear(input_size, 1)self.sigmoid = nn.Sigmoid()def forward(self, x):out = self.linear(x)out = self.sigmoid(out)return out# 初始化模型
input_size = 2
model = LogisticRegression(input_size)# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):outputs = model(X_tensor)loss = criterion(outputs, y_tensor)optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 保存整个模型
torch.save(model, 'whole_model.pth')# 加载整个模型
loaded_model = torch.load('whole_model.pth')
loaded_model.eval()# 生成新数据进行预测
new_X = np.random.randn(10, 2).astype(np.float32)
new_X_tensor = torch.from_numpy(new_X)with torch.no_grad():predictions = loaded_model(new_X_tensor)predicted_labels = (predictions >= 0.5).float()print("预测概率:")
print(predictions.numpy())
print("预测标签:")
print(predicted_labels.numpy())

代码解释

  1. 模型训练:同样先定义并训练逻辑回归模型。
  2. 保存模型:使用 torch.save(model, 'whole_model.pth') 保存整个模型对象到文件 whole_model.pth
  3. 加载模型:使用 torch.load('whole_model.pth') 直接加载整个模型。
  4. 预测:将模型设置为评估模式,生成新数据进行预测。

通过以上两种方式,可以根据实际需求选择合适的模型保存和加载方法。

三、加载pytorch框架逻辑回归模型

以下将分别详细介绍在 PyTorch 中针对只保存模型参数和保存结构与参数这两种不同保存方式对应的模型加载方法,同时给出完整的代码示例。

方式 1:只保存模型参数的加载方式

当用户只保存了模型的参数(即 state_dict)时,在加载模型时需要先定义好与原模型相同结构的模型,再将保存的参数加载到该模型中。

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np# 自定义数据集
X = np.random.randn(100, 2).astype(np.float32)
y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1)X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义逻辑回归模型
class LogisticRegression(nn.Module):def __init__(self, input_size):super(LogisticRegression, self).__init__()self.linear = nn.Linear(input_size, 1)self.sigmoid = nn.Sigmoid()def forward(self, x):out = self.linear(x)out = self.sigmoid(out)return out# 初始化模型
input_size = 2
model = LogisticRegression(input_size)# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):outputs = model(X_tensor)loss = criterion(outputs, y_tensor)optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 保存模型的参数
torch.save(model.state_dict(), 'model_params.pth')# 加载模型的参数
# 重新定义模型结构
loaded_model = LogisticRegression(input_size)
# 加载保存的参数
loaded_model.load_state_dict(torch.load('model_params.pth'))
# 将模型设置为评估模式
loaded_model.eval()# 生成新数据进行预测
new_X = np.random.randn(10, 2).astype(np.float32)
new_X_tensor = torch.from_numpy(new_X)# 进行预测
with torch.no_grad():predictions = loaded_model(new_X_tensor)predicted_labels = (predictions >= 0.5).float()print("预测概率:")
print(predictions.numpy())
print("预测标签:")
print(predicted_labels.numpy())

代码解释

  1. 模型定义与训练:定义了一个简单的逻辑回归模型,并使用自定义数据集进行训练。
  2. 保存参数:使用 torch.save(model.state_dict(), 'model_params.pth') 保存模型的参数。
  3. 加载参数
    • 重新定义与原模型相同结构的 loaded_model
    • 使用 loaded_model.load_state_dict(torch.load('model_params.pth')) 加载保存的参数。
  4. 预测:将模型设置为评估模式,生成新数据进行预测。

方式 2:保存结构和参数的模型加载方式

当保存了模型的结构和参数时,加载模型就相对简单,直接使用 torch.load 函数即可加载整个模型。

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np# 自定义数据集
X = np.random.randn(100, 2).astype(np.float32)
y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1)X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义逻辑回归模型
class LogisticRegression(nn.Module):def __init__(self, input_size):super(LogisticRegression, self).__init__()self.linear = nn.Linear(input_size, 1)self.sigmoid = nn.Sigmoid()def forward(self, x):out = self.linear(x)out = self.sigmoid(out)return out# 初始化模型
input_size = 2
model = LogisticRegression(input_size)# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):outputs = model(X_tensor)loss = criterion(outputs, y_tensor)optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 保存整个模型(结构和参数)
torch.save(model, 'whole_model.pth')# 加载整个模型
loaded_model = torch.load('whole_model.pth')
# 将模型设置为评估模式
loaded_model.eval()# 生成新数据进行预测
new_X = np.random.randn(10, 2).astype(np.float32)
new_X_tensor = torch.from_numpy(new_X)# 进行预测
with torch.no_grad():predictions = loaded_model(new_X_tensor)predicted_labels = (predictions >= 0.5).float()print("预测概率:")
print(predictions.numpy())
print("预测标签:")
print(predicted_labels.numpy())

代码解释

  1. 模型定义与训练:同样定义并训练逻辑回归模型。
  2. 保存整个模型:使用 torch.save(model, 'whole_model.pth') 保存模型的结构和参数。
  3. 加载整个模型:使用 torch.load('whole_model.pth') 直接加载整个模型。
  4. 预测:将模型设置为评估模式,生成新数据进行预测。

通过以上两种方式,可以根据不同的保存情况正确加载 PyTorch 模型。

五、计算pytorch模型预测结果的精确度

在机器学习任务中,计算预测结果的精确度(Accuracy)是评估模型性能的重要指标。对于回归任务,通常使用均方误差(MSE)平均绝对误差(MAE)R² 分数 来评估模型的性能;而对于分类任务,则使用准确率(Accuracy)精确率(Precision)召回率(Recall) 等指标。

以下是如何在 PyTorch 中计算预测结果的精确度(以回归任务为例):

1. 分类任务的精确度计算

对于分类任务,常用的评估指标是准确率(Accuracy),即预测正确的样本数占总样本数的比例。

代码实现

import torch# 假设有真实标签和预测标签
y_true = torch.tensor([0, 1, 1, 0, 1, 0, 0, 1])  # 真实标签
y_pred = torch.tensor([0, 1, 0, 0, 1, 0, 1, 1])  # 预测标签# 计算准确率
accuracy = (y_true == y_pred).float().mean()
print(f"准确率: {accuracy.item():.4f}")

 2. 回归任务的精确度计算

对于回归任务,常用的评估指标包括:

  • 均方误差(MSE):预测值与真实值之间差异的平方的平均值。

  • 平均绝对误差(MAE):预测值与真实值之间差异的绝对值的平均值。

  • R² 分数:表示模型对数据的拟合程度,取值范围为 [0, 1],越接近 1 表示模型越好。

代码实现

import torch
import torch.nn as nn# 假设有真实值和预测值
y_true = torch.tensor([3.0, 5.0, 7.0, 9.0], dtype=torch.float32)
y_pred = torch.tensor([2.8, 5.1, 7.2, 8.9], dtype=torch.float32)# 计算均方误差 (MSE)
mse = nn.MSELoss()(y_pred, y_true)
print(f"Mean Squared Error (MSE): {mse.item():.4f}")# 计算平均绝对误差 (MAE)
mae = nn.L1Loss()(y_pred, y_true)
print(f"Mean Absolute Error (MAE): {mae.item():.4f}")# 计算 R² 分数
def r2_score(y_true, y_pred):ss_total = torch.sum((y_true - torch.mean(y_true)) ** 2)ss_residual = torch.sum((y_true - y_pred) ** 2)r2 = 1 - (ss_residual / ss_total)return r2r2 = r2_score(y_true, y_pred)
print(f"R²分数: {r2.item():.4f}")

六、计算pytorch模型预测结果的召回率

1. 召回率的定义

在分类任务中,召回率(Recall) 是一个重要的评估指标,用于衡量模型对正类样本的识别能力。召回率的定义是:

Recall= \frac{True Positives (TP)}{True Positives (TP)+False Negatives (FN)}

其中:

  • True Positives (TP):模型正确预测为正类的样本数。

  • False Negatives (FN):模型错误预测为负类的正类样本数。

2. 计算召回率的步骤

  1. 获取真实标签和预测标签

  • 真实标签(y_true):数据集中样本的真实类别。
  • 预测标签(y_pred):模型对样本的预测类别。
  1. 计算混淆矩阵

  • 通过比较 y_true 和 y_pred,计算混淆矩阵中的 TP 和 FN。
  1. 计算召回率

        使用公式 Recall= \frac{TP}{TP+FN} 计算召回率。

3. 二分类任务召回率代码

  • 对于二分类任务,召回率衡量模型对正类样本的识别能力。

import torch# 假设有真实标签和预测标签
y_true = torch.tensor([0, 1, 1, 0, 1, 0, 0, 1])  # 真实标签
y_pred = torch.tensor([0, 1, 0, 0, 1, 0, 1, 1])  # 预测标签# 计算混淆矩阵
def confusion_matrix(y_true, y_pred):TP = ((y_true == 1) & (y_pred == 1)).sum().item()  # 模型正确预测为正类的样本数FN = ((y_true == 1) & (y_pred == 0)).sum().item()  # 模型错误预测为负类的正类样本数FP = ((y_true == 0) & (y_pred == 1)).sum().item()  # 模型错误预测为正类的正类样本数TN = ((y_true == 0) & (y_pred == 0)).sum().item()  # 模型正确预测为负类的样本数return TP, FN, FP, TN# 计算召回率
def recall_score(y_true, y_pred):TP, FN, _, _ = confusion_matrix(y_true, y_pred)if TP + FN == 0:return 0.0  # 避免除以零return TP / (TP + FN)# 计算召回率
recall = recall_score(y_true, y_pred)
print(f"召回率: {recall:.4f}")

 4. 多分类任务召回率代码

  • 对于多分类任务,可以分别计算每个类别的召回率,然后取平均值。

import torch# 假设有真实标签和预测标签(多分类任务)
y_true = torch.tensor([0, 1, 2, 0, 1, 2])  # 真实标签
y_pred = torch.tensor([0, 1, 0, 0, 1, 2])  # 预测标签# 计算每个类别的召回率
def recall_score_multiclass(y_true, y_pred, num_classes):recall_scores = []for cls in range(num_classes):TP = ((y_true == cls) & (y_pred == cls)).sum().item()  # 模型正确预测为正类的样本数FN = ((y_true == cls) & (y_pred != cls)).sum().item()  # 模型错误预测为负类的正类样本数if TP + FN == 0:recall_scores.append(0.0)  # 避免除以零else:recall_scores.append(TP / (TP + FN))return recall_scores# 计算召回率
num_classes = 3
recall_scores = recall_score_multiclass(y_true, y_pred, num_classes)
for cls, recall in enumerate(recall_scores):print(f"每个类别的召回率 {cls}: {recall:.4f}")# 计算宏平均召回率
macro_recall = sum(recall_scores) / num_classes
print(f"宏平均召回率: {macro_recall:.4f}")

七、计算pytorch模型预测结果的F1分数

1. F1分数的定义

F1 分数(F1 Score) 是分类任务中常用的评估指标,结合了 精确率(Precision) 和 召回率(Recall) 的信息。F1 分数的定义是:

F1 Score= 2\times \frac{Precision\times ×Recall}{Precision+Recall}

其中:

  • 精确率(Precision):预测为正类的样本中,实际为正类的比例。

  • 召回率(Recall):实际为正类的样本中,预测为正类的比例。

F1 分数的取值范围为 [0, 1],越接近 1 表示模型性能越好。

2. 计算 F1 分数的步骤

  1. 获取真实标签和预测标签

  • 真实标签(y_true):数据集中样本的真实类别。
  • 预测标签(y_pred):模型对样本的预测类别。
  1. 计算混淆矩阵

  • 通过比较 y_true 和 y_pred,计算混淆矩阵中的 TP、FP 和 FN。
  1. 计算精确率和召回率

  • 精确率:

Precision=\frac{TP}{TP+FP}

  • 召回率:

Recall=\frac{TP}{TP+FN}

  1. 计算 F1 分数

  • 使用公式:

F1 Score= 2\times \frac{Precision\times ×Recall}{Precision+Recall}

3. 二分类任务F1分数代码

  • 对于二分类任务,F1 分数结合了精确率和召回率,是评估模型性能的重要指标。

import torch# 假设有真实标签和预测标签
y_true = torch.tensor([0, 1, 1, 0, 1, 0, 0, 1])  # 真实标签
y_pred = torch.tensor([0, 1, 0, 0, 1, 0, 1, 1])  # 预测标签# 计算混淆矩阵
def confusion_matrix(y_true, y_pred):TP = ((y_true == 1) & (y_pred == 1)).sum().item()  # 模型正确预测为正类的样本数FN = ((y_true == 1) & (y_pred == 0)).sum().item()  # 模型错误预测为负类的正类样本数FP = ((y_true == 0) & (y_pred == 1)).sum().item()  # 模型错误预测为正类的正类样本数TN = ((y_true == 0) & (y_pred == 0)).sum().item()  # 模型正确预测为负类的样本数return TP, FN, FP, TN# 计算 F1 分数
def f1_score(y_true, y_pred):TP, FN, FP, _ = confusion_matrix(y_true, y_pred)# 计算精确率和召回率precision = TP / (TP + FP) if (TP + FP) > 0 else 0.0recall = TP / (TP + FN) if (TP + FN) > 0 else 0.0# 计算 F1 分数if precision + recall == 0:return 0.0  # 避免除以零f1 = 2 * (precision * recall) / (precision + recall)return f1# 计算 F1 分数
f1 = f1_score(y_true, y_pred)
print(f"F1分数: {f1:.4f}")

4. 多分类任务F1分数代码

  • 对于多分类任务,可以分别计算每个类别的 F1 分数,然后取平均值。

import torch# 假设有真实标签和预测标签(多分类任务)
y_true = torch.tensor([0, 1, 2, 0, 1, 2])  # 真实标签
y_pred = torch.tensor([0, 1, 0, 0, 1, 2])  # 预测标签# 计算每个类别的 F1 分数
def f1_score_multiclass(y_true, y_pred, num_classes):f1_scores = []for cls in range(num_classes):TP = ((y_true == cls) & (y_pred == cls)).sum().item()  # 模型正确预测为正类的样本数FN = ((y_true == cls) & (y_pred != cls)).sum().item()  # 模型错误预测为负类的正类样本数FP = ((y_true != cls) & (y_pred == cls)).sum().item()  # 模型错误预测为正类的正类样本数# 计算精确率和召回率precision = TP / (TP + FP) if (TP + FP) > 0 else 0.0recall = TP / (TP + FN) if (TP + FN) > 0 else 0.0# 计算 F1 分数if precision + recall == 0:f1_scores.append(0.0)  # 避免除以零else:f1_scores.append(2 * (precision * recall) / (precision + recall))return f1_scores# 计算 F1 分数
num_classes = 3
f1_scores = f1_score_multiclass(y_true, y_pred, num_classes)
for cls, f1 in enumerate(f1_scores):print(f"每个类别的F1分数 {cls}: {f1:.4f}")# 计算宏平均 F1 分数
macro_f1 = sum(f1_scores) / num_classes
print(f"宏平均 F1 分数: {macro_f1:.4f}")

八、完整流程(使用直接继承 nn.Module逻辑回归,且仅保存模型的权重和其他参数,计算了二分类任务的精确度、召回率及F1分数)

1. 实现思路

① 自定义数据集

生成 100 个样本,每个样本有 2 个特征。

根据特征生成标签,使用简单的线性组合和阈值判断。

② 定义逻辑回归模型

使用 nn.Linear 定义一个线性层,并通过  实现逻辑回归。

③ 训练模型

使用二元交叉熵损失 (nn.BCELoss) 和随机梯度下降优化器 (optim.SGD) 训练模型。

④ 保存模型

使用 torch.save 保存模型参数。

⑤ 加载模型

使用 torch.load 加载模型参数。

⑥ 预测

加载模型后,使用新数据进行预测,并将概率转换为类别(0 或 1)。

⑦ 评估模型

计算模型的精确度、召回率和 F1 分数。

2. 代码示例

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np# 自定义数据集
# 生成 100 个样本,每个样本有 2 个特征
X = np.random.randn(100, 2).astype(np.float32)
# 根据特征生成标签,使用简单的线性组合和阈值判断
y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1)# 将 numpy 数组转换为 PyTorch 张量
X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)# 定义逻辑回归模型
class LogisticRegression(nn.Module):def __init__(self, input_size):super(LogisticRegression, self).__init__()self.linear = nn.Linear(input_size, 1)self.sigmoid = nn.Sigmoid()def forward(self, x):out = self.linear(x)out = self.sigmoid(out)return out# 初始化模型
input_size = 2
model = LogisticRegression(input_size)# 定义损失函数和优化器
criterion = nn.BCELoss()  # 二元交叉熵损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):# 前向传播outputs = model(X_tensor)loss = criterion(outputs, y_tensor)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 保存模型
torch.save(model.state_dict(), 'logistic_regression_model.pth')# 加载模型
loaded_model = LogisticRegression(input_size)
loaded_model.load_state_dict(torch.load('logistic_regression_model.pth'))
loaded_model.eval()# 生成新数据进行预测
new_X = np.random.randn(10, 2).astype(np.float32)
new_X_tensor = torch.from_numpy(new_X)# 使用加载的模型进行预测
with torch.no_grad():predictions = loaded_model(new_X_tensor)predicted_labels = (predictions >= 0.5).float()print("预测概率:")
print(predictions.numpy())
print("预测标签:")
print(predicted_labels.numpy())# 计算精确度、召回率和 F1 分数
def evaluate_model(y_true, y_pred):# 计算混淆矩阵TP = ((y_true == 1) & (y_pred == 1)).sum().item()  # 模型正确预测为正类的样本数FN = ((y_true == 1) & (y_pred == 0)).sum().item()  # 模型错误预测为负类的正类样本数FP = ((y_true == 0) & (y_pred == 1)).sum().item()  # 模型错误预测为正类的正类样本数TN = ((y_true == 0) & (y_pred == 0)).sum().item()  # 模型正确预测为负类的样本数# 计算精确度、召回率和 F1 分数accuracy = (TP + TN) / (TP + TN + FP + FN) if (TP + TN + FP + FN) > 0 else 0.0precision = TP / (TP + FP) if (TP + FP) > 0 else 0.0recall = TP / (TP + FN) if (TP + FN) > 0 else 0.0f1 = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0.0return accuracy, precision, recall, f1# 对训练集进行预测,计算评估指标
with torch.no_grad():train_predictions = loaded_model(X_tensor)train_predicted_labels = (train_predictions >= 0.5).float()# 计算评估指标
accuracy, precision, recall, f1 = evaluate_model(y_tensor, train_predicted_labels)# 输出结果
print("\n模型评估结果:")
print(f"精确度: {accuracy:.4f}")
print(f"精确率: {precision:.4f}")
print(f"召回率: {recall:.4f}")
print(f"F1分数: {f1:.4f}")

3. 代码解释 

① 数据集生成:

  • X = np.random.randn(100, 2).astype(np.float32):生成 100 个样本,每个样本有 2 个特征。
  • y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1):根据特征的线性组合生成标签,大于 0 标记为 1,否则标记为 0。
  • X_tensor = torch.from_numpy(X) 和 y_tensor = torch.from_numpy(y):将 numpy 数组转换为 PyTorch 张量。

② 模型定义:

  • LogisticRegression 类继承自 nn.Module,包含一个线性层 nn.Linear 和一个 Sigmoid 激活函数 nn.Sigmoid
  • forward 方法定义了前向传播的逻辑。

③ 损失函数和优化器:

  • criterion = nn.BCELoss():使用二元交叉熵损失函数,适用于二分类问题。
  • optimizer = optim.SGD(model.parameters(), lr=0.01):使用随机梯度下降优化器,学习率为 0.01。

④ 模型训练:

  • 通过多次迭代进行前向传播、损失计算、反向传播和参数更新。
  • 每 100 个 epoch 打印一次损失值。

⑤ 模型保存:

  • torch.save(model.state_dict(), 'logistic_regression_model.pth'):保存模型的参数到本地文件 logistic_regression_model.pth

⑥ 模型加载和预测:

  1. loaded_model = LogisticRegression(input_size):创建一个新的模型实例。
  2. loaded_model.load_state_dict(torch.load('logistic_regression_model.pth')):加载保存的模型参数。
  3. loaded_model.eval():将模型设置为评估模式。
  4. 生成新数据 new_X 并转换为张量 new_X_tensor
  5. 使用 loaded_model 进行预测,通过 (predictions >= 0.5).float() 将预测概率转换为标签。

⑦ 模型评估

  • 定义 evaluate_model 函数:

        计算混淆矩阵(TP、FN、FP、TN)。

        计算精确度、精确率、召回率和 F1 分数。

  • 对训练集进行预测并计算评估指标:

        train_predictions = loaded_model(X_tensor):计算训练集的预测概率。

        train_predicted_labels = (train_predictions >= 0.5).float():将预测概率转换为标签。

  • 输出评估结果:

        精确度(Accuracy):模型预测正确的样本比例。

        精确率(Precision):预测为正类的样本中,实际为正类的比例。

        召回率(Recall):实际为正类的样本中,预测为正类的比例。

        F1 分数(F1 Score):精确率和召回率的调和平均值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/894350.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高性能消息队列Disruptor

定义一个事件模型 之后创建一个java类来使用这个数据模型。 /* <h1>事件模型工程类&#xff0c;用于生产事件消息</h1> */ no usages public class EventMessageFactory implements EventFactory<EventMessage> { Overridepublic EventMessage newInstance(…

Java线程认识和Object的一些方法ObjectMonitor

专栏系列文章地址&#xff1a;https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标&#xff1a; 要对Java线程有整体了解&#xff0c;深入认识到里面的一些方法和Object对象方法的区别。认识到Java对象的ObjectMonitor&#xff0c;这有助于后面的Synchron…

基于YOLO11的肺结节检测系统

基于YOLO11的肺结节检测系统 (价格90) LUNA16数据集 数据一共 1186张 按照8&#xff1a;1&#xff1a;1随机划分训练集&#xff08;948张&#xff09;、验证集&#xff08;118张&#xff09;与测试集&#xff08;120张&#xff09; 包含 nodule 肺结节 1种…

C++ Primer 自定义数据结构

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

《AI大模型开发笔记》DeepSeek技术创新点

一、DeepSeek横空出世 DeepSeek V3 以颠覆性技术架构创新强势破局&#xff01;革命性的上下文处理机制实现长文本推理成本断崖式下降&#xff0c;综合算力需求锐减90%&#xff0c;开启高效 AI 新纪元&#xff01; 最新开源的 DeepSeek V3模型不仅以顶尖基准测试成绩比肩业界 …

数仓实战项目,大数据数仓实战(离线数仓+实时数仓)

1.课程目标 2.电商行业与电商系统介绍 3.数仓项目整体技术架构介绍 4.数仓项目架构-kylin补充 5.数仓具体技术介绍与项目环境介绍 6.kettle的介绍与安装 7.kettle入门案例 这个连线是点击shift键&#xff0c;然后鼠标左键拖动 ctrls保存一下 csv输入配置 Excel输出配置 配置完 …

Spring Web MVC基础第一篇

目录 1.什么是Spring Web MVC&#xff1f; 2.创建Spring Web MVC项目 3.注解使用 3.1RequestMapping&#xff08;路由映射&#xff09; 3.2一般参数传递 3.3RequestParam&#xff08;参数重命名&#xff09; 3.4RequestBody&#xff08;传递JSON数据&#xff09; 3.5Pa…

sobel边缘检测算法

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 Sobel边缘检测算法是一种用于图像处理中的边缘检测方法&#xff0c;它能够突出图像中灰度变化剧烈的地方&#xff0c;也就是边缘。该算法通过计算图像在水平方向和垂直方向上的梯度来检测边缘&#xff0c;梯度值越大…

Google Chrome-便携增强版[解压即用]

Google Chrome-便携增强版 链接&#xff1a;https://pan.xunlei.com/s/VOI0OyrhUx3biEbFgJyLl-Z8A1?pwdf5qa# a 特点描述 √ 无升级、便携式、绿色免安装&#xff0c;即可以覆盖更新又能解压使用&#xff01; √ 此增强版&#xff0c;支持右键解压使用 √ 加入Chrome增强…

分布式数据库架构与实践:原理、设计与优化

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 随着大数据和云计算的快速发展&#xff0c;传统单机数据库已难以满足大规模数据存储和高并发访问的需求。分布式数据库&…

设计模式Python版 桥接模式

文章目录 前言一、桥接模式二、桥接模式示例三、桥接模式与适配器模式的联用 前言 GOF设计模式分三大类&#xff1a; 创建型模式&#xff1a;关注对象的创建过程&#xff0c;包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式&…

【C语言】main函数解析

文章目录 一、前言二、main函数解析三、代码示例四、应用场景 一、前言 在学习编程的过程中&#xff0c;我们很早就接触到了main函数。在Linux系统中&#xff0c;当你运行一个可执行文件&#xff08;例如 ./a.out&#xff09;时&#xff0c;如果需要传入参数&#xff0c;就需要…

CSS核心

CSS的引入方式 内部样式表是在 html 页面内部写一个 style 标签&#xff0c;在标签内部编写 CSS 代码控制整个 HTML 页面的样式。<style> 标签理论上可以放在 HTML 文档的任何地方&#xff0c;但一般会放在文档的 <head> 标签中。 <style> div { color: r…

变量的作用域和生命周期

一、根据变量的作用域不同&#xff0c;可分为 局部变量 和 全局变量 1. 作用域&#xff1a;变量起作用的范围&#xff08;变量定义之后&#xff0c;在哪里可以访问变量&#xff09;。 就近原则&#xff1a;当不同作用域里面有两个或者多个同名变量&#xff0c;那么遵循就近原…

力扣【669. 修剪二叉搜索树】Java题解

一开始在想为什么题目说存在唯一答案。然后发现是二叉搜索树就合理了。如下图&#xff1a;如果0节点小于low&#xff0c;那其左子树也都小于low&#xff0c;故可以排除&#xff1b;对于4&#xff0c;其右子树也是可以排除。 代码如下&#xff1a; class Solution {public Tre…

论文阅读:Realistic Noise Synthesis with Diffusion Models

这篇文章是 2025 AAAI 的一篇工作&#xff0c;主要介绍的是用扩散模型实现对真实噪声的仿真模拟 Abstract 深度去噪模型需要大量来自现实世界的训练数据&#xff0c;而获取这些数据颇具挑战性。当前的噪声合成技术难以准确模拟复杂的噪声分布。我们提出一种新颖的逼真噪声合成…

群晖Alist套件无法挂载到群晖webdav,报错【连接被服务器拒绝】

声明&#xff1a;我不是用docker安装的 在套件中心安装矿神的Alist套件后&#xff0c;想把夸克挂载到群晖上&#xff0c;方便复制文件的&#xff0c;哪知道一直报错&#xff0c;最后发现问题出在两个地方&#xff1a; 1&#xff09;挂载的路径中&#xff0c;直接填 dav &…

玩转大语言模型——配置图数据库Neo4j(含apoc插件)并导入GraphRAG生成的知识图谱

系列文章目录 玩转大语言模型——使用langchain和Ollama本地部署大语言模型 玩转大语言模型——ollama导入huggingface下载的模型 玩转大语言模型——langchain调用ollama视觉多模态语言模型 玩转大语言模型——使用GraphRAGOllama构建知识图谱 玩转大语言模型——完美解决Gra…

全程Kali linux---CTFshow misc入门(25-37)

第二十五题&#xff1a; 提示&#xff1a;flag在图片下面。 直接检查CRC&#xff0c;检测到错误&#xff0c;就直接暴力破解。 暴力破解CRC的python代码。 import binascii import struct def brute_force_ihdr_crc(filename): # 读取文件二进制数据 with open(filen…

对比DeepSeek、ChatGPT和Kimi的学术写作撰写引言能力

引言 引言部分引入研究主题&#xff0c;明确研究背景、问题陈述&#xff0c;并提出研究的目的和重要性&#xff0c;最后&#xff0c;概述研究方法和论文结构。 下面我们使用DeepSeek、ChatGPT4以及Kimi辅助引言撰写。 提示词&#xff1a; 你现在是一名[计算机理论专家]&#…