[譯] TensorFlow 教程 #09 - 視頻數據

題圖來自: Pictures: S06E16 Bart vs. Australia
本文主要演示了如何使用本身的圖像數據,建立分類器。php

01 - 簡單線性模型 | 02 - 卷積神經網絡 | 03 - PrettyTensor | 04 - 保存& 恢復
05 - 集成學習 | 06 - CIFAR 10 | 07 - Inception 模型 | 08 - 遷移學習python

by Magnus Erik Hvass Pedersen / GitHub / Videos on YouTube
中文翻譯 thrillerist / Githubgit

若有轉載,請附上本文連接。github


介紹

上一篇教程#08介紹瞭如何在CIFAR-10數據集上用預訓練的Inception模型來作遷移學習(Transfer Learning)。本文將會展現如何使用你本身的圖像。數組

爲了示範,咱們使用新的數據集Knifey-Spoony,它包含了上千張不一樣背景下的餐刀、勺子和叉子的圖像。訓練集有4170張圖像,測試集有530張。類別爲knifey、sppony和forky,這是對辛普森一家的引用。緩存

knifey-spoony數據集中的圖像是用一個簡單的Python腳本從視頻文件中獲取的,腳本在Linux上運行(它須要avconv程序將視頻轉成圖像)。這讓你能夠很快地從幾分鐘的錄像視頻中建立包含上千張圖像的數據集。bash

本文基於上一篇教程,你須要瞭解熟悉教程#08中的遷移學習,以及以前教程中關於如何在TensorFlow中建立和訓練神經網絡的部分。網絡

流程圖

下圖展現了用Inception模型作遷移學習時數據的流向。首先,咱們在Inception模型中輸入並處理一張圖像。在模型最終的分類層以前,將所謂的Transfer- Values保存到緩存文件中。session

這與在教程#08中作的類似,只是如今用Knifey-Spoony數據集代替CIFAR-10,這說明咱們將jpeg圖像送到Inception模型中,而不是使用包含圖像數據的numpy數組。app

當新數據集裏的全部圖像都用Inception處理過,而且生成的transfer-values都保存到緩存文件以後,咱們能夠將這些transfer-values做爲其它神經網絡的輸入。接着用新數據集中的類別來訓練第二個神經網絡,所以,網絡基於Inception模型的transfer-values來學習如何分類圖像。

這樣,Inception模型從圖像中提取出有用的信息,而後用另外的神經網絡來作真正的分類工做。

from IPython.display import Image, display
Image('images/09_transfer_learning_flowchart.png')複製代碼

導入

%matplotlib inline
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
import time
from datetime import timedelta
import os

# Functions and classes for loading and using the Inception model.
import inception

# We use Pretty Tensor to define the new classifier.
import prettytensor as pt複製代碼

使用Python3.5.2(Anaconda)開發,TensorFlow版本是:

tf.__version__複製代碼
'0.12.0-rc0'複製代碼

PrettyTensor 版本:

pt.__version__複製代碼

'0.7.1'

載入數據

import knifey複製代碼

knifey模塊中已經定義好了數據維度,所以咱們須要時只要導入就行。

from knifey import num_classes複製代碼

設置電腦上保存數據集的路徑。

# knifey.data_dir = "data/knifey-spoony/"複製代碼

設置本教程中保存緩存文件的文件夾。

data_dir = knifey.data_dir複製代碼

Knifey-Spoony數據集大概有22MB,若是給定路徑沒有找到文件的話,將會自動下載。

knifey.maybe_download_and_extract()複製代碼

Data has apparently already been downloaded and unpacked.

如今載入數據集。程序會遍歷子文件夾來獲取全部*.jpg格式的圖像,而後將文件名放入訓練集和測試集的兩個列表中。實際上此時並未載入圖像,在計算好transfer-values以後再執行載入。

文件名列表將會保存到硬盤上,咱們必須確保它們按以後重載數據集的順序排列。這個很重要,這樣咱們就能知道哪些圖像對應哪些transfer-values。

dataset = knifey.load()複製代碼

Creating dataset from the files in: data/knifey-spoony/

  • Data loaded from cache-file: data/knifey-spoony/knifey-spoony.pkl

你的數據

