学习与反思
准确率只有0.1左右?(or 很低)
- 有可能是因为权重没有初始化(不一定是必要的)
- 或者学习率设置的问题,可能设置的太大了,试着调小一些
如何区分验证集和测试集?
- 训练集 (训练阶段)
- 验证集 Validation Set(模型挑选阶段)
- 测试集 Test Set(验证阶段 评估泛化误差)
如何训练自己的数据集?
- 首先获取自己的数据,各类数据要相对均衡,以及图片命名尽量不要使用中文
- 划分训练集和测试集
数据集为什么要进行归一化?
数据归一化(Normalization)是数据预处理中的一个重要步骤,尤其在机器学习和深度学习中。它将数据缩放到一个统一的范围(通常是 [0, 1] 或 [-1, 1]),从而提高模型的训练效率和性能。
数据归一化是深度学习中不可或缺的步骤,它通过调整数据的范围和分布,帮助模型更快地收敛,减少数值计算问题,提高泛化能力,并简化模型的设计和训练。
图形预处理
- 尺寸变化
- 格式转换(变为Tensor格式)
- 归一化
为什么有时损失函数增加但是精度却在上升?
在训练深度学习模型时,有时会观察到一个看似矛盾的现象:损失函数(Loss)在增加,
但精度(Accuracy)却在上升。这种现象可能由多种原因引起,以下是一些可能的解释:
- 损失函数和精度的衡量方式不同
- 损失函数(Loss):衡量的是模型输出与真实标签之间的差异,通常是一个连续的数值。常见的损失函数包括交叉熵损失(Cross-Entropy
Loss)、均方误差(MSE)等。损失函数越小,表示模型的预测越接近真实值。 - 精度(Accuracy):衡量的是模型预测正确的比例,是一个离散的指标。例如,在分类任务中,精度是模型正确分类的样本数占总样本数的比例。
原因:损失函数和精度的优化目标不同。损失函数关注的是预测值与真实值之间的差异,而精度关注的是预测结果是否完全正确。因此,即使损失函数增加,模型的预测结果可能仍然足够接近真实值,从而导致精度上升。
- 数据不平衡或类别分布不均
- 如果数据集中某些类别占主导地位,模型可能会偏向于预测这些类别,从而导致损失函数增加,但精度仍然较高。
- 模型过拟合
- 如果模型在训练集上表现良好,但在验证集上损失函数增加但精度上升,可能是因为模型过拟合了训练集中的某些噪声或异常值。
- 学习率过高
- 如果学习率设置过高,模型的权重更新可能会过大,导致损失函数在某些迭代中增加。然而,如果模型的预测结果仍然接近真实值,精度可能不会受到影响。
- 损失函数的选择问题
- 不同的损失函数对误差的敏感度不同。例如,交叉熵损失对概率值的微小变化非常敏感,而精度则只关注最终的分类结果。
数据预处理或数据增强的影响
-如果在训练过程中使用了数据增强(如随机裁剪、旋转等),模型可能会在某些增强后的数据上表现不佳,导致损失函数增加。但如果这些增强后的数据对精度的影响较小,精度可能仍然较高。模型架构或正则化的影响
- 如果模型架构过于复杂,或者正则化不足,模型可能会在某些样本上表现不佳,导致损失函数增加。但如果这些样本对精度的影响较小,精度可能仍然较高。
- 批量大小(Batch Size)的影响
- 如果批量大小设置得过大或过小,可能会导致损失函数和精度之间的不一致。
随着层数的增加, 训练误差和测试误差不降反增?
这是由于"退化问题"导致的, 退化问题最明显的表现就是给网络叠加更多的层之后, 性能却快速下降的情况. 按照道理, 给网络叠加更多的层,
浅层网络的解空间是包含在深层网络的解空间中的, 深层网络的解空间至少存在不差于浅层网络的解, 因为只需要将增加的层变成恒等映射,
其他层的权重原封不动复制浅层网络, 就可以获得和浅层网络同样的性能. 更好地解明明存在, 为什么找不到, 找到的反而是更差的解?
退化问题的原因可以总结为:
- 优化难度随着深度的增加非线性上升: 深层网络拥有更多参数, 解空间的维度和复杂性呈现指数级增长, 这使得优化算法需要在一个更大的高维空间内找到最优解,
难度大大增加 - 误差积累: 深层网路中的每一层都会对后续层的输入产生影响, 如果某些层的输出有轻微偏差, 这些偏差可能随着层数的增加而累积放大,
导致最终的误差增大
大白话解释:打个比方, 你有一张比别人更大的藏宝图(解空间), 理论上你能找到更多的保障, 但是如果你没有很好的工具(
优化算法), 反而会因为地图太复杂, 找不到最好的路径, 结果挖了一些不值钱的东西(次优解), 甚至挖错地方.
为什么训练集和测试集的精准度很高,而验证集的精准度很低?
可能的原因是在model_train.py文件中train_transform = transforms.Compose([transforms.Resize((224, 224)), transforms.ToTensor(), normalize])
未加上最后的那个归一化处理
LeakyReLU()和ReLU()函数的区别
- ReLU():x>0:输出x;x<0,输出0
- LeakyReLU():f(x):x>0,输出x;x<0,输出a*x(a表示一个很小的斜率值)
为什么要计算梯度?
计算梯度的主要目的是通过优化算法调整模型的参数,以最小化损失函数。以下是具体原因:
(1)优化模型参数
梯度是优化算法(如梯度下降)的基础。通过计算损失函数对每个参数的梯度,可以知道如何调整参数以减少损失。
例如,在梯度下降中,参数更新公式为:
θnew=θold−η⋅∇L(θ)
其中,η 是学习率(learning rate),表示每次更新的步长。
(2)找到损失函数的最小值
- 梯度指向损失函数增加最快的方向,而负梯度指向损失函数减少最快的方向。
- 通过沿着负梯度方向更新参数,可以逐步找到损失函数的最小值。
(3)自动微分
- 神经网络的训练涉及复杂的函数组合,手动计算梯度非常困难且容易出错。
- PyTorch 和 TensorFlow 等深度学习框架通过自动微分(Automatic Differentiation)技术,自动计算梯度,大大简化了训练过程。
为什么有时需要权重初始化?
- 避免梯度消失或爆炸。
- 加速模型收敛。
- 打破对称性,使每个神经元能够学习不同的特征。
- 提高模型的最终性能。
常见的损失函数及其适用领域和任务的详细说明:
独家技巧
- 一般情况:在大多数CNN架构中,平均池化层后面通常会跟一个平展层,因为平展后的特征通常用于全连接层的输入,进行分类或回归任务。
- 注意:bn层里面放前一个通道数的大小
- 全连接层(Fully Connected Layer)和卷积层(Convolutional Layer)后一般会跟着一个激活函数(Activation Function)。
- 在 PyTorch 中,当你创建一个 nn.Module 的实例时,例如 self.c1 = Conv_Block(3, 64),这会调用 Conv_Block 类的 init
方法,初始化模块的参数。而当你调用模块实例,例如 R1 = self.c1(x),这会自动调用 Conv_Block 类的 forward 方法,执行前向传播逻辑。 - 必备公式:OH=(H+2*P-FH)/S+1;其中OH是计算后的高度,H是计算前的高度,FH是卷积和的高度。
- 在Gan网络中,判别器中的激活函数推荐使用LeakyReLU(),可以保留一定的梯度信息
- 在交叉熵损失中我们一般使用BECLoss()函数;交叉熵损失函数(Cross-Entropy Loss)常用于分类任务,尤其是二分类任务(Binary Cross-Entropy Loss,简称 BCELoss)和多分类任务(Categorical Cross-Entropy Loss)
- len(dataloader)返回批次数,len(dataset)返回样本数
- 注意:nn.imshow() 默认期望的范围是 [0, 1] 或 [0, 255]
- 在数据加载的时候,训练阶段需要
shuffle=True
。而验证和测试阶段为shuffle=True
,因为保持数据的原始顺序可以方便地与真实标签进行对比,从而更准确地评估模型的性能。