TensorFlow + Keras 图像识别:Dogs vs Cats Image Classification(Transfer Learning using MobileNet)

OS:Win10

Interpreter: Python3.7

Environment: Anaconda3 + Tensorflow-gpu2.0.0 + Spyder + Tensorflow_hub5.0.0

API:  tf.keras(a high-level API to build and train models in TensorFlow)

和上一个项目(https://blog.csdn.net/Happy_hui520/article/details/95474814)用的是同一个数据集,主要是应用迁移学习,大幅度提高分类准确度(~83% -> ~99%),参考自TensorFlow官方项目展示https://colab.research.google.com/github/tensorflow/examples/blob/master/courses/udacity_intro_to_tensorflow_for_deep_learning/l06c01_tensorflow_hub_and_transfer_learning.ipynb

这里先贴一下完整的代码,部分改动较大。没有和官方代码用同样的数据集(太大了,训练耗时长),也没有用同样的数据导入方式(tensorflow_hub内用函数直接导入需要网络能访问外网,我用代理服务器试了一下可以),改用的tensorflow.keras.preprocessing.image.ImageDataGenerator从磁盘加载数据。

直接下载网络模型会报错:

完整代码

# -*- coding: utf-8 -*-
"""
Created on Fri Jul 12 17:36:46 2019

@author: Happy_hui
"""

from __future__ import absolute_import, division, print_function, unicode_literals

import matplotlib.pylab as plt
import numpy as np

import tensorflow as tf
import tensorflow_hub as hub
import tensorflow_datasets as tfds
from tensorflow.keras import layers
from tensorflow.keras.preprocessing.image import ImageDataGenerator

import logging
logger = tf.get_logger()
logger.setLevel(logging.ERROR)

CLASSIFIER_URL ="https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/2"
IMAGE_RES = 224
# 用hub下载的模型作为单位的网络层序列化成tf.keras模型
model = tf.keras.Sequential([
    hub.KerasLayer(CLASSIFIER_URL, input_shape=(IMAGE_RES, IMAGE_RES, 3))
])

import numpy as np
import PIL.Image as Image
# 第一个参数是文件名,返回文件存储路径
grace_hopper_path = tf.keras.utils.get_file('image.jpg','https://storage.googleapis.com/download.tensorflow.org/example_images/grace_hopper.jpg')
grace_hopper = Image.open(grace_hopper_path).resize((IMAGE_RES, IMAGE_RES)) # Image对象 

# PIL.Image可以直接转换为np矩阵
grace_hopper = np.array(grace_hopper)/255

# 记住,模型总是想要处理一批(batch)图像,所以要添加一个批维度(batch dimension)然后传给模型做预测
result = model.predict(grace_hopper[np.newaxis,:]) #首部加一个新维度
result.shape # (1,1001) 这是原模型的输出向量,一共有1001个类别,每个数代表属于此类的概率
predicted_class = np.argmax(result[0])

# Decode the predictions
labels_path = tf.keras.utils.get_file('ImageNetLabels.txt','https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
# 从txt文件中读出数据、按行切分,然后变成矩阵
imagenet_labels = np.array(open(labels_path).read().splitlines())

# 把预测结果和图像同时打印出来
plt.imshow(grace_hopper)
plt.axis('off')
predicted_class_name = imagenet_labels[predicted_class]
plt.title("Prediction: " + predicted_class_name) # 正确!


"""
# Dataset
# We can use TensorFlow Datasets to load the Dogs vs Cats dataset.

splits = tfds.Split.ALL.subsplit(weighted=(8,2))
# tfds.load只能下载官网上的公开数据集?
datasets, info = tfds.load('cats_vs_dogs', with_info=True, as_supervised=True, split = splits)
(train_examples, validation_examples) = datasets

num_examples = info.datasets['train'].num_examples
num_classes = info.datasets['label'].num_classes
"""

# 准备数据(数据集已经下载完)
# Setting Model Parameters
base_dir = r'C:\Users\DELL\.keras\datasets\cats_and_dogs_filtered'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')

BATCH_SIZE = 20
IMAGE_SHAPE = 224
train_image_generator = ImageDataGenerator(rescale = 1./255)
validation_image_generator = ImageDataGenerator(rescale = 1./255)
# we need to reformat all images to the resolution expected by MobileNet (224, 224)
train_data_gen = train_image_generator.flow_from_directory(batch_size=BATCH_SIZE,
                                                                  directory = train_dir,
                                                                  shuffle = True,
                                                                  target_size=(IMAGE_SHAPE,IMAGE_SHAPE),
                                                                  class_mode='binary')

val_data_gen = validation_image_generator.flow_from_directory(batch_size=BATCH_SIZE,
                                                              directory = validation_dir,
                                                              shuffle=True,
                                                              target_size=(IMAGE_SHAPE,IMAGE_SHAPE),
                                                              class_mode='binary')

# visualize training images
sample_training_images, _ = next(train_data_gen) # a batch of images

# This function will plot images in the form of a grid of 2 row and 3 columns where images are placed in each column
def plotImages(images_arr):
    fig, axes = plt.subplots(2, 3, figsize=(10,10))
    axes = axes.flatten() #变成一个一维数组
    for img, ax in zip( images_arr, axes):
        ax.imshow(img)
    plt.tight_layout()
    plt.show()
    
plotImages(sample_training_images[:6])  # Plot images 0-6

# Run the classifier on a batch of images
image_batch, label_batch = next(train_data_gen)
result_batch = model.predict(image_batch)

predicted_class_names = imagenet_labels[np.argmax(result_batch)]
predicted_class_names

# Let's now plot the images from our Dogs vs Cats dataset and put the ImageNet label next to them.
plt.figure(figsize=(10,9))
for n in range(20):
  plt.subplot(5,4,n+1)
  plt.imshow(image_batch[n])
  plt.title(predicted_class_names[n])
  plt.axis('off')
  plt.suptitle("ImageNet predictions")
  
# Do simple transfer learning with TensorFlow Hub
  # get the partial model
URL = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/2"
feature_extractor = hub.keras_layer(URL,input_shape=(IMAGE_RES,IMAGE_RES,3))

# check feature_extractor
feature_batch = feature_extractor(image_batch)
print(feature_batch.shape) # (20,1280) ,最后一层有1280个神经元

# !!!Freeze the variables in the feature extractor layer, so that the training only modifies the final classifier layer.
feature_extractor.trainable = False

# Attach a classification head
model = tf.keras.Sequential([
    feature_extractor,
    layers.Dense(2, activation='softmax')            
])

model.compile(
  optimizer='adam', 
  loss='sparse_categorical_crossentropy',
  metrics=['accuracy'])

EPOCHS = 6
history = model.fit(train_data_gen,
                    epochs=EPOCHS,
                    validation_data=val_data_gen)

# Visualizing results of the training
# return a list containing the accuracy of each epoch
accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(EPOCHS)

plt.figure(figsize=(8,8))
# Draw accuracy figure
plt.subplot(1,2,1)
plt.plot(epochs_range, accuracy, label="Training Accuray")
plt.plot(epochs_range, val_accuracy, label="Validation Accuracy")
plt.legend(loc="lower right")
plt.title("Training and Validation Accuracy")

# Draw loss figure
plt.subplot(1,2,2)
plt.plot(epochs_range, loss, label="Training Loss")
plt.plot(epochs_range, val_loss, label="Validation_Loss")
plt.legend(loc="lower right")
plt.title("Training and Validaion Loss")

 

实验结果

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值