task5:Pytorch实现dropout及L1,L2正则化

1 dropout

部分转自:https://blog.csdn.net/program_developer/article/details/80737724

1.1 Drop出现原因

深度学习网路中,参数多,可能出现过拟合及费时问题。为了解决这一问题,
通过实验,在2012年,Hinton在其论文《Improving neural networks by preventing co-adaptation of feature detectors》中提出Dropout。证明了其能有效解决过拟合的能力。
dropout 是指在深度学习网络的训练过程中,按照一定的概率将一部分神经网络单元暂时从网络中丢弃,相当于从原始的网络中找到一个更瘦的网络
示意图如下:
在这里插入图片描述
其实现是以某种概率分布使得一些神经元为0,一些为1.这样在有N个神经元的神经网络中,其参数搭配可能有2^N种。
具体介绍 见论文(我也不是很懂 实现得见)
适用情况:
1 Dropout主要用在数据量不够,容易过拟合,需要dropout。

1.2 numpy举例

训练时候

import numpy as np
def dropout(x, level):  
    if level < 0. or level >= 1:#level是概率值,必须在0~1之间  
        raise Exception('Dropout level must be in interval [0, 1[.')  
    retain_prob = 1. - level  
    #我们通过binomial函数,生成与x一样的维数向量。binomial函数就像抛硬币一样,我们可以把每个神经元当做抛硬币一样  
    #硬币 正面的概率为p,n表示每个神经元试验的次数  
    #因为我们每个神经元只需要抛一次就可以了所以n=1,size参数是我们有多少个硬币。  
    sample=np.random.binomial(n=1,p=retain_prob,size=x.shape)#即将生成一个0、1分布的向量,0表示这个神经元被屏蔽,不工作了,也就是dropout了  
    print (sample)  
    x *=sample          #屏蔽某些神经元
    print(x) 
    x /= retain_prob   #此处是dropout

    return x  

训练时 x/p 概率 测试时 x*p (看以上博客链接)这里没看懂,有人理解的话 留言感激不尽

2 pytorch实现dropout

见上文task4中:
https://blog.csdn.net/wehung/article/details/89215211

class Model(nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        # 定义多层神经网络
        self.fc1 = torch.nn.Linear(8,6)
        self.fc2 = torch.nn.Linear(6,4)
        self.fc3 = torch.nn.Linear(4,1)
        
    def forward(self,x):
        x = F.relu(self.fc1(x))            # 8->6
        x = F.dropout(x,p=0.5)             #dropout 1 此处为dropout
        x = F.relu(self.fc2(x))            #-6->4
        x = F.dropout(x,p=0.5)             # dropout 2  #此处为drouout
        y_pred = torch.sigmoid(self.fc3(x))         # 4->1 ->sigmoid 
        # warnings.warn("nn.functional.sigmoid is deprecated. Use torch.sigmoid instead."
        return y_pred

3 pytorch添加L1及L2正则化

3.1 L1及L2介绍

L1及L2是为了减少过拟合情况,提高模型泛化性能。
在这里插入图片描述
正则化图像
以下参考https://www.cnblogs.com/lliuye/p/9354972.html
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
综上:
L1及L2可以使得结构化风险最小
其中:
L1的参数具有稀疏性(具有更多的0或1)
L2的参数趋近于分散化 ,其参数值趋向于选择更简单(趋于0的参数),因此比较平滑

3.2 代码

因为在pytorch中optim自带L2正则化

criterion  = torch.nn.BCELoss() #定义损失函数
optimizer = torch.optim.SGD(model.parameters(),lr = 0.01, momentum=0, dampening=0,weight_decay=0) #weight_decay 表示使用L2正则化

自己实现:
在task4中 的训练部分加上部分代码即可:

for epoch in range(2000):
    y_pred = model(x_data)
    #计算误差
    cross_loss = criterion(y_pred,y_data)
    
    l1_regularization, l2_regularization = torch.tensor([0],dtype =torch.float32), torch.tensor([0],dtype=torch.float32) #定义L1及L2正则化损失
    #注意 此处for循环 当上面定义了weight_decay时候,应注释掉
    for param in model.parameters():
        l1_regularization += torch.norm(param, 1) #L1正则化
        l2_regularization += torch.norm(param, 2) #L2 正则化
    #
    #prin(loss.item())
    #loss = cross_loss + l1_regularization #L1 正则化
    loss = cross_loss + l2_regularization #L2 正则化
    
    Loss.append(loss.item())
    #每迭代1000次打印Lost并记录
    if epoch%100 == 0:
        print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, 2000, loss.item()))
    #梯度清零
    optimizer.zero_grad()
    #反向传播
    loss.backward()
    #更新梯度
    optimizer.step()

