网易首页 > 网易号 > 正文 申请入驻

使用PyTorch实现L1, L2和Elastic Net正则化

0
分享至


在机器学习中,L1正则化、L2正则化和Elastic Net正则化是用来避免过拟合的技术,它们通过在损失函数中添加一个惩罚项来实现。



正则化介绍

L1 正则化(Lasso回归)

L1 正则化通过向损失函数添加参数的绝对值的和来实施惩罚,公式可以表示为:



其中 L0 是原始的损失函数,λ 是正则化强度,wi是模型参数。

L1 正则化的特点是它可以产生稀疏模型,即许多模型参数会被设置为零。这种特性使得L1正则化不仅可以防止过拟合,还可以进行特征选择。

L2 正则化(Ridge回归)

L2 正则化通过添加参数的平方和来施加惩罚,公式为:



λ 控制着正则化的强度。

L2 正则化倾向于让参数值趋近于零但不会完全为零,这有助于处理参数值过大的问题,从而减少模型在训练数据上的过拟合。

Elastic Net 正则化

Elastic Net 正则化是L1和L2正则化的组合,它在损失函数中同时添加了L1和L2惩罚项,公式为:



这种方法结合了L1和L2的优点,既可以产生稀疏模型,也可以平滑模型参数。

在实际应用中,Elastic Net特别适合于那些特征数量多于样本数量,或者特征之间高度相关的情况。

在sklearn中,我们可以使用内置的回归函数来实现

Lasso回归是应用L1正则化的典型模型。它可以通过Lasso类实现;Ridge回归使用L2正则化。它可以通过Ridge类来实现;Elastic Net回归结合了L1和L2正则化。它通过ElasticNet类实现

Pytorch代码实现

但是这些都是最简单的线性回归的扩展,通过上面的介绍,我们看到这些正则化的方式都是通过修改模型本身的权重来实现的,所以我们可以在MLP上也使用这些正则化的方法,下面我们将使用Pytorch来演示这个步骤

首先我们看下L1

import os
import torch
from torch import nn
from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
from torchvision import transforms
class MLP(nn.Module):
'''
Multilayer Perceptron.
'''
def __init__(self):
super().__init__()
self.layers = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28 * 1, 64),
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 10)
)
def forward(self, x):
'''Forward pass'''
return self.layers(x)
def compute_l1_loss(self, w):
return torch.abs(w).sum()
if __name__ == '__main__':
# Set fixed random number seed
torch.manual_seed(42)
# Prepare CIFAR-10 dataset
dataset = MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())
trainloader = torch.utils.data.DataLoader(dataset, batch_size=10, shuffle=True, num_workers=1)
# Initialize the MLP
mlp = MLP()
# Define the loss function and optimizer
loss_function = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(mlp.parameters(), lr=1e-4)
# Run the training loop
for epoch in range(0, 5): # 5 epochs at maximum
# Print epoch
print(f'Starting epoch {epoch+1}')
# Iterate over the DataLoader for training data
for i, data in enumerate(trainloader, 0):
# Get inputs
inputs, targets = data
# Zero the gradients
optimizer.zero_grad()
# Perform forward pass
outputs = mlp(inputs)
# Compute loss
loss = loss_function(outputs, targets)
# Compute L1 loss component
l1_weight = 1.0
l1_parameters = []
for parameter in mlp.parameters():
l1_parameters.append(parameter.view(-1))
l1 = l1_weight * mlp.compute_l1_loss(torch.cat(l1_parameters))
# Add L1 loss component
loss += l1
# Perform backward pass
loss.backward()
# Perform optimization
optimizer.step()
# Print statistics
minibatch_loss = loss.item()
if i % 500 == 499:
print('Loss after mini-batch %5d: %.5f (of which %.5f L1 loss)' %
(i + 1, minibatch_loss, l1))
current_loss = 0.0
# Process is complete.
print('Training process has finished.')

我们在本身的一个简单的MLP中增加了一个compute_l1_loss方法,在我们计算完基本的损失后,还会计算模型参数的L1 损失,然后与基本损失相加,最后使用这个最终损失来进行反向传播。

L2正则化也很容易。我们不取权重值的绝对值,而是取它们的平方。

