『Chainerで作るコンテンツ自動生成AIプログラミング入門』という書籍の第３章を参考に、超解像画像生成のためのCNNを作成しています。  
作成中のプログラムにvalidationを実装しようとしましたが、エラーが出てしまいました。  
なお、python3.5.2、chainer6.4.0を使用しています。

以下に、変更前のプログラム、変更後のプログラム、エラー文をのせておきます。

変更前

```

    import chainer
    import chainer.functions as F
    import chainer.links as L
    from chainer import training, datasets, iterators, optimizers
    from chainer import report 
    from chainer.training import extensions
    from chainer.datasets import LabeledImageDataset
    import numpy as np
    import os
    import math
    from PIL import Image
    from PIL import ImageFile
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    
    batch_size = 128
    uses_device = 0                # GPU#0を使用
    
    # GPU使用時とCPU使用時でデータ形式が変わる
    if uses_device >= 0:
        import cupy as cp
        import chainer.cuda
    else:
        cp = np
    
    class SuperResolution_NN(chainer.Chain):
    
        def __init__(self):
            # 重みデータの初期値を指定する
            w1 = chainer.initializers.Normal(scale=0.0378, dtype=None)
            w2 = chainer.initializers.Normal(scale=0.3536, dtype=None)
            w3 = chainer.initializers.Normal(scale=0.1179, dtype=None)
            w4 = chainer.initializers.Normal(scale=0.189, dtype=None)
            w5 = chainer.initializers.Normal(scale=0.0001, dtype=None)
            super(SuperResolution_NN, self).__init__()
            # 全ての層を定義する
            with self.init_scope():
                self.c1 = L.Convolution2D(1, 56, ksize=5, stride=1, pad=0, initialW=w1)
                self.l1 = L.PReLU()
                self.c2 = L.Convolution2D(56, 12, ksize=1, stride=1, pad=0, initialW=w2)
                self.l2 = L.PReLU()
                self.c3 = L.Convolution2D(12, 12, ksize=3, stride=1, pad=1, initialW=w3)
                self.l3 = L.PReLU()
                self.c4 = L.Convolution2D(12, 12, ksize=3, stride=1, pad=1, initialW=w3)
                self.l4 = L.PReLU()
                self.c5 = L.Convolution2D(12, 12, ksize=3, stride=1, pad=1, initialW=w3)
                self.l5 = L.PReLU()
                self.c6 = L.Convolution2D(12, 12, ksize=3, stride=1, pad=1, initialW=w3)
                self.l6 = L.PReLU()
                self.c7 = L.Convolution2D(12, 56, ksize=1, stride=1, pad=1, initialW=w4)
                self.l7 = L.PReLU()
                self.c8 = L.Deconvolution2D(56, 1, ksize=9, stride=3, pad=4, initialW=w5)
    
        def __call__(self, x, t=None, train=True):
            h1 = self.l1(self.c1(x))
            h2 = self.l2(self.c2(h1))
            h3 = self.l3(self.c3(h2))
            h4 = self.l4(self.c4(h3))
            h5 = self.l5(self.c5(h4))
            h6 = self.l6(self.c6(h5))
            h7 = self.l7(self.c7(h6))
            h8 = self.c8(h7)
            loss = F.mean_squared_error(h8, t)
            report ({ 'loss' : loss }, self )
    
            # 損失か結果を返す
            return F.mean_squared_error(h8, t) if train else h8
    
    # カスタムUpdaterのクラス
    class SRUpdater(training.StandardUpdater):
    
        def __init__(self, train_iter, optimizer, device):
            super(SRUpdater, self).__init__(
                train_iter,
                optimizer,
                device=device
            )
    
        def update_core(self):
            # データを1バッチ分取得
            batch = self.get_iterator('main').next()
            # Optimizerを取得
            optimizer = self.get_optimizer('main')
    
            # バッチ分のデータを作る
            x_batch = [] # 入力データ
            y_batch = [] # 正解データ
            for img in batch:
                # 高解像度データ
                hpix = np.array(img, dtype=np.float32)  / 255.0
                y_batch.append([hpix[:,:,0]]) # Yのみの1chデータ
                # 低解像度データを作る
                low = img.resize((16, 16), Image.NEAREST)
                lpix = np.array(low, dtype=np.float32) / 255.0
                x_batch.append([lpix[:,:,0]]) # Yのみの1chデータ
    
            # numpy or cupy配列にする
            x = cp.array(x_batch, dtype=cp.float32)
            y = cp.array(y_batch, dtype=cp.float32)
    
            # ニューラルネットワークを学習させる
            optimizer.update(optimizer.target, x, y)
    
    # ニューラルネットワークを作成
    model = SuperResolution_NN()
    
    if uses_device >= 0:
        # GPUを使う
        chainer.cuda.get_device_from_id(0).use()
        chainer.cuda.check_cuda_available()
        # GPU用データ形式に変換
        model.to_gpu()
    
    images_train = []
    # 全てのファイル
    fs = os.listdir('images/train')
    for fn in fs:
        # 画像を読み込み
        img = Image.open('images/train/' + fn).resize((320, 320)).convert('YCbCr')
        cur_x = 0
        while cur_x <= 320 - 40:
            cur_y = 0
            while cur_y <= 320 - 40:
                # 画像から切りだし
                rect = (cur_x, cur_y, cur_x+40, cur_y+40)
                cropimg = img.crop(rect).copy()
                # 配列に追加
                images_train.append(cropimg)
                # 次の切りだし場所へ
                cur_y += 20
            cur_x += 20
    
    # 繰り返し条件を作成する
    train_iter = iterators.SerialIterator(images_train, batch_size, shuffle=True)
    
    # 誤差逆伝播法アルゴリズムを選択する
    optimizer = optimizers.Adam()
    optimizer.setup(model)
    
    # デバイスを選択してTrainerを作成する
    updater = SRUpdater(train_iter, optimizer, device=uses_device)
    trainer = training.Trainer(updater, (2000, 'epoch'), out="result")
    
    # 学習の進展を表示するようにする
    trainer.extend(extensions.ProgressBar())
    
    trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'elapsed_time'])) 
    
    #学習のlogを保存する
    trainer.extend(extensions.LogReport())
    
    # 損失関数の値をグラフにする機能
    if extensions.PlotReport.available():
        trainer.extend(extensions.PlotReport(['main/loss'], x_key='epoch', file_name='loss.png'))
    
    # 中間結果を保存する
    n_save = 0
    @chainer.training.make_extension(trigger=(1000, 'epoch'))
    def save_model(trainer):
        # NNのデータを保存
        global n_save
        n_save = n_save+1
        chainer.serializers.save_hdf5( 'net/fsrcnn-'+str(n_save)+'.hdf5', model )
    trainer.extend(save_model)
    
    # 機械学習を実行する
    trainer.run()
    
    # 学習結果を保存する
    chainer.serializers.save_hdf5( 'net/fsrcnn.hdf5', model )
    
```

