关于权重衰减可以看一下我贴上来的的笔记
下面时使用高维线性模型来进行权重衰减的实现的jupyter代码
#%%
'''
验证权重衰减的高纬线性回归实验
'''
%matplotlib inline
import torch
import torch.nn as nn
import numpy as np
import sys
sys.path.append("..")
import dlzh.d2lzh_pytorch as d2l
#%%
'''
标签生成函数为 y=0.05+sum(0.01x_i)+noise
其中噪声项noise服从均值为0,标准差为0。01的正态分布
这里为了形成过拟合的情况,所以训练数据集变少设置为20
设置维度为200
'''
n_train,n_test,num_inputs=20,100,200
true_w, true_b = torch.ones(num_inputs, 1) * 0.01, 0.05
features = torch.randn((n_train + n_test, num_inputs))
labels = torch.matmul(features, true_w) + true_b
labels += torch.tensor(np.random.normal(0, 0.01,size=labels.size()), dtype=torch.float)
train_features, test_features = features[:n_train, :],features[n_train:, :]
train_labels, test_labels = labels[:n_train], labels[n_train:]
#%%
'''1. 首先随机初始化模型参数'''
#定义随机初始化模型参数的函数,该函数为每个参数附上梯度
def init_params():
w=torch.randn((num_inputs,1),requires_grad=True)
b=torch.zeros(1,requires_grad=True)
return [w,b]
#%%
'''2. 定义L2范数的惩罚项'''
#这里没有采用矩阵的乘法,因为矩阵的乘法该是多少行多少列实在是太麻烦了
def l2_penalty(w):
return (w**2).sum()/2
#%%
'''3. 定义和训练模型'''
batch_size,num_enpochs,lr=1,100,0.003
net,loss=d2l.linreg,d2l.squared_loss
dataset=torch.utils.data.TensorDataset(train_features,train_labels)
train_iter=torch.utils.data.DataLoader(dataset,batch_size=batch_size,shuffle=True)
#训练模型,这里唯一的参数就是惩罚项的lamdb参数
def fit_and_plot(lambd):
w,b=init_params()
#用来记录训练误差和测试误差
train_ls,test_ls=[],[]
for _ in range(num_enpochs):
for X,y in train_iter:
y_pre=net(X,w,b)
l=loss(y_pre,y)+lambd*l2_penalty(w)
#这里求和是为了后面的反向传播方便,因为使用backward()函数最好是一个值而不是一个tensor
l=l.sum()
if w.grad is not None:
w.grad.data.zero_()
b.grad.data.zero_()
l.backward()
d2l.sgd([w,b],lr,batch_size)
train_ls.append(loss(net(train_features,w,b),train_labels).mean().item())
test_ls.append(loss(net(test_features,w,b),test_labels).mean().item())
d2l.semilogy(range(1, num_enpochs + 1), train_ls, 'epochs',
'loss',range(1, num_enpochs + 1), test_ls, ['train','test'])
print('L2 norm of w:', w.norm().item())
#%%
#当不设置lamda参数时
fit_and_plot(0)
#%%
#将lamda参数设置为5的时候
fit_and_plot(5)
这里有几个function用到了自己写的一个库中的function,我把用到的贴上来大家看一下
#这个函数时批量梯度优化函数
def sgd(params, lr, batch_size):
for param in params:
param.data -= lr * param.grad / batch_size # 注意这里更改param时用的param.data
#线性模型
def linreg(X, w, b):
return torch.mm(X, w) + b
# 平方loss function
def squared_loss(y_hat, y):
# 注意这里返回的是向量, 另外, pytorch里的MSELoss并没有除以 2
return ((y_hat - y.view(y_hat.size())) ** 2) / 2
最后一个semilogy是一个画图函数就不贴啦,大家可以自己画自己喜欢的~