你能夠用本身的圖像來代替knifey-spoony數據集。須要建立一個dataset.py模塊中的DataSet對象。最好的方法是使用load_cache()封裝函數,它會自動將圖像列表保存到緩存文件中,所以你須要確保列表順序和後面生成的transfer-values順順序一致。

每一個類別的圖像須要組織在各自的文件夾裏。dataset.py模塊中的文檔有更多細節。

# This is the code you would run to load your own image-files.
# It has been commented out so it won't run now.

# from dataset import load_cached
# dataset = load_cached(cache_path='my_dataset_cache.pkl', in_dir='my_images/')
# num_classes = dataset.num_classes複製代碼

訓練集和測試集

獲取類別名。

class_names = dataset.class_names
class_names複製代碼

['forky', 'knifey', 'spoony']

獲取測試集。它返回圖像的文件路徑、整形類別號和One-Hot編碼的類別號數組,稱爲標籤。

image_paths_train, cls_train, labels_train = dataset.get_training_set()複製代碼

打印第一個圖像地址,看看是否正確。

image_paths_train[0]複製代碼

'/home/magnus/development/TensorFlow-Tutorials/data/knifey-spoony/forky/forky-05-0023.jpg'

獲取測試集。

image_paths_test, cls_test, labels_test = dataset.get_test_set()複製代碼

打印第一個圖像地址,看看是否正確。

image_paths_test[0]複製代碼

'/home/magnus/development/TensorFlow-Tutorials/data/knifey-spoony/forky/test/forky-test-01-0163.jpg'

如今已經載入了Knifey-Spoony數據集,它包含4700張圖像以及相應的標籤(圖像的分類)。數據集被手動地分爲兩個子集,訓練集和測試集。

print("Size of:")
print("- Training-set:\t\t{}".format(len(image_paths_train)))
print("- Test-set:\t\t{}".format(len(image_paths_test)))複製代碼

Size of:

  • Training-set: 4170
  • Test-set: 530

用來繪製圖像的幫助函數

這個函數用來在3x3的柵格中畫9張圖像,而後在每張圖像下面寫出真實類別和預測類別。

def plot_images(images, cls_true, cls_pred=None, smooth=True):

    assert len(images) == len(cls_true)

    # Create figure with sub-plots.
    fig, axes = plt.subplots(3, 3)

    # Adjust vertical spacing.
    if cls_pred is None:
        hspace = 0.3
    else:
        hspace = 0.6
    fig.subplots_adjust(hspace=hspace, wspace=0.3)

    # Interpolation type.
    if smooth:
        interpolation = 'spline16'
    else:
        interpolation = 'nearest'

    for i, ax in enumerate(axes.flat):
        # There may be less than 9 images, ensure it doesn't crash.
        if i < len(images):
            # Plot image.
            ax.imshow(images[i],
                      interpolation=interpolation)

            # Name of the true class.
            cls_true_name = class_names[cls_true[i]]

            # Show true and predicted classes.
            if cls_pred is None:
                xlabel = "True: {0}".format(cls_true_name)
            else:
                # Name of the predicted class.
                cls_pred_name = class_names[cls_pred[i]]

                xlabel = "True: {0}\nPred: {1}".format(cls_true_name, cls_pred_name)

            # Show the classes as the label on the x-axis.
            ax.set_xlabel(xlabel)

        # Remove ticks from the plot.
        ax.set_xticks([])
        ax.set_yticks([])

    # Ensure the plot is shown correctly with multiple plots
    # in a single Notebook cell.
    plt.show()複製代碼

載入圖像的幫助函數

數據集並未載入實際圖像,在訓練集和測試集中各有一個圖像(地址)列表。下面的幫助函數載入了一些圖像文件。

from matplotlib.image import imread

def load_images(image_paths):
    # Load the images from disk.
    images = [imread(path) for path in image_paths]

    # Convert to a numpy array and return it.
    return np.asarray(images)複製代碼

繪製一些圖像看看數據是否正確

# Load the first images from the test-set.
images = load_images(image_paths=image_paths_test[0:9])

# Get the true classes for those images.
cls_true = cls_test[0:9]

# Plot the images and labels using our helper-function above.
plot_images(images=images, cls_true=cls_true, smooth=True)複製代碼

下載Inception模型

