Keras-如何训练多班模型?

时间:2019-01-12 07:53:03

标签: python-3.x tensorflow keras

我是机器学习的新手,我遵循了一些youtube指南,并且仅使用2类图像就可以从头开始进行图像分类。

但是现在我很迷茫。我不确定如何制作多类图像分类器。不过,我已经收集了一些线索,例如使用"categorical_crossentrpy"softmax。但是我的问题是在喂入训练之前如何处理图像?

所以我有3个文件夹,每个文件夹约有2000张图像:TreeFoilageStump

我可以使用model.fitbinary_crossentropy执行sigmoid。但是,损失和val_loss为负值。

当我尝试让model.fitcategorical_crossentropy运行softmax时,会抛出此错误:

ValueError: You are passing a target array of shape (460, 1) while using as loss `categorical_crossentropy`. `categorical_crossentropy` expects targets to be binary matrices (1s and 0s) of shape (samples, classes). If your targets are integer classes, you can convert them to the expected format via:
from keras.utils import to_categorical
y_binary = to_categorical(y_int)

Alternatively, you can use the loss function `sparse_categorical_crossentropy` instead, which does expect integer targets.

这是处理代码: 顺便说一下,我所有的代码都是用Jupyter编写的。不好意思,很抱歉。我尽力了。

import numpy as np
import matplotlib.pyplot as plt
import os
import cv2
from tqdm import tqdm

DATADIR = "assets"

CATEGORIES = ["Tree", "Stump", "Ground"]

for category in CATEGORIES:
    path = os.path.join(DATADIR,category)
    for img in os.listdir(path):
        img_array = cv2.imread(os.path.join(path,img) ,cv2.IMREAD_GRAYSCALE)
        plt.imshow(img_array, cmap='gray')
        plt.show()

        break
    break
print(img_array)
print(img_array.shape)
IMG_SIZE = 150

new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
plt.imshow(new_array, cmap='gray')
plt.show()

new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
plt.imshow(new_array, cmap='gray')
plt.show()

training_data = []

def create_training_data():
    for category in CATEGORIES:

        path = os.path.join(DATADIR,category)
        class_num = CATEGORIES.index(category)

        for img in tqdm(os.listdir(path)):
            try:
                img_array = cv2.imread(os.path.join(path,img) ,cv2.IMREAD_GRAYSCALE)
                new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
                training_data.append([new_array, class_num])
            except Exception as e:
                print(e)

create_training_data()

print(len(training_data))

import random

random.shuffle(training_data)

X = []
y = []

for features,label in training_data:
    X.append(features)
    y.append(label)


#print(X[0].reshape(-1, IMG_SIZE, IMG_SIZE, 1))

X = np.array(X).reshape(-1, IMG_SIZE, IMG_SIZE, 1)
# y_len = len(y)
# y = np.array(y).reshape((y_len, 1))
print(y)

import pickle

pickle_out = open("X.pickle","wb")
pickle.dump(X, pickle_out)
pickle_out.close()

pickle_out = open("y.pickle","wb")
pickle.dump(y, pickle_out)
pickle_out.close()

这是制作模型的代码:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.callbacks import TensorBoard
import pickle
import time
import keras
pickle_in = open("X.pickle","rb")
X = pickle.load(pickle_in)

pickle_in = open("y.pickle","rb")
y = pickle.load(pickle_in)
# y = keras.utils.to_categorical(y, num_classes = 3)
# print(y)

X = X/255.0

dense_layers = [0, 1, 2]
layer_sizes = [32, 64, 128]
conv_layers = [1, 2, 3]

for dense_layer in dense_layers:
    for layer_size in layer_sizes:
        for conv_layer in conv_layers:
            NAME = "{}-conv-{}-nodes-{}-dense-{}".format(conv_layer, layer_size, dense_layer, int(time.time()))
            print(NAME)

            model = Sequential()

            model.add(Conv2D(layer_size, (3, 3), input_shape=X.shape[1:]))
            model.add(Activation('relu'))
            model.add(MaxPooling2D(pool_size=(2, 2)))

            for l in range(conv_layer-1):
                model.add(Conv2D(layer_size, (3, 3)))
                model.add(Activation('relu'))
                model.add(MaxPooling2D(pool_size=(2, 2)))

            model.add(Flatten())

            for _ in range(dense_layer):
                model.add(Dense(layer_size))
                model.add(Activation('relu'))

            model.add(Dense(1)) # this value no change ah
            model.add(Activation('softmax'))

            tensorboard = TensorBoard(log_dir="logs/{}".format(NAME))

model.compile(loss='categorical_crossentropy',
                          optimizer='adam',
                          metrics=['accuracy'],
                          )
model.fit(X, y,
                      batch_size=32,
                      epochs=1,
                      validation_split=0.3,
                      callbacks=[tensorboard])

我希望能够训练3个班级的模型。

1 个答案:

答案 0 :(得分:1)

您的代码中有几个错误。 首先,最终致密层的大小必须与标签数相同(在您的情况下为3):

model.add(Dense(1)) # Change this to be 3
model.add(Activation('softmax'))

在单个输出上使用softmax没有意义。

此外,您需要将标签矢量(y)转换为单热编码表示形式,这样,您将拥有:[1,0,0], [0,1,0], [0,0,1](我假设您没有黑莓,而不是0,1和2类)。不会根据您当前的输出形状进行操作):

import numpy as np
num_classes = 3
y.reshape(-1) # your initial classes
Y = np.eye(num_classes )[y]
相关问题