Fender12345
@Fender12345 (Fender 12345)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

複数入力モデルのdataset作成方法について

解決したいこと

Chainerを使用したNNの複数入力モデル※において
学習時のバッジ処理で使用するdatasetの要素となるデータ同士の配列長さが異なる場合
 ①TupleDataset使用した際にエラーを回避する方法
 ②TupleDatasetを使用せずdatasetを作成する方法

(言い換えると、配列長さが異なるデータをバッジ処理させるための解決方法を知りたいです)

________________________________________________________
【補足】
※NNの複数入力モデルについて(詳細は後述のソースをご確認ください)
・x1のみ畳み込み→プーリング層を通過
・x2はプーリング層通過後の全結合層へ合流させるバイパスモデルを検討
→x2のデータ長さは、x1の畳み込み→プーリング層通過後の長さに合わせる必要があります
→そのため、dataset作成時に配列長さが異なるデータを結合させる必要があると思っております
→学習時にバッジ処理を行う際、これまで使用していたTupleDatasetが使えずdataset作成に困っております

発生している問題・エラー

Chainerのチュートリアルでも紹介のあるTupleDatasetで配列長さが異なるデータを結合させてみたがエラーとなりました。
そもそもTupleDatasetは配列長さが同じデータを配列化させる機能なので、できなくて当たり前の認識です...

~\Anaconda3\lib\site-packages\chainer\datasets\tuple_dataset.py in __init__(self, *datasets)
     35             if len(dataset) != length:
     36                 raise ValueError(
---> 37                     'dataset of the index {} has a wrong length'.format(i))
     38         self._datasets = datasets
     39         self._length = length

ValueError: dataset of the index 1 has a wrong length

となると、「配列長さが異なるデータをバッジ処理させるためのdataset作成をどうすればよいか?」というの疑問です。

検討したソースコード

以下を参考に実装しました。
https://aniharu.hatenablog.com/entry/2018/01/25/005110

############# 複数箇所入力可能なCNNのDatasetについて ############# 


# ---------- import ----------
import chainer
import chainer.functions as F
import chainer.links as L
import numpy as np
import pandas as pd
import scipy.io
from chainer.datasets import tuple_dataset
from chainer.dataset import convert

# ---------- CNNの定義 ----------

class BYPASS(chainer.Chain):
    def __init__(self):
        super(BYPASS,self).__init__()
        with self.init_scope():
            self.conv1=L.ConvolutionND(1,1,10,19,stride=1)
            self.bat1=L.BatchNormalization(10)
            self.l1 = L.Linear(None, 3)

    def __call__(self, x1, x2):
        conv1    = self.conv1(x1)
        bat1     = self.bat1(conv1)
        relu1    = F.relu(bat1)
        pool1    = F.max_pooling_nd(relu1,6,Stride=1)        
        pool2    = F.concat([pooll1,x2],axis=1)
        out      = self.l1(pool2)
        return out

# ---------- 学習用の定義 ----------
"""
iterator,trainer,optimizerの記述は省略・・・
    
"""
#---------- train用データ作成 ----------
train_data   = np.ones((25, 1, 1))
train_data2  = np.ones((15, 1, 2))  #15は適当な値です。本来は全結合通過前の長さに合わせる必要あり
train_label  = np.ones((25, 1, 3))

train_data  = train_data.astype('float32')
train_data2 = train_data2.astype('float32')
train_label = train_label.astype('int32')

#---------- TupleDatasetでバッジ処理用の入力データを作成----------

# バイパスモデル(x1,x2)への入力用のdataset作成
# x1は畳み込み層を通過させ、x2は畳み込み層通過後の全結合層へ合流させる

# 上記を目的とするdatasetを以下のように作成したがTupleDatasetではNG
# TupleDatasetは同じ配列長さのデータをまとめるため、畳み込み層通過後のデータx1と、x1長さに合わせたx2を結合は不可?
train = tuple_dataset.TupleDataset(train_data,train_data2)  #dataset of the index 1 has a wrong length 
train = tuple_dataset.TupleDataset(train,train_label) 

 #こちらであれば配列長さが同じため、配列化は可能
train = tuple_dataset.TupleDataset(train,train_label) 
train[0]

自分で試したこと

・配列長さを合わせてみるとTupleDatasetのエラーはなくなりました(定義通りです)

調べたこと

・プーリング後のx1のデータ長さをゼロパディングなどで修正することで、TupleDatasetに入力するx2のデータ長さをx1と同じにできる可能性あり

こちらの方法だとTupleDatasetは使えそうですが、
モデルの肥大化が予想※されるため避けたいと思ってます
(※畳み込み層→プーリング層→ゼロパディング層・・・となるため)

教えていただきたいこと

Chainer以外の色々な情報を集めつつ、参考書やマニュアルを見ながら自力で解決を試みましたが、このようなモデルのサンプルも少なく...独力では限界を感じております

バッジ処理用のdatasetが作る方法としてTupleDatasetを使いつつ工夫すればできるのか
(その場合、モデルサイズ肥大化は避けたいです)、
それともTupleDatasetを使わずとも実現できるのか、皆目見当もつきません。

解決方法を御存知の方やバイパスモデル作成の経験がある方がいらっしゃいましたら、
ぜひ教えていただけないでしょうか?よろしくお願いします。

1

1Answer

Your answer might help someone💌