從網上下載Inception模型。這是你保存數據文件的默認文件夾。若是文件夾不存在就自動建立。

# inception.data_dir = 'inception/'複製代碼

若是文件夾中不存在Inception模型,就自動下載。 它有85MB。

更多詳情見教程#07。

inception.maybe_download()複製代碼
Downloading Inception v3 Model ...
Data has apparently already been downloaded and unpacked.複製代碼

載入Inception模型

載入模型,爲圖像分類作準備。

注意warning信息,之後可能會致使程序運行失敗。

model = inception.Inception()複製代碼

計算 Transfer-Values

導入用來從Inception模型中獲取transfer-values的幫助函數。

from inception import transfer_values_cache複製代碼

設置訓練集和測試集緩存文件的目錄。

file_path_cache_train = os.path.join(data_dir, 'inception-knifey-train.pkl')
file_path_cache_test = os.path.join(data_dir, 'inception-knifey-test.pkl')複製代碼
print("Processing Inception transfer-values for training-images ...")

# If transfer-values have already been calculated then reload them,
# otherwise calculate them and save them to a cache-file.
transfer_values_train = transfer_values_cache(cache_path=file_path_cache_train,
                                              image_paths=image_paths_train,
                                              model=model)複製代碼
Processing Inception transfer-values for training-images ...
- Data loaded from cache-file: data/knifey-spoony/inception-knifey-train.pkl複製代碼
print("Processing Inception transfer-values for test-images ...")

# If transfer-values have already been calculated then reload them,
# otherwise calculate them and save them to a cache-file.
transfer_values_test = transfer_values_cache(cache_path=file_path_cache_test,
                                             image_paths=image_paths_test,
                                             model=model)複製代碼
Processing Inception transfer-values for test-images ...
- Data loaded from cache-file: data/knifey-spoony/inception-knifey-test.pkl複製代碼

檢查transfer-values的數組大小。在訓練集中有4170張圖像,每張圖像有2048個transfer-values。

transfer_values_train.shape複製代碼

(4170, 2048)

一樣,在測試集中有530張圖像,每張圖像有2048個transfer-values。

transfer_values_test.shape複製代碼

(530, 2048)

繪製transfer-values的幫助函數

def plot_transfer_values(i):
    print("Input image:")

    # Plot the i'th image from the test-set.
    image = imread(image_paths_test[i])
    plt.imshow(image, interpolation='spline16')
    plt.show()

    print("Transfer-values for the image using Inception model:")

    # Transform the transfer-values into an image.
    img = transfer_values_test[i]
    img = img.reshape((32, 64))

    # Plot the image for the transfer-values.
    plt.imshow(img, interpolation='nearest', cmap='Reds')
    plt.show()複製代碼
plot_transfer_values(i=100)複製代碼

Input image:

Transfer-values for the image using Inception model:

plot_transfer_values(i=300)複製代碼

Input image:

Transfer-values for the image using Inception model:

transfer-values的PCA分析結果

用scikit-learn裏的主成分分析(PCA),將transfer-values的數組維度從2048維降到2維,方便繪製。

from sklearn.decomposition import PCA複製代碼

建立一個新的PCA-object,將目標數組維度設爲2。

pca = PCA(n_components=2)複製代碼

計算PCA須要一段時間。本文的數據集並非很大,不然你須要挑選訓練集中的一小部分,來加速計算。

# transfer_values = transfer_values_train[0:3000]
transfer_values = transfer_values_train複製代碼

獲取你選取的樣本的類別號。

# cls = cls_train[0:3000]
cls = cls_train複製代碼

保數組有4170份樣本,每一個樣本有2048個transfer-values。

transfer_values.shape複製代碼

(4170, 2048)

用PCA將transfer-value從2048維下降到2維。

transfer_values_reduced = pca.fit_transform(transfer_values)複製代碼

數組如今有4170個樣本,每一個樣本兩個值。

transfer_values_reduced.shape複製代碼

(4170, 2)

幫助函數用來繪製降維後的transfer-values。