import os
import torch
from torch import nn
from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
from torchvision import transforms
class MLP(nn.Module):
'''
Multilayer Perceptron.
'''
def __init__(self):
super().__init__()
self.layers = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28 * 1, 64),
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 10)
)
def forward(self, x):
'''Forward pass'''
return self.layers(x)
def compute_l2_loss(self, w):
return torch.square(w).sum()
if __name__ == '__main__':
# Set fixed random number seed
torch.manual_seed(42)
# Prepare CIFAR-10 dataset
dataset = MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())
trainloader = torch.utils.data.DataLoader(dataset, batch_size=10, shuffle=True, num_workers=1)
# Initialize the MLP
mlp = MLP()
# Define the loss function and optimizer
loss_function = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(mlp.parameters(), lr=1e-4)
# Run the training loop
for epoch in range(0, 5): # 5 epochs at maximum
# Print epoch
print(f'Starting epoch {epoch+1}')
# Iterate over the DataLoader for training data
for i, data in enumerate(trainloader, 0):
# Get inputs
inputs, targets = data
# Zero the gradients
optimizer.zero_grad()
# Perform forward pass
outputs = mlp(inputs)
# Compute loss
loss = loss_function(outputs, targets)
# Compute l2 loss component
l2_weight = 1.0
l2_parameters = []
for parameter in mlp.parameters():
l2_parameters.append(parameter.view(-1))
l2 = l2_weight * mlp.compute_l2_loss(torch.cat(l2_parameters))
# Add l2 loss component
loss += l2
# Perform backward pass
loss.backward()
# Perform optimization
optimizer.step()
# Print statistics
minibatch_loss = loss.item()
if i % 500 == 499:
print('Loss after mini-batch %5d: %.5f (of which %.5f l2 loss)' %
(i + 1, minibatch_loss, l2))
current_loss = 0.0
# Process is complete.
print('Training process has finished.')

最终的计算过程和L1正则化一样,只不过是计算附加损失的方法不同。

对于L2的正则化Pytorch的Adam优化器有一个官方的参数,叫做权重衰减weight_decay

optimizer = torch.optim.Adam(mlp.parameters(), lr=1e-4, weight_decay=1.0)

你可能不知道他和L2的关系,但是你一定用到过,所以我们这样一解释就非常明白了对吧

最后就是Elastic Net (L1 + L2)

class MLP(nn.Module):
'''
Multilayer Perceptron.
'''
def __init__(self):
super().__init__()
self.layers = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28 * 1, 64),
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 10)
)
def forward(self, x):
'''Forward pass'''
return self.layers(x)
def compute_l1_loss(self, w):
return torch.abs(w).sum()
def compute_l2_loss(self, w):
return torch.square(w).sum()
if __name__ == '__main__':
# Set fixed random number seed
torch.manual_seed(42)
# Prepare CIFAR-10 dataset
dataset = MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())
trainloader = torch.utils.data.DataLoader(dataset, batch_size=10, shuffle=True, num_workers=1)
# Initialize the MLP
mlp = MLP()
# Define the loss function and optimizer
loss_function = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(mlp.parameters(), lr=1e-4)
# Run the training loop
for epoch in range(0, 5): # 5 epochs at maximum
# Print epoch
print(f'Starting epoch {epoch+1}')
# Iterate over the DataLoader for training data
for i, data in enumerate(trainloader, 0):
# Get inputs
inputs, targets = data
# Zero the gradients
optimizer.zero_grad()
# Perform forward pass
outputs = mlp(inputs)
# Compute loss
loss = loss_function(outputs, targets)
# Specify L1 and L2 weights
l1_weight = 0.3
l2_weight = 0.7
# Compute L1 and L2 loss component
parameters = []
for parameter in mlp.parameters():
parameters.append(parameter.view(-1))
l1 = l1_weight * mlp.compute_l1_loss(torch.cat(parameters))
l2 = l2_weight * mlp.compute_l2_loss(torch.cat(parameters))
# Add L1 and L2 loss components
loss += l1
loss += l2
# Perform backward pass
loss.backward()
# Perform optimization
optimizer.step()
# Print statistics
minibatch_loss = loss.item()
if i % 500 == 499:
print('Loss after mini-batch %5d: %.5f (of which %.5f L1 loss; %0.5f L2 loss)' %
(i + 1, minibatch_loss, l1, l2))
current_loss = 0.0
# Process is complete.
print('Training process has finished.')

也非常的简单,并且我们可以设置两个权重,就是L1和L2的占比,使用不同的加权,可以获得更好的结果。

总结

这篇文章是要是为了介绍L1, L2和Elastic Net (L1+L2)正则化在理论上是如何工作的。并且我们也在PyTorch中使用了L1, L2和Elastic Net (L1+L2)正则化。这三种正则化方法在不同的情况和数据集上有不同的效果,选择哪种正则化方法取决于具体的应用场景和数据特性。

https://avoid.overfit.cn/post/c99ec105e41c4a71a0a1a29735245944

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
越闹越大!局长质问央视记者污水毒性,官方回应来了,评论区炸锅

越闹越大!局长质问央视记者污水毒性,官方回应来了,评论区炸锅

白小李的自留地
2024-05-28 21:45:47
特斯拉停在小米汽车旁边.…突然感觉

特斯拉停在小米汽车旁边.…突然感觉

悠闲葡萄
2024-05-28 21:23:38
女子电子厂上班晒真实收入:工作28天日均12个小时,工资到手发了6300多块

女子电子厂上班晒真实收入:工作28天日均12个小时,工资到手发了6300多块