変更後

```

    import chainer
    import chainer.functions as F
    import chainer.links as L
    from chainer import training, datasets, iterators, optimizers
    from chainer import report  
    from chainer.training import extensions
    from chainer.datasets import LabeledImageDataset
    import numpy as np
    import os
    import math
    from PIL import Image
    from PIL import ImageFile
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    
    batch_size = 128           
    uses_device = 0                # GPU#0を使用
    
    # GPU使用時とCPU使用時でデータ形式が変わる
    if uses_device >= 0:
        import cupy as cp
        import chainer.cuda
    else:
        cp = np
    
    class SuperResolution_NN(chainer.Chain):
    
        def __init__(self):
            # 重みデータの初期値を指定する
            w1 = chainer.initializers.Normal(scale=0.0378, dtype=None)
            w2 = chainer.initializers.Normal(scale=0.3536, dtype=None)
            w3 = chainer.initializers.Normal(scale=0.1179, dtype=None)
            w4 = chainer.initializers.Normal(scale=0.189, dtype=None)
            w5 = chainer.initializers.Normal(scale=0.0001, dtype=None)
            super(SuperResolution_NN, self).__init__()
            # 全ての層を定義する
            with self.init_scope():
                self.c1 = L.Convolution2D(1, 56, ksize=5, stride=1, pad=0, initialW=w1)
                self.l1 = L.PReLU()
                self.c2 = L.Convolution2D(56, 12, ksize=1, stride=1, pad=0, initialW=w2)
                self.l2 = L.PReLU()
                self.c3 = L.Convolution2D(12, 12, ksize=3, stride=1, pad=1, initialW=w3)
                self.l3 = L.PReLU()
                self.c4 = L.Convolution2D(12, 12, ksize=3, stride=1, pad=1, initialW=w3)
                self.l4 = L.PReLU()
                self.c5 = L.Convolution2D(12, 12, ksize=3, stride=1, pad=1, initialW=w3)
                self.l5 = L.PReLU()
                self.c6 = L.Convolution2D(12, 12, ksize=3, stride=1, pad=1, initialW=w3)
                self.l6 = L.PReLU()
                self.c7 = L.Convolution2D(12, 56, ksize=1, stride=1, pad=1, initialW=w4)
                self.l7 = L.PReLU()
                self.c8 = L.Deconvolution2D(56, 1, ksize=9, stride=3, pad=4, initialW=w5)
    
        def __call__(self, x, t=None, train=True):
            h1 = self.l1(self.c1(x))
            h2 = self.l2(self.c2(h1))
            h3 = self.l3(self.c3(h2))
            h4 = self.l4(self.c4(h3))
            h5 = self.l5(self.c5(h4))
            h6 = self.l6(self.c6(h5))
            h7 = self.l7(self.c7(h6))
            h8 = self.c8(h7)
            loss = F.mean_squared_error(h8, t)
            report ({ 'loss' : loss }, self )
    
            # 損失か結果を返す
            return F.mean_squared_error(h8, t) if train else h8
    
    # カスタムUpdaterのクラス
    class SRUpdater(training.StandardUpdater):
    
        def __init__(self, train_iter, optimizer, device):
            super(SRUpdater, self).__init__(
                train_iter,
                optimizer,
                device=device
            )
    
        def update_core(self):
            # データを1バッチ分取得
            batch = self.get_iterator('main').next()
            # Optimizerを取得
            optimizer = self.get_optimizer('main')
    
            # バッチ分のデータを作る
            x_batch = [] # 入力データ
            y_batch = [] # 正解データ
            for img in batch:
                # 高解像度データ
                hpix = np.array(img, dtype=np.float32)  / 255.0
                y_batch.append([hpix[:,:,0]]) # Yのみの1chデータ
                # 低解像度データを作る
                low = img.resize((16, 16), Image.NEAREST)
                lpix = np.array(low, dtype=np.float32) / 255.0
                x_batch.append([lpix[:,:,0]]) # Yのみの1chデータ
    
            # numpy or cupy配列にする
            x = cp.array(x_batch, dtype=cp.float32)
            y = cp.array(y_batch, dtype=cp.float32)
    
            # ニューラルネットワークを学習させる
            optimizer.update(optimizer.target, x, y)
    
    # ニューラルネットワークを作成
    model = SuperResolution_NN()
    
    if uses_device >= 0:
        # GPUを使う
        chainer.cuda.get_device_from_id(0).use()
        chainer.cuda.check_cuda_available()
        # GPU用データ形式に変換
        model.to_gpu()
    
    images_train = []
    
    # 全てのファイル
    fs = os.listdir('images/train')
    for fn in fs:
        # 画像を読み込み
        img = Image.open('images/train/' + fn).resize((320, 320)).convert('YCbCr')
        cur_x = 0
        while cur_x <= 320 - 40:
            cur_y = 0
            while cur_y <= 320 - 40:
                # 画像から切りだし
                rect = (cur_x, cur_y, cur_x+40, cur_y+40)
                cropimg = img.crop(rect).copy()
                # 配列に追加
                images_train.append(cropimg)
                # 次の切りだし場所へ
                cur_y += 20
            cur_x += 20
    
    images_val = []     #追加
    
    # 全てのファイル
    fs = os.listdir('images/val')
    for fn in fs:
        # 画像を読み込み
        img = Image.open('images/val/' + fn).resize((320, 320)).convert('YCbCr')
    
        cur_x = 0
        while cur_x <= 320 - 40:
            cur_y = 0
            while cur_y <= 320 - 40:
                # 画像から切りだし
                rect = (cur_x, cur_y, cur_x+40, cur_y+40)
                cropimg = img.crop(rect).copy()
                # 配列に追加
                images_val.append(cropimg)
                # 次の切りだし場所へ
                cur_y += 20
            cur_x += 20
    
    # 繰り返し条件を作成する
    train_iter = iterators.SerialIterator(images_train, batch_size, shuffle=True)
    
    val_iter = iterators.SerialIterator(images_val, batch_size, shuffle=False, repeat=False)  #追加
    
    # 誤差逆伝播法アルゴリズムを選択する
    optimizer = optimizers.Adam()
    optimizer.setup(model)
    
    # デバイスを選択してTrainerを作成する
    updater = SRUpdater(train_iter, optimizer, device=uses_device)
    trainer = training.Trainer(updater, (2000, 'epoch'), out="result")
    
    # 学習の進展を表示するようにする
    trainer.extend(extensions.ProgressBar())
    
    # モデルのtrainプロパティをFalseに設定してvalidationするextension
    trainer.extend(extensions.Evaluator(val_iter, model,device=uses_device))  #追加
    
    trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'validation/main/loss', 'elapsed_time'])) #追加
    
    #学習のlogを保存する
    trainer.extend(extensions.LogReport())
    
    # 損失関数の値をグラフにする機能
    if extensions.PlotReport.available():
        trainer.extend(extensions.PlotReport(['main/loss'], x_key='epoch', file_name='loss.png'))
        trainer.extend(extensions.PlotReport(['validation/main/loss'], x_key='epoch', file_name='val_loss.png')) #追加
    
    # 中間結果を保存する
    n_save = 0
    @chainer.training.make_extension(trigger=(1000, 'epoch'))
    def save_model(trainer):
        # NNのデータを保存
        global n_save
        n_save = n_save+1
        chainer.serializers.save_hdf5( 'net/fsrcnn-'+str(n_save)+'.hdf5', model )
    trainer.extend(save_model)
    
    # 機械学習を実行する
    trainer.run()
    
    # 学習結果を保存する
    chainer.serializers.save_hdf5( 'net/fsrcnn.hdf5', model )
    
```