def plot_scatter(values, cls):
    # Create a color-map with a different color for each class.
    import matplotlib.cm as cm
    cmap = cm.rainbow(np.linspace(0.0, 1.0, num_classes))

    # Create an index with a random permutation to make a better plot.
    idx = np.random.permutation(len(values))

    # Get the color for each sample.
    colors = cmap[cls[idx]]

    # Extract the x- and y-values.
    x = values[idx, 0]
    y = values[idx, 1]

    # Plot it.
    plt.scatter(x, y, color=colors, alpha=0.5)
    plt.show()複製代碼

畫出用PCA降維後的transfer-values。用3種不一樣的顏色來表示Knifey-Spoony數據集中不一樣的類別。顏色有不少重疊部分。這多是由於PCA沒法正確地分離transfer-values。

plot_scatter(transfer_values_reduced, cls=cls)複製代碼

transfer-values的t-SNE分析結果

from sklearn.manifold import TSNE複製代碼

另外一種降維的方法是t-SNE。不幸的是,t-SNE很慢,所以咱們先用PCA將維度從2048減小到50。

pca = PCA(n_components=50)
transfer_values_50d = pca.fit_transform(transfer_values)複製代碼

建立一個新的t-SNE對象,用來作最後的降維工做,將目標維度設爲2維。

tsne = TSNE(n_components=2)複製代碼

用t-SNE執行最終的降維。目前在scikit-learn中實現的t-SNE可能沒法處理不少樣本的數據,因此若是你用整個訓練集的話,程序可能會崩潰。

transfer_values_reduced = tsne.fit_transform(transfer_values_50d)複製代碼

確保數組有4170份樣本,每一個樣本有兩個transfer-values。

transfer_values_reduced.shape複製代碼

(4170, 2)

畫出用t-SNE下降至二維的transfer-values,相比上面PCA的結果,它有更好的分離度。

這意味着由Inception模型獲得的transfer-values彷佛包含了足夠多的信息,能夠對Knifey-Sponny圖像進行分類,然而仍是有一些重疊部分,說明分離並不完美。

plot_scatter(transfer_values_reduced, cls=cls)複製代碼

TensorFlow中的新分類器

在咱們將會在TensorFlow中建立一個新的神經網絡。這個網絡會把Inception模型中的transfer-values做爲輸入,而後輸出Knifey-Spoony圖像的預測類別。

這裏假定你已經熟悉如何在TensorFlow中創建神經網絡,不然請閱讀教程#03。

佔位符 (Placeholder)變量

首先須要找到transfer-values的數組長度,它是保存在Inception模型對象中的一個變量。

transfer_len = model.transfer_len複製代碼

如今爲輸入的transfer-values建立一個placeholder變量,輸入到咱們新建的網絡中。變量的形狀是[None, transfer_len]None表示它的輸入數組包含任意數量的樣本,每一個樣本元素個數爲2048,即transfer_len

x = tf.placeholder(tf.float32, shape=[None, transfer_len], name='x')複製代碼

爲輸入圖像的真實類型標籤訂義另一個placeholder變量。這是One-Hot編碼的數組,包含10個元素,每一個元素表明了數據集中的一種可能類別。

y_true = tf.placeholder(tf.float32, shape=[None, num_classes], name='y_true')複製代碼

計算表明真實類別的整形數字。這也多是一個placeholder變量。

y_true_cls = tf.argmax(y_true, dimension=1)複製代碼

神經網絡

建立在Knifey-Spoony數據集上作分類的神經網絡。它將Inception模型獲得的transfer-values做爲輸入,保存在placeholder變量x中。網絡輸出預測的類別y_pred

教程#03中有更多使用Pretty Tensor構造神經網絡的細節。

# Wrap the transfer-values as a Pretty Tensor object.
x_pretty = pt.wrap(x)

with pt.defaults_scope(activation_fn=tf.nn.relu):
    y_pred, loss = x_pretty.\
        fully_connected(size=1024, name='layer_fc1').\
        softmax_classifier(num_classes=num_classes, labels=y_true)複製代碼

優化方法

建立一個變量來記錄當前優化迭代的次數。

global_step = tf.Variable(initial_value=0,
                          name='global_step', trainable=False)複製代碼

優化新的神經網絡的方法。

optimizer = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(loss, global_step)複製代碼

分類準確率

網絡的輸出y_pred是一個包含3個元素的數組。類別號是數組中最大元素的索引。

y_pred_cls = tf.argmax(y_pred, dimension=1)複製代碼

