質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.12%

numpy.reshapeの変換エラーについて

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 4,692

mirai0322

score 24

 前提・実現したいこと

PythonでTesnsorflowを使用し、GANによる画像生成プログラムをかいています。
学習画像を読み込み、配列に格納し、numpy.reshape()で形状変換しようとしたところ、
以下のエラーが発生しました。

 発生している問題・エラーメッセージ

type(batch_tuple) :  <class 'tuple'>
type(batch_tuple[0]) :  <class 'numpy.ndarray'>
type(batch_tuple[0][0]) :  <class 'numpy.ndarray'>
len(batch_tuple[0]) :  50
len(batch_tuple[0][0]) :  50
sum :  2500
Traceback (most recent call last):
  File "gan_mnist.py", line 173, in <module>
    batch_images = batch_tuple[0].reshape((BATCH_SIZE, 50))
ValueError: cannot reshape array of size 375000 into shape (50,50)

 数値データに変換するコード(問題なく動作する)

from sklearn.model_selection import train_test_split
from PIL import Image
import os, glob
import numpy as np

root_dir = "./images"   #画像ファイルのあるルートディレクトリ
categories = ["cat", "dog"]     #カテゴリーセット

images_data = []    #画像データ
label_data = []     #ラベルデータ

#ラベリング
for index, name in enumerate(categories):
    #画像ディレクトリのパス
    image_dir = root_dir + "/" + name
    #ディレクトリ内の全画像ファイルを取得
    files = glob.glob(image_dir + "/*.jpg")
    print("-----", name, "処理中-----")
    for index, file in enumerate(files):
        print(file , "-----loading")
        #画像読み込み
        img = Image.open(file)
        #カラーモードをRGBにする
        img = img.convert("RGB")
        #画像をリサイズする
        img = img.resize((50, 50))
        #配列に変換
        data = np.asarray(img)
        #リストに追加
        images_data.append(data)
        label_data.append(index)
#配列に変換、格納
images_data = np.array(images_data)
label_data = np.array(label_data)

#学習データとテストデータを分ける
image_train, image_test, label_train, label_test = train_test_split(images_data, label_data)
#タプルに格納
xy = (image_train, image_test, label_train, label_test)
#ファイル保存
np.save("./images/animal.npy", xy)
print("ok,", len(label_data))

 画像生成プログラム(該当コード)

# 1 ライブラリのインポートとデータセットの取得
import tensorflow as tf

#MNISTデータセット取得のための準備
from tensorflow.examples.tutorials.mnist import input_data
import datetime as dt
import numpy as np

#学習過程で生成される画像の保管はpkl形式
import pickle as pkl

#活性化関数を指定する際に使用
from functools import partial

#各種パラメータ(調整すれば精度向上するかも)

#エポック数(学習回数)ビュアーで定義
EPOCHS = 100
#バッチサイズ 一度に供給するデータの数
BATCH_SIZE = 50
#学習率
LEARNING_RATE = 0.001
#活性化関数のハイパーパラメータ設定
ALPHA = 0.01

categories = ["cat", "dog"]
nb_classes = len(categories)

#パラメータをテキストに出力
#パラメータをテキストに出力
path_w = './パラメータ.txt'
with open(path_w, mode='w', encoding='UTF-8') as f:
    f.write("エポック数:" + str(EPOCHS) + "\n"\
        "バッチサイズ:" + str(BATCH_SIZE) + "\n"\
        "学習率:" + str(LEARNING_RATE) + "\n"\
        "活性化関数:" + str(ALPHA) + "\n")

# 2 生成モデル(Generator)を作る関数の定義

def generator(randomData, alpha, reuse=False):
    with tf.variable_scope('GAN/generator', reuse=reuse):
        #隠れ層
        h1 = tf.layers.dense(randomData, 256, \
            activation=partial(tf.nn.leaky_relu, alpha=alpha))

        #出力層
        o1 = tf.layers.dense(h1, 50*50, activation=None)
        #活性化関数
        img = tf.tanh(o1)

        return img

# 3 識別モデル(Discriminator)を作る関数の定義
def discriminator(img, alpha, reuse=False) :
    with tf.variable_scope('GAN/discriminator', reuse=reuse):
        #隠れ層
        h1 = tf.layers.dense(img, 128, activation=partial(tf.nn.leaky_relu, alpha=alpha))
        #出力層
        D_logits = tf.layers.dense(h1, 1, activation=None)
        #活性化関数
        D = tf.nn.sigmoid(D_logits)

        return D, D_logits

