sklearn 管道中的 PyTorch 训练循环

Pet*_*etr 5 python pipeline scikit-learn pytorch

我现在正在尝试的是在管道中使用 PyTorch,所有预处理都将在管道中处理。

我有能力让它发挥作用。然而,我得到的结果有点偏离。随着训练循环的进行,损失函数似乎没有减少并且陷入困境(大概处于局部最优?)。

我遵循标准 PyTorch 训练循环并将其包装在 fit 方法中,因为这就是 sklearn 想要的:

import torch
from sklearn.base import BaseEstimator, TransformerMixin

import torch.nn.functional as F

from IPython.core.debugger import set_trace

# +
import pandas as pd
import seaborn as sns
import numpy as np

from tqdm import tqdm
import random
# -

df = sns.load_dataset("tips")
df.head()


# +
class LinearRegressionModel(torch.nn.Module, BaseEstimator, TransformerMixin):
 
    def __init__(self, loss_func = torch.nn.MSELoss()):
        super(LinearRegressionModel, self).__init__()
        self.linear = torch.nn.Linear(3, 1)  # One in and one out
        self.loss_func = loss_func
        self.optimizer = torch.optim.SGD(self.parameters(), lr = 0.01)
 
    def forward(self, x):
        y_pred = F.relu(self.linear(x))
        return y_pred    
    
    def fit(self, X, y):
        
#         set_trace()        

        X = torch.from_numpy(X.astype(np.float32))
        y = torch.from_numpy(y.values.astype(np.float32))
                
        for epoch in tqdm(range(0, 12)):
             
            pred_y = self.forward(X)

            # Compute and print loss
            loss = self.loss_func(pred_y, X)

            # Zero gradients, perform a backward pass,
            # and update the weights.
            self.optimizer.zero_grad()
            loss.backward()
            self.optimizer.step()
            print('epoch {}, loss {}'.format(epoch, loss.item()))            


# +
from sklearn.pipeline import Pipeline

from sklego.preprocessing import PatsyTransformer
# -

my_model = LinearRegressionModel()

pipe = Pipeline([
    ("patsy", PatsyTransformer("tip + size")),
    ("model", my_model)
])

pipe.fit(df, df['total_bill'])

Run Code Online (Sandbox Code Playgroud)

这不仅仅是因为模型过于简单。如果我使用通过随机梯度下降(SGDRegressor)估计的 sklearn 线性回归,结果看起来不错。因此,我得出的结论是问题出在我的 PyTorch 类中

# +
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

pipe2 = Pipeline([
    ("patsy", PatsyTransformer("tip + C(size) + C(time)")),
    ("model", LinearRegression())
])

pipe2.fit(df, df['total_bill'])
# -

mean_squared_error(df['total_bill'], pipe2.predict(df))



Run Code Online (Sandbox Code Playgroud)

Pet*_*etr 3

这个实现的问题出在fit方法上。

我们正在比较预测矩阵和设计矩阵

# Compute and print loss
loss = self.loss_func(pred_y, X)
Run Code Online (Sandbox Code Playgroud)

应该是预测值和实际值 y:

loss = self.loss_func(pred_y, y)
Run Code Online (Sandbox Code Playgroud)