建立一個布爾向量,表示每張圖像的真實類別是否與預測類別相同。

correct_prediction = tf.equal(y_pred_cls, y_true_cls)複製代碼

將布爾值向量類型轉換成浮點型向量,這樣子False就變成0,True變成1,而後計算這些值的平均數,以此來計算分類的準確度。

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))複製代碼

運行TensorFlow

建立TensorFlow會話(session)

一旦建立了TensorFlow圖,咱們須要建立一個TensorFlow會話,用來運行圖。

session = tf.Session()複製代碼

初始化變量

咱們須要在開始優化weights和biases變量以前對它們進行初始化。

session.run(tf.global_variables_initializer())複製代碼

獲取隨機訓練batch的幫助函數

訓練集中有4170張圖像(以及保存transfer-values的數組)。用這些圖像(transfer-vlues)計算模型的梯度會花不少時間。所以,咱們在優化器的每次迭代裏只用到了一小部分的圖像(transfer-vlues)。

若是內存耗盡致使電腦死機或變得很慢,你應該試着減小這些數量,但同時可能還須要更優化的迭代。

train_batch_size = 64複製代碼

函數用來從訓練集中選擇隨機batch的transfer-vlues。

def random_batch():
    # Number of images (transfer-values) in the training-set.
    num_images = len(transfer_values_train)

    # Create a random index.
    idx = np.random.choice(num_images,
                           size=train_batch_size,
                           replace=False)

    # Use the random index to select random x and y-values.
    # We use the transfer-values instead of images as x-values.
    x_batch = transfer_values_train[idx]
    y_batch = labels_train[idx]

    return x_batch, y_batch複製代碼

執行優化迭代的幫助函數

函數用來執行必定數量的優化迭代,以此來逐漸改善網絡層的變量。在每次迭代中,會從訓練集中選擇新的一批數據,而後TensorFlow在這些訓練樣本上執行優化。每100次迭代會打印出進度。

def optimize(num_iterations):
    # Start-time used for printing time-usage below.
    start_time = time.time()

    for i in range(num_iterations):
        # Get a batch of training examples.
        # x_batch now holds a batch of images (transfer-values) and
        # y_true_batch are the true labels for those images.
        x_batch, y_true_batch = random_batch()

        # Put the batch into a dict with the proper names
        # for placeholder variables in the TensorFlow graph.
        feed_dict_train = {x: x_batch,
                           y_true: y_true_batch}

        # Run the optimizer using this batch of training data.
        # TensorFlow assigns the variables in feed_dict_train
        # to the placeholder variables and then runs the optimizer.
        # We also want to retrieve the global_step counter.
        i_global, _ = session.run([global_step, optimizer],
                                  feed_dict=feed_dict_train)

        # Print status to screen every 100 iterations (and last).
        if (i_global % 100 == 0) or (i == num_iterations - 1):
            # Calculate the accuracy on the training-batch.
            batch_acc = session.run(accuracy,
                                    feed_dict=feed_dict_train)

            # Print status.
            msg = "Global Step: {0:>6}, Training Batch Accuracy: {1:>6.1%}"
            print(msg.format(i_global, batch_acc))

    # Ending time.
    end_time = time.time()

    # Difference between start and end-times.
    time_dif = end_time - start_time

    # Print the time-usage.
    print("Time usage: " + str(timedelta(seconds=int(round(time_dif)))))複製代碼

展現結果的幫助函數

繪製錯誤樣本的幫助函數

函數用來繪製測試集中被誤分類的樣本。

def plot_example_errors(cls_pred, correct):
    # This function is called from print_test_accuracy() below.

    # cls_pred is an array of the predicted class-number for
    # all images in the test-set.

    # correct is a boolean array whether the predicted class
    # is equal to the true class for each image in the test-set.

    # Negate the boolean array.
    incorrect = (correct == False)

    # Get the indices for the incorrectly classified images.
    idx = np.flatnonzero(incorrect)

    # Number of images to select, max 9.
    n = min(len(idx), 9)

    # Randomize and select n indices.
    idx = np.random.choice(idx,
                           size=n,
                           replace=False)

    # Get the predicted classes for those images.
    cls_pred = cls_pred[idx]

    # Get the true classes for those images.
    cls_true = cls_test[idx]

    # Load the corresponding images from the test-set.
    # Note: We cannot do image_paths_test[idx] on lists of strings.
    image_paths = [image_paths_test[i] for i in idx]
    images = load_images(image_paths)

    # Plot the images.
    plot_images(images=images,
                cls_true=cls_true,
                cls_pred=cls_pred)複製代碼

