Translator|朱宪忠审稿人|SunShujuanPretrained神经元网络使用数百万个数据点进行训练。如今,这种技术最著名的用途是训练深度神经网络,因为这种方法在用较少的数据训练深度神经网络时表现出了良好的性能。事实上,这种技术在数据科学领域也很有用,因为大多数现实世界的数据通常没有数百万个数据点来训练一个健壮的深度学习模型。目前,有许多模型使用数百万个数据点进行训练,这些模型可用于以最大准确度训练复杂的深度学习神经网络。在本教程中,您将学习如何使用迁移学习技术训练深度神经网络的完整过程。使用Keras程序进行迁移学习在构建或训练深度神经网络之前,您必须弄清楚哪些选项可用于迁移学习,以及必须使用哪个选项来为您的项目训练复杂的深度神经网络。Keras应用程序是一种高级深度学习模型,可提供可用于预测、特征提取和微调的预训练权重。Keras库中内置了许多现成的模型,其中一些流行的模型包括:XceptionVGG16和VGG19ResNet系列MobileNet【补充】Keras应用程序提供了一组深度学习模型,可以与预训练的权重一起使用。关于这些模型更具体的内容,请参考Keras官网内容。在本文中,您将了解MobileNet模型在迁移学习中的应用。训练深度学习模型在本节中,您将学习如何通过几个步骤构建用于图像识别的自定义深度学习模型,而无需编写任何系列的卷积神经网络(CNN),您只需微调预trainedmodel允许您的模型在训练数据集上进行训练。在本文中,我们构建了一个能够识别手势语言数字图像的深度学习模型。接下来,让我们着手构建这个定制的深度学习模型。获取数据集要开始构建深度学习模型的过程,您首先需要准备数据,您可以通过访问名为Kaggle的网站轻松地从数百万数据集中选择合适的数据集。当然,还有许多其他网站提供可用于构建深度学习或机器学习模型的数据集。但本文将使用的数据集取自Kaggle网站提供的AmericanSignLanguageDigits数据集。数据预处理下载数据集并将其保存到本地存储后,现在是时候对数据集进行一些预处理了,比如准备数据,将数据拆分为训练目录、有效目录和测试目录,定义它们的路径以及创建批次用于训练目的等。在准备下载数据集的数据时,它包含一个从0到9的数据目录,其中包含输入图像、输出图像三个子文件夹和一个名为CSV的文件夹。接下来,从每个目录中删除输出图像和CSV文件夹,将输入图像文件夹的内容移动到主目录,并删除输入图像文件夹。数据集的每个主目录现在包含500张图像,您可以选择保留所有图像。但是,出于演示目的,本文的每个目录中仅使用了其中的200张图像。最后,数据集的结构如下图所示:数据集的文件夹结构拆分数据集现在,让我们首先将数据集拆分为三个子目录:train、valid和test。train目录将包含训练数据,这些数据将用作我们模型的输入以学习模式和不规则性。有效目录将包含将被输入模型的验证数据,并且将是模型看到的第一个看不见的数据,这将有助于实现最大的准确性。测试目录将包含用于测试模型的测试数据。首先,让我们导入将在代码中进一步使用的库。#Importrequiredlibrariesimportosimportshutilimportrandom以下是生成所需目录并将数据移动到特定目录的代码。#创建三个子目录:train、valid和test,整理下它们下的数据os.chdir('D:\SACHIN\Jupyter\HandSignLanguage\Hand_Sign_Language_DL_Project\American-Sign-Language-Digits-Dataset')#If如果目录不存在,如果os.path.isdir('train/0/')为False,则创建相应的子目录:os.mkdir('train')os.mkdir('valid')os.mkdir('test')foriinrange(0,10):#将0-9子目录移动到train子目录shutil.move(f'{i}','train')os.mkdir(f'valid/{i}')os.mkdir(f'test/{i}')#从有效子目录中取90张样本图片valid_samples=random.sample(os.listdir(f'train/{i}'),90)forjinvalid_samples:#Move从子目录train到有效子目录的样本图像shutil.move(f'train/{i}/{j}',f'valid/{i}')#从test子目录样本图像中取90个样本test_samples=random.sample(os.listdir(f'train/{i}'),10)forkintest_samples:#将样本图片从train子目录移动到test子目录shutil.move(f'train/{i}/{k}',f'test/{i}')os.chdir('../..')在上面的代码中,我们首先更改本地存储中数据集对应的目录,然后检查如果train/0目录已经存在;如果没有,我们将分别创建train、valid和test子目录。然后,我们创建子目录0到9并将所有数据移动到train目录中,并分别在valid和test子目录下创建子目录0到9。然后,我们遍历训练目录中的子目录0到9,并从每个子目录中随机获取90个图像数据,并将它们移动到有效目录中的相应子目录中。测试目录test也是如此。【补充】Python中执行高级文件操作的shutil模块(手动将文件或文件夹从一个目录复制或移动到另一个目录是一件很痛苦的事情,详细的技巧可以参考文章https://medium.com/@geekpython/perform-high-level-file-operations-in-python-shutil-module-dfd71b149d32)。定义目录路径创建所需目录后,您现在需要定义三个子目录train、valid和test的路径。#分别为train、valid、test三个子目录指定路径train_path='D:/SACHIN/Jupyter/HandSignLanguage/Hand_Sign_Language_DL_Project/American-Sign-Language-Digits-Dataset/train'valid_path='D:/SACHIN/Jupyter/HandSignLanguage/Hand_Sign_Language_DL_Project/American-Sign-Language-Digits-Dataset/valid'test_path='D:/SACHIN/Jupyter/HandSignLanguage/Hand_Sign_Language_DL_Project/American-Sign-Language-Digits-Dataset/test'用于预处理预训练深度学习模型需要一些经过预处理的数据,这对于训练来说非常理想。因此,数据需要采用预训练模型所需的格式。在应用任何预处理之前,让我们导入TensorFlow及其将在代码中进一步使用的实用程序。#导入TensorFlow及其应用程序importtensorflowastffromtensorflowimportkerasfromtensorflow.keras.layersimportDense,Activationfromtensorflow.keras.optimizersimportAdamfromtensorflow.keras.metricsimportcategorical_crossentropyfromtensorflow.keras.preprocessing.imageimportImageDataGeneratorfromtensorflow.keras.preprocessingimportimagefromtensorflow.keras.modelsimportModelfromtensorflow.keras.modelsimportload_model#创建批量训练、验证和测试图像,使用Mobilenet的预处理模型进行预处理train_batches=ImageDataGenerator(preprocessing_function=tf.keras.applications.mobilenet.preprocess_input).flow_from_directory(目录=train_path,target_size=(224,224),batch_size=10,shuffle=True)valid_batches=ImageDataGenerator(preprocessing_function=tf.keras.applications.mobilenet.preprocess_input).flow_from_directory(directory=valid_path,target_size=(224,224),batch_size=10,shuffle=True)test_batches=ImageDataGenerator(preprocessing_function=tf.keras.applications.mobilenet.preprocess_input).flow_from_directory(directory=test_path,target_size=(224,224),batch_size=10,shuffle=False)我们使用ImageDatagenerator,它有一个参数preprocessing_function,在preprocessing_function中我们处理MobileNet模型提供的图像,经过预处理后,flow_from_directory函数被调用,我们在其中提供要训练的图像的目录和尺寸的路径,因为MobileNet模型是针对尺寸为224x224的图像进行训练的。接下来,定义批量大小——一次迭代可以处理多少张图像,然后我们随机打乱图像处理的顺序。在这里,我们不会随机打乱测试数据的图像,因为测试数据不会用于训练。在JupyterNotebook或GoogleColab中运行上述代码片段后,您将看到如下结果。以上代码的输出。ImageDataGenerator一般的应用场景是扩充数据。以下是在Keras框架中使用ImageDataGenerator进行数据扩充的指南。创建模型在将训练和验证数据拟合到模型中之前,深度学习模型MobileNet需要通过添加输出层、删除不必要的层并使某些层不可训练来进行微调以提高准确性。以下代码将从Keras下载MobileNet模型并将其存储在mobile变量中。第一次运行以下代码片段时需要连接到Internet。mobile=tf.keras.applications.mobilenet.MobileNet()如果运行以下代码,您将看到模型的摘要,您可以在其中看到一系列神经网络层的输出。mobile.summary()现在,我们将以10为单位向模型添加一个完全连接的输出层(也称为“密集层”)——因为从0到9将有10个输出。此外,我们删除了最后一个来自MobileNet模型的六层。#移除最后6层并添加一个输出层x=mobile.layers[-6].outputoutput=Dense(units=10,activation='softmax')(x)然后,我们将所有输入和输出层添加到模型.model=Model(inputs=mobile.input,outputs=output)现在,我们将最后23层设置为不可训练-实际上是一个相对任意的数字。通常,这个特定数字是通过大量试验和错误得出的。此代码的唯一目的是通过使某些层不可训练来提高准确性。#我们不会训练最后的23层-23这里是mobile.layers[:-23]中层的一个相对任意的数字:layer.trainable=False如果你看到微调模型的汇总输出,你会付出代价注意与之前看到的原始摘要相比,不可训练参数和层数的数量存在一些差异。model.summary()接下来,我们需要编译一个名为Adam的优化器,选择0.0001的学习率、一个损失函数和一个测量参数来衡量模型的准确性。model.compile(optimizer=Adam(learning_rate=0.0001),loss='categorical_crossentropy',metrics=['accuracy'])现在是准备模型并开始训练训练和验证数据的时候了。在下面的代码中,我们提供了训练和验证数据以及训练的总轮数。Detailsarejusttoshowaccuracyprogress,hereyoucanspecifyanumericparametervalueof0,1or2.#运行总共10个epochsmodel.fit(x=train_batches,validation_data=valid_batches,epochs=10,verbose=2)如果你运行上面的代码片段那么你会看到trainingdataloss和accuracyepochs每一步的输出内容。对于验证数据,您还可以看到此输出。训练epochsteps记忆模型显示准确度值该模型现已准备就绪,准确度得分为99%。现在记住一件事:这个模型可能过度拟合,因此可能在给定数据集图像以外的图像上表现不佳。#检查模型是否存在;否则,如果os.path.isfile("D:/SACHIN/Models/Hand-Sign-Digit-Language/digit_model.h5")为False,则保存模型:model.save("D:/SACHIN/Models/Hand-Sign-Digit-Language/digit_model.h5")上面的代码将检查是否已经存在模型的副本。如果没有,调用save函数将模型保存到指定路径。测试模型此时,模型已经过训练并准备好识别图像。本节介绍加载模型和编写函数以准备图像、预测结果以及显示和打印预测结果。在编写任何代码之前,您需要导入一些必要的库,这些库将在代码中进一步使用。importnumpyasnpiimportmatplotlib.pyplotaspltfromPILimportImageload图像的自定义模型预测将使用上面使用迁移学习技术创建的模型进行。因此,我们首先需要加载模型以备后用。my_model=load_model("D:/SACHIN/Models/Hand-Sign-Digit-Language/digit_model.h5")在这里,我们使用load_model函数从指定路径加载模型并存储在my_model变量中,以便进一步在下面的代码中使用。准备输入图像在将任何图像输入模型进行预测或识别之前,我们需要以模型期望的格式提供它。defpreprocess_img(img_path):open_img=image.load_img(img_path,target_size=(224,224))img_arr=image.img_to_array(open_img)/255.0img_reshape=img_arr.reshape(1,224,224,3)returnimg_reshape定义一个函数preprocess_img它获取图像的路径,然后使用图像实用程序中的load_img函数加载该图像并将目标大小设置为224x224。然后将该图像转换为数组并将该数组除以255.0,这会将图像的像素值转换为0和1,然后将图像数组重新缩放为形状(224,224,3)最后返回转换后的形状图片。编写预测函数defpredict_result(predict):pred=my_model.predict(predict)returnnp.argmax(pred[0],axis=-1)在这里,我们定义了一个接受预测参数的函数predict_result,它基本上是一个预处理图像。然后,我们调用模型的预测函数来预测结果。最后,返回预测结果中的最大值。显示和预测图像首先,我们将创建一个获取图像路径的函数,然后显示图像和预测。#显示和预测图像函数defdisplay_and_predict(img_path_input):display_img=Image.open(img_path_input)plt.imshow(display_img)plt.show()img=preprocess_img(img_path_input)pred=predict_result(img)print("Prediction:",pred)上面函数display_and_predict首先获取图片的路径并使用PIL库中的Image.open函数打开图片,然后使用matplotlib库显示图片,然后将图片传递给preprep_img函数输出预测结果,最后使用predict_result函数得到结果,最后打印出来。img_input=input("Enterthepathofanimage:")display_and_predict(img_input)如果运行上面的代码片段并在数据集中输入图像的路径,您将获得所需的输出。预测结果图请注意,到目前为止,该模型已使用迁移学习技术成功创建,而无需编写与一系列神经网络层相关的任何代码。现在,该模型可用于开发能够进行图像识别的Web应用程序。文末链接提供了如何将模型应用到Flask应用中的完整实现源码。结论在本文中,我们描述了使用预训练模型或迁移学习技术制作自定义深度学习模型的过程。到目前为止,您已经了解了创建完整深度学习模型所涉及的每个步骤。综上所述,使用的总体步骤包括:准备数据集预处理数据创建模型保存自定义模型测试自定义模型最后,您可以从GitHub上获取本文示例项目的完整源码。译者介绍朱宪忠,社区编辑,专家博主,讲师,潍坊某高校计算机教师,自由编程资深人士。原标题:TrainedACustomDeepLearningModelUsingATransferLearningTechnique,作者:SachinPal
