https://www.toutiao.com/a6670173759829180936/
在本文中,我们将讨论如何使用Keras在不适合内存的大数据集上训练我们的深度学习网络。
深度学习算法优于所有其他算法,能够在大多数问题上产生最先进的结果。深度学习算法成功的主要原因是数据集的大小越来越大。现在,深度学习算法在大型数据集上进行训练,这些数据集甚至不适合内存。问题是:如何在如此庞大的数据集上训练我们的模型?本文分为以下几个部分:
一般情况下,深度学习算法的性能优于其他算法,并且能够在大多数问题上产生较好的结果。深度学习算法成功的主要原因是数据集的不断增大。现在,深度学习算法在大型数据集上进行训练,这些数据集甚至不适合内存。问题是:如何在如此巨的数据集中训练我们的深度学习模型呢?本文分为以下几个部分:
作为一个例子,我们将解决Kaggle“Plant Seedlings Classification”的挑战。这个数据集并不大,但我们将假设数据集太大,无法装入内存,然后将批量加载数据集。
您可以从此处下载(https://www.kaggle.com/c/plant-seedlings-classification/data)数据集。解压缩train.zip文件夹。该数据集包含分类为12种植物物种的不同阶段的植物幼苗的4750幅图像。12种植物有Black-grass,Charlock,Cleavers,Common Chickweed,Common wheat,Fat Hen,Losse Silky-bent,Maize,Scentless Mayweed,Shepherds Purse,Small-flowered Cranesbill,Sugar beet。竞赛的目标是创建一个能够从照片中确定植物种类的分类器。
当前目录如下所示:
文件夹目录
如果您的问题数据集不是这种格式,请不要担心。您的数据集可以是任何格式。我们将在下一节中看到,目标是获取所有数据点(即我们示例中的图像)并将它们保存到单个文件夹中。数据点可以是图像,音频等。
下一步是获取整个数据集(即所有数据点(在我们的示例中为图像))并将它们存储到一个文件夹中。我们创建一个名为“all_images”的新文件夹,目标是将数据集中的所有图像存储在这个“all_images”文件夹中。
我们使用以下脚本将所有图像存储在“all_images”文件夹中。您可以编写类似的脚本来获取数据集中的所有数据点(可以是图像,音频等)并将它们存储到新文件夹中。
import os
import shutil
train_dir = '/content/train'
dest_dir = '/content/all_images'
counter = 0
for subdir, dirs, files in os.walk(train_dir):
#print(files)
for file in files:
full_path = os.path.join(subdir, file)
shutil.copy(full_path, dest_dir)
counter = counter + 1
print(counter)
下一步是将每个数据点的名称(即每个图像的名称)存储在一个数组中(让我们将数组命名为filename)。还有一件事是将与每个数据点关联的标签存储在另一个数组中(让我们将这个数组称为labels)。
下面是一个Python脚本,它将每个图像的名称存储在filenames数组中,并将与该图像关联的标签存储在labels数组中。
注意:请记住,每个数据点的名称应该是唯一的。
import numpy as np
subdirs, dirs, files = os.walk('/content/all_images').__next__()
m = len(files)
print(m)
filenames = []
labels = np.zeros((m, 1))
import os
import shutil
images_dir = '/content/all_images'
filenames_counter = 0
labels_counter = -1
for subdir, dirs, files in os.walk(train_dir):
#print(files)
for file in files:
filenames.append(file)
labels[filenames_counter, 0] = labels_counter
filenames_counter = filenames_counter + 1
labels_counter = labels_counter+1
print(len(filenames))
print(labels.shape)
现在,您可以保存“all_images”文件夹、“filename”数组和“labels”数组,以便稍后使用。
下面我们创建一个由filename 和labels组成的numpy数组,并将它们保存为.npy文件。
# saving the filename array as .npy file
np.save('filenames.npy', filenames)
import keras
from keras.utils import to_categorical
# One hot vector representation of labels
y_labels_one_hot = to_categorical(labels)
# saving the y_labels_one_hot array as a .npy file
np.save('y_labels_one_hot.npy', y_labels_one_hot)
下一步是对数据集进行shuffle ,以便从数据集中删除对称性。
from sklearn.utils import shuffle
filenames_shuffled, y_labels_one_hot_shuffled = shuffle(filenames, y_labels_one_hot)
# saving the shuffled file.
# you can load them later using np.load().
np.save('y_labels_one_hot_shuffled.npy', y_labels_one_hot_shuffled)
np.save('filenames_shuffled.npy', filenames_shuffled)
现在,让我们将数据集拆分为训练和验证集。我们也可以保存这些文件,因为这些文件稍后将用于训练和验证我们的机器学习模型。
from sklearn.model_selection import train_test_split
filenames_shuffled_numpy = np.array(filenames_shuffled)
X_train_filenames, X_val_filenames, y_train, y_val = train_test_split(
filenames_shuffled_numpy, y_labels_one_hot_shuffled, test_size=0.2, random_state=1)
print(X_train_filenames.shape)
print(y_train.shape)
print(X_val_filenames.shape)
print(y_val.shape)
np.save('X_train_filenames.npy', X_train_filenames)
np.save('y_train.npy', y_train)
np.save('X_val_filenames.npy', X_val_filenames)
np.save('y_val.npy', y_val)
您还可以将“all_images”文件夹保存为zip格式,以便与其他团队成员共享数据集。
这些代码行只创建一个“all_images.zip”文件夹。
import shutil
shutil.make_archive("all_images", "zip", "all_images")
注意:由于我们的数据集太大而无法容纳在内存中,因此我们必须将数据集从硬盘批量加载到内存中。
为此,我们将创建一个自定义生成器。我们的自定义生成器将要将数据集从硬盘批量加载到内存中。
class My_Custom_Generator(keras.utils.Sequence) :
def __init__(self, image_filenames, labels, batch_size) :
self.image_filenames = image_filenames
self.labels = labels
self.batch_size = batch_size
def __len__(self) :
return (np.ceil(len(self.image_filenames) / float(self.batch_size))).astype(np.int)
def __getitem__(self, idx) :
batch_x = self.image_filenames[idx * self.batch_size : (idx+1) * self.batch_size]
batch_y = self.labels[idx * self.batch_size : (idx+1) * self.batch_size]
return np.array([
resize(imread('/content/all_images/' + str(file_name)), (80, 80, 3))
for file_name in batch_x])/255.0, np.array(batch_y)
让我们试着理解整个代码:
我们已经创建了数据生成器。下一步是创建此类的实例。
batch_size = 32
my_training_batch_generator = My_Custom_Generator(X_train_filenames, y_train, batch_size)
my_validation_batch_generator = My_Custom_Generator(X_val_filenames, y_val, batch_size)
我们先导入一些Python库:
import numpy as np
import pandas as pd
from skimage.io import imread
from skimage.transform import resize
import keras
from keras.models import Sequential, Model, load_model
from keras.layers import Input, Conv1D, Conv2D, MaxPooling1D, MaxPooling2D, Dense, Dropout, Activation, Flatten
from keras.layers.normalization import BatchNormalization
from keras.utils import to_categorical
现在,让我们定义模型架构并编译机器学习模型。您可以在此处使用任何模型架构。
model = Sequential()
model.add(Conv2D(filters = 64, kernel_size = (5,5), activation ='relu',input_shape=(80,80,3)))
model.add(BatchNormalization(axis=3))
model.add(Conv2D(filters = 64, kernel_size = (5,5), activation ='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization(axis=3))
model.add(Dropout(0.25))
model.add(Conv2D(filters = 128, kernel_size = (5,5), activation ='relu'))
model.add(BatchNormalization(axis=3))
model.add(Conv2D(filters = 128, kernel_size = (5,5), activation ='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization(axis=3))
model.add(Dropout(0.25))
model.add(Conv2D(filters = 256, kernel_size = (5,5), activation ='relu'))
model.add(BatchNormalization(axis=3))
model.add(Conv2D(filters = 256, kernel_size = (5,5), activation ='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization(axis=3))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation = "relu")) #Fully connected layer
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(60, activation = "relu")) #Fully connected layer
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(12, activation = "softmax")) #Classification layer or output layer
model.compile(optimizer="adam", loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
现在,让我们训练我们的机器学习模型。
model.fit_generator(generator=my_training_batch_generator,
steps_per_epoch = int(3800 // batch_size),
epochs = 10,
verbose = 1,
validation_data = my_validation_batch_generator,
validation_steps = int(950 // batch_size))
训练结果:
我们的模型没有给出很好的结果,而且过度拟合。我们可以使用不同的模型架构,或者预处理我们的数据集,或使用数据增强,或者使用迁移学习来提高精度。但是,这不是本文的目的。我希望现在您已经非常清楚地理解了如何使用大数据集来训练一个深度学习模型。
这篇文章,我试着用一个例子给你一个非常清晰的理解,告诉你如何用一个巨大的数据集训练你自己的深度学习模型。
注意:最好先对数据集进行预处理,然后将其提供给学习算法。