繪製混淆(confusion)矩陣的幫助函數

# Import a function from sklearn to calculate the confusion-matrix.
from sklearn.metrics import confusion_matrix

def plot_confusion_matrix(cls_pred):
    # This is called from print_test_accuracy() below.

    # cls_pred is an array of the predicted class-number for
    # all images in the test-set.

    # Get the confusion matrix using sklearn.
    cm = confusion_matrix(y_true=cls_test,  # True class for test-set.
                          y_pred=cls_pred)  # Predicted class.

    # Print the confusion matrix as text.
    for i in range(num_classes):
        # Append the class-name to each line.
        class_name = "({}) {}".format(i, class_names[i])
        print(cm[i, :], class_name)

    # Print the class-numbers for easy reference.
    class_numbers = [" ({0})".format(i) for i in range(num_classes)]
    print("".join(class_numbers))複製代碼

計算分類的幫助函數

這個函數用來計算圖像的預測類別,同時返回一個表明每張圖像分類是否正確的布爾數組。

因爲計算可能會耗費太多內存,就分批處理。若是你的電腦死機了,試着下降batch-size。

# Split the data-set in batches of this size to limit RAM usage.
batch_size = 256

def predict_cls(transfer_values, labels, cls_true):
    # Number of images.
    num_images = len(transfer_values)

    # Allocate an array for the predicted classes which
    # will be calculated in batches and filled into this array.
    cls_pred = np.zeros(shape=num_images, dtype=np.int)

    # Now calculate the predicted classes for the batches.
    # We will just iterate through all the batches.
    # There might be a more clever and Pythonic way of doing this.

    # The starting index for the next batch is denoted i.
    i = 0

    while i < num_images:
        # The ending index for the next batch is denoted j.
        j = min(i + batch_size, num_images)

        # Create a feed-dict with the images and labels
        # between index i and j.
        feed_dict = {x: transfer_values[i:j],
                     y_true: labels[i:j]}

        # Calculate the predicted class using TensorFlow.
        cls_pred[i:j] = session.run(y_pred_cls, feed_dict=feed_dict)

        # Set the start-index for the next batch to the
        # end-index of the current batch.
        i = j

    # Create a boolean array whether each image is correctly classified.
    correct = (cls_true == cls_pred)

    return correct, cls_pred複製代碼

計算測試集上的預測類別。

def predict_cls_test():
    return predict_cls(transfer_values = transfer_values_test,
                       labels = labels_test,
                       cls_true = cls_test)複製代碼

計算分類準確率的幫助函數

這個函數計算了給定布爾數組的分類準確率,布爾數組表示每張圖像是否被正確分類。好比, cls_accuracy([True, True, False, False, False]) = 2/5 = 0.4

def classification_accuracy(correct):
    # When averaging a boolean array, False means 0 and True means 1.
    # So we are calculating: number of True / len(correct) which is
    # the same as the classification accuracy.

    # Return the classification accuracy
    # and the number of correct classifications.
    return correct.mean(), correct.sum()複製代碼

展現分類準確率的幫助函數

函數用來打印測試集上的分類準確率。

爲測試集上的全部圖片計算分類會花費一段時間,所以咱們直接從這個函數裏調用上面的函數,這樣就不用每一個函數都從新計算分類。

def print_test_accuracy(show_example_errors=False, show_confusion_matrix=False):

    # For all the images in the test-set,
    # calculate the predicted classes and whether they are correct.
    correct, cls_pred = predict_cls_test()

    # Classification accuracy and the number of correct classifications.
    acc, num_correct = classification_accuracy(correct)

    # Number of images being classified.
    num_images = len(correct)

    # Print the accuracy.
    msg = "Accuracy on Test-Set: {0:.1%} ({1} / {2})"
    print(msg.format(acc, num_correct, num_images))

    # Plot some examples of mis-classifications, if desired.
    if show_example_errors:
        print("Example errors:")
        plot_example_errors(cls_pred=cls_pred, correct=correct)

    # Plot the confusion matrix, if desired.
    if show_confusion_matrix:
        print("Confusion Matrix:")
        plot_confusion_matrix(cls_pred=cls_pred)複製代碼

