目录

0. 极力推荐一个反向传播的讲解,是看过的讲的清楚的

1. Introduction

2. 操作走一走

2.1 先做一个半圆的数据集

2.2 可视化

2.3 Dropout(基于一个全连接网络)

2.4 添加L2正则化,并放入optimizer中

2.5 训练模型,可视化loss曲线,print预测准确率


0. 极力推荐一个反向传播的讲解

参考

1. Introduction

过拟合,其实就是泛化能力差---直观的讲就是训练集指标(比如准确率)高于测试集指标较多---因此是一种方差大而bias小的问题。其实也好理解,就是训练模型时,事事太细,放入测试集时,反而会到处跑。

方法有L1和L2正则化;增强数据;early stop;dropout;

参考

2. 操作走一走

2.1 先做一个半圆的数据集

import torch
import numpy as np
import matplotlib.pyplot as plt
import torch.nn as nn

#继承nn.Module类,构建网络模型
class LogicNet(nn.Module):
    def __init__(self,inputdim,hiddendim,outputdim):#初始化网络结构
        super(LogicNet,self).__init__()
        self.Linear1 = nn.Linear(inputdim,hiddendim) #定义全连接层
        self.Linear2 = nn.Linear(hiddendim,outputdim)#定义全连接层
        self.criterion = nn.CrossEntropyLoss() #定义交叉熵函数

    def forward(self,x): #搭建用两层全连接组成的网络模型
        x = self.Linear1(x)#将输入数据传入第1层
        x = torch.tanh(x)#对第一层的结果进行非线性变换
        x = self.Linear2(x)#再将数据传入第2层
#        print("LogicNet")
        return x

    def predict(self,x):#实现LogicNet类的预测接口
        #调用自身网络模型,并对结果进行softmax处理,分别得出预测数据属于每一类的概率
        pred = torch.softmax(self.forward(x),dim=1)
        return torch.argmax(pred,dim=1)  #返回每组预测概率中最大的索引

    def getloss(self,x,y): #实现LogicNet类的损失值计算接口
        y_pred = self.forward(x)
        loss = self.criterion(y_pred,y)#计算损失值得交叉熵
        return loss




def moving_average(a, w=10):#定义函数计算移动平均损失值
    if len(a) < w:
        return a[:]
    return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]

def plot_losses(losses):
    avgloss= moving_average(losses) #获得损失值的移动平均值
    plt.figure(1)
    plt.subplot(211)
    plt.plot(range(len(avgloss)), avgloss, 'b--')
    plt.xlabel('step number')
    plt.ylabel('Training loss')
    plt.title('step number vs. Training loss')
    plt.show()

def predict(model,x):   #封装支持Numpy的预测接口
    x = torch.from_numpy(x).type(torch.FloatTensor)
    ans = model.predict(x)
    return ans.numpy()

def plot_decision_boundary(pred_func,X,Y):#在直角坐标系中可视化模型能力
    #计算取值范围
    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    h = 0.01
    #在坐标系中采用数据,生成网格矩阵,用于输入模型
    xx,yy=np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    #将数据输入并进行预测
    Z = pred_func(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)

2.2 可视化

plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.title("Linear predict")
    arg = np.squeeze(np.argwhere(Y==0),axis = 1)
    arg2 = np.squeeze(np.argwhere(Y==1),axis = 1)
    plt.scatter(X[arg,0], X[arg,1], s=100,c='b',marker='+')
    plt.scatter(X[arg2,0], X[arg2,1],s=40, c='r',marker='o')
    plt.show()

2.3 Dropout(基于一个全连接网络)

  • 注意 x = nn.functional.dropout(x, p=0.07, traing=self.self.training)即为dropout。dropout的原因来自于数据可能是不纯净的,因此剔除一些异常数据,忽略一些节点。
  • p表示丢弃率,介于0-1,1表示全部丢弃,默认为0,5(即丢掉50%的数据)。
  • 扩展是,Dropout为一维线性,Dropout2D为二维,Dropout3D为3维。
class Logic_Dropout_Net(LogicNet):
    def __init__(self, inputdim, hiddendim, outputdim):
        super(Logic_Dropout_Net,self).__init__(inputdim, hiddendim, outputdim)
    
    def forward(self,x):
        x = self.Linear1(x)
        x = torch.tanh(x)
        x = nn.functional.dropout(x, p=0.07, traing=self.self.training)
        x = self.Linear2(x)
        return x
model = Logic_Dropout_Net(inputdim=2, hiddendim=500, outputdim=2)

2.4 添加L2正则化,并放入optimizer中

原形式为optimizer = torch.optim.Adam(model.parameters(),lr=0.01)

weight_p=[]
bias_p=[]
for name, p in model.named_parameters():
    if 'bias' in name:
        bias_p +=[p]
    else:
        weight_p +=[p]
optimizer = torch.optim.Adam([{'params':weight_p, 'weight_decay':0.001},
                             {'params': bias_p, 'weight_decay':0}],
                            lr=0.01)

2.5 训练模型,可视化loss曲线,print预测准确率

xt = torch.from_numpy(X).type(torch.FloatTensor)
yt = torch.from_numpy(Y).type(torch.LongTensor)

epochs=1000
losses=[]
for i in range(epochs):
    loss = model.getloss(xt, yt)
    losses.append(loss.item())
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

avgloss = moving_average(losses)
plt.figure()
plt.subplot()
plt.plot(range(len(avgloss)),avgloss, 'b--')
plt.xlabel('step number')
plt.ylabel('training loss')
plt.title('step number vs training loss')
plt.show()


Xtest, Ytest = sklearn.datasets.make_moons(80, noise=0.2)
plot_decision_boundary(lambda x: predict(model,x),Xtest,Ytest)
Xtest_t = torch.from_numpy(Xtest).type(torch.FloatTensor)
Ytest_t = torch.from_numpy(Ytest).type(torch.FloatTensor)
print('测试时准确率:',accuracy_score(model.predict(Xtest_t),(Ytest_t)))