【发布时间】:2019-01-20 10:53:36
【问题描述】:
我是机器学习的初学者。我正在使用 keras 制作一个 CNN 模型来检测叶子图像中的害虫。在训练数据期间,内存超出,我无法训练。我使用过 kaggle/Google Collab,但两者都有记忆问题。 有人建议我使用数据生成器,但是在尝试这样做时,我无法做到。是否有任何其他有效训练的方法或是否使用数据生成器的任何示例(看过很多示例但添加时遇到问题。
import numpy as np
import pickle
import cv2
from os import listdir
from sklearn.preprocessing import LabelBinarizer
from keras.models import Sequential
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation, Flatten, Dropout, Dense
from keras import backend as K
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
from keras.preprocessing import image
from keras.preprocessing.image import img_to_array
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
EPOCHS = 25
INIT_LR = 1e-3
BS = 32
default_image_size = tuple((256, 256))
image_size = 0
directory_root = 'PlantVillage/'
width=256
height=256
depth=3
#Function to convert images to array
def convert_image_to_array(image_dir):
try:
image = cv2.imread(image_dir)
if image is not None:
image = cv2.resize(image,default_image_size)
return img_to_array(image)
else:
return np.array([])
except Exception as e:
print(f"Error : {e}")
return None
image_list, label_list = [], []
try:
print("[INFO] Loading images ...")
root_dir = listdir(directory_root)
#Looping inside root_directory
for directory in root_dir :
# remove .DS_Store from list
if directory == ".DS_Store" :
root_dir.remove(directory)
for plant_folder in root_dir :
plant_disease_folder_list = listdir(f"{directory_root}/{plant_folder}")
print(f"[INFO] Processing {plant_folder} ...")
#looping in images
for disease_folder in plant_disease_folder_list :
# remove .DS_Store from list
if disease_folder == ".DS_Store" :
plant_disease_folder_list.remove(plant_folder)
#If all data taken not able to train
for images in plant_disease_folder_list:
image_directory = f"{directory_root}/{plant_folder}/{images}"
if image_directory.endswith(".jpg") == True or image_directory.endswith(".JPG") == True:
image_list.append(convert_image_to_array(image_directory))
label_list.append(plant_folder)
print("[INFO] Image loading completed")
except Exception as e:
print(f"Error : {e}")
#Get Size of Processed Image
image_size = len(image_list)
#Converting multi-class labels to binary labels(belong or doesnot belong in the class)
label_binarizer = LabelBinarizer()
image_labels = label_binarizer.fit_transform(label_list)
#Saving label binarizer instance using pickle
pickle.dump(label_binarizer,open('label_transform.pkl','wb'))
n_classes = len(label_binarizer.classes_)
print(label_binarizer.classes_)
#Normalizing image from [0,255] to [0,1]
np_image_list = np.array(image_list, dtype = np.float)/255.0
#Splitting data into training and test set 80:20
print('Splitting data to train,test')
x_train, x_test, y_train, y_test = train_test_split(np_image_list, image_labels, test_size=0.2, random_state = 42)
#Creating image generator object which performs random rotations, shifs,flips,crops,sheers
aug = ImageDataGenerator(
rotation_range = 25, width_shift_range=0.1,
height_shift_range=0.1, shear_range=0.2,
zoom_range=0.2, horizontal_flip = True,
fill_mode="nearest")
model = Sequential()
inputShape = (height, width, depth)
chanDim = -1
if K.image_data_format() == "channels_first":
inputShape = (depth, height, width)
chanDim = 1
model.add(Conv2D(32, (3, 3), padding="same",input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(32))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(n_classes))
model.add(Activation("softmax"))
#model.summary()
#Compiling the CNN
opt = Adam(lr= INIT_LR, decay= INIT_LR/EPOCHS)
#distribution
model.compile(loss="binary_crossentropy", optimizer = opt, metrics=["accuracy"])
#training the Model
print("Training Model.....")
history = model.fit_generator(
aug.flow(x_train, y_train, batch_size= BS),
validation_data = (x_test, y_test),
steps_per_epoch = len(x_train) // BS,
epochs = EPOCHS, verbose = 1
)
您也可以在 link 中找到代码。
【问题讨论】:
-
你训练了多少张图片?对于 1-2M 图像的训练,我使用了 10k 图像块。因此,将 10k 图像读入内存,拟合模型,加载下一个块,拟合模型,直到所有图像都经过一个 epoch,然后迭代所需的 epoch 数量。我不知道生成器是否会做一些更聪明的事情,或者它是否会影响准确性。
-
def sgd(X_train, y_train, minibatch_size = 200): while True: for iter in range(n_iter): print('Iteration {}'.format(iter)) # 随机化数据点 X_train, y_train = shuffle(X_train, y_train) for i in range(0, X_train.shape[0], minibatch_size): # 获取当前minibatch/chunk的一对(X, y) X_train_mini = X_train[i:i + minibatch_size] y_train_mini = y_train[i:i + minibatch_size] return X_train_mini,y_train_mini
标签: machine-learning keras computer-vision conv-neural-network