李宏毅深度学习课程Spring2022作业1 改进

分为 simple baseline medium 、strong、boss

上一篇 : simple:
在这里插入图片描述
在这里插入图片描述

1. 小结

  • Medium Baseline (mse<1.49430): 使用特征选择(feature selection)。原始特征有117个,噪音较多,神经网络学习相对困难。因为我们预测的是第5天的tested_postive,比较合理的想法是选择前四天的tested_positive数据作为训练特征。因这四个特征对应的index是[53, 69, 85, 101],我们将select_feat函数中的feat_idx 进行修改。
  • Strong Baseline (mse<1.05728): 使用特征选择+网络架构采用LeakyReLU + Adam优化器。特征选择仍然用medium baseline的方法,网络架构中将nn.ReLU()代替为nn.LeakyReLU(0.1),将SGD优化器换成Adam,同时将learning rate由原来的1e-5扩大10倍。
  • Boss Baseline (mse<0.85800): 使用更精准的特征选择+归一化+网络架构改变+Adam优化器+余弦退火学习率。特征选择利用sklearn中的特征选择方法,选择了24个最有影响的特征。对特征进行归一化处理,将其转换到[0, 1]区间内。网络架构中将nn.ReLU()代替为nn.LeakyReLU(0.1),同时变动了层的宽度,使用了dropout减少过拟合。将SGD优化器换成Adam,学习率使用余弦退火。

2. medium : feature selection

https://editor.csdn.net/md/?articleId=134950253

特征选择

见之前的文章: [feature_select](https://blog.csdn.net/weixin_39107270/article/details/134950253?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170303766016800197015774%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=170303766016800197015774&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-2-13495025
3-null-null.nonecase&utm_term=feature%20selec&spm=1018.2226.3001.4450)

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_regression

features = pd.read_csv('./covid.train.csv')
x_data, y_data = features.iloc[:, 0:117], features.iloc[:, 117]

#try choose your k best features
k = 24
selector = SelectKBest(score_func=f_regression, k=k)
result = selector.fit(x_data, y_data)

#result.scores_ inclues scores for each features
#np.argsort sort scores in ascending order by index, we reverse it to make it descending.
idx = np.argsort(result.scores_)[::-1]
print(f'Top {k} Best feature score ')
print(result.scores_[idx[:k]])

print(f'\nTop {k} Best feature index ')
print(idx[:k])

print(f'\nTop {k} Best feature name')
print(x_data.columns[idx[:k]])

selected_idx = list(np.sort(idx[:k]))
print(selected_idx)
print(x_data.columns[selected_idx])

3. strong : Different model architectures and optimizers

optimizers: 修改优化器

这是一些用于训练神经网络和深度学习模型的优化算法,它们用于更新模型的权重以最小化损失函数。以下是这些优化算法的简要介绍:

Adam (Adaptive Moment Estimation): Adam 是一种自适应学习率的优化算法。它结合了动量和自适应学习率的特性,能够在训练过程中自动调整学习率。Adam 通常被认为是一种有效的优化算法,对于各种深度学习任务都表现良好。Adam: RMSProp + Moment

SGD (Stochastic Gradient Descent): 随机梯度下降是深度学习中最基本的优化算法之一。它在每个训练样本上计算梯度并更新模型权重。虽然简单,但 SGD 可能需要较长时间才能收敛,因此通常需要手动调整学习率。

Adagrad (Adaptive Gradient Algorithm): Adagrad 是一种自适应学习率算法,它根据每个参数的历史梯度来调整学习率。这意味着对于频繁出现的参数,学习率会逐渐减小,从而使其收敛得更快。但在某些情况下,学习率可能会过于降低,导致训练不稳定。

RMSprop (Root Mean Square Propagation): RMSprop 也是一种自适应学习率算法,它使用了类似 Adagrad 的思想,但引入了一个衰减系数来限制历史梯度的影响。这有助于克服 Adagrad 中学习率过于降低的问题。

Sparse Adam: Sparse Adam 是对标准 Adam 算法的一种变体,专门用于处理稀疏数据和稀疏梯度。它在处理大规模稀疏数据时通常效果更好。

这些优化算法在深度学习中起到关键作用,不同的算法适用于不同的问题和数据集。选择合适的优化算法通常取决于具体的任务和模型。Adam /AdamW通常被认为是一种默认的选择,因为它在许多情况下表现良好。

    #optimizer = torch.optim.SGD(model.parameters(), lr=config['learning_rate'], momentum=0.9) 
    optimizer = torch.optim.Adam(model.parameters(), lr=config['learning_rate']*10)

修改模型深度

加深神经网络的层数。但是这个问题本身足够简单,数据量也不大,所以不能带来明显提升。

修改激活函数:

带泄露修正线性单元(Leaky ReLU)函数是经典(以及广泛使用的)的ReLu激活函数的变体,该函数输出对负值输入有很小的坡度。由于导数总是不为零,这能减少静默神经元的出现,允许基于梯度的学习(虽然会很慢),解决了Relu函数进入负区间后,导致神经元不学习的问题。
Andrew Ng说:

1,Leaky ReLU函数比ReLU函数效果好,但实际中Leaky ReLU并没有ReLU用的多。

2,除了输出层是一个二元分类问题外,基本不用Sigmoid函数

3,Relu是最常用的默认激活函数,若不确定用哪个激活函数,就使用Relu或者Leaky Relu