エラー文

```

    Exception in main training loop: int() argument must be a string, a bytes-like object or a number, not 'Image'
    Traceback (most recent call last):###########################.] 99.93%
     File "/usr/local/lib/python3.5/dist-packages/chainer/training/trainer.py", line 319, in run
       entry.extension(self)imated time to finish: 0:31:41.206374.
     File "/usr/local/lib/python3.5/dist-packages/chainer/training/extensions/evaluator.py", line 161, in __call__
       result = self.evaluate()
     File "/usr/local/lib/python3.5/dist-packages/chainer/training/extensions/evaluator.py", line 216, in evaluate
       self.converter, batch, self.device)
     File "/usr/local/lib/python3.5/dist-packages/chainer/dataset/convert.py", line 73, in _call_converter
       return converter(batch, device)
     File "/usr/local/lib/python3.5/dist-packages/chainer/dataset/convert.py", line 58, in wrap_call
       return func(*args, **kwargs)
     File "/usr/local/lib/python3.5/dist-packages/chainer/dataset/convert.py", line 239, in concat_examples
       return to_device(device, _concat_arrays(batch, padding))
     File "/usr/local/lib/python3.5/dist-packages/chainer/dataset/convert.py", line 246, in _concat_arrays
       arrays = numpy.asarray(arrays)
     File "/usr/local/lib/python3.5/dist-packages/numpy/core/numeric.py", line 501, in asarray
       return array(a, dtype, copy=False, order=order)
    Will finalize trainer extensions and updater before reraising the exception.
    Traceback (most recent call last):
     File "train.py", line 201, in <module>
       trainer.run()
     File "/usr/local/lib/python3.5/dist-packages/chainer/training/trainer.py", line 349, in run
       six.reraise(*exc_info)
     File "/usr/lib/python3/dist-packages/six.py", line 686, in reraise
       raise value
     File "/usr/local/lib/python3.5/dist-packages/chainer/training/trainer.py", line 319, in run
       entry.extension(self)
     File "/usr/local/lib/python3.5/dist-packages/chainer/training/extensions/evaluator.py", line 161, in __call__
       result = self.evaluate()
     File "/usr/local/lib/python3.5/dist-packages/chainer/training/extensions/evaluator.py", line 216, in evaluate
       self.converter, batch, self.device)
     File "/usr/local/lib/python3.5/dist-packages/chainer/dataset/convert.py", line 73, in _call_converter
       return converter(batch, device)
     File "/usr/local/lib/python3.5/dist-packages/chainer/dataset/convert.py", line 58, in wrap_call
       return func(*args, **kwargs)
     File "/usr/local/lib/python3.5/dist-packages/chainer/dataset/convert.py", line 239, in concat_examples
       return to_device(device, _concat_arrays(batch, padding))
     File "/usr/local/lib/python3.5/dist-packages/chainer/dataset/convert.py", line 246, in _concat_arrays
       arrays = numpy.asarray(arrays)
     File "/usr/local/lib/python3.5/dist-packages/numpy/core/numeric.py", line 501, in asarray
       return array(a, dtype, copy=False, order=order)
    TypeError: int() argument must be a string, a bytes-like object or a number, not 'Image'
    
```

「＃追加」と書かれている部分だけ追加したのですが、なぜエラーが出ているのか分かりません。どなたか改善方法を教えていただけたら幸いです。
CC BY-SA 4.0
2019-10-23T07:18:00.163
59907
2019-10-24T09:54:58.683
2019-10-24T09:54:58.683
36317
36317
question
python python3 機械学習 chainer
chainerでvalidationが実装できません。