六子吃凉粉
2024-05-28 13:50:46
楼市大放松!彻底不装了!

楼市大放松!彻底不装了!

樱桃大房子
2024-05-28 22:05:59
上海的楼市大招,给我看乐了

上海的楼市大招,给我看乐了

中产先生
2024-05-28 13:38:57
刚刚!广州,打响第一枪!

刚刚!广州,打响第一枪!

中国基金报
2024-05-28 19:22:46
某平台小女主播户外直播尿尿

某平台小女主播户外直播尿尿

姜子牙道长
2024-05-28 22:20:15
制裁再次升级,日本海鲜被彻底赶出中国市场

制裁再次升级,日本海鲜被彻底赶出中国市场

枫冷慕诗
2024-05-28 19:30:03
台湾上空发生激烈交锋,中美军机交手,专家发现不对:大陆咋来的

台湾上空发生激烈交锋,中美军机交手,专家发现不对:大陆咋来的

星辰故事屋
2024-05-27 22:00:17
妻子陪初恋男友法国游玩,下飞机才通知丈夫,返回后直接愣在机场

妻子陪初恋男友法国游玩,下飞机才通知丈夫,返回后直接愣在机场

局内人
2024-05-15 14:12:33
前世界第一爆冷输球!朱琳30次非受迫性失误,郑钦文发文送别老将

前世界第一爆冷输球!朱琳30次非受迫性失误,郑钦文发文送别老将

排球黄金眼
2024-05-29 02:09:32
赴韩参会不访韩,只待一天就匆匆回国,中国的态度,日韩读懂了吗

赴韩参会不访韩,只待一天就匆匆回国,中国的态度,日韩读懂了吗

小豆豆赛事
2024-05-28 16:47:27
中国正式回复泽连斯基,若他继续假装听不懂,普京恐不会再手软了

中国正式回复泽连斯基,若他继续假装听不懂,普京恐不会再手软了

千里持剑
2024-05-28 16:58:30
广东南粤银行:6月1日起,终止个人贷款理财账户业务

广东南粤银行:6月1日起,终止个人贷款理财账户业务

财经网
2024-05-24 14:33:07
“发现一个、查处一个”!中央纪委重要内设部门,披露查办“老虎”孙力军案细节

“发现一个、查处一个”!中央纪委重要内设部门,披露查办“老虎”孙力军案细节

政知新媒体
2024-05-28 19:31:46
俄罗斯宣布进入紧急状态,巨亏之下俄天然气公司生产洗衣机自救

俄罗斯宣布进入紧急状态,巨亏之下俄天然气公司生产洗衣机自救

史政先锋
2024-05-28 21:00:36
有一种痛苦叫“凉席”,没销量还不受待见,正在淡出无数中国家庭

有一种痛苦叫“凉席”,没销量还不受待见,正在淡出无数中国家庭

装修秀
2024-05-27 17:07:55
好家伙,这是立了多大的功,给全国人民发短信,表扬大家收到了吗

好家伙,这是立了多大的功,给全国人民发短信,表扬大家收到了吗

芯怡飞
2024-05-28 08:25:19
两盘横扫晋级!郑钦文仅丢3局轻松过关,连续3年突破法网首轮

两盘横扫晋级!郑钦文仅丢3局轻松过关,连续3年突破法网首轮

ALL体育
2024-05-28 19:34:43
将近40岁满脸褶,却尬演18岁少女,是谁给了她“强行装嫩”的勇气

将近40岁满脸褶,却尬演18岁少女,是谁给了她“强行装嫩”的勇气

娱乐圈十三太保
2024-05-28 13:56:53
2024-05-29 07:02:44
deephub
deephub
CV NLP和数据挖掘知识
1350文章数 1414关注度
往期回顾 全部

科技要闻

4月中国手机需求回升 iPhone出货量增长52%

头条要闻

安徽坍塌居民楼结构脆弱 专家称其"像积木搭在墙上"

头条要闻

安徽坍塌居民楼结构脆弱 专家称其"像积木搭在墙上"

体育要闻

商讨球队建队计划?巴萨主席拉波尔塔与弗里克共进晚餐

娱乐要闻

昆凌晒三胎正面照,2岁妹妹超像周杰伦

财经要闻

东方通收购藏雷 花6亿买来"业绩变脸"

汽车要闻

三联屏/纯电续航318km 岚图FREE 318官图发布

态度原创

教育
家居
手机
亲子
军事航空

教育要闻

TTS新传高级名词解释:疤痕效应|对青年的持续损害

家居要闻

圆的世界 流动的曲线与自如的空间

手机要闻

荣耀双喜同至:荣耀X60已入网,Magic6系列卫星通信功能上线!

亲子要闻

妈妈分享自家萌娃玩蹦蹦车的样子,这不就是爷爷奶奶的梦中情孙吗

军事要闻

以军装甲部队进入加沙地带南部城市拉法市中心

无障碍浏览 进入关怀版