繁体   English   中英

如何将输入昏暗从 fit 方法传递给 skorch 包装器?

[英]How to pass input dim from fit method to skorch wrapper?

我正在尝试将 PyTorch 功能整合到scikit-learn环境(特别是 Pipelines 和 GridSearchCV)中,因此一直在研究skorch 神经网络的标准文档示例看起来像

import torch.nn.functional as F
from torch import nn
from skorch import NeuralNetClassifier

class MyModule(nn.Module):
    def __init__(self, num_units=10, nonlin=F.relu):
        super(MyModule, self).__init__()

        self.dense0 = nn.Linear(20, num_units)
        self.nonlin = nonlin
        self.dropout = nn.Dropout(0.5)
        ...
        ...
        self.output = nn.Linear(10, 2)
    ...
    ...

您可以通过将输入和输出维度硬编码到构造函数中来显式传递它们。 然而,这并不是scikit-learn接口的真正工作方式,其中输入和输出维度由fit方法派生,而不是显式传递给构造函数。 作为一个实际的例子考虑

# copied from the documentation
net = NeuralNetClassifier(
    MyModule,
    max_epochs=10,
    lr=0.1,
    # Shuffle training data on each epoch
    iterator_train__shuffle=True,
)

# any general Pipeline interface
pipeline = Pipeline([
        ('transformation', AnyTransformer()),
        ('net', net)
        ])

gs = GridSearchCV(net, params, refit=False, cv=3, scoring='accuracy')
gs.fit(X, y)

除了转换器中没有任何地方必须指定输入和输出维度这一事实之外,在模型之前应用的转换器可能会改变训练集的维度(考虑降维等),因此在神经网络中硬编码输入和输出网络构造函数就是不行。

我是否误解了这应该如何工作或建议的解决方案是什么(我正在考虑将构造函数指定到forward方法中,您已经有X可供拟合,但我不确定这是一个好习惯)?

这是一个非常好的问题,恐怕有最佳实践答案,因为 PyTorch 通常以初始化和执行是分开的步骤的方式编写,这正是您在这种情况下想要的。

有几种方法都朝着同一个方向前进,即内省输入数据并在拟合之前重新初始化网络。 我能想到的最简单的方法是编写一个回调,在训练开始期间设置相应的参数:

class InputShapeSetter(skorch.callbacks.Callback):
    def on_train_begin(self, net, X, y):
        net.set_params(module__input_dim=X.shape[-1])

这会在训练开始期间设置一个模块参数,它将使用所述参数重新初始化 PyTorch 模块。 这个特定的回调期望第一层的参数被称为input_dim但你可以根据需要更改它。

一个完整的例子:

import torch
import skorch
from sklearn.datasets import make_classification
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA

X, y = make_classification()
X = X.astype('float32')

class ClassifierModule(torch.nn.Module):
    def __init__(self, input_dim=80):
        super().__init__()
        self.l0 = torch.nn.Linear(input_dim, 10)
        self.l1 = torch.nn.Linear(10, 2)

    def forward(self, X):
        y = self.l0(X)
        y = self.l1(y)
        return torch.softmax(y, dim=-1)


class InputShapeSetter(skorch.callbacks.Callback):
    def on_train_begin(self, net, X, y):
        net.set_params(module__input_dim=X.shape[-1])


net = skorch.NeuralNetClassifier(
    ClassifierModule,
    callbacks=[InputShapeSetter()],
)

pipe = Pipeline([
    ('pca', PCA(n_components=10)),
    ('net', net),
])

pipe.fit(X, y)
print(pipe.predict(X))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM