深圳网站建设招聘,做公司网站要走哪些流程,网站做网站广告,公共服务网站系统建设方案结果并不优秀#xff0c;只有58%左右的准确率。而本周我们了解了浅层神经网络的各部分原理#xff0c;知道了其如何提高拟合效果#xff0c;现在便延续上一周的内容#xff0c;再次在这个数据集上应用本周更新的内容#xff0c;来看一看效果。2.1 逻辑回归模型代码先回看一…结果并不优秀只有58%左右的准确率。而本周我们了解了浅层神经网络的各部分原理知道了其如何提高拟合效果现在便延续上一周的内容再次在这个数据集上应用本周更新的内容来看一看效果。2.1 逻辑回归模型代码先回看一下之前的模型代码class LogisticRegressionModel(nn.Module):# 类继承自nn.Module是 PyTorch 所有模型的基类#初始化方法def __init__(self):super().__init__() #父类初始化用于注册子模块等涉及源码这里当成固定即可。self.flatten nn.Flatten() #把张量后三维展平为一维通道C*高H*宽Wself.linear nn.Linear(128 * 128 * 3, 1) # 输入是128x128x3输出1个加权和# nn.Linear接受的是二维输入[batch_size, features]这里是[32,128 * 128 * 3]# 但Linear层不需要在参数里写 batch 维度它内部会自动处理批量输入只关心每个样本的特征数和每个样本输出的维度这也是广播机制的应用。self.sigmoid nn.Sigmoid() #激活函数#向前传播方法def forward(self, x):# 现在x的维度是[32,3,128,128]x self.flatten(x) #1.展平# 现在x的维度是[32,128 * 128 * 3]x self.linear(x) #2.过线性组合得到加权和# 现在x的维度是[32,1]x self.sigmoid(x) #3.过激活函数得到输出# 现在x的维度是[32,1]return x虽然注释较多但其原理并不复杂我们看向前传播函数实际上一次正向传播只有三步显式计算。2.2 浅层神经网络模型代码class ShallowNeuralNetwork(nn.Module):def __init__(self):super().__init__()self.flatten nn.Flatten() ## 隐藏层输入128*128*3维特征输出4个神经元self.hidden nn.Linear(128 * 128 * 3, 4)# 隐藏层激活函数ReLU作用是加入非线性特征self.ReLU nn.ReLU()# 输出层将隐藏层的 4 个输出映射为 1 个加权和self.output nn.Linear(4, 1)self.sigmoid nn.Sigmoid()# 前向传播方法def forward(self, x):# 输入 x 的维度为 [32, 3, 128, 128]x self.flatten(x)# 展平后 x 的维度为 [32, 128 * 128 * 3]x self.hidden(x)# 通过隐藏层线性变换后x 的维度为 [32, 4]x self.ReLU(x)# 经过 ReLU 激活后形状不变仍为 [32, 4]x self.output(x)# 通过输出层得到加权和形状变为 [32, 1]x self.sigmoid(x)# 经过 sigmoid 激活后得到 0~1 的概率值形状仍为 [32, 1]return x这就是设置了四个隐藏层神经元的浅层神经网络的代码可以发现在Pytorch的内置方法帮助下我们只不过相对逻辑回归改动了几行代码便实现了从逻辑回归到浅层神经网络进行二分类的效果。2.3 验证模型优化现在我们依旧使用上周的代码只将模型替换为浅层神经网络而不改变其他任何部分(完整代码附在文末)。先来看一张测试结果Pasted image 20251021100322如果只看这两张图的对比可能会想只是简单的扩大一下网络的规模就实现了准确率的提升确实差别展示的非常明显。但可惜事实并非如此实际上图中右侧的结果只是多次运行结果中最好的一次几乎不可控就像抽卡游戏里非常小概率的金卡一样。而实际上最终测试的准确率依旧在50%到60%之间徘徊。那问题又来了那增加隐藏层就一点作用也没有吗答案当然是否定的我们再来看一组对比Pasted image 20251021102101我们观察两幅图像会很明显的发现区分。在逻辑回归的图像中准确率的曲线几乎看不出幅度而在浅层神经网络中它甚至已经和损失曲线相相交了。回看刚刚每轮的损失我们会发现造成这种差别的原因是准确率只在0到1间波动而逻辑回归的平均损失却在1-10这个量级内相比之下浅层神经网络的平均损失已经降到了0到1之间。逻辑回归的损失在数值高的情况下相比浅层神经网络的波动也较大而浅层神经网络的下降趋势几乎成了一条直线。而这是因为逻辑回归因为模型太简单、只能学习线性关系训练时更容易在高损失区震荡而浅层神经网络具备初步非线性表达能力能更稳定地逼近最优解损失下降更平滑、更接近直线。从这方面来看增加隐藏层又有其提升。可是还有一个问题损失函数是用来反向传播更新参数从而提高拟合效果提高准确率的那现在损失变小准确率不提升是为什么在这次代码实践中我们重点讨论一下这个问题。2.4 为什么损失减少不增加准确率虽然损失函数的值在不断下降但准确率却没有显著提高这并不矛盾我们来细究一下首先损失函数本质上衡量的是模型输出概率与真实标签的差距而准确率衡量的是最终分类结果是否正确两者关注的维度不同。当模型预测的概率逐渐接近真实标签例如从 0.49 提高到 0.51 或从 0.4 提高到 0.6损失会明显下降但是只要这些概率在 0.5 的分类阈值附近徘徊模型的预测仍可能被判定为错误于是准确率就不会显著改变。更进一步来说在模型训练初期损失的下降主要来自于“模型更有信心地接近正确答案”但这种接近往往还不足以跨过分类边界。例如对于真实标签为 1 的样本输出可能从 0.3 提升到 0.4这的确让损失下降了很多但它仍被判断为 0 类这对准确率没有任何贡献。同样地若对于真实为 0 的样本输出从 0.8 降为 0.6也会使损失变小但预测依旧是错误的类别如图所示Pasted image 20251021110924还有一种情况也会导致损失在下降但准确率“卡住不动”那就是数据本身太复杂。 我们可以把它想象成两类数据混在一起不是泾渭分明地分成左右两堆而是交错、环绕甚至夹杂着噪声。浅层神经网络虽然比逻辑回归更聪明一点但它的“想象力”依然有限只能学会把整体误差变小却画不出一条真正把两类数据明显分开的界线就像这张图Pasted image 20251021111334因此在本次实操中我们会发现损失下降说明模型确实在学习但如果模型能力不足、特征没有被有效分离或者分类阈值附近的样本占比过高那么准确率依旧可能停留在50%到60%之间。而如何进一步提升准确率便需要我们继续学习继续优化。最后附上完整代码依旧要强调的是在规范流程里我们应该根据每次验证的准确率调整超参数最后再进行测试只是这部分内容还在后面我们经过系统学习后再正式引入这部分。import torchimport torch.nn as nnimport torch.optim as optimfrom torchvision import datasets, transformsfrom torch.utils.data import DataLoader, random_splitimport matplotlib.pyplot as pltfrom sklearn.metrics import accuracy_scoretransform transforms.Compose([transforms.Resize((128, 128)),transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,))])dataset datasets.ImageFolder(root./cat_dog, transformtransform)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])train_loader DataLoader(train_dataset, batch_size32, shuffleTrue)val_loader DataLoader(val_dataset, batch_size32, shuffleFalse)test_loader DataLoader(test_dataset, batch_size32, shuffleFalse)class ShallowNeuralNetwork(nn.Module):def __init__(self):super().__init__()self.flatten nn.Flatten()# 隐藏层self.hidden nn.Linear(128 * 128 * 3, 4) # 1 个隐藏层4 个神经元self.ReLU nn.ReLU()# 输出层self.output nn.Linear(4, 1)self.sigmoid nn.Sigmoid()def forward(self, x):x self.flatten(x)x self.hidden(x)x self.ReLU(x)x self.output(x)x self.sigmoid(x)return xmodel ShallowNeuralNetwork()device torch.device(cuda if torch.cuda.is_available() else cpu)model.to(device)criterion nn.BCELoss()optimizer optim.SGD(model.parameters(), lr0.01)epochs 10train_losses []val_accuracies []for epoch in range(epochs):model.train()epoch_train_loss 0for images, labels in train_loader:images, labels images.to(device), labels.to(device).float().unsqueeze(1)outputs model(images)loss criterion(outputs, labels)optimizer.zero_grad()loss.backward()optimizer.step()epoch_train_loss loss.item()avg_train_loss epoch_train_loss / len(train_loader)train_losses.append(avg_train_loss)model.eval()val_true, val_pred [], []with torch.no_grad():for images, labels in val_loader:images images.to(device)outputs model(images)preds (outputs.cpu().numpy() 0.5).astype(int).flatten()val_pred.extend(preds)val_true.extend(labels.numpy())val_acc accuracy_score(val_true, val_pred)val_accuracies.append(val_acc)print(f轮次: [{epoch 1}/{epochs}], 训练损失: {avg_train_loss:.4f}, 验证准确率: {val_acc:.4f})plt.rcParams[font.sans-serif] [SimHei]plt.rcParams[axes.unicode_minus] Falseplt.plot(train_losses, label训练损失)plt.plot(val_accuracies, label验证准确率)plt.title(训练损失与验证准确率随轮次变化图)plt.xlabel(训练轮次Epoch)plt.ylabel(数值)plt.legend()plt.grid(True)plt.show()model.eval()y_true, y_pred [], []with torch.no_grad():for images, labels in test_loader:images images.to(device)outputs model(images)preds (outputs.cpu().numpy() 0.5).astype(int).flatten()y_pred.extend(preds)y_true.extend(labels.numpy())acc accuracy_score(y_true, y_pred)print(f测试准确率: {acc:.4f})