if __name__ == '__main__':
    #データをロードする
    image_train, image_test, label_train, label_test = np.load("./animal.npy")
    #データを正規化する
    image_train = image_train.astype("float") / 256
    print(len(image_train))
    print(len(label_train))
    image_test = image_test.astype("float") / 256
    print(len(image_test))
    print(len(label_test))
    #label_train = np_utils.to_categorical(label_train, nb_classes)
    #label_test = np_utils.to_categorical(label_test, nb_classes)

    #処理開始時間の取得
    tstamp_s = dt.datetime.now().strftime("%H:%M:%S")

    #プレースホルダー
    #本物の画像データ(784次元 28*28px)をバッチサイズ分
    #保管するプレースホルダーを準備する
    ph_realData = tf.placeholder(tf.float32, (BATCH_SIZE, 50*50))
    #100次元の一様乱数を保管するプレースホルダーを準備
    #サイズは、学習時はバッチサイズの100件、
    #各エポックでの生成時は25件と動的に変わるので、
    #Noneを指定し、実行時にサイズを決定する
    ph_randomData = tf.placeholder(tf.float32, (None, 100))

    #一様乱数を与えて画像生成
    gimage = generator(ph_randomData, ALPHA)

    #本物の画像を与えて判定結果を取得
    real_D, real_D_logits = discriminator(ph_realData, ALPHA)

    #生成画像を与えて判定結果を取得
    fake_D, fake_D_logits = discriminator(gimage, ALPHA, reuse=True)

    # 4 損失関数の実装
    #本物画像(ラベル=1)との誤差を
    #クロスエントロピーの平均として取得
    d_real_xentropy = \
    tf.nn.sigmoid_cross_entropy_with_logits(\
        logits=real_D_logits, labels=tf.ones_like(real_D))
    loss_real = tf.reduce_mean(d_real_xentropy)

    ##生成画像(ラベル=0)との誤差を
    #クロスエントロピーの平均として取得
    d_fake_xentropy = \
    tf.nn.sigmoid_cross_entropy_with_logits(\
        logits=fake_D_logits, labels=tf.zeros_like(fake_D))
    loss_fake = tf.reduce_mean(d_fake_xentropy)

    #discriminatorの誤差は本物画像、生成画像における誤差を
    #合計した値とする
    d_loss = loss_real + loss_fake

    #Generatorの誤差を取得
    g_xentropy = tf.nn.sigmoid_cross_entropy_with_logits(\
        logits=fake_D_logits, labels=tf.ones_like(fake_D))
    g_loss = tf.reduce_mean(g_xentropy)

    #学習によって最適化を行うパラメータ(重み)を
    #tf.trainable_variablesから一括して取得する。
    #取得の際に、Discriminator用とGenerator用と取り分けて
    #それぞれのネットワークを最適化していく必要がある

    #discriminatorの最適化を行う学習パラメータを取得
    d_training_parameter = \
    [trainVar for trainVar in tf.trainable_variables() \
    if 'GAN/discriminator' in trainVar.name]

    #generatorの最適化を行う学習パラメータを取得
    g_training_parameter = \
    [trainVar for trainVar in tf.trainable_variables() \
    if 'GAN/generator' in trainVar.name]

    #パラメータの最適化
    #Discriminatorのパラメータを更新
    d_optimize = tf.train.AdamOptimizer(\
        LEARNING_RATE).minimize(d_loss, var_list=d_training_parameter)

    #generatorのパラメータを更新
    g_optimize = tf.train.AdamOptimizer(\
        LEARNING_RATE).minimize(g_loss, var_list=g_training_parameter)   

    # 5 学習処理の実装
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())

        #EPOCHS数分繰り返す
        for e in range(EPOCHS):
            #バッチサイズ50
            for i in range(len(image_train)//BATCH_SIZE):
                img = []
                lbl = []
                for j in range(0, BATCH_SIZE):
                    rand = np.random.randint(len(image_train))
                    img.append(image_train[rand])
                    lbl.append(label_train[rand])

                batch_tuple = (np.array(img), np.array(lbl))
                print("type(batch_tuple) : ", type(batch_tuple))
                print("type(batch_tuple[0]) : ", type(batch_tuple[0]))
                print("type(batch_tuple[0][0]) : ", type(batch_tuple[0][0]))
                print("len(batch_tuple[0]) : ", len(batch_tuple[0]))
                print("len(batch_tuple[0][0]) : ", len(batch_tuple[0][0]))
                sum = 0
                for i in batch_tuple[0]:
                    sum += len(i)
                print("sum : ", sum)
                batch_images = batch_tuple[0].reshape((BATCH_SIZE, 50))
                #generatorにて活性化関数tanhを使用したため、レンジを合わせる
                batch_images = batch_images * 2 - 1
                #generatorに渡す一様分布のランダムノイズ生成
                #値は-1~1まで、サイズはbatch_size*100
                batch_z = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))
                #最適化計算・パラメータ更新を行う
                #discriminatorの最適化に使うデータ群をfeed_dictで与える
                sess.run(d_optimize, feed_dict=\
                    {ph_realData:batch_images, ph_randomData:batch_z})

                #generatorの最適化と最適化に使うデータ群をfeed_dictで与える
                sess.run(g_optimize, feed_dict=\
                    {ph_randomData: batch_z})

            #トレーニングロスを記録
            train_loss_d = sess.run(d_loss, \
                {ph_randomData:batch_z, ph_realData:batch_images})
            #evalはgeneratorのロスを出力する命令
            train_loss_g = g_loss.eval({ph_randomData: batch_z})

            #学習過程の表示
            print(\
                '{0} Epoch={1}/{2}, DLoss={3:.4F}, GLoss={4:.4f}'. \
                format(dt.datetime.now().strftime("%H:%M:%S"), e+1, \
                    EPOCHS, train_loss_d, train_loss_g))

            #lossを格納するためのリストに追加する
            #後で可視化できるようにする
            save_loss.append((train_loss_d, train_loss_g))

            #学習過程の生成モデルで画像を生成して保存
            #一様乱数を25個生成して、そのデータを使って画像を生成し保存
            randomData = np.random.uniform(-1, 1, size=(25, 100))
            #gen_samplesに現時点のモデルで作ったデータを読ませておく
            #ノイズ、サイズ、ユニット数(128),reuseは状態維持
            #データはrandomDataとしてfeed_dict西頴娃
            gen_samples = sess.run(generator(ph_randomData, \
                ALPHA, True), feed_dict={ph_randomData:randomData})
            #生成画像を保存
            save_gimage.append(gen_samples)

        #pkl形式で画像を保存
        with open('save_gimage.pkl', 'wb') as f:
            pkl.dump(save_gimage, f)

        #各エポックで得た損失関数を値を保存
        with open('save_loss.pkl', 'wb') as f:
            pkl.dump(save_loss, f)

        #処理終了時刻の取得
        tstamp_e = dt.datetime.now().strftime("%H:%M:%S")

        time1 = dt.datetime.strptime(tstamp_s, "%H:%M:%S")
        time2 = dt.datetime.strptime(tstamp_e, "%H:%M:%S")

        #処理時間を表示
        print("開始:{0}, 終了:{1}, 処理時間:{2}".format(tstamp_s, \
            tstamp_e, (time2-time1)))

 試したこと

