回帰問題におけるnanについて

1,198 views
Skip to first unread message

siiii

unread,
Jan 12, 2017, 6:39:00 AM1/12/17
to Chainer Japanese User Group
お世話になっております。

Chainerで画像に対する回帰問題に取り組んでおります。
具体的には自動車のドライブレコーダーからの画像とそれに対応する1秒後の速度をラベルとし、次の速度にふさわしい値を求めるというようなことを行っています。

ネットワークはGoogLeNetの一部(初めからinception4aまで)を利用し、lossにはF.softmax_cross_entropyからF.mean_squared_errorを使い2乗誤差を求めています。
リンクのGoogLeNetはlossを3つ算出し、1つにまとめていますが、inception4aから最後のdropout, F.averagePoolingに繋ぎ、2乗誤差を1つのみ算出しています。

そこでlossがnanになるエラーが出ています。
学習率の問題かと思いましたが最適化関数はAdamを使っておりこちらの問題ではないのかなと思い、ネットワーク内のhの値を見てみたところ以下のように
なっていました。
(arrayとdtype=float32の間にバッチサイズ分の値が, lossまでの間にデータ数分の数が表示されています)
(array[[4.69 .....],
          [1.88 .....],
.
.
.
         [3.23 ......]], dtype=float32))
(array[[nan],
          [nan],
.
.
.
         [nan]], dtype=float32))

.....

(array[[nan],
          [nan],
.
.
.
         [nan]], dtype=float32))

epoch:1 loss = nan time:1.129 ....

(array[[4.69 .....],
          [1.88 .....],
.
.
.
         [3.23 ......]], dtype=float32))
(array[[nan],
          [nan],
.
.
.
         [nan]], dtype=float32))

.....

(array[[nan],
          [nan],
.
.
.
         [nan]], dtype=float32))
epoch:2 loss = nan time:1.129 ....

画像とラベルを読み込み、1回目のバッチサイズ分のデータを渡すまでは正しく動いている様ですが、2回目のバッチサイズ分のデータを渡す間にエラーがでているように
思えます。どの部分が悪いのかわからずじまいです。原因のわかる方おりましたらご享受頂きたい次第です。よろしくお願い致します。

Ubuntu14.04
CUDA v7.0
core 17 3.00GHz
GoForceGTX TITAN X 12GB 
メモリ 64GB 8*8 

class GoogLeNet(chainer.Chain):

    cuda.get_device(0).use()

    insize = 256


    def __init__(self):

        super(GoogLeNet, self).__init__(

            conv1=L.Convolution2D(None64, 7, stride=2, pad=3),

            conv2_reduce=L.Convolution2D(None64, 1),

            conv2=L.Convolution2D(None, 192, 3, stride=1, pad=1),

            inc3a=L.Inception(None6496, 128, 163232),

            inc3b=L.Inception(None, 128, 128, 192, 329664),

            inc4a=L.Inception(None, 19296, 208, 164864),

            inc4b=L.Inception(None, 160, 112, 224, 246464),

            inc4c=L.Inception(None, 128, 128, 256, 246464),

            inc4d=L.Inception(None, 112, 144, 288, 326464),

            inc4e=L.Inception(None, 256, 160, 320, 32, 128, 128),

            inc5a=L.Inception(None, 256, 160, 320, 32, 128, 128),

            inc5b=L.Inception(None, 384, 192, 384, 48, 128, 128),

            loss3_fc=L.Linear(None, 1),


            loss1_conv=L.Convolution2D(None, 128, 1),

            loss1_fc1=L.Linear(None, 1024),

            loss1_fc2=L.Linear(None, 1),


            loss2_conv=L.Convolution2D(None, 128, 1),

            loss2_fc1=L.Linear(None, 1024),

            loss2_fc2=L.Linear(None, 1),

        )

        self.train = True


    def __call__(self, x_data, t_data):

        x = Variable(x_data)

t = Variable(t_data)

        h = F.relu(self.conv1(x))


        h = F.local_response_normalization(

            F.max_pooling_2d(h, 3, stride=2), n=5)

        h = F.relu(self.conv2_reduce(h))

        h = F.relu(self.conv2(h))

        h = F.max_pooling_2d(

            F.local_response_normalization(h, n=5), 3, stride=2)


        h = self.inc3a(h)

        h = self.inc3b(h)

        h = F.max_pooling_2d(h, 3, stride=2)

        h = self.inc4a(h)


      h = F.average_pooling_2d(h, 7, stride=1)

        h = self.loss3_fc(F.dropout(h, 0.4, train=self.train))

        loss = F.mean_squared_error(h.data, t.data)

