TL;DR L'impression de réécrire le code MNIST de Chainer dans PyTorch était presque la même. La différence était la couche au-dessus de Updater dans Chainer et la couche Ignite dans PyTorch. De plus, si vous utilisez [chainer-pytorch-migration] 3, vous pouvez utiliser les extensions utilisées dans Chainer dans Ignite, et vous pouvez utiliser PyTorch + Ignite tout comme Chainer. Je pense que ceux qui ont utilisé Chainer pourront s'habituer naturellement à PyTorch + Ignite.
Comme décrit ici [\ [1 ]] 1, il a été annoncé que PFN mettra fin au développement de Chainer et passera à PyTorch.
Preferred Networks Co., Ltd. (Siège social: Chiyoda-ku, Tokyo, Président: Toru Nishikawa, Preferred Networks, ci-après PFN) a développé un cadre d'apprentissage en profondeur, qui est la technologie de base pour la recherche et le développement, à partir de son Chainer ™ développé en interne. Migrez vers PyTorch de manière séquentielle. Dans le même temps, nous collaborerons avec Facebook, qui développe PyTorch, et la communauté des développeurs de PyTorch, et participerons au développement de PyTorch. De plus, Chainer passera à la phase de maintenance avec la dernière version v7, qui est une mise à jour majeure de la version publiée aujourd'hui. Pour les utilisateurs de Chainer, nous fournissons de la documentation et des bibliothèques pour vous aider à migrer vers PyTorch.
Ce n'est pas que vous ne pouvez pas utiliser Chainer tout de suite, mais les utilisateurs de Chainer sont progressivement obligés de passer à d'autres frameworks.
Je pense que de nombreux utilisateurs ont été déroutés par l'annonce soudaine de la fin du développement de Chainer, mais PFN prend également en charge la transition vers PyTorch en prévision de cette situation [Document \ [2 ]] 2 et [Bibliothèque \ [ 3 ]] 3 est fourni.
En regardant le document ci-dessus, la correspondance entre Chainer et PyTorch + Ignite est la suivante.
cited from [2]
Ce que vous pouvez voir ci-dessus
--PyTorch prend en charge le rôle de Chainer jusqu'à Optimizer --Ignite prend en charge le rôle de Updater / Trainer of Chainer.
Donc, si vous voulez écrire les étapes d'apprentissage vous-même, vous ne pouvez écrire qu'avec PyTorch, mais si vous voulez que les étapes d'apprentissage soient gérées par le framework comme Trainer of Chainer, vous devez utiliser PyTorch + Ignite.
Il y a un cahier pour la formation et l'inférence MNIST en utilisant Chainer's Trainer sur le lien ci-dessous.
Cette fois, je voudrais réécrire le code ci-dessus en utilisant PyTorch + Ignite.
from chainer.datasets import mnist
train, test = mnist.get_mnist()
↓
from torchvision.datasets import MNIST
from torchvision.transforms import ToTensor
data_transform = ToTensor()
train = MNIST(download=True, root=".", transform=data_transform, train=True)
test = MNIST(download=False, root=".", transform=data_transform, train=False)
Iterator -> DataLoader
from chainer import iterators
batchsize = 128
train_iter = iterators.SerialIterator(train, batchsize)
test_iter = iterators.SerialIterator(test, batchsize, False, False)
↓
from torch.utils.data import DataLoader
batch_size = 128
train_loader = DataLoader(train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test, batch_size=batch_size, shuffle=False)
import chainer
import chainer.links as L
import chainer.functions as F
class MLP(chainer.Chain):
def __init__(self, n_mid_units=100, n_out=10):
super(MLP, self).__init__()
with self.init_scope():
self.l1=L.Linear(None, n_mid_units)
self.l2=L.Linear(None, n_mid_units)
self.l3=L.Linear(None, n_out)
def forward(self, x):
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
return self.l3(h2)
gpu_id = 0 # Set to -1 if you don't have a GPU
model = L.Classifier(model)
if gpu_id >= 0:
model.to_gpu(gpu_id)
↓
from torch import nn
import torch.nn.functional as F
import torch
class MLP(nn.Module):
def __init__(self, n_mid_units=100, n_out=10):
super(MLP, self).__init__()
self.l1 = nn.Linear(784, n_mid_units)
self.l2 = nn.Linear(n_mid_units, n_mid_units)
self.l3 = nn.Linear(n_mid_units, n_out)
def forward(self, x):
x = torch.flatten(x, start_dim=1)
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
h3 = self.l3(h2)
return F.log_softmax(h3, dim=1)
device = 'cuda:0'
model = MLP()
de
Linear` ne peuvent pas être omis comme "None".x = torch.flatten (x, start_dim = 1)
.from chainer import optimizers
lr = 0.01
optimizer = optimizers.SGD(lr=lr)
optimizer.setup(model)
↓
from torch import optim
lr = 0.01
#Sélection de la méthode d'optimisation
optimizer = optim.SGD(model.parameters(), lr=lr)
Updater -> Ignite
from chainer import training
updater = training.StandardUpdater(train_iter, optimizer, device=gpu_id)
↓
from ignite.engine import create_supervised_trainer
trainer = create_supervised_trainer(model, optimizer, F.nll_loss, device=device)
from chainer.training import extensions
trainer = training.Trainer(
updater, (max_epoch, 'epoch'), out='mnist_result'
)
trainer.extend(extensions.LogReport())
.
.
.
trainer.extend(extensions.Evaluator(test_iter, model, device=gpu_id))
↓
from ignite.engine import create_supervised_evaluator
from ignite.metrics import Accuracy, Loss
from ignite.engine import Events
evaluator = create_supervised_evaluator(
model,
metrics={
'accuracy': Accuracy(),
'nll': Loss(F.nll_loss),
},
device=device,
)
training_history = {'accuracy':[],'loss':[]}
validation_history = {'accuracy':[],'loss':[]}
@trainer.on(Events.EPOCH_COMPLETED)
def log_training_results(engine):
evaluator.run(train_loader)
metrics = evaluator.state.metrics
avg_accuracy = metrics['accuracy']
avg_nll = metrics['nll']
training_history['accuracy'].append(avg_accuracy)
training_history['loss'].append(avg_nll)
print(
"Training Results - Epoch: {} Avg accuracy: {:.2f} Avg loss: {:.2f}"
.format(engine.state.epoch, avg_accuracy, avg_nll)
)
@trainer.on(Events.EPOCH_COMPLETED)
def log_validation_results(engine):
evaluator.run(test_loader)
metrics = evaluator.state.metrics
avg_accuracy = metrics['accuracy']
avg_nll = metrics['nll']
validation_history['accuracy'].append(avg_accuracy)
validation_history['loss'].append(avg_nll)
print(
"Validation Results - Epoch: {} Avg accuracy: {:.2f} Avg loss: {:.2f}"
.format(engine.state.epoch, avg_accuracy, avg_nll))
# Create snapshot
from ignite.handlers import ModelCheckpoint
checkpointer = ModelCheckpoint(
'./models',
'MNIST',
save_interval=1,
n_saved=2,
create_dir=True,
save_as_state_dict=True,
require_empty=False,
)
trainer.add_event_handler(Events.EPOCH_COMPLETED, checkpointer, {'MNIST': model})
trainer.run()
↓
max_epochs = 10
trainer.run(train_loader, max_epochs=max_epochs)
Vous trouverez ci-dessous un bloc-notes qui migre et s'exécute sur Colaboratory. En plus du code expliqué ci-dessus, ce qui suit est également inclus, alors essayez de l'exécuter à portée de main si vous le souhaitez.
https://drive.google.com/open?id=1NqHYJjFz-dl1tWP8kMO0y0kCZ9-ZWLxi
En fait, si vous utilisez [chainer-pytorch-migration] 3, vous pouvez utiliser les extensions utilisées dans Chainer dans Ignite! Si vous manquez les extensions Chainer, essayez d'utiliser chainer-pytorch-migration.
import chainer_pytorch_migration as cpm
import chainer_pytorch_migration.ignite
from chainer.training import extensions
optimizer.target = model
trainer.out = 'result'
cpm.ignite.add_trainer_extension(trainer, optimizer, extensions.LogReport())
cpm.ignite.add_trainer_extension(trainer, optimizer, extensions.ExponentialShift('lr', 0.9, 1.0, 0.1))
cpm.ignite.add_trainer_extension(trainer, optimizer, extensions.PrintReport(
['epoch', 'iteration', 'loss', 'lr']))
max_epochs = 10
trainer.run(train_loader, max_epochs=max_epochs)
Reference
Recommended Posts