全部代码如下:
运行环境 pytorch 1.0 python 3.7

#!/usr/bin/env python
# coding: utf-8

# In[1]:


import numpy as np
import matplotlib.pyplot as plt


# In[2]:


m =200 
X =np.random.randn(2,m) #产生2*200 高斯分布 均值为0 方差为1 


# In[3]:


print(X.shape)


# In[4]:


Y = (X[0,:]>0)*(X[1,:]>0)*1.0 + (X[0,:]<0)*(X[1,:]<0)


# In[5]:


#可视化
get_ipython().run_line_magic('matplotlib', 'inline')
plt.scatter(X[0,:],X[1,:],c=Y,s=40,cmap = plt.cm.Spectral) #


# In[6]:


import torch 
import torch.nn as nn
import torch.nn.init as init
import torch.nn.functional as F


# In[ ]:





# In[7]:


#import pandas as pd
#x = pd.read_csv('X.csv',delimiter = ' ',header=None,names = list(np.arange(10)),dtype = np.float32)
#x.head()
#x = x.to_numpy() #转化为numpy 便于后续转化未Tensot

#y = pd.read_csv('y.csv',delimiter = ' ',header=None,names = list(np.arange(1)),dtype =np.float32)
#y.head()         #查看是否转化为想要的格式
#y = y.to_numpy()
#print(y.shape)


# In[8]:


import pandas as pd
xy = pd.read_csv('diabetes.csv',delimiter=',',dtype= np.float32)
#print(xy.head())
xy_numpy = xy.to_numpy()
x = xy_numpy[:,0:-1]
y = xy_numpy[:,-1].reshape(-1,1)


# In[9]:


y_frame = pd.DataFrame(y,columns= ['A'])


# In[10]:


y_frame['A'].value_counts()


# In[11]:


xy.head()


# In[12]:


#from sklearn.pipeline import Pipeline
#from sklearn.preprocessing import StandardScaler #标准化 最后一步数字
#num_pipeline = Pipeline([
 #   ('std_scaler',StandardScaler()),# 注意函数实例化 注意有括号
#])


# In[13]:


#x_rr =num_pipeline.fit_transform(x)


# In[14]:


x_data = torch.Tensor(torch.from_numpy(x)) #注意此处的Tensor 若由numpy转换过来 numpy的dtype须为np.float_n
y_data = torch.Tensor(torch.from_numpy(y))


# In[15]:


#print(x_data.shape)
# print(y_data.shape)


# In[16]:


# xy


# In[17]:


print(x_data.data.shape)
print(y_data.data.shape)


# # 类的定义

# In[18]:


