在做项目的过程中,我使用Pytorc和Sklearn和MLPRegressor写了相同结构的网络,但PyTorch的模型总是差很多。Pytorch的网络MSE为3.0,MLP的网络的MSE为2.0。

以下是Sklearn,MLP的代码

import torch
from sklearn.neural_network import MLPRegressor
clf = MLPRegressor(hidden_layer_sizes=(10), batch_size=5,shuffle=False)
clf.fit(x_train,y_train)
y_pred=clf.predict(x_test)

cost = torch.nn.MSELoss()
torch_y_pred = torch.FloatTensor(y_pred)
torch_y_test = torch.FloatTensor(y_test)
print("mse", cost(torch_y_pred, torch_y_test))

这是Pytorch的代码,其中Policy_Network是self.model的网络结构。

class Policy_Network(nn.Module):
    def __init__(self):
        super(Policy_Network, self).__init__()
        self.layer = nn.Sequential(
            nn.Linear(INPUT_DIM, 10),
            nn.ReLU(True),
            nn.Linear(10, 5),
            nn.ReLU(True),
            nn.Linear(5, 1),
        )
        self.to("cuda:0")

    def __call__(self, x):
        return self.layer(x)

for epoch in range(20):
    sum_loss = 0
    idx = 0
    for idx, x in enumerate(self.train_loader):
        # 正向传播计算误差
        feature, label = self.control_input(x)
        predict = self.model(feature).to('cpu')
        loss = self.cost(label, predict)
        sum_loss += loss.detach().numpy()
        # 梯度反向传播更新模型
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()
    print(f"{epoch} train sum_loss = ", sum_loss / idx)
    loss = self.eval()

在尝试过了许多方法,TM最终发现是loss计算时有问题。

  1. Sklearn的MLP计算时,y_pred、y_true维度都是(n)
  2. Pytorch计算时,y_pred的维度是(n, 1),而y_true的维度是(1, n)

为什么这样计算会出现问题呢?举例来说明

  1. 如果是MLP计算Loss时:

$$ pred - true = \begin{bmatrix} 1.1 & 1.5 \end{bmatrix}- \begin{bmatrix} 1 & 0 \end{bmatrix}=\begin{bmatrix} 0.1 & 1.5 \end{bmatrix} $$

$$ MSE( \begin{bmatrix} 0.1 & 1.5 \end{bmatrix}) = (0.01 + 2.25)/2 = 1.13 $$

  1. 如果是Pytorch计算Loss时:

    $$ pred - true = \begin{bmatrix} 1.1 \\ 1.5\end{bmatrix}- \begin{bmatrix} 1 & 0 \end{bmatrix}=\begin{bmatrix} 0.1 & 1.1 \\ 0.5 & 1.5 \end{bmatrix} $$

    $$ MSE(\begin{bmatrix} 0.1 & 1.1 \\ 0.5 & 1.5 \end{bmatrix}) = (0.01+1.21+0.25+2.25)/4=0.93 $$

解决方法:

我们只需要把true提高一个维度,即把$\begin{bmatrix} 1 & 0 \end{bmatrix}$变成$\begin{bmatrix} 1 \\ 0 \end{bmatrix}$即可。