使用Tensorflow Keras进行猴子识别
猴子识别
机器学习是很简单的。如果您没有任何数学背景知识或任何学术背景的机器学习,也不会是太难的事情。我当然也是属于这个类别。
使用机器学习最基本的目标之一是识别某些东西。我想建立一个可以进行面部识别,识别动物物种,事物名称等的模型。对于数学知识不足的人来说,学习数学是非常可怕的。在我发现“预训练模型”之前,我几乎放弃了这个看似无法实现的目标。
预训练模型基本上是在不同数据集上训练以解决类似问题的模型。有不同种类的预训练模型,每种模型都针对不同问题的具体目的。
今天,我将向您展示如何使用预先训练的模型ResNet50构建猴子识别模型。ResNet50非常适合指定物种。这也用于狗和猫。
开始构建我们的基础
我们还必须有一个包含种类所有索引的JSON文件。
最后,下载ResNet50的预训练模型。
构建我们的数据目录
我的目录文件夹如下所示:
我们有用于训练和验证的图像。记住数据拆分
在训练/验证文件夹中,我们有每个物种及其图像的目录。
转换图像
第一个障碍是把图像转换成机器学习模型可以理解的东西。
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator from tensorflow.python.keras.applications.resnet50 import preprocess_input image_size = 224 data_generator_with_aug = ImageDataGenerator(preprocessing_function=preprocess_input, horizontal_flip=True, width_shift_range=0.2, height_shift_range=0.2) train_path='10-monkey-species/training' train_generator = data_generator_with_aug.flow_from_directory(train_path, target_size=(image_size, image_size), batch_size=24, class_mode='categorical') data_generator_with_no_aug = ImageDataGenerator(preprocessing_function=preprocess_input) validation_path='10-monkey-species/validation' validation_generator = data_generator_with_no_aug.flow_from_directory(validation_path, target_size=(image_size, image_size), batch_size=24, class_mode='categorical')
让我们来分析一下。ImageDataGenerator是一个函数,它接收图像并预处理图像并输出模型能够理解的数据。preprocessing_function参数采用另一个函数,在本例中是ResNet50的preprocess_input,它可以转换RestNet50可以理解的图像。其他参数允许数据扩充。
数据扩充基本上允许您扩充数据。这意味着它允许您增加数据样本,而不必实际增加数据的数量。在这个例子中,翻转图像或稍微改变图像的宽度和高度允许我们有更多的图像样本,而不是实际使用相同的图像。
flow_from_directory 接收您放在目录中的所有图像。
构建我们的模型
from tensorflow.python.keras.applications import ResNet50 from tensorflow.python.keras.models import Sequential from tensorflow.python.keras.layers import Dense, Flatten, Conv2D, Dropout resnet_weights_path = 'resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5' model = Sequential() model.add(ResNet50(include_top=False, pooling='avg', weights=resnet_weights_path)) num_classes = 10 model.add(Dense(num_classes, activation='softmax')) # Say not to train first layer (ResNet) model. It is already trained model.layers[0].trainable = False model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy']) model.fit_generator(train_generator, steps_per_epoch=3, epochs=20, validation_data=validation_generator, validation_steps=1)
分解:
- 所以我们使用了顺序卷积网络。然后我们添加了一个带有预训练权重的ResNet50层。
- 然后我们添加了一个密集层,其中有10个类。类的数量意味着我们试图识别的物种数量。
- 我们还说过,对于我们模型的第一层,我们不想对它进行再训练。
- 然后我们编译了使用model.compile()所做的一切,并最终安装了model.fit_generator()中的所有内容
把我们转换图像时生成的生成器放在这里。
- Epochs基本上是模型在图像中循环的次数。
- steps_per_epoch 是每个epochs接收的图像数量。
测试我们的模型
import numpy as np from os.path import join from tensorflow.python.keras.preprocessing.image import load_img, img_to_array image_dir = '10-monkey-species/validation' img_paths = [join(image_dir, filename) for filename in ['n0/n000.jpg', 'n5/n502.jpg', 'n9/n9031.jpg', 'n2/n2014.jpg']] image_size = 224 def read_prep_images(img_paths, img_height=image_size, img_width=image_size): imgs = [load_img(img_path, target_size=(img_height, img_width)) for img_path in img_paths] img_array = np.array([img_to_array(img) for img in imgs]) output = preprocess_input(img_array) return output test_data = read_prep_images(img_paths)
在这里,我们从验证数据集中获取一些测试图像,并使用read_prep函数将它们更改为np.array。
然后用我们的模型预测它们。
preds = model.predict(test_data) print(preds)
转化我们的预测
我们需要将我们的预测转化为索引,以便:
- 我们可以在JSON文件上使用该索引
- 返回该索引的适当数据
这是我对数据做的一些细微的调整。
import json from IPython.display import Image, display def decode_predictions(preds, top=5, class_list_path=None): if len(preds.shape) != 2 or preds.shape[1] != 10: raise ValueError('`decode_predictions` expects ' 'a batch of predictions ' '(i.e. a 2D array of shape (samples, 1000)). ' 'Found array with shape: ' + str(preds.shape)) index_list = json.load(open(class_list_path)) results = [] for pred in preds: top_indices = pred.argsort()[-top:][::-1] result = [tuple(index_list[str(i)]) + (pred[i],) for i in top_indices] result.sort(key=lambda x: x[2], reverse=True) results.append(result) return results most_likely_labels = decode_predictions(preds, top=5, class_list_path='10-monkey-species/class_monkey_species.json') for i, img_path in enumerate(img_paths): display(Image(img_path)) print(most_likely_labels[i])
因此,该decode_predictions进程接收preds,它是一个2D数组并从json文件索引相应的对象。例如,如果preds是[0,1,8],那么它将从json中索引它并返回[[index_0 ', 'folder_name'], ['index_1', 'folder_name'], ['index_8', 'folder_name']]。
for循环基本上接收图像并用解码后的预测显示它们。
这就是结果:
结论
机器学习变得非常简单。像'softmax'和'relu'这样的特定术语都是数学术语,不需要深入研究它们的机制,但是如果你对它们的作用和用途有一个大致的了解,这将是非常有用的。