print(h.data, t.data)   ←ここでhの値を確認しています。


        chainer.report({

            'loss': loss,

        }, self)

        return loss


# 学習モデル設定

model = GoogLeNet()

optimizer = optimizers.Adam()

optimizer.setup(model)

cnt = 0


cuda.init(0)

model.to_gpu()


# 学習データリストファイルから一行ずつ読み込む

train_list = []

for line in open(args.train_list):

    pair = line.strip().split()

    train_list.append((pair[0], np.float32(pair[1])))

# 画像データとラベルデータを取得する

x_train = []    # 画像データ格納

y_train = []    # ラベルデータ格納

for filepath,  label in train_list:

    print(filepath)

    img = cv2.imread(filepath)

    x_train.append(np.transpose(img, (2, 0, 1)))

    y_train.append(label)

    cnt = cnt + 1


x_train = np.array(x_train,np.float32)

y_train = np.array(y_train,np.float32).reshape(cnt, 1)


N = len(y_train)


batchsize = 16

datasize = len(x_train)

n_epoch =  args.epoch   # 繰り返し学習回数

# 学習開始

train_start = time.time()

for epoch in range(1, n_epoch+1):

    sum_loss = 0

    perm = np.random.permutation(N) # データセットの順番をシャッフル

    train_start_one = time.time()

    for i in range(0,datasize, batchsize):

        # 初期化

        optimizer.zero_grads()

#model.zero_grads()

        x_batch = cuda.to_gpu(x_train[perm[i:i+batchsize]]) # バッチサイズ分のデータを取り出す

        y_batch = cuda.to_gpu(y_train[perm[i:i+batchsize]])


        # 誤差伝播

        loss = model(x_batch, y_batch)

        # 誤差逆伝播

        loss.backward()

        # ネットワークパラメータ更新

        optimizer.update()


        sum_loss += loss.data

    print "epoch:{} loss={} time:{}".format(epoch, sum_loss / (datasize/batchsize), time.time()-train_start_one)


print "train time:{}".format(time.time()-train_start)

# 学習したモデルを出力する

serializers.save_npz("model.model", model)

serializers.save_npz("state.state", optimizer)




siiii

unread,
Jan 12, 2017, 6:51:07 AM1/12/17
to Chainer Japanese User Group
すみません。端末での表示ですが、以下の間違いでした。
1回目のデータの読み込み時以外は全てnanです


(array[[nan],
          [nan],
.
.
.
         [nan]], dtype=float32))

.....

(array[[nan],
          [nan],
.
.
.
         [nan]], dtype=float32))
epoch:2 loss = nan time:1.129 ....

2017年1月12日木曜日 20時39分00秒 UTC+9 siiii:

Daiki Sanno

unread,
Jan 15, 2017, 10:28:56 PM1/15/17
to Chainer Japanese User Group
はじめまして

GoogLeNetの__call__()にある
loss = F.mean_squared_error(h.data, t.data)
ですが、.dataをとると計算グラフが途切れるので
loss = F.mean_squared_error(h, t)
とするのが正しいです。

2017年1月12日木曜日 20時51分07秒 UTC+9 siiii:

siiii

unread,
Jan 16, 2017, 3:24:45 AM1/16/17
to Chainer Japanese User Group
返信ありがとうございます。

loss = F.mean_squared_error(h, t)としましたがnanのまま変わらずです...
OS X の環境で同様のプログラムを実行した結果, 

//anaconda/lib/python2.7/site-packages/chainer/functions/activation/relu.py:43: RuntimeWarning: invalid value encountered in greater

  return utils.force_array(gy[0] * (x[0] > 0)),


のメッセージが表示されました。結果も同様です。

optimizer.update()をコメント化するとlossが更新されない代わりに全てのhの値が正しく読み込まれますが関係はあるのでしょうか...




siiii

unread,
Jan 16, 2017, 8:35:20 PM1/16/17
to Chainer Japanese User Group
おそらく解決したので報告です。

optimizer.update() を
optimizer.update(model, x_batch, y_batch) とおくことでhやlossもおそらく正常に動きました。
学習中の現在ですので確実とは言えませんがご報告とさせていただきます。

ありがとうございました。

Reply all
Reply to author
Forward
0 new messages