Chainerで、Trainer使用時と、学習ループを直接書いた場合とで、精度が異なる現象について
皆さま
Chainerで、Mnistのサンプルをtrainerを使って学習させた場合と、
学習ループを直接書いて学習させた場合で、精度が異なってしまいます。
学習ループを書く場合は、何か特殊なオプションやメソッド呼び出しなどが必要であればご指摘、ご助言いただけないでしょうか?
下記のコードで、training1を使った場合は、98%程度の精度、training2を使った場合は、95%程度の精度となっています。
学習は、下記コードのtraining1を使うときは、training2をコメントアウトして使っています。
環境は、下記を使っています。
ubuntu 16.04 64bit
python 2.7
chainer 3.3
初歩的な質問かもしれませんが、よろしくお願いいたします。
コードは以下になります。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import numpy as np
import chainer
from chainer import cuda, Function, gradient_check, report, training,
utils, Variable
from chainer import datasets, iterators, optimizers, serializers
from chainer import Link, Chain, ChainList
from chainer.dataset import convert
import chainer.functions as F
import chainer.links as L
from chainer.datasets import tuple_dataset
from chainer import training
from chainer.training import extensions
import time
##use GPU
xp = cuda.cupy
train, test = datasets.get_mnist(withlabel=True, ndim=3)
train_count = len(train)
test_count = len(test)
class MyModel(Chain):
def __init__(self):
super(MyModel, self).__init__(
cn1=L.Convolution2D(1, 20, 5),
cn2=L.Convolution2D(20, 50, 5),
fc1=L.Linear(800, 500),
fc2=L.Linear(500, 10),
)
def __call__(self, x, t):
##convert data
converted_x, converted_t = Variable(cuda.to_gpu(x)),
Variable(cuda.to_gpu(t))
#return F.softmax_cross_entropy(self.fwd(x), t)
return F.softmax_cross_entropy(self.fwd(converted_x), converted_t)
def fwd(self, x):
h1 = F.max_pooling_2d(F.relu(self.cn1(x)), 2)
h2 = F.max_pooling_2d(F.relu(self.cn2(h1)), 2)
h3 = F.dropout(F.relu(self.fc1(h2)))
return self.fc2(h3)
###setting--------------------
model = MyModel()
#gpu mode
gpu_device = 0
model.to_gpu(gpu_device)
optimizer = optimizers.Adam()
optimizer.setup(model)
##set parameter
batchsize=1000
epochsize=60
N=len(train) #training data
train_iter = iterators.SerialIterator(train, batchsize)#1000 is batch size
test_iter = chainer.iterators.SerialIterator(test,batchsize,repeat=False, shuffle=False)
###----training1-----------------------------------------------------------------------
for epoch in range(0, epochsize):
print "epoch: %d" % epoch
sum_loss = 0
x_batch = np.array([train[epoch*batchsize][0]])
y_batch = np.array(train[epoch*batchsize][1])
#create batch
for i in range(1, batchsize):
trainingdata=np.array([train[(epoch*batchsize) + i][0]])
x_batch = np.append(x_batch,trainingdata,axis=0)
labeldata=np.array([train[(epoch*batchsize) + i][1]])
y_batch = np.append(y_batch,labeldata)
#learning
model.cleargrads()
loss=model(x_batch,y_batch)
loss.backward()
optimizer.update(model, x_batch, y_batch)
sum_loss += float(loss.data) * len(y_batch)
###----training2-----------------------------------------------------------------------
iterator = iterators.SerialIterator(train, batchsize)#1000 is batch size
updater = training.StandardUpdater(iterator, optimizer)
trainer = training.Trainer(updater, (epochsize, 'epoch')) #10 is epoch
trainer.extend(extensions.ProgressBar())
trainer.run()
###----test-----------------
ok = 0
for i in range(len(test)):
x = Variable(cuda.to_gpu(np.array([test[i][0]])))
t = test[i][1]
out = model.fwd(x)
ans = np.argmax(cuda.to_cpu(out.data))
####labe and predicted label
print("label is ",t)
print("predicted label is ", ans)
if (ans == t):
ok += 1
print (ok * 1.0) / len(test)