Task3-DatawhaleX 李宏毅苹果书AI夏令营-深度学习入门
1、学习链接:
https://linklearner.com/activity/16/14/562、视频链接:
3、相关笔记以及理解
模型偏差(Model Bias): 模型偏差描述的是模型的预测结果与真实数据之间差异的系统性错误。在统计学中,偏差可以通过期望预测误差来量化。 优化问题(Optimization Problem): 优化问题通常涉及寻找一组参数,使得损失函数(如均方误差、交叉熵等)最小化。在机器学习中,常用的优化算法包括梯度下降法。 过拟合(Overfitting): 过拟合发生在模型在训练数据上表现很好,但在未见过的数据上表现差的情况。这可以通过增加数据集大小、使用正则化技术(如L1、L2正则化)、早停(early stopping)等方法来缓解。 交叉验证(Cross-validation): 交叉验证是一种评估模型泛化能力的方法,通常涉及将数据集分成多个子集,然后使用部分子集训练模型,剩余的子集用于验证。 不匹配(Mismatch): 不匹配指的是训练数据和测试数据分布不一致的情况。这可能导致模型在训练集上表现良好,但在测试集上表现不佳。 深度学习(Deep Learning): 深度学习涉及使用多层神经网络来学习数据的复杂模式。这通常包括前向传播和反向传播算法,以及激活函数(如ReLU、sigmoid等)。 残差网络(Residual Networks, ResNets): 残差网络通过引入跳跃连接来解决深层网络训练中的退化问题。数学上,这涉及到残差块的设计,其中输入和输出通过跳跃连接相加。 数据增强(Data Augmentation): 数据增强通过变换训练数据(如旋转、缩放、裁剪等)来增加数据的多样性,从而提高模型的泛化能力。 丢弃法(Dropout): Dropout是一种正则化技术,通过在训练过程中随机丢弃(置零)网络中的一些神经元,以防止模型过拟合。
优化机器学习模型性能通常涉及以下几个方面:
1. 损失函数:
选择合适的损失函数来量化模型预测与实际结果之间的差异。常见的损失函数包括均方误差(MSE)用于回归问题,交叉熵损失用于分类问题。
\[ \text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 \]
\[ \text{Cross-Entropy} = -\sum_{i=1}^{n} t_i \log(\hat{t}_i) \]
其中 \( y_i \) 是真实值,\( \hat{y}_i \) 是预测值,\( t_i \) 是目标概率(通常是 0 或 1),\( \hat{t}_i \) 是预测概率。
2. 优化算法:
利用梯度下降或其变体(如随机梯度下降 SGD、Adam 等)来最小化损失函数。
\[ \theta = \theta - \eta \nabla_\theta J(\theta) \]
其中 \( \theta \) 表示模型参数,\( \eta \) 是学习率,\( J(\theta) \) 是损失函数,\( \nabla_\theta J(\theta) \) 是损失函数关于参数的梯度。
3. 正则化:
为了防止过拟合,可以在损失函数中添加正则化项,如 L1 或 L2 正则化。
\[ J_{\text{regularized}}(\theta) = J(\theta) + \lambda \sum_{i=1}^{n} \theta_i^2 \text{ (L2 regularization)} \]
其中 \( \lambda \) 是正则化系数。
4. 早停:
在训练过程中,当验证集上的性能不再提升时停止训练,以避免过拟合。
早停不涉及特定的数学公式,但它是一种有效的模型性能优化策略。
5. 超参数调整:
通过调整学习率、正则化系数、网络层数、神经元数量等超参数来优化模型。
可以使用网格搜索(Grid Search)、随机搜索(Random Search)或贝叶斯优化等方法。
6. 模型选择准则:
使用如 AIC(赤池信息准则)或 BIC(贝叶斯信息准则)等准则来选择模型。
\[ \text{AIC} = 2k - 2\log(\hat{L}) \]
\[ \text{BIC} = \log(n)k - 2\log(\hat{L}) \]
其中 \( k \) 是模型参数的数量,\( \hat{L} \) 是最大似然估计,\( n \) 是样本数量。
7. 交叉验证:
使用 k 折交叉验证来评估模型的泛化能力。
计算每一折的损失,然后取平均值作为模型性能的估计。
8. 数据增强:
通过变换训练数据来增加数据集的多样性,从而提高模型的泛化能力。
9. 批量归一化:
通过规范化神经网络中间层的输出来提高训练的稳定性和速度。
\[ \hat{x} = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} \]
\[ y = \gamma \hat{x} + \beta \]
其中 \( x \) 是层的输入,\( \mu \) 和 \( \sigma^2 \) 分别是该层输出的均值和方差,\( \epsilon \) 是一个小的常数以防止除以零,\( \gamma \) 和 \( \beta \) 是可学习的参数。
通过结合数学公式和算法,可以系统地优化机器学习模型的性能。
解决过拟合问题有多种策略,以下是一些常见的方法:
1、 增加训练数据:
通过增加更多的训练样本来提高模型的泛化能力。
2、 数据增强:
对训练数据进行变换,如旋转、缩放、裁剪等,以增加数据的多样性。
3、 限制模型复杂度:
减少模型的层数或每层的神经元数量,减少模型的参数量。
4、 正则化:
在损失函数中添加正则项,如L1或L2正则化,以惩罚大的权重值。
5、 丢弃法:
在训练过程中随机丢弃一部分神经元,以减少模型对特定数据的依赖。
6、 早停:
当验证集上的性能不再提升时停止训练,以避免过度拟合训练数据。
7、 使用预训练模型:
使用在大量数据上预训练的模型作为特征提取器,只训练顶层分类器。
8、 集成学习:
结合多个模型的预测结果,如随机森林或Boosting方法。
9、 权重衰减:
与L2正则化类似,通过减小权重的大小来减少过拟合。
下面给出一个关于通过权重衰减早停方法解决过拟合问题的方法:
import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader from torchvision import datasets, transforms from torch.optim.lr_scheduler import StepLR from torch.nn.utils import clip_grad_norm_ # 数据增强 transform = transforms.Compose([ transforms.RandomHorizontalFlip(), transforms.RandomRotation(10), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 加载数据集 train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True) test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False) # 定义模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) self.dropout = nn.Dropout(0.5) self.fc1 = nn.Linear(64 * 8 * 8, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = F.relu(self.conv1(x)) x = F.max_pool2d(x, 2) x = F.relu(self.conv2(x)) x = F.max_pool2d(x, 2) x = x.view(-1, 64 * 8 * 8) x = self.dropout(x) x = F.relu(self.fc1(x)) x = self.fc2(x) return x model = Net() # 权重衰减 optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4) # 早停 class EarlyStopping: def __init__(self, patience=7, verbose=False): self.patience = patience self.verbose = verbose self.counter = 0 self.best_loss = None def __call__(self, val_loss, model): if self.best_loss is None: self.best_loss = val_loss elif val_loss > self.best_loss: self.counter += 1 if self.counter >= self.patience: if self.verbose: print(f'Early stopping') return True else: self.best_loss = val_loss self.counter = 0 return False early_stopping = EarlyStopping(patience=10, verbose=True) # 训练模型 def train_epoch(model, train_loader, optimizer, criterion): model.train() total_loss = 0 for data, target in train_loader: optimizer.zero_grad() output = model(data) loss = criterion(output, target) loss.backward() clip_grad_norm_(model.parameters(), 1) optimizer.step() total_loss += loss.item() return total_loss / len(train_loader) def evaluate_model(model, test_loader, criterion): model.eval() total_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: output = model(data) loss = criterion(output, target) total_loss += loss.item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() return total_loss / len(test_loader), correct / len(test_loader.dataset) criterion = nn.CrossEntropyLoss() best_val_loss = float('inf') for epoch in range(50): val_loss, val_accuracy = evaluate_model(model, test_loader, criterion) improved = early_stopping(val_loss, model) if improved: print(f'Stopping early at epoch {epoch}') break train_loss = train_epoch(model, train_loader, optimizer, criterion) print(f'Epoch {epoch}: Train Loss = {train_loss:.4f}, Val Loss = {val_loss:.4f}, Val Accuracy = {val_accuracy:.4f}')
4、总结和感悟
通过三次的Datawhale 打卡学习,我对深度学习的基本概念有了更加深入的认识和理解,原来对一些知识点比如梯度下降和过拟合问题的优化存在很多困惑,经过学习后从原理上对问题进行了剖析。