Tensorflow快餐教程(11)-不懂機器學習就只調API行不行?

lusing發表於2018-05-18

高層封裝API

有同學問,我們學習Tensorflow就是想學習一套可以用的套,像程式設計一樣呼叫就行了,不想學習機器學習的細節,有沒有這樣的方式?

針對於已經有成熟解決方案的模型,why not呢?
在前面已經快速將CNN, RNN的大致概念和深度學習的簡史走馬觀花過了一遍之後,我們就可以開始嘗試使用高層封裝的API。

模型 – 訓練 – 評估 三條語句搞定

既然高層封裝,我們就採用最簡單的方式:首先是一個模型,然後就開始訓練,最後評估一下效果如何。

我們還是舉祖傳的MNIST的例子。
核心三條語句,一句模型,一句訓練,一句評估:

estimator = tf.estimator.LinearClassifier(feature_columns=[image_column], n_classes=10)

# Train.
estimator.train(input_fn=train_input_fn, steps=2000)

# Evaluate and report metrics.
eval_metrics = estimator.evaluate(input_fn=eval_input_fn, steps=1)

我們首先知道MNIST是把手寫影像分成十類,那麼就用個線性迴歸分類器,指定分成10類:

estimator = tf.estimator.LinearClassifier(feature_columns=[image_column], n_classes=10)

訓練也是無腦的,指定訓練多少步就是了:

estimator.train(input_fn=train_input_fn, steps=2000)

評估也不需要懂啥,給個測試集就是了:

eval_metrics = estimator.evaluate(input_fn=eval_input_fn, steps=1)

給大家一個完整能執行的例子,主要的工作量都在處理輸入資料上,真正有功能的就是那三條語句:

import numpy as np
import tensorflow as tf

def get_input_fn(dataset_split, batch_size, capacity=10000, min_after_dequeue=3000):

  def _input_fn():
    images_batch, labels_batch = tf.train.shuffle_batch(
        tensors=[dataset_split.images, dataset_split.labels.astype(np.int32)],
        batch_size=batch_size,
        capacity=capacity,
        min_after_dequeue=min_after_dequeue,
        enqueue_many=True,
        num_threads=4)
    features_map = {`images`: images_batch}
    return features_map, labels_batch

  return _input_fn

data = tf.contrib.learn.datasets.mnist.load_mnist()

train_input_fn = get_input_fn(data.train, batch_size=256)
eval_input_fn = get_input_fn(data.validation, batch_size=5000)

# Specify the feature(s) to be used by the estimator.
image_column = tf.contrib.layers.real_valued_column(`images`, dimension=784)
estimator = tf.estimator.LinearClassifier(feature_columns=[image_column], n_classes=10)

# Train.
estimator.train(input_fn=train_input_fn, steps=2000)

# Evaluate and report metrics.
eval_metrics = estimator.evaluate(input_fn=eval_input_fn, steps=1)
print(eval_metrics)

三步法進階

現在我們已經學會三步法了。雖然不涉及底層細節,我們還是有很多工具可以做得更好的。

比如我們要自己設計優化方法, 從三條語句變成四條:

optimizer2 = tf.train.FtrlOptimizer(learning_rate=5.0, l2_regularization_strength=1.0)
estimator2 = tf.estimator.LinearClassifier(
    feature_columns=[image_column], n_classes=10, optimizer=optimizer2)

# Train.
estimator2.train(input_fn=train_input_fn, steps=2000)

# Evaluate and report metrics.
eval_metrics2 = estimator2.evaluate(input_fn=eval_input_fn, steps=1)
print(eval_metrics2)

這段程式碼不是片斷,拼接到上面的程式碼的後面就可以直接執行。

更進一步:支援向量機

預設的雖然通用,但是效果可能不如更專業的更好。比如我們想用前深度學習時代最強大的工具之一 – 支援向量機來進行MNIST識別。我們還是可以用高層API來實現。將LinearClassifier換成KernelLinearClassifier。

optimizer3 = tf.train.FtrlOptimizer(
   learning_rate=50.0, l2_regularization_strength=0.001)