class Model(nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        # 定义多层神经网络
        self.fc1 = torch.nn.Linear(8,6)
        self.fc2 = torch.nn.Linear(6,4)
        self.fc3 = torch.nn.Linear(4,1)
        
    def forward(self,x):
        x = F.relu(self.fc1(x))            # 8->6
        x = F.dropout(x,p=0.5)             #dropout 1
        x = F.relu(self.fc2(x))            #-6->4
        x = F.dropout(x,p=0.5)             # dropout 2
        y_pred = torch.sigmoid(self.fc3(x))         # 4->1 ->sigmoid 
        # warnings.warn("nn.functional.sigmoid is deprecated. Use torch.sigmoid instead."
        return y_pred


# In[19]:


## 求解


# In[20]:


def weight_init(m):
    classname = m.__class__.__name__
    if classname.find('Linear')!= -1:
        print("hi")
        m.weight.data = torch.randn(m.weight.data.size()[0],m.weight.data.size()[1])
        m.bias.data = torch.randn(m.bias.data.size()[0])


# # 实例化类

# In[21]:


model = Model()


# In[22]:


list(model.parameters())


# In[23]:


# print(model.__class__.__name__.find('Linear')) #该函数需要用到apply


# In[24]:


#model.apply(weight_init)


# In[25]:


#list(model.parameters())


# # 定义损失函数及优化器

# In[42]:


criterion  = torch.nn.BCELoss() #定义损失函数
optimizer = torch.optim.SGD(model.parameters(),lr = 0.01, momentum=0, dampening=0,weight_decay=0) #weight_decay 表示使用L2正则化


# In[43]:


Loss = []
#l1_regularization, l2_regularization = torch.tensor(0), torch.tensor(0) #定义L1及L2正则化损失


# In[44]:


print(x.shape)


# In[45]:


for epoch in range(2000):
    y_pred = model(x_data)
    #计算误差
    cross_loss = criterion(y_pred,y_data)
    
    l1_regularization, l2_regularization = torch.tensor([0],dtype =torch.float32), torch.tensor([0],dtype=torch.float32) #定义L1及L2正则化损失
    
    #for param in model.parameters():
       # l1_regularization += torch.norm(param, 1)
        #l2_regularization += torch.norm(param, 2)
    #
    #prin(loss.item())
    #loss = cross_loss + l1_regularization #L1 正则化
    loss = cross_loss + l2_regularization #L2 正则化
    
    Loss.append(loss.item())
    #每迭代1000次打印Lost并记录
    if epoch%100 == 0:
        print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, 2000, loss.item()))
    #梯度清零
    optimizer.zero_grad()
    #反向传播
    loss.backward()
    #更新梯度
    optimizer.step()


# In[46]:


mm = y_pred.detach().numpy() #将预测的tensor转化为numpy


# In[47]:


for i in range(len(y_pred)):
    if(y_pred[i]>0.5):
        y_pred[i] = 1.0
    else:
        y_pred[i] = 0.0
#print(y_pred)
type(y_pred)

# In[48]:
(y_pred == y_data).sum().item()/len(y_data) # torch.Tensor.sum()函数

  • 13
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
使用PyTorch实现L1L2正则化,可以通过在损失函数中添加相应的正则化项来实现。下面是一个简单的示例: ```python import torch import torch.nn as nn import torch.optim as optim # 定义模型 class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() self.linear = nn.Linear(10, 1) def forward(self, x): return self.linear(x) model = MyModel() # 定义损失函数和优化器 criterion = nn.MSELoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 定义正则化权重 l1_lambda = 0.01 l2_lambda = 0.01 # 训练循环 for epoch in range(num_epochs): for inputs, targets in data_loader: optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, targets) # 添加L1正则化 l1_reg = torch.tensor(0.) for param in model.parameters(): l1_reg += torch.norm(param, 1) loss += l1_lambda * l1_reg # 添加L2正则化 l2_reg = torch.tensor(0.) for param in model.parameters(): l2_reg += torch.norm(param, 2) loss += l2_lambda * l2_reg loss.backward() optimizer.step() ``` 在上述代码中,我们定义了一个`MyModel`类来表示我们的模型。然后,我们使用`nn.MSELoss()`作为损失函数,并使用`optim.SGD`作为优化器。在训练循环中,我们通过遍历模型的参数并计算其L1L2范数来计算正则化项。然后将正则化项加到损失函数中,通过调整`l1_lambda`和`l2_lambda`参数来控制正则化的强度。最后,我们进行反向传播和参数更新以完成训练。 请注意,这只是一个简单的示例,实际应用中可能还会有其他细节需要考虑,如权重衰减(weight decay)等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值