上のエラーメッセージのところにも載せてあるが、配列の要素数の確認をしてみたが、
問題はなさそうだった。

 補足情報(FW/ツールのバージョンなど)

Tensorflow 1.11.0
Numpy 1.15.3

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

エラーを見る限り375000サイズを50x50=2500に変更することはできませんとでていると思います。また、画像データを入力すると考えるならば、(BATCH_SIZE, h*w*c)の入力tensorになると考えられます。375000のサイズから推論させて頂くと、(50, 50*50*3)のサイズを期待しているのではないでしょうか。そのため、 batch_tuple[0].reshape((BATCH_SIZE, 50*50*3))としてみては如何でしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/18 22:42

    回答ありがとうございます
    ご教授頂いた通りにしたら解決しました。
    Pythonを触り始めたばかりでわからないのですが、h*w*cのcの部分にはどんな数値が入るのですか?

    キャンセル

  • 2018/11/19 07:57

    cはチャネルでRGBであれば3,グレースケールであれば1が入ると思います(グレースケールでも3次元に同じ値を入れて3にするケースも見たことがあります.).これはどちらかというとPythonというよりは画像の取扱に関する知識だと思います.

    キャンセル

  • 2018/11/20 15:58

    そうなのですね
    ありがとうございます!

    キャンセル

  • 2018/11/20 15:58

    そうなのですね
    ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る