結果

優化以前的性能

測試集上的準確度很低,這是因爲模型只作了初始化,並沒作任何優化,因此它只是對圖像作隨機分類。

print_test_accuracy(show_example_errors=False,
                    show_confusion_matrix=True)複製代碼

Accuracy on Test-Set: 30.0% (159 / 530)
Confusion Matrix:
[151 0 0] (0) forky
[122 3 12] (1) knifey
[237 0 5] (2) spoony
(0) (1) (2)

1000次優化迭代後的性能

在1000次優化迭代以後,測試集上的準確率大約爲70%。

optimize(num_iterations=1000)複製代碼

Global Step: 100, Training Batch Accuracy: 95.3%
Global Step: 200, Training Batch Accuracy: 96.9%
Global Step: 300, Training Batch Accuracy: 98.4%
Global Step: 400, Training Batch Accuracy: 100.0%
Global Step: 500, Training Batch Accuracy: 100.0%
Global Step: 600, Training Batch Accuracy: 100.0%
Global Step: 700, Training Batch Accuracy: 100.0%
Global Step: 800, Training Batch Accuracy: 100.0%
Global Step: 900, Training Batch Accuracy: 100.0%
Global Step: 1000, Training Batch Accuracy: 100.0%
Time usage: 0:00:02

print_test_accuracy(show_example_errors=True,
                    show_confusion_matrix=True)複製代碼

Accuracy on Test-Set: 71.3% (378 / 530)
Example errors:

Confusion Matrix:
[35 36 80] (0) forky
[ 6 101 30] (1) knifey
[ 0 0 242] (2) spoony
(0) (1) (2)

關閉TensorFlow會話

如今咱們已經用TensorFlow完成了任務,關閉session,釋放資源。注意,咱們須要關閉兩個TensorFlow-session,每一個模型對象各有一個。

# This has been commented out in case you want to modify and experiment
# with the Notebook without having to restart it.
# model.close()
# session.close()複製代碼

總結

這篇教程向咱們展現瞭如何在Inception模型上用本身的圖像作遷移學習。教程中使用的幾千張圖像是咱們用一個Python腳本從幾分鐘的錄像視頻中生成的。

然而,Knifey-Spoony數據集上的分類準確率不是很高,特別是叉子的圖像。多是由於Inception模型在ImageNet數據集上訓練,而其中只有16張叉子的圖像,但它卻包括了1200多張勺子圖像和1300多張餐刀圖像。所以Inception模型極可能沒法正確識別叉子。

所以咱們須要另外一種技巧來微調Inception模型,這樣它就能更好地識別叉子。

練習

下面使一些可能會讓你提高TensorFlow技能的一些建議練習。爲了學習如何更合適地使用TensorFlow,實踐經驗是很重要的。

在你對這個Notebook進行修改以前,可能須要先備份一下。

  • 試着爲新的分類器改變神經網絡。若是你刪掉全鏈接層或添加更多的全鏈接層會發生什麼?
  • 若是你執行更多或更少的迭代會出現什麼狀況?
  • 試着在訓練集中刪掉一些勺子的圖像,這樣每種類別的圖象數量就差很少(先作個備份)。你還須要刪除全部文件名帶有*.pkl的緩存文件,而後從新運行Notebook。這樣會提升分類準確率嗎?比較改變先後的混淆矩陣。
  • convert.py 腳本創建你本身的數據集。好比,錄下汽車和摩托車的視頻,而後建立一個分類系統。
  • 須要從你建立的訓練集中刪除一些不明確的圖像嗎?如何你刪掉這些圖像以後,分類準確率有什麼變化?
  • 改變Notebook,這樣你能夠輸入單張圖像而不是整個數據集。你不用從Inception模型中保存transfer-values。
  • 你能建立一個比用Inception模型來作遷移學習更好的或更快的神經網絡嗎?
  • 向朋友解釋程序如何工做。
相關文章
相關標籤/搜索