自前で用意したデータで学習しようとしています。
import
1from keras.layers import Conv2D, BatchNormalization, Activation, AveragePooling2D, GlobalAveragePooling2D, Dense, Dropout, Input, Multiply, Reshape 2from keras.models import Model 3from keras.optimizers import Adam 4import numpy as np 5from PIL import Image 6import os 7from keras.utils.np_utils import to_categorical 8 9# 学習用のデータを作る. 10image_list = [] 11label_list = [] 12# ./data/train 以下のorange,appleディレクトリ以下の画像を読み込む。 13for dir in os.listdir("data/training"): 14 if dir == ".DS_Store": 15 continue 16 17 dir1 = "data/training/" + dir 18 label = 0 19 20 if dir == "no": # appleはラベル0 21 label = 0 22 elif dir == "ok": # orangeはラベル1 23 label = 1 24 25 for file in os.listdir(dir1): 26 if file != ".DS_Store": 27 # 配列label_listに正解ラベルを追加(りんご:0 オレンジ:1) 28 label_list.append(label) 29 filepath = dir1 + "/" + file 30 # 画像を25x25pixelに変換し、1要素が[R,G,B]3要素を含む配列の25x25の2次元配列として読み込む。 31 # [R,G,B]はそれぞれが0-255の配列。 32 image = np.array(Image.open(filepath).resize((25, 25))) 33 print(filepath) 34 # 配列を変換し、[[Redの配列],[Greenの配列],[Blueの配列]] のような形にする。 35 image = image.transpose(2, 0, 1) 36 # さらにフラットな1次元配列に変換。最初の1/3はRed、次がGreenの、最後がBlueの要素がフラットに並ぶ。 37 image = image.reshape(1, image.shape[0] * image.shape[1] * image.shape[2]).astype("float32")[0] 38 # 出来上がった配列をimage_listに追加。 39 image_list.append(image / 255.) #この行と1つ上の行を削除しても結果は変わりませんでした 40# kerasに渡すためにnumpy配列に変換。 41image_list = np.array(image_list) 42# ラベルの配列を1と0からなるラベル配列に変更 43# 0 -> [1,0], 1 -> [0,1] という感じ。 44Y = to_categorical(label_list) 45 46def create_new_conv(input, chs): 47 x = Conv2D(chs, 3, padding="same")(input) 48 x = BatchNormalization()(x) 49 return Activation("relu")(x) 50 51# Squeeze and Excitation 52def se_block(input, channels, r=8): 53 # Squeeze 54 x = GlobalAveragePooling2D()(input) 55 # Excitation 56 x = Dense(channels//r, activation="relu")(x) 57 x = Dense(channels, activation="sigmoid")(x) 58 return Multiply()([input, x]) 59 60def create_new_network(use_se_block): 61 input = Input(shape=(25, 25)) 62 x = input 63 x = Reshape((25, 25, 1), input_shape=(25, 25))(input) #ここから上3行の数値部分を変更していました。 64 for i in range(3): 65 x = create_new_conv(x, 50) 66 if use_se_block: x = se_block(x, 50) 67 x = AveragePooling2D(2)(x) 68 for i in range(3): 69 x = create_new_conv(x, 100) 70 if use_se_block: x = se_block(x, 100) 71 x = AveragePooling2D(2)(x) 72 for i in range(3): 73 x = create_new_conv(x, 200) 74 if use_se_block: x = se_block(x, 200) 75 x = GlobalAveragePooling2D()(x) 76 x = Dense(2, activation="sigmoid")(x) 77 78 return Model(input, x) 79model = create_new_network(se_block) 80# オプティマイザにAdamを使用 81opt = Adam(lr=0.001) 82# モデルをコンパイル 83model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"]) 84 # 学習を実行。10%はテストに使用。 85model.fit(image_list, Y, nb_epoch=1500, batch_size=100, validation_split=0.1) 86 87# テスト用ディレクトリ(./data/train/)の画像でチェック。正解率を表示する。 88total = 0. 89ok_count = 0. 90 91for dir in os.listdir("data/training"): 92 if dir == ".DS_Store": 93 continue 94 95 dir1 = "data/validation/" + dir 96 label = 0 97 98 if dir == "no": 99 label = 0 100 elif dir == "ok": 101 label = 1 102 103 for file in os.listdir(dir1): 104 if file != ".DS_Store": 105 label_list.append(label) 106 filepath = dir1 + "/" + file 107 image = np.array(Image.open(filepath).resize((25, 25))) 108 print(filepath) 109 image = image.transpose(2, 0, 1) 110 image = image.reshape(1, image.shape[0] * image.shape[1] * image.shape[2]).astype("float32")[0] 111 result = model.predict_classes(np.array([image / 255.])) 112 print("label:", label, "result:", result[0]) 113 114 total += 1. 115 116 if label == result[0]: 117 ok_count += 1. 118 119print("seikai: ", ok_count / total * 100, "%") 120# モデルの可視化 121from IPython.display import SVG 122from keras.utils.vis_utils import model_to_dot 123 124SVG(model_to_dot(model).create(prog='dot', format='svg'))
#エラー
ValueError: Input 0 is incompatible with layer conv2d_48: expected ndim=4, found ndim=3
ValueError: Error when checking input: expected input_24 to have 3 dimensions, but got array with shape (40, 1875)
色々なサイトを参照しても解決できず、一度画像の形状をprint(Y)で調べると以下のような結果になりました。
data/training/apple/ta1.jpg
1data/training/apple/ta10.jpg 2data/training/apple/ta11.jpg 3data/training/apple/ta12.jpg 4data/training/apple/ta13.jpg 5data/training/apple/ta14.jpg 6data/training/apple/ta15.jpg 7data/training/apple/ta16.jpg 8data/training/apple/ta17.jpg 9data/training/apple/ta18.jpg 10data/training/apple/ta19.jpg 11data/training/apple/ta2.jpg 12data/training/apple/ta20.jpg 13data/training/apple/ta3.jpg 14data/training/apple/ta4.jpg 15data/training/apple/ta5.jpg 16data/training/apple/ta6.jpg 17data/training/apple/ta7.jpg 18data/training/apple/ta8.jpg 19data/training/apple/ta9.jpg 20data/training/orange/to1.jpg 21data/training/orange/to10.jpg 22data/training/orange/to11.jpg 23data/training/orange/to12.jpg 24data/training/orange/to13.jpg 25data/training/orange/to14.jpg 26data/training/orange/to15.jpg 27data/training/orange/to16.jpg 28data/training/orange/to17.jpg 29data/training/orange/to18.jpg 30data/training/orange/to19.jpg 31data/training/orange/to2.jpg 32data/training/orange/to20.jpg 33data/training/orange/to3.jpg 34data/training/orange/to4.jpg 35data/training/orange/to5.jpg 36data/training/orange/to6.jpg 37data/training/orange/to7.jpg 38data/training/orange/to8.jpg 39data/training/orange/to9.jpg 40[[1.] 41 [1.] 42 [1.] 43 [1.] 44 [1.] 45 [1.] 46 [1.] 47 [1.] 48 [1.] 49 [1.] 50 [1.] 51 [1.] 52 [1.] 53 [1.] 54 [1.] 55 [1.] 56 [1.] 57 [1.] 58 [1.] 59 [1.] 60 [1.] 61 [1.] 62 [1.] 63 [1.] 64 [1.] 65 [1.] 66 [1.] 67 [1.] 68 [1.] 69 [1.] 70 [1.] 71 [1.] 72 [1.] 73 [1.] 74 [1.] 75 [1.] 76 [1.] 77 [1.] 78 [1.] 79 [1.]]
本来なら、ここは[1.0][0.1]のような形状(配列?)になっているはずなのですが、どう書き換えても上のような表示になってしまいます。どうすればいいのでしょうか
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。