class My_Model(nn.Module):
    def __init__(self, input_dim):
        super(My_Model, self).__init__()
        # TODO: modify model's structure, be aware of dimensions. 
        self.layers = nn.Sequential(
            nn.Linear(input_dim, 16),
            nn.LeakyReLU(0.1),
            nn.Linear(16, 8),
            nn.LeakyReLU(0.1),            
            nn.Linear(8, 1)
        )

    def forward(self, x):
        x = self.layers(x)
        x = x.squeeze(1) # (B, 1) -> (B)
        return x

4. boss: L2正则化和更多参数

针对过拟合现象,可以通过正则化和 Dropout 缓解
权重衰减是最广泛使用的正则化的技术之一,通常被称为L2正则化。
当权重比较大时,在测试集上,预测错的概率更大,过拟合越严重。 所以,在保证正确率的基础上,尽量使得 权重 w 也小。

L2正则化

在这里插入图片描述
实现方法一:
pytorch实现L2和L1正则化regularization的方法
torch.optim优化器实现L2正则化
torch.optim集成了很多优化器,如SGD,Adadelta,Adam,Adagrad,RMSprop等,这些优化器自带的一个参数weight_decay,用于指定权值衰减率,相当于L2正则化中的λ参数,注意torch.optim集成的优化器只有L2正则化方法,你可以查看注释,参数weight_decay 的解析是:

 weight_decay (float, optional): weight decay (L2 penalty) (default: 0)

使用torch.optim的优化器,可如下设置L2正则化

optimizer = optim.Adam(model.parameters(),lr=learning_rate,weight_decay=0.01)

方法二:

class NN_Model(nn.Module):
    def __init__(self, input_dim):
        super(NN_Model, self).__init__()
        # TODO: modify model's structure, be aware of dimensions. 
        self.layers = nn.Sequential(
            nn.Linear(input_dim, 16),
            nn.BatchNorm1d(16),
            nn.LeakyReLU(),
            nn.Dropout(0.1),
            nn.Linear(16, 1)
            nn.BatchNorm1d(8),
            nn.LeakyReLU(),
            nn.Dropout(0.1),
            nn.Linear(8,1)
        )
        self.criterion = nn.MSELoss(reduction='mean')
        #self.criterion = nn.CrossEntropyLoss()

    def forward(self, x):
        x = self.layers(x)
        x = x.squeeze(1) # (B, 1) -> (B)
        return x
    #添加L2正则项
    def regularization(self, coef):
      item = 0
      for param in self.net.parameters():
        item += torch.norm(param,2)
      res = coef*item
      return res

    def cal_loss(self,pred,target):
      #RMSE+L2 regularization
      loss = torch.sqrt(self.criterion(pred, target)) + self.regularization(0) 
      return loss
      return loss

Dropout

好的模型具有泛化性、平滑性。即函数不应该对其输入的微小变化敏感。例如,当我们对图像进行分类时,我们预计向像素添加一些随机噪声应该是基本无影响的。 1995年,克里斯托弗·毕晓普证明了 具有输入噪声的训练等价于Tikhonov正则化 (Bishop, 1995)。 这项工作用数学证实了“要求函数光滑”和“要求函数对输入的随机噪声具有适应性”之间的联系。
暂退法在前向传播过程中,计算每一内部层的同时注入噪声,这已经成为训练神经网络的常用技术。 这种方法之所以被称为暂退法,因为我们从表面上看是在训练过程中丢弃(drop out)一些神经元。 在整个训练过程的每一次迭代中,标准暂退法包括在计算下一层之前将当前层中的一些节点置零。
那么关键的挑战就是如何注入这种噪声。 一种想法是以一种无偏向(unbiased)的方式注入噪声。 这样在固定住其他层时,每一层的期望值等于没有噪音时的值。
在这里插入图片描述

代码

class My_Model(nn.Module):
    def __init__(self, input_dim):
        super(My_Model, self).__init__()
        # TODO: modify model's structure, be aware of dimensions. 
        #input_dim is the num of features we selected
        self.layers = nn.Sequential(
            nn.Linear(input_dim, 64),
            nn.LeakyReLU(0.2),
            nn.BatchNorm1d(64),
            nn.Dropout(0.2),
            
            nn.Linear(64, 16),
            nn.LeakyReLU(0.2),
            #nn.BatchNorm1d(10),
            nn.Dropout(0.1),
            
            nn.Linear(16, 1)
        )

    def forward(self, x):
        x = self.layers(x)
        x = x.squeeze(1) # (B, 1) -> (B)
        return x

BatchNormalization

torch.nn.BatchNorm1d()是为了保持深度神经网络训练过程中每一层神经网络的输入同分布的方法。训练深度网络的时候经常发生训练困难的问题:因为,每一次参数迭代更新后,上一层网络的输出数据经过这一层网络计算后,数据的分布会发生变化,为下一层网络的学习带来困难,这被称为Internal Covariate Shift。为了解决Internal Covariate Shift,我们使用Batch Normalization。

torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  • num_features – 特征维度
  • eps – 为数值稳定性而加到分母上的值。
  • momentum – 移动平均的动量值。
  • affine – 一个布尔值,当设置为真时,此模块具有可学习的仿射参数。

余弦退火

主要两个方面: 1。根据余弦半周期的变化趋势,梯度先缓慢下降再极速下降再换忙下降
2. 为了避免陷入局部最优解,有时候需要突然增大学习率。,来“跳出”局部最小值并找到通向全局最小值的路径。这种方式称为带重启的随机梯度下降方法。
【学习率调整】学习率衰减之周期余弦退火 (cyclic cosine annealing learning rate schedule)
https://pytorch.org/docs/stable/optim.html
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
参考:
HW01

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闪闪发亮的小星星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值