【从0到1搞懂大模型】神经网络的实现:数据策略、模型调优与评估体系(3)
一、数据集的划分
(1)按一定比例划分为训练集和测试集
我们通常取8-2、7-3、6-4、5-5比例切分,直接将数据随机划分为训练集和测试集,然后使用训练集来生成模型,再用测试集来测试模型的正确率和误差,以验证模型的有效性。
这种方法常见于决策树、朴素贝叶斯分类器、线性回归和逻辑回归等任务中。
(2)交叉验证法
交叉验证一般采用k折交叉验证,即k-fold cross validation,往往k取为10。在这种数据集划分法中,我们将数据集划分为k个子集,每个子集均做一次测试集,每次将其余的作为训练集。在交叉验证时,我们重复训练k次,每次选择一个子集作为测试集,并将k次的平均交叉验证的正确率作为最终的结果。
from sklearn.model_selection import KFold
import numpy as np# 将PyTorch Tensor转为Numpy
X_np = X.numpy()
y_np = y.numpy()# 5折交叉验证
kf = KFold(n_splits=5, shuffle=True, random_state=42)
for fold, (train_idx, val_idx) in enumerate(kf.split(X_np)):# 转换为PyTorch DataLoadertrain_fold = TensorDataset(torch.from_numpy(X_np[train_idx]), torch.from_numpy(y_np[train_idx]))val_fold = TensorDataset(torch.from_numpy(X_np[val_idx]), torch.from_numpy(y_np[val_idx]))train_loader = DataLoader(train_fold, batch_size=32, shuffle=True)val_loader = DataLoader(val_fold, batch_size=32)print(f"Fold {fold+1}: Train {len(train_fold)}, Val {len(val_fold)}")
(3)训练集、验证集、测试集法
我们首先将数据集划分为训练集和测试集,由于模型的构建过程中也需要检验模型,检验模型的配置,以及训练程度,过拟合还是欠拟合,所以会将训练数据再划分为两个部分,一部分是用于训练的训练集,另一部分是进行检验的验证集。验证集可以重复使用,主要是用来辅助我们构建模型的。
训练集用于训练得到神经网络模型,然后用验证集验证模型的有效性,挑选获得最佳效果的模型,直到我们得到一个满意的模型为止。最后,当模型“通过”验证集之后,我们再使用测试集测试模型的最终效果,评估模型的准确率,以及误差等。测试集只在模型检验时使用,绝对不能根据测试集上的结果来调整网络参数配置,以及选择训练好的模型,否则会导致模型在测试集上过拟合。
一般来说,最终的正确率,训练集大于验证集,验证集大于测试集。
对于部分机器学习任务,我们划分的测试集必须是模型从未见过的数据,比如语音识别中一个完全不同的人的说话声,图像识别中一个完全不同的识别个体。这时,一般来说,训练集和验证集的数据分布是同分布的,而测试集的数据分布与前两者会略有不同。在这种情况下,通常,测试集的正确率会比验证集的正确率低得多,这样就可以看出模型的泛化能力,可以预测出实际应用中的真实效果。
下面是按照 8-1-1 划分数据集的代码示例:
import torch
from torch.utils.data import DataLoader, TensorDataset, random_split# 生成示例数据
X = torch.randn(1000, 10) # 1000个样本,10维特征
y = torch.randint(0, 2, (1000,)) # 二分类标签
dataset = TensorDataset(X, y)# 划分比例:80%训练,10%验证,10%测试
train_size = int(0.8 * len(dataset))
val_size = int(0.1 * len(dataset))
test_size = len(dataset) - train_size - val_sizetrain_dataset, val_dataset, test_dataset = random_split(dataset, [train_size, val_size, test_size],generator=torch.Generator().manual_seed(42) # 固定随机种子
)# 创建DataLoader
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32)
test_loader = DataLoader(test_dataset, batch_size=32)print(f"训练集样本数: {len(train_dataset)}") # 直接查看原始数据集
print(f"DataLoader 批次数量: {len(train_loader)}") # 总批次 = 样本数 // batch_size# 获取第一个批次的数据
batch = next(iter(train_loader)) # 返回的是 (features, labels)
features, labels = batch# 查看特征和标签的形状
print("特征张量形状:", features.shape) # [batch_size, 10]
print("标签张量形状:", labels.shape) # [batch_size]
print("标签示例:", labels[:5]) # 查看前5个标签
二、偏差与方差
-
假设这就是数据集,如果给这个数据集拟合一条直线,可能得到一个逻辑回归拟合,但它并不能很好地拟合该数据,这是高偏差(high bias)的情况,我们称为**“欠拟合”(underfitting)**。
-
相反的如果我们拟合一个非常复杂的分类器,比如深度神经网络或含有隐藏单元的神经网络,可能就非常适用于这个数据集,但是这看起来也不是一种很好的拟合方式分类器方差较高(high variance),数据过度拟合(overfitting)。
衡量方式
- 一般可通过查看训练集与验证集误差来诊断。
-
评估偏差(bias),一般看训练集 训练集误差大——偏差较高,欠拟合
-
评估方差(variance),一般看验证集 训练集误差小,验证集误差大——方差较高,过拟合
学习曲线
-
学习曲线作用: 查看模型的学习效果; 通过学习曲线可以清晰的看出模型对数据的过拟合和欠拟合;
-
学习曲线:随着训练样本的逐渐增多,算法训练出的模型的表现能力;
-
表现能力:也就是模型的预测准确情况。
总结就是如果训练样本准确率一直上不去就是欠拟合,如果训练集准确率很高,但是验证集很低,就是过拟合。下面是两个案例
案例 1——欠拟合
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt# 生成非线性数据(100个样本)
torch.manual_seed(42)
x = torch.unsqueeze(torch.linspace(-5, 5, 100), 1)
y = torch.sin(x) * 2 + torch.normal(0, 0.3, x.shape)# 划分训练集(70%)和验证集(30%)
split = int(0.7 * len(x))
x_train, y_train = x[:split], y[:split]
x_val, y_val = x[split:], y[split:]# 构建欠拟合模型(单层线性回归)
class UnderfitModel(nn.Module):def __init__(self):super().__init__()self.linear = nn.Linear(1, 1) # 仅一个线性层def forward(self, x):return self.linear(x)model = UnderfitModel()
optimizer = optim.SGD(model.parameters(), lr=0.01) # 使用低学习率
criterion = nn.MSELoss()# 训练过程(仅50次迭代)
train_loss = []
val_loss = []
for epoch in range(50):# 训练模式model.train()output = model(x_train)loss = criterion(output, y_train)optimizer.zero_grad()loss.backward()optimizer.step()# 验证模式model.eval()with torch.no_grad():val_pred = model(x_val)v_loss = criterion(val_pred, y_val)# 记录损失train_loss.append(loss.item())val_loss.append(v_loss.item())# 可视化损失曲线
plt.figure(figsize=(10,5))
plt.plot(train_loss, label='train_loss')
plt.plot(val_loss, label='valid_loss')
plt.ylim(0, 5)
plt.legend()
plt.title("欠拟合训练过程")
plt.show()# 最终预测可视化
model.eval()
with torch.no_grad():pred = model(x)plt.figure(figsize=(12,5))
plt.scatter(x_train, y_train, c='r', label='train_data')
plt.scatter(x_val, y_val, c='g', label='valid_data')
plt.plot(x, pred.numpy(), 'b-', lw=3, label='model_predict')
plt.plot(x, torch.sin(x)*2, 'k--', label='true_function')
plt.legend()
plt.show()# 输出误差指标
print(f'[最终误差] 训练集:{train_loss[-1]:.4f} | 验证集:{val_loss[-1]:.4f}')
print(f'模型参数:w={model.linear.weight.item():.2f}, b={model.linear.bias.item():.2f}')
它最终的学习曲线如下
可以很明显看到模型预测与真实曲线相差很远
案例 2——过拟合
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt# 生成少量训练数据(20个样本)
torch.manual_seed(1)
x_train = torch.unsqueeze(torch.linspace(-5, 5, 20), dim=1)
y_train = 1.2 * x_train + 0.8 + torch.normal(0, 0.5, size=x_train.size())# 构建过参数化模型(4层全连接网络)
class OverfitModel(nn.Module):def __init__(self):super().__init__()self.net = nn.Sequential(nn.Linear(1, 100),nn.ReLU(),nn.Linear(100, 100),nn.ReLU(),nn.Linear(100, 100),nn.ReLU(),nn.Linear(100, 1))def forward(self, x):return self.net(x)model = OverfitModel()
optimizer = optim.Adam(model.parameters(), lr=0.01)
criterion = nn.MSELoss()# 训练循环(3000次迭代)
loss_history = []
for epoch in range(3000):output = model(x_train)loss = criterion(output, y_train)optimizer.zero_grad()loss.backward()optimizer.step()loss_history.append(loss.item())# 生成测试数据(同分布但未参与训练)
x_test = torch.unsqueeze(torch.linspace(-6, 6, 100), dim=1)
y_test = 1.2 * x_test + 0.8 + torch.normal(0, 0.5, size=x_test.size())# 绘制结果对比
plt.figure(figsize=(12,5))
plt.scatter(x_train.numpy(), y_train.numpy(), c='r', label='train_data')
plt.plot(x_test.numpy(), model(x_test).detach().numpy(), 'b-', lw=3, label='predict')
plt.plot(x_test.numpy(), 1.2*x_test+0.8, 'g--', label='true_function')
plt.legend()
plt.show()# 输出训练误差和测试误差
train_loss = criterion(model(x_train), y_train)
test_loss = criterion(model(x_test), y_test)
print(f'训练误差:{train_loss.item():.4f}')
print(f'测试误差:{test_loss.item():.4f}')
可以看到最后生成的拟合曲线如蓝色所示,很明显过拟合,切测试误差比训练误差大很多
三、过拟合&欠拟合的处理方式
1、首先根据训练集效果来判断是否是高偏差?也就是是否欠拟合。
如果不是,跳转到下一步(判断是否高方差)。
如果是,有四种可尝试的方法:
A、新网络,比如:更多的隐藏层或隐藏单元。
B、增加新特征,可以考虑加入进特征组合、高次特征或者添加多项式特征(将线性模型通过添加二次项或者三次项使模型泛化能力更强)
C、用更多时间训练算法。
D、尝试更先进的优化算法。
反复调试,直到偏差降到和接受范围内,然后进行下一步。
2、根据验证集效果来判断是否是高方差?也就是是否过拟合。
如果不是,说明得到了很好的结果,训练结束,开始将该模型放入测试集。
如果是,有三种可尝试的方法:
A、更多数据来训练。
B、正则化来减少过拟合。
C、控制模型的复杂度,用dropout、early stopping等方法
D、尝试新网络框架(有时有用有时没用)。
名词解释
- 正则化
L2正则化:目标函数中增加所有权重w参数的平方之和, 逼迫所有w尽可能趋向零但不为零. 因为过拟合的时候, 拟合函数需要顾忌每一个点, 最终形成的拟合函数波动很大, 在某些很小的区间里, 函数值的变化很剧烈, 也就是某些w非常大. 为此, L2正则化的加入就惩罚了权重变大的趋势.
model = nn.Sequential(nn.Linear(784, 256),nn.ReLU(),nn.Linear(256, 10)
)# 设置优化器时添加weight_decay参数(L2系数)
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
L1正则化:目标函数中增加所有权重w参数的绝对值之和, 逼迫更多w为零(也就是变稀疏. L2因为其导数也趋0, 奔向零的速度不如L1给力了).大家对稀疏规则化趋之若鹜的一个关键原因在于它能实现特征的自动选择。一般来说,xi的大部分元素(也就是特征)都是和最终的输出yi没有关系或者不提供任何信息的,在最小化目标函数的时候考虑xi这些额外的特征,虽然可以获得更小的训练误差,但在预测新的样本时,这些没用的特征权重反而会被考虑,从而干扰了对正确yi的预测。稀疏规则化算子的引入就是为了完成特征自动选择的光荣使命,它会学习地去掉这些无用的特征,也就是把这些特征对应的权重置为0。
L1 正则化 torch 没有直接实现,可以手动实现
def l1_regularization(model, lambda_l1):l1_loss = 0for param in model.parameters():l1_loss += torch.sum(torch.abs(param))return lambda_l1 * l1_loss# 训练循环
for data, target in dataloader:optimizer.zero_grad()output = model(data)loss = F.cross_entropy(output, target)# 添加L1正则项l1_lambda = 0.001loss += l1_regularization(model, l1_lambda)loss.backward()optimizer.step()
下面是一个同时引用 L1 正则化和 L2 正则化的案例
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as Fclass RegularizedModel(nn.Module):def __init__(self):super().__init__()self.fc = nn.Sequential(nn.Flatten(), nn.Linear(784, 256),nn.BatchNorm1d(256),nn.ReLU(),nn.Linear(256, 10))def forward(self, x):return self.fc(x)def train(model, train_loader, lambda_l1=0, lambda_l2=0):optimizer = optim.AdamW(model.parameters(), lr=0.001)for epoch in range(100):total_loss = 0for x, y in train_loader:optimizer.zero_grad()pred = model(x)loss = F.cross_entropy(pred, y)# L1正则项if lambda_l1 > 0:l1 = sum(p.abs().sum() for p in model.parameters())loss += lambda_l1 * l1# L2正则项if lambda_l2 > 0:l2 = sum(p.pow(2).sum() for p in model.parameters())loss += 0.5 * lambda_l2 * l2loss.backward()optimizer.step()total_loss += loss.item()print(f"Epoch {epoch}: Loss={total_loss/len(train_loader):.4f}")# 使用示例import torch
from torch.utils.data import DataLoader, TensorDataset# 参数配置
batch_size = 16
input_dim = 784 # 对应模型输入维度
num_classes = 10
num_samples = 1000 # 总样本量# 生成正态分布虚拟数据
X = torch.randn(num_samples, input_dim) # 形状 (1000, 784)
y = torch.randint(0, num_classes, (num_samples,)) # 随机标签# 创建数据集和数据加载器
dataset = TensorDataset(X, y)
train_loader = DataLoader(dataset, batch_size=batch_size, shuffle=True)# 验证数据形状
sample_X, sample_y = next(iter(train_loader))
print(f"输入数据形状: {sample_X.shape}") # 应输出 torch.Size([16, 784])
print(f"标签形状: {sample_y.shape}") # 应输出 torch.Size([16])model = RegularizedModel()
train(model, train_loader, lambda_l1=1e-5, lambda_l2=1e-4)
- dropout
在训练的运行的时候,让神经元以超参数p的概率被激活(也就是1-p的概率被设置为0), 每个w因此随机参与, 使得任意w都不是不可或缺的, 效果类似于数量巨大的模型集成。
class RegularizedModel(nn.Module):def __init__(self, input_dim):super().__init__()self.net = nn.Sequential(nn.Linear(input_dim, 128),nn.ReLU(),nn.Dropout(0.5), # 添加Dropout层nn.Linear(128, 64),nn.ReLU(),nn.Dropout(0.3),nn.Linear(64, 1))def forward(self, x):return torch.sigmoid(self.net(x)).squeeze()
- early stop
提前终止训练,即在模型对训练数据集迭代收敛之前停止迭代来防止过拟合,常用的停止条件就是当 N 轮迭代都loss 都没有降低后可以停止迭代
下面案例的停止条件就是当 loss 连续 10 次都没有低于最佳 loss-0.001时就触发,这里设置了一个delta为 0.001,就能保证即使损失有波动,只要未突破阈值就计数
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader, TensorDataset# 早停监控器(带模型保存功能)
class EarlyStopper:def __init__(self, patience=5, delta=0, path='best_model.pth'):self.patience = patience # 容忍epoch数self.delta = delta # 视为改进的最小变化量self.path = path # 最佳模型保存路径self.counter = 0 # 未改进计数器self.best_score = None # 最佳监控指标值self.early_stop = False # 停止标志def __call__(self, val_loss, model):score = -val_loss # 默认监控验证损失(越大越好)if self.best_score is None:self.best_score = scoreself.save_checkpoint(model)elif score < self.best_score + self.delta:self.counter += 1print(f'EarlyStopping counter: {self.counter}/{self.patience}')if self.counter >= self.patience:self.early_stop = Trueelse:self.best_score = scoreself.save_checkpoint(model)self.counter = 0def save_checkpoint(self, model):torch.save(model.state_dict(), self.path)# 生成模拟数据(回归任务)
def generate_data(samples=1000):X = torch.linspace(-10, 10, samples).unsqueeze(1)y = 0.5 * X**3 - 2 * X**2 + 3 * X + torch.randn(X.size()) * 10return X, y# 过参数化的全连接网络
class OverfitModel(nn.Module):def __init__(self):super().__init__()self.net = nn.Sequential(nn.Linear(1, 128),nn.ReLU(),nn.Linear(128, 256),nn.ReLU(),nn.Linear(256, 128),nn.ReLU(),nn.Linear(128, 1))def forward(self, x):return self.net(x)# 训练函数(集成早停)
def train_with_earlystop(model, train_loader, val_loader, epochs=1000):optimizer = optim.Adam(model.parameters(), lr=0.001)criterion = nn.MSELoss()early_stopper = EarlyStopper(patience=10, delta=0.001)train_losses = []val_losses = []for epoch in range(epochs):# 训练阶段model.train()train_loss = 0for X_batch, y_batch in train_loader:optimizer.zero_grad()pred = model(X_batch)loss = criterion(pred, y_batch)loss.backward()optimizer.step()train_loss += loss.item()train_loss /= len(train_loader)train_losses.append(train_loss)# 验证阶段model.eval()val_loss = 0with torch.no_grad():for X_val, y_val in val_loader:pred_val = model(X_val)val_loss += criterion(pred_val, y_val).item()val_loss /= len(val_loader)val_losses.append(val_loss)print(f'Epoch {epoch+1:03d} | 'f'Train Loss: {train_loss:.4f} | 'f'Val Loss: {val_loss:.4f}')# 早停检查early_stopper(val_loss, model)if early_stopper.early_stop:print("==> Early stopping triggered")break# 恢复最佳模型model.load_state_dict(torch.load('best_model.pth'))return train_losses, val_losses# 可视化训练过程
def plot_learning_curve(train_loss, val_loss):plt.figure(figsize=(10, 6))plt.plot(train_loss, label='Training Loss')plt.plot(val_loss, label='Validation Loss')plt.xlabel('Epochs')plt.ylabel('Loss')plt.title('Learning Curve with Early Stopping')plt.legend()plt.grid(True)plt.show()# 主程序
if __name__ == "__main__":# 数据准备X, y = generate_data()dataset = TensorDataset(X, y)# 划分训练集和验证集(8:2)train_size = int(0.8 * len(dataset))val_size = len(dataset) - train_sizetrain_dataset, val_dataset = torch.utils.data.random_split(dataset, [train_size, val_size])train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)val_loader = DataLoader(val_dataset, batch_size=32)# 初始化模型model = OverfitModel()# 开始训练train_loss, val_loss = train_with_earlystop(model, train_loader, val_loader, epochs=1000)# 绘制学习曲线plot_learning_curve(train_loss, val_loss)# 最终模型测试model.eval()with torch.no_grad():test_input = torch.tensor([[5.0], [-3.0], [8.0]])predictions = model(test_input)print("\nModel Predictions at x=5, -3, 8:")print(predictions.numpy())
四、模型的效果评估
具体模型的评估方法也可以看我之前的文章,本文主要补充一些代码案例【Python数据分析】数据挖掘建模——分类与预测算法评价(含ROC曲线、F1等指标的解释)_分类f1指标 python-CSDN博客
(1)分类任务评估(混淆矩阵、AUC)
from sklearn.metrics import confusion_matrix, roc_auc_scoredef evaluate_model(model, loader):model.eval()all_preds = []all_labels = []with torch.no_grad():for X_batch, y_batch in loader:outputs = model(X_batch)preds = (outputs > 0.5).float()all_preds.extend(preds.cpu().numpy())all_labels.extend(y_batch.cpu().numpy())# 计算指标cm = confusion_matrix(all_labels, all_preds)auc = roc_auc_score(all_labels, all_preds)print("Confusion Matrix:")print(cm)print(f"AUC Score: {auc:.4f}")# 在测试集上评估
evaluate_model(model, test_loader)
(2)回归任务评估(MAE、MSE)
def evaluate_regression(model, loader):model.eval()total_mae = 0total_mse = 0with torch.no_grad():for X_batch, y_batch in loader:outputs = model(X_batch)mae = torch.abs(outputs - y_batch).mean()mse = ((outputs - y_batch)**2).mean()total_mae += mae.item() * X_batch.size(0)total_mse += mse.item() * X_batch.size(0)mae = total_mae / len(loader.dataset)mse = total_mse / len(loader.dataset)print(f"MAE: {mae:.4f}, MSE: {mse:.4f}")
当然也可以把二者结合一下
import torch
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import (roc_curve, auc, confusion_matrix, precision_recall_curve,r2_score,mean_squared_error
)
import seaborn as snsdef evaluate_model(model, data_loader, task_type='classification'):"""综合模型评估函数参数:model : 训练好的PyTorch模型data_loader : 数据加载器task_type : 任务类型 ['classification', 'regression']返回:包含各项指标的字典"""model.eval()device = next(model.parameters()).deviceall_targets = []all_outputs = []with torch.no_grad():for inputs, targets in data_loader:inputs = inputs.to(device)outputs = model(inputs)all_targets.append(targets.cpu().numpy())all_outputs.append(outputs.cpu().numpy())y_true = np.concatenate(all_targets)y_pred = np.concatenate(all_outputs)metrics = {}if task_type == 'classification':# 分类任务指标y_prob = torch.softmax(torch.tensor(y_pred), dim=1).numpy()y_pred_labels = np.argmax(y_pred, axis=1)# 多分类AUC计算(OvR策略)fpr = dict()tpr = dict()roc_auc = dict()n_classes = y_prob.shape[1]for i in range(n_classes):fpr[i], tpr[i], _ = roc_curve((y_true == i).astype(int), y_prob[:, i])roc_auc[i] = auc(fpr[i], tpr[i])# 计算宏观平均AUCfpr["macro"], tpr["macro"], _ = roc_curve(y_true.ravel(), y_prob.ravel())roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])metrics.update({'accuracy': np.mean(y_pred_labels == y_true),'auc_macro': roc_auc["macro"],'confusion_matrix': confusion_matrix(y_true, y_pred_labels),'classification_report': classification_report(y_true, y_pred_labels)})# 绘制ROC曲线plt.figure(figsize=(10, 6))for i in range(n_classes):plt.plot(fpr[i], tpr[i], lw=1,label=f'Class {i} (AUC = {roc_auc[i]:.2f})')plt.plot([0, 1], [0, 1], 'k--', lw=1)plt.xlim([0.0, 1.0])plt.ylim([0.0, 1.05])plt.xlabel('False Positive Rate')plt.ylabel('True Positive Rate')plt.title('ROC Curves')plt.legend(loc="lower right")plt.show()elif task_type == 'regression':# 回归任务指标metrics.update({'mse': mean_squared_error(y_true, y_pred),'mae': np.mean(np.abs(y_true - y_pred)),'r2': r2_score(y_true, y_pred)})# 绘制预测值与真实值散点图plt.figure(figsize=(8, 6))plt.scatter(y_true, y_pred, alpha=0.5)plt.plot([y_true.min(), y_true.max()], [y_true.min(), y_true.max()], 'r--')plt.xlabel('True Values')plt.ylabel('Predictions')plt.title('Regression Evaluation')plt.show()return metrics# 使用示例(分类任务)
if __name__ == "__main__":# 假设已有训练好的分类模型和数据加载器from sklearn.metrics import classification_report# 加载测试数据test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)# 进行评估classification_metrics = evaluate_model(model, test_loader, 'classification')# 打印关键指标print(f"准确率: {classification_metrics['accuracy']:.4f}")print(f"宏观平均AUC: {classification_metrics['auc_macro']:.4f}")print("\n分类报告:")print(classification_metrics['classification_report'])# 绘制混淆矩阵plt.figure(figsize=(10, 8))sns.heatmap(classification_metrics['confusion_matrix'], annot=True, fmt='d', cmap='Blues')plt.title('Confusion Matrix')plt.xlabel('Predicted Label')plt.ylabel('True Label')plt.show()# 回归任务使用示例
# regression_metrics = evaluate_model(model, test_loader, 'regression')
# print(f"MSE: {regression_metrics['mse']:.4f}")
# print(f"R²: {regression_metrics['r2']:.4f}")
好啦 神经网络的基础就在这结束啦,之后就开始进一步讲深度学习内容(包括 RNN、LSTM、transformer 等)最后就引出大模型的原理,继续期待叭~
相关文章:

【从0到1搞懂大模型】神经网络的实现:数据策略、模型调优与评估体系(3)
一、数据集的划分 (1)按一定比例划分为训练集和测试集 我们通常取8-2、7-3、6-4、5-5比例切分,直接将数据随机划分为训练集和测试集,然后使用训练集来生成模型,再用测试集来测试模型的正确率和误差,以验证…...

从0到1入门RabbitMQ
一、同步调用 优势:时效性强,等待到结果后才返回 缺点: 拓展性差性能下降级联失败问题 二、异步调用 优势: 耦合度低,拓展性强异步调用,无需等待,性能好故障隔离,下游服务故障不影响…...

MySQL数据库复杂的增删改查操作
在前面的文章中,我们主要学习了数据库的基础知识以及基本的增删改查的操作。接下去将以一个比较实际的公司数据库为例子,进行讲解一些较为复杂且现时需求的例子。 基础知识: 一文清晰梳理Mysql 数据库基础知识_字段变动如何梳理清楚-CSDN博…...

点云软件VeloView开发环境搭建与编译
官方编译说明 LidarView / LidarView-Superbuild GitLab 我的编译过程: 安装vs2019,windows sdk,qt5.14.2(没安装到5.15.7),git,cmake3.31,python3.7.9,ninja下载放到…...

本地YARN集群部署
请先完成HDFS的前置部署,部署方式可查看:本地部署HDFS集群https://blog.csdn.net/m0_73641796/article/details/145998092?spm1001.2014.3001.5502 部署说明 组件配置文件启动进程备注Hadoop HDFS需修改 需启动: NameNode作为主节点 DataNode作为从节点 Secondary…...

STM32常见外设的驱动示例和代码解析
以下是针对STM32常见外设的驱动示例和代码解析,基于HAL库实现,适用于大多数STM32系列(如F1/F4/H7等),可根据具体型号调整引脚和时钟配置。 1. GPIO驱动 应用场景:控制LED、按键检测、继电器开关等。 示例代码: // 初始化LED(推挽输出) void LED_Init(void) {GPIO_In…...

使用数据库和缓存的时候,是如何解决数据不一致的问题的?
1.缓存更新策略 1.1. 缓存旁路模式(Cache Aside) 在应用里负责管理缓存,读取时先查缓存,如果命中了则返回缓存,如果未命中就查询数据库,然后返回缓存,返回缓存的同时把数据给写入缓存中。更新…...

VS Code C++ 开发环境配置
VS Code 是当前非常流行的开发工具. 本文讲述如何配置 VS Code 作为 C开发环境. 本文将按照如下步骤来介绍如何配置 VS Code 作为 C开发环境. 安装编译器安装插件配置工作区 第一个步骤的具体操作会因为系统不同或者方案不同而有不同的选择. 环境要求 首先需要立即 VS Code…...

使用OpenCV和MediaPipe库——实现人体姿态检测
目录 准备工作如何在Windows系统中安装OpenCV和MediaPipe库? 安装Python 安装OpenCV 安装MediaPipe 验证安装 代码逻辑 整体代码 效果展示 准备工作如何在Windows系统中安装OpenCV和MediaPipe库? 安装Python 可以通过命令行运行python --versio…...

JWT的学习
1、HTTP无状态及解决方案 HTTP一种是无状态的协议,每次请求都是一次独立的请求,一次交互之后就是陌生人。 以CSDN为例,先登录一次,然后浏览器退出,这个时候在进入CSDN,按理说服务器是不知道你已经登陆了&…...

elasticsearch是哪家的
Elasticsearch:数据搜索与分析的领航者 在当今这个信息爆炸的时代,快速且准确地处理海量数据成为了众多企业和组织追求的目标。而Elasticsearch正是在这个背景下脱颖而出的一款强大的开源搜索引擎。它是由位于美国加利福尼亚州的Elastic公司所开发和维护…...

《A++ 敏捷开发》- 18 软件需求
需求并不是关于需求 (Requirements are not really about requirements) 大家去公共图书馆寄存物品,以前都是扫二维码开箱,有些图书馆升级了使用指纹识别。 “是否新方法比以前好?”我问年轻的开发人员。 “当然用指纹识别好。新技术&#x…...

计算机网络:计算机网络的组成和功能
计算机网络的组成: 计算机网络的工作方式: 计算机网络的逻辑功能; 总结: 计算机网络的功能: 1.数据通信 2.资源共享 3.分布式处理:计算机网络的分布式处理是指将计算任务分散到网络中的多个节点(计算机或设备&…...

Upload-Labs-Linux 1-20
前端校验绕过:pass 01 两种思路:1.通过抓包,修改后缀 2.前端禁用js绕过前端后缀检验 首先写一个木马,改为图片格式GIF89a<?php eval($_POST[cmd])?>抓包之后改为PHP格式: 使用蚁剑连接木马,第一次尝…...

Compose笔记(八)--权限
这一节主要了解一下Compose中权限的申请,其中主要用到accompanist-permissions这个权限库,它是一个简化的Android Compose 中权限管理的库,如下使用: 栗子: 依赖添加 dependencies {implementation("com.google.accompani…...

单例模式:确保一个类只有一个实例
目录 引言 1. 单例模式的核心思想 2. 单例模式的实现方式 2.1 饿汉式单例 2.2 懒汉式单例 2.3 线程安全的懒汉式单例 2.4 双重检查锁定(Double-Checked Locking) 2.5 静态内部类实现单例 2.6 枚举实现单例 3. 单例模式的使用场景 4. 单例模式…...

推荐一个好用的在线文本对比网站 - diffchecker
推荐网址:https://www.diffchecker.com UI设计也很不错,响应也很快,广告少 生成的对比还可以生成在线链接:(点击右上角“分享”) 可设置过期时间等 我生成的示例:https://www.diffchecker.c…...

学习第八十五行
[capture](parameters) -> return_type {// function body }capture: 捕获列表,指定如何捕获周围作用域中的变量。parameters: 参数列表,与普通函数类似。return_type: 返回类型,可以省略,编译器会自动推断。function body: 函…...

基于Django创建一个WEB后端框架(DjangoRestFramework+MySQL)流程
一、Django项目初始化 1.创建Django项目 Django-admin startproject 项目名 2.安装 djangorestframework pip install djangorestframework 解释: Django REST Framework (DRF) 是基于 Django 框架的一个强大的 Web API 框架,提供了多种工具和库来构建 RESTf…...

【Python 2D绘图】Matplotlib绘图(统计图表)
【Python 2D绘图】Matplotlib绘图(统计图表) 1. 概述1.1 简介1.2 安装1.3 导入1.4 保存1.5 数据来源1.5.1 Numpy ndarray1.5.2 Pandas DataFrame 1.6 中文显示 2. 基础样式2.1 颜色2.1.1 简称2.1.2 全称 2.2 布局2.2.1 Matplotlib 画布划分2.2.2 绘制子图…...

vue3框架的响应式依赖追踪机制
当存在一个响应式变量于视图中发生改变时会更新当前组件的所以视图显示,但是没有视图中不写这个响应式变量就就算修改该变量也不会修改视图,这是为什么?我们能否可以理解宽泛的理解为vue组件的更新就是视图的更新,单当视图中不存在…...

.Net 6 上传文件接口 文件大小报错整体配置
/// <summary>/// 上传文件/// </summary>/// <param name"file"></param>/// <returns></returns>[HttpPost("UploadifyFile")][RequestSizeLimit(2000 * 1024 * 1024)] // 设置最大请求体大小为 100MBpublic async …...

Git基础之工作原理
基础概念 git本地有三个工作区域,工作目录 Working Directory,暂存区Stage/Index和资源区Repository/Git Directory,如果在加上远程的git仓库就是四个工作区域 四个区域与文件交换的命令之间的关系 WorkSpace:工作区,就…...

小程序 wxml 语法 —— 41列表渲染 - 进阶用法
这一节讲解列表渲染的两个进阶用法: 如果需要对默认的变量名和下标进行修改,可以使用 wx:for-item 和 wx:for-item: 使用 wx:for-item 可以指定数组当前元素的变量名使用 wx:for-index 可以指定数组当前下标的变量名 将 wx:for 用在 标签上&…...

ElasticSearch 入门教程
ElasticSearch 入门教程 ElasticSearch 是一个分布式、可扩展的搜索和分析引擎,基于 Apache Lucene 构建,支持全文检索、结构化查询和聚合分析。本教程将带你深入了解 ElasticSearch 的核心概念、安装配置、常见操作,并提供示例代码…...

用Python写一个算24点的小程序
一、运行界面 二、显示答案——递归介绍 工作流程: 1. 基本情况:函数首先检查输入的数字列表 nums 的长度。如果列表中只剩下一个数字,它会判断这个数字是否接近 24(使用 abs(nums[0] - 24) < 1e-10 来处理浮点数精度问题&…...

分布式网络
分布式网络(Distributed Network)指的是一种计算机网络架构,其中计算资源(计算、存储、数据处理等)分布在多个物理或逻辑上的节点上,而不是集中在单一的服务器或数据中心中。这种架构的主要目标是提高系统的…...

忘记dedecms后台超级管理员账号和密码的解决方案
解决方案: 方案一、数据库修改: 1、前提是您能登录到数据库后台,登录MySQL数据库管理工具(如phpMyAdmin) 2、打开数据库中的 dede_admin 表,找到管理员记录,将 pwd 字段的值改成 f297a57a5a7…...

【Linux学习笔记】Linux基本指令分析和权限的概念
【Linux学习笔记】Linux基本指令分析和权限的概念 🔥个人主页:大白的编程日记 🔥专栏:Linux学习笔记 文章目录 【Linux学习笔记】Linux基本指令分析和权限的概念前言一. 指令的分析1.1 alias 指令1.2 grep 指令1.3 zip/unzip 指…...

Git基础之分支
常用指令 git branch 列出本地所有分支 git branch -r 列出所有远程分支 git branch [branch-name] 新建一个分支,但依然停留在当前分支 git checkout -b [branch] 新建一个分支,并切换到该分支 git merge [branch] 合并指定分支当前分支 git branch -d …...