kernel_mapper3 = tf.contrib.kernel_methods.RandomFourierFeatureMapper(
  input_dim=784, output_dim=2000, stddev=5.0, name=`rffm`)
kernel_mappers3 = {image_column: [kernel_mapper3]}
estimator3 = tf.contrib.kernel_methods.KernelLinearClassifier(
   n_classes=10, optimizer=optimizer3, kernel_mappers=kernel_mappers3)

# Train.
estimator3.fit(input_fn=train_input_fn, steps=2000)

# Evaluate and report metrics.
eval_metrics3 = estimator3.evaluate(input_fn=eval_input_fn, steps=1)
print(eval_metrics3)

我們來比較一下三種方法:

Elapsed time: 80.69186925888062 seconds
{`loss`: 0.26811677, `accuracy`: 0.9228, `global_step`: 2000}
Elapsed time: 80.33205699920654 seconds
{`loss`: 0.26356304, `accuracy`: 0.9276, `global_step`: 2000}
Elapsed time: 98.87778902053833 seconds
{`loss`: 0.10834637, `accuracy`: 0.9668, `global_step`: 2000}

SVM支援向量機力量果然強大,從92%的識別率提升到了96%.

高層深度學習API

準備資料的語句不變,我們再加一種採用深度學習的方式,也是三步:

classifier = tf.estimator.DNNClassifier(
    feature_columns=[image_column],
    hidden_units=[784, 625],
    n_classes=10)

# Train.
classifier.train(
    input_fn=train_input_fn,
    steps=2000)

eval_result = classifier.evaluate(
    input_fn=eval_input_fn, steps=1)

print(eval_result)

列印出來的結果如下:

{`accuracy`: 0.9812, `average_loss`: 0.064692736, `loss`: 323.46368, `global_step`: 2000}

識別率達到98%,比支援向量機還要強一些。

Tensorflow的API結構

Tensorflow API

我們從第一講到第十講學習的都是Mid-Level API。這一講講的是High-Level API。

Tensorflow r1.8 Estimators API的變化

Tensorflow API的變化一向以迅速著稱,相容性也不是很好。
tf.estimator.Estimators的前身是tf.contrib.learn.Estimators。

我們對比一下LinearClassifier在這兩個版本的區別:
新版:

estimator = tf.estimator.LinearClassifier(feature_columns=[image_column],
                                          n_classes=10)

# Train.
estimator.train(input_fn=train_input_fn, steps=2000)

# Evaluate and report metrics.
eval_metrics = estimator.evaluate(input_fn=eval_input_fn, steps=1)

舊版:

estimator = tf.contrib.learn.LinearClassifier(feature_columns=[image_column], n_classes=10)

# Train.
estimator.fit(input_fn=train_input_fn, steps=2000)

# Evaluate and report metrics.
eval_metrics = estimator.evaluate(input_fn=eval_input_fn, steps=1)
print(eval_metrics)

主要區別為:

  1. 包名改變了
  2. 新版的訓練方法是train,而舊版是fit。
    因為新版本沒有提供支援向量機的分類器,我們用的核函式版本的KernelLinearClassifier還是老的包中的,所以還是用的fit來訓練。

前情提要

有對前10節感興趣的,請移步:
Tensorflow快餐教程(1) – 30行程式碼搞定手寫識別:https://yq.aliyun.com/articles/582122
Tensorflow快餐教程(2) – 標量運算:https://yq.aliyun.com/articles/582490
Tensorflow快餐教程(3) – 向量:https://yq.aliyun.com/articles/584202
Tensorflow快餐教程(4) – 矩陣:https://yq.aliyun.com/articles/584526
Tensorflow快餐教程(5) – 範數:https://yq.aliyun.com/articles/584896
Tensorflow快餐教程(6) – 矩陣分解:https://yq.aliyun.com/articles/585599
Tensorflow快餐教程(7) – 梯度下降:https://yq.aliyun.com/articles/587350
Tensorflow快餐教程(8) – 深度學習簡史:https://yq.aliyun.com/articles/588920
Tensorflow快餐教程(9) – 卷積:https://yq.aliyun.com/articles/590233
Tensorflow快餐教程(10) – 迴圈神經網路: https://yq.aliyun.com/articles/591118


相關文章