Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题

    一、简单讨论激活函数对拟合问题的影响

       最近在学习全连接网络,希望利用全连接网络实现拟合或者插值问题。即给定一些已知的散点,想要利用全连接网络,输入一个x,相应地网络会输出一个y,利用已知散点的真实值计算MSELoss,从而逼近已知点。

网络的结构很简单,利用了两层线性层,中间加不同的激活函数(代码显示的是ReLU):

class DNN(nn.Module):
    def __init__(self):
        super().__init__()
        layers =  [1,50,1]
        self.layer1 = nn.Linear(layers[0],layers[1])
        self.layer2 = nn.Linear(layers[1],layers[2])
        self.relu = nn.ReLU()
    def forward(self,d):
        d1 = self.layer1(d)
        d1 = self.relu(d1)
        d2 = self.layer2(d1)
        return d2

我用的例子是sin(x),在-π到π的50个点中随机取10个,作为我们的训练数据[x,y]:

x = np.linspace(-np.pi,np.pi).astype(np.float32)
y = np.sin(x)
#随机取十个点
x_train = random.sample(x.tolist(),10)
y_train = np.sin(x_train)
plt.scatter(x_train,y_train,c="r")
plt.plot(x,y)

随机点的位置如下:

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第1张图片

设定一些参数,比如迭代10000次,学习率调成0.1等,每次只从训练数据中输入一个。以下是不同激活函数的训练结果:

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第2张图片

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第3张图片

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第4张图片

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第5张图片

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第6张图片

从以上结果我们可以得到一些不太准确的粗略讨论

(1)不同的激活函数对输出的影响是不同的。

(2)LeakyReLU我不确定为什么会出现右边界严重脱离的情况,对结果影响比较严重。

(3)就平滑度而言,直观感受是ELU和Sigmoid会更加平滑,Tanh会出现尖灭点,这和数据点位置也有一定的关系。而ReLU整体直线的拼接感会比较重。

 (4)就拟合程度而言,不论是哪一种激活函数,都没有办法保证已知点很好地落在预测曲线上,增加神经元的个数或许会有更好的效果。就这点而言,Tanh表现要更好一点。

二、网络加深的问题

       以上是对于两层简单网络不同激活函数的探讨,接下来我想聊聊把网络加深对结果带来的影响。我们知道,如果是拟合问题,我们希望预测出来的整体曲线是平滑且符合大致趋势的,但是如果是插值问题,我们更希望看到已知的数据点是在我们预测的曲线上面的,由于loss几乎不可能完全为0,所以我们想要尽可能地让它收敛,哪怕是达到过拟合的情况。 

于是我把网络该成立四层的全连接,中间用不同的激活函数进行非线性映射:

class DNN(nn.Module):
    def __init__(self):
        super().__init__()
        layers =  [1,50,25,12,1]
        self.layer1 = nn.Linear(layers[0],layers[1])
        self.layer2 = nn.Linear(layers[1],layers[2])
        self.layer3 = nn.Linear(layers[2],layers[3])
        self.layer4 = nn.Linear(layers[3],layers[4])
        self.elu = nn.ELU()
    def forward(self,d):
        d1 = self.elu(self.layer1(d ))
        d2 = self.elu(self.layer2(d1))
        d3 = self.elu(self.layer3(d2))
        d4 = self.layer4(d3)

        return d4

结果如下:

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第7张图片

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第8张图片

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第9张图片

       可以看到,不论是哪个激活函数,预测出来的曲线都完全不对,训练过程中loss也基本不变,但是神经元的权重是在改变的。这显然已经不是激活函数的问题了,而且可以看出,在0的左右两端不论输入是什么,出来的值基本上是一致的。这一直是我很疑惑的点,有可能是因为神经元过多,而输入数据仅有一个x导致的。

       但当我以为只是每一层的神经元过多,我把每一层的神经元减少,并用ReLU和Tanh作为激活函数时,结果却依旧如此,甚至变得更加糟糕。

每一层的神经元:

 layers =  [1,12,6,3,1]

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第10张图片

Pytorch全连接网络:激活函数对一维拟合问题的影响探讨;网络加深后带来的loss不降问题_第11张图片

希望大佬们可以提出一些可能出现的原因!!!

你可能感兴趣的:(python,神经网络,深度学习,pytorch)